| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- package alerting
- import (
- "context"
- "errors"
- "testing"
- "time"
- "github.com/stretchr/testify/assert"
- "github.com/grafana/grafana/pkg/models"
- )
- func TestStateIsUpdatedWhenNeeded(t *testing.T) {
- ctx := NewEvalContext(context.TODO(), &Rule{Conditions: []Condition{&conditionStub{firing: true}}})
- t.Run("ok -> alerting", func(t *testing.T) {
- ctx.PrevAlertState = models.AlertStateOK
- ctx.Rule.State = models.AlertStateAlerting
- if !ctx.ShouldUpdateAlertState() {
- t.Fatalf("expected should updated to be true")
- }
- })
- t.Run("ok -> ok", func(t *testing.T) {
- ctx.PrevAlertState = models.AlertStateOK
- ctx.Rule.State = models.AlertStateOK
- if ctx.ShouldUpdateAlertState() {
- t.Fatalf("expected should updated to be false")
- }
- })
- }
- func TestGetStateFromEvalContext(t *testing.T) {
- tcs := []struct {
- name string
- expected models.AlertStateType
- applyFn func(ec *EvalContext)
- }{
- {
- name: "ok -> alerting",
- expected: models.AlertStateAlerting,
- applyFn: func(ec *EvalContext) {
- ec.Firing = true
- ec.PrevAlertState = models.AlertStateOK
- },
- },
- {
- name: "ok -> error(alerting)",
- expected: models.AlertStateAlerting,
- applyFn: func(ec *EvalContext) {
- ec.PrevAlertState = models.AlertStateOK
- ec.Error = errors.New("test error")
- ec.Rule.ExecutionErrorState = models.ExecutionErrorSetAlerting
- },
- },
- {
- name: "ok -> pending. since its been firing for less than FOR",
- expected: models.AlertStatePending,
- applyFn: func(ec *EvalContext) {
- ec.PrevAlertState = models.AlertStateOK
- ec.Firing = true
- ec.Rule.LastStateChange = time.Now().Add(-time.Minute * 2)
- ec.Rule.For = time.Minute * 5
- },
- },
- {
- name: "ok -> pending. since it has to be pending longer than FOR and prev state is ok",
- expected: models.AlertStatePending,
- applyFn: func(ec *EvalContext) {
- ec.PrevAlertState = models.AlertStateOK
- ec.Firing = true
- ec.Rule.LastStateChange = time.Now().Add(-(time.Hour * 5))
- ec.Rule.For = time.Minute * 2
- },
- },
- {
- name: "pending -> alerting. since its been firing for more than FOR and prev state is pending",
- expected: models.AlertStateAlerting,
- applyFn: func(ec *EvalContext) {
- ec.PrevAlertState = models.AlertStatePending
- ec.Firing = true
- ec.Rule.LastStateChange = time.Now().Add(-(time.Hour * 5))
- ec.Rule.For = time.Minute * 2
- },
- },
- {
- name: "alerting -> alerting. should not update regardless of FOR",
- expected: models.AlertStateAlerting,
- applyFn: func(ec *EvalContext) {
- ec.PrevAlertState = models.AlertStateAlerting
- ec.Firing = true
- ec.Rule.LastStateChange = time.Now().Add(-time.Minute * 5)
- ec.Rule.For = time.Minute * 2
- },
- },
- {
- name: "ok -> ok. should not update regardless of FOR",
- expected: models.AlertStateOK,
- applyFn: func(ec *EvalContext) {
- ec.PrevAlertState = models.AlertStateOK
- ec.Rule.LastStateChange = time.Now().Add(-time.Minute * 5)
- ec.Rule.For = time.Minute * 2
- },
- },
- {
- name: "ok -> error(keep_last)",
- expected: models.AlertStateOK,
- applyFn: func(ec *EvalContext) {
- ec.PrevAlertState = models.AlertStateOK
- ec.Error = errors.New("test error")
- ec.Rule.ExecutionErrorState = models.ExecutionErrorKeepState
- },
- },
- {
- name: "pending -> error(keep_last)",
- expected: models.AlertStatePending,
- applyFn: func(ec *EvalContext) {
- ec.PrevAlertState = models.AlertStatePending
- ec.Error = errors.New("test error")
- ec.Rule.ExecutionErrorState = models.ExecutionErrorKeepState
- },
- },
- {
- name: "ok -> no_data(alerting)",
- expected: models.AlertStateAlerting,
- applyFn: func(ec *EvalContext) {
- ec.PrevAlertState = models.AlertStateOK
- ec.Rule.NoDataState = models.NoDataSetAlerting
- ec.NoDataFound = true
- },
- },
- {
- name: "ok -> no_data(keep_last)",
- expected: models.AlertStateOK,
- applyFn: func(ec *EvalContext) {
- ec.PrevAlertState = models.AlertStateOK
- ec.Rule.NoDataState = models.NoDataKeepState
- ec.NoDataFound = true
- },
- },
- {
- name: "pending -> no_data(keep_last)",
- expected: models.AlertStatePending,
- applyFn: func(ec *EvalContext) {
- ec.PrevAlertState = models.AlertStatePending
- ec.Rule.NoDataState = models.NoDataKeepState
- ec.NoDataFound = true
- },
- },
- {
- name: "pending -> no_data(alerting) with for duration have not passed",
- expected: models.AlertStatePending,
- applyFn: func(ec *EvalContext) {
- ec.PrevAlertState = models.AlertStatePending
- ec.Rule.NoDataState = models.NoDataSetAlerting
- ec.NoDataFound = true
- ec.Rule.For = time.Minute * 5
- ec.Rule.LastStateChange = time.Now().Add(-time.Minute * 2)
- },
- },
- {
- name: "pending -> no_data(alerting) should set alerting since time passed FOR",
- expected: models.AlertStateAlerting,
- applyFn: func(ec *EvalContext) {
- ec.PrevAlertState = models.AlertStatePending
- ec.Rule.NoDataState = models.NoDataSetAlerting
- ec.NoDataFound = true
- ec.Rule.For = time.Minute * 2
- ec.Rule.LastStateChange = time.Now().Add(-time.Minute * 5)
- },
- },
- {
- name: "pending -> error(alerting) with for duration have not passed ",
- expected: models.AlertStatePending,
- applyFn: func(ec *EvalContext) {
- ec.PrevAlertState = models.AlertStatePending
- ec.Rule.ExecutionErrorState = models.ExecutionErrorSetAlerting
- ec.Error = errors.New("test error")
- ec.Rule.For = time.Minute * 5
- ec.Rule.LastStateChange = time.Now().Add(-time.Minute * 2)
- },
- },
- {
- name: "pending -> error(alerting) should set alerting since time passed FOR",
- expected: models.AlertStateAlerting,
- applyFn: func(ec *EvalContext) {
- ec.PrevAlertState = models.AlertStatePending
- ec.Rule.ExecutionErrorState = models.ExecutionErrorSetAlerting
- ec.Error = errors.New("test error")
- ec.Rule.For = time.Minute * 2
- ec.Rule.LastStateChange = time.Now().Add(-time.Minute * 5)
- },
- },
- }
- for _, tc := range tcs {
- evalContext := NewEvalContext(context.Background(), &Rule{Conditions: []Condition{&conditionStub{firing: true}}})
- tc.applyFn(evalContext)
- newState := evalContext.GetNewState()
- assert.Equal(t, tc.expected, newState, "failed: %s \n expected '%s' have '%s'\n", tc.name, tc.expected, string(newState))
- }
- }
|