Merge pull request #13680 from davewat/add-notification-channel-option-to-disable-resolved-alert

Add channel option to disable the resolved alert (OK Message)
This commit is contained in:
Carl Bergquist 2018-10-17 11:08:39 +02:00 committed by GitHub
commit 94e2d2b483
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 122 additions and 82 deletions

View File

@ -49,28 +49,30 @@ func formatShort(interval time.Duration) string {
func NewAlertNotification(notification *models.AlertNotification) *AlertNotification { func NewAlertNotification(notification *models.AlertNotification) *AlertNotification {
return &AlertNotification{ return &AlertNotification{
Id: notification.Id, Id: notification.Id,
Name: notification.Name, Name: notification.Name,
Type: notification.Type, Type: notification.Type,
IsDefault: notification.IsDefault, IsDefault: notification.IsDefault,
Created: notification.Created, Created: notification.Created,
Updated: notification.Updated, Updated: notification.Updated,
Frequency: formatShort(notification.Frequency), Frequency: formatShort(notification.Frequency),
SendReminder: notification.SendReminder, SendReminder: notification.SendReminder,
Settings: notification.Settings, DisableResolveMessage: notification.DisableResolveMessage,
Settings: notification.Settings,
} }
} }
type AlertNotification struct { type AlertNotification struct {
Id int64 `json:"id"` Id int64 `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Type string `json:"type"` Type string `json:"type"`
IsDefault bool `json:"isDefault"` IsDefault bool `json:"isDefault"`
SendReminder bool `json:"sendReminder"` SendReminder bool `json:"sendReminder"`
Frequency string `json:"frequency"` DisableResolveMessage bool `json:"disableResolveMessage"`
Created time.Time `json:"created"` Frequency string `json:"frequency"`
Updated time.Time `json:"updated"` Created time.Time `json:"created"`
Settings *simplejson.Json `json:"settings"` Updated time.Time `json:"updated"`
Settings *simplejson.Json `json:"settings"`
} }
type AlertTestCommand struct { type AlertTestCommand struct {
@ -100,11 +102,12 @@ type EvalMatch struct {
} }
type NotificationTestCommand struct { type NotificationTestCommand struct {
Name string `json:"name"` Name string `json:"name"`
Type string `json:"type"` Type string `json:"type"`
SendReminder bool `json:"sendReminder"` SendReminder bool `json:"sendReminder"`
Frequency string `json:"frequency"` DisableResolveMessage bool `json:"disableResolveMessage"`
Settings *simplejson.Json `json:"settings"` Frequency string `json:"frequency"`
Settings *simplejson.Json `json:"settings"`
} }
type PauseAlertCommand struct { type PauseAlertCommand struct {

View File

@ -23,38 +23,41 @@ var (
) )
type AlertNotification struct { type AlertNotification struct {
Id int64 `json:"id"` Id int64 `json:"id"`
OrgId int64 `json:"-"` OrgId int64 `json:"-"`
Name string `json:"name"` Name string `json:"name"`
Type string `json:"type"` Type string `json:"type"`
SendReminder bool `json:"sendReminder"` SendReminder bool `json:"sendReminder"`
Frequency time.Duration `json:"frequency"` DisableResolveMessage bool `json:"disableResolveMessage"`
IsDefault bool `json:"isDefault"` Frequency time.Duration `json:"frequency"`
Settings *simplejson.Json `json:"settings"` IsDefault bool `json:"isDefault"`
Created time.Time `json:"created"` Settings *simplejson.Json `json:"settings"`
Updated time.Time `json:"updated"` Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
} }
type CreateAlertNotificationCommand struct { type CreateAlertNotificationCommand struct {
Name string `json:"name" binding:"Required"` Name string `json:"name" binding:"Required"`
Type string `json:"type" binding:"Required"` Type string `json:"type" binding:"Required"`
SendReminder bool `json:"sendReminder"` SendReminder bool `json:"sendReminder"`
Frequency string `json:"frequency"` DisableResolveMessage bool `json:"disableResolveMessage"`
IsDefault bool `json:"isDefault"` Frequency string `json:"frequency"`
Settings *simplejson.Json `json:"settings"` IsDefault bool `json:"isDefault"`
Settings *simplejson.Json `json:"settings"`
OrgId int64 `json:"-"` OrgId int64 `json:"-"`
Result *AlertNotification Result *AlertNotification
} }
type UpdateAlertNotificationCommand struct { type UpdateAlertNotificationCommand struct {
Id int64 `json:"id" binding:"Required"` Id int64 `json:"id" binding:"Required"`
Name string `json:"name" binding:"Required"` Name string `json:"name" binding:"Required"`
Type string `json:"type" binding:"Required"` Type string `json:"type" binding:"Required"`
SendReminder bool `json:"sendReminder"` SendReminder bool `json:"sendReminder"`
Frequency string `json:"frequency"` DisableResolveMessage bool `json:"disableResolveMessage"`
IsDefault bool `json:"isDefault"` Frequency string `json:"frequency"`
Settings *simplejson.Json `json:"settings" binding:"Required"` IsDefault bool `json:"isDefault"`
Settings *simplejson.Json `json:"settings" binding:"Required"`
OrgId int64 `json:"-"` OrgId int64 `json:"-"`
Result *AlertNotification Result *AlertNotification

View File

@ -27,6 +27,7 @@ type Notifier interface {
GetNotifierId() int64 GetNotifierId() int64
GetIsDefault() bool GetIsDefault() bool
GetSendReminder() bool GetSendReminder() bool
GetDisableResolveMessage() bool
GetFrequency() time.Duration GetFrequency() time.Duration
} }

View File

@ -6,7 +6,6 @@ import (
"github.com/grafana/grafana/pkg/log" "github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/alerting" "github.com/grafana/grafana/pkg/services/alerting"
) )
@ -15,13 +14,14 @@ const (
) )
type NotifierBase struct { type NotifierBase struct {
Name string Name string
Type string Type string
Id int64 Id int64
IsDeault bool IsDeault bool
UploadImage bool UploadImage bool
SendReminder bool SendReminder bool
Frequency time.Duration DisableResolveMessage bool
Frequency time.Duration
log log.Logger log log.Logger
} }
@ -34,14 +34,15 @@ func NewNotifierBase(model *models.AlertNotification) NotifierBase {
} }
return NotifierBase{ return NotifierBase{
Id: model.Id, Id: model.Id,
Name: model.Name, Name: model.Name,
IsDeault: model.IsDefault, IsDeault: model.IsDefault,
Type: model.Type, Type: model.Type,
UploadImage: uploadImage, UploadImage: uploadImage,
SendReminder: model.SendReminder, SendReminder: model.SendReminder,
Frequency: model.Frequency, DisableResolveMessage: model.DisableResolveMessage,
log: log.New("alerting.notifier." + model.Name), Frequency: model.Frequency,
log: log.New("alerting.notifier." + model.Name),
} }
} }
@ -83,6 +84,11 @@ func (n *NotifierBase) ShouldNotify(ctx context.Context, context *alerting.EvalC
} }
} }
// Do not notify when state is OK if DisableResolveMessage is set to true
if context.Rule.State == models.AlertStateOK && n.DisableResolveMessage {
return false
}
return true return true
} }
@ -106,6 +112,10 @@ func (n *NotifierBase) GetSendReminder() bool {
return n.SendReminder return n.SendReminder
} }
func (n *NotifierBase) GetDisableResolveMessage() bool {
return n.DisableResolveMessage
}
func (n *NotifierBase) GetFrequency() time.Duration { func (n *NotifierBase) GetFrequency() time.Duration {
return n.Frequency return n.Frequency
} }

View File

@ -179,5 +179,10 @@ func TestBaseNotifier(t *testing.T) {
base := NewNotifierBase(model) base := NewNotifierBase(model)
So(base.UploadImage, ShouldBeTrue) So(base.UploadImage, ShouldBeTrue)
}) })
Convey("default value should be false for backwards compatibility", func() {
base := NewNotifierBase(model)
So(base.DisableResolveMessage, ShouldBeFalse)
})
}) })
} }

View File

@ -66,6 +66,7 @@ func GetAlertNotificationsToSend(query *m.GetAlertNotificationsToSendQuery) erro
alert_notification.updated, alert_notification.updated,
alert_notification.settings, alert_notification.settings,
alert_notification.is_default, alert_notification.is_default,
alert_notification.disable_resolve_message,
alert_notification.send_reminder, alert_notification.send_reminder,
alert_notification.frequency alert_notification.frequency
FROM alert_notification FROM alert_notification
@ -106,6 +107,7 @@ func getAlertNotificationInternal(query *m.GetAlertNotificationsQuery, sess *DBS
alert_notification.updated, alert_notification.updated,
alert_notification.settings, alert_notification.settings,
alert_notification.is_default, alert_notification.is_default,
alert_notification.disable_resolve_message,
alert_notification.send_reminder, alert_notification.send_reminder,
alert_notification.frequency alert_notification.frequency
FROM alert_notification FROM alert_notification
@ -166,15 +168,16 @@ func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error
} }
alertNotification := &m.AlertNotification{ alertNotification := &m.AlertNotification{
OrgId: cmd.OrgId, OrgId: cmd.OrgId,
Name: cmd.Name, Name: cmd.Name,
Type: cmd.Type, Type: cmd.Type,
Settings: cmd.Settings, Settings: cmd.Settings,
SendReminder: cmd.SendReminder, SendReminder: cmd.SendReminder,
Frequency: frequency, DisableResolveMessage: cmd.DisableResolveMessage,
Created: time.Now(), Frequency: frequency,
Updated: time.Now(), Created: time.Now(),
IsDefault: cmd.IsDefault, Updated: time.Now(),
IsDefault: cmd.IsDefault,
} }
if _, err = sess.MustCols("send_reminder").Insert(alertNotification); err != nil { if _, err = sess.MustCols("send_reminder").Insert(alertNotification); err != nil {
@ -210,6 +213,7 @@ func UpdateAlertNotification(cmd *m.UpdateAlertNotificationCommand) error {
current.Type = cmd.Type current.Type = cmd.Type
current.IsDefault = cmd.IsDefault current.IsDefault = cmd.IsDefault
current.SendReminder = cmd.SendReminder current.SendReminder = cmd.SendReminder
current.DisableResolveMessage = cmd.DisableResolveMessage
if current.SendReminder { if current.SendReminder {
if cmd.Frequency == "" { if cmd.Frequency == "" {
@ -224,7 +228,7 @@ func UpdateAlertNotification(cmd *m.UpdateAlertNotificationCommand) error {
current.Frequency = frequency current.Frequency = frequency
} }
sess.UseBool("is_default", "send_reminder") sess.UseBool("is_default", "send_reminder", "disable_resolve_message")
if affected, err := sess.ID(cmd.Id).Update(current); err != nil { if affected, err := sess.ID(cmd.Id).Update(current); err != nil {
return err return err

View File

@ -219,6 +219,7 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
So(cmd.Result.OrgId, ShouldNotEqual, 0) So(cmd.Result.OrgId, ShouldNotEqual, 0)
So(cmd.Result.Type, ShouldEqual, "email") So(cmd.Result.Type, ShouldEqual, "email")
So(cmd.Result.Frequency, ShouldEqual, 10*time.Second) So(cmd.Result.Frequency, ShouldEqual, 10*time.Second)
So(cmd.Result.DisableResolveMessage, ShouldBeFalse)
Convey("Cannot save Alert Notification with the same name", func() { Convey("Cannot save Alert Notification with the same name", func() {
err = CreateAlertNotificationCommand(cmd) err = CreateAlertNotificationCommand(cmd)
@ -227,18 +228,20 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
Convey("Can update alert notification", func() { Convey("Can update alert notification", func() {
newCmd := &models.UpdateAlertNotificationCommand{ newCmd := &models.UpdateAlertNotificationCommand{
Name: "NewName", Name: "NewName",
Type: "webhook", Type: "webhook",
OrgId: cmd.Result.OrgId, OrgId: cmd.Result.OrgId,
SendReminder: true, SendReminder: true,
Frequency: "60s", DisableResolveMessage: true,
Settings: simplejson.New(), Frequency: "60s",
Id: cmd.Result.Id, Settings: simplejson.New(),
Id: cmd.Result.Id,
} }
err := UpdateAlertNotification(newCmd) err := UpdateAlertNotification(newCmd)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(newCmd.Result.Name, ShouldEqual, "NewName") So(newCmd.Result.Name, ShouldEqual, "NewName")
So(newCmd.Result.Frequency, ShouldEqual, 60*time.Second) So(newCmd.Result.Frequency, ShouldEqual, 60*time.Second)
So(newCmd.Result.DisableResolveMessage, ShouldBeTrue)
}) })
Convey("Can update alert notification to disable sending of reminders", func() { Convey("Can update alert notification to disable sending of reminders", func() {

View File

@ -71,6 +71,9 @@ func addAlertMigrations(mg *Migrator) {
mg.AddMigration("Add column send_reminder", NewAddColumnMigration(alert_notification, &Column{ mg.AddMigration("Add column send_reminder", NewAddColumnMigration(alert_notification, &Column{
Name: "send_reminder", Type: DB_Bool, Nullable: true, Default: "0", Name: "send_reminder", Type: DB_Bool, Nullable: true, Default: "0",
})) }))
mg.AddMigration("Add column disable_resolve_message", NewAddColumnMigration(alert_notification, &Column{
Name: "disable_resolve_message", Type: DB_Bool, Nullable: false, Default: "0",
}))
mg.AddMigration("add index alert_notification org_id & name", NewAddIndexMigration(alert_notification, alert_notification.Indices[0])) mg.AddMigration("add index alert_notification org_id & name", NewAddIndexMigration(alert_notification, alert_notification.Indices[0]))

View File

@ -12,6 +12,7 @@ export class AlertNotificationEditCtrl {
defaults: any = { defaults: any = {
type: 'email', type: 'email',
sendReminder: false, sendReminder: false,
disableResolveMessage: false,
frequency: '15m', frequency: '15m',
settings: { settings: {
httpMethod: 'POST', httpMethod: 'POST',

View File

@ -21,21 +21,28 @@
<gf-form-switch <gf-form-switch
class="gf-form" class="gf-form"
label="Send on all alerts" label="Send on all alerts"
label-class="width-12" label-class="width-14"
checked="ctrl.model.isDefault" checked="ctrl.model.isDefault"
tooltip="Use this notification for all alerts"> tooltip="Use this notification for all alerts">
</gf-form-switch> </gf-form-switch>
<gf-form-switch <gf-form-switch
class="gf-form" class="gf-form"
label="Include image" label="Include image"
label-class="width-12" label-class="width-14"
checked="ctrl.model.settings.uploadImage" checked="ctrl.model.settings.uploadImage"
tooltip="Captures an image and include it in the notification"> tooltip="Captures an image and include it in the notification">
</gf-form-switch> </gf-form-switch>
<gf-form-switch
class="gf-form"
label="Disable Resolve Message"
label-class="width-14"
checked="ctrl.model.disableResolveMessage"
tooltip="Disable the resolve message [OK] that is sent when alerting state returns to false">
</gf-form-switch>
<gf-form-switch <gf-form-switch
class="gf-form" class="gf-form"
label="Send reminders" label="Send reminders"
label-class="width-12" label-class="width-14"
checked="ctrl.model.sendReminder" checked="ctrl.model.sendReminder"
tooltip="Send additional notifications for triggered alerts"> tooltip="Send additional notifications for triggered alerts">
</gf-form-switch> </gf-form-switch>