diff --git a/pkg/services/alerting/extractor.go b/pkg/services/alerting/extractor.go index edfab2dedee..221d58feaf2 100644 --- a/pkg/services/alerting/extractor.go +++ b/pkg/services/alerting/extractor.go @@ -2,6 +2,7 @@ package alerting import ( "errors" + "time" "fmt" @@ -113,15 +114,25 @@ func (e *DashAlertExtractor) getAlertFromPanels(jsonWithPanels *simplejson.Json, return nil, ValidationError{Reason: "Could not parse frequency"} } + rawDebouce := jsonAlert.Get("debounceDuration").MustString() + var debounceDuration time.Duration + if rawDebouce != "" { + debounceDuration, err = time.ParseDuration(rawDebouce) + if err != nil { + return nil, ValidationError{Reason: "Could not parse debounceDuration"} + } + } + alert := &m.Alert{ - DashboardId: e.Dash.Id, - OrgId: e.OrgID, - PanelId: panelID, - Id: jsonAlert.Get("id").MustInt64(), - Name: jsonAlert.Get("name").MustString(), - Handler: jsonAlert.Get("handler").MustInt64(), - Message: jsonAlert.Get("message").MustString(), - Frequency: frequency, + DashboardId: e.Dash.Id, + OrgId: e.OrgID, + PanelId: panelID, + Id: jsonAlert.Get("id").MustInt64(), + Name: jsonAlert.Get("name").MustString(), + Handler: jsonAlert.Get("handler").MustInt64(), + Message: jsonAlert.Get("message").MustString(), + Frequency: frequency, + DebounceDuration: debounceDuration, } for _, condition := range jsonAlert.Get("conditions").MustArray() { diff --git a/pkg/services/sqlstore/alert.go b/pkg/services/sqlstore/alert.go index 2f17402b80c..88ffa3a9b4e 100644 --- a/pkg/services/sqlstore/alert.go +++ b/pkg/services/sqlstore/alert.go @@ -193,7 +193,8 @@ func updateAlerts(existingAlerts []*m.Alert, cmd *m.SaveAlertsCommand, sess *DBS if alertToUpdate.ContainsUpdates(alert) { alert.Updated = timeNow() alert.State = alertToUpdate.State - sess.MustCols("message") + sess.MustCols("message", "debounce_duration") + _, err := sess.ID(alert.Id).Update(alert) if err != nil { return err diff --git a/public/app/features/alerting/AlertTabCtrl.ts b/public/app/features/alerting/AlertTabCtrl.ts index 146b7026353..43752d0a8c9 100644 --- a/public/app/features/alerting/AlertTabCtrl.ts +++ b/public/app/features/alerting/AlertTabCtrl.ts @@ -169,6 +169,7 @@ export class AlertTabCtrl { alert.frequency = alert.frequency || '1m'; alert.handler = alert.handler || 1; alert.notifications = alert.notifications || []; + alert.debounceDuration = alert.debounceDuration || '5m'; const defaultName = this.panel.title + ' alert'; alert.name = alert.name || defaultName; diff --git a/public/app/features/alerting/partials/alert_tab.html b/public/app/features/alerting/partials/alert_tab.html index cb101672aa4..de5fc4df382 100644 --- a/public/app/features/alerting/partials/alert_tab.html +++ b/public/app/features/alerting/partials/alert_tab.html @@ -1,147 +1,159 @@
- -
-
-
- {{ctrl.error}} -
+
+
+
+ {{ctrl.error}} +
-
-
Alert Config
-
- Name - - Evaluate every - -
-
+
+
Alert Config
+
+ Name + +
+
+
+ Evaluate every + +
+
+ + + + Configuring this value means that an alert rule have to be firing for atleast this duration before changing state. + This should reduce false positive alerts and avoid flapping alerts. + +
+
+
-
-
Conditions
-
-
- - WHEN -
-
- - - OF -
-
- - -
-
- - - - -
-
- -
-
+
+
Conditions
+
+
+ + WHEN +
+
+ + + OF +
+
+ + +
+
+ + + + +
+
+ +
+
-
- -
-
+
+ +
+
-
-
- If no data or all values are null - SET STATE TO -
- -
-
+
+
+ If no data or all values are null + SET STATE TO +
+ +
+
-
- If execution error or timeout - SET STATE TO -
- -
-
+
+ If execution error or timeout + SET STATE TO +
+ +
+
-
- -
-
+
+ +
+
-
- Evaluating rule -
+
+ Evaluating rule +
-
- -
-
+
+ +
+
-
-
Notifications
-
-
- Send to - -  {{nc.name}}  - - - -
-
-
- Message - -
-
+
+
Notifications
+
+
+ Send to + +  {{nc.name}}  + + + +
+
+
+ Message + +
+
-
- -
- State history (last 50 state changes) -
+
+ +
+ State history (last 50 state changes) +
-
-
- No state changes recorded -
+
+
+ No state changes recorded +