Chore: Add alert ctx (#41161)

* Add context for alert

* Remove context.TODO

* Remove xorm

* Remove context.TODO

* Fix UsageStatsQuerier interface
This commit is contained in:
idafurjes 2021-11-03 14:10:39 +01:00 committed by GitHub
parent 0997065e04
commit 9340430723
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 198 additions and 186 deletions

View File

@ -330,7 +330,7 @@ func (hs *HTTPServer) PostDashboard(c *models.ReqContext, cmd models.SaveDashboa
}
dashSvc := dashboards.NewService(hs.SQLStore)
dashboard, err := dashSvc.SaveDashboard(dashItem, allowUiUpdate)
dashboard, err := dashSvc.SaveDashboard(ctx, dashItem, allowUiUpdate)
if hs.Live != nil {
// Tell everyone listening that the dashboard changed

View File

@ -18,5 +18,5 @@ type Store interface {
SaveDashboard(cmd models.SaveDashboardCommand) (*models.Dashboard, error)
UpdateDashboardACLCtx(ctx context.Context, uid int64, items []*models.DashboardAcl) error
// SaveAlerts saves dashboard alerts.
SaveAlerts(dashID int64, alerts []*models.Alert) error
SaveAlerts(ctx context.Context, dashID int64, alerts []*models.Alert) error
}

View File

@ -16,10 +16,10 @@ func (usm *UsageStatsMock) RegisterMetricsFunc(fn MetricsFunc) {
usm.metricsFuncs = append(usm.metricsFuncs, fn)
}
func (usm *UsageStatsMock) GetUsageReport(_ context.Context) (Report, error) {
func (usm *UsageStatsMock) GetUsageReport(ctx context.Context) (Report, error) {
all := make(map[string]interface{})
for _, fn := range usm.metricsFuncs {
fnMetrics, err := fn()
fnMetrics, err := fn(ctx)
require.NoError(usm.T, err)
for name, value := range fnMetrics {

View File

@ -15,7 +15,7 @@ type Report struct {
UsageStatsId string `json:"usageStatsId"`
}
type MetricsFunc func() (map[string]interface{}, error)
type MetricsFunc func(context.Context) (map[string]interface{}, error)
type SendReportCallbackFunc func()

View File

@ -93,7 +93,7 @@ func (uss *UsageStats) GetUsageReport(ctx context.Context) (usagestats.Report, e
metrics["stats.edition.oss.count"] = ossEditionCount
metrics["stats.edition.enterprise.count"] = enterpriseEditionCount
uss.registerExternalMetrics(metrics)
uss.registerExternalMetrics(ctx, metrics)
// must run after registration of external metrics
if v, ok := metrics["stats.valid_license.count"]; ok {
@ -231,9 +231,9 @@ func (uss *UsageStats) GetUsageReport(ctx context.Context) (usagestats.Report, e
return report, nil
}
func (uss *UsageStats) registerExternalMetrics(metrics map[string]interface{}) {
func (uss *UsageStats) registerExternalMetrics(ctx context.Context, metrics map[string]interface{}) {
for _, fn := range uss.externalMetrics {
fnMetrics, err := fn()
fnMetrics, err := fn(ctx)
if err != nil {
uss.log.Error("Failed to fetch external metrics", "error", err)
continue

View File

@ -448,11 +448,11 @@ func TestMetrics(t *testing.T) {
metricName := "stats.test_metric.count"
t.Run("Adds a new metric to the external metrics", func(t *testing.T) {
uss.RegisterMetricsFunc(func() (map[string]interface{}, error) {
uss.RegisterMetricsFunc(func(context.Context) (map[string]interface{}, error) {
return map[string]interface{}{metricName: 1}, nil
})
metrics, err := uss.externalMetrics[0]()
metrics, err := uss.externalMetrics[0](context.Background())
require.NoError(t, err)
assert.Equal(t, map[string]interface{}{metricName: 1}, metrics)
})
@ -502,7 +502,7 @@ func TestMetrics(t *testing.T) {
})
t.Run("Should include external metrics", func(t *testing.T) {
uss.RegisterMetricsFunc(func() (map[string]interface{}, error) {
uss.RegisterMetricsFunc(func(context.Context) (map[string]interface{}, error) {
return map[string]interface{}{metricName: 1}, nil
})
@ -519,26 +519,26 @@ func TestMetrics(t *testing.T) {
metrics := map[string]interface{}{"stats.test_metric.count": 1, "stats.test_metric_second.count": 2}
extMetricName := "stats.test_external_metric.count"
uss.RegisterMetricsFunc(func() (map[string]interface{}, error) {
uss.RegisterMetricsFunc(func(context.Context) (map[string]interface{}, error) {
return map[string]interface{}{extMetricName: 1}, nil
})
uss.registerExternalMetrics(metrics)
uss.registerExternalMetrics(context.Background(), metrics)
assert.Equal(t, 1, metrics[extMetricName])
t.Run("When loading a metric results to an error", func(t *testing.T) {
uss.RegisterMetricsFunc(func() (map[string]interface{}, error) {
uss.RegisterMetricsFunc(func(context.Context) (map[string]interface{}, error) {
return map[string]interface{}{extMetricName: 1}, nil
})
extErrorMetricName := "stats.test_external_metric_error.count"
t.Run("Should not add it to metrics", func(t *testing.T) {
uss.RegisterMetricsFunc(func() (map[string]interface{}, error) {
uss.RegisterMetricsFunc(func(context.Context) (map[string]interface{}, error) {
return map[string]interface{}{extErrorMetricName: 1}, errors.New("some error")
})
uss.registerExternalMetrics(metrics)
uss.registerExternalMetrics(context.Background(), metrics)
extErrorMetric := metrics[extErrorMetricName]
extMetric := metrics[extMetricName]

View File

@ -43,7 +43,7 @@ func (ac *OSSAccessControlService) IsDisabled() bool {
}
func (ac *OSSAccessControlService) registerUsageMetrics() {
ac.UsageStats.RegisterMetricsFunc(func() (map[string]interface{}, error) {
ac.UsageStats.RegisterMetricsFunc(func(context.Context) (map[string]interface{}, error) {
return map[string]interface{}{
"stats.oss.accesscontrol.enabled.count": ac.getUsageMetrics(),
}, nil

View File

@ -21,14 +21,14 @@ type UsageStats struct {
// UsageStatsQuerier returns usage stats about alert rules
// configured in Grafana.
type UsageStatsQuerier interface {
QueryUsageStats() (*UsageStats, error)
QueryUsageStats(context.Context) (*UsageStats, error)
}
// QueryUsageStats returns usage stats about alert rules
// configured in Grafana.
func (e *AlertEngine) QueryUsageStats() (*UsageStats, error) {
func (e *AlertEngine) QueryUsageStats(ctx context.Context) (*UsageStats, error) {
cmd := &models.GetAllAlertsQuery{}
err := e.Bus.Dispatch(cmd)
err := e.Bus.DispatchCtx(ctx, cmd)
if err != nil {
return nil, err
}

View File

@ -56,7 +56,7 @@ func TestAlertingUsageStats(t *testing.T) {
return nil
})
result, err := ae.QueryUsageStats()
result, err := ae.QueryUsageStats(context.Background())
require.NoError(t, err, "getAlertingUsage should not return error")
expected := map[string]int{

View File

@ -97,7 +97,7 @@ func (e *AlertEngine) alertingTicker(grafanaCtx context.Context) error {
case tick := <-e.ticker.C:
// TEMP SOLUTION update rules ever tenth tick
if tickIndex%10 == 0 {
e.scheduler.Update(e.ruleReader.fetch())
e.scheduler.Update(e.ruleReader.fetch(grafanaCtx))
}
e.scheduler.Tick(tick, e.execQueue)
@ -246,8 +246,8 @@ func (e *AlertEngine) processJob(attemptID int, attemptChan chan int, cancelChan
}
func (e *AlertEngine) registerUsageMetrics() {
e.usageStatsService.RegisterMetricsFunc(func() (map[string]interface{}, error) {
alertingUsageStats, err := e.QueryUsageStats()
e.usageStatsService.RegisterMetricsFunc(func(ctx context.Context) (map[string]interface{}, error) {
alertingUsageStats, err := e.QueryUsageStats(ctx)
if err != nil {
return nil, err
}

View File

@ -1,6 +1,7 @@
package alerting
import (
"context"
"sync"
"github.com/grafana/grafana/pkg/bus"
@ -10,7 +11,7 @@ import (
)
type ruleReader interface {
fetch() []*Rule
fetch(context.Context) []*Rule
}
type defaultRuleReader struct {
@ -26,10 +27,10 @@ func newRuleReader() *defaultRuleReader {
return ruleReader
}
func (arr *defaultRuleReader) fetch() []*Rule {
func (arr *defaultRuleReader) fetch(ctx context.Context) []*Rule {
cmd := &models.GetAllAlertsQuery{}
if err := bus.Dispatch(cmd); err != nil {
if err := bus.DispatchCtx(ctx, cmd); err != nil {
arr.log.Error("Could not load alerts", "error", err)
return []*Rule{}
}

View File

@ -21,7 +21,7 @@ import (
// DashboardService is a service for operating on dashboards.
type DashboardService interface {
SaveDashboard(dto *SaveDashboardDTO, allowUiUpdate bool) (*models.Dashboard, error)
SaveDashboard(ctx context.Context, dto *SaveDashboardDTO, allowUiUpdate bool) (*models.Dashboard, error)
ImportDashboard(dto *SaveDashboardDTO) (*models.Dashboard, error)
DeleteDashboard(dashboardId int64, orgId int64) error
MakeUserAdmin(ctx context.Context, orgID int64, userID, dashboardID int64, setViewAndEditPermissions bool) error
@ -29,8 +29,8 @@ type DashboardService interface {
// DashboardProvisioningService is a service for operating on provisioned dashboards.
type DashboardProvisioningService interface {
SaveProvisionedDashboard(dto *SaveDashboardDTO, provisioning *models.DashboardProvisioning) (*models.Dashboard, error)
SaveFolderForProvisionedDashboards(*SaveDashboardDTO) (*models.Dashboard, error)
SaveProvisionedDashboard(ctx context.Context, dto *SaveDashboardDTO, provisioning *models.DashboardProvisioning) (*models.Dashboard, error)
SaveFolderForProvisionedDashboards(context.Context, *SaveDashboardDTO) (*models.Dashboard, error)
GetProvisionedDashboardData(name string) ([]*models.DashboardProvisioning, error)
GetProvisionedDashboardDataByDashboardID(dashboardID int64) (*models.DashboardProvisioning, error)
UnprovisionDashboard(dashboardID int64) error
@ -205,17 +205,17 @@ func validateDashboardRefreshInterval(dash *models.Dashboard) error {
// UpdateAlerting updates alerting.
//
// Stubbable by tests.
var UpdateAlerting = func(store dashboards.Store, orgID int64, dashboard *models.Dashboard, user *models.SignedInUser) error {
var UpdateAlerting = func(ctx context.Context, store dashboards.Store, orgID int64, dashboard *models.Dashboard, user *models.SignedInUser) error {
extractor := alerting.NewDashAlertExtractor(dashboard, orgID, user)
alerts, err := extractor.GetAlerts()
if err != nil {
return err
}
return store.SaveAlerts(dashboard.Id, alerts)
return store.SaveAlerts(ctx, dashboard.Id, alerts)
}
func (dr *dashboardServiceImpl) SaveProvisionedDashboard(dto *SaveDashboardDTO,
func (dr *dashboardServiceImpl) SaveProvisionedDashboard(ctx context.Context, dto *SaveDashboardDTO,
provisioning *models.DashboardProvisioning) (*models.Dashboard, error) {
if err := validateDashboardRefreshInterval(dto.Dashboard); err != nil {
dr.log.Warn("Changing refresh interval for provisioned dashboard to minimum refresh interval", "dashboardUid",
@ -241,14 +241,14 @@ func (dr *dashboardServiceImpl) SaveProvisionedDashboard(dto *SaveDashboardDTO,
}
// alerts
if err := UpdateAlerting(dr.dashboardStore, dto.OrgId, dash, dto.User); err != nil {
if err := UpdateAlerting(ctx, dr.dashboardStore, dto.OrgId, dash, dto.User); err != nil {
return nil, err
}
return dash, nil
}
func (dr *dashboardServiceImpl) SaveFolderForProvisionedDashboards(dto *SaveDashboardDTO) (*models.Dashboard, error) {
func (dr *dashboardServiceImpl) SaveFolderForProvisionedDashboards(ctx context.Context, dto *SaveDashboardDTO) (*models.Dashboard, error) {
dto.User = &models.SignedInUser{
UserId: 0,
OrgRole: models.ROLE_ADMIN,
@ -263,14 +263,14 @@ func (dr *dashboardServiceImpl) SaveFolderForProvisionedDashboards(dto *SaveDash
return nil, err
}
if err := UpdateAlerting(dr.dashboardStore, dto.OrgId, dash, dto.User); err != nil {
if err := UpdateAlerting(ctx, dr.dashboardStore, dto.OrgId, dash, dto.User); err != nil {
return nil, err
}
return dash, nil
}
func (dr *dashboardServiceImpl) SaveDashboard(dto *SaveDashboardDTO,
func (dr *dashboardServiceImpl) SaveDashboard(ctx context.Context, dto *SaveDashboardDTO,
allowUiUpdate bool) (*models.Dashboard, error) {
if err := validateDashboardRefreshInterval(dto.Dashboard); err != nil {
dr.log.Warn("Changing refresh interval for imported dashboard to minimum refresh interval",
@ -289,7 +289,7 @@ func (dr *dashboardServiceImpl) SaveDashboard(dto *SaveDashboardDTO,
return nil, fmt.Errorf("saving dashboard failed: %w", err)
}
if err := UpdateAlerting(dr.dashboardStore, dto.OrgId, dash, dto.User); err != nil {
if err := UpdateAlerting(ctx, dr.dashboardStore, dto.OrgId, dash, dto.User); err != nil {
return nil, err
}
@ -360,7 +360,7 @@ type FakeDashboardService struct {
ProvisionedDashData *models.DashboardProvisioning
}
func (s *FakeDashboardService) SaveDashboard(dto *SaveDashboardDTO, allowUiUpdate bool) (*models.Dashboard, error) {
func (s *FakeDashboardService) SaveDashboard(ctx context.Context, dto *SaveDashboardDTO, allowUiUpdate bool) (*models.Dashboard, error) {
s.SavedDashboards = append(s.SavedDashboards, dto)
if s.SaveDashboardResult == nil && s.SaveDashboardError == nil {
@ -371,7 +371,7 @@ func (s *FakeDashboardService) SaveDashboard(dto *SaveDashboardDTO, allowUiUpdat
}
func (s *FakeDashboardService) ImportDashboard(dto *SaveDashboardDTO) (*models.Dashboard, error) {
return s.SaveDashboard(dto, true)
return s.SaveDashboard(context.Background(), dto, true)
}
func (s *FakeDashboardService) DeleteDashboard(dashboardId int64, orgId int64) error {

View File

@ -4,6 +4,7 @@
package dashboards
import (
"context"
"testing"
"github.com/grafana/grafana/pkg/components/simplejson"
@ -24,7 +25,7 @@ func TestIntegratedDashboardService(t *testing.T) {
t.Cleanup(func() {
UpdateAlerting = origUpdateAlerting
})
UpdateAlerting = func(store dashboards.Store, orgID int64, dashboard *models.Dashboard, user *models.SignedInUser) error {
UpdateAlerting = func(ctx context.Context, store dashboards.Store, orgID int64, dashboard *models.Dashboard, user *models.SignedInUser) error {
return nil
}
@ -849,7 +850,7 @@ func callSaveWithResult(t *testing.T, cmd models.SaveDashboardCommand, sqlStore
t.Helper()
dto := toSaveDashboardDto(cmd)
res, err := NewService(sqlStore).SaveDashboard(&dto, false)
res, err := NewService(sqlStore).SaveDashboard(context.Background(), &dto, false)
require.NoError(t, err)
return res
@ -857,7 +858,7 @@ func callSaveWithResult(t *testing.T, cmd models.SaveDashboardCommand, sqlStore
func callSaveWithError(cmd models.SaveDashboardCommand, sqlStore *sqlstore.SQLStore) error {
dto := toSaveDashboardDto(cmd)
_, err := NewService(sqlStore).SaveDashboard(&dto, false)
_, err := NewService(sqlStore).SaveDashboard(context.Background(), &dto, false)
return err
}
@ -883,7 +884,7 @@ func saveTestDashboard(t *testing.T, title string, orgID, folderID int64, sqlSto
},
}
res, err := NewService(sqlStore).SaveDashboard(&dto, false)
res, err := NewService(sqlStore).SaveDashboard(context.Background(), &dto, false)
require.NoError(t, err)
return res
@ -910,7 +911,7 @@ func saveTestFolder(t *testing.T, title string, orgID int64, sqlStore *sqlstore.
},
}
res, err := NewService(sqlStore).SaveDashboard(&dto, false)
res, err := NewService(sqlStore).SaveDashboard(context.Background(), &dto, false)
require.NoError(t, err)
return res

View File

@ -1,6 +1,7 @@
package dashboards
import (
"context"
"fmt"
"testing"
@ -37,7 +38,7 @@ func TestDashboardService(t *testing.T) {
for _, title := range titles {
dto.Dashboard = models.NewDashboard(title)
_, err := service.SaveDashboard(dto, false)
_, err := service.SaveDashboard(context.Background(), dto, false)
require.Equal(t, err, models.ErrDashboardTitleEmpty)
}
})
@ -45,13 +46,13 @@ func TestDashboardService(t *testing.T) {
t.Run("Should return validation error if it's a folder and have a folder id", func(t *testing.T) {
dto.Dashboard = models.NewDashboardFolder("Folder")
dto.Dashboard.FolderId = 1
_, err := service.SaveDashboard(dto, false)
_, err := service.SaveDashboard(context.Background(), dto, false)
require.Equal(t, err, models.ErrDashboardFolderCannotHaveParent)
})
t.Run("Should return validation error if folder is named General", func(t *testing.T) {
dto.Dashboard = models.NewDashboardFolder("General")
_, err := service.SaveDashboard(dto, false)
_, err := service.SaveDashboard(context.Background(), dto, false)
require.Equal(t, err, models.ErrDashboardFolderNameExists)
})
@ -104,7 +105,7 @@ func TestDashboardService(t *testing.T) {
dto.Dashboard = models.NewDashboard("Dash")
dto.Dashboard.SetId(3)
dto.User = &models.SignedInUser{UserId: 1}
_, err := service.SaveDashboard(dto, false)
_, err := service.SaveDashboard(context.Background(), dto, false)
require.Equal(t, err, models.ErrDashboardCannotSaveProvisionedDashboard)
})
@ -120,7 +121,7 @@ func TestDashboardService(t *testing.T) {
dto.Dashboard = models.NewDashboard("Dash")
dto.Dashboard.SetId(3)
dto.User = &models.SignedInUser{UserId: 1}
_, err := service.SaveDashboard(dto, true)
_, err := service.SaveDashboard(context.Background(), dto, true)
require.NoError(t, err)
})
@ -134,7 +135,7 @@ func TestDashboardService(t *testing.T) {
}
dto.Dashboard = models.NewDashboard("Dash")
_, err := service.SaveDashboard(dto, false)
_, err := service.SaveDashboard(context.Background(), dto, false)
require.Equal(t, err.Error(), "alert validation error")
})
})
@ -147,7 +148,7 @@ func TestDashboardService(t *testing.T) {
t.Cleanup(func() {
UpdateAlerting = origUpdateAlerting
})
UpdateAlerting = func(store dashboards.Store, orgID int64, dashboard *models.Dashboard,
UpdateAlerting = func(ctx context.Context, store dashboards.Store, orgID int64, dashboard *models.Dashboard,
user *models.SignedInUser) error {
return nil
}
@ -163,7 +164,7 @@ func TestDashboardService(t *testing.T) {
dto.Dashboard = models.NewDashboard("Dash")
dto.Dashboard.SetId(3)
dto.User = &models.SignedInUser{UserId: 1}
_, err := service.SaveProvisionedDashboard(dto, nil)
_, err := service.SaveProvisionedDashboard(context.Background(), dto, nil)
require.NoError(t, err)
})
@ -184,7 +185,7 @@ func TestDashboardService(t *testing.T) {
t.Cleanup(func() {
UpdateAlerting = origUpdateAlerting
})
UpdateAlerting = func(store dashboards.Store, orgID int64, dashboard *models.Dashboard,
UpdateAlerting = func(ctx context.Context, store dashboards.Store, orgID int64, dashboard *models.Dashboard,
user *models.SignedInUser) error {
return nil
}
@ -193,7 +194,7 @@ func TestDashboardService(t *testing.T) {
dto.Dashboard.SetId(3)
dto.User = &models.SignedInUser{UserId: 1}
dto.Dashboard.Data.Set("refresh", "1s")
_, err := service.SaveProvisionedDashboard(dto, nil)
_, err := service.SaveProvisionedDashboard(context.Background(), dto, nil)
require.NoError(t, err)
require.Equal(t, dto.Dashboard.Data.Get("refresh").MustString(), "5m")
})
@ -220,7 +221,7 @@ func TestDashboardService(t *testing.T) {
t.Cleanup(func() {
UpdateAlerting = origUpdateAlerting
})
UpdateAlerting = func(store dashboards.Store, orgID int64, dashboard *models.Dashboard,
UpdateAlerting = func(ctx context.Context, store dashboards.Store, orgID int64, dashboard *models.Dashboard,
user *models.SignedInUser) error {
return nil
}
@ -317,6 +318,6 @@ func (s *fakeDashboardStore) SaveDashboard(cmd models.SaveDashboardCommand) (*mo
return cmd.GetDashboardModel(), nil
}
func (s *fakeDashboardStore) SaveAlerts(dashID int64, alerts []*models.Alert) error {
func (s *fakeDashboardStore) SaveAlerts(ctx context.Context, dashID int64, alerts []*models.Alert) error {
return nil
}

View File

@ -94,7 +94,7 @@ func TestFolderService(t *testing.T) {
t.Cleanup(func() {
UpdateAlerting = origUpdateAlerting
})
UpdateAlerting = func(store dashboards.Store, orgID int64, dashboard *models.Dashboard,
UpdateAlerting = func(ctx context.Context, store dashboards.Store, orgID int64, dashboard *models.Dashboard,
user *models.SignedInUser) error {
return nil
}

View File

@ -189,12 +189,12 @@ func createDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, user models.Sign
t.Cleanup(func() {
dashboards.UpdateAlerting = origUpdateAlerting
})
dashboards.UpdateAlerting = func(store dboards.Store, orgID int64, dashboard *models.Dashboard,
dashboards.UpdateAlerting = func(ctx context.Context, store dboards.Store, orgID int64, dashboard *models.Dashboard,
user *models.SignedInUser) error {
return nil
}
dashboard, err := dashboards.NewService(sqlStore).SaveDashboard(dashItem, true)
dashboard, err := dashboards.NewService(sqlStore).SaveDashboard(context.Background(), dashItem, true)
require.NoError(t, err)
return dashboard

View File

@ -1417,12 +1417,12 @@ func createDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, user *models.Sig
t.Cleanup(func() {
dashboards.UpdateAlerting = origUpdateAlerting
})
dashboards.UpdateAlerting = func(store dboards.Store, orgID int64, dashboard *models.Dashboard,
dashboards.UpdateAlerting = func(ctx context.Context, store dboards.Store, orgID int64, dashboard *models.Dashboard,
user *models.SignedInUser) error {
return nil
}
dashboard, err := dashboards.NewService(sqlStore).SaveDashboard(dashItem, true)
dashboard, err := dashboards.NewService(sqlStore).SaveDashboard(context.Background(), dashItem, true)
require.NoError(t, err)
return dashboard

View File

@ -1210,7 +1210,7 @@ func (g *GrafanaLive) resetLiveStats() {
func (g *GrafanaLive) registerUsageMetrics() {
g.usageStatsService.RegisterSendReportCallback(g.resetLiveStats)
g.usageStatsService.RegisterMetricsFunc(func() (map[string]interface{}, error) {
g.usageStatsService.RegisterMetricsFunc(func(context.Context) (map[string]interface{}, error) {
liveUsersAvg := 0
liveClientsAvg := 0

View File

@ -146,7 +146,7 @@ func (fr *FileReader) storeDashboardsInFolder(ctx context.Context, filesFoundOnD
// save dashboards based on json files
for path, fileInfo := range filesFoundOnDisk {
provisioningMetadata, err := fr.saveDashboard(path, folderID, fileInfo, dashboardRefs)
provisioningMetadata, err := fr.saveDashboard(ctx, path, folderID, fileInfo, dashboardRefs)
if err != nil {
fr.log.Error("failed to save dashboard", "error", err)
continue
@ -174,7 +174,7 @@ func (fr *FileReader) storeDashboardsInFoldersFromFileStructure(ctx context.Cont
return fmt.Errorf("can't provision folder %q from file system structure: %w", folderName, err)
}
provisioningMetadata, err := fr.saveDashboard(path, folderID, fileInfo, dashboardRefs)
provisioningMetadata, err := fr.saveDashboard(ctx, path, folderID, fileInfo, dashboardRefs)
usageTracker.track(provisioningMetadata)
if err != nil {
fr.log.Error("failed to save dashboard", "error", err)
@ -218,7 +218,7 @@ func (fr *FileReader) handleMissingDashboardFiles(provisionedDashboardRefs map[s
}
// saveDashboard saves or updates the dashboard provisioning file at path.
func (fr *FileReader) saveDashboard(path string, folderID int64, fileInfo os.FileInfo,
func (fr *FileReader) saveDashboard(ctx context.Context, path string, folderID int64, fileInfo os.FileInfo,
provisionedDashboardRefs map[string]*models.DashboardProvisioning) (provisioningMetadata, error) {
provisioningMetadata := provisioningMetadata{}
resolvedFileInfo, err := resolveSymlink(fileInfo, path)
@ -265,7 +265,7 @@ func (fr *FileReader) saveDashboard(path string, folderID int64, fileInfo os.Fil
Updated: resolvedFileInfo.ModTime().Unix(),
CheckSum: jsonFile.checkSum,
}
if _, err := fr.dashboardProvisioningService.SaveProvisionedDashboard(dash, dp); err != nil {
if _, err := fr.dashboardProvisioningService.SaveProvisionedDashboard(ctx, dash, dp); err != nil {
return provisioningMetadata, err
}
} else {
@ -312,7 +312,7 @@ func getOrCreateFolderID(ctx context.Context, cfg *config, service dashboards.Da
dash.OrgId = cfg.OrgID
// set dashboard folderUid if given
dash.Dashboard.SetUid(cfg.FolderUID)
dbDash, err := service.SaveFolderForProvisionedDashboards(dash)
dbDash, err := service.SaveFolderForProvisionedDashboards(ctx, dash)
if err != nil {
return 0, err
}

View File

@ -565,7 +565,7 @@ func (s *fakeDashboardProvisioningService) GetProvisionedDashboardData(name stri
return s.provisioned[name], nil
}
func (s *fakeDashboardProvisioningService) SaveProvisionedDashboard(dto *dashboards.SaveDashboardDTO,
func (s *fakeDashboardProvisioningService) SaveProvisionedDashboard(ctx context.Context, dto *dashboards.SaveDashboardDTO,
provisioning *models.DashboardProvisioning) (*models.Dashboard, error) {
// Copy the structs as we need to change them but do not want to alter outside world.
var copyProvisioning = &models.DashboardProvisioning{}
@ -603,7 +603,7 @@ func (s *fakeDashboardProvisioningService) SaveProvisionedDashboard(dto *dashboa
return dto.Dashboard, nil
}
func (s *fakeDashboardProvisioningService) SaveFolderForProvisionedDashboards(dto *dashboards.SaveDashboardDTO) (*models.Dashboard, error) {
func (s *fakeDashboardProvisioningService) SaveFolderForProvisionedDashboards(ctx context.Context, dto *dashboards.SaveDashboardDTO) (*models.Dashboard, error) {
s.inserted = append(s.inserted, dto)
return dto.Dashboard, nil
}

View File

@ -14,20 +14,21 @@ import (
// timeNow makes it possible to test usage of time
var timeNow = time.Now
func init() {
bus.AddHandler("sql", SaveAlerts)
bus.AddHandler("sql", HandleAlertsQuery)
bus.AddHandler("sql", GetAlertById)
bus.AddHandler("sql", GetAllAlertQueryHandler)
bus.AddHandler("sql", SetAlertState)
bus.AddHandler("sql", GetAlertStatesForDashboard)
bus.AddHandler("sql", PauseAlert)
bus.AddHandler("sql", PauseAllAlerts)
func (ss *SQLStore) addAlertQueryAndCommandHandlers() {
bus.AddHandlerCtx("sql", SaveAlerts)
bus.AddHandlerCtx("sql", ss.HandleAlertsQuery)
bus.AddHandlerCtx("sql", ss.GetAlertById)
bus.AddHandlerCtx("sql", ss.GetAllAlertQueryHandler)
bus.AddHandlerCtx("sql", SetAlertState)
bus.AddHandlerCtx("sql", ss.GetAlertStatesForDashboard)
bus.AddHandlerCtx("sql", PauseAlert)
bus.AddHandlerCtx("sql", PauseAllAlerts)
}
func GetAlertById(query *models.GetAlertByIdQuery) error {
func (ss *SQLStore) GetAlertById(ctx context.Context, query *models.GetAlertByIdQuery) error {
return ss.WithDbSession(ctx, func(sess *DBSession) error {
alert := models.Alert{}
has, err := x.ID(query.Id).Get(&alert)
has, err := sess.ID(query.Id).Get(&alert)
if !has {
return fmt.Errorf("could not find alert")
}
@ -37,17 +38,20 @@ func GetAlertById(query *models.GetAlertByIdQuery) error {
query.Result = &alert
return nil
})
}
func GetAllAlertQueryHandler(query *models.GetAllAlertsQuery) error {
func (ss *SQLStore) GetAllAlertQueryHandler(ctx context.Context, query *models.GetAllAlertsQuery) error {
return ss.WithDbSession(ctx, func(sess *DBSession) error {
var alerts []*models.Alert
err := x.SQL("select * from alert").Find(&alerts)
err := sess.SQL("select * from alert").Find(&alerts)
if err != nil {
return err
}
query.Result = alerts
return nil
})
}
func deleteAlertByIdInternal(alertId int64, reason string, sess *DBSession) error {
@ -72,7 +76,8 @@ func deleteAlertByIdInternal(alertId int64, reason string, sess *DBSession) erro
return nil
}
func HandleAlertsQuery(query *models.GetAlertsQuery) error {
func (ss *SQLStore) HandleAlertsQuery(ctx context.Context, query *models.GetAlertsQuery) error {
return ss.WithDbSession(ctx, func(sess *DBSession) error {
builder := SQLBuilder{}
builder.Write(`SELECT
@ -136,7 +141,7 @@ func HandleAlertsQuery(query *models.GetAlertsQuery) error {
}
alerts := make([]*models.AlertListItemDTO, 0)
if err := x.SQL(builder.GetSQLString(), builder.params...).Find(&alerts); err != nil {
if err := sess.SQL(builder.GetSQLString(), builder.params...).Find(&alerts); err != nil {
return err
}
@ -148,6 +153,7 @@ func HandleAlertsQuery(query *models.GetAlertsQuery) error {
query.Result = alerts
return nil
})
}
func deleteAlertDefinition(dashboardId int64, sess *DBSession) error {
@ -167,7 +173,7 @@ func deleteAlertDefinition(dashboardId int64, sess *DBSession) error {
return nil
}
func (ss *SQLStore) SaveAlerts(dashID int64, alerts []*models.Alert) error {
func (ss *SQLStore) SaveAlerts(ctx context.Context, dashID int64, alerts []*models.Alert) error {
return ss.WithTransactionalDbSession(context.Background(), func(sess *DBSession) error {
existingAlerts, err := GetAlertsByDashboardId2(dashID, sess)
if err != nil {
@ -186,7 +192,7 @@ func (ss *SQLStore) SaveAlerts(dashID int64, alerts []*models.Alert) error {
})
}
func SaveAlerts(cmd *models.SaveAlertsCommand) error {
func SaveAlerts(ctx context.Context, cmd *models.SaveAlertsCommand) error {
return inTransaction(func(sess *DBSession) error {
existingAlerts, err := GetAlertsByDashboardId2(cmd.DashboardId, sess)
if err != nil {
@ -299,7 +305,7 @@ func GetAlertsByDashboardId2(dashboardId int64, sess *DBSession) ([]*models.Aler
return alerts, nil
}
func SetAlertState(cmd *models.SetAlertStateCommand) error {
func SetAlertState(ctx context.Context, cmd *models.SetAlertStateCommand) error {
return inTransaction(func(sess *DBSession) error {
alert := models.Alert{}
@ -338,7 +344,7 @@ func SetAlertState(cmd *models.SetAlertStateCommand) error {
})
}
func PauseAlert(cmd *models.PauseAlertCommand) error {
func PauseAlert(ctx context.Context, cmd *models.PauseAlertCommand) error {
return inTransaction(func(sess *DBSession) error {
if len(cmd.AlertIds) == 0 {
return fmt.Errorf("command contains no alertids")
@ -372,7 +378,7 @@ func PauseAlert(cmd *models.PauseAlertCommand) error {
})
}
func PauseAllAlerts(cmd *models.PauseAllAlertCommand) error {
func PauseAllAlerts(ctx context.Context, cmd *models.PauseAllAlertCommand) error {
return inTransaction(func(sess *DBSession) error {
var newState string
if cmd.Paused {
@ -390,7 +396,8 @@ func PauseAllAlerts(cmd *models.PauseAllAlertCommand) error {
})
}
func GetAlertStatesForDashboard(query *models.GetAlertStatesForDashboardQuery) error {
func (ss *SQLStore) GetAlertStatesForDashboard(ctx context.Context, query *models.GetAlertStatesForDashboardQuery) error {
return ss.WithDbSession(ctx, func(sess *DBSession) error {
var rawSQL = `SELECT
id,
dashboard_id,
@ -401,7 +408,8 @@ func GetAlertStatesForDashboard(query *models.GetAlertStatesForDashboardQuery) e
WHERE org_id = ? AND dashboard_id = ?`
query.Result = make([]*models.AlertStateInfoDTO, 0)
err := x.SQL(rawSQL, query.OrgId, query.DashboardId).Find(&query.Result)
err := sess.SQL(rawSQL, query.OrgId, query.DashboardId).Find(&query.Result)
return err
})
}

View File

@ -63,7 +63,7 @@ func TestAlertingDataAccess(t *testing.T) {
UserId: 1,
}
err = SaveAlerts(&cmd)
err = SaveAlerts(context.Background(), &cmd)
require.Nil(t, err)
}
@ -72,7 +72,7 @@ func TestAlertingDataAccess(t *testing.T) {
// Get alert so we can use its ID in tests
alertQuery := models.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, PanelId: 1, OrgId: 1, User: &models.SignedInUser{OrgRole: models.ROLE_ADMIN}}
err2 := HandleAlertsQuery(&alertQuery)
err2 := sqlStore.HandleAlertsQuery(context.Background(), &alertQuery)
require.Nil(t, err2)
insertedAlert := alertQuery.Result[0]
@ -83,11 +83,11 @@ func TestAlertingDataAccess(t *testing.T) {
State: models.AlertStateOK,
}
err := SetAlertState(cmd)
err := SetAlertState(context.Background(), cmd)
require.Nil(t, err)
})
alert, _ := getAlertById(t, insertedAlert.Id)
alert, _ := getAlertById(t, insertedAlert.Id, sqlStore)
stateDateBeforePause := alert.NewStateDate
t.Run("can pause all alerts", func(t *testing.T) {
@ -100,18 +100,18 @@ func TestAlertingDataAccess(t *testing.T) {
State: models.AlertStateOK,
}
err = SetAlertState(cmd)
err = SetAlertState(context.Background(), cmd)
require.Error(t, err)
})
t.Run("alert is paused", func(t *testing.T) {
alert, _ = getAlertById(t, insertedAlert.Id)
alert, _ = getAlertById(t, insertedAlert.Id, sqlStore)
currentState := alert.State
require.Equal(t, models.AlertStatePaused, currentState)
})
t.Run("pausing alerts should update their NewStateDate", func(t *testing.T) {
alert, _ = getAlertById(t, insertedAlert.Id)
alert, _ = getAlertById(t, insertedAlert.Id, sqlStore)
stateDateAfterPause := alert.NewStateDate
require.True(t, stateDateBeforePause.Before(stateDateAfterPause))
})
@ -119,7 +119,7 @@ func TestAlertingDataAccess(t *testing.T) {
t.Run("unpausing alerts should update their NewStateDate again", func(t *testing.T) {
err := pauseAllAlerts(t, false)
require.Nil(t, err)
alert, _ = getAlertById(t, insertedAlert.Id)
alert, _ = getAlertById(t, insertedAlert.Id, sqlStore)
stateDateAfterUnpause := alert.NewStateDate
require.True(t, stateDateBeforePause.Before(stateDateAfterUnpause))
})
@ -129,7 +129,7 @@ func TestAlertingDataAccess(t *testing.T) {
t.Run("Can read properties", func(t *testing.T) {
setup(t)
alertQuery := models.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, PanelId: 1, OrgId: 1, User: &models.SignedInUser{OrgRole: models.ROLE_ADMIN}}
err2 := HandleAlertsQuery(&alertQuery)
err2 := sqlStore.HandleAlertsQuery(context.Background(), &alertQuery)
alert := alertQuery.Result[0]
require.Nil(t, err2)
@ -151,7 +151,7 @@ func TestAlertingDataAccess(t *testing.T) {
setup(t)
viewerUser := &models.SignedInUser{OrgRole: models.ROLE_VIEWER, OrgId: 1}
alertQuery := models.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, PanelId: 1, OrgId: 1, User: viewerUser}
err2 := HandleAlertsQuery(&alertQuery)
err2 := sqlStore.HandleAlertsQuery(context.Background(), &alertQuery)
require.Nil(t, err2)
require.Equal(t, 1, len(alertQuery.Result))
@ -169,7 +169,7 @@ func TestAlertingDataAccess(t *testing.T) {
Alerts: modifiedItems,
}
err := SaveAlerts(&modifiedCmd)
err := SaveAlerts(context.Background(), &modifiedCmd)
t.Run("Can save alerts with same dashboard and panel id", func(t *testing.T) {
require.Nil(t, err)
@ -177,7 +177,7 @@ func TestAlertingDataAccess(t *testing.T) {
t.Run("Alerts should be updated", func(t *testing.T) {
query := models.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, OrgId: 1, User: &models.SignedInUser{OrgRole: models.ROLE_ADMIN}}
err2 := HandleAlertsQuery(&query)
err2 := sqlStore.HandleAlertsQuery(context.Background(), &query)
require.Nil(t, err2)
require.Equal(t, 1, len(query.Result))
@ -189,7 +189,7 @@ func TestAlertingDataAccess(t *testing.T) {
})
t.Run("Updates without changes should be ignored", func(t *testing.T) {
err3 := SaveAlerts(&modifiedCmd)
err3 := SaveAlerts(context.Background(), &modifiedCmd)
require.Nil(t, err3)
})
})
@ -221,13 +221,13 @@ func TestAlertingDataAccess(t *testing.T) {
}
cmd.Alerts = multipleItems
err := SaveAlerts(&cmd)
err := SaveAlerts(context.Background(), &cmd)
t.Run("Should save 3 dashboards", func(t *testing.T) {
require.Nil(t, err)
queryForDashboard := models.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, OrgId: 1, User: &models.SignedInUser{OrgRole: models.ROLE_ADMIN}}
err2 := HandleAlertsQuery(&queryForDashboard)
err2 := sqlStore.HandleAlertsQuery(context.Background(), &queryForDashboard)
require.Nil(t, err2)
require.Equal(t, 3, len(queryForDashboard.Result))
@ -237,11 +237,11 @@ func TestAlertingDataAccess(t *testing.T) {
missingOneAlert := multipleItems[:2]
cmd.Alerts = missingOneAlert
err = SaveAlerts(&cmd)
err = SaveAlerts(context.Background(), &cmd)
t.Run("should delete the missing alert", func(t *testing.T) {
query := models.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, OrgId: 1, User: &models.SignedInUser{OrgRole: models.ROLE_ADMIN}}
err2 := HandleAlertsQuery(&query)
err2 := sqlStore.HandleAlertsQuery(context.Background(), &query)
require.Nil(t, err2)
require.Equal(t, 2, len(query.Result))
})
@ -266,7 +266,7 @@ func TestAlertingDataAccess(t *testing.T) {
UserId: 1,
}
err := SaveAlerts(&cmd)
err := SaveAlerts(context.Background(), &cmd)
require.Nil(t, err)
err = DeleteDashboard(context.Background(), &models.DeleteDashboardCommand{
@ -277,7 +277,7 @@ func TestAlertingDataAccess(t *testing.T) {
t.Run("Alerts should be removed", func(t *testing.T) {
query := models.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, OrgId: 1, User: &models.SignedInUser{OrgRole: models.ROLE_ADMIN}}
err2 := HandleAlertsQuery(&query)
err2 := sqlStore.HandleAlertsQuery(context.Background(), &query)
require.Nil(t, err2)
require.Equal(t, 0, len(query.Result))
@ -301,7 +301,7 @@ func TestPausingAlerts(t *testing.T) {
// Get alert so we can use its ID in tests
alertQuery := models.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, PanelId: 1, OrgId: 1, User: &models.SignedInUser{OrgRole: models.ROLE_ADMIN}}
err2 := HandleAlertsQuery(&alertQuery)
err2 := sqlStore.HandleAlertsQuery(context.Background(), &alertQuery)
require.Nil(t, err2)
insertedAlert := alertQuery.Result[0]
@ -311,7 +311,7 @@ func TestPausingAlerts(t *testing.T) {
require.Nil(t, err)
t.Run("the NewStateDate should be updated", func(t *testing.T) {
alert, err := getAlertById(t, insertedAlert.Id)
alert, err := getAlertById(t, insertedAlert.Id, sqlStore)
require.Nil(t, err)
stateDateAfterPause = alert.NewStateDate
@ -324,7 +324,7 @@ func TestPausingAlerts(t *testing.T) {
require.Nil(t, err)
t.Run("the NewStateDate should be updated again", func(t *testing.T) {
alert, err := getAlertById(t, insertedAlert.Id)
alert, err := getAlertById(t, insertedAlert.Id, sqlStore)
require.Nil(t, err)
stateDateAfterUnpause := alert.NewStateDate
@ -339,7 +339,7 @@ func pauseAlert(t *testing.T, orgId int64, alertId int64, pauseState bool) (int6
AlertIds: []int64{alertId},
Paused: pauseState,
}
err := PauseAlert(cmd)
err := PauseAlert(context.Background(), cmd)
require.Nil(t, err)
return cmd.ResultCount, err
}
@ -363,15 +363,15 @@ func insertTestAlert(title string, message string, orgId int64, dashId int64, se
UserId: 1,
}
err := SaveAlerts(&cmd)
err := SaveAlerts(context.Background(), &cmd)
return cmd.Alerts[0], err
}
func getAlertById(t *testing.T, id int64) (*models.Alert, error) {
func getAlertById(t *testing.T, id int64, ss *SQLStore) (*models.Alert, error) {
q := &models.GetAlertByIdQuery{
Id: id,
}
err := GetAlertById(q)
err := ss.GetAlertById(context.Background(), q)
require.Nil(t, err)
return q.Result, err
}
@ -380,7 +380,7 @@ func pauseAllAlerts(t *testing.T, pauseState bool) error {
cmd := &models.PauseAllAlertCommand{
Paused: pauseState,
}
err := PauseAllAlerts(cmd)
err := PauseAllAlerts(context.Background(), cmd)
require.Nil(t, err)
return err
}

View File

@ -117,6 +117,7 @@ func newSQLStore(cfg *setting.Cfg, cacheService *localcache.CacheService, bus bu
ss.addQuotaQueryAndCommandHandlers()
ss.addOrgUsersQueryAndCommandHandlers()
ss.addStarQueryAndCommandHandlers()
ss.addAlertQueryAndCommandHandlers()
// if err := ss.Reset(); err != nil {
// return nil, err