mirror of
https://github.com/grafana/grafana.git
synced 2025-02-20 11:48:34 -06:00
* Alerting: Validate contact point configuration during the migration This minimises the chances of generating broken configuration as part of the migration. Originally, we wanted to generate it and not produce a hard stop in Grafana but this strategy has the chance to avoid delivering notifications for our users. We now think it's better to hard stop the migration and let the user take care of resolving the configuration manually.
110 lines
2.9 KiB
Go
110 lines
2.9 KiB
Go
package channels
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/prometheus/alertmanager/template"
|
|
"github.com/prometheus/alertmanager/types"
|
|
|
|
"github.com/grafana/grafana/pkg/bus"
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/models"
|
|
)
|
|
|
|
// TeamsNotifier is responsible for sending
|
|
// alert notifications to Microsoft teams.
|
|
type TeamsNotifier struct {
|
|
*Base
|
|
URL string
|
|
Message string
|
|
tmpl *template.Template
|
|
log log.Logger
|
|
}
|
|
|
|
// NewTeamsNotifier is the constructor for Teams notifier.
|
|
func NewTeamsNotifier(model *NotificationChannelConfig, t *template.Template) (*TeamsNotifier, error) {
|
|
if model.Settings == nil {
|
|
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
|
}
|
|
|
|
u := model.Settings.Get("url").MustString()
|
|
if u == "" {
|
|
return nil, receiverInitError{Cfg: *model, Reason: "could not find url property in settings"}
|
|
}
|
|
|
|
return &TeamsNotifier{
|
|
Base: NewBase(&models.AlertNotification{
|
|
Uid: model.UID,
|
|
Name: model.Name,
|
|
Type: model.Type,
|
|
DisableResolveMessage: model.DisableResolveMessage,
|
|
Settings: model.Settings,
|
|
}),
|
|
URL: u,
|
|
Message: model.Settings.Get("message").MustString(`{{ template "teams.default.message" .}}`),
|
|
log: log.New("alerting.notifier.teams"),
|
|
tmpl: t,
|
|
}, nil
|
|
}
|
|
|
|
// Notify send an alert notification to Microsoft teams.
|
|
func (tn *TeamsNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
|
|
var tmplErr error
|
|
tmpl, _ := TmplText(ctx, tn.tmpl, as, tn.log, &tmplErr)
|
|
|
|
ruleURL := joinUrlPath(tn.tmpl.ExternalURL.String(), "/alerting/list", tn.log)
|
|
|
|
title := tmpl(`{{ template "default.title" . }}`)
|
|
body := map[string]interface{}{
|
|
"@type": "MessageCard",
|
|
"@context": "http://schema.org/extensions",
|
|
// summary MUST not be empty or the webhook request fails
|
|
// summary SHOULD contain some meaningful information, since it is used for mobile notifications
|
|
"summary": title,
|
|
"title": title,
|
|
"themeColor": getAlertStatusColor(types.Alerts(as...).Status()),
|
|
"sections": []map[string]interface{}{
|
|
{
|
|
"title": "Details",
|
|
"text": tmpl(tn.Message),
|
|
},
|
|
},
|
|
"potentialAction": []map[string]interface{}{
|
|
{
|
|
"@context": "http://schema.org",
|
|
"@type": "OpenUri",
|
|
"name": "View Rule",
|
|
"targets": []map[string]interface{}{
|
|
{
|
|
"os": "default",
|
|
"uri": ruleURL,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
u := tmpl(tn.URL)
|
|
if tmplErr != nil {
|
|
tn.log.Debug("failed to template Teams message", "err", tmplErr.Error())
|
|
}
|
|
|
|
b, err := json.Marshal(&body)
|
|
if err != nil {
|
|
return false, errors.Wrap(err, "marshal json")
|
|
}
|
|
cmd := &models.SendWebhookSync{Url: u, Body: string(b)}
|
|
|
|
if err := bus.DispatchCtx(ctx, cmd); err != nil {
|
|
return false, errors.Wrap(err, "send notification to Teams")
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func (tn *TeamsNotifier) SendResolved() bool {
|
|
return !tn.GetDisableResolveMessage()
|
|
}
|