mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(alerting): more work on notifications
This commit is contained in:
parent
a6c6094775
commit
14eba30f63
@ -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
|
||||||
|
}
|
||||||
|
@ -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")
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package transformers
|
|
||||||
|
|
||||||
import "github.com/grafana/grafana/pkg/tsdb"
|
|
||||||
|
|
||||||
type Transformer interface {
|
|
||||||
Transform(timeserie *tsdb.TimeSeries) (float64, error)
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user