mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
AlertingNG: Notification channel for emails (#31768)
* Email notification channel in ngalert Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in> * Use existing templating system Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in> * Update template and add unit tests Signed-off-by: Ganesh Vernekar <cs15btech11018@iith.ac.in>
This commit is contained in:
92
pkg/services/ngalert/notifier/channels/email.go
Normal file
92
pkg/services/ngalert/notifier/channels/email.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package channels
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
gokit_log "github.com/go-kit/kit/log"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
old_notifiers "github.com/grafana/grafana/pkg/services/alerting/notifiers"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/prometheus/alertmanager/notify"
|
||||
"github.com/prometheus/alertmanager/template"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/common/model"
|
||||
)
|
||||
|
||||
// EmailNotifier is responsible for sending
|
||||
// alert notifications over email.
|
||||
type EmailNotifier struct {
|
||||
old_notifiers.NotifierBase
|
||||
Addresses []string
|
||||
SingleEmail bool
|
||||
log log.Logger
|
||||
externalUrl *url.URL
|
||||
}
|
||||
|
||||
// NewEmailNotifier is the constructor function
|
||||
// for the EmailNotifier.
|
||||
func NewEmailNotifier(model *models.AlertNotification) (*EmailNotifier, error) {
|
||||
addressesString := model.Settings.Get("addresses").MustString()
|
||||
singleEmail := model.Settings.Get("singleEmail").MustBool(false)
|
||||
|
||||
if addressesString == "" {
|
||||
return nil, alerting.ValidationError{Reason: "Could not find addresses in settings"}
|
||||
}
|
||||
|
||||
// split addresses with a few different ways
|
||||
addresses := util.SplitEmails(addressesString)
|
||||
|
||||
// TODO: remove this URL hack and add an actual external URL.
|
||||
u, err := url.Parse("http://localhost")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &EmailNotifier{
|
||||
NotifierBase: old_notifiers.NewNotifierBase(model),
|
||||
Addresses: addresses,
|
||||
SingleEmail: singleEmail,
|
||||
log: log.New("alerting.notifier.email"),
|
||||
externalUrl: u,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Notify sends the alert notification.
|
||||
func (en *EmailNotifier) Notify(ctx context.Context, as ...*types.Alert) error {
|
||||
// TODO(codesome): make sure the receiver name is added in the ctx before calling this.
|
||||
ctx = notify.WithReceiverName(ctx, "email-notification-channel") // Dummy.
|
||||
// TODO(codesome): make sure the group labels is added in the ctx before calling this.
|
||||
ctx = notify.WithGroupLabels(ctx, model.LabelSet{}) // Dummy.
|
||||
|
||||
// We only need ExternalURL from this template object. This hack should go away with https://github.com/prometheus/alertmanager/pull/2508.
|
||||
data := notify.GetTemplateData(ctx, &template.Template{ExternalURL: en.externalUrl}, as, gokit_log.NewNopLogger())
|
||||
|
||||
cmd := &models.SendEmailCommandSync{
|
||||
SendEmailCommand: models.SendEmailCommand{
|
||||
Subject: "TODO",
|
||||
Data: map[string]interface{}{
|
||||
"Title": "TODO",
|
||||
"Subject": "TODO",
|
||||
"Receiver": data.Receiver,
|
||||
"Status": data.Status,
|
||||
"Alerts": data.Alerts,
|
||||
"GroupLabels": data.GroupLabels,
|
||||
"CommonLabels": data.CommonLabels,
|
||||
"CommonAnnotations": data.CommonAnnotations,
|
||||
"ExternalURL": data.ExternalURL,
|
||||
"RuleUrl": "TODO",
|
||||
"AlertPageUrl": "TODO",
|
||||
},
|
||||
To: en.Addresses,
|
||||
SingleEmail: en.SingleEmail,
|
||||
Template: "ng_alert_notification.html",
|
||||
},
|
||||
}
|
||||
|
||||
return bus.DispatchCtx(ctx, cmd)
|
||||
}
|
||||
59
pkg/services/ngalert/notifier/channels/email_test.go
Normal file
59
pkg/services/ngalert/notifier/channels/email_test.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package channels
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestEmailNotifier(t *testing.T) {
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
|
||||
settingsJSON, _ := simplejson.NewJson([]byte(json))
|
||||
model := &models.AlertNotification{
|
||||
Name: "ops",
|
||||
Type: "email",
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := NewEmailNotifier(model)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("from settings", func(t *testing.T) {
|
||||
json := `{"addresses": "ops@grafana.org"}`
|
||||
settingsJSON, err := simplejson.NewJson([]byte(json))
|
||||
require.NoError(t, err)
|
||||
|
||||
emailNotifier, err := NewEmailNotifier(&models.AlertNotification{
|
||||
Name: "ops",
|
||||
Type: "email",
|
||||
Settings: settingsJSON,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "ops", emailNotifier.Name)
|
||||
require.Equal(t, "email", emailNotifier.Type)
|
||||
require.Equal(t, []string{"ops@grafana.org"}, emailNotifier.Addresses)
|
||||
})
|
||||
|
||||
t.Run("from settings with two emails", func(t *testing.T) {
|
||||
json := `{"addresses": "ops@grafana.org;dev@grafana.org"}`
|
||||
settingsJSON, err := simplejson.NewJson([]byte(json))
|
||||
require.NoError(t, err)
|
||||
|
||||
emailNotifier, err := NewEmailNotifier(&models.AlertNotification{
|
||||
Name: "ops",
|
||||
Type: "email",
|
||||
Settings: settingsJSON,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "ops", emailNotifier.Name)
|
||||
require.Equal(t, "email", emailNotifier.Type)
|
||||
require.Equal(t, []string{"ops@grafana.org", "dev@grafana.org"}, emailNotifier.Addresses)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user