mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(alerting): add state persister interface (#80384)
This commit is contained in:
committed by
GitHub
parent
2d49fb6a7a
commit
82638d059f
@@ -19,13 +19,10 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/expr"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/log/logtest"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/eval"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/metrics"
|
||||
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
// Not for parallel tests.
|
||||
@@ -82,84 +79,6 @@ func TestStateIsStale(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestManager_saveAlertStates(t *testing.T) {
|
||||
type stateWithReason struct {
|
||||
State eval.State
|
||||
Reason string
|
||||
}
|
||||
create := func(s eval.State, r string) stateWithReason {
|
||||
return stateWithReason{
|
||||
State: s,
|
||||
Reason: r,
|
||||
}
|
||||
}
|
||||
allStates := [...]stateWithReason{
|
||||
create(eval.Normal, ""),
|
||||
create(eval.Normal, eval.NoData.String()),
|
||||
create(eval.Normal, eval.Error.String()),
|
||||
create(eval.Normal, util.GenerateShortUID()),
|
||||
create(eval.Alerting, ""),
|
||||
create(eval.Pending, ""),
|
||||
create(eval.NoData, ""),
|
||||
create(eval.Error, ""),
|
||||
}
|
||||
|
||||
transitionToKey := map[ngmodels.AlertInstanceKey]StateTransition{}
|
||||
transitions := make([]StateTransition, 0)
|
||||
for _, fromState := range allStates {
|
||||
for i, toState := range allStates {
|
||||
tr := StateTransition{
|
||||
State: &State{
|
||||
State: toState.State,
|
||||
StateReason: toState.Reason,
|
||||
Labels: ngmodels.GenerateAlertLabels(5, fmt.Sprintf("%d--", i)),
|
||||
},
|
||||
PreviousState: fromState.State,
|
||||
PreviousStateReason: fromState.Reason,
|
||||
}
|
||||
key, err := tr.GetAlertInstanceKey()
|
||||
require.NoError(t, err)
|
||||
transitionToKey[key] = tr
|
||||
transitions = append(transitions, tr)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("should save all transitions if doNotSaveNormalState is false", func(t *testing.T) {
|
||||
st := &FakeInstanceStore{}
|
||||
m := Manager{instanceStore: st, doNotSaveNormalState: false, maxStateSaveConcurrency: 1}
|
||||
m.saveAlertStates(context.Background(), &logtest.Fake{}, transitions...)
|
||||
|
||||
savedKeys := map[ngmodels.AlertInstanceKey]ngmodels.AlertInstance{}
|
||||
for _, op := range st.RecordedOps {
|
||||
saved := op.(ngmodels.AlertInstance)
|
||||
savedKeys[saved.AlertInstanceKey] = saved
|
||||
}
|
||||
assert.Len(t, transitionToKey, len(savedKeys))
|
||||
|
||||
for key, tr := range transitionToKey {
|
||||
assert.Containsf(t, savedKeys, key, "state %s (%s) was not saved but should be", tr.State.State, tr.StateReason)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("should not save Normal->Normal if doNotSaveNormalState is true", func(t *testing.T) {
|
||||
st := &FakeInstanceStore{}
|
||||
m := Manager{instanceStore: st, doNotSaveNormalState: true, maxStateSaveConcurrency: 1}
|
||||
m.saveAlertStates(context.Background(), &logtest.Fake{}, transitions...)
|
||||
|
||||
savedKeys := map[ngmodels.AlertInstanceKey]ngmodels.AlertInstance{}
|
||||
for _, op := range st.RecordedOps {
|
||||
saved := op.(ngmodels.AlertInstance)
|
||||
savedKeys[saved.AlertInstanceKey] = saved
|
||||
}
|
||||
for key, tr := range transitionToKey {
|
||||
if tr.State.State == eval.Normal && tr.StateReason == "" && tr.PreviousState == eval.Normal && tr.PreviousStateReason == "" {
|
||||
continue
|
||||
}
|
||||
assert.Containsf(t, savedKeys, key, "state %s (%s) was not saved but should be", tr.State.State, tr.StateReason)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TestProcessEvalResults_StateTransitions tests how state.Manager's ProcessEvalResults processes results and creates or changes states.
|
||||
// In other words, it tests the state transition.
|
||||
//
|
||||
@@ -328,19 +247,18 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
|
||||
|
||||
testMetrics := metrics.NewNGAlert(prometheus.NewPedanticRegistry()).GetStateMetrics()
|
||||
cfg := ManagerCfg{
|
||||
Metrics: testMetrics,
|
||||
Tracer: tracing.InitializeTracerForTest(),
|
||||
Log: log.New("ngalert.state.manager"),
|
||||
ExternalURL: nil,
|
||||
InstanceStore: &FakeInstanceStore{},
|
||||
Images: &NotAvailableImageService{},
|
||||
Clock: clk,
|
||||
Historian: &FakeHistorian{},
|
||||
MaxStateSaveConcurrency: 1,
|
||||
Metrics: testMetrics,
|
||||
Tracer: tracing.InitializeTracerForTest(),
|
||||
Log: log.New("ngalert.state.manager"),
|
||||
ExternalURL: nil,
|
||||
InstanceStore: &FakeInstanceStore{},
|
||||
Images: &NotAvailableImageService{},
|
||||
Clock: clk,
|
||||
Historian: &FakeHistorian{},
|
||||
|
||||
ApplyNoDataAndErrorToAllStates: applyNoDataErrorToAllStates,
|
||||
}
|
||||
st := NewManager(cfg)
|
||||
st := NewManager(cfg, NewNoopPersister())
|
||||
|
||||
tss := make([]time.Time, 0, len(resultsAtTime))
|
||||
for ts, results := range resultsAtTime {
|
||||
|
||||
Reference in New Issue
Block a user