mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Add context.Context to RuleStore (#45004)
Alerting: Add context.Context to RuleStore
This commit is contained in:
parent
31ba5bfea0
commit
a9399ab3cd
@ -101,7 +101,7 @@ func (srv PrometheusSrv) RouteGetRuleStatuses(c *models.ReqContext) response.Res
|
|||||||
DashboardUID: dashboardUID,
|
DashboardUID: dashboardUID,
|
||||||
PanelID: panelID,
|
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.Status = "error"
|
||||||
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("failure getting rule groups: %s", err.Error())
|
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("failure getting rule groups: %s", err.Error())
|
||||||
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrServer
|
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrServer
|
||||||
@ -113,7 +113,7 @@ func (srv PrometheusSrv) RouteGetRuleStatuses(c *models.ReqContext) response.Res
|
|||||||
DashboardUID: dashboardUID,
|
DashboardUID: dashboardUID,
|
||||||
PanelID: panelID,
|
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.Status = "error"
|
||||||
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("failure getting rules: %s", err.Error())
|
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("failure getting rules: %s", err.Error())
|
||||||
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrServer
|
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrServer
|
||||||
|
@ -38,7 +38,7 @@ func (srv RulerSrv) RouteDeleteNamespaceRulesConfig(c *models.ReqContext) respon
|
|||||||
return toNamespaceErrorResponse(err)
|
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 {
|
if err != nil {
|
||||||
return ErrResp(http.StatusInternalServerError, err, "failed to delete namespace alert rules")
|
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)
|
return toNamespaceErrorResponse(err)
|
||||||
}
|
}
|
||||||
ruleGroup := web.Params(c.Req)[":Groupname"]
|
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 err != nil {
|
||||||
if errors.Is(err, ngmodels.ErrRuleGroupNamespaceNotFound) {
|
if errors.Is(err, ngmodels.ErrRuleGroupNamespaceNotFound) {
|
||||||
@ -90,7 +90,7 @@ func (srv RulerSrv) RouteGetNamespaceRulesConfig(c *models.ReqContext) response.
|
|||||||
OrgID: c.SignedInUser.OrgId,
|
OrgID: c.SignedInUser.OrgId,
|
||||||
NamespaceUID: namespace.Uid,
|
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")
|
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,
|
NamespaceUID: namespace.Uid,
|
||||||
RuleGroup: ruleGroup,
|
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")
|
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,
|
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")
|
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,
|
OrgID: c.SignedInUser.OrgId,
|
||||||
NamespaceUID: namespace.Uid,
|
NamespaceUID: namespace.Uid,
|
||||||
RuleGroupConfig: ruleGroupConfig,
|
RuleGroupConfig: ruleGroupConfig,
|
||||||
|
@ -169,7 +169,7 @@ func (ng *AlertNG) init() error {
|
|||||||
// Run starts the scheduler and Alertmanager.
|
// Run starts the scheduler and Alertmanager.
|
||||||
func (ng *AlertNG) Run(ctx context.Context) error {
|
func (ng *AlertNG) Run(ctx context.Context) error {
|
||||||
ng.Log.Debug("ngalert starting")
|
ng.Log.Debug("ngalert starting")
|
||||||
ng.stateManager.Warm()
|
ng.stateManager.Warm(ctx)
|
||||||
|
|
||||||
children, subCtx := errgroup.WithContext(ctx)
|
children, subCtx := errgroup.WithContext(ctx)
|
||||||
|
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package schedule
|
package schedule
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
"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()
|
start := time.Now()
|
||||||
defer func() {
|
defer func() {
|
||||||
sch.metrics.GetAlertRulesDuration.Observe(time.Since(start).Seconds())
|
sch.metrics.GetAlertRulesDuration.Observe(time.Since(start).Seconds())
|
||||||
@ -15,7 +16,7 @@ func (sch *schedule) getAlertRules(disabledOrgs []int64) []*models.AlertRule {
|
|||||||
q := models.ListAlertRulesQuery{
|
q := models.ListAlertRulesQuery{
|
||||||
ExcludeOrgs: disabledOrgs,
|
ExcludeOrgs: disabledOrgs,
|
||||||
}
|
}
|
||||||
err := sch.ruleStore.GetAlertRulesForScheduling(&q)
|
err := sch.ruleStore.GetAlertRulesForScheduling(ctx, &q)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sch.log.Error("failed to fetch alert definitions", "err", err)
|
sch.log.Error("failed to fetch alert definitions", "err", err)
|
||||||
return nil
|
return nil
|
||||||
|
@ -377,7 +377,7 @@ func (sch *schedule) schedulePeriodic(ctx context.Context) error {
|
|||||||
disabledOrgs = append(disabledOrgs, disabledOrg)
|
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)
|
sch.log.Debug("alert rules fetched", "count", len(alertRules), "disabled_orgs", disabledOrgs)
|
||||||
|
|
||||||
// registeredDefinitions is a map used for finding deleted alert rules
|
// 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)
|
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}
|
q := models.GetAlertRuleByUIDQuery{OrgID: key.OrgID, UID: key.UID}
|
||||||
err := sch.ruleStore.GetAlertRuleByUID(&q)
|
err := sch.ruleStore.GetAlertRuleByUID(ctx, &q)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("failed to fetch alert rule", "err", err)
|
logger.Error("failed to fetch alert rule", "err", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -591,7 +591,7 @@ func (sch *schedule) ruleRoutine(grafanaCtx context.Context, key models.AlertRul
|
|||||||
case <-updateCh:
|
case <-updateCh:
|
||||||
logger.Info("fetching new version of the rule")
|
logger.Info("fetching new version of the rule")
|
||||||
err := retryIfError(func(attempt int64) error {
|
err := retryIfError(func(attempt int64) error {
|
||||||
newRule, err := updateRule(currentRule)
|
newRule, err := updateRule(grafanaCtx, currentRule)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -622,7 +622,7 @@ func (sch *schedule) ruleRoutine(grafanaCtx context.Context, key models.AlertRul
|
|||||||
err := retryIfError(func(attempt int64) error {
|
err := retryIfError(func(attempt int64) error {
|
||||||
// fetch latest alert rule version
|
// fetch latest alert rule version
|
||||||
if currentRule == nil || currentRule.Version < ctx.version {
|
if currentRule == nil || currentRule.Version < ctx.version {
|
||||||
newRule, err := updateRule(currentRule)
|
newRule, err := updateRule(grafanaCtx, currentRule)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -36,10 +36,11 @@ type evalAppliedInfo struct {
|
|||||||
func TestWarmStateCache(t *testing.T) {
|
func TestWarmStateCache(t *testing.T) {
|
||||||
evaluationTime, err := time.Parse("2006-01-02", "2021-03-25")
|
evaluationTime, err := time.Parse("2006-01-02", "2021-03-25")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
ctx := context.Background()
|
||||||
ng, dbstore := tests.SetupTestEnv(t, 1)
|
ng, dbstore := tests.SetupTestEnv(t, 1)
|
||||||
|
|
||||||
const mainOrgID int64 = 1
|
const mainOrgID int64 = 1
|
||||||
rule := tests.CreateTestAlertRule(t, dbstore, 600, mainOrgID)
|
rule := tests.CreateTestAlertRule(t, ctx, dbstore, 600, mainOrgID)
|
||||||
|
|
||||||
expectedEntries := []*state.State{
|
expectedEntries := []*state.State{
|
||||||
{
|
{
|
||||||
@ -105,7 +106,7 @@ func TestWarmStateCache(t *testing.T) {
|
|||||||
AdminConfigPollInterval: 10 * time.Minute, // do not poll in unit tests.
|
AdminConfigPollInterval: 10 * time.Minute, // do not poll in unit tests.
|
||||||
}
|
}
|
||||||
st := state.NewManager(schedCfg.Logger, testMetrics.GetStateMetrics(), nil, dbstore, dbstore, ng.SQLStore)
|
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) {
|
t.Run("instance cache has expected entries", func(t *testing.T) {
|
||||||
for _, entry := range expectedEntries {
|
for _, entry := range expectedEntries {
|
||||||
@ -121,13 +122,14 @@ func TestWarmStateCache(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAlertingTicker(t *testing.T) {
|
func TestAlertingTicker(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
ng, dbstore := tests.SetupTestEnv(t, 1)
|
ng, dbstore := tests.SetupTestEnv(t, 1)
|
||||||
|
|
||||||
alerts := make([]*models.AlertRule, 0)
|
alerts := make([]*models.AlertRule, 0)
|
||||||
|
|
||||||
const mainOrgID int64 = 1
|
const mainOrgID int64 = 1
|
||||||
// create alert rule under main org with one second interval
|
// 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
|
const disabledOrgID int64 = 3
|
||||||
|
|
||||||
@ -162,8 +164,6 @@ func TestAlertingTicker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
sched := schedule.NewScheduler(schedCfg, nil, appUrl, st)
|
sched := schedule.NewScheduler(schedCfg, nil, appUrl, st)
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err := sched.Run(ctx)
|
err := sched.Run(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -178,7 +178,7 @@ func TestAlertingTicker(t *testing.T) {
|
|||||||
|
|
||||||
// add alert rule under main org with three seconds interval
|
// add alert rule under main org with three seconds interval
|
||||||
var threeSecInterval int64 = 3
|
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)
|
t.Logf("alert rule: %v added with interval: %d", alerts[1].GetKey(), threeSecInterval)
|
||||||
|
|
||||||
expectedAlertRulesEvaluated = []models.AlertRuleKey{alerts[0].GetKey()}
|
expectedAlertRulesEvaluated = []models.AlertRuleKey{alerts[0].GetKey()}
|
||||||
@ -200,7 +200,7 @@ func TestAlertingTicker(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
key := alerts[0].GetKey()
|
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)
|
require.NoError(t, err)
|
||||||
t.Logf("alert rule: %v deleted", key)
|
t.Logf("alert rule: %v deleted", key)
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ func TestAlertingTicker(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// create alert rule with one second interval
|
// 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()}
|
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) {
|
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
|
// 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()}
|
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) {
|
t.Run(fmt.Sprintf("on 8th tick alert rules: %s should be evaluated", concatenate(expectedAlertRulesEvaluated)), func(t *testing.T) {
|
||||||
|
@ -482,6 +482,7 @@ func TestSchedule_ruleRoutine(t *testing.T) {
|
|||||||
evalChan := make(chan *evalContext)
|
evalChan := make(chan *evalContext)
|
||||||
evalAppliedChan := make(chan time.Time)
|
evalAppliedChan := make(chan time.Time)
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
sch, ruleStore, _, _, _ := createSchedule(evalAppliedChan)
|
sch, ruleStore, _, _, _ := createSchedule(evalAppliedChan)
|
||||||
|
|
||||||
rule := CreateTestAlertRule(t, ruleStore, 10, rand.Int63(), randomNormalState())
|
rule := CreateTestAlertRule(t, ruleStore, 10, rand.Int63(), randomNormalState())
|
||||||
@ -504,7 +505,7 @@ func TestSchedule_ruleRoutine(t *testing.T) {
|
|||||||
// Now update the rule
|
// Now update the rule
|
||||||
newRule := *rule
|
newRule := *rule
|
||||||
newRule.Version++
|
newRule.Version++
|
||||||
ruleStore.putRule(&newRule)
|
ruleStore.putRule(ctx, &newRule)
|
||||||
|
|
||||||
// and call with new version
|
// and call with new version
|
||||||
expectedTime = expectedTime.Add(time.Duration(rand.Intn(10)) * time.Second)
|
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)
|
evalAppliedChan := make(chan time.Time)
|
||||||
updateChan := make(chan struct{})
|
updateChan := make(chan struct{})
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
sch, ruleStore, _, _, _ := createSchedule(evalAppliedChan)
|
sch, ruleStore, _, _, _ := createSchedule(evalAppliedChan)
|
||||||
sch.senders[orgID] = s
|
sch.senders[orgID] = s
|
||||||
|
|
||||||
@ -728,7 +730,7 @@ func TestSchedule_ruleRoutine(t *testing.T) {
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
newRule := rule
|
newRule := rule
|
||||||
newRule.Version++
|
newRule.Version++
|
||||||
ruleStore.putRule(&newRule)
|
ruleStore.putRule(ctx, &newRule)
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
updateChan <- struct{}{}
|
updateChan <- struct{}{}
|
||||||
wg.Wait()
|
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.
|
// 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 {
|
func CreateTestAlertRule(t *testing.T, dbstore *fakeRuleStore, intervalSeconds int64, orgID int64, evalResult eval.State) *models.AlertRule {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
t.Helper()
|
t.Helper()
|
||||||
records := make([]interface{}, 0, len(dbstore.recordedOps))
|
records := make([]interface{}, 0, len(dbstore.recordedOps))
|
||||||
copy(records, 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")
|
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,
|
OrgID: orgID,
|
||||||
NamespaceUID: "namespace",
|
NamespaceUID: "namespace",
|
||||||
RuleGroupConfig: apimodels.PostableRuleGroupConfig{
|
RuleGroupConfig: apimodels.PostableRuleGroupConfig{
|
||||||
@ -1118,7 +1122,7 @@ func CreateTestAlertRule(t *testing.T, dbstore *fakeRuleStore, intervalSeconds i
|
|||||||
NamespaceUID: "namespace",
|
NamespaceUID: "namespace",
|
||||||
RuleGroup: ruleGroup,
|
RuleGroup: ruleGroup,
|
||||||
}
|
}
|
||||||
err = dbstore.GetRuleGroupAlertRules(&q)
|
err = dbstore.GetRuleGroupAlertRules(ctx, &q)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotEmpty(t, q.Result)
|
require.NotEmpty(t, q.Result)
|
||||||
|
|
||||||
|
@ -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
|
// 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()
|
f.mtx.Lock()
|
||||||
defer f.mtx.Unlock()
|
defer f.mtx.Unlock()
|
||||||
f.rules[r.OrgID][r.RuleGroup][r.NamespaceUID] = []*models.AlertRule{
|
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
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *fakeRuleStore) DeleteAlertRuleByUID(_ int64, _ string) error { return nil }
|
func (f *fakeRuleStore) DeleteAlertRuleByUID(_ context.Context, _ int64, _ string) error { return nil }
|
||||||
func (f *fakeRuleStore) DeleteNamespaceAlertRules(_ int64, _ string) ([]string, error) {
|
func (f *fakeRuleStore) DeleteNamespaceAlertRules(_ context.Context, _ int64, _ string) ([]string, error) {
|
||||||
return []string{}, nil
|
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
|
return []string{}, nil
|
||||||
}
|
}
|
||||||
func (f *fakeRuleStore) DeleteAlertInstancesByRuleUID(_ int64, _ string) error { return nil }
|
func (f *fakeRuleStore) DeleteAlertInstancesByRuleUID(_ context.Context, _ int64, _ string) error {
|
||||||
func (f *fakeRuleStore) GetAlertRuleByUID(q *models.GetAlertRuleByUIDQuery) error {
|
return nil
|
||||||
|
}
|
||||||
|
func (f *fakeRuleStore) GetAlertRuleByUID(_ context.Context, q *models.GetAlertRuleByUIDQuery) error {
|
||||||
f.mtx.Lock()
|
f.mtx.Lock()
|
||||||
defer f.mtx.Unlock()
|
defer f.mtx.Unlock()
|
||||||
f.recordedOps = append(f.recordedOps, *q)
|
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.
|
// 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()
|
f.mtx.Lock()
|
||||||
defer f.mtx.Unlock()
|
defer f.mtx.Unlock()
|
||||||
f.recordedOps = append(f.recordedOps, *q)
|
f.recordedOps = append(f.recordedOps, *q)
|
||||||
@ -146,19 +148,19 @@ func (f *fakeRuleStore) GetAlertRulesForScheduling(q *models.ListAlertRulesQuery
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (f *fakeRuleStore) GetOrgAlertRules(q *models.ListAlertRulesQuery) error {
|
func (f *fakeRuleStore) GetOrgAlertRules(_ context.Context, q *models.ListAlertRulesQuery) error {
|
||||||
f.mtx.Lock()
|
f.mtx.Lock()
|
||||||
defer f.mtx.Unlock()
|
defer f.mtx.Unlock()
|
||||||
f.recordedOps = append(f.recordedOps, *q)
|
f.recordedOps = append(f.recordedOps, *q)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (f *fakeRuleStore) GetNamespaceAlertRules(q *models.ListNamespaceAlertRulesQuery) error {
|
func (f *fakeRuleStore) GetNamespaceAlertRules(_ context.Context, q *models.ListNamespaceAlertRulesQuery) error {
|
||||||
f.mtx.Lock()
|
f.mtx.Lock()
|
||||||
defer f.mtx.Unlock()
|
defer f.mtx.Unlock()
|
||||||
f.recordedOps = append(f.recordedOps, *q)
|
f.recordedOps = append(f.recordedOps, *q)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (f *fakeRuleStore) GetRuleGroupAlertRules(q *models.ListRuleGroupAlertRulesQuery) error {
|
func (f *fakeRuleStore) GetRuleGroupAlertRules(_ context.Context, q *models.ListRuleGroupAlertRulesQuery) error {
|
||||||
f.mtx.Lock()
|
f.mtx.Lock()
|
||||||
defer f.mtx.Unlock()
|
defer f.mtx.Unlock()
|
||||||
f.recordedOps = append(f.recordedOps, *q)
|
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) {
|
func (f *fakeRuleStore) GetNamespaceByTitle(_ context.Context, _ string, _ int64, _ *models2.SignedInUser, _ bool) (*models2.Folder, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
func (f *fakeRuleStore) GetOrgRuleGroups(q *models.ListOrgRuleGroupsQuery) error {
|
func (f *fakeRuleStore) GetOrgRuleGroups(_ context.Context, q *models.ListOrgRuleGroupsQuery) error {
|
||||||
f.mtx.Lock()
|
f.mtx.Lock()
|
||||||
defer f.mtx.Unlock()
|
defer f.mtx.Unlock()
|
||||||
f.recordedOps = append(f.recordedOps, *q)
|
f.recordedOps = append(f.recordedOps, *q)
|
||||||
@ -206,7 +208,7 @@ func (f *fakeRuleStore) GetOrgRuleGroups(q *models.ListOrgRuleGroupsQuery) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *fakeRuleStore) UpsertAlertRules(q []store.UpsertRule) error {
|
func (f *fakeRuleStore) UpsertAlertRules(_ context.Context, q []store.UpsertRule) error {
|
||||||
f.mtx.Lock()
|
f.mtx.Lock()
|
||||||
defer f.mtx.Unlock()
|
defer f.mtx.Unlock()
|
||||||
f.recordedOps = append(f.recordedOps, q)
|
f.recordedOps = append(f.recordedOps, q)
|
||||||
@ -215,7 +217,7 @@ func (f *fakeRuleStore) UpsertAlertRules(q []store.UpsertRule) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (f *fakeRuleStore) UpdateRuleGroup(cmd store.UpdateRuleGroupCmd) error {
|
func (f *fakeRuleStore) UpdateRuleGroup(_ context.Context, cmd store.UpdateRuleGroupCmd) error {
|
||||||
f.mtx.Lock()
|
f.mtx.Lock()
|
||||||
defer f.mtx.Unlock()
|
defer f.mtx.Unlock()
|
||||||
f.recordedOps = append(f.recordedOps, cmd)
|
f.recordedOps = append(f.recordedOps, cmd)
|
||||||
|
@ -54,7 +54,7 @@ func (st *Manager) Close() {
|
|||||||
st.quit <- struct{}{}
|
st.quit <- struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Manager) Warm() {
|
func (st *Manager) Warm(ctx context.Context) {
|
||||||
st.log.Info("warming cache for startup")
|
st.log.Info("warming cache for startup")
|
||||||
st.ResetCache()
|
st.ResetCache()
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ func (st *Manager) Warm() {
|
|||||||
ruleCmd := ngModels.ListAlertRulesQuery{
|
ruleCmd := ngModels.ListAlertRulesQuery{
|
||||||
OrgID: orgId,
|
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())
|
st.log.Error("unable to fetch previous state", "msg", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1513,10 +1513,11 @@ func TestStaleResultsHandler(t *testing.T) {
|
|||||||
t.Fatalf("error parsing date format: %s", err.Error())
|
t.Fatalf("error parsing date format: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
_, dbstore := tests.SetupTestEnv(t, 1)
|
_, dbstore := tests.SetupTestEnv(t, 1)
|
||||||
|
|
||||||
const mainOrgID int64 = 1
|
const mainOrgID int64 = 1
|
||||||
rule := tests.CreateTestAlertRule(t, dbstore, 600, mainOrgID)
|
rule := tests.CreateTestAlertRule(t, ctx, dbstore, 600, mainOrgID)
|
||||||
|
|
||||||
saveCmd1 := &models.SaveAlertInstanceCommand{
|
saveCmd1 := &models.SaveAlertInstanceCommand{
|
||||||
RuleOrgID: rule.OrgID,
|
RuleOrgID: rule.OrgID,
|
||||||
@ -1589,9 +1590,10 @@ func TestStaleResultsHandler(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
ctx := context.Background()
|
||||||
sqlStore := mockstore.NewSQLStoreMock()
|
sqlStore := mockstore.NewSQLStoreMock()
|
||||||
st := state.NewManager(log.New("test_stale_results_handler"), testMetrics.GetStateMetrics(), nil, dbstore, dbstore, sqlStore)
|
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)
|
existingStatesForRule := st.GetStatesForRuleUID(rule.OrgID, rule.UID)
|
||||||
|
|
||||||
// We have loaded the expected number of entries from the db
|
// We have loaded the expected number of entries from the db
|
||||||
|
@ -39,20 +39,20 @@ type UpsertRule struct {
|
|||||||
|
|
||||||
// Store is the interface for persisting alert rules and instances
|
// Store is the interface for persisting alert rules and instances
|
||||||
type RuleStore interface {
|
type RuleStore interface {
|
||||||
DeleteAlertRuleByUID(orgID int64, ruleUID string) error
|
DeleteAlertRuleByUID(ctx context.Context, orgID int64, ruleUID string) error
|
||||||
DeleteNamespaceAlertRules(orgID int64, namespaceUID string) ([]string, error)
|
DeleteNamespaceAlertRules(ctx context.Context, orgID int64, namespaceUID string) ([]string, error)
|
||||||
DeleteRuleGroupAlertRules(orgID int64, namespaceUID string, ruleGroup string) ([]string, error)
|
DeleteRuleGroupAlertRules(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string) ([]string, error)
|
||||||
DeleteAlertInstancesByRuleUID(orgID int64, ruleUID string) error
|
DeleteAlertInstancesByRuleUID(ctx context.Context, orgID int64, ruleUID string) error
|
||||||
GetAlertRuleByUID(*ngmodels.GetAlertRuleByUIDQuery) error
|
GetAlertRuleByUID(ctx context.Context, query *ngmodels.GetAlertRuleByUIDQuery) error
|
||||||
GetAlertRulesForScheduling(query *ngmodels.ListAlertRulesQuery) error
|
GetAlertRulesForScheduling(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error
|
||||||
GetOrgAlertRules(query *ngmodels.ListAlertRulesQuery) error
|
GetOrgAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error
|
||||||
GetNamespaceAlertRules(query *ngmodels.ListNamespaceAlertRulesQuery) error
|
GetNamespaceAlertRules(ctx context.Context, query *ngmodels.ListNamespaceAlertRulesQuery) error
|
||||||
GetRuleGroupAlertRules(query *ngmodels.ListRuleGroupAlertRulesQuery) error
|
GetRuleGroupAlertRules(ctx context.Context, query *ngmodels.ListRuleGroupAlertRulesQuery) error
|
||||||
GetNamespaces(context.Context, int64, *models.SignedInUser) (map[string]*models.Folder, error)
|
GetNamespaces(context.Context, int64, *models.SignedInUser) (map[string]*models.Folder, error)
|
||||||
GetNamespaceByTitle(context.Context, string, int64, *models.SignedInUser, bool) (*models.Folder, error)
|
GetNamespaceByTitle(context.Context, string, int64, *models.SignedInUser, bool) (*models.Folder, error)
|
||||||
GetOrgRuleGroups(query *ngmodels.ListOrgRuleGroupsQuery) error
|
GetOrgRuleGroups(ctx context.Context, query *ngmodels.ListOrgRuleGroupsQuery) error
|
||||||
UpsertAlertRules([]UpsertRule) error
|
UpsertAlertRules(ctx context.Context, rule []UpsertRule) error
|
||||||
UpdateRuleGroup(UpdateRuleGroupCmd) error
|
UpdateRuleGroup(ctx context.Context, cmd UpdateRuleGroupCmd) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAlertRuleByUID(sess *sqlstore.DBSession, alertRuleUID string, orgID int64) (*ngmodels.AlertRule, 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.
|
// DeleteAlertRuleByUID is a handler for deleting an alert rule.
|
||||||
func (st DBstore) DeleteAlertRuleByUID(orgID int64, ruleUID string) error {
|
func (st DBstore) DeleteAlertRuleByUID(ctx context.Context, orgID int64, ruleUID string) error {
|
||||||
return st.SQLStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) 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)
|
_, err := sess.Exec("DELETE FROM alert_rule WHERE org_id = ? AND uid = ?", orgID, ruleUID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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.
|
// 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{}
|
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 {
|
if err := sess.SQL("SELECT uid FROM alert_rule WHERE org_id = ? and namespace_uid = ?", orgID, namespaceUID).Find(&ruleUIDs); err != nil {
|
||||||
return err
|
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.
|
// 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{}
|
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 = ?",
|
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 {
|
orgID, namespaceUID, ruleGroup).Find(&ruleUIDs); err != nil {
|
||||||
return err
|
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
|
// 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 {
|
func (st DBstore) DeleteAlertInstancesByRuleUID(ctx context.Context, orgID int64, ruleUID string) error {
|
||||||
return st.SQLStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) 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)
|
_, err := sess.Exec("DELETE FROM alert_instance WHERE rule_org_id = ? AND rule_uid = ?", orgID, ruleUID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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.
|
// 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.
|
// It returns ngmodels.ErrAlertRuleNotFound if no alert rule is found for the provided ID.
|
||||||
func (st DBstore) GetAlertRuleByUID(query *ngmodels.GetAlertRuleByUIDQuery) error {
|
func (st DBstore) GetAlertRuleByUID(ctx context.Context, query *ngmodels.GetAlertRuleByUIDQuery) error {
|
||||||
return st.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
return st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||||
alertRule, err := getAlertRuleByUID(sess, query.UID, query.OrgID)
|
alertRule, err := getAlertRuleByUID(sess, query.UID, query.OrgID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -185,8 +185,8 @@ func (st DBstore) GetAlertRuleByUID(query *ngmodels.GetAlertRuleByUIDQuery) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpsertAlertRules is a handler for creating/updating alert rules.
|
// UpsertAlertRules is a handler for creating/updating alert rules.
|
||||||
func (st DBstore) UpsertAlertRules(rules []UpsertRule) error {
|
func (st DBstore) UpsertAlertRules(ctx context.Context, rules []UpsertRule) error {
|
||||||
return st.SQLStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
return st.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||||
newRules := make([]ngmodels.AlertRule, 0, len(rules))
|
newRules := make([]ngmodels.AlertRule, 0, len(rules))
|
||||||
ruleVersions := make([]ngmodels.AlertRuleVersion, 0, len(rules))
|
ruleVersions := make([]ngmodels.AlertRuleVersion, 0, len(rules))
|
||||||
for _, r := range 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.
|
// GetOrgAlertRules is a handler for retrieving alert rules of specific organisation.
|
||||||
func (st DBstore) GetOrgAlertRules(query *ngmodels.ListAlertRulesQuery) error {
|
func (st DBstore) GetOrgAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error {
|
||||||
return st.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
return st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||||
alertRules := make([]*ngmodels.AlertRule, 0)
|
alertRules := make([]*ngmodels.AlertRule, 0)
|
||||||
q := "SELECT * FROM alert_rule WHERE org_id = ?"
|
q := "SELECT * FROM alert_rule WHERE org_id = ?"
|
||||||
params := []interface{}{query.OrgID}
|
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.
|
// GetNamespaceAlertRules is a handler for retrieving namespace alert rules of specific organisation.
|
||||||
func (st DBstore) GetNamespaceAlertRules(query *ngmodels.ListNamespaceAlertRulesQuery) error {
|
func (st DBstore) GetNamespaceAlertRules(ctx context.Context, query *ngmodels.ListNamespaceAlertRulesQuery) error {
|
||||||
return st.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
return st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||||
alertRules := make([]*ngmodels.AlertRule, 0)
|
alertRules := make([]*ngmodels.AlertRule, 0)
|
||||||
// TODO rewrite using group by namespace_uid, rule_group
|
// TODO rewrite using group by namespace_uid, rule_group
|
||||||
q := "SELECT * FROM alert_rule WHERE org_id = ? and namespace_uid = ?"
|
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.
|
// GetRuleGroupAlertRules is a handler for retrieving rule group alert rules of specific organisation.
|
||||||
func (st DBstore) GetRuleGroupAlertRules(query *ngmodels.ListRuleGroupAlertRulesQuery) error {
|
func (st DBstore) GetRuleGroupAlertRules(ctx context.Context, query *ngmodels.ListRuleGroupAlertRulesQuery) error {
|
||||||
return st.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) 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 = ?"
|
q := "SELECT * FROM alert_rule WHERE org_id = ? and namespace_uid = ? and rule_group = ?"
|
||||||
args := []interface{}{query.OrgID, query.NamespaceUID, query.RuleGroup}
|
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)
|
// GetAlertRulesForScheduling returns alert rule info (identifier, interval, version state)
|
||||||
// that is useful for it's scheduling.
|
// that is useful for it's scheduling.
|
||||||
func (st DBstore) GetAlertRulesForScheduling(query *ngmodels.ListAlertRulesQuery) error {
|
func (st DBstore) GetAlertRulesForScheduling(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error {
|
||||||
return st.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
return st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||||
alerts := make([]*ngmodels.AlertRule, 0)
|
alerts := make([]*ngmodels.AlertRule, 0)
|
||||||
q := "SELECT uid, org_id, interval_seconds, version FROM alert_rule"
|
q := "SELECT uid, org_id, interval_seconds, version FROM alert_rule"
|
||||||
if len(query.ExcludeOrgs) > 0 {
|
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
|
// UpdateRuleGroup creates new rules and updates and/or deletes existing rules
|
||||||
func (st DBstore) UpdateRuleGroup(cmd UpdateRuleGroupCmd) error {
|
func (st DBstore) UpdateRuleGroup(ctx context.Context, cmd UpdateRuleGroupCmd) error {
|
||||||
return st.SQLStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
return st.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||||
ruleGroup := cmd.RuleGroupConfig.Name
|
ruleGroup := cmd.RuleGroupConfig.Name
|
||||||
q := &ngmodels.ListRuleGroupAlertRulesQuery{
|
q := &ngmodels.ListRuleGroupAlertRulesQuery{
|
||||||
OrgID: cmd.OrgID,
|
OrgID: cmd.OrgID,
|
||||||
NamespaceUID: cmd.NamespaceUID,
|
NamespaceUID: cmd.NamespaceUID,
|
||||||
RuleGroup: ruleGroup,
|
RuleGroup: ruleGroup,
|
||||||
}
|
}
|
||||||
if err := st.GetRuleGroupAlertRules(q); err != nil {
|
if err := st.GetRuleGroupAlertRules(ctx, q); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
existingGroupRules := q.Result
|
existingGroupRules := q.Result
|
||||||
@ -578,7 +578,7 @@ func (st DBstore) UpdateRuleGroup(cmd UpdateRuleGroupCmd) error {
|
|||||||
upsertRules = append(upsertRules, upsertRule)
|
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) {
|
if st.SQLStore.Dialect.IsUniqueConstraintViolation(err) {
|
||||||
return ngmodels.ErrAlertRuleUniqueConstraintViolation
|
return ngmodels.ErrAlertRuleUniqueConstraintViolation
|
||||||
}
|
}
|
||||||
@ -588,7 +588,7 @@ func (st DBstore) UpdateRuleGroup(cmd UpdateRuleGroupCmd) error {
|
|||||||
// delete instances for rules that will not be removed
|
// delete instances for rules that will not be removed
|
||||||
for _, rule := range existingGroupRules {
|
for _, rule := range existingGroupRules {
|
||||||
if _, ok := existingGroupRulesUIDs[rule.UID]; !ok {
|
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
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -596,7 +596,7 @@ func (st DBstore) UpdateRuleGroup(cmd UpdateRuleGroupCmd) error {
|
|||||||
|
|
||||||
// delete the remaining rules
|
// delete the remaining rules
|
||||||
for ruleUID := range existingGroupRulesUIDs {
|
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
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -604,8 +604,8 @@ func (st DBstore) UpdateRuleGroup(cmd UpdateRuleGroupCmd) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st DBstore) GetOrgRuleGroups(query *ngmodels.ListOrgRuleGroupsQuery) error {
|
func (st DBstore) GetOrgRuleGroups(ctx context.Context, query *ngmodels.ListOrgRuleGroupsQuery) error {
|
||||||
return st.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
return st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||||
var ruleGroups [][]string
|
var ruleGroups [][]string
|
||||||
q := `
|
q := `
|
||||||
SELECT DISTINCT
|
SELECT DISTINCT
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
package store_test
|
package store_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -26,20 +27,21 @@ func mockTimeNow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAlertInstanceOperations(t *testing.T) {
|
func TestAlertInstanceOperations(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
_, dbstore := tests.SetupTestEnv(t, baseIntervalSeconds)
|
_, dbstore := tests.SetupTestEnv(t, baseIntervalSeconds)
|
||||||
|
|
||||||
const mainOrgID int64 = 1
|
const mainOrgID int64 = 1
|
||||||
|
|
||||||
alertRule1 := tests.CreateTestAlertRule(t, dbstore, 60, mainOrgID)
|
alertRule1 := tests.CreateTestAlertRule(t, ctx, dbstore, 60, mainOrgID)
|
||||||
orgID := alertRule1.OrgID
|
orgID := alertRule1.OrgID
|
||||||
|
|
||||||
alertRule2 := tests.CreateTestAlertRule(t, dbstore, 60, mainOrgID)
|
alertRule2 := tests.CreateTestAlertRule(t, ctx, dbstore, 60, mainOrgID)
|
||||||
require.Equal(t, orgID, alertRule2.OrgID)
|
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)
|
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)
|
require.Equal(t, orgID, alertRule4.OrgID)
|
||||||
|
|
||||||
t.Run("can save and read new alert instance", func(t *testing.T) {
|
t.Run("can save and read new alert instance", func(t *testing.T) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package tests
|
package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"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.
|
// 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())
|
ruleGroup := fmt.Sprintf("ruleGroup-%s", util.GenerateShortUID())
|
||||||
err := dbstore.UpdateRuleGroup(store.UpdateRuleGroupCmd{
|
err := dbstore.UpdateRuleGroup(ctx, store.UpdateRuleGroupCmd{
|
||||||
OrgID: orgID,
|
OrgID: orgID,
|
||||||
NamespaceUID: "namespace",
|
NamespaceUID: "namespace",
|
||||||
RuleGroupConfig: apimodels.PostableRuleGroupConfig{
|
RuleGroupConfig: apimodels.PostableRuleGroupConfig{
|
||||||
@ -92,7 +93,7 @@ func CreateTestAlertRule(t *testing.T, dbstore *store.DBstore, intervalSeconds i
|
|||||||
NamespaceUID: "namespace",
|
NamespaceUID: "namespace",
|
||||||
RuleGroup: ruleGroup,
|
RuleGroup: ruleGroup,
|
||||||
}
|
}
|
||||||
err = dbstore.GetRuleGroupAlertRules(&q)
|
err = dbstore.GetRuleGroupAlertRules(ctx, &q)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotEmpty(t, q.Result)
|
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.
|
// 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{
|
cmd := store.UpdateRuleGroupCmd{
|
||||||
OrgID: 1,
|
OrgID: 1,
|
||||||
NamespaceUID: "namespace",
|
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)
|
require.NoError(t, err)
|
||||||
|
|
||||||
q := models.ListRuleGroupAlertRulesQuery{
|
q := models.ListRuleGroupAlertRulesQuery{
|
||||||
@ -127,7 +128,7 @@ func UpdateTestAlertRuleIntervalSeconds(t *testing.T, dbstore *store.DBstore, ex
|
|||||||
NamespaceUID: "namespace",
|
NamespaceUID: "namespace",
|
||||||
RuleGroup: existingRule.RuleGroup,
|
RuleGroup: existingRule.RuleGroup,
|
||||||
}
|
}
|
||||||
err = dbstore.GetRuleGroupAlertRules(&q)
|
err = dbstore.GetRuleGroupAlertRules(ctx, &q)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotEmpty(t, q.Result)
|
require.NotEmpty(t, q.Result)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user