grafana/pkg/services/alerting/notifiers/webhook.go
Thibault Chataigner fd633a1d5d Add a per-notifier ShouldNotify()
This way we are able to edit notification behavior per notifier.
This would be usefull to let some notifiers send notifications,
even when the state doesn't change, or with custom condition.

Signed-off-by: Thibault Chataigner <t.chataigner@criteo.com>
2017-12-12 17:35:54 +01:00

112 lines
3.4 KiB
Go

package notifiers
import (
"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"
)
func init() {
alerting.RegisterNotifier(&alerting.NotifierPlugin{
Type: "webhook",
Name: "webhook",
Description: "Sends HTTP POST request to a URL",
Factory: NewWebHookNotifier,
OptionsTemplate: `
<h3 class="page-heading">Webhook settings</h3>
<div class="gf-form">
<span class="gf-form-label width-10">Url</span>
<input type="text" required class="gf-form-input max-width-26" ng-model="ctrl.model.settings.url"></input>
</div>
<div class="gf-form">
<span class="gf-form-label width-10">Http Method</span>
<div class="gf-form-select-wrapper width-14">
<select class="gf-form-input" ng-model="ctrl.model.settings.httpMethod" ng-options="t for t in ['POST', 'PUT']">
</select>
</div>
</div>
<div class="gf-form">
<span class="gf-form-label width-10">Username</span>
<input type="text" class="gf-form-input max-width-14" ng-model="ctrl.model.settings.username"></input>
</div>
<div class="gf-form">
<span class="gf-form-label width-10">Password</span>
<input type="text" class="gf-form-input max-width-14" ng-model="ctrl.model.settings.password"></input>
</div>
`,
})
}
func NewWebHookNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
url := model.Settings.Get("url").MustString()
if url == "" {
return nil, alerting.ValidationError{Reason: "Could not find url property in settings"}
}
return &WebhookNotifier{
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
Url: url,
User: model.Settings.Get("username").MustString(),
Password: model.Settings.Get("password").MustString(),
HttpMethod: model.Settings.Get("httpMethod").MustString("POST"),
log: log.New("alerting.notifier.webhook"),
}, nil
}
type WebhookNotifier struct {
NotifierBase
Url string
User string
Password string
HttpMethod string
log log.Logger
}
func (this *WebhookNotifier) ShouldNotify(context *alerting.EvalContext) bool {
return defaultShouldNotify(context)
}
func (this *WebhookNotifier) Notify(evalContext *alerting.EvalContext) error {
this.log.Info("Sending webhook")
bodyJSON := simplejson.New()
bodyJSON.Set("title", evalContext.GetNotificationTitle())
bodyJSON.Set("ruleId", evalContext.Rule.Id)
bodyJSON.Set("ruleName", evalContext.Rule.Name)
bodyJSON.Set("state", evalContext.Rule.State)
bodyJSON.Set("evalMatches", evalContext.EvalMatches)
ruleUrl, err := evalContext.GetRuleUrl()
if err == nil {
bodyJSON.Set("ruleUrl", ruleUrl)
}
if evalContext.ImagePublicUrl != "" {
bodyJSON.Set("imageUrl", evalContext.ImagePublicUrl)
}
if evalContext.Rule.Message != "" {
bodyJSON.Set("message", evalContext.Rule.Message)
}
body, _ := bodyJSON.MarshalJSON()
cmd := &m.SendWebhookSync{
Url: this.Url,
User: this.User,
Password: this.Password,
Body: string(body),
HttpMethod: this.HttpMethod,
}
if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
this.log.Error("Failed to send webhook", "error", err, "webhook", this.Name)
return err
}
return nil
}