mirror of
https://github.com/grafana/grafana.git
synced 2025-08-03 03:13:49 +08:00
Alerting: Change handling of settings to pagerduty contact point (#57524)
* Add custom title to pagerduty contact point * Fix tests by saving decrypted key * Use simplejson
This commit is contained in:
@ -31,83 +31,68 @@ var (
|
||||
// alert notifications to pagerduty
|
||||
type PagerdutyNotifier struct {
|
||||
*Base
|
||||
Key string
|
||||
Severity string
|
||||
CustomDetails map[string]string
|
||||
Class string
|
||||
Component string
|
||||
Group string
|
||||
Summary string
|
||||
tmpl *template.Template
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
images ImageStore
|
||||
tmpl *template.Template
|
||||
log log.Logger
|
||||
ns notifications.WebhookSender
|
||||
images ImageStore
|
||||
settings pagerdutySettings
|
||||
}
|
||||
|
||||
type PagerdutyConfig struct {
|
||||
*NotificationChannelConfig
|
||||
Key string
|
||||
Severity string
|
||||
Class string
|
||||
Component string
|
||||
Group string
|
||||
Summary string
|
||||
type pagerdutySettings struct {
|
||||
Key string `json:"integrationKey,omitempty" yaml:"integrationKey,omitempty"`
|
||||
Severity string `json:"severity,omitempty" yaml:"severity,omitempty"`
|
||||
customDetails map[string]string
|
||||
Class string `json:"class,omitempty" yaml:"class,omitempty"`
|
||||
Component string `json:"component,omitempty" yaml:"component,omitempty"`
|
||||
Group string `json:"group,omitempty" yaml:"group,omitempty"`
|
||||
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
|
||||
}
|
||||
|
||||
func PagerdutyFactory(fc FactoryConfig) (NotificationChannel, error) {
|
||||
cfg, err := NewPagerdutyConfig(fc.Config, fc.DecryptFunc)
|
||||
pdn, err := newPagerdutyNotifier(fc)
|
||||
if err != nil {
|
||||
return nil, receiverInitError{
|
||||
Reason: err.Error(),
|
||||
Cfg: *fc.Config,
|
||||
}
|
||||
}
|
||||
return NewPagerdutyNotifier(cfg, fc.NotificationService, fc.ImageStore, fc.Template), nil
|
||||
}
|
||||
|
||||
func NewPagerdutyConfig(config *NotificationChannelConfig, decryptFunc GetDecryptedValueFn) (*PagerdutyConfig, error) {
|
||||
key := decryptFunc(context.Background(), config.SecureSettings, "integrationKey", config.Settings.Get("integrationKey").MustString())
|
||||
if key == "" {
|
||||
return nil, errors.New("could not find integration key property in settings")
|
||||
}
|
||||
return &PagerdutyConfig{
|
||||
NotificationChannelConfig: config,
|
||||
Key: key,
|
||||
Severity: config.Settings.Get("severity").MustString("critical"),
|
||||
Class: config.Settings.Get("class").MustString("default"),
|
||||
Component: config.Settings.Get("component").MustString("Grafana"),
|
||||
Group: config.Settings.Get("group").MustString("default"),
|
||||
Summary: config.Settings.Get("summary").MustString(DefaultMessageTitleEmbed),
|
||||
}, nil
|
||||
return pdn, nil
|
||||
}
|
||||
|
||||
// NewPagerdutyNotifier is the constructor for the PagerDuty notifier
|
||||
func NewPagerdutyNotifier(config *PagerdutyConfig, ns notifications.WebhookSender, images ImageStore, t *template.Template) *PagerdutyNotifier {
|
||||
func newPagerdutyNotifier(fc FactoryConfig) (*PagerdutyNotifier, error) {
|
||||
key := fc.DecryptFunc(context.Background(), fc.Config.SecureSettings, "integrationKey", fc.Config.Settings.Get("integrationKey").MustString())
|
||||
if key == "" {
|
||||
return nil, errors.New("could not find integration key property in settings")
|
||||
}
|
||||
|
||||
return &PagerdutyNotifier{
|
||||
Base: NewBase(&models.AlertNotification{
|
||||
Uid: config.UID,
|
||||
Name: config.Name,
|
||||
Type: config.Type,
|
||||
DisableResolveMessage: config.DisableResolveMessage,
|
||||
Settings: config.Settings,
|
||||
Uid: fc.Config.UID,
|
||||
Name: fc.Config.Name,
|
||||
Type: fc.Config.Type,
|
||||
DisableResolveMessage: fc.Config.DisableResolveMessage,
|
||||
Settings: fc.Config.Settings,
|
||||
}),
|
||||
Key: config.Key,
|
||||
CustomDetails: map[string]string{
|
||||
"firing": `{{ template "__text_alert_list" .Alerts.Firing }}`,
|
||||
"resolved": `{{ template "__text_alert_list" .Alerts.Resolved }}`,
|
||||
"num_firing": `{{ .Alerts.Firing | len }}`,
|
||||
"num_resolved": `{{ .Alerts.Resolved | len }}`,
|
||||
tmpl: fc.Template,
|
||||
log: log.New("alerting.notifier." + fc.Config.Name),
|
||||
ns: fc.NotificationService,
|
||||
images: fc.ImageStore,
|
||||
settings: pagerdutySettings{
|
||||
Key: key,
|
||||
Severity: fc.Config.Settings.Get("severity").MustString("critical"),
|
||||
customDetails: map[string]string{
|
||||
"firing": `{{ template "__text_alert_list" .Alerts.Firing }}`,
|
||||
"resolved": `{{ template "__text_alert_list" .Alerts.Resolved }}`,
|
||||
"num_firing": `{{ .Alerts.Firing | len }}`,
|
||||
"num_resolved": `{{ .Alerts.Resolved | len }}`,
|
||||
},
|
||||
Class: fc.Config.Settings.Get("class").MustString("default"),
|
||||
Component: fc.Config.Settings.Get("component").MustString("Grafana"),
|
||||
Group: fc.Config.Settings.Get("group").MustString("default"),
|
||||
Summary: fc.Config.Settings.Get("summary").MustString(DefaultMessageTitleEmbed),
|
||||
},
|
||||
Severity: config.Severity,
|
||||
Class: config.Class,
|
||||
Component: config.Component,
|
||||
Group: config.Group,
|
||||
Summary: config.Summary,
|
||||
tmpl: t,
|
||||
log: log.New("alerting.notifier." + config.Name),
|
||||
ns: ns,
|
||||
images: images,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Notify sends an alert notification to PagerDuty
|
||||
@ -158,8 +143,8 @@ func (pn *PagerdutyNotifier) buildPagerdutyMessage(ctx context.Context, alerts m
|
||||
var tmplErr error
|
||||
tmpl, data := TmplText(ctx, pn.tmpl, as, pn.log, &tmplErr)
|
||||
|
||||
details := make(map[string]string, len(pn.CustomDetails))
|
||||
for k, v := range pn.CustomDetails {
|
||||
details := make(map[string]string, len(pn.settings.customDetails))
|
||||
for k, v := range pn.settings.customDetails {
|
||||
detail, err := pn.tmpl.ExecuteTextString(v, data)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("%q: failed to template %q: %w", k, v, err)
|
||||
@ -170,21 +155,20 @@ func (pn *PagerdutyNotifier) buildPagerdutyMessage(ctx context.Context, alerts m
|
||||
msg := &pagerDutyMessage{
|
||||
Client: "Grafana",
|
||||
ClientURL: pn.tmpl.ExternalURL.String(),
|
||||
RoutingKey: pn.Key,
|
||||
RoutingKey: pn.settings.Key,
|
||||
EventAction: eventType,
|
||||
DedupKey: key.Hash(),
|
||||
Links: []pagerDutyLink{{
|
||||
HRef: pn.tmpl.ExternalURL.String(),
|
||||
Text: "External URL",
|
||||
}},
|
||||
Description: tmpl(DefaultMessageTitleEmbed), // TODO: this can be configurable template.
|
||||
Payload: pagerDutyPayload{
|
||||
Component: tmpl(pn.Component),
|
||||
Summary: tmpl(pn.Summary),
|
||||
Severity: tmpl(pn.Severity),
|
||||
Component: tmpl(pn.settings.Component),
|
||||
Summary: tmpl(pn.settings.Summary),
|
||||
Severity: tmpl(pn.settings.Severity),
|
||||
CustomDetails: details,
|
||||
Class: tmpl(pn.Class),
|
||||
Group: tmpl(pn.Group),
|
||||
Class: tmpl(pn.settings.Class),
|
||||
Group: tmpl(pn.settings.Group),
|
||||
},
|
||||
}
|
||||
|
||||
@ -223,7 +207,6 @@ type pagerDutyMessage struct {
|
||||
RoutingKey string `json:"routing_key,omitempty"`
|
||||
ServiceKey string `json:"service_key,omitempty"`
|
||||
DedupKey string `json:"dedup_key,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
EventAction string `json:"event_action"`
|
||||
Payload pagerDutyPayload `json:"payload"`
|
||||
Client string `json:"client,omitempty"`
|
||||
|
@ -49,7 +49,6 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
expMsg: &pagerDutyMessage{
|
||||
RoutingKey: "abcdefgh0123456789",
|
||||
DedupKey: "6e3538104c14b583da237e9693b76debbc17f0f8058ef20492e5853096cf8733",
|
||||
Description: "[FIRING:1] (val1)",
|
||||
EventAction: "trigger",
|
||||
Payload: pagerDutyPayload{
|
||||
Summary: "[FIRING:1] (val1)",
|
||||
@ -70,6 +69,40 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
Links: []pagerDutyLink{{HRef: "http://localhost", Text: "External URL"}},
|
||||
},
|
||||
expMsgError: nil,
|
||||
}, {
|
||||
name: "Default config with one alert and custom summary",
|
||||
settings: `{"integrationKey": "abcdefgh0123456789", "summary": "Alerts firing: {{ len .Alerts.Firing }}"}`,
|
||||
alerts: []*types.Alert{
|
||||
{
|
||||
Alert: model.Alert{
|
||||
Labels: model.LabelSet{"alertname": "alert1", "lbl1": "val1"},
|
||||
Annotations: model.LabelSet{"ann1": "annv1", "__dashboardUid__": "abcd", "__panelId__": "efgh"},
|
||||
},
|
||||
},
|
||||
},
|
||||
expMsg: &pagerDutyMessage{
|
||||
RoutingKey: "abcdefgh0123456789",
|
||||
DedupKey: "6e3538104c14b583da237e9693b76debbc17f0f8058ef20492e5853096cf8733",
|
||||
EventAction: "trigger",
|
||||
Payload: pagerDutyPayload{
|
||||
Summary: "Alerts firing: 1",
|
||||
Source: hostname,
|
||||
Severity: "critical",
|
||||
Class: "default",
|
||||
Component: "Grafana",
|
||||
Group: "default",
|
||||
CustomDetails: map[string]string{
|
||||
"firing": "\nValue: [no value]\nLabels:\n - alertname = alert1\n - lbl1 = val1\nAnnotations:\n - ann1 = annv1\nSilence: http://localhost/alerting/silence/new?alertmanager=grafana&matcher=alertname%3Dalert1&matcher=lbl1%3Dval1\nDashboard: http://localhost/d/abcd\nPanel: http://localhost/d/abcd?viewPanel=efgh\n",
|
||||
"num_firing": "1",
|
||||
"num_resolved": "0",
|
||||
"resolved": "",
|
||||
},
|
||||
},
|
||||
Client: "Grafana",
|
||||
ClientURL: "http://localhost",
|
||||
Links: []pagerDutyLink{{HRef: "http://localhost", Text: "External URL"}},
|
||||
},
|
||||
expMsgError: nil,
|
||||
}, {
|
||||
name: "Custom config with multiple alerts",
|
||||
settings: `{
|
||||
@ -95,7 +128,6 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
expMsg: &pagerDutyMessage{
|
||||
RoutingKey: "abcdefgh0123456789",
|
||||
DedupKey: "6e3538104c14b583da237e9693b76debbc17f0f8058ef20492e5853096cf8733",
|
||||
Description: "[FIRING:2] ",
|
||||
EventAction: "trigger",
|
||||
Payload: pagerDutyPayload{
|
||||
Summary: "[FIRING:2] ",
|
||||
@ -128,18 +160,22 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
|
||||
require.NoError(t, err)
|
||||
secureSettings := make(map[string][]byte)
|
||||
|
||||
m := &NotificationChannelConfig{
|
||||
Name: "pageduty_testing",
|
||||
Type: "pagerduty",
|
||||
Settings: settingsJSON,
|
||||
SecureSettings: secureSettings,
|
||||
}
|
||||
|
||||
webhookSender := mockNotificationService()
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
decryptFn := secretsService.GetDecryptedValue
|
||||
cfg, err := NewPagerdutyConfig(m, decryptFn)
|
||||
|
||||
fc := FactoryConfig{
|
||||
Config: &NotificationChannelConfig{
|
||||
Name: "pageduty_testing",
|
||||
Type: "pagerduty",
|
||||
Settings: settingsJSON,
|
||||
SecureSettings: secureSettings,
|
||||
},
|
||||
NotificationService: webhookSender,
|
||||
DecryptFunc: decryptFn,
|
||||
Template: tmpl,
|
||||
}
|
||||
pn, err := newPagerdutyNotifier(fc)
|
||||
if c.expInitError != "" {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, c.expInitError, err.Error())
|
||||
@ -149,7 +185,6 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
|
||||
ctx := notify.WithGroupKey(context.Background(), "alertname")
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{"alertname": ""})
|
||||
pn := NewPagerdutyNotifier(cfg, webhookSender, &UnavailableImageStore{}, tmpl)
|
||||
ok, err := pn.Notify(ctx, c.alerts...)
|
||||
if c.expMsgError != nil {
|
||||
require.False(t, ok)
|
||||
|
@ -286,8 +286,9 @@ func GetAvailableNotifiers() []*NotifierPlugin {
|
||||
{ // New in 8.0.
|
||||
Label: "Summary",
|
||||
Description: "You can use templates for summary",
|
||||
Element: ElementTypeTextArea,
|
||||
Placeholder: channels.DefaultMessageEmbed,
|
||||
Element: ElementTypeInput,
|
||||
InputType: InputTypeText,
|
||||
Placeholder: channels.DefaultMessageTitleEmbed,
|
||||
PropertyName: "summary",
|
||||
},
|
||||
},
|
||||
|
@ -1612,7 +1612,7 @@ const alertmanagerConfig = `
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "slack_recv2",
|
||||
"grafana_managed_receiver_configs": [
|
||||
@ -2356,7 +2356,6 @@ var expNonEmailNotifications = map[string][]string{
|
||||
`{
|
||||
"routing_key": "pagerduty_recv/pagerduty_test",
|
||||
"dedup_key": "234edb34441f942f713f3c2ccf58b1d719d921b4cbe34e57a1630f1dee847e3b",
|
||||
"description": "[FIRING:1] PagerdutyAlert (default)",
|
||||
"event_action": "trigger",
|
||||
"payload": {
|
||||
"summary": "Integration Test [FIRING:1] PagerdutyAlert (default)",
|
||||
|
Reference in New Issue
Block a user