Public Dashboards: Only use queries from dashboard for caching (#54596)

Don't accept frontend queries for query caching when its from a public dashboard. Use queries on the dashboard instead.
This commit is contained in:
owensmallwood 2022-09-07 12:08:52 -06:00 committed by GitHub
parent 4223d3a6a7
commit 108678a8cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 204 additions and 99 deletions

View File

@ -158,8 +158,8 @@ func (api *Api) QueryPublicDashboard(c *models.ReqContext) response.Response {
return response.Error(http.StatusBadRequest, "invalid panel ID", err)
}
reqDTO := &PublicDashboardQueryDTO{}
if err = web.Bind(c.Req, reqDTO); err != nil {
reqDTO := PublicDashboardQueryDTO{}
if err = web.Bind(c.Req, &reqDTO); err != nil {
return response.Error(http.StatusBadRequest, "bad request data", err)
}

View File

@ -0,0 +1,24 @@
package internal
import (
"strconv"
"testing"
"time"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/stretchr/testify/require"
)
// Gets time range from dashboard in unix milliseconds
func GetTimeRangeFromDashboard(t *testing.T, dashboardData *simplejson.Json) (string, string) {
to := dashboardData.GetPath("time", "to").MustString()
from := dashboardData.GetPath("time", "from").MustString()
toTime, err := time.Parse("2006-01-02T15:04:05.000Z", to)
require.NoError(t, err)
fromTime, err := time.Parse("2006-01-02T15:04:05.000Z", from)
require.NoError(t, err)
toUnixMilli := strconv.FormatInt(toTime.UnixMilli(), 10)
fromUnixMilli := strconv.FormatInt(fromTime.UnixMilli(), 10)
return fromUnixMilli, toUnixMilli
}

View File

@ -1,10 +1,12 @@
package models
import (
"strconv"
"time"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/tsdb/legacydata"
)
// PublicDashboardErr represents a dashboard error.
@ -81,24 +83,21 @@ type TimeSettings struct {
// build time settings object from json on public dashboard. If empty, use
// defaults on the dashboard
func (pd PublicDashboard) BuildTimeSettings(dashboard *models.Dashboard) *TimeSettings {
ts := &TimeSettings{
From: dashboard.Data.GetPath("time", "from").MustString(),
To: dashboard.Data.GetPath("time", "to").MustString(),
func (pd PublicDashboard) BuildTimeSettings(dashboard *models.Dashboard) TimeSettings {
from := dashboard.Data.GetPath("time", "from").MustString()
to := dashboard.Data.GetPath("time", "to").MustString()
timeRange := legacydata.NewDataTimeRange(from, to)
// Were using epoch ms because this is used to build a MetricRequest, which is used by query caching, which expected the time range in epoch milliseconds.
ts := TimeSettings{
From: strconv.FormatInt(timeRange.GetFromAsMsEpoch(), 10),
To: strconv.FormatInt(timeRange.GetToAsMsEpoch(), 10),
}
if pd.TimeSettings == nil {
return ts
}
// merge time settings from public dashboard
to := pd.TimeSettings.Get("to").MustString("")
from := pd.TimeSettings.Get("from").MustString("")
if to != "" && from != "" {
ts.From = from
ts.To = to
}
return ts
}

View File

@ -5,6 +5,7 @@ import (
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/publicdashboards/internal"
"github.com/stretchr/testify/assert"
)
@ -13,38 +14,30 @@ func TestPublicDashboardTableName(t *testing.T) {
}
func TestBuildTimeSettings(t *testing.T) {
var dashboardData = simplejson.NewFromAny(map[string]interface{}{"time": map[string]interface{}{"from": "now-8", "to": "now"}})
var dashboardData = simplejson.NewFromAny(map[string]interface{}{"time": map[string]interface{}{"from": "2022-09-01T00:00:00.000Z", "to": "2022-09-01T12:00:00.000Z"}})
fromMs, toMs := internal.GetTimeRangeFromDashboard(t, dashboardData)
testCases := []struct {
name string
dashboard *models.Dashboard
pubdash *PublicDashboard
timeResult *TimeSettings
timeResult TimeSettings
}{
{
name: "should use dashboard time if pubdash time empty",
dashboard: &models.Dashboard{Data: dashboardData},
pubdash: &PublicDashboard{},
timeResult: &TimeSettings{
From: "now-8",
To: "now",
timeResult: TimeSettings{
From: fromMs,
To: toMs,
},
},
{
name: "should use dashboard time if pubdash to/from empty",
dashboard: &models.Dashboard{Data: dashboardData},
pubdash: &PublicDashboard{},
timeResult: &TimeSettings{
From: "now-8",
To: "now",
},
},
{
name: "should use pubdash time",
name: "should use dashboard time even if pubdash time exists",
dashboard: &models.Dashboard{Data: dashboardData},
pubdash: &PublicDashboard{TimeSettings: simplejson.NewFromAny(map[string]interface{}{"from": "now-12", "to": "now"})},
timeResult: &TimeSettings{
From: "now-12",
To: "now",
timeResult: TimeSettings{
From: fromMs,
To: toMs,
},
},
}

View File

@ -4,13 +4,19 @@ package publicdashboards
import (
context "context"
testing "testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
models "github.com/grafana/grafana/pkg/models"
publicdashboardsmodels "github.com/grafana/grafana/pkg/services/publicdashboards/models"
backend "github.com/grafana/grafana-plugin-sdk-go/backend"
dtos "github.com/grafana/grafana/pkg/api/dtos"
mock "github.com/stretchr/testify/mock"
models "github.com/grafana/grafana/pkg/models"
publicdashboardsmodels "github.com/grafana/grafana/pkg/services/publicdashboards/models"
testing "testing"
user "github.com/grafana/grafana/pkg/services/user"
)
@ -63,27 +69,6 @@ func (_m *FakePublicDashboardService) BuildAnonymousUser(ctx context.Context, da
return r0, r1
}
// GetQueryDataResponse provides a mock function with given fields: ctx, skipCache, reqDTO, panelId, accessToken
func (_m *FakePublicDashboardService) GetQueryDataResponse(ctx context.Context, skipCache bool, reqDTO *publicdashboardsmodels.PublicDashboardQueryDTO, panelId int64, accessToken string) (*backend.QueryDataResponse, error) {
ret := _m.Called(ctx, skipCache, reqDTO, panelId, accessToken)
var r0 *backend.QueryDataResponse
if rf, ok := ret.Get(0).(func(context.Context, bool, *publicdashboardsmodels.PublicDashboardQueryDTO, int64, string) *backend.QueryDataResponse); ok {
r0 = rf(ctx, skipCache, reqDTO, panelId, accessToken)
} else {
r0 = ret.Get(0).(*backend.QueryDataResponse)
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, bool, *publicdashboardsmodels.PublicDashboardQueryDTO, int64, string) error); ok {
r1 = rf(ctx, skipCache, reqDTO, panelId, accessToken)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetDashboard provides a mock function with given fields: ctx, dashboardUid
func (_m *FakePublicDashboardService) GetDashboard(ctx context.Context, dashboardUid string) (*models.Dashboard, error) {
ret := _m.Called(ctx, dashboardUid)
@ -107,6 +92,27 @@ func (_m *FakePublicDashboardService) GetDashboard(ctx context.Context, dashboar
return r0, r1
}
// GetMetricRequest provides a mock function with given fields: ctx, dashboard, publicDashboard, panelId, reqDTO
func (_m *FakePublicDashboardService) GetMetricRequest(ctx context.Context, dashboard *models.Dashboard, publicDashboard *publicdashboardsmodels.PublicDashboard, panelId int64, reqDTO publicdashboardsmodels.PublicDashboardQueryDTO) (dtos.MetricRequest, error) {
ret := _m.Called(ctx, dashboard, publicDashboard, panelId, reqDTO)
var r0 dtos.MetricRequest
if rf, ok := ret.Get(0).(func(context.Context, *models.Dashboard, *publicdashboardsmodels.PublicDashboard, int64, publicdashboardsmodels.PublicDashboardQueryDTO) dtos.MetricRequest); ok {
r0 = rf(ctx, dashboard, publicDashboard, panelId, reqDTO)
} else {
r0 = ret.Get(0).(dtos.MetricRequest)
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *models.Dashboard, *publicdashboardsmodels.PublicDashboard, int64, publicdashboardsmodels.PublicDashboardQueryDTO) error); ok {
r1 = rf(ctx, dashboard, publicDashboard, panelId, reqDTO)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetPublicDashboard provides a mock function with given fields: ctx, accessToken
func (_m *FakePublicDashboardService) GetPublicDashboard(ctx context.Context, accessToken string) (*publicdashboardsmodels.PublicDashboard, *models.Dashboard, error) {
ret := _m.Called(ctx, accessToken)
@ -162,6 +168,29 @@ func (_m *FakePublicDashboardService) GetPublicDashboardConfig(ctx context.Conte
return r0, r1
}
// GetQueryDataResponse provides a mock function with given fields: ctx, skipCache, reqDTO, panelId, accessToken
func (_m *FakePublicDashboardService) GetQueryDataResponse(ctx context.Context, skipCache bool, reqDTO publicdashboardsmodels.PublicDashboardQueryDTO, panelId int64, accessToken string) (*backend.QueryDataResponse, error) {
ret := _m.Called(ctx, skipCache, reqDTO, panelId, accessToken)
var r0 *backend.QueryDataResponse
if rf, ok := ret.Get(0).(func(context.Context, bool, publicdashboardsmodels.PublicDashboardQueryDTO, int64, string) *backend.QueryDataResponse); ok {
r0 = rf(ctx, skipCache, reqDTO, panelId, accessToken)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*backend.QueryDataResponse)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, bool, publicdashboardsmodels.PublicDashboardQueryDTO, int64, string) error); ok {
r1 = rf(ctx, skipCache, reqDTO, panelId, accessToken)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// PublicDashboardEnabled provides a mock function with given fields: ctx, dashboardUid
func (_m *FakePublicDashboardService) PublicDashboardEnabled(ctx context.Context, dashboardUid string) (bool, error) {
ret := _m.Called(ctx, dashboardUid)

View File

@ -4,6 +4,7 @@ import (
"context"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/models"
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
"github.com/grafana/grafana/pkg/services/user"
@ -13,25 +14,26 @@ import (
//go:generate mockery --name Service --structname FakePublicDashboardService --inpackage --filename public_dashboard_service_mock.go
type Service interface {
AccessTokenExists(ctx context.Context, accessToken string) (bool, error)
BuildAnonymousUser(ctx context.Context, dashboard *models.Dashboard) (*user.SignedInUser, error)
GetPublicDashboard(ctx context.Context, accessToken string) (*PublicDashboard, *models.Dashboard, error)
GetDashboard(ctx context.Context, dashboardUid string) (*models.Dashboard, error)
GetMetricRequest(ctx context.Context, dashboard *models.Dashboard, publicDashboard *PublicDashboard, panelId int64, reqDTO PublicDashboardQueryDTO) (dtos.MetricRequest, error)
GetPublicDashboardConfig(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error)
SavePublicDashboardConfig(ctx context.Context, u *user.SignedInUser, dto *SavePublicDashboardConfigDTO) (*PublicDashboard, error)
GetQueryDataResponse(ctx context.Context, skipCache bool, reqDTO *PublicDashboardQueryDTO, panelId int64, accessToken string) (*backend.QueryDataResponse, error)
GetQueryDataResponse(ctx context.Context, skipCache bool, reqDTO PublicDashboardQueryDTO, panelId int64, accessToken string) (*backend.QueryDataResponse, error)
PublicDashboardEnabled(ctx context.Context, dashboardUid string) (bool, error)
AccessTokenExists(ctx context.Context, accessToken string) (bool, error)
SavePublicDashboardConfig(ctx context.Context, u *user.SignedInUser, dto *SavePublicDashboardConfigDTO) (*PublicDashboard, error)
}
//go:generate mockery --name Store --structname FakePublicDashboardStore --inpackage --filename public_dashboard_store_mock.go
type Store interface {
GetPublicDashboard(ctx context.Context, accessToken string) (*PublicDashboard, *models.Dashboard, error)
AccessTokenExists(ctx context.Context, accessToken string) (bool, error)
GetDashboard(ctx context.Context, dashboardUid string) (*models.Dashboard, error)
GetPublicDashboardConfig(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error)
GetPublicDashboardByUid(ctx context.Context, uid string) (*PublicDashboard, error)
GenerateNewPublicDashboardUid(ctx context.Context) (string, error)
GetPublicDashboard(ctx context.Context, accessToken string) (*PublicDashboard, *models.Dashboard, error)
GetPublicDashboardByUid(ctx context.Context, uid string) (*PublicDashboard, error)
GetPublicDashboardConfig(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error)
PublicDashboardEnabled(ctx context.Context, dashboardUid string) (bool, error)
SavePublicDashboardConfig(ctx context.Context, cmd SavePublicDashboardConfigCommand) error
UpdatePublicDashboardConfig(ctx context.Context, cmd SavePublicDashboardConfigCommand) error
PublicDashboardEnabled(ctx context.Context, dashboardUid string) (bool, error)
AccessTokenExists(ctx context.Context, accessToken string) (bool, error)
}

View File

@ -190,23 +190,13 @@ func (pd *PublicDashboardServiceImpl) updatePublicDashboardConfig(ctx context.Co
return dto.PublicDashboard.Uid, pd.store.UpdatePublicDashboardConfig(ctx, cmd)
}
func (pd *PublicDashboardServiceImpl) GetQueryDataResponse(ctx context.Context, skipCache bool, reqDTO *PublicDashboardQueryDTO, panelId int64, accessToken string) (*backend.QueryDataResponse, error) {
if err := validation.ValidateQueryPublicDashboardRequest(reqDTO); err != nil {
return nil, ErrPublicDashboardBadRequest
}
func (pd *PublicDashboardServiceImpl) GetQueryDataResponse(ctx context.Context, skipCache bool, queryDto PublicDashboardQueryDTO, panelId int64, accessToken string) (*backend.QueryDataResponse, error) {
publicDashboard, dashboard, err := pd.GetPublicDashboard(ctx, accessToken)
if err != nil {
return nil, err
}
metricReqDTO, err := pd.buildPublicDashboardMetricRequest(
ctx,
dashboard,
publicDashboard,
panelId,
reqDTO,
)
metricReq, err := pd.GetMetricRequest(ctx, dashboard, publicDashboard, panelId, queryDto)
if err != nil {
return nil, err
}
@ -216,12 +206,31 @@ func (pd *PublicDashboardServiceImpl) GetQueryDataResponse(ctx context.Context,
return nil, err
}
return pd.QueryDataService.QueryDataMultipleSources(ctx, anonymousUser, skipCache, metricReqDTO, true)
return pd.QueryDataService.QueryDataMultipleSources(ctx, anonymousUser, skipCache, metricReq, true)
}
// BuildPublicDashboardMetricRequest merges public dashboard parameters with
func (pd *PublicDashboardServiceImpl) GetMetricRequest(ctx context.Context, dashboard *models.Dashboard, publicDashboard *PublicDashboard, panelId int64, queryDto PublicDashboardQueryDTO) (dtos.MetricRequest, error) {
if err := validation.ValidateQueryPublicDashboardRequest(queryDto); err != nil {
return dtos.MetricRequest{}, ErrPublicDashboardBadRequest
}
metricReqDTO, err := pd.buildMetricRequest(
ctx,
dashboard,
publicDashboard,
panelId,
queryDto,
)
if err != nil {
return dtos.MetricRequest{}, err
}
return metricReqDTO, nil
}
// buildMetricRequest merges public dashboard parameters with
// dashboard and returns a metrics request to be sent to query backend
func (pd *PublicDashboardServiceImpl) buildPublicDashboardMetricRequest(ctx context.Context, dashboard *models.Dashboard, publicDashboard *PublicDashboard, panelId int64, reqDTO *PublicDashboardQueryDTO) (dtos.MetricRequest, error) {
func (pd *PublicDashboardServiceImpl) buildMetricRequest(ctx context.Context, dashboard *models.Dashboard, publicDashboard *PublicDashboard, panelId int64, reqDTO PublicDashboardQueryDTO) (dtos.MetricRequest, error) {
// group queries by panel
queriesByPanel := queryModels.GroupQueriesByPanelId(dashboard.Data)
queries, ok := queriesByPanel[panelId]
@ -290,7 +299,7 @@ func GenerateAccessToken() (string, error) {
// this is an additional validation, all data sources implements QueryData interface and should have proper validations
// of these limits
// for the maxDataPoints we took a hard limit from prometheus which is 11000
func (pd *PublicDashboardServiceImpl) getSafeIntervalAndMaxDataPoints(reqDTO *PublicDashboardQueryDTO, ts *TimeSettings) (int64, int64) {
func (pd *PublicDashboardServiceImpl) getSafeIntervalAndMaxDataPoints(reqDTO PublicDashboardQueryDTO, ts TimeSettings) (int64, int64) {
// arbitrary max value for all data sources, it is actually a hard limit defined in prometheus
safeResolution := int64(11000)

View File

@ -6,6 +6,7 @@ import (
"time"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/publicdashboards/internal"
"github.com/grafana/grafana/pkg/services/user"
"github.com/google/uuid"
@ -18,7 +19,7 @@ import (
"github.com/grafana/grafana/pkg/models"
dashboardsDB "github.com/grafana/grafana/pkg/services/dashboards/database"
. "github.com/grafana/grafana/pkg/services/publicdashboards"
database "github.com/grafana/grafana/pkg/services/publicdashboards/database"
"github.com/grafana/grafana/pkg/services/publicdashboards/database"
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
@ -352,13 +353,57 @@ func TestBuildAnonymousUser(t *testing.T) {
})
}
func TestBuildPublicDashboardMetricRequest(t *testing.T) {
func TestGetMetricRequest(t *testing.T) {
sqlStore := sqlstore.InitTestDB(t)
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures())
publicdashboardStore := database.ProvideStore(sqlStore)
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
publicDashboard := &PublicDashboard{
Uid: "1",
DashboardUid: dashboard.Uid,
IsEnabled: true,
AccessToken: "abc123",
}
service := &PublicDashboardServiceImpl{
log: log.New("test.logger"),
store: publicdashboardStore,
intervalCalculator: intervalv2.NewCalculator(),
}
t.Run("will return an error when validation fails", func(t *testing.T) {
publicDashboardQueryDTO := PublicDashboardQueryDTO{
IntervalMs: int64(-1),
MaxDataPoints: int64(-1),
}
_, err := service.GetMetricRequest(context.Background(), dashboard, publicDashboard, 1, publicDashboardQueryDTO)
require.Error(t, err)
})
t.Run("will not return an error when validation succeeds", func(t *testing.T) {
publicDashboardQueryDTO := PublicDashboardQueryDTO{
IntervalMs: int64(1),
MaxDataPoints: int64(1),
}
from, to := internal.GetTimeRangeFromDashboard(t, dashboard.Data)
metricReq, err := service.GetMetricRequest(context.Background(), dashboard, publicDashboard, 1, publicDashboardQueryDTO)
require.NoError(t, err)
require.Equal(t, from, metricReq.From)
require.Equal(t, to, metricReq.To)
})
}
func TestBuildMetricRequest(t *testing.T) {
sqlStore := sqlstore.InitTestDB(t)
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures())
publicdashboardStore := database.ProvideStore(sqlStore)
publicDashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
nonPublicDashboard := insertTestDashboard(t, dashboardStore, "testNonPublicDashie", 1, 0, true, []map[string]interface{}{})
from, to := internal.GetTimeRangeFromDashboard(t, publicDashboard.Data)
service := &PublicDashboardServiceImpl{
log: log.New("test.logger"),
@ -366,7 +411,7 @@ func TestBuildPublicDashboardMetricRequest(t *testing.T) {
intervalCalculator: intervalv2.NewCalculator(),
}
publicDashboardQueryDTO := &PublicDashboardQueryDTO{
publicDashboardQueryDTO := PublicDashboardQueryDTO{
IntervalMs: int64(10000000),
MaxDataPoints: int64(200),
}
@ -400,7 +445,7 @@ func TestBuildPublicDashboardMetricRequest(t *testing.T) {
require.NoError(t, err)
t.Run("extracts queries from provided dashboard", func(t *testing.T) {
reqDTO, err := service.buildPublicDashboardMetricRequest(
reqDTO, err := service.buildMetricRequest(
context.Background(),
publicDashboard,
publicDashboardPD,
@ -409,8 +454,8 @@ func TestBuildPublicDashboardMetricRequest(t *testing.T) {
)
require.NoError(t, err)
require.Equal(t, timeSettings.Get("from").MustString(), reqDTO.From)
require.Equal(t, timeSettings.Get("to").MustString(), reqDTO.To)
require.Equal(t, from, reqDTO.From)
require.Equal(t, to, reqDTO.To)
for i := range reqDTO.Queries {
require.Equal(t, publicDashboardQueryDTO.IntervalMs, reqDTO.Queries[i].Get("intervalMs").MustInt64())
@ -449,7 +494,7 @@ func TestBuildPublicDashboardMetricRequest(t *testing.T) {
})
t.Run("returns an error when panel missing", func(t *testing.T) {
_, err := service.buildPublicDashboardMetricRequest(
_, err := service.buildMetricRequest(
context.Background(),
publicDashboard,
publicDashboardPD,
@ -514,6 +559,10 @@ func insertTestDashboard(t *testing.T, dashboardStore *dashboardsDB.DashboardSto
"templating": map[string]interface{}{
"list": templateVars,
},
"time": map[string]interface{}{
"from": "2022-09-01T00:00:00.000Z",
"to": "2022-09-01T12:00:00.000Z",
},
}),
}
dash, err := dashboardStore.SaveDashboard(cmd)
@ -526,8 +575,8 @@ func insertTestDashboard(t *testing.T, dashboardStore *dashboardsDB.DashboardSto
func TestPublicDashboardServiceImpl_getSafeIntervalAndMaxDataPoints(t *testing.T) {
type args struct {
reqDTO *PublicDashboardQueryDTO
ts *TimeSettings
reqDTO PublicDashboardQueryDTO
ts TimeSettings
}
tests := []struct {
name string
@ -538,11 +587,11 @@ func TestPublicDashboardServiceImpl_getSafeIntervalAndMaxDataPoints(t *testing.T
{
name: "return original interval",
args: args{
reqDTO: &PublicDashboardQueryDTO{
reqDTO: PublicDashboardQueryDTO{
IntervalMs: 10000,
MaxDataPoints: 300,
},
ts: &TimeSettings{
ts: TimeSettings{
From: "now-3h",
To: "now",
},
@ -553,11 +602,11 @@ func TestPublicDashboardServiceImpl_getSafeIntervalAndMaxDataPoints(t *testing.T
{
name: "return safe interval because of a small interval",
args: args{
reqDTO: &PublicDashboardQueryDTO{
reqDTO: PublicDashboardQueryDTO{
IntervalMs: 1000,
MaxDataPoints: 300,
},
ts: &TimeSettings{
ts: TimeSettings{
From: "now-6h",
To: "now",
},
@ -568,11 +617,11 @@ func TestPublicDashboardServiceImpl_getSafeIntervalAndMaxDataPoints(t *testing.T
{
name: "return safe interval for long time range",
args: args{
reqDTO: &PublicDashboardQueryDTO{
reqDTO: PublicDashboardQueryDTO{
IntervalMs: 100,
MaxDataPoints: 300,
},
ts: &TimeSettings{
ts: TimeSettings{
From: "now-90d",
To: "now",
},
@ -583,8 +632,8 @@ func TestPublicDashboardServiceImpl_getSafeIntervalAndMaxDataPoints(t *testing.T
{
name: "return safe interval when reqDTO is empty",
args: args{
reqDTO: &PublicDashboardQueryDTO{},
ts: &TimeSettings{
reqDTO: PublicDashboardQueryDTO{},
ts: TimeSettings{
From: "now-90d",
To: "now",
},

View File

@ -21,7 +21,7 @@ func hasTemplateVariables(dashboard *models.Dashboard) bool {
return len(templateVariables) > 0
}
func ValidateQueryPublicDashboardRequest(req *publicDashboardModels.PublicDashboardQueryDTO) error {
func ValidateQueryPublicDashboardRequest(req publicDashboardModels.PublicDashboardQueryDTO) error {
if req.IntervalMs < 0 {
return fmt.Errorf("intervalMS should be greater than 0")
}