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"
|
2019-05-13 01:45:54 -05:00
|
|
|
"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",
|
2020-06-29 06:39:12 -05:00
|
|
|
Heading: "HipChat settings",
|
2017-02-07 10:50:49 -06:00
|
|
|
Factory: NewHipChatNotifier,
|
2020-06-29 06:39:12 -05:00
|
|
|
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
|
|
|
|
)
|
|
|
|
|
2019-05-20 08:23:06 -05:00
|
|
|
// 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()
|
2019-05-20 08:23:06 -05:00
|
|
|
roomID := model.Settings.Get("roomid").MustString()
|
2017-02-07 10:50:49 -06:00
|
|
|
|
|
|
|
return &HipChatNotifier{
|
2018-06-05 03:27:29 -05:00
|
|
|
NotifierBase: NewNotifierBase(model),
|
2019-05-20 08:23:06 -05:00
|
|
|
URL: url,
|
|
|
|
APIKey: apikey,
|
|
|
|
RoomID: roomID,
|
2017-02-07 10:50:49 -06:00
|
|
|
log: log.New("alerting.notifier.hipchat"),
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2019-05-20 08:23:06 -05:00
|
|
|
// HipChatNotifier is responsible for sending
|
|
|
|
// alert notifications to Hipchat.
|
2017-02-07 10:50:49 -06:00
|
|
|
type HipChatNotifier struct {
|
|
|
|
NotifierBase
|
2019-05-20 08:23:06 -05:00
|
|
|
URL string
|
|
|
|
APIKey string
|
|
|
|
RoomID string
|
2017-02-07 10:50:49 -06:00
|
|
|
log log.Logger
|
|
|
|
}
|
|
|
|
|
2019-05-20 08:23:06 -05:00
|
|
|
// Notify sends an alert notification to HipChat
|
|
|
|
func (hc *HipChatNotifier) Notify(evalContext *alerting.EvalContext) error {
|
2019-06-03 03:25:58 -05:00
|
|
|
hc.log.Info("Executing hipchat notification", "ruleId", evalContext.Rule.ID, "notification", hc.Name)
|
2017-02-07 10:50:49 -06:00
|
|
|
|
2019-06-03 03:25:58 -05:00
|
|
|
ruleURL, err := evalContext.GetRuleURL()
|
2017-02-07 10:50:49 -06:00
|
|
|
if err != nil {
|
2019-05-20 08:23:06 -05:00
|
|
|
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 {
|
2017-10-04 09:07:13 -05:00
|
|
|
metricName := evt.Metric
|
|
|
|
if len(metricName) > 50 {
|
|
|
|
metricName = metricName[:50]
|
|
|
|
}
|
2017-08-24 06:40:33 -05:00
|
|
|
attributes = append(attributes, map[string]interface{}{
|
2017-10-04 09:07:13 -05:00
|
|
|
"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 := ""
|
2020-09-22 09:22:19 -05:00
|
|
|
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
|
|
|
|
}
|
2017-10-04 09:07:13 -05:00
|
|
|
|
2017-10-05 09:00:55 -05:00
|
|
|
if message == "" {
|
2017-10-04 09:07:13 -05:00
|
|
|
message = evalContext.GetNotificationTitle() + " in state " + evalContext.GetStateModel().Text
|
|
|
|
}
|
|
|
|
|
2020-09-22 09:22:19 -05:00
|
|
|
// 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:
|
2018-09-14 10:22:07 -05:00
|
|
|
color = "gray"
|
2017-02-08 04:24:49 -06:00
|
|
|
case models.AlertStateAlerting:
|
2017-02-07 10:50:49 -06:00
|
|
|
color = "red"
|
2020-12-01 02:53:27 -06:00
|
|
|
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",
|
2019-05-20 08:23:06 -05:00
|
|
|
"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{}{
|
2017-03-21 09:37:55 -05:00
|
|
|
"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
|
|
|
}
|
2020-03-30 17:46:01 -05:00
|
|
|
if hc.NeedsImage() && evalContext.ImagePublicURL != "" {
|
2017-08-24 07:52:23 -05:00
|
|
|
card["thumbnail"] = map[string]interface{}{
|
2019-06-03 03:25:58 -05:00
|
|
|
"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
|
|
|
|
2019-05-20 08:23:06 -05: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)
|
2019-05-20 08:23:06 -05:00
|
|
|
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 {
|
2019-05-20 08:23:06 -05:00
|
|
|
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
|
|
|
|
}
|