Alerting: Persist alert instance FiredAt field (#105927)

* Persist alert instance fired at

* Update protos and tests
This commit is contained in:
Fayzal Ghantiwala
2025-05-27 10:04:26 +01:00
committed by GitHub
parent e3326713f6
commit 589046bcdc
18 changed files with 186 additions and 140 deletions
+1
View File
@@ -15,6 +15,7 @@ type AlertInstance struct {
CurrentStateEnd time.Time
LastEvalTime time.Time
LastSentAt *time.Time
FiredAt *time.Time
ResolvedAt *time.Time
ResultFingerprint string
}
+1
View File
@@ -296,6 +296,7 @@ func (c *cache) GetAlertInstances() []ngModels.AlertInstance {
LastEvalTime: v2.LastEvaluationTime,
CurrentStateSince: v2.StartsAt,
CurrentStateEnd: v2.EndsAt,
FiredAt: v2.FiredAt,
ResolvedAt: v2.ResolvedAt,
LastSentAt: v2.LastSentAt,
ResultFingerprint: v2.ResultFingerprint.String(),
+3 -1
View File
@@ -91,7 +91,9 @@ func StateToPostableAlert(transition StateTransition, appURL *url.URL, featureTo
startsAt := strfmt.DateTime(alertState.StartsAt)
if featureToggles.IsEnabledGlobally(featuremgmt.FlagAlertRuleUseFiredAtForStartsAt) {
startsAt = strfmt.DateTime(alertState.FiredAt)
if alertState.FiredAt != nil {
startsAt = strfmt.DateTime(*alertState.FiredAt)
}
}
return &models.PostableAlert{
+2 -2
View File
@@ -106,7 +106,7 @@ func Test_StateToPostableAlert(t *testing.T) {
// feature flag is enabled
result = StateToPostableAlert(alertState, appURL, featuremgmt.WithFeatures(featuremgmt.FlagAlertRuleUseFiredAtForStartsAt))
require.Equal(t, strfmt.DateTime(alertState.FiredAt), result.StartsAt)
require.Equal(t, strfmt.DateTime(*alertState.FiredAt), result.StartsAt)
})
t.Run("should copy annotations", func(t *testing.T) {
@@ -361,7 +361,7 @@ func randomTransition(from, to eval.State) StateTransition {
State: to,
AlertRuleUID: util.GenerateShortUID(),
StartsAt: time.Now(),
FiredAt: randomTimeInPast(),
FiredAt: util.Pointer(randomTimeInPast()),
EndsAt: randomTimeInFuture(),
LastEvaluationTime: randomTimeInPast(),
EvaluationDuration: randomDuration(),
+1
View File
@@ -206,6 +206,7 @@ func (st *Manager) Warm(ctx context.Context, orgReader OrgReader, rulesReader Ru
LastEvaluationString: "",
StartsAt: entry.CurrentStateSince,
EndsAt: entry.CurrentStateEnd,
FiredAt: entry.FiredAt,
LastEvaluationTime: entry.LastEvalTime,
Annotations: annotations,
ResultFingerprint: resultFp,
@@ -428,7 +428,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t1.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t1,
LastSentAt: &t1,
},
@@ -506,7 +506,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.Alerting),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t2,
LastSentAt: &t2,
},
@@ -575,7 +575,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Alerting),
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t3,
FiredAt: &t3,
LastEvaluationTime: t3,
LastSentAt: &t3,
},
@@ -630,7 +630,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.Normal),
StartsAt: t2,
EndsAt: t2,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
ResolvedAt: &t2,
LastSentAt: &t2,
@@ -691,7 +691,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t3,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
ResolvedAt: &t3,
LastSentAt: &t3,
@@ -753,7 +753,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t1.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t1,
LastSentAt: &t1,
},
@@ -812,7 +812,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t1.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t1,
LastSentAt: &t1,
},
@@ -827,7 +827,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.Normal),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
LastSentAt: &t1,
},
@@ -842,7 +842,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Normal),
StartsAt: t2,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
LastSentAt: &t1,
},
@@ -857,7 +857,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t4, eval.Normal),
StartsAt: t4,
EndsAt: t4,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t4,
LastSentAt: &t4,
ResolvedAt: &t4,
@@ -890,7 +890,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t1.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t1,
LastSentAt: &t1,
},
@@ -905,7 +905,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.Normal),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
LastSentAt: &t1,
},
@@ -920,7 +920,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Alerting),
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t3,
FiredAt: &t3,
LastEvaluationTime: t3,
LastSentAt: &t1,
},
@@ -955,7 +955,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.Alerting),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t2,
LastSentAt: &t2,
},
@@ -970,7 +970,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Normal),
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t3,
LastSentAt: &t2,
},
@@ -985,7 +985,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t4, eval.Alerting),
StartsAt: t4,
EndsAt: t4.Add(ResendDelay * 4),
FiredAt: t4,
FiredAt: &t4,
LastEvaluationTime: t4,
LastSentAt: &t2,
},
@@ -1017,7 +1017,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t1.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t1,
LastSentAt: &t1,
},
@@ -1061,7 +1061,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t3,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
ResolvedAt: &t3,
LastSentAt: &t3,
@@ -1126,7 +1126,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t4,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t4,
ResolvedAt: &t4,
LastSentAt: &t4,
@@ -1159,7 +1159,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t1.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t1,
LastSentAt: &t1,
},
@@ -1189,7 +1189,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t2,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
ResolvedAt: &t2,
LastSentAt: &t2,
@@ -1237,7 +1237,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t1.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t1,
LastSentAt: &t1,
},
@@ -1250,7 +1250,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t1.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t1,
LastSentAt: &t1,
},
@@ -1265,7 +1265,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.Alerting),
StartsAt: t1,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
LastSentAt: &t1,
},
@@ -1281,7 +1281,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t2,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
ResolvedAt: &t2,
LastSentAt: &t2,
@@ -1297,7 +1297,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Alerting),
StartsAt: t1,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
LastSentAt: &t1,
},
@@ -1326,7 +1326,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.Alerting),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t2,
LastSentAt: &t2,
},
@@ -1410,7 +1410,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.NoData),
StartsAt: t1,
EndsAt: t1.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t1,
LastSentAt: &t1,
},
@@ -1495,7 +1495,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluationWithValues(t2, eval.NoData, map[string]float64{"A": float64(-1)}),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t2,
LastSentAt: &t2,
Values: map[string]float64{"A": float64(-1)},
@@ -1593,7 +1593,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t3,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
ResolvedAt: &t3,
LastSentAt: &t3,
@@ -1625,7 +1625,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.NoData),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t2,
LastSentAt: &t2,
},
@@ -1640,7 +1640,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.NoData),
StartsAt: t1,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
LastSentAt: &t1,
},
@@ -1658,7 +1658,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.NoData),
StartsAt: t2,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t3,
LastSentAt: &t2,
},
@@ -1674,7 +1674,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.NoData),
StartsAt: t1,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
LastSentAt: &t1,
},
@@ -1706,7 +1706,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.NoData),
StartsAt: t2,
EndsAt: t2,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
ResolvedAt: &t2,
LastSentAt: &t2,
@@ -1739,7 +1739,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.NoData),
StartsAt: t2,
EndsAt: t2,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
ResolvedAt: &t2,
LastSentAt: &t2,
@@ -1772,7 +1772,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.NoData),
StartsAt: t1,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
LastSentAt: &t1,
},
@@ -1804,7 +1804,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.NoData),
StartsAt: t1,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
LastSentAt: &t1,
},
@@ -1908,7 +1908,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.NoData),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t2,
LastSentAt: &t2,
},
@@ -1926,7 +1926,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.NoData),
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t3,
FiredAt: &t3,
LastEvaluationTime: t3,
LastSentAt: &t3,
},
@@ -1942,7 +1942,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.NoData),
StartsAt: t2,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t3,
LastSentAt: &t2,
},
@@ -2034,7 +2034,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.NoData),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t2,
LastSentAt: &t2,
},
@@ -2066,7 +2066,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.NoData),
StartsAt: t2,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t3,
LastSentAt: &t2,
},
@@ -2100,7 +2100,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Alerting),
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t3,
FiredAt: &t3,
LastEvaluationTime: t3,
LastSentAt: &t3,
},
@@ -2118,7 +2118,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Alerting),
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t3,
FiredAt: &t3,
LastEvaluationTime: t3,
LastSentAt: &t3,
},
@@ -2152,7 +2152,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Alerting),
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t3,
FiredAt: &t3,
LastEvaluationTime: t3,
LastSentAt: &t3,
},
@@ -2205,7 +2205,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t3,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
ResolvedAt: &t3,
LastSentAt: &t3,
@@ -2253,7 +2253,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.NoData),
StartsAt: t1,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
LastSentAt: &t1,
},
@@ -2271,7 +2271,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.NoData),
StartsAt: t1,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
LastSentAt: &t1,
},
@@ -2289,7 +2289,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t4, eval.NoData),
StartsAt: t1,
EndsAt: t4.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t4,
LastSentAt: &t4,
},
@@ -2308,7 +2308,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.NoData),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
LastSentAt: &t1,
},
@@ -2326,7 +2326,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.NoData),
StartsAt: t2,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
LastSentAt: &t1,
},
@@ -2344,7 +2344,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t4, eval.NoData),
StartsAt: t4,
EndsAt: t4,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t4,
LastSentAt: &t4,
ResolvedAt: &t4,
@@ -2364,7 +2364,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.NoData),
StartsAt: t1,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
LastSentAt: &t1,
},
@@ -2382,7 +2382,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.NoData),
StartsAt: t1,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
LastSentAt: &t1,
},
@@ -2400,7 +2400,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t4, eval.NoData),
StartsAt: t1,
EndsAt: t4.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t4,
LastSentAt: &t4,
},
@@ -2514,7 +2514,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.NoData),
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t3,
FiredAt: &t3,
LastEvaluationTime: t3,
LastSentAt: &t3,
},
@@ -2530,7 +2530,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t4, eval.Normal),
StartsAt: t4,
EndsAt: t4.Add(ResendDelay * 4),
FiredAt: t3,
FiredAt: &t3,
LastEvaluationTime: t4,
LastSentAt: &t3,
},
@@ -2546,7 +2546,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t5, eval.NoData),
StartsAt: t5,
EndsAt: t5.Add(ResendDelay * 4),
FiredAt: t5,
FiredAt: &t5,
LastEvaluationTime: t5,
LastSentAt: &t3,
Annotations: mergeLabels(baseRule.Annotations, noDataAnnotations),
@@ -2716,7 +2716,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.NoData),
StartsAt: t1,
EndsAt: t3,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
ResolvedAt: &t3,
LastSentAt: &t3,
@@ -2821,7 +2821,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.NoData),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t2,
LastSentAt: &t2,
},
@@ -2903,7 +2903,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t3,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
ResolvedAt: &t3,
LastSentAt: &t3,
@@ -2935,7 +2935,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.NoData),
StartsAt: t1,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
LastSentAt: &t1,
},
@@ -2953,7 +2953,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.NoData),
StartsAt: t1,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
LastSentAt: &t1,
},
@@ -2972,7 +2972,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.NoData),
StartsAt: t2,
EndsAt: t2,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
ResolvedAt: &t2,
LastSentAt: &t2,
@@ -2991,7 +2991,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.NoData),
StartsAt: t2,
EndsAt: t2,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
ResolvedAt: &t2,
LastSentAt: &t2,
@@ -3011,7 +3011,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.NoData),
StartsAt: t1,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
LastSentAt: &t1,
},
@@ -3029,7 +3029,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.NoData),
StartsAt: t1,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
LastSentAt: &t1,
},
@@ -3077,7 +3077,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Alerting),
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t3,
FiredAt: &t3,
LastEvaluationTime: t3,
LastSentAt: &t3,
},
@@ -3110,7 +3110,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Alerting),
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t3,
FiredAt: &t3,
LastEvaluationTime: t3,
LastSentAt: &t3,
},
@@ -3174,7 +3174,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Alerting),
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t3,
FiredAt: &t3,
LastEvaluationTime: t3,
LastSentAt: &t3,
},
@@ -3267,7 +3267,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Error),
StartsAt: t1,
EndsAt: t1.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t1,
LastSentAt: &t1,
},
@@ -3349,7 +3349,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Error),
StartsAt: t1,
EndsAt: t1.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t1,
LastSentAt: &t1,
},
@@ -3438,7 +3438,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluationWithValues(t2, eval.Error, map[string]float64{"A": float64(-1)}),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t2,
LastSentAt: &t2,
Values: map[string]float64{"A": float64(-1)},
@@ -3476,7 +3476,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluationWithValues(t2, eval.Error, map[string]float64{"A": float64(-1)}),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t2,
LastSentAt: &t2,
Values: map[string]float64{"A": float64(-1)},
@@ -3531,7 +3531,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluationWithValues(t2, eval.Error, map[string]float64{"A": float64(-1)}),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t2,
LastSentAt: &t2,
Values: map[string]float64{"A": float64(-1)},
@@ -3650,7 +3650,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Error),
StartsAt: t1,
EndsAt: t3,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
ResolvedAt: &t3,
LastSentAt: &t3,
@@ -3791,7 +3791,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.Normal),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
LastSentAt: &t1,
},
@@ -3806,7 +3806,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Normal),
StartsAt: t2,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
LastSentAt: &t1,
},
@@ -3821,7 +3821,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t4, eval.Normal),
StartsAt: t4,
EndsAt: t4,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t4,
ResolvedAt: &t4,
LastSentAt: &t4,
@@ -4000,7 +4000,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.Error),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t2,
LastSentAt: &t2,
Annotations: datasourceErrorAnnotations,
@@ -4017,7 +4017,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Normal),
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t3,
LastSentAt: &t2,
},
@@ -4034,7 +4034,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t4, eval.Error),
StartsAt: t4,
EndsAt: t4.Add(ResendDelay * 4),
FiredAt: t4,
FiredAt: &t4,
LastEvaluationTime: t4,
LastSentAt: &t2,
Annotations: datasourceErrorAnnotations,
@@ -4183,7 +4183,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.Error),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t2,
LastSentAt: &t2,
},
@@ -4285,7 +4285,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.Error),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t2,
LastSentAt: &t2,
},
@@ -4321,7 +4321,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.Error),
StartsAt: t2,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t2,
LastSentAt: &t2,
},
@@ -4407,7 +4407,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Alerting),
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t3,
FiredAt: &t3,
LastEvaluationTime: t3,
LastSentAt: &t3,
},
@@ -4471,7 +4471,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Alerting),
StartsAt: t3,
EndsAt: t3.Add(ResendDelay * 4),
FiredAt: t3,
FiredAt: &t3,
LastEvaluationTime: t3,
LastSentAt: &t3,
},
@@ -4518,7 +4518,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.Normal),
StartsAt: t2,
EndsAt: t2,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
ResolvedAt: &t2,
LastSentAt: &t2,
@@ -4623,7 +4623,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Error),
StartsAt: t1,
EndsAt: t1.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t1,
LastSentAt: &t1,
},
@@ -4642,7 +4642,7 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
LatestResult: newEvaluation(t2, eval.Error),
StartsAt: t1,
EndsAt: t2.Add(ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
LastSentAt: &t1,
},
+15 -15
View File
@@ -476,7 +476,7 @@ func TestProcessEvalResults(t *testing.T) {
LatestResult: newEvaluation(t1, eval.Alerting),
StartsAt: t1,
EndsAt: t1.Add(state.ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t1,
LastSentAt: &t1,
},
@@ -525,7 +525,7 @@ func TestProcessEvalResults(t *testing.T) {
LatestResult: newEvaluation(t2, eval.Alerting),
StartsAt: t2,
EndsAt: t2.Add(state.ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t2,
LastSentAt: &t2,
},
@@ -557,7 +557,7 @@ func TestProcessEvalResults(t *testing.T) {
LatestResult: newEvaluation(tn(4), eval.Alerting),
StartsAt: tn(4),
EndsAt: tn(4).Add(state.ResendDelay * 4),
FiredAt: tn(4),
FiredAt: util.Pointer(tn(4)),
LastEvaluationTime: tn(4),
LastSentAt: util.Pointer(tn(4)),
},
@@ -583,7 +583,7 @@ func TestProcessEvalResults(t *testing.T) {
LatestResult: newEvaluation(t2, eval.Normal),
StartsAt: t2,
EndsAt: t2,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t2,
ResolvedAt: &t2,
LastSentAt: &t2,
@@ -613,7 +613,7 @@ func TestProcessEvalResults(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Normal),
StartsAt: t2,
EndsAt: t2,
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t3,
ResolvedAt: &t2,
LastSentAt: &t2,
@@ -646,7 +646,7 @@ func TestProcessEvalResults(t *testing.T) {
LatestResult: newEvaluation(tn(4), eval.Alerting),
StartsAt: tn(4),
EndsAt: tn(4).Add(state.ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: tn(4),
ResolvedAt: &t3,
LastSentAt: &t3,
@@ -713,7 +713,7 @@ func TestProcessEvalResults(t *testing.T) {
LatestResult: newEvaluation(tn(4), eval.NoData),
StartsAt: tn(4),
EndsAt: tn(4).Add(state.ResendDelay * 4),
FiredAt: t3,
FiredAt: &t3,
LastEvaluationTime: tn(4),
LastSentAt: &t3, // Resend delay is 30s, so last sent at is t3.
},
@@ -967,7 +967,7 @@ func TestProcessEvalResults(t *testing.T) {
LatestResult: newEvaluation(tn(5), eval.Error),
StartsAt: tn(5),
EndsAt: tn(5).Add(state.ResendDelay * 4),
FiredAt: tn(5),
FiredAt: util.Pointer(tn(5)),
LastEvaluationTime: tn(5),
LastSentAt: util.Pointer(tn(5)),
},
@@ -1035,7 +1035,7 @@ func TestProcessEvalResults(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Alerting),
StartsAt: t3,
EndsAt: t3.Add(state.ResendDelay * 4),
FiredAt: t3,
FiredAt: &t3,
LastEvaluationTime: t3,
LastSentAt: &t1, // Resend delay is 30s, so last sent at is t1.
},
@@ -1067,7 +1067,7 @@ func TestProcessEvalResults(t *testing.T) {
}),
StartsAt: t1,
EndsAt: t1.Add(state.ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t1,
LastSentAt: &t1,
Values: map[string]float64{
@@ -1103,7 +1103,7 @@ func TestProcessEvalResults(t *testing.T) {
}),
StartsAt: t1,
EndsAt: t1.Add(state.ResendDelay * 4),
FiredAt: t1,
FiredAt: &t1,
LastEvaluationTime: t1,
LastSentAt: &t1,
Values: map[string]float64{
@@ -1136,7 +1136,7 @@ func TestProcessEvalResults(t *testing.T) {
LatestResult: newEvaluation(t3, eval.Normal),
StartsAt: t3,
EndsAt: t3.Add(state.ResendDelay * 4),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: t3,
LastSentAt: util.Pointer(t2),
},
@@ -1171,7 +1171,7 @@ func TestProcessEvalResults(t *testing.T) {
LatestResult: newEvaluation(tn(5), eval.Normal),
StartsAt: tn(5),
EndsAt: tn(5),
FiredAt: t2,
FiredAt: &t2,
LastEvaluationTime: tn(5),
LastSentAt: util.Pointer(tn(5)),
ResolvedAt: util.Pointer(tn(5)),
@@ -1210,7 +1210,7 @@ func TestProcessEvalResults(t *testing.T) {
LatestResult: newEvaluation(tn(6), eval.Normal),
StartsAt: tn(6),
EndsAt: tn(6).Add(state.ResendDelay * 4),
FiredAt: tn(4),
FiredAt: util.Pointer(tn(4)),
LastEvaluationTime: tn(6),
LastSentAt: util.Pointer(tn(5)),
},
@@ -1245,7 +1245,7 @@ func TestProcessEvalResults(t *testing.T) {
LatestResult: newEvaluation(tn(5), eval.Alerting),
StartsAt: tn(5),
EndsAt: tn(5).Add(state.ResendDelay * 4),
FiredAt: tn(5),
FiredAt: util.Pointer(tn(5)),
LastEvaluationTime: tn(5),
LastSentAt: util.Pointer(t3),
},
@@ -94,6 +94,7 @@ func (a *SyncStatePersister) saveAlertStates(ctx context.Context, states ...Stat
LastEvalTime: s.LastEvaluationTime,
CurrentStateSince: s.StartsAt,
CurrentStateEnd: s.EndsAt,
FiredAt: s.FiredAt,
ResolvedAt: s.ResolvedAt,
LastSentAt: s.LastSentAt,
ResultFingerprint: s.ResultFingerprint.String(),
+3 -2
View File
@@ -64,7 +64,7 @@ type State struct {
Values map[string]float64
// FiredAt is the time the state first transitions to Alerting.
FiredAt time.Time
FiredAt *time.Time
StartsAt time.Time
// EndsAt is different from the Prometheus EndsAt as EndsAt is updated for both Normal states
@@ -103,6 +103,7 @@ func newState(ctx context.Context, log log.Logger, alertRule *models.AlertRule,
EndsAt: result.EvaluatedAt,
ResolvedAt: nil,
LastSentAt: nil,
FiredAt: nil,
LastEvaluationString: "",
LastEvaluationTime: result.EvaluatedAt,
EvaluationDuration: result.EvaluationDuration,
@@ -165,7 +166,7 @@ func (a *State) SetAlerting(reason string, startsAt, endsAt time.Time) {
a.Error = nil
// FiredAt is only ever set when the state is set to Alerting.
a.FiredAt = startsAt
a.FiredAt = &startsAt
}
// SetPending sets the state to Pending. It changes both the start and end time.
+2 -2
View File
@@ -46,7 +46,7 @@ func TestSetAlerting(t *testing.T) {
StateReason: "this is a reason",
StartsAt: mock.Now(),
EndsAt: mock.Now().Add(time.Minute),
FiredAt: mock.Now(),
FiredAt: util.Pointer(mock.Now()),
},
}, {
name: "previous state is removed",
@@ -61,7 +61,7 @@ func TestSetAlerting(t *testing.T) {
State: eval.Alerting,
StartsAt: mock.Now(),
EndsAt: mock.Now().Add(time.Minute),
FiredAt: mock.Now(),
FiredAt: util.Pointer(mock.Now()),
},
}}
@@ -73,6 +73,7 @@ func (st InstanceDBStore) SaveAlertInstance(ctx context.Context, alertInstance m
alertInstance.CurrentStateSince.Unix(),
alertInstance.CurrentStateEnd.Unix(),
alertInstance.LastEvalTime.Unix(),
nullableTimeToUnix(alertInstance.FiredAt),
nullableTimeToUnix(alertInstance.ResolvedAt),
nullableTimeToUnix(alertInstance.LastSentAt),
alertInstance.ResultFingerprint,
@@ -81,7 +82,7 @@ func (st InstanceDBStore) SaveAlertInstance(ctx context.Context, alertInstance m
upsertSQL := st.SQLStore.GetDialect().UpsertSQL(
"alert_instance",
[]string{"rule_org_id", "rule_uid", "labels_hash"},
[]string{"rule_org_id", "rule_uid", "labels", "labels_hash", "current_state", "current_reason", "current_state_since", "current_state_end", "last_eval_time", "resolved_at", "last_sent_at", "result_fingerprint"})
[]string{"rule_org_id", "rule_uid", "labels", "labels_hash", "current_state", "current_reason", "current_state_since", "current_state_end", "last_eval_time", "fired_at", "resolved_at", "last_sent_at", "result_fingerprint"})
_, err = sess.SQL(upsertSQL, params...).Query()
if err != nil {
return err
@@ -255,10 +256,10 @@ func (st InstanceDBStore) insertInstancesBatch(sess *sqlstore.DBSession, batch [
query := strings.Builder{}
placeholders := make([]string, 0, len(batch))
args := make([]any, 0, len(batch)*11)
args := make([]any, 0, len(batch)*12)
query.WriteString("INSERT INTO alert_instance ")
query.WriteString("(rule_org_id, rule_uid, labels, labels_hash, current_state, current_reason, current_state_since, current_state_end, last_eval_time, resolved_at, last_sent_at) VALUES ")
query.WriteString("(rule_org_id, rule_uid, labels, labels_hash, current_state, current_reason, current_state_since, current_state_end, last_eval_time, fired_at, resolved_at, last_sent_at) VALUES ")
for _, instance := range batch {
if err := models.ValidateAlertInstance(instance); err != nil {
@@ -272,7 +273,7 @@ func (st InstanceDBStore) insertInstancesBatch(sess *sqlstore.DBSession, batch [
continue
}
placeholders = append(placeholders, "(?,?,?,?,?,?,?,?,?,?,?)")
placeholders = append(placeholders, "(?,?,?,?,?,?,?,?,?,?,?,?)")
args = append(args,
instance.RuleOrgID,
instance.RuleUID,
@@ -283,6 +284,7 @@ func (st InstanceDBStore) insertInstancesBatch(sess *sqlstore.DBSession, batch [
instance.CurrentStateSince.Unix(),
instance.CurrentStateEnd.Unix(),
instance.LastEvalTime.Unix(),
nullableTimeToUnix(instance.FiredAt),
nullableTimeToUnix(instance.ResolvedAt),
nullableTimeToUnix(instance.LastSentAt),
)
@@ -594,6 +594,7 @@ func generateTestAlertInstance(orgID int64, ruleID string) models.AlertInstance
CurrentStateSince: time.Now(),
LastEvalTime: time.Now(),
LastSentAt: util.Pointer(time.Now()),
FiredAt: util.Pointer(time.Now()),
ResolvedAt: util.Pointer(time.Now()),
CurrentReason: "abc",
}
@@ -34,6 +34,7 @@ type AlertInstance struct {
LastSentAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=last_sent_at,json=lastSentAt,proto3" json:"last_sent_at,omitempty"`
ResolvedAt *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=resolved_at,json=resolvedAt,proto3" json:"resolved_at,omitempty"`
ResultFingerprint string `protobuf:"bytes,10,opt,name=result_fingerprint,json=resultFingerprint,proto3" json:"result_fingerprint,omitempty"`
FiredAt *timestamppb.Timestamp `protobuf:"bytes,11,opt,name=fired_at,json=firedAt,proto3" json:"fired_at,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@@ -138,6 +139,13 @@ func (x *AlertInstance) GetResultFingerprint() string {
return ""
}
func (x *AlertInstance) GetFiredAt() *timestamppb.Timestamp {
if x != nil {
return x.FiredAt
}
return nil
}
type AlertInstances struct {
state protoimpl.MessageState `protogen:"open.v1"`
Instances []*AlertInstance `protobuf:"bytes,1,rep,name=instances,proto3" json:"instances,omitempty"`
@@ -189,7 +197,7 @@ var file_alert_rule_state_proto_rawDesc = string([]byte{
0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x6e, 0x67, 0x61, 0x6c, 0x65, 0x72,
0x74, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xfc, 0x04, 0x0a, 0x0d,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb3, 0x05, 0x0a, 0x0d,
0x41, 0x6c, 0x65, 0x72, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1f, 0x0a,
0x0b, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0a, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x48, 0x61, 0x73, 0x68, 0x12, 0x43,
@@ -225,21 +233,24 @@ var file_alert_rule_state_proto_rawDesc = string([]byte{
0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x41, 0x74,
0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65,
0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65,
0x73, 0x75, 0x6c, 0x74, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x1a,
0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4f, 0x0a, 0x0e, 0x41, 0x6c,
0x65, 0x72, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x3d, 0x0a, 0x09,
0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x1f, 0x2e, 0x6e, 0x67, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e,
0x76, 0x31, 0x2e, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
0x52, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x40, 0x5a, 0x3e, 0x67,
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e,
0x61, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x6e, 0x67, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x2f, 0x73,
0x74, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
0x73, 0x75, 0x6c, 0x74, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12,
0x35, 0x0a, 0x08, 0x66, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x66,
0x69, 0x72, 0x65, 0x64, 0x41, 0x74, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73,
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
0x01, 0x22, 0x4f, 0x0a, 0x0e, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e,
0x63, 0x65, 0x73, 0x12, 0x3d, 0x0a, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73,
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6e, 0x67, 0x61, 0x6c, 0x65, 0x72, 0x74,
0x2e, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x49,
0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
0x65, 0x73, 0x42, 0x40, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61,
0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x6e, 0x67,
0x61, 0x6c, 0x65, 0x72, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
})
var (
@@ -268,12 +279,13 @@ var file_alert_rule_state_proto_depIdxs = []int32{
3, // 3: ngalert.store.v1.AlertInstance.last_eval_time:type_name -> google.protobuf.Timestamp
3, // 4: ngalert.store.v1.AlertInstance.last_sent_at:type_name -> google.protobuf.Timestamp
3, // 5: ngalert.store.v1.AlertInstance.resolved_at:type_name -> google.protobuf.Timestamp
0, // 6: ngalert.store.v1.AlertInstances.instances:type_name -> ngalert.store.v1.AlertInstance
7, // [7:7] is the sub-list for method output_type
7, // [7:7] is the sub-list for method input_type
7, // [7:7] is the sub-list for extension type_name
7, // [7:7] is the sub-list for extension extendee
0, // [0:7] is the sub-list for field type_name
3, // 6: ngalert.store.v1.AlertInstance.fired_at:type_name -> google.protobuf.Timestamp
0, // 7: ngalert.store.v1.AlertInstances.instances:type_name -> ngalert.store.v1.AlertInstance
8, // [8:8] is the sub-list for method output_type
8, // [8:8] is the sub-list for method input_type
8, // [8:8] is the sub-list for extension type_name
8, // [8:8] is the sub-list for extension extendee
0, // [0:8] is the sub-list for field type_name
}
func init() { file_alert_rule_state_proto_init() }
@@ -17,6 +17,7 @@ message AlertInstance {
google.protobuf.Timestamp last_sent_at = 8;
google.protobuf.Timestamp resolved_at = 9;
string result_fingerprint = 10;
google.protobuf.Timestamp fired_at = 11;
}
message AlertInstances {
@@ -149,6 +149,7 @@ func alertInstanceModelToProto(modelInstance models.AlertInstance) *pb.AlertInst
CurrentReason: modelInstance.CurrentReason,
LastEvalTime: timestamppb.New(modelInstance.LastEvalTime),
LastSentAt: nullableTimeToTimestamp(modelInstance.LastSentAt),
FiredAt: nullableTimeToTimestamp(modelInstance.FiredAt),
ResolvedAt: nullableTimeToTimestamp(modelInstance.ResolvedAt),
ResultFingerprint: modelInstance.ResultFingerprint,
}
@@ -191,6 +192,7 @@ func alertInstanceProtoToModel(ruleUID string, ruleOrgID int64, protoInstance *p
CurrentReason: protoInstance.CurrentReason,
LastEvalTime: protoInstance.LastEvalTime.AsTime(),
LastSentAt: nullableTimestampToTime(protoInstance.LastSentAt),
FiredAt: nullableTimestampToTime(protoInstance.FiredAt),
ResolvedAt: nullableTimestampToTime(protoInstance.ResolvedAt),
ResultFingerprint: protoInstance.ResultFingerprint,
}
@@ -17,6 +17,7 @@ func TestAlertInstanceModelToProto(t *testing.T) {
currentStateEnd := currentStateSince.Add(time.Minute)
lastEvalTime := currentStateSince.Add(-time.Minute)
lastSentAt := currentStateSince.Add(-2 * time.Minute)
firedAt := currentStateSince.Add(-2 * time.Minute)
resolvedAt := currentStateSince.Add(-3 * time.Minute)
tests := []struct {
@@ -39,6 +40,7 @@ func TestAlertInstanceModelToProto(t *testing.T) {
CurrentReason: "Some reason",
LastEvalTime: lastEvalTime,
LastSentAt: &lastSentAt,
FiredAt: &firedAt,
ResolvedAt: &resolvedAt,
ResultFingerprint: "fingerprint",
},
@@ -51,6 +53,7 @@ func TestAlertInstanceModelToProto(t *testing.T) {
CurrentReason: "Some reason",
LastEvalTime: timestamppb.New(lastEvalTime),
LastSentAt: toProtoTimestampPtr(&lastSentAt),
FiredAt: toProtoTimestampPtr(&firedAt),
ResolvedAt: toProtoTimestampPtr(&resolvedAt),
ResultFingerprint: "fingerprint",
},
@@ -70,6 +73,7 @@ func TestAlertInstanceProtoToModel(t *testing.T) {
currentStateEnd := currentStateSince.Add(time.Minute).UTC()
lastEvalTime := currentStateSince.Add(-time.Minute).UTC()
lastSentAt := currentStateSince.Add(-2 * time.Minute).UTC()
firedAt := currentStateSince.Add(-2 * time.Minute).UTC()
resolvedAt := currentStateSince.Add(-3 * time.Minute).UTC()
ruleUID := "rule-uid-1"
orgID := int64(1)
@@ -89,6 +93,7 @@ func TestAlertInstanceProtoToModel(t *testing.T) {
CurrentStateEnd: timestamppb.New(currentStateEnd),
LastEvalTime: timestamppb.New(lastEvalTime),
LastSentAt: toProtoTimestampPtr(&lastSentAt),
FiredAt: toProtoTimestampPtr(&firedAt),
ResolvedAt: toProtoTimestampPtr(&resolvedAt),
ResultFingerprint: "fingerprint",
},
@@ -104,6 +109,7 @@ func TestAlertInstanceProtoToModel(t *testing.T) {
CurrentStateEnd: currentStateEnd,
LastEvalTime: lastEvalTime,
LastSentAt: &lastSentAt,
FiredAt: &firedAt,
ResolvedAt: &resolvedAt,
ResultFingerprint: "fingerprint",
},
@@ -126,7 +132,7 @@ func TestModelAlertInstanceMatchesProtobuf(t *testing.T) {
// and update them accordingly.
t.Run("when AlertInstance model changes", func(t *testing.T) {
modelType := reflect.TypeOf(models.AlertInstance{})
require.Equal(t, 10, modelType.NumField(), "AlertInstance model has changed, update the protobuf")
require.Equal(t, 11, modelType.NumField(), "AlertInstance model has changed, update the protobuf")
})
}
@@ -142,6 +148,7 @@ func TestCompressAndDecompressAlertInstances(t *testing.T) {
CurrentStateEnd: timestamppb.New(now.Add(time.Hour)),
CurrentReason: "reason-1",
LastEvalTime: timestamppb.New(now.Add(-time.Minute)),
FiredAt: timestamppb.New(now.Add(-time.Minute * 2)),
ResolvedAt: timestamppb.New(now.Add(time.Hour * 2)),
ResultFingerprint: "fingerprint-1",
},
@@ -153,4 +153,6 @@ func (oss *OSSMigrations) AddMigration(mg *Migrator) {
accesscontrol.AddDatasourceDrilldownRemovalMigration(mg)
ualert.DropTitleUniqueIndexMigration(mg)
ualert.AddStateFiredAtColumn(mg)
}
@@ -0,0 +1,12 @@
package ualert
import "github.com/grafana/grafana/pkg/services/sqlstore/migrator"
// AddStateFiredAtColumn adds a fired_at column to alert_instance to represent FiredAt.
func AddStateFiredAtColumn(mg *migrator.Migrator) {
mg.AddMigration("add fired_at column to alert_instance table", migrator.NewAddColumnMigration(migrator.Table{Name: "alert_instance"}, &migrator.Column{
Name: "fired_at",
Type: migrator.DB_BigInt, // BigInt, to match existing time fields.
Nullable: true,
}))
}