Ver Fonte

Update VictorOps notifier w/ auto resolve and image URL (#8431)

* Fixed newline JSON buy in VictorOps integration

* Fixed payload sent to VictorOps so that link displays correctly

* Fixed formatted to resolve go error

* Add auto resolve incidents and image URL to VictorOps notifier
Dave Scott há 8 anos atrás
pai
commit
f7215608e9
1 ficheiros alterados com 39 adições e 12 exclusões
  1. 39 12
      pkg/services/alerting/notifiers/victorops.go

+ 39 - 12
pkg/services/alerting/notifiers/victorops.go

@@ -1,10 +1,10 @@
 package notifiers
 
 import (
-	"encoding/json"
 	"time"
 
 	"github.com/grafana/grafana/pkg/bus"
+	"github.com/grafana/grafana/pkg/components/simplejson"
 	"github.com/grafana/grafana/pkg/log"
 	"github.com/grafana/grafana/pkg/metrics"
 	"github.com/grafana/grafana/pkg/models"
@@ -15,6 +15,8 @@ import (
 // AlertStateCritical - Victorops uses "CRITICAL" string to indicate "Alerting" state
 const AlertStateCritical = "CRITICAL"
 
+const AlertStateRecovery = "RECOVERY"
+
 func init() {
 	alerting.RegisterNotifier(&alerting.NotifierPlugin{
 		Type:        "victorops",
@@ -27,6 +29,15 @@ func init() {
         <span class="gf-form-label width-6">Url</span>
         <input type="text" required class="gf-form-input max-width-30" ng-model="ctrl.model.settings.url" placeholder="VictorOps url"></input>
       </div>
+      <div class="gf-form">
+        <gf-form-switch
+           class="gf-form"
+           label="Auto resolve incidents"
+           label-class="width-14"
+           checked="ctrl.model.settings.autoResolve"
+           tooltip="Resolve incidents in VictorOps once the alert goes back to ok.">
+        </gf-form-switch>
+      </div>
     `,
 	})
 }
@@ -34,6 +45,7 @@ func init() {
 // NewVictoropsNotifier creates an instance of VictoropsNotifier that
 // handles posting notifications to Victorops REST API
 func NewVictoropsNotifier(model *models.AlertNotification) (alerting.Notifier, error) {
+	autoResolve := model.Settings.Get("autoResolve").MustBool(true)
 	url := model.Settings.Get("url").MustString()
 	if url == "" {
 		return nil, alerting.ValidationError{Reason: "Could not find victorops url property in settings"}
@@ -42,6 +54,7 @@ func NewVictoropsNotifier(model *models.AlertNotification) (alerting.Notifier, e
 	return &VictoropsNotifier{
 		NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
 		URL:          url,
+		AutoResolve:  autoResolve,
 		log:          log.New("alerting.notifier.victorops"),
 	}, nil
 }
@@ -51,8 +64,9 @@ func NewVictoropsNotifier(model *models.AlertNotification) (alerting.Notifier, e
 // Victorops specifications (http://victorops.force.com/knowledgebase/articles/Integration/Alert-Ingestion-API-Documentation/)
 type VictoropsNotifier struct {
 	NotifierBase
-	URL string
-	log log.Logger
+	URL         string
+	AutoResolve bool
+	log         log.Logger
 }
 
 // Notify sends notification to Victorops via POST to URL endpoint
@@ -66,6 +80,11 @@ func (this *VictoropsNotifier) Notify(evalContext *alerting.EvalContext) error {
 		return err
 	}
 
+	if evalContext.Rule.State == models.AlertStateOK && !this.AutoResolve {
+		this.log.Info("Not alerting VictorOps", "state", evalContext.Rule.State, "auto resolve", this.AutoResolve)
+		return nil
+	}
+
 	fields := make([]map[string]interface{}, 0)
 	fieldLimitCount := 4
 	for index, evt := range evalContext.EvalMatches {
@@ -92,20 +111,28 @@ func (this *VictoropsNotifier) Notify(evalContext *alerting.EvalContext) error {
 		messageType = AlertStateCritical
 	}
 
-	body := map[string]interface{}{
-		"message_type":     messageType,
-		"entity_id":        evalContext.Rule.Name,
-		"timestamp":        time.Now().Unix(),
-		"state_start_time": evalContext.StartTime.Unix(),
-		"state_message":    evalContext.Rule.Message + "\n" + ruleUrl,
-		"monitoring_tool":  "Grafana v" + setting.BuildVersion,
+	if evalContext.Rule.State == models.AlertStateOK {
+		messageType = AlertStateRecovery
+	}
+
+	bodyJSON := simplejson.New()
+	bodyJSON.Set("message_type", messageType)
+	bodyJSON.Set("entity_id", evalContext.Rule.Name)
+	bodyJSON.Set("timestamp", time.Now().Unix())
+	bodyJSON.Set("state_start_time", evalContext.StartTime.Unix())
+	bodyJSON.Set("state_message", evalContext.Rule.Message)
+	bodyJSON.Set("monitoring_tool", "Grafana v"+setting.BuildVersion)
+	bodyJSON.Set("alert_url", ruleUrl)
+
+	if evalContext.ImagePublicUrl != "" {
+		bodyJSON.Set("image_url", evalContext.ImagePublicUrl)
 	}
 
-	data, _ := json.Marshal(&body)
+	data, _ := bodyJSON.MarshalJSON()
 	cmd := &models.SendWebhookSync{Url: this.URL, Body: string(data)}
 
 	if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
-		this.log.Error("Failed to send victorops notification", "error", err, "webhook", this.Name)
+		this.log.Error("Failed to send Victorops notification", "error", err, "webhook", this.Name)
 		return err
 	}