From d25284a36441ef3ec2f1e8953acbd7fb4680f7a9 Mon Sep 17 00:00:00 2001 From: bergquist Date: Mon, 5 Nov 2018 10:23:43 +0100 Subject: [PATCH] introduce state `unknown` for rules that have not been evaluated yet --- pkg/api/alerting.go | 2 +- pkg/models/alert.go | 8 +++++++- pkg/services/alerting/eval_context.go | 5 +++++ pkg/services/alerting/notifiers/base.go | 5 +++++ pkg/services/alerting/notifiers/base_test.go | 16 ++++++++++++++++ pkg/services/sqlstore/alert.go | 6 +++--- pkg/services/sqlstore/alert_test.go | 4 ++-- public/app/features/alerting/state/alertDef.ts | 7 +++++++ 8 files changed, 46 insertions(+), 7 deletions(-) diff --git a/pkg/api/alerting.go b/pkg/api/alerting.go index a936d696207..b007b3a3492 100644 --- a/pkg/api/alerting.go +++ b/pkg/api/alerting.go @@ -291,7 +291,7 @@ func PauseAlert(c *m.ReqContext, dto dtos.PauseAlertCommand) Response { return Error(500, "", err) } - var response m.AlertStateType = m.AlertStatePending + var response m.AlertStateType = m.AlertStateUnknown pausedState := "un-paused" if cmd.Paused { response = m.AlertStatePaused diff --git a/pkg/models/alert.go b/pkg/models/alert.go index e35ba106688..37f40134796 100644 --- a/pkg/models/alert.go +++ b/pkg/models/alert.go @@ -19,6 +19,7 @@ const ( AlertStateAlerting AlertStateType = "alerting" AlertStateOK AlertStateType = "ok" AlertStatePending AlertStateType = "pending" + AlertStateUnknown AlertStateType = "unknown" ) const ( @@ -39,7 +40,12 @@ var ( ) func (s AlertStateType) IsValid() bool { - return s == AlertStateOK || s == AlertStateNoData || s == AlertStatePaused || s == AlertStatePending + return s == AlertStateOK || + s == AlertStateNoData || + s == AlertStatePaused || + s == AlertStatePending || + s == AlertStateAlerting || + s == AlertStateUnknown } func (s NoDataOption) IsValid() bool { diff --git a/pkg/services/alerting/eval_context.go b/pkg/services/alerting/eval_context.go index 49e28bbf5ec..8986af85406 100644 --- a/pkg/services/alerting/eval_context.go +++ b/pkg/services/alerting/eval_context.go @@ -68,6 +68,11 @@ func (c *EvalContext) GetStateModel() *StateDescription { Color: "#D63232", Text: "Alerting", } + case m.AlertStateUnknown: + return &StateDescription{ + Color: "888888", + Text: "Unknown", + } default: panic("Unknown rule state for alert notifications " + c.Rule.State) } diff --git a/pkg/services/alerting/notifiers/base.go b/pkg/services/alerting/notifiers/base.go index d141d6cd257..35d3ff518a0 100644 --- a/pkg/services/alerting/notifiers/base.go +++ b/pkg/services/alerting/notifiers/base.go @@ -67,6 +67,11 @@ func (n *NotifierBase) ShouldNotify(ctx context.Context, context *alerting.EvalC } // Do not notify when we become OK for the first time. + if context.PrevAlertState == models.AlertStateUnknown && context.Rule.State == models.AlertStateOK { + return false + } + + // Do not notify when we become OK from pending if context.PrevAlertState == models.AlertStatePending && context.Rule.State == models.AlertStateOK { return false } diff --git a/pkg/services/alerting/notifiers/base_test.go b/pkg/services/alerting/notifiers/base_test.go index 5062828cb4f..388c2db17ee 100644 --- a/pkg/services/alerting/notifiers/base_test.go +++ b/pkg/services/alerting/notifiers/base_test.go @@ -132,6 +132,22 @@ func TestShouldSendAlertNotification(t *testing.T) { prevState: m.AlertStateOK, state: &m.AlertNotificationState{State: m.AlertNotificationStatePending, UpdatedAt: tnow.Add(-2 * time.Minute).Unix()}, + expect: true, + }, + { + name: "unknown -> ok", + prevState: m.AlertStateUnknown, + newState: m.AlertStateOK, + state: &m.AlertNotificationState{}, + + expect: false, + }, + { + name: "unknown -> alerting", + prevState: m.AlertStateUnknown, + newState: m.AlertStateAlerting, + state: &m.AlertNotificationState{}, + expect: true, }, } diff --git a/pkg/services/sqlstore/alert.go b/pkg/services/sqlstore/alert.go index 88ffa3a9b4e..78a71cc8497 100644 --- a/pkg/services/sqlstore/alert.go +++ b/pkg/services/sqlstore/alert.go @@ -205,7 +205,7 @@ func updateAlerts(existingAlerts []*m.Alert, cmd *m.SaveAlertsCommand, sess *DBS } else { alert.Updated = timeNow() alert.Created = timeNow() - alert.State = m.AlertStatePending + alert.State = m.AlertStateUnknown alert.NewStateDate = timeNow() _, err := sess.Insert(alert) @@ -300,7 +300,7 @@ func PauseAlert(cmd *m.PauseAlertCommand) error { params = append(params, string(m.AlertStatePaused)) params = append(params, timeNow()) } else { - params = append(params, string(m.AlertStatePending)) + params = append(params, string(m.AlertStateUnknown)) params = append(params, timeNow()) } @@ -324,7 +324,7 @@ func PauseAllAlerts(cmd *m.PauseAllAlertCommand) error { if cmd.Paused { newState = string(m.AlertStatePaused) } else { - newState = string(m.AlertStatePending) + newState = string(m.AlertStateUnknown) } res, err := sess.Exec(`UPDATE alert SET state = ?, new_state_date = ?`, newState, timeNow()) diff --git a/pkg/services/sqlstore/alert_test.go b/pkg/services/sqlstore/alert_test.go index d97deb45f0e..40867e96b4d 100644 --- a/pkg/services/sqlstore/alert_test.go +++ b/pkg/services/sqlstore/alert_test.go @@ -109,7 +109,7 @@ func TestAlertingDataAccess(t *testing.T) { So(alert.DashboardId, ShouldEqual, testDash.Id) So(alert.PanelId, ShouldEqual, 1) So(alert.Name, ShouldEqual, "Alerting title") - So(alert.State, ShouldEqual, "pending") + So(alert.State, ShouldEqual, m.AlertStateUnknown) So(alert.NewStateDate, ShouldNotBeNil) So(alert.EvalData, ShouldNotBeNil) So(alert.EvalData.Get("test").MustString(), ShouldEqual, "test") @@ -154,7 +154,7 @@ func TestAlertingDataAccess(t *testing.T) { So(query.Result[0].Name, ShouldEqual, "Name") Convey("Alert state should not be updated", func() { - So(query.Result[0].State, ShouldEqual, "pending") + So(query.Result[0].State, ShouldEqual, m.AlertStateUnknown) }) }) diff --git a/public/app/features/alerting/state/alertDef.ts b/public/app/features/alerting/state/alertDef.ts index 11d2aafaa7f..378be0afb91 100644 --- a/public/app/features/alerting/state/alertDef.ts +++ b/public/app/features/alerting/state/alertDef.ts @@ -99,6 +99,13 @@ function getStateDisplayModel(state) { stateClass: 'alert-state-warning', }; } + case 'unknown': { + return { + text: 'UNKNOWN', + iconClass: 'fa fa-question', + stateClass: 'alert-state-paused', + }; + } } throw { message: 'Unknown alert state' };