mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(alerting): converter for db model to notification
This commit is contained in:
parent
6eca26e8ec
commit
9a8416416d
@ -38,7 +38,8 @@ type UpdateAlertNotificationCommand struct {
|
|||||||
|
|
||||||
type GetAlertNotificationQuery struct {
|
type GetAlertNotificationQuery struct {
|
||||||
Name string
|
Name string
|
||||||
ID int64
|
Id int64
|
||||||
|
Ids []int64
|
||||||
OrgID int64
|
OrgID int64
|
||||||
|
|
||||||
Result []*AlertNotification
|
Result []*AlertNotification
|
||||||
|
@ -1 +1,114 @@
|
|||||||
package alerting
|
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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
68
pkg/services/alerting/notifier_test.go
Normal file
68
pkg/services/alerting/notifier_test.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-xorm/xorm"
|
"github.com/go-xorm/xorm"
|
||||||
@ -43,6 +44,25 @@ func getAlertNotifications(query *m.GetAlertNotificationQuery, sess *xorm.Sessio
|
|||||||
params = append(params, query.Name)
|
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
|
var result []*m.AlertNotification
|
||||||
if err := sess.Sql(sql.String(), params...).Find(&result); err != nil {
|
if err := sess.Sql(sql.String(), params...).Find(&result); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -71,15 +91,16 @@ func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error
|
|||||||
Type: cmd.Type,
|
Type: cmd.Type,
|
||||||
Created: time.Now(),
|
Created: time.Now(),
|
||||||
Settings: cmd.Settings,
|
Settings: cmd.Settings,
|
||||||
|
Updated: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := sess.Insert(alertNotification)
|
_, err = sess.Insert(alertNotification)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
alertNotification.Id = id
|
//alertNotification.Id = int(id)
|
||||||
cmd.Result = alertNotification
|
cmd.Result = alertNotification
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -87,30 +108,34 @@ func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error
|
|||||||
|
|
||||||
func UpdateAlertNotification(cmd *m.UpdateAlertNotificationCommand) error {
|
func UpdateAlertNotification(cmd *m.UpdateAlertNotificationCommand) error {
|
||||||
return inTransaction(func(sess *xorm.Session) (err error) {
|
return inTransaction(func(sess *xorm.Session) (err error) {
|
||||||
alertNotification := &m.AlertNotification{}
|
current := &m.AlertNotification{}
|
||||||
|
_, err = sess.Id(cmd.Id).Get(current)
|
||||||
var has bool
|
|
||||||
has, err = sess.Id(cmd.Id).Get(alertNotification)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !has {
|
alertNotification := &m.AlertNotification{}
|
||||||
return fmt.Errorf("Alert notification does not exist")
|
alertNotification.Id = cmd.Id
|
||||||
}
|
alertNotification.OrgId = cmd.OrgID
|
||||||
|
|
||||||
alertNotification.Name = cmd.Name
|
alertNotification.Name = cmd.Name
|
||||||
alertNotification.Type = cmd.Type
|
alertNotification.Type = cmd.Type
|
||||||
alertNotification.Settings = cmd.Settings
|
alertNotification.Settings = cmd.Settings
|
||||||
alertNotification.Updated = time.Now()
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if affected == 0 {
|
||||||
|
return fmt.Errorf("Could not find alert notification")
|
||||||
|
}
|
||||||
|
|
||||||
cmd.Result = alertNotification
|
cmd.Result = alertNotification
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||||
m "github.com/grafana/grafana/pkg/models"
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
)
|
)
|
||||||
@ -27,41 +28,62 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
|
|||||||
|
|
||||||
Convey("Can save Alert Notification", func() {
|
Convey("Can save Alert Notification", func() {
|
||||||
cmd := &m.CreateAlertNotificationCommand{
|
cmd := &m.CreateAlertNotificationCommand{
|
||||||
Name: "ops",
|
Name: "ops",
|
||||||
Type: "email",
|
Type: "email",
|
||||||
|
OrgID: 1,
|
||||||
|
Settings: simplejson.New(),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = CreateAlertNotificationCommand(cmd)
|
err = CreateAlertNotificationCommand(cmd)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(cmd.Result.Id, ShouldNotEqual, 0)
|
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() {
|
Convey("Cannot save Alert Notification with the same name", func() {
|
||||||
err = CreateAlertNotificationCommand(cmd)
|
err = CreateAlertNotificationCommand(cmd)
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Cannot update alert notification that does not exist", func() {
|
|
||||||
newCmd := &m.UpdateAlertNotificationCommand{
|
|
||||||
Name: "NewName",
|
|
||||||
Type: cmd.Result.Type,
|
|
||||||
OrgID: cmd.Result.OrgId,
|
|
||||||
Id: 1337,
|
|
||||||
}
|
|
||||||
err = UpdateAlertNotification(newCmd)
|
|
||||||
So(err, ShouldNotBeNil)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("Can update alert notification", func() {
|
Convey("Can update alert notification", func() {
|
||||||
newCmd := &m.UpdateAlertNotificationCommand{
|
newCmd := &m.UpdateAlertNotificationCommand{
|
||||||
Name: "NewName",
|
Name: "NewName",
|
||||||
Type: cmd.Result.Type,
|
Type: "webhook",
|
||||||
OrgID: cmd.Result.OrgId,
|
OrgID: cmd.Result.OrgId,
|
||||||
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")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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 := AlertNotificationQuery(query)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(len(query.Result), ShouldEqual, 2)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user