Alerting: Add "Keep Last State" backend functionality (#83940)

* Implement keep last state for state transitions

* Respect For duration when keeping state

* Only keep transition from recording an annotation

* Add keep last state option for nodata/error in UI
This commit is contained in:
William Wernert
2024-03-12 10:00:43 -04:00
committed by GitHub
parent fe1ed0a9e1
commit 10dc6c6d75
10 changed files with 988 additions and 35 deletions

View File

@@ -812,6 +812,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
ngmodels.NoData: baseRuleWith(ngmodels.WithNoDataExecAs(ngmodels.NoData)),
ngmodels.Alerting: baseRuleWith(ngmodels.WithNoDataExecAs(ngmodels.Alerting)),
ngmodels.OK: baseRuleWith(ngmodels.WithNoDataExecAs(ngmodels.OK)),
ngmodels.KeepLast: baseRuleWith(ngmodels.WithNoDataExecAs(ngmodels.KeepLast)),
}
type noDataTestCase struct {
@@ -919,6 +920,24 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLast: {
t1: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule + no-data"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t1, eval.NoData),
},
StartsAt: t1,
EndsAt: t1,
LastEvaluationTime: t1,
},
},
},
},
},
},
{
@@ -985,6 +1004,24 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLast: {
t2: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule + no-data"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t2, eval.NoData),
},
StartsAt: t2,
EndsAt: t2,
LastEvaluationTime: t2,
},
},
},
},
},
expectedTransitionsApplyNoDataErrorToAllStates: map[ngmodels.NoDataState]map[time.Time][]StateTransition{
ngmodels.Alerting: {
@@ -1025,6 +1062,25 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLast: {
t2: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule + labels1"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t1, eval.Normal),
newEvaluation(t2, eval.NoData),
},
StartsAt: t1,
EndsAt: t1,
LastEvaluationTime: t2,
},
},
},
},
},
},
{
@@ -1202,6 +1258,55 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLast: {
t3: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule + labels1"],
State: eval.Normal,
StateReason: ngmodels.StateReasonMissingSeries,
Results: []Evaluation{
newEvaluation(t1, eval.Normal),
},
StartsAt: t1,
EndsAt: t3,
LastEvaluationTime: t3,
},
},
{
PreviousState: eval.Alerting,
State: &State{
Labels: labels["system + rule + labels2"],
State: eval.Normal,
StateReason: ngmodels.StateReasonMissingSeries,
Results: []Evaluation{
newEvaluation(t1, eval.Alerting),
},
StartsAt: t1,
EndsAt: t3,
LastEvaluationTime: t3,
Resolved: true,
},
},
{
PreviousState: eval.Normal,
PreviousStateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
State: &State{
Labels: labels["system + rule + no-data"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t2, eval.NoData),
newEvaluation(t3, eval.NoData),
},
StartsAt: t2,
EndsAt: t2,
LastEvaluationTime: t3,
},
},
},
},
},
expectedTransitionsApplyNoDataErrorToAllStates: map[ngmodels.NoDataState]map[time.Time][]StateTransition{
ngmodels.Alerting: {
@@ -1345,6 +1450,76 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLast: {
t2: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule + labels1"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t1, eval.Normal),
newEvaluation(t2, eval.NoData),
},
StartsAt: t1,
EndsAt: t1,
LastEvaluationTime: t2,
},
},
{
PreviousState: eval.Alerting,
State: &State{
Labels: labels["system + rule + labels2"],
State: eval.Alerting,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t1, eval.Alerting),
newEvaluation(t2, eval.NoData),
},
StartsAt: t1,
EndsAt: t2.Add(ResendDelay * 4),
LastEvaluationTime: t2,
},
},
},
t3: {
{
PreviousState: eval.Normal,
PreviousStateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
State: &State{
Labels: labels["system + rule + labels1"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t1, eval.Normal),
newEvaluation(t2, eval.NoData),
newEvaluation(t3, eval.NoData),
},
StartsAt: t1,
EndsAt: t1,
LastEvaluationTime: t3,
},
},
{
PreviousState: eval.Alerting,
PreviousStateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
State: &State{
Labels: labels["system + rule + labels2"],
State: eval.Alerting,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t1, eval.Alerting),
newEvaluation(t2, eval.NoData),
newEvaluation(t3, eval.NoData),
},
StartsAt: t1,
EndsAt: t3.Add(ResendDelay * 4),
LastEvaluationTime: t3,
},
},
},
},
},
},
{
@@ -1533,6 +1708,53 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLast: {
t3: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule + labels1"],
State: eval.Normal,
StateReason: ngmodels.StateReasonMissingSeries,
Results: []Evaluation{
newEvaluation(t1, eval.Normal),
},
StartsAt: t1,
EndsAt: t3,
LastEvaluationTime: t3,
},
},
{
PreviousState: eval.Pending,
State: &State{
Labels: labels["system + rule + labels2"],
State: eval.Normal,
StateReason: ngmodels.StateReasonMissingSeries,
Results: []Evaluation{
newEvaluation(t1, eval.Alerting),
},
StartsAt: t1,
EndsAt: t3,
LastEvaluationTime: t3,
},
},
{
PreviousState: eval.Normal,
PreviousStateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
State: &State{
Labels: labels["system + rule + no-data"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t3, eval.NoData),
},
StartsAt: t2,
EndsAt: t2,
LastEvaluationTime: t3,
},
},
},
},
},
expectedTransitionsApplyNoDataErrorToAllStates: map[ngmodels.NoDataState]map[time.Time][]StateTransition{
ngmodels.Alerting: {
@@ -1663,6 +1885,70 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLast: {
t2: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule + labels1"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t2, eval.NoData),
},
StartsAt: t1,
EndsAt: t1,
LastEvaluationTime: t2,
},
},
{
PreviousState: eval.Pending,
State: &State{
Labels: labels["system + rule + labels2"],
State: eval.Alerting,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t2, eval.NoData),
},
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
LastEvaluationTime: t2,
},
},
},
t3: {
{
PreviousState: eval.Normal,
PreviousStateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
State: &State{
Labels: labels["system + rule + labels1"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t3, eval.NoData),
},
StartsAt: t1,
EndsAt: t1,
LastEvaluationTime: t3,
},
},
{
PreviousState: eval.Alerting,
PreviousStateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
State: &State{
Labels: labels["system + rule + labels2"],
State: eval.Alerting,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t3, eval.NoData),
},
StartsAt: t2,
EndsAt: t3.Add(ResendDelay * 4),
LastEvaluationTime: t3,
},
},
},
},
},
},
{
@@ -1734,6 +2020,24 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLast: {
t3: {
{
PreviousState: eval.Pending,
State: &State{
Labels: labels["system + rule + labels1"],
State: eval.Alerting,
Results: []Evaluation{
newEvaluation(t1, eval.Alerting),
newEvaluation(t3, eval.Alerting),
},
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
LastEvaluationTime: t3,
},
},
},
},
},
expectedTransitionsApplyNoDataErrorToAllStates: map[ngmodels.NoDataState]map[time.Time][]StateTransition{
ngmodels.Alerting: {
@@ -1774,6 +2078,25 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLast: {
t3: {
{
PreviousState: eval.Pending,
PreviousStateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
State: &State{
Labels: labels["system + rule + labels1"],
State: eval.Alerting,
Results: []Evaluation{
newEvaluation(t2, eval.NoData),
newEvaluation(t3, eval.Alerting),
},
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
LastEvaluationTime: t3,
},
},
},
},
},
},
{
@@ -1889,6 +2212,39 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLast: {
t3: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule + labels1"],
State: eval.Normal,
Results: []Evaluation{
newEvaluation(t2, eval.Normal),
newEvaluation(t3, eval.Normal),
},
StartsAt: t2,
EndsAt: t2,
LastEvaluationTime: t3,
},
},
{
PreviousState: eval.Normal,
PreviousStateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
State: &State{
Labels: labels["system + rule + no-data"],
State: eval.Normal,
StateReason: ngmodels.StateReasonMissingSeries,
Results: []Evaluation{
newEvaluation(t1, eval.NoData),
},
StartsAt: t1,
EndsAt: t3,
LastEvaluationTime: t3,
},
},
},
},
},
},
{
@@ -1955,6 +2311,24 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLast: {
t2: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule + no-data"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t2, eval.NoData),
},
StartsAt: t2,
EndsAt: t2,
LastEvaluationTime: t2,
},
},
},
},
},
expectedTransitionsApplyNoDataErrorToAllStates: map[ngmodels.NoDataState]map[time.Time][]StateTransition{
ngmodels.Alerting: {
@@ -1995,10 +2369,29 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLast: {
t2: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t1, eval.Normal),
newEvaluation(t2, eval.NoData),
},
StartsAt: t1,
EndsAt: t1,
LastEvaluationTime: t2,
},
},
},
},
},
},
{
desc: "t1[{}:alerting] t2[NoData] t3[NoData] at t3",
desc: "t1[{}:alerting] t2[NoData] t3[NoData] at t2,t3",
results: map[time.Time]eval.Results{
t1: {
newResult(eval.WithState(eval.Alerting)),
@@ -2129,6 +2522,41 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLast: {
t3: {
{
PreviousState: eval.Alerting,
State: &State{
Labels: labels["system + rule"],
State: eval.Normal,
StateReason: ngmodels.StateReasonMissingSeries,
Results: []Evaluation{
newEvaluation(t1, eval.Alerting),
},
StartsAt: t1,
EndsAt: t3,
LastEvaluationTime: t3,
Resolved: true,
},
},
{
PreviousState: eval.Normal,
PreviousStateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
State: &State{
Labels: labels["system + rule + no-data"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t2, eval.NoData),
newEvaluation(t3, eval.NoData),
},
StartsAt: t2,
EndsAt: t2,
LastEvaluationTime: t3,
},
},
},
},
},
expectedTransitionsApplyNoDataErrorToAllStates: map[ngmodels.NoDataState]map[time.Time][]StateTransition{
ngmodels.Alerting: {
@@ -2208,6 +2636,44 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLast: {
t2: {
{
PreviousState: eval.Alerting,
State: &State{
Labels: labels["system + rule"],
State: eval.Alerting,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t1, eval.Alerting),
newEvaluation(t2, eval.NoData),
},
StartsAt: t1,
EndsAt: t2.Add(ResendDelay * 4),
LastEvaluationTime: t2,
},
},
},
t3: {
{
PreviousState: eval.Alerting,
PreviousStateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
State: &State{
Labels: labels["system + rule"],
State: eval.Alerting,
StateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t1, eval.Alerting),
newEvaluation(t2, eval.NoData),
newEvaluation(t3, eval.NoData),
},
StartsAt: t1,
EndsAt: t3.Add(ResendDelay * 4),
LastEvaluationTime: t3,
},
},
},
},
},
},
{
@@ -2294,6 +2760,24 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLast: {
t3: {
{
PreviousState: eval.Pending,
State: &State{
Labels: labels["system + rule"],
State: eval.Alerting,
Results: []Evaluation{
newEvaluation(t1, eval.Alerting),
newEvaluation(t3, eval.Alerting),
},
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
LastEvaluationTime: t3,
},
},
},
},
},
expectedTransitionsApplyNoDataErrorToAllStates: map[ngmodels.NoDataState]map[time.Time][]StateTransition{
ngmodels.Alerting: {
@@ -2334,6 +2818,25 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLast: {
t3: {
{
PreviousState: eval.Pending,
PreviousStateReason: ngmodels.ConcatReasons(eval.NoData.String(), ngmodels.StateReasonKeepLast),
State: &State{
Labels: labels["system + rule"],
State: eval.Alerting,
Results: []Evaluation{
newEvaluation(t2, eval.NoData),
newEvaluation(t3, eval.Alerting),
},
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
LastEvaluationTime: t3,
},
},
},
},
},
},
}
@@ -2350,6 +2853,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
ngmodels.ErrorErrState: baseRuleWith(ngmodels.WithErrorExecAs(ngmodels.ErrorErrState)),
ngmodels.AlertingErrState: baseRuleWith(ngmodels.WithErrorExecAs(ngmodels.AlertingErrState)),
ngmodels.OkErrState: baseRuleWith(ngmodels.WithErrorExecAs(ngmodels.OkErrState)),
ngmodels.KeepLastErrState: baseRuleWith(ngmodels.WithErrorExecAs(ngmodels.KeepLastErrState)),
}
cacheID := func(lbls data.Labels) string {
@@ -2472,6 +2976,24 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLastErrState: {
t1: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.Error.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t1, eval.Error),
},
StartsAt: t1,
EndsAt: t1,
LastEvaluationTime: t1,
},
},
},
},
},
},
{
@@ -2540,6 +3062,24 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLastErrState: {
t1: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.Error.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t1, eval.Error),
},
StartsAt: t1,
EndsAt: t1,
LastEvaluationTime: t1,
},
},
},
},
},
},
{
@@ -2613,6 +3153,24 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLastErrState: {
t2: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.Error.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t2, eval.Error),
},
StartsAt: t2,
EndsAt: t2,
LastEvaluationTime: t2,
},
},
},
},
},
expectedTransitionsApplyNoDataErrorToAllStates: map[ngmodels.ExecutionErrorState]map[time.Time][]StateTransition{
ngmodels.AlertingErrState: {
@@ -2652,6 +3210,24 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLastErrState: {
t2: {
{
PreviousState: eval.Pending,
State: &State{
Labels: labels["system + rule + labels1"],
State: eval.Alerting,
StateReason: ngmodels.ConcatReasons(eval.Error.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t2, eval.Error),
},
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
LastEvaluationTime: t2,
},
},
},
},
},
},
{
@@ -2724,6 +3300,24 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLastErrState: {
t2: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.Error.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t2, eval.Error),
},
StartsAt: t2,
EndsAt: t2,
LastEvaluationTime: t2,
},
},
},
},
},
expectedTransitionsApplyNoDataErrorToAllStates: map[ngmodels.ExecutionErrorState]map[time.Time][]StateTransition{
ngmodels.AlertingErrState: {
@@ -2765,6 +3359,25 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLastErrState: {
t2: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule + labels1"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.Error.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t1, eval.Normal),
newEvaluation(t2, eval.Error),
},
StartsAt: t1,
EndsAt: t1,
LastEvaluationTime: t2,
},
},
},
},
},
},
{
@@ -2886,6 +3499,39 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLastErrState: {
t3: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule + labels1"],
State: eval.Normal,
Results: []Evaluation{
newEvaluation(t2, eval.Normal),
newEvaluation(t3, eval.Normal),
},
StartsAt: t2,
EndsAt: t2,
LastEvaluationTime: t3,
},
},
{
PreviousState: eval.Normal,
PreviousStateReason: ngmodels.ConcatReasons(eval.Error.String(), ngmodels.StateReasonKeepLast),
State: &State{
Labels: labels["system + rule"],
State: eval.Normal,
StateReason: ngmodels.StateReasonMissingSeries,
Results: []Evaluation{
newEvaluation(t1, eval.Error),
},
StartsAt: t1,
EndsAt: t3,
LastEvaluationTime: t3,
},
},
},
},
},
},
{
@@ -2961,6 +3607,25 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLastErrState: {
t2: {
{
PreviousState: eval.Normal,
State: &State{
Labels: labels["system + rule"],
State: eval.Normal,
StateReason: ngmodels.ConcatReasons(eval.Error.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t1, eval.Normal),
newEvaluation(t2, eval.Error),
},
StartsAt: t1,
EndsAt: t1,
LastEvaluationTime: t2,
},
},
},
},
},
},
{
@@ -3049,6 +3714,24 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLastErrState: {
t2: {
{
PreviousState: eval.Pending,
State: &State{
Labels: labels["system + rule"],
State: eval.Alerting,
StateReason: ngmodels.ConcatReasons(eval.Error.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t2, eval.Error),
},
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
LastEvaluationTime: t2,
},
},
},
},
},
},
{
@@ -3178,6 +3861,42 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLastErrState: {
t2: {
{
PreviousState: eval.Pending,
State: &State{
Labels: labels["system + rule"],
State: eval.Pending,
StateReason: ngmodels.ConcatReasons(eval.Error.String(), ngmodels.StateReasonKeepLast),
Results: []Evaluation{
newEvaluation(t1, eval.Alerting),
newEvaluation(t2, eval.Error),
},
StartsAt: t1,
EndsAt: t1.Add(ResendDelay * 4),
LastEvaluationTime: t2,
},
},
},
t3: {
{
PreviousState: eval.Pending,
PreviousStateReason: ngmodels.ConcatReasons(eval.Error.String(), ngmodels.StateReasonKeepLast),
State: &State{
Labels: labels["system + rule"],
State: eval.Alerting,
Results: []Evaluation{
newEvaluation(t2, eval.Error),
newEvaluation(t3, eval.Alerting),
},
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
LastEvaluationTime: t3,
},
},
},
},
},
},
{
@@ -3248,6 +3967,25 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
},
},
},
ngmodels.KeepLastErrState: {
t2: {
{
PreviousState: eval.Normal,
PreviousStateReason: ngmodels.ConcatReasons(eval.Error.String(), ngmodels.StateReasonKeepLast),
State: &State{
Labels: labels["system + rule"],
State: eval.Normal,
Results: []Evaluation{
newEvaluation(t1, eval.Error),
newEvaluation(t2, eval.Normal),
},
StartsAt: t1,
EndsAt: t1,
LastEvaluationTime: t2,
},
},
},
},
},
},
}