mirror of
https://github.com/grafana/grafana.git
synced 2024-11-25 18:30:41 -06:00
f6a46744a6
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>
66 lines
1.7 KiB
Go
66 lines
1.7 KiB
Go
package schedule
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/grafana/grafana-plugin-sdk-go/data"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/grafana/grafana/pkg/services/ngalert/eval"
|
|
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/state"
|
|
)
|
|
|
|
func TestLoadedResultsFromRuleState(t *testing.T) {
|
|
rule := ngmodels.AlertRuleGen()()
|
|
p := &FakeRuleStateProvider{
|
|
map[ngmodels.AlertRuleKey][]*state.State{
|
|
rule.GetKey(): {
|
|
{State: eval.Alerting, ResultFingerprint: data.Fingerprint(1)},
|
|
{State: eval.Pending, ResultFingerprint: data.Fingerprint(2)},
|
|
{State: eval.Normal, ResultFingerprint: data.Fingerprint(3)},
|
|
{State: eval.NoData, ResultFingerprint: data.Fingerprint(4)},
|
|
{State: eval.Error, ResultFingerprint: data.Fingerprint(5)},
|
|
},
|
|
},
|
|
}
|
|
|
|
reader := AlertingResultsFromRuleState{
|
|
Manager: p,
|
|
Rule: rule,
|
|
}
|
|
|
|
t.Run("should return pending and alerting states", func(t *testing.T) {
|
|
loaded := reader.Read()
|
|
require.Len(t, loaded, 2)
|
|
require.Contains(t, loaded, data.Fingerprint(1))
|
|
require.Contains(t, loaded, data.Fingerprint(2))
|
|
})
|
|
|
|
t.Run("should not return any states with reason", func(t *testing.T) {
|
|
for _, s := range p.states[rule.GetKey()] {
|
|
s.StateReason = uuid.NewString()
|
|
}
|
|
loaded := reader.Read()
|
|
require.Empty(t, loaded)
|
|
})
|
|
|
|
t.Run("empty if no states", func(t *testing.T) {
|
|
p.states[rule.GetKey()] = nil
|
|
loaded := reader.Read()
|
|
require.Empty(t, loaded)
|
|
})
|
|
}
|
|
|
|
type FakeRuleStateProvider struct {
|
|
states map[ngmodels.AlertRuleKey][]*state.State
|
|
}
|
|
|
|
func (f FakeRuleStateProvider) GetStatesForRuleUID(orgID int64, UID string) []*state.State {
|
|
return f.states[ngmodels.AlertRuleKey{
|
|
OrgID: orgID,
|
|
UID: UID,
|
|
}]
|
|
}
|