Alerting: Add context.Context to RuleStore (#45004)

Alerting: Add context.Context to RuleStore
This commit is contained in:
George Robinson 2022-02-08 08:52:03 +00:00 committed by GitHub
parent 31ba5bfea0
commit a9399ab3cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 108 additions and 96 deletions

View File

@ -101,7 +101,7 @@ func (srv PrometheusSrv) RouteGetRuleStatuses(c *models.ReqContext) response.Res
DashboardUID: dashboardUID,
PanelID: panelID,
}
if err := srv.store.GetOrgRuleGroups(&ruleGroupQuery); err != nil {
if err := srv.store.GetOrgRuleGroups(c.Req.Context(), &ruleGroupQuery); err != nil {
ruleResponse.DiscoveryBase.Status = "error"
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("failure getting rule groups: %s", err.Error())
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrServer
@ -113,7 +113,7 @@ func (srv PrometheusSrv) RouteGetRuleStatuses(c *models.ReqContext) response.Res
DashboardUID: dashboardUID,
PanelID: panelID,
}
if err := srv.store.GetOrgAlertRules(&alertRuleQuery); err != nil {
if err := srv.store.GetOrgAlertRules(c.Req.Context(), &alertRuleQuery); err != nil {
ruleResponse.DiscoveryBase.Status = "error"
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("failure getting rules: %s", err.Error())
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrServer

View File

@ -38,7 +38,7 @@ func (srv RulerSrv) RouteDeleteNamespaceRulesConfig(c *models.ReqContext) respon
return toNamespaceErrorResponse(err)
}
uids, err := srv.store.DeleteNamespaceAlertRules(c.SignedInUser.OrgId, namespace.Uid)
uids, err := srv.store.DeleteNamespaceAlertRules(c.Req.Context(), c.SignedInUser.OrgId, namespace.Uid)
if err != nil {
return ErrResp(http.StatusInternalServerError, err, "failed to delete namespace alert rules")
}
@ -60,7 +60,7 @@ func (srv RulerSrv) RouteDeleteRuleGroupConfig(c *models.ReqContext) response.Re
return toNamespaceErrorResponse(err)
}
ruleGroup := web.Params(c.Req)[":Groupname"]
uids, err := srv.store.DeleteRuleGroupAlertRules(c.SignedInUser.OrgId, namespace.Uid, ruleGroup)
uids, err := srv.store.DeleteRuleGroupAlertRules(c.Req.Context(), c.SignedInUser.OrgId, namespace.Uid, ruleGroup)
if err != nil {
if errors.Is(err, ngmodels.ErrRuleGroupNamespaceNotFound) {
@ -90,7 +90,7 @@ func (srv RulerSrv) RouteGetNamespaceRulesConfig(c *models.ReqContext) response.
OrgID: c.SignedInUser.OrgId,
NamespaceUID: namespace.Uid,
}
if err := srv.store.GetNamespaceAlertRules(&q); err != nil {
if err := srv.store.GetNamespaceAlertRules(c.Req.Context(), &q); err != nil {
return ErrResp(http.StatusInternalServerError, err, "failed to update rule group")
}
@ -133,7 +133,7 @@ func (srv RulerSrv) RouteGetRulegGroupConfig(c *models.ReqContext) response.Resp
NamespaceUID: namespace.Uid,
RuleGroup: ruleGroup,
}
if err := srv.store.GetRuleGroupAlertRules(&q); err != nil {
if err := srv.store.GetRuleGroupAlertRules(c.Req.Context(), &q); err != nil {
return ErrResp(http.StatusInternalServerError, err, "failed to get group alert rules")
}
@ -187,7 +187,7 @@ func (srv RulerSrv) RouteGetRulesConfig(c *models.ReqContext) response.Response
PanelID: panelID,
}
if err := srv.store.GetOrgAlertRules(&q); err != nil {
if err := srv.store.GetOrgAlertRules(c.Req.Context(), &q); err != nil {
return ErrResp(http.StatusInternalServerError, err, "failed to get alert rules")
}
@ -282,7 +282,7 @@ func (srv RulerSrv) RoutePostNameRulesConfig(c *models.ReqContext, ruleGroupConf
}
}
if err := srv.store.UpdateRuleGroup(store.UpdateRuleGroupCmd{
if err := srv.store.UpdateRuleGroup(c.Req.Context(), store.UpdateRuleGroupCmd{
OrgID: c.SignedInUser.OrgId,
NamespaceUID: namespace.Uid,
RuleGroupConfig: ruleGroupConfig,

View File

@ -169,7 +169,7 @@ func (ng *AlertNG) init() error {
// Run starts the scheduler and Alertmanager.
func (ng *AlertNG) Run(ctx context.Context) error {
ng.Log.Debug("ngalert starting")
ng.stateManager.Warm()
ng.stateManager.Warm(ctx)
children, subCtx := errgroup.WithContext(ctx)

View File

@ -1,12 +1,13 @@
package schedule
import (
"context"
"time"
"github.com/grafana/grafana/pkg/services/ngalert/models"
)
func (sch *schedule) getAlertRules(disabledOrgs []int64) []*models.AlertRule {
func (sch *schedule) getAlertRules(ctx context.Context, disabledOrgs []int64) []*models.AlertRule {
start := time.Now()
defer func() {
sch.metrics.GetAlertRulesDuration.Observe(time.Since(start).Seconds())
@ -15,7 +16,7 @@ func (sch *schedule) getAlertRules(disabledOrgs []int64) []*models.AlertRule {
q := models.ListAlertRulesQuery{
ExcludeOrgs: disabledOrgs,
}
err := sch.ruleStore.GetAlertRulesForScheduling(&q)
err := sch.ruleStore.GetAlertRulesForScheduling(ctx, &q)
if err != nil {
sch.log.Error("failed to fetch alert definitions", "err", err)
return nil

View File

@ -377,7 +377,7 @@ func (sch *schedule) schedulePeriodic(ctx context.Context) error {
disabledOrgs = append(disabledOrgs, disabledOrg)
}
alertRules := sch.getAlertRules(disabledOrgs)
alertRules := sch.getAlertRules(ctx, disabledOrgs)
sch.log.Debug("alert rules fetched", "count", len(alertRules), "disabled_orgs", disabledOrgs)
// registeredDefinitions is a map used for finding deleted alert rules
@ -528,9 +528,9 @@ func (sch *schedule) ruleRoutine(grafanaCtx context.Context, key models.AlertRul
notify(expiredAlerts, logger)
}
updateRule := func(oldRule *models.AlertRule) (*models.AlertRule, error) {
updateRule := func(ctx context.Context, oldRule *models.AlertRule) (*models.AlertRule, error) {
q := models.GetAlertRuleByUIDQuery{OrgID: key.OrgID, UID: key.UID}
err := sch.ruleStore.GetAlertRuleByUID(&q)
err := sch.ruleStore.GetAlertRuleByUID(ctx, &q)
if err != nil {
logger.Error("failed to fetch alert rule", "err", err)
return nil, err
@ -591,7 +591,7 @@ func (sch *schedule) ruleRoutine(grafanaCtx context.Context, key models.AlertRul
case <-updateCh:
logger.Info("fetching new version of the rule")
err := retryIfError(func(attempt int64) error {
newRule, err := updateRule(currentRule)
newRule, err := updateRule(grafanaCtx, currentRule)
if err != nil {
return err
}
@ -622,7 +622,7 @@ func (sch *schedule) ruleRoutine(grafanaCtx context.Context, key models.AlertRul
err := retryIfError(func(attempt int64) error {
// fetch latest alert rule version
if currentRule == nil || currentRule.Version < ctx.version {
newRule, err := updateRule(currentRule)
newRule, err := updateRule(grafanaCtx, currentRule)
if err != nil {
return err
}

View File

@ -36,10 +36,11 @@ type evalAppliedInfo struct {
func TestWarmStateCache(t *testing.T) {
evaluationTime, err := time.Parse("2006-01-02", "2021-03-25")
require.NoError(t, err)
ctx := context.Background()
ng, dbstore := tests.SetupTestEnv(t, 1)
const mainOrgID int64 = 1
rule := tests.CreateTestAlertRule(t, dbstore, 600, mainOrgID)
rule := tests.CreateTestAlertRule(t, ctx, dbstore, 600, mainOrgID)
expectedEntries := []*state.State{
{
@ -105,7 +106,7 @@ func TestWarmStateCache(t *testing.T) {
AdminConfigPollInterval: 10 * time.Minute, // do not poll in unit tests.
}
st := state.NewManager(schedCfg.Logger, testMetrics.GetStateMetrics(), nil, dbstore, dbstore, ng.SQLStore)
st.Warm()
st.Warm(ctx)
t.Run("instance cache has expected entries", func(t *testing.T) {
for _, entry := range expectedEntries {
@ -121,13 +122,14 @@ func TestWarmStateCache(t *testing.T) {
}
func TestAlertingTicker(t *testing.T) {
ctx := context.Background()
ng, dbstore := tests.SetupTestEnv(t, 1)
alerts := make([]*models.AlertRule, 0)
const mainOrgID int64 = 1
// create alert rule under main org with one second interval
alerts = append(alerts, tests.CreateTestAlertRule(t, dbstore, 1, mainOrgID))
alerts = append(alerts, tests.CreateTestAlertRule(t, ctx, dbstore, 1, mainOrgID))
const disabledOrgID int64 = 3
@ -162,8 +164,6 @@ func TestAlertingTicker(t *testing.T) {
}
sched := schedule.NewScheduler(schedCfg, nil, appUrl, st)
ctx := context.Background()
go func() {
err := sched.Run(ctx)
require.NoError(t, err)
@ -178,7 +178,7 @@ func TestAlertingTicker(t *testing.T) {
// add alert rule under main org with three seconds interval
var threeSecInterval int64 = 3
alerts = append(alerts, tests.CreateTestAlertRule(t, dbstore, threeSecInterval, mainOrgID))
alerts = append(alerts, tests.CreateTestAlertRule(t, ctx, dbstore, threeSecInterval, mainOrgID))
t.Logf("alert rule: %v added with interval: %d", alerts[1].GetKey(), threeSecInterval)
expectedAlertRulesEvaluated = []models.AlertRuleKey{alerts[0].GetKey()}
@ -200,7 +200,7 @@ func TestAlertingTicker(t *testing.T) {
})
key := alerts[0].GetKey()
err := dbstore.DeleteAlertRuleByUID(alerts[0].OrgID, alerts[0].UID)
err := dbstore.DeleteAlertRuleByUID(ctx, alerts[0].OrgID, alerts[0].UID)
require.NoError(t, err)
t.Logf("alert rule: %v deleted", key)
@ -221,7 +221,7 @@ func TestAlertingTicker(t *testing.T) {
})
// create alert rule with one second interval
alerts = append(alerts, tests.CreateTestAlertRule(t, dbstore, 1, mainOrgID))
alerts = append(alerts, tests.CreateTestAlertRule(t, ctx, dbstore, 1, mainOrgID))
expectedAlertRulesEvaluated = []models.AlertRuleKey{alerts[2].GetKey()}
t.Run(fmt.Sprintf("on 7th tick alert rules: %s should be evaluated", concatenate(expectedAlertRulesEvaluated)), func(t *testing.T) {
@ -230,7 +230,7 @@ func TestAlertingTicker(t *testing.T) {
})
// create alert rule with one second interval under disabled org
alerts = append(alerts, tests.CreateTestAlertRule(t, dbstore, 1, disabledOrgID))
alerts = append(alerts, tests.CreateTestAlertRule(t, ctx, dbstore, 1, disabledOrgID))
expectedAlertRulesEvaluated = []models.AlertRuleKey{alerts[2].GetKey()}
t.Run(fmt.Sprintf("on 8th tick alert rules: %s should be evaluated", concatenate(expectedAlertRulesEvaluated)), func(t *testing.T) {

View File

@ -482,6 +482,7 @@ func TestSchedule_ruleRoutine(t *testing.T) {
evalChan := make(chan *evalContext)
evalAppliedChan := make(chan time.Time)
ctx := context.Background()
sch, ruleStore, _, _, _ := createSchedule(evalAppliedChan)
rule := CreateTestAlertRule(t, ruleStore, 10, rand.Int63(), randomNormalState())
@ -504,7 +505,7 @@ func TestSchedule_ruleRoutine(t *testing.T) {
// Now update the rule
newRule := *rule
newRule.Version++
ruleStore.putRule(&newRule)
ruleStore.putRule(ctx, &newRule)
// and call with new version
expectedTime = expectedTime.Add(time.Duration(rand.Intn(10)) * time.Second)
@ -681,6 +682,7 @@ func TestSchedule_ruleRoutine(t *testing.T) {
evalAppliedChan := make(chan time.Time)
updateChan := make(chan struct{})
ctx := context.Background()
sch, ruleStore, _, _, _ := createSchedule(evalAppliedChan)
sch.senders[orgID] = s
@ -728,7 +730,7 @@ func TestSchedule_ruleRoutine(t *testing.T) {
wg.Wait()
newRule := rule
newRule.Version++
ruleStore.putRule(&newRule)
ruleStore.putRule(ctx, &newRule)
wg.Add(1)
updateChan <- struct{}{}
wg.Wait()
@ -1041,6 +1043,8 @@ func setupScheduler(t *testing.T, rs store.RuleStore, is store.InstanceStore, ac
// createTestAlertRule creates a dummy alert definition to be used by the tests.
func CreateTestAlertRule(t *testing.T, dbstore *fakeRuleStore, intervalSeconds int64, orgID int64, evalResult eval.State) *models.AlertRule {
ctx := context.Background()
t.Helper()
records := make([]interface{}, 0, len(dbstore.recordedOps))
copy(records, dbstore.recordedOps)
@ -1080,7 +1084,7 @@ func CreateTestAlertRule(t *testing.T, dbstore *fakeRuleStore, intervalSeconds i
require.Fail(t, "Alert rule with desired evaluation result NoData is not supported yet")
}
err := dbstore.UpdateRuleGroup(store.UpdateRuleGroupCmd{
err := dbstore.UpdateRuleGroup(ctx, store.UpdateRuleGroupCmd{
OrgID: orgID,
NamespaceUID: "namespace",
RuleGroupConfig: apimodels.PostableRuleGroupConfig{
@ -1118,7 +1122,7 @@ func CreateTestAlertRule(t *testing.T, dbstore *fakeRuleStore, intervalSeconds i
NamespaceUID: "namespace",
RuleGroup: ruleGroup,
}
err = dbstore.GetRuleGroupAlertRules(&q)
err = dbstore.GetRuleGroupAlertRules(ctx, &q)
require.NoError(t, err)
require.NotEmpty(t, q.Result)

View File

@ -70,7 +70,7 @@ type fakeRuleStore struct {
}
// putRule puts the rule in the rules map. If there are existing rule in the same namespace, they will be overwritten
func (f *fakeRuleStore) putRule(r *models.AlertRule) {
func (f *fakeRuleStore) putRule(_ context.Context, r *models.AlertRule) {
f.mtx.Lock()
defer f.mtx.Unlock()
f.rules[r.OrgID][r.RuleGroup][r.NamespaceUID] = []*models.AlertRule{
@ -94,15 +94,17 @@ func (f *fakeRuleStore) getRecordedCommands(predicate func(cmd interface{}) (int
return result
}
func (f *fakeRuleStore) DeleteAlertRuleByUID(_ int64, _ string) error { return nil }
func (f *fakeRuleStore) DeleteNamespaceAlertRules(_ int64, _ string) ([]string, error) {
func (f *fakeRuleStore) DeleteAlertRuleByUID(_ context.Context, _ int64, _ string) error { return nil }
func (f *fakeRuleStore) DeleteNamespaceAlertRules(_ context.Context, _ int64, _ string) ([]string, error) {
return []string{}, nil
}
func (f *fakeRuleStore) DeleteRuleGroupAlertRules(_ int64, _ string, _ string) ([]string, error) {
func (f *fakeRuleStore) DeleteRuleGroupAlertRules(_ context.Context, _ int64, _ string, _ string) ([]string, error) {
return []string{}, nil
}
func (f *fakeRuleStore) DeleteAlertInstancesByRuleUID(_ int64, _ string) error { return nil }
func (f *fakeRuleStore) GetAlertRuleByUID(q *models.GetAlertRuleByUIDQuery) error {
func (f *fakeRuleStore) DeleteAlertInstancesByRuleUID(_ context.Context, _ int64, _ string) error {
return nil
}
func (f *fakeRuleStore) GetAlertRuleByUID(_ context.Context, q *models.GetAlertRuleByUIDQuery) error {
f.mtx.Lock()
defer f.mtx.Unlock()
f.recordedOps = append(f.recordedOps, *q)
@ -129,7 +131,7 @@ func (f *fakeRuleStore) GetAlertRuleByUID(q *models.GetAlertRuleByUIDQuery) erro
}
// For now, we're not implementing namespace filtering.
func (f *fakeRuleStore) GetAlertRulesForScheduling(q *models.ListAlertRulesQuery) error {
func (f *fakeRuleStore) GetAlertRulesForScheduling(_ context.Context, q *models.ListAlertRulesQuery) error {
f.mtx.Lock()
defer f.mtx.Unlock()
f.recordedOps = append(f.recordedOps, *q)
@ -146,19 +148,19 @@ func (f *fakeRuleStore) GetAlertRulesForScheduling(q *models.ListAlertRulesQuery
return nil
}
func (f *fakeRuleStore) GetOrgAlertRules(q *models.ListAlertRulesQuery) error {
func (f *fakeRuleStore) GetOrgAlertRules(_ context.Context, q *models.ListAlertRulesQuery) error {
f.mtx.Lock()
defer f.mtx.Unlock()
f.recordedOps = append(f.recordedOps, *q)
return nil
}
func (f *fakeRuleStore) GetNamespaceAlertRules(q *models.ListNamespaceAlertRulesQuery) error {
func (f *fakeRuleStore) GetNamespaceAlertRules(_ context.Context, q *models.ListNamespaceAlertRulesQuery) error {
f.mtx.Lock()
defer f.mtx.Unlock()
f.recordedOps = append(f.recordedOps, *q)
return nil
}
func (f *fakeRuleStore) GetRuleGroupAlertRules(q *models.ListRuleGroupAlertRulesQuery) error {
func (f *fakeRuleStore) GetRuleGroupAlertRules(_ context.Context, q *models.ListRuleGroupAlertRulesQuery) error {
f.mtx.Lock()
defer f.mtx.Unlock()
f.recordedOps = append(f.recordedOps, *q)
@ -196,7 +198,7 @@ func (f *fakeRuleStore) GetNamespaces(_ context.Context, _ int64, _ *models2.Sig
func (f *fakeRuleStore) GetNamespaceByTitle(_ context.Context, _ string, _ int64, _ *models2.SignedInUser, _ bool) (*models2.Folder, error) {
return nil, nil
}
func (f *fakeRuleStore) GetOrgRuleGroups(q *models.ListOrgRuleGroupsQuery) error {
func (f *fakeRuleStore) GetOrgRuleGroups(_ context.Context, q *models.ListOrgRuleGroupsQuery) error {
f.mtx.Lock()
defer f.mtx.Unlock()
f.recordedOps = append(f.recordedOps, *q)
@ -206,7 +208,7 @@ func (f *fakeRuleStore) GetOrgRuleGroups(q *models.ListOrgRuleGroupsQuery) error
return nil
}
func (f *fakeRuleStore) UpsertAlertRules(q []store.UpsertRule) error {
func (f *fakeRuleStore) UpsertAlertRules(_ context.Context, q []store.UpsertRule) error {
f.mtx.Lock()
defer f.mtx.Unlock()
f.recordedOps = append(f.recordedOps, q)
@ -215,7 +217,7 @@ func (f *fakeRuleStore) UpsertAlertRules(q []store.UpsertRule) error {
}
return nil
}
func (f *fakeRuleStore) UpdateRuleGroup(cmd store.UpdateRuleGroupCmd) error {
func (f *fakeRuleStore) UpdateRuleGroup(_ context.Context, cmd store.UpdateRuleGroupCmd) error {
f.mtx.Lock()
defer f.mtx.Unlock()
f.recordedOps = append(f.recordedOps, cmd)

View File

@ -54,7 +54,7 @@ func (st *Manager) Close() {
st.quit <- struct{}{}
}
func (st *Manager) Warm() {
func (st *Manager) Warm(ctx context.Context) {
st.log.Info("warming cache for startup")
st.ResetCache()
@ -69,7 +69,7 @@ func (st *Manager) Warm() {
ruleCmd := ngModels.ListAlertRulesQuery{
OrgID: orgId,
}
if err := st.ruleStore.GetOrgAlertRules(&ruleCmd); err != nil {
if err := st.ruleStore.GetOrgAlertRules(ctx, &ruleCmd); err != nil {
st.log.Error("unable to fetch previous state", "msg", err.Error())
}

View File

@ -1513,10 +1513,11 @@ func TestStaleResultsHandler(t *testing.T) {
t.Fatalf("error parsing date format: %s", err.Error())
}
ctx := context.Background()
_, dbstore := tests.SetupTestEnv(t, 1)
const mainOrgID int64 = 1
rule := tests.CreateTestAlertRule(t, dbstore, 600, mainOrgID)
rule := tests.CreateTestAlertRule(t, ctx, dbstore, 600, mainOrgID)
saveCmd1 := &models.SaveAlertInstanceCommand{
RuleOrgID: rule.OrgID,
@ -1589,9 +1590,10 @@ func TestStaleResultsHandler(t *testing.T) {
}
for _, tc := range testCases {
ctx := context.Background()
sqlStore := mockstore.NewSQLStoreMock()
st := state.NewManager(log.New("test_stale_results_handler"), testMetrics.GetStateMetrics(), nil, dbstore, dbstore, sqlStore)
st.Warm()
st.Warm(ctx)
existingStatesForRule := st.GetStatesForRuleUID(rule.OrgID, rule.UID)
// We have loaded the expected number of entries from the db

View File

@ -39,20 +39,20 @@ type UpsertRule struct {
// Store is the interface for persisting alert rules and instances
type RuleStore interface {
DeleteAlertRuleByUID(orgID int64, ruleUID string) error
DeleteNamespaceAlertRules(orgID int64, namespaceUID string) ([]string, error)
DeleteRuleGroupAlertRules(orgID int64, namespaceUID string, ruleGroup string) ([]string, error)
DeleteAlertInstancesByRuleUID(orgID int64, ruleUID string) error
GetAlertRuleByUID(*ngmodels.GetAlertRuleByUIDQuery) error
GetAlertRulesForScheduling(query *ngmodels.ListAlertRulesQuery) error
GetOrgAlertRules(query *ngmodels.ListAlertRulesQuery) error
GetNamespaceAlertRules(query *ngmodels.ListNamespaceAlertRulesQuery) error
GetRuleGroupAlertRules(query *ngmodels.ListRuleGroupAlertRulesQuery) error
DeleteAlertRuleByUID(ctx context.Context, orgID int64, ruleUID string) error
DeleteNamespaceAlertRules(ctx context.Context, orgID int64, namespaceUID string) ([]string, error)
DeleteRuleGroupAlertRules(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string) ([]string, error)
DeleteAlertInstancesByRuleUID(ctx context.Context, orgID int64, ruleUID string) error
GetAlertRuleByUID(ctx context.Context, query *ngmodels.GetAlertRuleByUIDQuery) error
GetAlertRulesForScheduling(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error
GetOrgAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error
GetNamespaceAlertRules(ctx context.Context, query *ngmodels.ListNamespaceAlertRulesQuery) error
GetRuleGroupAlertRules(ctx context.Context, query *ngmodels.ListRuleGroupAlertRulesQuery) error
GetNamespaces(context.Context, int64, *models.SignedInUser) (map[string]*models.Folder, error)
GetNamespaceByTitle(context.Context, string, int64, *models.SignedInUser, bool) (*models.Folder, error)
GetOrgRuleGroups(query *ngmodels.ListOrgRuleGroupsQuery) error
UpsertAlertRules([]UpsertRule) error
UpdateRuleGroup(UpdateRuleGroupCmd) error
GetOrgRuleGroups(ctx context.Context, query *ngmodels.ListOrgRuleGroupsQuery) error
UpsertAlertRules(ctx context.Context, rule []UpsertRule) error
UpdateRuleGroup(ctx context.Context, cmd UpdateRuleGroupCmd) error
}
func getAlertRuleByUID(sess *sqlstore.DBSession, alertRuleUID string, orgID int64) (*ngmodels.AlertRule, error) {
@ -69,8 +69,8 @@ func getAlertRuleByUID(sess *sqlstore.DBSession, alertRuleUID string, orgID int6
}
// DeleteAlertRuleByUID is a handler for deleting an alert rule.
func (st DBstore) DeleteAlertRuleByUID(orgID int64, ruleUID string) error {
return st.SQLStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
func (st DBstore) DeleteAlertRuleByUID(ctx context.Context, orgID int64, ruleUID string) error {
return st.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
_, err := sess.Exec("DELETE FROM alert_rule WHERE org_id = ? AND uid = ?", orgID, ruleUID)
if err != nil {
return err
@ -91,10 +91,10 @@ func (st DBstore) DeleteAlertRuleByUID(orgID int64, ruleUID string) error {
}
// DeleteNamespaceAlertRules is a handler for deleting namespace alert rules. A list of deleted rule UIDs are returned.
func (st DBstore) DeleteNamespaceAlertRules(orgID int64, namespaceUID string) ([]string, error) {
func (st DBstore) DeleteNamespaceAlertRules(ctx context.Context, orgID int64, namespaceUID string) ([]string, error) {
ruleUIDs := []string{}
err := st.SQLStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
err := st.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
if err := sess.SQL("SELECT uid FROM alert_rule WHERE org_id = ? and namespace_uid = ?", orgID, namespaceUID).Find(&ruleUIDs); err != nil {
return err
}
@ -123,10 +123,10 @@ func (st DBstore) DeleteNamespaceAlertRules(orgID int64, namespaceUID string) ([
}
// DeleteRuleGroupAlertRules is a handler for deleting rule group alert rules. A list of deleted rule UIDs are returned.
func (st DBstore) DeleteRuleGroupAlertRules(orgID int64, namespaceUID string, ruleGroup string) ([]string, error) {
func (st DBstore) DeleteRuleGroupAlertRules(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string) ([]string, error) {
ruleUIDs := []string{}
err := st.SQLStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
err := st.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
if err := sess.SQL("SELECT uid FROM alert_rule WHERE org_id = ? and namespace_uid = ? and rule_group = ?",
orgID, namespaceUID, ruleGroup).Find(&ruleUIDs); err != nil {
return err
@ -161,8 +161,8 @@ func (st DBstore) DeleteRuleGroupAlertRules(orgID int64, namespaceUID string, ru
}
// DeleteAlertInstanceByRuleUID is a handler for deleting alert instances by alert rule UID when a rule has been updated
func (st DBstore) DeleteAlertInstancesByRuleUID(orgID int64, ruleUID string) error {
return st.SQLStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
func (st DBstore) DeleteAlertInstancesByRuleUID(ctx context.Context, orgID int64, ruleUID string) error {
return st.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
_, err := sess.Exec("DELETE FROM alert_instance WHERE rule_org_id = ? AND rule_uid = ?", orgID, ruleUID)
if err != nil {
return err
@ -173,8 +173,8 @@ func (st DBstore) DeleteAlertInstancesByRuleUID(orgID int64, ruleUID string) err
// GetAlertRuleByUID is a handler for retrieving an alert rule from that database by its UID and organisation ID.
// It returns ngmodels.ErrAlertRuleNotFound if no alert rule is found for the provided ID.
func (st DBstore) GetAlertRuleByUID(query *ngmodels.GetAlertRuleByUIDQuery) error {
return st.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
func (st DBstore) GetAlertRuleByUID(ctx context.Context, query *ngmodels.GetAlertRuleByUIDQuery) error {
return st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
alertRule, err := getAlertRuleByUID(sess, query.UID, query.OrgID)
if err != nil {
return err
@ -185,8 +185,8 @@ func (st DBstore) GetAlertRuleByUID(query *ngmodels.GetAlertRuleByUIDQuery) erro
}
// UpsertAlertRules is a handler for creating/updating alert rules.
func (st DBstore) UpsertAlertRules(rules []UpsertRule) error {
return st.SQLStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
func (st DBstore) UpsertAlertRules(ctx context.Context, rules []UpsertRule) error {
return st.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
newRules := make([]ngmodels.AlertRule, 0, len(rules))
ruleVersions := make([]ngmodels.AlertRuleVersion, 0, len(rules))
for _, r := range rules {
@ -318,8 +318,8 @@ func (st DBstore) UpsertAlertRules(rules []UpsertRule) error {
}
// GetOrgAlertRules is a handler for retrieving alert rules of specific organisation.
func (st DBstore) GetOrgAlertRules(query *ngmodels.ListAlertRulesQuery) error {
return st.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
func (st DBstore) GetOrgAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error {
return st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
alertRules := make([]*ngmodels.AlertRule, 0)
q := "SELECT * FROM alert_rule WHERE org_id = ?"
params := []interface{}{query.OrgID}
@ -354,8 +354,8 @@ func (st DBstore) GetOrgAlertRules(query *ngmodels.ListAlertRulesQuery) error {
}
// GetNamespaceAlertRules is a handler for retrieving namespace alert rules of specific organisation.
func (st DBstore) GetNamespaceAlertRules(query *ngmodels.ListNamespaceAlertRulesQuery) error {
return st.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
func (st DBstore) GetNamespaceAlertRules(ctx context.Context, query *ngmodels.ListNamespaceAlertRulesQuery) error {
return st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
alertRules := make([]*ngmodels.AlertRule, 0)
// TODO rewrite using group by namespace_uid, rule_group
q := "SELECT * FROM alert_rule WHERE org_id = ? and namespace_uid = ?"
@ -369,8 +369,8 @@ func (st DBstore) GetNamespaceAlertRules(query *ngmodels.ListNamespaceAlertRules
}
// GetRuleGroupAlertRules is a handler for retrieving rule group alert rules of specific organisation.
func (st DBstore) GetRuleGroupAlertRules(query *ngmodels.ListRuleGroupAlertRulesQuery) error {
return st.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
func (st DBstore) GetRuleGroupAlertRules(ctx context.Context, query *ngmodels.ListRuleGroupAlertRulesQuery) error {
return st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
q := "SELECT * FROM alert_rule WHERE org_id = ? and namespace_uid = ? and rule_group = ?"
args := []interface{}{query.OrgID, query.NamespaceUID, query.RuleGroup}
@ -440,8 +440,8 @@ func (st DBstore) GetNamespaceByTitle(ctx context.Context, namespace string, org
// GetAlertRulesForScheduling returns alert rule info (identifier, interval, version state)
// that is useful for it's scheduling.
func (st DBstore) GetAlertRulesForScheduling(query *ngmodels.ListAlertRulesQuery) error {
return st.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
func (st DBstore) GetAlertRulesForScheduling(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error {
return st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
alerts := make([]*ngmodels.AlertRule, 0)
q := "SELECT uid, org_id, interval_seconds, version FROM alert_rule"
if len(query.ExcludeOrgs) > 0 {
@ -511,15 +511,15 @@ func (st DBstore) validateAlertRule(alertRule ngmodels.AlertRule) error {
}
// UpdateRuleGroup creates new rules and updates and/or deletes existing rules
func (st DBstore) UpdateRuleGroup(cmd UpdateRuleGroupCmd) error {
return st.SQLStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
func (st DBstore) UpdateRuleGroup(ctx context.Context, cmd UpdateRuleGroupCmd) error {
return st.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
ruleGroup := cmd.RuleGroupConfig.Name
q := &ngmodels.ListRuleGroupAlertRulesQuery{
OrgID: cmd.OrgID,
NamespaceUID: cmd.NamespaceUID,
RuleGroup: ruleGroup,
}
if err := st.GetRuleGroupAlertRules(q); err != nil {
if err := st.GetRuleGroupAlertRules(ctx, q); err != nil {
return err
}
existingGroupRules := q.Result
@ -578,7 +578,7 @@ func (st DBstore) UpdateRuleGroup(cmd UpdateRuleGroupCmd) error {
upsertRules = append(upsertRules, upsertRule)
}
if err := st.UpsertAlertRules(upsertRules); err != nil {
if err := st.UpsertAlertRules(ctx, upsertRules); err != nil {
if st.SQLStore.Dialect.IsUniqueConstraintViolation(err) {
return ngmodels.ErrAlertRuleUniqueConstraintViolation
}
@ -588,7 +588,7 @@ func (st DBstore) UpdateRuleGroup(cmd UpdateRuleGroupCmd) error {
// delete instances for rules that will not be removed
for _, rule := range existingGroupRules {
if _, ok := existingGroupRulesUIDs[rule.UID]; !ok {
if err := st.DeleteAlertInstancesByRuleUID(cmd.OrgID, rule.UID); err != nil {
if err := st.DeleteAlertInstancesByRuleUID(ctx, cmd.OrgID, rule.UID); err != nil {
return err
}
}
@ -596,7 +596,7 @@ func (st DBstore) UpdateRuleGroup(cmd UpdateRuleGroupCmd) error {
// delete the remaining rules
for ruleUID := range existingGroupRulesUIDs {
if err := st.DeleteAlertRuleByUID(cmd.OrgID, ruleUID); err != nil {
if err := st.DeleteAlertRuleByUID(ctx, cmd.OrgID, ruleUID); err != nil {
return err
}
}
@ -604,8 +604,8 @@ func (st DBstore) UpdateRuleGroup(cmd UpdateRuleGroupCmd) error {
})
}
func (st DBstore) GetOrgRuleGroups(query *ngmodels.ListOrgRuleGroupsQuery) error {
return st.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
func (st DBstore) GetOrgRuleGroups(ctx context.Context, query *ngmodels.ListOrgRuleGroupsQuery) error {
return st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
var ruleGroups [][]string
q := `
SELECT DISTINCT

View File

@ -4,6 +4,7 @@
package store_test
import (
"context"
"testing"
"time"
@ -26,20 +27,21 @@ func mockTimeNow() {
}
func TestAlertInstanceOperations(t *testing.T) {
ctx := context.Background()
_, dbstore := tests.SetupTestEnv(t, baseIntervalSeconds)
const mainOrgID int64 = 1
alertRule1 := tests.CreateTestAlertRule(t, dbstore, 60, mainOrgID)
alertRule1 := tests.CreateTestAlertRule(t, ctx, dbstore, 60, mainOrgID)
orgID := alertRule1.OrgID
alertRule2 := tests.CreateTestAlertRule(t, dbstore, 60, mainOrgID)
alertRule2 := tests.CreateTestAlertRule(t, ctx, dbstore, 60, mainOrgID)
require.Equal(t, orgID, alertRule2.OrgID)
alertRule3 := tests.CreateTestAlertRule(t, dbstore, 60, mainOrgID)
alertRule3 := tests.CreateTestAlertRule(t, ctx, dbstore, 60, mainOrgID)
require.Equal(t, orgID, alertRule3.OrgID)
alertRule4 := tests.CreateTestAlertRule(t, dbstore, 60, mainOrgID)
alertRule4 := tests.CreateTestAlertRule(t, ctx, dbstore, 60, mainOrgID)
require.Equal(t, orgID, alertRule4.OrgID)
t.Run("can save and read new alert instance", func(t *testing.T) {

View File

@ -1,6 +1,7 @@
package tests
import (
"context"
"encoding/json"
"fmt"
"testing"
@ -50,9 +51,9 @@ func SetupTestEnv(t *testing.T, baseInterval time.Duration) (*ngalert.AlertNG, *
}
// CreateTestAlertRule creates a dummy alert definition to be used by the tests.
func CreateTestAlertRule(t *testing.T, dbstore *store.DBstore, intervalSeconds int64, orgID int64) *models.AlertRule {
func CreateTestAlertRule(t *testing.T, ctx context.Context, dbstore *store.DBstore, intervalSeconds int64, orgID int64) *models.AlertRule {
ruleGroup := fmt.Sprintf("ruleGroup-%s", util.GenerateShortUID())
err := dbstore.UpdateRuleGroup(store.UpdateRuleGroupCmd{
err := dbstore.UpdateRuleGroup(ctx, store.UpdateRuleGroupCmd{
OrgID: orgID,
NamespaceUID: "namespace",
RuleGroupConfig: apimodels.PostableRuleGroupConfig{
@ -92,7 +93,7 @@ func CreateTestAlertRule(t *testing.T, dbstore *store.DBstore, intervalSeconds i
NamespaceUID: "namespace",
RuleGroup: ruleGroup,
}
err = dbstore.GetRuleGroupAlertRules(&q)
err = dbstore.GetRuleGroupAlertRules(ctx, &q)
require.NoError(t, err)
require.NotEmpty(t, q.Result)
@ -102,7 +103,7 @@ func CreateTestAlertRule(t *testing.T, dbstore *store.DBstore, intervalSeconds i
}
// updateTestAlertRule update a dummy alert definition to be used by the tests.
func UpdateTestAlertRuleIntervalSeconds(t *testing.T, dbstore *store.DBstore, existingRule *models.AlertRule, intervalSeconds int64) *models.AlertRule {
func UpdateTestAlertRuleIntervalSeconds(t *testing.T, ctx context.Context, dbstore *store.DBstore, existingRule *models.AlertRule, intervalSeconds int64) *models.AlertRule {
cmd := store.UpdateRuleGroupCmd{
OrgID: 1,
NamespaceUID: "namespace",
@ -119,7 +120,7 @@ func UpdateTestAlertRuleIntervalSeconds(t *testing.T, dbstore *store.DBstore, ex
},
}
err := dbstore.UpdateRuleGroup(cmd)
err := dbstore.UpdateRuleGroup(ctx, cmd)
require.NoError(t, err)
q := models.ListRuleGroupAlertRulesQuery{
@ -127,7 +128,7 @@ func UpdateTestAlertRuleIntervalSeconds(t *testing.T, dbstore *store.DBstore, ex
NamespaceUID: "namespace",
RuleGroup: existingRule.RuleGroup,
}
err = dbstore.GetRuleGroupAlertRules(&q)
err = dbstore.GetRuleGroupAlertRules(ctx, &q)
require.NoError(t, err)
require.NotEmpty(t, q.Result)