feat(alerting): more work on notifications

This commit is contained in:
Torkel Ödegaard 2016-07-23 11:50:48 +02:00
parent a6c6094775
commit 14eba30f63
3 changed files with 194 additions and 270 deletions

View File

@ -1,195 +1,197 @@
package alerting package alerting
// type NotifierImpl struct { import (
// log log.Logger "fmt"
// getNotifications func(orgId int64, notificationGroups []int64) []*Notification "log"
// } "strconv"
//
// func NewNotifier() *NotifierImpl {
// log := log.New("alerting.notifier")
// return &NotifierImpl{
// log: log,
// getNotifications: buildGetNotifiers(log),
// }
// }
// func (n NotifierImpl) ShouldDispath(alertResult *AlertResultContext, notifier *Notification) bool { "github.com/grafana/grafana/pkg/bus"
// warn := alertResult.State == alertstates.Warn && notifier.SendWarning "github.com/grafana/grafana/pkg/components/simplejson"
// crit := alertResult.State == alertstates.Critical && notifier.SendCritical "github.com/grafana/grafana/pkg/setting"
// return (warn || crit) || alertResult.State == alertstates.Ok )
// }
// type NotifierImpl struct {
// func (n *NotifierImpl) Notify(alertResult *AlertResultContext) { log log.Logger
// notifiers := n.getNotifications(alertResult.Rule.OrgId, alertResult.Rule.Notifications) getNotifications func(orgId int64, notificationGroups []int64) []*Notification
// }
// for _, notifier := range notifiers {
// if n.ShouldDispath(alertResult, notifier) { func NewNotifier() *NotifierImpl {
// n.log.Info("Sending notification", "state", alertResult.State, "type", notifier.Type) log := log.New("alerting.notifier")
// go notifier.Notifierr.Dispatch(alertResult) return &NotifierImpl{
// } log: log,
// } getNotifications: buildGetNotifiers(log),
// } }
// }
// type Notification struct {
// Name string func (n *NotifierImpl) Notify(alertResult *AlertResultContext) {
// Type string notifiers := n.getNotifications(alertResult.Rule.OrgId, alertResult.Rule.Notifications)
// SendWarning bool
// SendCritical bool for _, notifier := range notifiers {
// n.log.Info("Sending notification", "state", alertResult.State, "type", notifier.Type)
// Notifierr NotificationDispatcher go notifier.Notifierr.Dispatch(alertResult)
// } }
// }
// type EmailNotifier struct {
// To string type Notification struct {
// log log.Logger Name string
// } Type string
// SendWarning bool
// func (this *EmailNotifier) Dispatch(alertResult *AlertResult) { SendCritical bool
// this.log.Info("Sending email")
// grafanaUrl := fmt.Sprintf("%s:%s", setting.HttpAddr, setting.HttpPort) Notifierr NotificationDispatcher
// if setting.AppSubUrl != "" { }
// grafanaUrl += "/" + setting.AppSubUrl
// } type EmailNotifier struct {
// To string
// query := &m.GetDashboardsQuery{ log log.Logger
// DashboardIds: []int64{alertResult.AlertJob.Rule.DashboardId}, }
// }
// func (this *EmailNotifier) Dispatch(alertResult *AlertResult) {
// if err := bus.Dispatch(query); err != nil { this.log.Info("Sending email")
// this.log.Error("Failed to load dashboard", "error", err) grafanaUrl := fmt.Sprintf("%s:%s", setting.HttpAddr, setting.HttpPort)
// return if setting.AppSubUrl != "" {
// } grafanaUrl += "/" + setting.AppSubUrl
// }
// if len(query.Result) != 1 {
// this.log.Error("Can only support one dashboard", "result", len(query.Result)) query := &m.GetDashboardsQuery{
// return DashboardIds: []int64{alertResult.AlertJob.Rule.DashboardId},
// } }
//
// dashboard := query.Result[0] if err := bus.Dispatch(query); err != nil {
// this.log.Error("Failed to load dashboard", "error", err)
// panelId := strconv.Itoa(int(alertResult.AlertJob.Rule.PanelId)) return
// }
// //TODO: get from alertrule and transforms to seconds
// from := "1466169458375" if len(query.Result) != 1 {
// to := "1466171258375" this.log.Error("Can only support one dashboard", "result", len(query.Result))
// return
// renderUrl := fmt.Sprintf("%s/render/dashboard-solo/db/%s?from=%s&to=%s&panelId=%s&width=1000&height=500", grafanaUrl, dashboard.Slug, from, to, panelId) }
// cmd := &m.SendEmailCommand{
// Data: map[string]interface{}{ dashboard := query.Result[0]
// "Name": "Name",
// "State": alertResult.State, panelId := strconv.Itoa(int(alertResult.AlertJob.Rule.PanelId))
// "Description": alertResult.Description,
// "TriggeredAlerts": alertResult.TriggeredAlerts, //TODO: get from alertrule and transforms to seconds
// "DashboardLink": grafanaUrl + "/dashboard/db/" + dashboard.Slug, from := "1466169458375"
// "AlertPageUrl": grafanaUrl + "/alerting", to := "1466171258375"
// "DashboardImage": renderUrl,
// }, renderUrl := fmt.Sprintf("%s/render/dashboard-solo/db/%s?from=%s&to=%s&panelId=%s&width=1000&height=500", grafanaUrl, dashboard.Slug, from, to, panelId)
// To: []string{this.To}, cmd := &m.SendEmailCommand{
// Template: "alert_notification.html", Data: map[string]interface{}{
// } "Name": "Name",
// "State": alertResult.State,
// err := bus.Dispatch(cmd) "Description": alertResult.Description,
// if err != nil { "TriggeredAlerts": alertResult.TriggeredAlerts,
// this.log.Error("Could not send alert notification as email", "error", err) "DashboardLink": grafanaUrl + "/dashboard/db/" + dashboard.Slug,
// } "AlertPageUrl": grafanaUrl + "/alerting",
// } "DashboardImage": renderUrl,
// },
// type WebhookNotifier struct { To: []string{this.To},
// Url string Template: "alert_notification.html",
// User string }
// Password string
// log log.Logger err := bus.Dispatch(cmd)
// } if err != nil {
// this.log.Error("Could not send alert notification as email", "error", err)
// func (this *WebhookNotifier) Dispatch(alertResult *AlertResultContext) { }
// this.log.Info("Sending webhook") }
//
// bodyJSON := simplejson.New() type WebhookNotifier struct {
// bodyJSON.Set("name", alertResult.AlertJob.Rule.Name) Url string
// bodyJSON.Set("state", alertResult.State) User string
// bodyJSON.Set("trigged", alertResult.TriggeredAlerts) Password string
// log log.Logger
// body, _ := bodyJSON.MarshalJSON() }
//
// cmd := &m.SendWebhook{ func (this *WebhookNotifier) Dispatch(alertResult *AlertResultContext) {
// Url: this.Url, this.log.Info("Sending webhook")
// User: this.User,
// Password: this.Password, bodyJSON := simplejson.New()
// Body: string(body), bodyJSON.Set("name", alertResult.AlertJob.Rule.Name)
// } bodyJSON.Set("state", alertResult.State)
// bodyJSON.Set("trigged", alertResult.TriggeredAlerts)
// bus.Dispatch(cmd)
// } body, _ := bodyJSON.MarshalJSON()
//
// type NotificationDispatcher interface { cmd := &m.SendWebhook{
// Dispatch(alertResult *AlertResult) Url: this.Url,
// } User: this.User,
// Password: this.Password,
// func buildGetNotifiers(log log.Logger) func(orgId int64, notificationGroups []int64) []*Notification { Body: string(body),
// return func(orgId int64, notificationGroups []int64) []*Notification { }
// query := &m.GetAlertNotificationQuery{
// OrgID: orgId, bus.Dispatch(cmd)
// Ids: notificationGroups, }
// IncludeAlwaysExecute: true,
// } type NotificationDispatcher interface {
// err := bus.Dispatch(query) Dispatch(alertResult *AlertResult)
// if err != nil { }
// log.Error("Failed to read notifications", "error", err)
// } func buildGetNotifiers(log log.Logger) func(orgId int64, notificationGroups []int64) []*Notification {
// return func(orgId int64, notificationGroups []int64) []*Notification {
// var result []*Notification query := &m.GetAlertNotificationQuery{
// for _, notification := range query.Result { OrgID: orgId,
// not, err := NewNotificationFromDBModel(notification) Ids: notificationGroups,
// if err == nil { IncludeAlwaysExecute: true,
// result = append(result, not) }
// } else { err := bus.Dispatch(query)
// log.Error("Failed to read notification model", "error", err) if err != nil {
// } log.Error("Failed to read notifications", "error", err)
// } }
//
// return result var result []*Notification
// } for _, notification := range query.Result {
// } not, err := NewNotificationFromDBModel(notification)
// if err == nil {
// func NewNotificationFromDBModel(model *m.AlertNotification) (*Notification, error) { result = append(result, not)
// notifier, err := createNotifier(model.Type, model.Settings) } else {
// log.Error("Failed to read notification model", "error", err)
// if err != nil { }
// return nil, err }
// }
// return result
// return &Notification{ }
// Name: model.Name, }
// Type: model.Type,
// Notifierr: notifier, func NewNotificationFromDBModel(model *m.AlertNotification) (*Notification, error) {
// SendCritical: model.Settings.Get("sendCrit").MustBool(), notifier, err := createNotifier(model.Type, model.Settings)
// SendWarning: model.Settings.Get("sendWarn").MustBool(),
// }, nil if err != nil {
// } return nil, err
// }
// var createNotifier = func(notificationType string, settings *simplejson.Json) (NotificationDispatcher, error) {
// if notificationType == "email" { return &Notification{
// to := settings.Get("to").MustString() Name: model.Name,
// Type: model.Type,
// if to == "" { Notifierr: notifier,
// return nil, fmt.Errorf("Could not find to propertie in settings") SendCritical: model.Settings.Get("sendCrit").MustBool(),
// } SendWarning: model.Settings.Get("sendWarn").MustBool(),
// }, nil
// return &EmailNotifier{ }
// To: to,
// log: log.New("alerting.notification.email"), var createNotifier = func(notificationType string, settings *simplejson.Json) (NotificationDispatcher, error) {
// }, nil if notificationType == "email" {
// } to := settings.Get("to").MustString()
//
// url := settings.Get("url").MustString() if to == "" {
// if url == "" { return nil, fmt.Errorf("Could not find to propertie in settings")
// return nil, fmt.Errorf("Could not find url propertie in settings") }
// }
// return &EmailNotifier{
// return &WebhookNotifier{ To: to,
// Url: url, log: log.New("alerting.notification.email"),
// User: settings.Get("user").MustString(), }, nil
// Password: settings.Get("password").MustString(), }
// log: log.New("alerting.notification.webhook"),
// }, nil url := settings.Get("url").MustString()
// } if url == "" {
return nil, fmt.Errorf("Could not find url propertie in settings")
}
return &WebhookNotifier{
Url: url,
User: settings.Get("user").MustString(),
Password: settings.Get("password").MustString(),
log: log.New("alerting.notification.webhook"),
}, nil
}

View File

@ -1,71 +0,0 @@
package transformers
import (
"fmt"
"math"
"github.com/grafana/grafana/pkg/tsdb"
)
func NewAggregationTransformer(method string) *AggregationTransformer {
return &AggregationTransformer{
Method: method,
}
}
type AggregationTransformer struct {
Method string
}
func (at *AggregationTransformer) Transform(timeserie *tsdb.TimeSeries) (float64, error) {
if at.Method == "avg" {
sum := float64(0)
for _, point := range timeserie.Points {
sum += point[0]
}
return sum / float64(len(timeserie.Points)), nil
}
if at.Method == "sum" {
sum := float64(0)
for _, v := range timeserie.Points {
sum += v[0]
}
return sum, nil
}
if at.Method == "min" {
min := timeserie.Points[0][0]
for _, v := range timeserie.Points {
if v[0] < min {
min = v[0]
}
}
return min, nil
}
if at.Method == "max" {
max := timeserie.Points[0][0]
for _, v := range timeserie.Points {
if v[0] > max {
max = v[0]
}
}
return max, nil
}
if at.Method == "mean" {
midPosition := int64(math.Floor(float64(len(timeserie.Points)) / float64(2)))
return timeserie.Points[midPosition][0], nil
}
return float64(0), fmt.Errorf("Missing method")
}

View File

@ -1,7 +0,0 @@
package transformers
import "github.com/grafana/grafana/pkg/tsdb"
type Transformer interface {
Transform(timeserie *tsdb.TimeSeries) (float64, error)
}