From d92625125bf0cbb4c51158cf7dcdd40efac49dfc Mon Sep 17 00:00:00 2001 From: Matthew Jacobson Date: Mon, 30 May 2022 11:55:34 -0400 Subject: [PATCH] Alerting: Add templated subject config to email notifier (#49742) * Add subject templating to email notifier * Fix linting --- .../ngalert/notifier/available_channels.go | 8 +++++++ .../ngalert/notifier/channels/email.go | 10 +++++--- .../ngalert/notifier/channels/email_test.go | 24 +++++++++++++++++-- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/pkg/services/ngalert/notifier/available_channels.go b/pkg/services/ngalert/notifier/available_channels.go index 7c197f68a72..1ba56d6dbcd 100644 --- a/pkg/services/ngalert/notifier/available_channels.go +++ b/pkg/services/ngalert/notifier/available_channels.go @@ -190,6 +190,14 @@ func GetAvailableNotifiers() []*alerting.NotifierPlugin { Element: alerting.ElementTypeTextArea, PropertyName: "message", }, + { // New in 9.0. + Label: "Subject", + Element: alerting.ElementTypeInput, + InputType: alerting.InputTypeText, + Description: "Templated subject of the email", + PropertyName: "subject", + Placeholder: `{{ template "default.title" . }}`, + }, }, }, { diff --git a/pkg/services/ngalert/notifier/channels/email.go b/pkg/services/ngalert/notifier/channels/email.go index bbbc6de13e0..db3861f781c 100644 --- a/pkg/services/ngalert/notifier/channels/email.go +++ b/pkg/services/ngalert/notifier/channels/email.go @@ -24,6 +24,7 @@ type EmailNotifier struct { Addresses []string SingleEmail bool Message string + Subject string log log.Logger ns notifications.EmailSender images ImageStore @@ -35,6 +36,7 @@ type EmailConfig struct { SingleEmail bool Addresses []string Message string + Subject string } func EmailFactory(fc FactoryConfig) (NotificationChannel, error) { @@ -59,6 +61,7 @@ func NewEmailConfig(config *NotificationChannelConfig) (*EmailConfig, error) { NotificationChannelConfig: config, SingleEmail: config.Settings.Get("singleEmail").MustBool(false), Message: config.Settings.Get("message").MustString(), + Subject: config.Settings.Get("subject").MustString(DefaultMessageTitleEmbed), Addresses: addresses, }, nil } @@ -77,6 +80,7 @@ func NewEmailNotifier(config *EmailConfig, ns notifications.EmailSender, images Addresses: config.Addresses, SingleEmail: config.SingleEmail, Message: config.Message, + Subject: config.Subject, log: log.New("alerting.notifier.email"), ns: ns, images: images, @@ -89,7 +93,7 @@ func (en *EmailNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool, var tmplErr error tmpl, data := TmplText(ctx, en.tmpl, as, en.log, &tmplErr) - title := tmpl(DefaultMessageTitleEmbed) + subject := tmpl(en.Subject) alertPageURL := en.tmpl.ExternalURL.String() ruleURL := en.tmpl.ExternalURL.String() @@ -106,9 +110,9 @@ func (en *EmailNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool, cmd := &models.SendEmailCommandSync{ SendEmailCommand: models.SendEmailCommand{ - Subject: title, + Subject: subject, Data: map[string]interface{}{ - "Title": title, + "Title": subject, "Message": tmpl(en.Message), "Status": data.Status, "Alerts": data.Alerts, diff --git a/pkg/services/ngalert/notifier/channels/email_test.go b/pkg/services/ngalert/notifier/channels/email_test.go index 35954447f7e..7761129cb67 100644 --- a/pkg/services/ngalert/notifier/channels/email_test.go +++ b/pkg/services/ngalert/notifier/channels/email_test.go @@ -117,6 +117,7 @@ func TestEmailNotifierIntegration(t *testing.T) { name string alerts []*types.Alert messageTmpl string + subjectTmpl string expSubject string expSnippets []string }{ @@ -220,11 +221,25 @@ func TestEmailNotifierIntegration(t *testing.T) { "<li>Firing: AlwaysFiring at warning </li>", }, }, + { + name: "single alert with templated subject", + alerts: []*types.Alert{ + { + Alert: model.Alert{ + Labels: model.LabelSet{"alertname": "AlwaysFiring", "severity": "warning"}, + Annotations: model.LabelSet{"runbook_url": "http://fix.me", "__dashboardUid__": "abc", "__panelId__": "5"}, + }, + }, + }, + subjectTmpl: `This notification is {{ .Status }}!`, + expSubject: "This notification is firing!", + expSnippets: []string{}, + }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { - emailNotifier := createSut(t, c.messageTmpl, emailTmpl, ns) + emailNotifier := createSut(t, c.messageTmpl, c.subjectTmpl, emailTmpl, ns) ok, err := emailNotifier.Notify(context.Background(), c.alerts...) require.NoError(t, err) @@ -271,7 +286,7 @@ func createCoreEmailService(t *testing.T) *notifications.NotificationService { return ns } -func createSut(t *testing.T, messageTmpl string, emailTmpl *template.Template, ns notifications.EmailSender) *EmailNotifier { +func createSut(t *testing.T, messageTmpl string, subjectTmpl string, emailTmpl *template.Template, ns notifications.EmailSender) *EmailNotifier { t.Helper() json := `{ @@ -282,6 +297,11 @@ func createSut(t *testing.T, messageTmpl string, emailTmpl *template.Template, n if messageTmpl != "" { settingsJSON.Set("message", messageTmpl) } + + if subjectTmpl != "" { + settingsJSON.Set("subject", subjectTmpl) + } + require.NoError(t, err) cfg, err := NewEmailConfig(&NotificationChannelConfig{ Name: "ops",