Commit b5a29b62 by bergquist

test(alerting): add tests for when to send notifcations

parent 6edae37a
...@@ -12,27 +12,33 @@ import ( ...@@ -12,27 +12,33 @@ import (
) )
type NotifierImpl struct { type NotifierImpl struct {
log log.Logger log log.Logger
getNotifications func(orgId int64, notificationGroups []int64) []*Notification
} }
func NewNotifier() *NotifierImpl { func NewNotifier() *NotifierImpl {
log := log.New("alerting.notifier")
return &NotifierImpl{ return &NotifierImpl{
log: log.New("alerting.notifier"), log: log,
getNotifications: buildGetNotifiers(log),
} }
} }
func (n NotifierImpl) ShouldDispath(alertResult *AlertResult, notifier *Notification) bool {
warn := alertResult.State == alertstates.Warn && notifier.SendWarning
crit := alertResult.State == alertstates.Critical && notifier.SendCritical
return (warn || crit) || alertResult.State == alertstates.Ok
}
func (n *NotifierImpl) Notify(alertResult *AlertResult) { func (n *NotifierImpl) Notify(alertResult *AlertResult) {
notifiers := n.getNotifiers(alertResult.AlertJob.Rule.OrgId, alertResult.AlertJob.Rule.NotificationGroups) notifiers := n.getNotifications(alertResult.AlertJob.Rule.OrgId, alertResult.AlertJob.Rule.NotificationGroups)
for _, notifier := range notifiers { for _, notifier := range notifiers {
warn := alertResult.State == alertstates.Warn && notifier.SendWarning if n.ShouldDispath(alertResult, notifier) {
crit := alertResult.State == alertstates.Critical && notifier.SendCritical
if (warn || crit) || alertResult.State == alertstates.Ok {
n.log.Info("Sending notification", "state", alertResult.State, "type", notifier.Type) n.log.Info("Sending notification", "state", alertResult.State, "type", notifier.Type)
go notifier.Notifierr.Dispatch(alertResult) go notifier.Notifierr.Dispatch(alertResult)
} }
} }
} }
type Notification struct { type Notification struct {
...@@ -107,29 +113,31 @@ type NotificationDispatcher interface { ...@@ -107,29 +113,31 @@ type NotificationDispatcher interface {
Dispatch(alertResult *AlertResult) Dispatch(alertResult *AlertResult)
} }
func (n *NotifierImpl) getNotifiers(orgId int64, notificationGroups []int64) []*Notification { func buildGetNotifiers(log log.Logger) func(orgId int64, notificationGroups []int64) []*Notification {
query := &m.GetAlertNotificationQuery{ return func(orgId int64, notificationGroups []int64) []*Notification {
OrgID: orgId, query := &m.GetAlertNotificationQuery{
Ids: notificationGroups, OrgID: orgId,
IncludeAlwaysExecute: true, Ids: notificationGroups,
} IncludeAlwaysExecute: true,
err := bus.Dispatch(query) }
if err != nil { err := bus.Dispatch(query)
n.log.Error("Failed to read notifications", "error", err) if err != nil {
} log.Error("Failed to read notifications", "error", err)
}
var result []*Notification var result []*Notification
n.log.Info("notifiriring", "count", len(query.Result), "groups", notificationGroups) log.Info("notifiriring", "count", len(query.Result), "groups", notificationGroups)
for _, notification := range query.Result { for _, notification := range query.Result {
not, err := NewNotificationFromDBModel(notification) not, err := NewNotificationFromDBModel(notification)
if err == nil { if err == nil {
result = append(result, not) result = append(result, not)
} else { } else {
n.log.Error("Failed to read notification model", "error", err) log.Error("Failed to read notification model", "error", err)
}
} }
}
return result return result
}
} }
func NewNotificationFromDBModel(model *m.AlertNotification) (*Notification, error) { func NewNotificationFromDBModel(model *m.AlertNotification) (*Notification, error) {
......
...@@ -7,93 +7,119 @@ import ( ...@@ -7,93 +7,119 @@ import (
"github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/components/simplejson"
m "github.com/grafana/grafana/pkg/models" m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/alerting/alertstates"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
) )
func TestAlertNotificationExtraction(t *testing.T) { func TestAlertNotificationExtraction(t *testing.T) {
Convey("Notifier tests", t, func() {
Convey("rules for sending notifications", func() {
dummieNotifier := NotifierImpl{}
result := &AlertResult{
State: alertstates.Critical,
}
notifier := &Notification{
Name: "Test Notifier",
Type: "TestType",
SendCritical: true,
SendWarning: true,
}
Convey("Should send notification", func() {
So(dummieNotifier.ShouldDispath(result, notifier), ShouldBeTrue)
})
Convey("Parsing alert notification from settings", t, func() { Convey("warn:false and state:warn should not send", func() {
Convey("Parsing email", func() { result.State = alertstates.Warn
Convey("empty settings should return error", func() { notifier.SendWarning = false
json := `{ }` So(dummieNotifier.ShouldDispath(result, notifier), ShouldBeFalse)
})
})
settingsJSON, _ := simplejson.NewJson([]byte(json)) Convey("Parsing alert notification from settings", func() {
model := &m.AlertNotification{ Convey("Parsing email", func() {
Name: "ops", Convey("empty settings should return error", func() {
Type: "email", json := `{ }`
Settings: settingsJSON,
}
_, err := NewNotificationFromDBModel(model) settingsJSON, _ := simplejson.NewJson([]byte(json))
So(err, ShouldNotBeNil) model := &m.AlertNotification{
}) Name: "ops",
Type: "email",
Settings: settingsJSON,
}
Convey("from settings", func() { _, err := NewNotificationFromDBModel(model)
json := ` So(err, ShouldNotBeNil)
})
Convey("from settings", func() {
json := `
{ {
"to": "ops@grafana.org" "to": "ops@grafana.org"
}` }`
settingsJSON, _ := simplejson.NewJson([]byte(json)) settingsJSON, _ := simplejson.NewJson([]byte(json))
model := &m.AlertNotification{ model := &m.AlertNotification{
Name: "ops", Name: "ops",
Type: "email", Type: "email",
Settings: settingsJSON, Settings: settingsJSON,
} }
not, err := NewNotificationFromDBModel(model) not, err := NewNotificationFromDBModel(model)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(not.Name, ShouldEqual, "ops") So(not.Name, ShouldEqual, "ops")
So(not.Type, ShouldEqual, "email") So(not.Type, ShouldEqual, "email")
So(reflect.TypeOf(not.Notifierr).Elem().String(), ShouldEqual, "alerting.EmailNotifier") So(reflect.TypeOf(not.Notifierr).Elem().String(), ShouldEqual, "alerting.EmailNotifier")
email := not.Notifierr.(*EmailNotifier) email := not.Notifierr.(*EmailNotifier)
So(email.To, ShouldEqual, "ops@grafana.org") So(email.To, ShouldEqual, "ops@grafana.org")
})
}) })
})
Convey("Parsing webhook", func() { Convey("Parsing webhook", func() {
Convey("empty settings should return error", func() { Convey("empty settings should return error", func() {
json := `{ }` json := `{ }`
settingsJSON, _ := simplejson.NewJson([]byte(json)) settingsJSON, _ := simplejson.NewJson([]byte(json))
model := &m.AlertNotification{ model := &m.AlertNotification{
Name: "ops", Name: "ops",
Type: "webhook", Type: "webhook",
Settings: settingsJSON, Settings: settingsJSON,
} }
_, err := NewNotificationFromDBModel(model) _, err := NewNotificationFromDBModel(model)
So(err, ShouldNotBeNil) So(err, ShouldNotBeNil)
}) })
Convey("from settings", func() { Convey("from settings", func() {
json := ` json := `
{ {
"url": "http://localhost:3000", "url": "http://localhost:3000",
"username": "username", "username": "username",
"password": "password" "password": "password"
}` }`
settingsJSON, _ := simplejson.NewJson([]byte(json)) settingsJSON, _ := simplejson.NewJson([]byte(json))
model := &m.AlertNotification{ model := &m.AlertNotification{
Name: "slack", Name: "slack",
Type: "webhook", Type: "webhook",
Settings: settingsJSON, Settings: settingsJSON,
} }
not, err := NewNotificationFromDBModel(model) not, err := NewNotificationFromDBModel(model)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(not.Name, ShouldEqual, "slack") So(not.Name, ShouldEqual, "slack")
So(not.Type, ShouldEqual, "webhook") So(not.Type, ShouldEqual, "webhook")
So(reflect.TypeOf(not.Notifierr).Elem().String(), ShouldEqual, "alerting.WebhookNotifier") So(reflect.TypeOf(not.Notifierr).Elem().String(), ShouldEqual, "alerting.WebhookNotifier")
webhook := not.Notifierr.(*WebhookNotifier) webhook := not.Notifierr.(*WebhookNotifier)
So(webhook.Url, ShouldEqual, "http://localhost:3000") So(webhook.Url, ShouldEqual, "http://localhost:3000")
})
}) })
}) })
}) })
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment