package notifiers import ( "fmt" "net/url" "strconv" "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/log" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/alerting" ) const PUSHOVER_ENDPOINT = "https://api.pushover.net/1/messages.json" func init() { alerting.RegisterNotifier(&alerting.NotifierPlugin{ Type: "pushover", Name: "Pushover", Description: "Sends HTTP POST request to the Pushover API", Factory: NewPushoverNotifier, OptionsTemplate: `

Pushover settings

API Token
User key(s)
Device(s) (optional)
Priority
Retry Expire
Sound
`, }) } func NewPushoverNotifier(model *m.AlertNotification) (alerting.Notifier, error) { userKey := model.Settings.Get("userKey").MustString() apiToken := model.Settings.Get("apiToken").MustString() device := model.Settings.Get("device").MustString() priority, _ := strconv.Atoi(model.Settings.Get("priority").MustString()) retry, _ := strconv.Atoi(model.Settings.Get("retry").MustString()) expire, _ := strconv.Atoi(model.Settings.Get("expire").MustString()) sound := model.Settings.Get("sound").MustString() if userKey == "" { return nil, alerting.ValidationError{Reason: "User key not given"} } if apiToken == "" { return nil, alerting.ValidationError{Reason: "API token not given"} } return &PushoverNotifier{ NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings), UserKey: userKey, ApiToken: apiToken, Priority: priority, Retry: retry, Expire: expire, Device: device, Sound: sound, log: log.New("alerting.notifier.pushover"), }, nil } type PushoverNotifier struct { NotifierBase UserKey string ApiToken string Priority int Retry int Expire int Device string Sound string log log.Logger } func (this *PushoverNotifier) ShouldNotify(context *alerting.EvalContext) bool { return defaultShouldNotify(context) } func (this *PushoverNotifier) Notify(evalContext *alerting.EvalContext) error { ruleUrl, err := evalContext.GetRuleUrl() if err != nil { this.log.Error("Failed get rule link", "error", err) return err } message := evalContext.Rule.Message for idx, evt := range evalContext.EvalMatches { message += fmt.Sprintf("\n%s: %v", evt.Metric, evt.Value) if idx > 4 { break } } if evalContext.Error != nil { message += fmt.Sprintf("\nError message: %s", evalContext.Error.Error()) } if evalContext.ImagePublicUrl != "" { message += fmt.Sprintf("\nShow graph image", evalContext.ImagePublicUrl) } if message == "" { message = "Notification message missing (Set a notification message to replace this text.)" } q := url.Values{} q.Add("user", this.UserKey) q.Add("token", this.ApiToken) q.Add("priority", strconv.Itoa(this.Priority)) if this.Priority == 2 { q.Add("retry", strconv.Itoa(this.Retry)) q.Add("expire", strconv.Itoa(this.Expire)) } if this.Device != "" { q.Add("device", this.Device) } if this.Sound != "default" { q.Add("sound", this.Sound) } q.Add("title", evalContext.GetNotificationTitle()) q.Add("url", ruleUrl) q.Add("url_title", "Show dashboard with alert") q.Add("message", message) q.Add("html", "1") cmd := &m.SendWebhookSync{ Url: PUSHOVER_ENDPOINT, HttpMethod: "POST", HttpHeader: map[string]string{"Content-Type": "application/x-www-form-urlencoded"}, Body: q.Encode(), } if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil { this.log.Error("Failed to send pushover notification", "error", err, "webhook", this.Name) return err } return nil }