Skip to content

Commit eb34855

Browse files
committed
feat(pagerduty): add support for auto resolve
closes grafana#6513
1 parent 0d729ae commit eb34855

File tree

3 files changed

+65
-43
lines changed

3 files changed

+65
-43
lines changed

pkg/services/alerting/notifiers/pagerduty.go

Lines changed: 52 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package notifiers
22

33
import (
4+
"strconv"
5+
46
"github.com/grafana/grafana/pkg/bus"
57
"github.com/grafana/grafana/pkg/components/simplejson"
68
"github.com/grafana/grafana/pkg/log"
@@ -18,6 +20,7 @@ var (
1820
)
1921

2022
func NewPagerdutyNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
23+
autoResolve := model.Settings.Get("autoResolve").MustBool(true)
2124
key := model.Settings.Get("integrationKey").MustString()
2225
if key == "" {
2326
return nil, alerting.ValidationError{Reason: "Could not find integration key property in settings"}
@@ -26,57 +29,66 @@ func NewPagerdutyNotifier(model *m.AlertNotification) (alerting.Notifier, error)
2629
return &PagerdutyNotifier{
2730
NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
2831
Key: key,
32+
AutoResolve: autoResolve,
2933
log: log.New("alerting.notifier.pagerduty"),
3034
}, nil
3135
}
3236

3337
type PagerdutyNotifier struct {
3438
NotifierBase
35-
Key string
36-
log log.Logger
39+
Key string
40+
AutoResolve bool
41+
log log.Logger
3742
}
3843

3944
func (this *PagerdutyNotifier) Notify(evalContext *alerting.EvalContext) error {
40-
this.log.Info("Notifying Pagerduty")
4145
metrics.M_Alerting_Notification_Sent_PagerDuty.Inc(1)
4246

43-
if evalContext.Rule.State == m.AlertStateAlerting {
44-
bodyJSON := simplejson.New()
45-
bodyJSON.Set("service_key", this.Key)
46-
bodyJSON.Set("description", evalContext.Rule.Name+" - "+evalContext.Rule.Message)
47-
bodyJSON.Set("client", "Grafana")
48-
bodyJSON.Set("event_type", "trigger")
49-
50-
ruleUrl, err := evalContext.GetRuleUrl()
51-
if err != nil {
52-
this.log.Error("Failed get rule link", "error", err)
53-
return err
54-
}
55-
bodyJSON.Set("client_url", ruleUrl)
56-
57-
if evalContext.ImagePublicUrl != "" {
58-
contexts := make([]interface{}, 1)
59-
imageJSON := simplejson.New()
60-
imageJSON.Set("type", "image")
61-
imageJSON.Set("src", evalContext.ImagePublicUrl)
62-
contexts[0] = imageJSON
63-
bodyJSON.Set("contexts", contexts)
64-
}
65-
66-
body, _ := bodyJSON.MarshalJSON()
67-
68-
cmd := &m.SendWebhookSync{
69-
Url: pagerdutyEventApiUrl,
70-
Body: string(body),
71-
HttpMethod: "POST",
72-
}
73-
74-
if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
75-
this.log.Error("Failed to send notification to Pagerduty", "error", err, "body", string(body))
76-
}
77-
78-
} else {
79-
this.log.Info("Not sending a trigger to Pagerduty", "state", evalContext.Rule.State)
47+
if evalContext.Rule.State == m.AlertStateOK && !this.AutoResolve {
48+
this.log.Info("Not sending a trigger to Pagerduty", "state", evalContext.Rule.State, "auto resolve", this.AutoResolve)
49+
return nil
50+
}
51+
52+
eventType := "trigger"
53+
if evalContext.Rule.State == m.AlertStateOK {
54+
eventType = "resolve"
55+
}
56+
57+
this.log.Info("Notifying Pagerduty", "event_type", eventType)
58+
59+
bodyJSON := simplejson.New()
60+
bodyJSON.Set("service_key", this.Key)
61+
bodyJSON.Set("description", evalContext.Rule.Name+" - "+evalContext.Rule.Message)
62+
bodyJSON.Set("client", "Grafana")
63+
bodyJSON.Set("event_type", eventType)
64+
bodyJSON.Set("incident_key", "alertId-"+strconv.FormatInt(evalContext.Rule.Id, 10))
65+
66+
ruleUrl, err := evalContext.GetRuleUrl()
67+
if err != nil {
68+
this.log.Error("Failed get rule link", "error", err)
69+
return err
70+
}
71+
bodyJSON.Set("client_url", ruleUrl)
72+
73+
if evalContext.ImagePublicUrl != "" {
74+
contexts := make([]interface{}, 1)
75+
imageJSON := simplejson.New()
76+
imageJSON.Set("type", "image")
77+
imageJSON.Set("src", evalContext.ImagePublicUrl)
78+
contexts[0] = imageJSON
79+
bodyJSON.Set("contexts", contexts)
80+
}
81+
82+
body, _ := bodyJSON.MarshalJSON()
83+
84+
cmd := &m.SendWebhookSync{
85+
Url: pagerdutyEventApiUrl,
86+
Body: string(body),
87+
HttpMethod: "POST",
88+
}
89+
90+
if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
91+
this.log.Error("Failed to send notification to Pagerduty", "error", err, "body", string(body))
8092
}
8193

8294
return nil

public/app/features/alerting/notification_edit_ctrl.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ export class AlertNotificationEditCtrl {
1818
this.model = {
1919
type: 'email',
2020
settings: {
21-
httpMethod: 'POST'
21+
httpMethod: 'POST',
22+
autoResolve: true,
2223
},
2324
isDefault: false
2425
};

public/app/features/alerting/partials/notification_edit.html

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,17 @@ <h3 class="page-heading">Email addresses</h3>
100100
<div class="gf-form-group" ng-if="ctrl.model.type === 'pagerduty'">
101101
<h3 class="page-heading">Pagerduty settings</h3>
102102
<div class="gf-form">
103-
<span class="gf-form-label width-12">Integration Key</span>
104-
<input type="text" required class="gf-form-input max-width-30" ng-model="ctrl.model.settings.integrationKey" placeholder="Pagerduty integeration Key"></input>
103+
<span class="gf-form-label width-14">Integration Key</span>
104+
<input type="text" required class="gf-form-input max-width-22" ng-model="ctrl.model.settings.integrationKey" placeholder="Pagerduty integeration Key"></input>
105+
</div>
106+
<div class="gf-form">
107+
<gf-form-switch
108+
class="gf-form"
109+
label="Auto resolve incidents"
110+
label-class="width-14"
111+
checked="ctrl.model.settings.autoResolve"
112+
tooltip="Resolve incidents in pagerduty once the alert goes back to ok.">
113+
</gf-form-switch>
105114
</div>
106115
</div>
107116

0 commit comments

Comments
 (0)