mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Support hysteresis command expression (#75189)
Backend: * Update the Grafana Alerting engine to provide feedback to HysteresisCommand. The feedback information is stored in state.Manager as a fingerprint of each state. The fingerprint is persisted to the database. Only fingerprints that belong to Pending and Alerting states are considered as "loaded" and provided back to the command. - add ResultFingerprint to state.State. It's different from other fingerprints we store in the state because it is calculated from the result labels. - add rule_fingerprint column to alert_instance - update alerting evaluator to accept AlertingResultsReader via context, and update scheduler to provide it. - add AlertingResultsFromRuleState that implements the new interface in eval package - update getExprRequest to patch the hysteresis command. * Only one "Recovery Threshold" query is allowed to be used in the alert rule and it must be the Condition. Frontend: * Add hysteresis option to Threshold in UI. It's called "Recovery Threshold" * Add test for getUnloadEvaluatorTypeFromCondition * Hide hysteresis in panel expressions * Refactor isInvalid and add test for it * Remove unnecesary React.memo * Add tests for updateEvaluatorConditions --------- Co-authored-by: Sonia Aguilar <soniaaguilarpeiron@gmail.com>
This commit is contained in:
@@ -286,6 +286,15 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
|
||||
"system + rule + datasource-error": mergeLabels(mergeLabels(expectedDatasourceErrorLabels, baseRule.Labels), systemLabels),
|
||||
}
|
||||
|
||||
resultFingerprints := map[string]data.Fingerprint{
|
||||
"system + rule": data.Labels{}.Fingerprint(),
|
||||
"system + rule + labels1": labels1.Fingerprint(),
|
||||
"system + rule + labels2": labels2.Fingerprint(),
|
||||
"system + rule + labels3": labels3.Fingerprint(),
|
||||
"system + rule + no-data": noDataLabels.Fingerprint(),
|
||||
"system + rule + datasource-error": data.Labels{}.Fingerprint(),
|
||||
}
|
||||
|
||||
patchState := func(r *ngmodels.AlertRule, s *State) {
|
||||
// patch all optional fields of the expected state
|
||||
setCacheID(s)
|
||||
@@ -304,6 +313,14 @@ func TestProcessEvalResults_StateTransitions(t *testing.T) {
|
||||
if s.Values == nil {
|
||||
s.Values = make(map[string]float64)
|
||||
}
|
||||
if s.ResultFingerprint == data.Fingerprint(0) {
|
||||
for key, set := range labels {
|
||||
if set.Fingerprint() == s.Labels.Fingerprint() {
|
||||
s.ResultFingerprint = resultFingerprints[key]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
executeTest := func(t *testing.T, alertRule *ngmodels.AlertRule, resultsAtTime map[time.Time]eval.Results, expectedTransitionsAtTime map[time.Time][]StateTransition, applyNoDataErrorToAllStates bool) {
|
||||
|
||||
Reference in New Issue
Block a user