Commit 9a841641 by bergquist

feat(alerting): converter for db model to notification

parent 6eca26e8
......@@ -38,7 +38,8 @@ type UpdateAlertNotificationCommand struct {
type GetAlertNotificationQuery struct {
Name string
ID int64
Id int64
Ids []int64
OrgID int64
Result []*AlertNotification
......
package alerting
import (
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/log"
m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/alerting/alertstates"
)
type Notifier struct {
log log.Logger
}
func NewNotifier() *Notifier {
return &Notifier{
log: log.New("alerting.notifier"),
}
}
func (n *Notifier) Notify(alertResult AlertResult) {
notifiers := 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 {
n.log.Info("Sending notification", "state", alertResult.State, "type", notifier.Type)
go notifier.Notifierr.Notify(alertResult)
}
}
}
type Notification struct {
Name string
Type string
SendWarning bool
SendCritical bool
Notifierr Notifierr
}
type EmailNotifier struct {
To string
From string
}
func (this EmailNotifier) Notify(alertResult AlertResult) {
//bus.dispath to notification package in grafana
}
type WebhookNotifier struct {
Url string
AuthUser string
AuthPassword string
}
func (this WebhookNotifier) Notify(alertResult AlertResult) {
//bus.dispath to notification package in grafana
}
type Notifierr interface {
Notify(alertResult AlertResult)
}
func getNotifiers(orgId int64, notificationGroups []int64) []*Notification {
var notifications []*m.AlertNotification
for _, notificationId := range notificationGroups {
query := m.GetAlertNotificationQuery{
OrgID: orgId,
Id: notificationId,
}
notifications = append(notifications, query.Result...)
}
var result []*Notification
for _, notification := range notifications {
not, err := NewNotificationFromDBModel(notification)
if err == nil {
result = append(result, not)
}
}
return result
}
func NewNotificationFromDBModel(model *m.AlertNotification) (*Notification, error) {
return &Notification{
Name: model.Name,
Type: model.Type,
Notifierr: createNotifier(model.Type, model.Settings),
SendCritical: !model.Settings.Get("ignoreCrit").MustBool(),
SendWarning: !model.Settings.Get("ignoreWarn").MustBool(),
}, nil
}
var createNotifier = func(notificationType string, settings *simplejson.Json) Notifierr {
if notificationType == "email" {
return &EmailNotifier{
To: settings.Get("to").MustString(),
From: settings.Get("from").MustString(),
}
}
return &WebhookNotifier{
Url: settings.Get("url").MustString(),
AuthUser: settings.Get("user").MustString(),
AuthPassword: settings.Get("password").MustString(),
}
}
package alerting
import (
"testing"
"reflect"
"github.com/grafana/grafana/pkg/components/simplejson"
m "github.com/grafana/grafana/pkg/models"
. "github.com/smartystreets/goconvey/convey"
)
func TestAlertNotificationExtraction(t *testing.T) {
Convey("Parsing alert notification from settings", t, func() {
Convey("Parsing email notification from settings", func() {
json := `
{
"from": "alerting@grafana.org",
"to": "ops@grafana.org"
}`
settingsJSON, _ := simplejson.NewJson([]byte(json))
model := &m.AlertNotification{
Name: "ops",
Type: "email",
Settings: settingsJSON,
}
not, err := NewNotificationFromDBModel(model)
So(err, ShouldBeNil)
So(not.Name, ShouldEqual, "ops")
So(not.Type, ShouldEqual, "email")
So(reflect.TypeOf(not.Notifierr).Elem().String(), ShouldEqual, "alerting.EmailNotifier")
email := not.Notifierr.(*EmailNotifier)
So(email.To, ShouldEqual, "ops@grafana.org")
So(email.From, ShouldEqual, "alerting@grafana.org")
})
Convey("Parsing webhook notification from settings", func() {
json := `
{
"url": "http://localhost:3000",
"username": "username",
"password": "password"
}`
settingsJSON, _ := simplejson.NewJson([]byte(json))
model := &m.AlertNotification{
Name: "slack",
Type: "webhook",
Settings: settingsJSON,
}
not, err := NewNotificationFromDBModel(model)
So(err, ShouldBeNil)
So(not.Name, ShouldEqual, "slack")
So(not.Type, ShouldEqual, "webhook")
So(reflect.TypeOf(not.Notifierr).Elem().String(), ShouldEqual, "alerting.WebhookNotifier")
webhook := not.Notifierr.(*WebhookNotifier)
So(webhook.Url, ShouldEqual, "http://localhost:3000")
})
})
}
......@@ -3,6 +3,7 @@ package sqlstore
import (
"bytes"
"fmt"
"strconv"
"time"
"github.com/go-xorm/xorm"
......@@ -43,6 +44,25 @@ func getAlertNotifications(query *m.GetAlertNotificationQuery, sess *xorm.Sessio
params = append(params, query.Name)
}
if query.Id != 0 {
sql.WriteString(` AND alert_notification.id = ?`)
params = append(params, strconv.Itoa(int(query.Id)))
}
if len(query.Ids) > 0 {
sql.WriteString(` AND (`)
for i, id := range query.Ids {
if i != 0 {
sql.WriteString(` OR`)
}
sql.WriteString(` alert_notification.id = ?`)
params = append(params, id)
}
sql.WriteString(`)`)
}
var result []*m.AlertNotification
if err := sess.Sql(sql.String(), params...).Find(&result); err != nil {
return err
......@@ -71,15 +91,16 @@ func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error
Type: cmd.Type,
Created: time.Now(),
Settings: cmd.Settings,
Updated: time.Now(),
}
id, err := sess.Insert(alertNotification)
_, err = sess.Insert(alertNotification)
if err != nil {
return err
}
alertNotification.Id = id
//alertNotification.Id = int(id)
cmd.Result = alertNotification
return nil
})
......@@ -87,30 +108,34 @@ func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error
func UpdateAlertNotification(cmd *m.UpdateAlertNotificationCommand) error {
return inTransaction(func(sess *xorm.Session) (err error) {
alertNotification := &m.AlertNotification{}
var has bool
has, err = sess.Id(cmd.Id).Get(alertNotification)
current := &m.AlertNotification{}
_, err = sess.Id(cmd.Id).Get(current)
if err != nil {
return err
}
if !has {
return fmt.Errorf("Alert notification does not exist")
}
alertNotification := &m.AlertNotification{}
alertNotification.Id = cmd.Id
alertNotification.OrgId = cmd.OrgID
alertNotification.Name = cmd.Name
alertNotification.Type = cmd.Type
alertNotification.Settings = cmd.Settings
alertNotification.Updated = time.Now()
alertNotification.Created = current.Created
_, err = sess.Id(alertNotification.Id).Cols("name", "type", "settings", "updated").Update(alertNotification)
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 {
return err
}
if affected == 0 {
return fmt.Errorf("Could not find alert notification")
}
cmd.Result = alertNotification
return nil
})
......
......@@ -4,6 +4,7 @@ import (
"fmt"
"testing"
"github.com/grafana/grafana/pkg/components/simplejson"
m "github.com/grafana/grafana/pkg/models"
. "github.com/smartystreets/goconvey/convey"
)
......@@ -27,40 +28,61 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
Convey("Can save Alert Notification", func() {
cmd := &m.CreateAlertNotificationCommand{
Name: "ops",
Type: "email",
Name: "ops",
Type: "email",
OrgID: 1,
Settings: simplejson.New(),
}
err = CreateAlertNotificationCommand(cmd)
So(err, ShouldBeNil)
So(cmd.Result.Id, ShouldNotEqual, 0)
So(cmd.Result.OrgId, ShouldNotEqual, 0)
So(cmd.Result.Type, ShouldEqual, "email")
Convey("Cannot save Alert Notification with the same name", func() {
err = CreateAlertNotificationCommand(cmd)
So(err, ShouldNotBeNil)
})
Convey("Cannot update alert notification that does not exist", func() {
Convey("Can update alert notification", func() {
newCmd := &m.UpdateAlertNotificationCommand{
Name: "NewName",
Type: cmd.Result.Type,
OrgID: cmd.Result.OrgId,
Id: 1337,
Name: "NewName",
Type: "webhook",
OrgID: cmd.Result.OrgId,
Settings: simplejson.New(),
Id: cmd.Result.Id,
}
err = UpdateAlertNotification(newCmd)
So(err, ShouldNotBeNil)
err := UpdateAlertNotification(newCmd)
So(err, ShouldBeNil)
So(newCmd.Result.Name, ShouldEqual, "NewName")
})
})
Convey("Can update alert notification", func() {
newCmd := &m.UpdateAlertNotificationCommand{
Name: "NewName",
Type: cmd.Result.Type,
OrgID: cmd.Result.OrgId,
Id: cmd.Result.Id,
Convey("Can search using an array of ids", func() {
So(CreateAlertNotificationCommand(&m.CreateAlertNotificationCommand{
Name: "ops2",
Type: "email",
OrgID: 1,
Settings: simplejson.New(),
}), ShouldBeNil)
So(CreateAlertNotificationCommand(&m.CreateAlertNotificationCommand{
Name: "slack",
Type: "webhook",
OrgID: 1,
Settings: simplejson.New(),
}), ShouldBeNil)
Convey("search", func() {
query := &m.GetAlertNotificationQuery{
Ids: []int64{1, 2, 3},
OrgID: 1,
}
err = UpdateAlertNotification(newCmd)
err := AlertNotificationQuery(query)
So(err, ShouldBeNil)
So(newCmd.Result.Name, ShouldEqual, "NewName")
So(len(query.Result), ShouldEqual, 2)
})
})
})
......
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