Alerting: Create instanceStore (#33587)

for https://github.com/grafana/alerting-squad/issues/129
This commit is contained in:
Kyle Brandt 2021-05-03 07:19:15 -04:00 committed by GitHub
parent 3c79138d21
commit c1034f3118
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 90 additions and 88 deletions

View File

@ -42,8 +42,8 @@ type API struct {
RouteRegister routing.RouteRegister
DataService *tsdb.Service
Schedule schedule.ScheduleService
Store store.Store
RuleStore store.RuleStore
InstanceStore store.InstanceStore
AlertingStore store.AlertingStore
DataProxy *datasourceproxy.DatasourceProxyService
Alertmanager Alertmanager

View File

@ -44,8 +44,8 @@ func (i InstanceStateType) IsValid() bool {
// SaveAlertInstanceCommand is the query for saving a new alert instance.
type SaveAlertInstanceCommand struct {
DefinitionOrgID int64
DefinitionUID string
RuleOrgID int64
RuleUID string
Labels InstanceLabels
State InstanceStateType
LastEvalTime time.Time
@ -56,18 +56,18 @@ type SaveAlertInstanceCommand struct {
// GetAlertInstanceQuery is the query for retrieving/deleting an alert definition by ID.
// nolint:unused
type GetAlertInstanceQuery struct {
DefinitionOrgID int64
DefinitionUID string
Labels InstanceLabels
RuleOrgID int64
RuleUID string
Labels InstanceLabels
Result *AlertInstance
}
// ListAlertInstancesQuery is the query list alert Instances.
type ListAlertInstancesQuery struct {
DefinitionOrgID int64 `json:"-"`
DefinitionUID string
State InstanceStateType
RuleOrgID int64 `json:"-"`
RuleUID string
State InstanceStateType
Result []*ListAlertInstancesQueryResult
}

View File

@ -65,14 +65,14 @@ func (ng *AlertNG) Init() error {
store := store.DBstore{BaseInterval: baseInterval, DefaultIntervalSeconds: defaultIntervalSeconds, SQLStore: ng.SQLStore}
schedCfg := schedule.SchedulerCfg{
C: clock.New(),
BaseInterval: baseInterval,
Logger: ng.Log,
MaxAttempts: maxAttempts,
Evaluator: eval.Evaluator{Cfg: ng.Cfg},
Store: store,
RuleStore: store,
Notifier: ng.Alertmanager,
C: clock.New(),
BaseInterval: baseInterval,
Logger: ng.Log,
MaxAttempts: maxAttempts,
Evaluator: eval.Evaluator{Cfg: ng.Cfg},
InstanceStore: store,
RuleStore: store,
Notifier: ng.Alertmanager,
}
ng.schedule = schedule.NewScheduler(schedCfg, ng.DataService)
@ -83,7 +83,7 @@ func (ng *AlertNG) Init() error {
DataService: ng.DataService,
Schedule: ng.schedule,
DataProxy: ng.DataProxy,
Store: store,
InstanceStore: store,
RuleStore: store,
AlertingStore: store,
Alertmanager: ng.Alertmanager,

View File

@ -146,10 +146,10 @@ type schedule struct {
evaluator eval.Evaluator
store store.Store
ruleStore store.RuleStore
instanceStore store.InstanceStore
dataService *tsdb.Service
notifier Notifier
@ -164,8 +164,8 @@ type SchedulerCfg struct {
MaxAttempts int64
StopAppliedFunc func(models.AlertRuleKey)
Evaluator eval.Evaluator
Store store.Store
RuleStore store.RuleStore
InstanceStore store.InstanceStore
Notifier Notifier
}
@ -182,8 +182,8 @@ func NewScheduler(cfg SchedulerCfg, dataService *tsdb.Service) *schedule {
evalAppliedFunc: cfg.EvalAppliedFunc,
stopAppliedFunc: cfg.StopAppliedFunc,
evaluator: cfg.Evaluator,
store: cfg.Store,
ruleStore: cfg.RuleStore,
instanceStore: cfg.InstanceStore,
dataService: dataService,
notifier: cfg.Notifier,
}
@ -321,15 +321,15 @@ func (sch *schedule) saveAlertStates(states []*state.State) {
sch.log.Debug("saving alert states", "count", len(states))
for _, s := range states {
cmd := models.SaveAlertInstanceCommand{
DefinitionOrgID: s.OrgID,
DefinitionUID: s.AlertRuleUID,
RuleOrgID: s.OrgID,
RuleUID: s.AlertRuleUID,
Labels: models.InstanceLabels(s.Labels),
State: models.InstanceStateType(s.State.String()),
LastEvalTime: s.LastEvaluationTime,
CurrentStateSince: s.StartsAt,
CurrentStateEnd: s.EndsAt,
}
err := sch.store.SaveAlertInstance(&cmd)
err := sch.instanceStore.SaveAlertInstance(&cmd)
if err != nil {
sch.log.Error("failed to save alert state", "uid", s.AlertRuleUID, "orgId", s.OrgID, "labels", s.Labels.String(), "state", s.State.String(), "msg", err.Error())
}
@ -341,8 +341,7 @@ func (sch *schedule) WarmStateCache(st *state.Manager) {
st.ResetCache()
orgIdsCmd := models.FetchUniqueOrgIdsQuery{}
if err := sch.store.FetchOrgIds(&orgIdsCmd); err != nil {
if err := sch.instanceStore.FetchOrgIds(&orgIdsCmd); err != nil {
sch.log.Error("unable to fetch orgIds", "msg", err.Error())
}
@ -363,9 +362,9 @@ func (sch *schedule) WarmStateCache(st *state.Manager) {
// Get Instances
cmd := models.ListAlertInstancesQuery{
DefinitionOrgID: orgIdResult.DefinitionOrgID,
RuleOrgID: orgIdResult.DefinitionOrgID,
}
if err := sch.ruleStore.ListAlertInstances(&cmd); err != nil {
if err := sch.instanceStore.ListAlertInstances(&cmd); err != nil {
sch.log.Error("unable to fetch previous state", "msg", err.Error())
}

View File

@ -50,9 +50,6 @@ type RuleStore interface {
GetOrgRuleGroups(query *ngmodels.ListOrgRuleGroupsQuery) error
UpsertAlertRules([]UpsertRule) error
UpdateRuleGroup(UpdateRuleGroupCmd) error
GetAlertInstance(*ngmodels.GetAlertInstanceQuery) error
ListAlertInstances(cmd *ngmodels.ListAlertInstancesQuery) error
SaveAlertInstance(cmd *ngmodels.SaveAlertInstanceCommand) error
}
func getAlertRuleByUID(sess *sqlstore.DBSession, alertRuleUID string, orgID int64) (*ngmodels.AlertRule, error) {

View File

@ -9,9 +9,15 @@ import (
"github.com/grafana/grafana/pkg/services/sqlstore"
)
type InstanceStore interface {
GetAlertInstance(cmd *models.GetAlertInstanceQuery) error
ListAlertInstances(cmd *models.ListAlertInstancesQuery) error
SaveAlertInstance(cmd *models.SaveAlertInstanceCommand) error
FetchOrgIds(cmd *models.FetchUniqueOrgIdsQuery) error
}
// GetAlertInstance is a handler for retrieving an alert instance based on OrgId, AlertDefintionID, and
// the hash of the labels.
// nolint:unused
func (st DBstore) GetAlertInstance(cmd *models.GetAlertInstanceQuery) error {
return st.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
instance := models.AlertInstance{}
@ -28,11 +34,11 @@ func (st DBstore) GetAlertInstance(cmd *models.GetAlertInstanceQuery) error {
return err
}
params := append(make([]interface{}, 0), cmd.DefinitionOrgID, cmd.DefinitionUID, hash)
params := append(make([]interface{}, 0), cmd.RuleOrgID, cmd.RuleUID, hash)
has, err := sess.SQL(s.String(), params...).Get(&instance)
if !has {
return fmt.Errorf("instance not found for labels %v (hash: %v), alert definition %v (org %v)", cmd.Labels, hash, cmd.DefinitionUID, cmd.DefinitionOrgID)
return fmt.Errorf("instance not found for labels %v (hash: %v), alert definition %v (org %v)", cmd.Labels, hash, cmd.RuleUID, cmd.RuleOrgID)
}
if err != nil {
return err
@ -57,10 +63,10 @@ func (st DBstore) ListAlertInstances(cmd *models.ListAlertInstancesQuery) error
params = append(params, p...)
}
addToQuery("SELECT alert_instance.*, alert_definition.title AS def_title FROM alert_instance LEFT JOIN alert_definition ON alert_instance.def_org_id = alert_definition.org_id AND alert_instance.def_uid = alert_definition.uid WHERE def_org_id = ?", cmd.DefinitionOrgID)
addToQuery("SELECT alert_instance.*, alert_definition.title AS def_title FROM alert_instance LEFT JOIN alert_definition ON alert_instance.def_org_id = alert_definition.org_id AND alert_instance.def_uid = alert_definition.uid WHERE def_org_id = ?", cmd.RuleOrgID)
if cmd.DefinitionUID != "" {
addToQuery(` AND def_uid = ?`, cmd.DefinitionUID)
if cmd.RuleUID != "" {
addToQuery(` AND def_uid = ?`, cmd.RuleUID)
}
if cmd.State != "" {
@ -77,7 +83,6 @@ func (st DBstore) ListAlertInstances(cmd *models.ListAlertInstancesQuery) error
}
// SaveAlertInstance is a handler for saving a new alert instance.
// nolint:unused
func (st DBstore) SaveAlertInstance(cmd *models.SaveAlertInstanceCommand) error {
return st.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
labelTupleJSON, labelsHash, err := cmd.Labels.StringAndHash()
@ -86,8 +91,8 @@ func (st DBstore) SaveAlertInstance(cmd *models.SaveAlertInstanceCommand) error
}
alertInstance := &models.AlertInstance{
RuleOrgID: cmd.DefinitionOrgID,
RuleUID: cmd.DefinitionUID,
RuleOrgID: cmd.RuleOrgID,
RuleUID: cmd.RuleUID,
Labels: cmd.Labels,
LabelsHash: labelsHash,
CurrentState: cmd.State,

View File

@ -42,18 +42,18 @@ func TestAlertInstanceOperations(t *testing.T) {
t.Run("can save and read new alert instance", func(t *testing.T) {
saveCmd := &models.SaveAlertInstanceCommand{
DefinitionOrgID: alertRule1.OrgID,
DefinitionUID: alertRule1.UID,
State: models.InstanceStateFiring,
Labels: models.InstanceLabels{"test": "testValue"},
RuleOrgID: alertRule1.OrgID,
RuleUID: alertRule1.UID,
State: models.InstanceStateFiring,
Labels: models.InstanceLabels{"test": "testValue"},
}
err := dbstore.SaveAlertInstance(saveCmd)
require.NoError(t, err)
getCmd := &models.GetAlertInstanceQuery{
DefinitionOrgID: saveCmd.DefinitionOrgID,
DefinitionUID: saveCmd.DefinitionUID,
Labels: models.InstanceLabels{"test": "testValue"},
RuleOrgID: saveCmd.RuleOrgID,
RuleUID: saveCmd.RuleUID,
Labels: models.InstanceLabels{"test": "testValue"},
}
err = dbstore.GetAlertInstance(getCmd)
@ -66,17 +66,17 @@ func TestAlertInstanceOperations(t *testing.T) {
t.Run("can save and read new alert instance with no labels", func(t *testing.T) {
saveCmd := &models.SaveAlertInstanceCommand{
DefinitionOrgID: alertRule2.OrgID,
DefinitionUID: alertRule2.UID,
State: models.InstanceStateNormal,
Labels: models.InstanceLabels{},
RuleOrgID: alertRule2.OrgID,
RuleUID: alertRule2.UID,
State: models.InstanceStateNormal,
Labels: models.InstanceLabels{},
}
err := dbstore.SaveAlertInstance(saveCmd)
require.NoError(t, err)
getCmd := &models.GetAlertInstanceQuery{
DefinitionOrgID: saveCmd.DefinitionOrgID,
DefinitionUID: saveCmd.DefinitionUID,
RuleOrgID: saveCmd.RuleOrgID,
RuleUID: saveCmd.RuleUID,
}
err = dbstore.GetAlertInstance(getCmd)
@ -89,27 +89,27 @@ func TestAlertInstanceOperations(t *testing.T) {
t.Run("can save two instances with same org_id, uid and different labels", func(t *testing.T) {
saveCmdOne := &models.SaveAlertInstanceCommand{
DefinitionOrgID: alertRule3.OrgID,
DefinitionUID: alertRule3.UID,
State: models.InstanceStateFiring,
Labels: models.InstanceLabels{"test": "testValue"},
RuleOrgID: alertRule3.OrgID,
RuleUID: alertRule3.UID,
State: models.InstanceStateFiring,
Labels: models.InstanceLabels{"test": "testValue"},
}
err := dbstore.SaveAlertInstance(saveCmdOne)
require.NoError(t, err)
saveCmdTwo := &models.SaveAlertInstanceCommand{
DefinitionOrgID: saveCmdOne.DefinitionOrgID,
DefinitionUID: saveCmdOne.DefinitionUID,
State: models.InstanceStateFiring,
Labels: models.InstanceLabels{"test": "meow"},
RuleOrgID: saveCmdOne.RuleOrgID,
RuleUID: saveCmdOne.RuleUID,
State: models.InstanceStateFiring,
Labels: models.InstanceLabels{"test": "meow"},
}
err = dbstore.SaveAlertInstance(saveCmdTwo)
require.NoError(t, err)
listQuery := &models.ListAlertInstancesQuery{
DefinitionOrgID: saveCmdOne.DefinitionOrgID,
DefinitionUID: saveCmdOne.DefinitionUID,
RuleOrgID: saveCmdOne.RuleOrgID,
RuleUID: saveCmdOne.RuleUID,
}
err = dbstore.ListAlertInstances(listQuery)
@ -120,7 +120,7 @@ func TestAlertInstanceOperations(t *testing.T) {
t.Run("can list all added instances in org", func(t *testing.T) {
listQuery := &models.ListAlertInstancesQuery{
DefinitionOrgID: orgID,
RuleOrgID: orgID,
}
err := dbstore.ListAlertInstances(listQuery)
@ -131,8 +131,8 @@ func TestAlertInstanceOperations(t *testing.T) {
t.Run("can list all added instances in org filtered by current state", func(t *testing.T) {
listQuery := &models.ListAlertInstancesQuery{
DefinitionOrgID: orgID,
State: models.InstanceStateNormal,
RuleOrgID: orgID,
State: models.InstanceStateNormal,
}
err := dbstore.ListAlertInstances(listQuery)
@ -143,27 +143,27 @@ func TestAlertInstanceOperations(t *testing.T) {
t.Run("update instance with same org_id, uid and different labels", func(t *testing.T) {
saveCmdOne := &models.SaveAlertInstanceCommand{
DefinitionOrgID: alertRule4.OrgID,
DefinitionUID: alertRule4.UID,
State: models.InstanceStateFiring,
Labels: models.InstanceLabels{"test": "testValue"},
RuleOrgID: alertRule4.OrgID,
RuleUID: alertRule4.UID,
State: models.InstanceStateFiring,
Labels: models.InstanceLabels{"test": "testValue"},
}
err := dbstore.SaveAlertInstance(saveCmdOne)
require.NoError(t, err)
saveCmdTwo := &models.SaveAlertInstanceCommand{
DefinitionOrgID: saveCmdOne.DefinitionOrgID,
DefinitionUID: saveCmdOne.DefinitionUID,
State: models.InstanceStateNormal,
Labels: models.InstanceLabels{"test": "testValue"},
RuleOrgID: saveCmdOne.RuleOrgID,
RuleUID: saveCmdOne.RuleUID,
State: models.InstanceStateNormal,
Labels: models.InstanceLabels{"test": "testValue"},
}
err = dbstore.SaveAlertInstance(saveCmdTwo)
require.NoError(t, err)
listQuery := &models.ListAlertInstancesQuery{
DefinitionOrgID: alertRule4.OrgID,
DefinitionUID: alertRule4.UID,
RuleOrgID: alertRule4.OrgID,
RuleUID: alertRule4.UID,
}
err = dbstore.ListAlertInstances(listQuery)
@ -171,8 +171,8 @@ func TestAlertInstanceOperations(t *testing.T) {
require.Len(t, listQuery.Result, 1)
require.Equal(t, saveCmdTwo.DefinitionOrgID, listQuery.Result[0].RuleOrgID)
require.Equal(t, saveCmdTwo.DefinitionUID, listQuery.Result[0].RuleDefinitionUID)
require.Equal(t, saveCmdTwo.RuleOrgID, listQuery.Result[0].RuleOrgID)
require.Equal(t, saveCmdTwo.RuleUID, listQuery.Result[0].RuleDefinitionUID)
require.Equal(t, saveCmdTwo.Labels, listQuery.Result[0].Labels)
require.Equal(t, saveCmdTwo.State, listQuery.Result[0].CurrentState)
})

View File

@ -69,8 +69,8 @@ func TestWarmStateCache(t *testing.T) {
}
saveCmd1 := &models.SaveAlertInstanceCommand{
DefinitionOrgID: rule.OrgID,
DefinitionUID: rule.UID,
RuleOrgID: rule.OrgID,
RuleUID: rule.UID,
Labels: models.InstanceLabels{"test1": "testValue1"},
State: models.InstanceStateNormal,
LastEvalTime: evaluationTime,
@ -81,8 +81,8 @@ func TestWarmStateCache(t *testing.T) {
_ = dbstore.SaveAlertInstance(saveCmd1)
saveCmd2 := &models.SaveAlertInstanceCommand{
DefinitionOrgID: rule.OrgID,
DefinitionUID: rule.UID,
RuleOrgID: rule.OrgID,
RuleUID: rule.UID,
Labels: models.InstanceLabels{"test2": "testValue2"},
State: models.InstanceStateFiring,
LastEvalTime: evaluationTime,
@ -97,8 +97,9 @@ func TestWarmStateCache(t *testing.T) {
C: clock.NewMock(),
BaseInterval: time.Second,
Logger: log.New("ngalert cache warming test"),
Store: dbstore,
RuleStore: dbstore,
RuleStore: dbstore,
InstanceStore: dbstore,
}
sched := schedule.NewScheduler(schedCfg, nil)
st := state.NewManager(schedCfg.Logger, nilMetrics)
@ -143,9 +144,9 @@ func TestAlertingTicker(t *testing.T) {
StopAppliedFunc: func(alertDefKey models.AlertRuleKey) {
stopAppliedCh <- alertDefKey
},
Store: dbstore,
RuleStore: dbstore,
Logger: log.New("ngalert schedule test"),
RuleStore: dbstore,
InstanceStore: dbstore,
Logger: log.New("ngalert schedule test"),
}
sched := schedule.NewScheduler(schedCfg, nil)