From 01da3f6cb29523dc8084c79c1a80c8bbe5d0ee12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 28 Jul 2016 17:03:53 +0200 Subject: [PATCH] feat(alerting): worked on improving slack alerts --- pkg/services/alerting/eval_context.go | 63 +++++++++++++++++++ pkg/services/alerting/eval_handler.go | 2 +- pkg/services/alerting/models.go | 37 ----------- pkg/services/alerting/notifiers/slack.go | 39 +++++++++--- .../alerting/partials/notification_edit.html | 2 +- 5 files changed, 94 insertions(+), 49 deletions(-) create mode 100644 pkg/services/alerting/eval_context.go diff --git a/pkg/services/alerting/eval_context.go b/pkg/services/alerting/eval_context.go new file mode 100644 index 00000000000..9dab0d9cf20 --- /dev/null +++ b/pkg/services/alerting/eval_context.go @@ -0,0 +1,63 @@ +package alerting + +import ( + "time" + + "github.com/grafana/grafana/pkg/log" + m "github.com/grafana/grafana/pkg/models" +) + +type EvalContext struct { + Firing bool + IsTestRun bool + Events []*Event + Logs []*ResultLogEntry + Error error + Description string + StartTime time.Time + EndTime time.Time + Rule *Rule + DoneChan chan bool + CancelChan chan bool + log log.Logger +} + +func (a *EvalContext) GetDurationMs() float64 { + return float64(a.EndTime.Nanosecond()-a.StartTime.Nanosecond()) / float64(1000000) +} + +func (c *EvalContext) GetColor() string { + if !c.Firing { + return "#36a64f" + } + + if c.Rule.Severity == m.AlertSeverityWarning { + return "#fd821b" + } else { + return "#D63232" + } +} + +func (c *EvalContext) GetStateText() string { + if !c.Firing { + return "OK" + } + + if c.Rule.Severity == m.AlertSeverityWarning { + return "WARNING" + } else { + return "CRITICAL" + } +} + +func NewEvalContext(rule *Rule) *EvalContext { + return &EvalContext{ + StartTime: time.Now(), + Rule: rule, + Logs: make([]*ResultLogEntry, 0), + Events: make([]*Event, 0), + DoneChan: make(chan bool, 1), + CancelChan: make(chan bool, 1), + log: log.New("alerting.engine"), + } +} diff --git a/pkg/services/alerting/eval_handler.go b/pkg/services/alerting/eval_handler.go index 8cea987a8be..ae8a3ba2c51 100644 --- a/pkg/services/alerting/eval_handler.go +++ b/pkg/services/alerting/eval_handler.go @@ -18,7 +18,7 @@ type DefaultEvalHandler struct { func NewEvalHandler() *DefaultEvalHandler { return &DefaultEvalHandler{ - log: log.New("alerting.handler"), + log: log.New("alerting.evalHandler"), alertJobTimeout: time.Second * 5, } } diff --git a/pkg/services/alerting/models.go b/pkg/services/alerting/models.go index ba175ef64f1..7b90403667f 100644 --- a/pkg/services/alerting/models.go +++ b/pkg/services/alerting/models.go @@ -1,11 +1,5 @@ package alerting -import ( - "time" - - "github.com/grafana/grafana/pkg/log" -) - type Job struct { Offset int64 Delay bool @@ -13,37 +7,6 @@ type Job struct { Rule *Rule } -type EvalContext struct { - Firing bool - IsTestRun bool - Events []*Event - Logs []*ResultLogEntry - Error error - Description string - StartTime time.Time - EndTime time.Time - Rule *Rule - DoneChan chan bool - CancelChan chan bool - log log.Logger -} - -func (a *EvalContext) GetDurationMs() float64 { - return float64(a.EndTime.Nanosecond()-a.StartTime.Nanosecond()) / float64(1000000) -} - -func NewEvalContext(rule *Rule) *EvalContext { - return &EvalContext{ - StartTime: time.Now(), - Rule: rule, - Logs: make([]*ResultLogEntry, 0), - Events: make([]*Event, 0), - DoneChan: make(chan bool, 1), - CancelChan: make(chan bool, 1), - log: log.New("alerting.engine"), - } -} - type ResultLogEntry struct { Message string Data interface{} diff --git a/pkg/services/alerting/notifiers/slack.go b/pkg/services/alerting/notifiers/slack.go index 4c2073f33b8..570c10cb13a 100644 --- a/pkg/services/alerting/notifiers/slack.go +++ b/pkg/services/alerting/notifiers/slack.go @@ -1,10 +1,10 @@ package notifiers import ( - "fmt" + "encoding/json" + "time" "github.com/grafana/grafana/pkg/bus" - "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" @@ -47,17 +47,36 @@ func (this *SlackNotifier) Notify(context *alerting.EvalContext) { return } - stateText := string(rule.Severity) - if !context.Firing { - stateText = "ok" + fields := make([]map[string]interface{}, 0) + for _, evt := range context.Events { + fields = append(fields, map[string]interface{}{ + "title": evt.Metric, + "value": evt.Value, + }) } - text := fmt.Sprintf("[%s]: <%s|%s>", stateText, ruleLink, rule.Name) + body := map[string]interface{}{ + "attachments": []map[string]interface{}{ + map[string]interface{}{ + "color": context.GetColor(), + //"pretext": "Optional text that appears above the attachment block", + // "author_name": "Bobby Tables", + // "author_link": "http://flickr.com/bobby/", + // "author_icon": "http://flickr.com/icons/bobby.jpg", + "title": "[" + context.GetStateText() + "] " + rule.Name, + "title_link": ruleLink, + // "text": "Optional text that appears within the attachment", + "fields": fields, + "image_url": "http://my-website.com/path/to/image.jpg", + "thumb_url": "http://example.com/path/to/thumb.png", + "footer": "Grafana v4.0.0", + "footer_icon": "http://grafana.org/assets/img/fav32.png", + "ts": time.Now().Unix(), + }, + }, + } - body := simplejson.New() - body.Set("text", text) - - data, _ := body.MarshalJSON() + data, _ := json.Marshal(&body) cmd := &m.SendWebhook{Url: this.Url, Body: string(data)} if err := bus.Dispatch(cmd); err != nil { diff --git a/public/app/features/alerting/partials/notification_edit.html b/public/app/features/alerting/partials/notification_edit.html index 3f025de97ae..1ba6784debb 100644 --- a/public/app/features/alerting/partials/notification_edit.html +++ b/public/app/features/alerting/partials/notification_edit.html @@ -49,7 +49,7 @@

Slack settings

Url - +