Browse Source

feat(alerting): add default notification group

bergquist 9 years ago
parent
commit
fa309ec925

+ 24 - 20
pkg/models/alert_notifications.go

@@ -7,30 +7,33 @@ import (
 )
 
 type AlertNotification struct {
-	Id       int64            `json:"id"`
-	OrgId    int64            `json:"-"`
-	Name     string           `json:"name"`
-	Type     string           `json:"type"`
-	Settings *simplejson.Json `json:"settings"`
-	Created  time.Time        `json:"created"`
-	Updated  time.Time        `json:"updated"`
+	Id            int64            `json:"id"`
+	OrgId         int64            `json:"-"`
+	Name          string           `json:"name"`
+	Type          string           `json:"type"`
+	AlwaysExecute bool             `json:"alwaysExecute"`
+	Settings      *simplejson.Json `json:"settings"`
+	Created       time.Time        `json:"created"`
+	Updated       time.Time        `json:"updated"`
 }
 
 type CreateAlertNotificationCommand struct {
-	Name     string           `json:"name"  binding:"Required"`
-	Type     string           `json:"type"  binding:"Required"`
-	OrgID    int64            `json:"-"`
-	Settings *simplejson.Json `json:"settings"`
+	Name          string           `json:"name"  binding:"Required"`
+	Type          string           `json:"type"  binding:"Required"`
+	AlwaysExecute bool             `json:"alwaysExecute"`
+	OrgID         int64            `json:"-"`
+	Settings      *simplejson.Json `json:"settings"`
 
 	Result *AlertNotification
 }
 
 type UpdateAlertNotificationCommand struct {
-	Id       int64            `json:"id"  binding:"Required"`
-	Name     string           `json:"name"  binding:"Required"`
-	Type     string           `json:"type"  binding:"Required"`
-	OrgID    int64            `json:"-"`
-	Settings *simplejson.Json `json:"settings"  binding:"Required"`
+	Id            int64            `json:"id"  binding:"Required"`
+	Name          string           `json:"name"  binding:"Required"`
+	Type          string           `json:"type"  binding:"Required"`
+	AlwaysExecute bool             `json:"alwaysExecute"`
+	OrgID         int64            `json:"-"`
+	Settings      *simplejson.Json `json:"settings"  binding:"Required"`
 
 	Result *AlertNotification
 }
@@ -41,10 +44,11 @@ type DeleteAlertNotificationCommand struct {
 }
 
 type GetAlertNotificationQuery struct {
-	Name  string
-	Id    int64
-	Ids   []int64
-	OrgID int64
+	Name                 string
+	Id                   int64
+	Ids                  []int64
+	OrgID                int64
+	IncludeAlwaysExecute bool
 
 	Result []*AlertNotification
 }

+ 2 - 0
pkg/services/alerting/alert_rule.go

@@ -63,6 +63,8 @@ func NewAlertRuleFromDBModel(ruleDef *m.Alert) (*AlertRule, error) {
 	model.State = ruleDef.State
 	model.Frequency = ruleDef.Frequency
 
+	model.NotificationGroups = []int64{1, 2}
+
 	critical := ruleDef.Settings.Get("crit")
 	model.Critical = Level{
 		Operator: critical.Get("op").MustString(),

+ 8 - 5
pkg/services/alerting/notifier.go

@@ -22,12 +22,12 @@ func NewNotifier() *NotifierImpl {
 }
 
 func (n *NotifierImpl) Notify(alertResult *AlertResult) {
-	notifiers := n.getNotifiers(alertResult.AlertJob.Rule.OrgId, []int64{1, 2})
+	notifiers := n.getNotifiers(alertResult.AlertJob.Rule.OrgId, alertResult.AlertJob.Rule.NotificationGroups)
 
 	for _, notifier := range notifiers {
 		warn := alertResult.State == alertstates.Warn && notifier.SendWarning
 		crit := alertResult.State == alertstates.Critical && notifier.SendCritical
-		if warn || crit {
+		if (warn || crit) || alertResult.State == alertstates.Ok {
 			n.log.Info("Sending notification", "state", alertResult.State, "type", notifier.Type)
 			go notifier.Notifierr.Dispatch(alertResult)
 		}
@@ -109,8 +109,9 @@ type NotificationDispatcher interface {
 
 func (n *NotifierImpl) getNotifiers(orgId int64, notificationGroups []int64) []*Notification {
 	query := &m.GetAlertNotificationQuery{
-		OrgID: orgId,
-		Ids:   notificationGroups,
+		OrgID:                orgId,
+		Ids:                  notificationGroups,
+		IncludeAlwaysExecute: true,
 	}
 	err := bus.Dispatch(query)
 	if err != nil {
@@ -118,11 +119,13 @@ func (n *NotifierImpl) getNotifiers(orgId int64, notificationGroups []int64) []*
 	}
 
 	var result []*Notification
-
+	n.log.Info("notifiriring", "count", len(query.Result), "groups", notificationGroups)
 	for _, notification := range query.Result {
 		not, err := NewNotificationFromDBModel(notification)
 		if err == nil {
 			result = append(result, not)
+		} else {
+			n.log.Error("Failed to read notification model", "error", err)
 		}
 	}
 

+ 0 - 2
pkg/services/notifications/send_email_integration_test.go

@@ -22,9 +22,7 @@ func TestEmailIntegrationTest(t *testing.T) {
 		err := Init()
 		So(err, ShouldBeNil)
 
-		var sentMsg *Message
 		addToMailQueue = func(msg *Message) {
-			sentMsg = msg
 			ioutil.WriteFile("../../../tmp/test_email.html", []byte(msg.Body), 0777)
 		}
 

+ 38 - 12
pkg/services/sqlstore/alert_notification.go

@@ -46,7 +46,8 @@ func getAlertNotifications(query *m.GetAlertNotificationQuery, sess *xorm.Sessio
 	                      alert_notification.type,
 	   					  alert_notification.created,
 	                      alert_notification.updated,
-	                      alert_notification.settings
+	                      alert_notification.settings,
+						  alert_notification.always_execute
 	   					  FROM alert_notification
 	   					  `)
 
@@ -77,18 +78,43 @@ func getAlertNotifications(query *m.GetAlertNotificationQuery, sess *xorm.Sessio
 		sql.WriteString(`)`)
 	}
 
-	var result []*m.AlertNotification
-	if err := sess.Sql(sql.String(), params...).Find(&result); err != nil {
+	var searches []*m.AlertNotification
+	if err := sess.Sql(sql.String(), params...).Find(&searches); err != nil {
 		return err
 	}
 
+	var result []*m.AlertNotification
+	var def []*m.AlertNotification
+	if query.IncludeAlwaysExecute {
+
+		if err := sess.Where("org_id = ? AND always_execute = 1", query.OrgID).Find(&def); err != nil {
+			return err
+		}
+
+		result = append(result, def...)
+	}
+
+	for _, s := range searches {
+		canAppend := true
+		for _, d := range result {
+			if d.Id == s.Id {
+				canAppend = false
+				break
+			}
+		}
+
+		if canAppend {
+			result = append(result, s)
+		}
+	}
+
 	query.Result = result
 	return nil
 }
 
 func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error {
 	return inTransaction(func(sess *xorm.Session) error {
-		existingQuery := &m.GetAlertNotificationQuery{OrgID: cmd.OrgID, Name: cmd.Name}
+		existingQuery := &m.GetAlertNotificationQuery{OrgID: cmd.OrgID, Name: cmd.Name, IncludeAlwaysExecute: false}
 		err := getAlertNotifications(existingQuery, sess)
 
 		if err != nil {
@@ -100,12 +126,13 @@ func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error
 		}
 
 		alertNotification := &m.AlertNotification{
-			OrgId:    cmd.OrgID,
-			Name:     cmd.Name,
-			Type:     cmd.Type,
-			Created:  time.Now(),
-			Settings: cmd.Settings,
-			Updated:  time.Now(),
+			OrgId:         cmd.OrgID,
+			Name:          cmd.Name,
+			Type:          cmd.Type,
+			Created:       time.Now(),
+			Settings:      cmd.Settings,
+			Updated:       time.Now(),
+			AlwaysExecute: cmd.AlwaysExecute,
 		}
 
 		_, err = sess.Insert(alertNotification)
@@ -114,7 +141,6 @@ func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error
 			return err
 		}
 
-		//alertNotification.Id = int(id)
 		cmd.Result = alertNotification
 		return nil
 	})
@@ -137,9 +163,9 @@ func UpdateAlertNotification(cmd *m.UpdateAlertNotificationCommand) error {
 		alertNotification.Settings = cmd.Settings
 		alertNotification.Updated = time.Now()
 		alertNotification.Created = current.Created
+		alertNotification.AlwaysExecute = cmd.AlwaysExecute
 
 		var affected int64
-		//affected, err = sess.Id(alertNotification.Id).Cols("name", "type", "settings", "updated").Update(alertNotification)
 		affected, err = sess.Id(alertNotification.Id).Update(alertNotification)
 
 		if err != nil {

+ 34 - 11
pkg/services/sqlstore/alert_notification_test.go

@@ -28,10 +28,11 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
 
 		Convey("Can save Alert Notification", func() {
 			cmd := &m.CreateAlertNotificationCommand{
-				Name:     "ops",
-				Type:     "email",
-				OrgID:    1,
-				Settings: simplejson.New(),
+				Name:          "ops",
+				Type:          "email",
+				OrgID:         1,
+				Settings:      simplejson.New(),
+				AlwaysExecute: true,
 			}
 
 			err = CreateAlertNotificationCommand(cmd)
@@ -39,6 +40,7 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
 			So(cmd.Result.Id, ShouldNotEqual, 0)
 			So(cmd.Result.OrgId, ShouldNotEqual, 0)
 			So(cmd.Result.Type, ShouldEqual, "email")
+			So(cmd.Result.AlwaysExecute, ShouldEqual, true)
 
 			Convey("Cannot save Alert Notification with the same name", func() {
 				err = CreateAlertNotificationCommand(cmd)
@@ -47,11 +49,12 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
 
 			Convey("Can update alert notification", func() {
 				newCmd := &m.UpdateAlertNotificationCommand{
-					Name:     "NewName",
-					Type:     "webhook",
-					OrgID:    cmd.Result.OrgId,
-					Settings: simplejson.New(),
-					Id:       cmd.Result.Id,
+					Name:          "NewName",
+					Type:          "webhook",
+					OrgID:         cmd.Result.OrgId,
+					Settings:      simplejson.New(),
+					Id:            cmd.Result.Id,
+					AlwaysExecute: true,
 				}
 				err := UpdateAlertNotification(newCmd)
 				So(err, ShouldBeNil)
@@ -60,6 +63,14 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
 		})
 
 		Convey("Can search using an array of ids", func() {
+			So(CreateAlertNotificationCommand(&m.CreateAlertNotificationCommand{
+				Name:          "nagios",
+				Type:          "webhook",
+				OrgID:         1,
+				Settings:      simplejson.New(),
+				AlwaysExecute: true,
+			}), ShouldBeNil)
+
 			So(CreateAlertNotificationCommand(&m.CreateAlertNotificationCommand{
 				Name:     "ops2",
 				Type:     "email",
@@ -75,14 +86,26 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
 			}), ShouldBeNil)
 
 			Convey("search", func() {
+				existingNotification := int64(2)
+				missingThatSholdNotCauseerrors := int64(99)
+
 				query := &m.GetAlertNotificationQuery{
-					Ids:   []int64{1, 2, 3},
-					OrgID: 1,
+					Ids:                  []int64{existingNotification, missingThatSholdNotCauseerrors},
+					OrgID:                1,
+					IncludeAlwaysExecute: true,
 				}
 
 				err := AlertNotificationQuery(query)
 				So(err, ShouldBeNil)
 				So(len(query.Result), ShouldEqual, 2)
+				defaultNotifications := 0
+				for _, not := range query.Result {
+					if not.AlwaysExecute {
+						defaultNotifications++
+					}
+				}
+
+				So(defaultNotifications, ShouldEqual, 1)
 			})
 		})
 	})

+ 1 - 0
pkg/services/sqlstore/migrations/alert_mig.go

@@ -74,6 +74,7 @@ func addAlertMigrations(mg *Migrator) {
 			{Name: "org_id", Type: DB_BigInt, Nullable: false},
 			{Name: "name", Type: DB_NVarchar, Length: 255, Nullable: false},
 			{Name: "type", Type: DB_NVarchar, Length: 255, Nullable: false},
+			{Name: "always_execute", Type: DB_Bool, Nullable: false},
 			{Name: "settings", Type: DB_Text, Nullable: false},
 			{Name: "created", Type: DB_DateTime, Nullable: false},
 			{Name: "updated", Type: DB_DateTime, Nullable: false},