grafana/pkg/services/alerting/notifiers/hipchat.go

187 lines
4.8 KiB
Go
Raw Normal View History

2017-02-07 10:50:49 -06:00
package notifiers
import (
"encoding/json"
2017-02-08 04:24:49 -06:00
"strconv"
"strings"
"fmt"
2017-02-07 10:50:49 -06:00
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/infra/log"
2017-02-08 04:24:49 -06:00
"github.com/grafana/grafana/pkg/models"
2017-02-07 10:50:49 -06:00
"github.com/grafana/grafana/pkg/services/alerting"
)
func init() {
alerting.RegisterNotifier(&alerting.NotifierPlugin{
Type: "hipchat",
Name: "HipChat",
Description: "Sends notifications uto a HipChat Room",
Heading: "HipChat settings",
2017-02-07 10:50:49 -06:00
Factory: NewHipChatNotifier,
Options: []alerting.NotifierOption{
{
Label: "Hip Chat Url",
Element: alerting.ElementTypeInput,
InputType: alerting.InputTypeText,
Placeholder: "HipChat URL (ex https://grafana.hipchat.com)",
PropertyName: "url",
Required: true,
},
{
Label: "API Key",
Element: alerting.ElementTypeInput,
InputType: alerting.InputTypeText,
Placeholder: "HipChat API Key",
PropertyName: "apiKey",
Required: true,
},
{
Label: "Room ID",
Element: alerting.ElementTypeInput,
InputType: alerting.InputTypeText,
PropertyName: "roomid",
},
},
2017-02-07 10:50:49 -06:00
})
}
2017-02-08 04:24:49 -06:00
const (
maxFieldCount int = 4
)
// NewHipChatNotifier is the constructor functions
// for the HipChatNotifier
2017-02-08 04:24:49 -06:00
func NewHipChatNotifier(model *models.AlertNotification) (alerting.Notifier, error) {
2017-02-07 10:50:49 -06:00
url := model.Settings.Get("url").MustString()
if strings.HasSuffix(url, "/") {
url = url[:len(url)-1]
}
if url == "" {
return nil, alerting.ValidationError{Reason: "Could not find url property in settings"}
}
apikey := model.Settings.Get("apikey").MustString()
roomID := model.Settings.Get("roomid").MustString()
2017-02-07 10:50:49 -06:00
return &HipChatNotifier{
NotifierBase: NewNotifierBase(model),
URL: url,
APIKey: apikey,
RoomID: roomID,
2017-02-07 10:50:49 -06:00
log: log.New("alerting.notifier.hipchat"),
}, nil
}
// HipChatNotifier is responsible for sending
// alert notifications to Hipchat.
2017-02-07 10:50:49 -06:00
type HipChatNotifier struct {
NotifierBase
URL string
APIKey string
RoomID string
2017-02-07 10:50:49 -06:00
log log.Logger
}
// Notify sends an alert notification to HipChat
func (hc *HipChatNotifier) Notify(evalContext *alerting.EvalContext) error {
hc.log.Info("Executing hipchat notification", "ruleId", evalContext.Rule.ID, "notification", hc.Name)
2017-02-07 10:50:49 -06:00
ruleURL, err := evalContext.GetRuleURL()
2017-02-07 10:50:49 -06:00
if err != nil {
hc.log.Error("Failed get rule link", "error", err)
2017-02-07 10:50:49 -06:00
return err
}
2017-08-24 06:40:33 -05:00
attributes := make([]map[string]interface{}, 0)
2017-02-07 10:50:49 -06:00
for index, evt := range evalContext.EvalMatches {
metricName := evt.Metric
if len(metricName) > 50 {
metricName = metricName[:50]
}
2017-08-24 06:40:33 -05:00
attributes = append(attributes, map[string]interface{}{
"label": metricName,
2017-08-24 06:40:33 -05:00
"value": map[string]interface{}{
"label": strconv.FormatFloat(evt.Value.Float64, 'f', -1, 64),
},
2017-02-07 10:50:49 -06:00
})
2017-02-08 04:24:49 -06:00
if index > maxFieldCount {
2017-02-07 10:50:49 -06:00
break
}
}
if evalContext.Error != nil {
2017-08-24 06:40:33 -05:00
attributes = append(attributes, map[string]interface{}{
"label": "Error message",
"value": map[string]interface{}{
"label": evalContext.Error.Error(),
},
2017-02-07 10:50:49 -06:00
})
}
2017-08-24 06:40:33 -05:00
message := ""
if evalContext.Rule.State != models.AlertStateOK { // don't add message when going back to alert state ok.
2017-02-07 10:50:49 -06:00
message += " " + evalContext.Rule.Message
}
if message == "" {
message = evalContext.GetNotificationTitle() + " in state " + evalContext.GetStateModel().Text
}
// HipChat has a set list of colors
2017-02-08 04:24:49 -06:00
var color string
2017-02-07 10:50:49 -06:00
switch evalContext.Rule.State {
2017-02-08 04:24:49 -06:00
case models.AlertStateOK:
2017-02-07 10:50:49 -06:00
color = "green"
2017-02-08 04:24:49 -06:00
case models.AlertStateNoData:
color = "gray"
2017-02-08 04:24:49 -06:00
case models.AlertStateAlerting:
2017-02-07 10:50:49 -06:00
color = "red"
default:
// Handle other cases?
2017-02-07 10:50:49 -06:00
}
// Add a card with link to the dashboard
card := map[string]interface{}{
2017-08-24 06:40:33 -05:00
"style": "application",
"url": ruleURL,
2017-02-07 10:50:49 -06:00
"id": "1",
"title": evalContext.GetNotificationTitle(),
2017-08-24 06:40:33 -05:00
"description": message,
2017-02-07 10:50:49 -06:00
"icon": map[string]interface{}{
"url": "https://grafana.com/assets/img/fav32.png",
2017-02-07 10:50:49 -06:00
},
2017-08-24 06:40:33 -05:00
"date": evalContext.EndTime.Unix(),
"attributes": attributes,
2017-02-07 10:50:49 -06:00
}
if hc.NeedsImage() && evalContext.ImagePublicURL != "" {
2017-08-24 07:52:23 -05:00
card["thumbnail"] = map[string]interface{}{
"url": evalContext.ImagePublicURL,
"url@2x": evalContext.ImagePublicURL,
2017-08-24 07:52:23 -05:00
"width": 1193,
"height": 564,
}
}
2017-02-07 10:50:49 -06:00
body := map[string]interface{}{
"message": message,
"notify": "true",
"message_format": "html",
"color": color,
"card": card,
}
2017-02-08 04:24:49 -06:00
hipURL := fmt.Sprintf("%s/v2/room/%s/notification?auth_token=%s", hc.URL, hc.RoomID, hc.APIKey)
2017-02-07 10:50:49 -06:00
data, _ := json.Marshal(&body)
hc.log.Info("Request payload", "json", string(data))
cmd := &models.SendWebhookSync{Url: hipURL, Body: string(data)}
2017-02-07 10:50:49 -06:00
if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
hc.log.Error("Failed to send hipchat notification", "error", err, "webhook", hc.Name)
2017-02-07 10:50:49 -06:00
return err
}
return nil
}