mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Allow customization of Google chat message (#43568)
* Allow customizable googlechat message via optional setting * Add optional message field in googlechat contact point configurator * Fix strange error message on send if template fails to fully evaluate * Elevate template evaluation failure logs to Warn level * Extract default.title template embed from all channels to shared constant
This commit is contained in:
@@ -740,6 +740,12 @@ func GetAvailableNotifiers() []*alerting.NotifierPlugin {
|
|||||||
PropertyName: "url",
|
PropertyName: "url",
|
||||||
Required: true,
|
Required: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Label: "Message",
|
||||||
|
Element: alerting.ElementTypeTextArea,
|
||||||
|
Placeholder: `{{ template "default.message" . }}`,
|
||||||
|
PropertyName: "message",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const DefaultMessageTitleEmbed = `{{ template "default.title" . }}`
|
||||||
|
|
||||||
var DefaultTemplateString = `
|
var DefaultTemplateString = `
|
||||||
{{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }} {{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ with .CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{ end }}{{ end }}
|
{{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }} {{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ with .CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{ end }}{{ end }}
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ func TestDefaultTemplateString(t *testing.T) {
|
|||||||
expected string
|
expected string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
templateString: `{{ template "default.title" .}}`,
|
templateString: DefaultMessageTitleEmbed,
|
||||||
expected: `[FIRING:2] (alert1)`,
|
expected: `[FIRING:2] (alert1)`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ func (dd *DingDingNotifier) Notify(ctx context.Context, as ...*types.Alert) (boo
|
|||||||
tmpl, _ := TmplText(ctx, dd.tmpl, as, dd.log, &tmplErr)
|
tmpl, _ := TmplText(ctx, dd.tmpl, as, dd.log, &tmplErr)
|
||||||
|
|
||||||
message := tmpl(dd.Message)
|
message := tmpl(dd.Message)
|
||||||
title := tmpl(`{{ template "default.title" . }}`)
|
title := tmpl(DefaultMessageTitleEmbed)
|
||||||
|
|
||||||
var bodyMsg map[string]interface{}
|
var bodyMsg map[string]interface{}
|
||||||
if tmpl(dd.MsgType) == "actionCard" {
|
if tmpl(dd.MsgType) == "actionCard" {
|
||||||
@@ -102,7 +102,7 @@ func (dd *DingDingNotifier) Notify(ctx context.Context, as ...*types.Alert) (boo
|
|||||||
|
|
||||||
u := tmpl(dd.URL)
|
u := tmpl(dd.URL)
|
||||||
if tmplErr != nil {
|
if tmplErr != nil {
|
||||||
dd.log.Debug("failed to template DingDing message", "err", tmplErr.Error())
|
dd.log.Warn("failed to template DingDing message", "err", tmplErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := json.Marshal(bodyMsg)
|
body, err := json.Marshal(bodyMsg)
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ func (d DiscordNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool,
|
|||||||
}
|
}
|
||||||
|
|
||||||
embed := simplejson.New()
|
embed := simplejson.New()
|
||||||
embed.Set("title", tmpl(`{{ template "default.title" . }}`))
|
embed.Set("title", tmpl(DefaultMessageTitleEmbed))
|
||||||
embed.Set("footer", footer)
|
embed.Set("footer", footer)
|
||||||
embed.Set("type", "rich")
|
embed.Set("type", "rich")
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ func (d DiscordNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool,
|
|||||||
|
|
||||||
u := tmpl(d.WebhookURL)
|
u := tmpl(d.WebhookURL)
|
||||||
if tmplErr != nil {
|
if tmplErr != nil {
|
||||||
d.log.Debug("failed to template Discord message", "err", tmplErr.Error())
|
d.log.Warn("failed to template Discord message", "err", tmplErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := json.Marshal(bodyJSON)
|
body, err := json.Marshal(bodyJSON)
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ func (en *EmailNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool,
|
|||||||
var tmplErr error
|
var tmplErr error
|
||||||
tmpl, data := TmplText(ctx, en.tmpl, as, en.log, &tmplErr)
|
tmpl, data := TmplText(ctx, en.tmpl, as, en.log, &tmplErr)
|
||||||
|
|
||||||
title := tmpl(`{{ template "default.title" . }}`)
|
title := tmpl(DefaultMessageTitleEmbed)
|
||||||
|
|
||||||
alertPageURL := en.tmpl.ExternalURL.String()
|
alertPageURL := en.tmpl.ExternalURL.String()
|
||||||
ruleURL := en.tmpl.ExternalURL.String()
|
ruleURL := en.tmpl.ExternalURL.String()
|
||||||
@@ -100,7 +100,7 @@ func (en *EmailNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tmplErr != nil {
|
if tmplErr != nil {
|
||||||
en.log.Debug("failed to template email message", "err", tmplErr.Error())
|
en.log.Warn("failed to template email message", "err", tmplErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := bus.Dispatch(ctx, cmd); err != nil {
|
if err := bus.Dispatch(ctx, cmd); err != nil {
|
||||||
|
|||||||
@@ -19,9 +19,10 @@ import (
|
|||||||
// alert notifications to Google chat.
|
// alert notifications to Google chat.
|
||||||
type GoogleChatNotifier struct {
|
type GoogleChatNotifier struct {
|
||||||
*Base
|
*Base
|
||||||
URL string
|
URL string
|
||||||
log log.Logger
|
log log.Logger
|
||||||
tmpl *template.Template
|
tmpl *template.Template
|
||||||
|
content string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGoogleChatNotifier(model *NotificationChannelConfig, t *template.Template) (*GoogleChatNotifier, error) {
|
func NewGoogleChatNotifier(model *NotificationChannelConfig, t *template.Template) (*GoogleChatNotifier, error) {
|
||||||
@@ -34,6 +35,8 @@ func NewGoogleChatNotifier(model *NotificationChannelConfig, t *template.Templat
|
|||||||
return nil, receiverInitError{Cfg: *model, Reason: "could not find url property in settings"}
|
return nil, receiverInitError{Cfg: *model, Reason: "could not find url property in settings"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
content := model.Settings.Get("message").MustString(`{{ template "default.message" . }}`)
|
||||||
|
|
||||||
return &GoogleChatNotifier{
|
return &GoogleChatNotifier{
|
||||||
Base: NewBase(&models.AlertNotification{
|
Base: NewBase(&models.AlertNotification{
|
||||||
Uid: model.UID,
|
Uid: model.UID,
|
||||||
@@ -42,9 +45,10 @@ func NewGoogleChatNotifier(model *NotificationChannelConfig, t *template.Templat
|
|||||||
DisableResolveMessage: model.DisableResolveMessage,
|
DisableResolveMessage: model.DisableResolveMessage,
|
||||||
Settings: model.Settings,
|
Settings: model.Settings,
|
||||||
}),
|
}),
|
||||||
URL: url,
|
URL: url,
|
||||||
log: log.New("alerting.notifier.googlechat"),
|
log: log.New("alerting.notifier.googlechat"),
|
||||||
tmpl: t,
|
tmpl: t,
|
||||||
|
content: content,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +61,7 @@ func (gcn *GoogleChatNotifier) Notify(ctx context.Context, as ...*types.Alert) (
|
|||||||
|
|
||||||
widgets := []widget{}
|
widgets := []widget{}
|
||||||
|
|
||||||
if msg := tmpl(`{{ template "default.message" . }}`); msg != "" {
|
if msg := tmpl(gcn.content); msg != "" {
|
||||||
// Add a text paragraph widget for the message if there is a message.
|
// Add a text paragraph widget for the message if there is a message.
|
||||||
// Google Chat API doesn't accept an empty text property.
|
// Google Chat API doesn't accept an empty text property.
|
||||||
widgets = append(widgets, textParagraphWidget{
|
widgets = append(widgets, textParagraphWidget{
|
||||||
@@ -67,6 +71,11 @@ func (gcn *GoogleChatNotifier) Notify(ctx context.Context, as ...*types.Alert) (
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tmplErr != nil {
|
||||||
|
gcn.log.Warn("failed to template Google Chat message", "err", tmplErr.Error())
|
||||||
|
tmplErr = nil
|
||||||
|
}
|
||||||
|
|
||||||
ruleURL := joinUrlPath(gcn.tmpl.ExternalURL.String(), "/alerting/list", gcn.log)
|
ruleURL := joinUrlPath(gcn.tmpl.ExternalURL.String(), "/alerting/list", gcn.log)
|
||||||
// Add a button widget (link to Grafana).
|
// Add a button widget (link to Grafana).
|
||||||
widgets = append(widgets, buttonWidget{
|
widgets = append(widgets, buttonWidget{
|
||||||
@@ -93,12 +102,12 @@ func (gcn *GoogleChatNotifier) Notify(ctx context.Context, as ...*types.Alert) (
|
|||||||
|
|
||||||
// Nest the required structs.
|
// Nest the required structs.
|
||||||
res := &outerStruct{
|
res := &outerStruct{
|
||||||
PreviewText: tmpl(`{{ template "default.title" . }}`),
|
PreviewText: tmpl(DefaultMessageTitleEmbed),
|
||||||
FallbackText: tmpl(`{{ template "default.title" . }}`),
|
FallbackText: tmpl(DefaultMessageTitleEmbed),
|
||||||
Cards: []card{
|
Cards: []card{
|
||||||
{
|
{
|
||||||
Header: header{
|
Header: header{
|
||||||
Title: tmpl(`{{ template "default.title" . }}`),
|
Title: tmpl(DefaultMessageTitleEmbed),
|
||||||
},
|
},
|
||||||
Sections: []section{
|
Sections: []section{
|
||||||
{
|
{
|
||||||
@@ -111,7 +120,7 @@ func (gcn *GoogleChatNotifier) Notify(ctx context.Context, as ...*types.Alert) (
|
|||||||
|
|
||||||
u := tmpl(gcn.URL)
|
u := tmpl(gcn.URL)
|
||||||
if tmplErr != nil {
|
if tmplErr != nil {
|
||||||
gcn.log.Debug("failed to template GoogleChat message", "err", tmplErr.Error())
|
gcn.log.Warn("failed to template GoogleChat message", "err", tmplErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := json.Marshal(res)
|
body, err := json.Marshal(res)
|
||||||
|
|||||||
@@ -152,6 +152,114 @@ func TestGoogleChatNotifier(t *testing.T) {
|
|||||||
name: "Error in initing",
|
name: "Error in initing",
|
||||||
settings: `{}`,
|
settings: `{}`,
|
||||||
expInitError: `failed to validate receiver "googlechat_testing" of type "googlechat": could not find url property in settings`,
|
expInitError: `failed to validate receiver "googlechat_testing" of type "googlechat": could not find url property in settings`,
|
||||||
|
}, {
|
||||||
|
name: "Customized message",
|
||||||
|
settings: `{"url": "http://localhost", "message": "I'm a custom template and you have {{ len .Alerts.Firing }} firing alert."}`,
|
||||||
|
alerts: []*types.Alert{
|
||||||
|
{
|
||||||
|
Alert: model.Alert{
|
||||||
|
Labels: model.LabelSet{"alertname": "alert1", "lbl1": "val1"},
|
||||||
|
Annotations: model.LabelSet{"ann1": "annv1", "__dashboardUid__": "abcd", "__panelId__": "efgh"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expMsg: &outerStruct{
|
||||||
|
PreviewText: "[FIRING:1] (val1)",
|
||||||
|
FallbackText: "[FIRING:1] (val1)",
|
||||||
|
Cards: []card{
|
||||||
|
{
|
||||||
|
Header: header{
|
||||||
|
Title: "[FIRING:1] (val1)",
|
||||||
|
},
|
||||||
|
Sections: []section{
|
||||||
|
{
|
||||||
|
Widgets: []widget{
|
||||||
|
textParagraphWidget{
|
||||||
|
Text: text{
|
||||||
|
Text: "I'm a custom template and you have 1 firing alert.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
buttonWidget{
|
||||||
|
Buttons: []button{
|
||||||
|
{
|
||||||
|
TextButton: textButton{
|
||||||
|
Text: "OPEN IN GRAFANA",
|
||||||
|
OnClick: onClick{
|
||||||
|
OpenLink: openLink{
|
||||||
|
URL: "http://localhost/alerting/list",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
textParagraphWidget{
|
||||||
|
Text: text{
|
||||||
|
// RFC822 only has the minute, hence it works in most cases.
|
||||||
|
Text: "Grafana v" + setting.BuildVersion + " | " + constNow.Format(time.RFC822),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expMsgError: nil,
|
||||||
|
}, {
|
||||||
|
name: "Invalid template",
|
||||||
|
settings: `{"url": "http://localhost", "message": "I'm a custom template {{ .NotAField }} bad template"}`,
|
||||||
|
alerts: []*types.Alert{
|
||||||
|
{
|
||||||
|
Alert: model.Alert{
|
||||||
|
Labels: model.LabelSet{"alertname": "alert1", "lbl1": "val1"},
|
||||||
|
Annotations: model.LabelSet{"ann1": "annv1", "__dashboardUid__": "abcd", "__panelId__": "efgh"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expMsg: &outerStruct{
|
||||||
|
PreviewText: "[FIRING:1] (val1)",
|
||||||
|
FallbackText: "[FIRING:1] (val1)",
|
||||||
|
Cards: []card{
|
||||||
|
{
|
||||||
|
Header: header{
|
||||||
|
Title: "[FIRING:1] (val1)",
|
||||||
|
},
|
||||||
|
Sections: []section{
|
||||||
|
{
|
||||||
|
Widgets: []widget{
|
||||||
|
textParagraphWidget{
|
||||||
|
Text: text{
|
||||||
|
Text: "I'm a custom template ",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
buttonWidget{
|
||||||
|
Buttons: []button{
|
||||||
|
{
|
||||||
|
TextButton: textButton{
|
||||||
|
Text: "OPEN IN GRAFANA",
|
||||||
|
OnClick: onClick{
|
||||||
|
OpenLink: openLink{
|
||||||
|
URL: "http://localhost/alerting/list",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
textParagraphWidget{
|
||||||
|
Text: text{
|
||||||
|
// RFC822 only has the minute, hence it works in most cases.
|
||||||
|
Text: "Grafana v" + setting.BuildVersion + " | " + constNow.Format(time.RFC822),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expMsgError: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func (kn *KafkaNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool,
|
|||||||
|
|
||||||
bodyJSON := simplejson.New()
|
bodyJSON := simplejson.New()
|
||||||
bodyJSON.Set("alert_state", state)
|
bodyJSON.Set("alert_state", state)
|
||||||
bodyJSON.Set("description", tmpl(`{{ template "default.title" . }}`))
|
bodyJSON.Set("description", tmpl(DefaultMessageTitleEmbed))
|
||||||
bodyJSON.Set("client", "Grafana")
|
bodyJSON.Set("client", "Grafana")
|
||||||
bodyJSON.Set("details", tmpl(`{{ template "default.message" . }}`))
|
bodyJSON.Set("details", tmpl(`{{ template "default.message" . }}`))
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ func (kn *KafkaNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool,
|
|||||||
topicURL := strings.TrimRight(kn.Endpoint, "/") + "/topics/" + tmpl(kn.Topic)
|
topicURL := strings.TrimRight(kn.Endpoint, "/") + "/topics/" + tmpl(kn.Topic)
|
||||||
|
|
||||||
if tmplErr != nil {
|
if tmplErr != nil {
|
||||||
kn.log.Debug("failed to template Kafka message", "err", tmplErr.Error())
|
kn.log.Warn("failed to template Kafka message", "err", tmplErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := &models.SendWebhookSync{
|
cmd := &models.SendWebhookSync{
|
||||||
|
|||||||
@@ -65,12 +65,12 @@ func (ln *LineNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool, e
|
|||||||
|
|
||||||
body := fmt.Sprintf(
|
body := fmt.Sprintf(
|
||||||
"%s\n%s\n\n%s",
|
"%s\n%s\n\n%s",
|
||||||
tmpl(`{{ template "default.title" . }}`),
|
tmpl(DefaultMessageTitleEmbed),
|
||||||
ruleURL,
|
ruleURL,
|
||||||
tmpl(`{{ template "default.message" . }}`),
|
tmpl(`{{ template "default.message" . }}`),
|
||||||
)
|
)
|
||||||
if tmplErr != nil {
|
if tmplErr != nil {
|
||||||
ln.log.Debug("failed to template Line message", "err", tmplErr.Error())
|
ln.log.Warn("failed to template Line message", "err", tmplErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
form := url.Values{}
|
form := url.Values{}
|
||||||
|
|||||||
@@ -156,10 +156,10 @@ func (on *OpsgenieNotifier) buildOpsgenieMessage(ctx context.Context, alerts mod
|
|||||||
var tmplErr error
|
var tmplErr error
|
||||||
tmpl, data := TmplText(ctx, on.tmpl, as, on.log, &tmplErr)
|
tmpl, data := TmplText(ctx, on.tmpl, as, on.log, &tmplErr)
|
||||||
|
|
||||||
title := tmpl(`{{ template "default.title" . }}`)
|
title := tmpl(DefaultMessageTitleEmbed)
|
||||||
description := fmt.Sprintf(
|
description := fmt.Sprintf(
|
||||||
"%s\n%s\n\n%s",
|
"%s\n%s\n\n%s",
|
||||||
tmpl(`{{ template "default.title" . }}`),
|
tmpl(DefaultMessageTitleEmbed),
|
||||||
ruleURL,
|
ruleURL,
|
||||||
tmpl(`{{ template "default.message" . }}`),
|
tmpl(`{{ template "default.message" . }}`),
|
||||||
)
|
)
|
||||||
@@ -207,7 +207,7 @@ func (on *OpsgenieNotifier) buildOpsgenieMessage(ctx context.Context, alerts mod
|
|||||||
apiURL = tmpl(on.APIUrl)
|
apiURL = tmpl(on.APIUrl)
|
||||||
|
|
||||||
if tmplErr != nil {
|
if tmplErr != nil {
|
||||||
on.log.Debug("failed to template Opsgenie message", "err", tmplErr.Error())
|
on.log.Warn("failed to template Opsgenie message", "err", tmplErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return bodyJSON, apiURL, nil
|
return bodyJSON, apiURL, nil
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func NewPagerdutyNotifier(model *NotificationChannelConfig, t *template.Template
|
|||||||
Class: model.Settings.Get("class").MustString("default"),
|
Class: model.Settings.Get("class").MustString("default"),
|
||||||
Component: model.Settings.Get("component").MustString("Grafana"),
|
Component: model.Settings.Get("component").MustString("Grafana"),
|
||||||
Group: model.Settings.Get("group").MustString("default"),
|
Group: model.Settings.Get("group").MustString("default"),
|
||||||
Summary: model.Settings.Get("summary").MustString(`{{ template "default.title" . }}`),
|
Summary: model.Settings.Get("summary").MustString(DefaultMessageTitleEmbed),
|
||||||
tmpl: t,
|
tmpl: t,
|
||||||
log: log.New("alerting.notifier." + model.Name),
|
log: log.New("alerting.notifier." + model.Name),
|
||||||
}, nil
|
}, nil
|
||||||
@@ -145,7 +145,7 @@ func (pn *PagerdutyNotifier) buildPagerdutyMessage(ctx context.Context, alerts m
|
|||||||
HRef: pn.tmpl.ExternalURL.String(),
|
HRef: pn.tmpl.ExternalURL.String(),
|
||||||
Text: "External URL",
|
Text: "External URL",
|
||||||
}},
|
}},
|
||||||
Description: tmpl(`{{ template "default.title" . }}`), // TODO: this can be configurable template.
|
Description: tmpl(DefaultMessageTitleEmbed), // TODO: this can be configurable template.
|
||||||
Payload: pagerDutyPayload{
|
Payload: pagerDutyPayload{
|
||||||
Component: tmpl(pn.Component),
|
Component: tmpl(pn.Component),
|
||||||
Summary: tmpl(pn.Summary),
|
Summary: tmpl(pn.Summary),
|
||||||
@@ -167,7 +167,7 @@ func (pn *PagerdutyNotifier) buildPagerdutyMessage(ctx context.Context, alerts m
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tmplErr != nil {
|
if tmplErr != nil {
|
||||||
pn.log.Debug("failed to template PagerDuty message", "err", tmplErr.Error())
|
pn.log.Warn("failed to template PagerDuty message", "err", tmplErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return msg, eventType, nil
|
return msg, eventType, nil
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ func (pn *PushoverNotifier) genPushoverBody(ctx context.Context, as ...*types.Al
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add title
|
// Add title
|
||||||
err = w.WriteField("title", tmpl(`{{ template "default.title" . }}`))
|
err = w.WriteField("title", tmpl(DefaultMessageTitleEmbed))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, b, err
|
return nil, b, err
|
||||||
}
|
}
|
||||||
@@ -218,7 +218,7 @@ func (pn *PushoverNotifier) genPushoverBody(ctx context.Context, as ...*types.Al
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tmplErr != nil {
|
if tmplErr != nil {
|
||||||
pn.log.Debug("failed to template pushover message", "err", tmplErr.Error())
|
pn.log.Warn("failed to template pushover message", "err", tmplErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark as html message
|
// Mark as html message
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ func (sn *SensuGoNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tmplErr != nil {
|
if tmplErr != nil {
|
||||||
sn.log.Debug("failed to template sensugo message", "err", tmplErr.Error())
|
sn.log.Warn("failed to template sensugo message", "err", tmplErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := json.Marshal(bodyMsgType)
|
body, err := json.Marshal(bodyMsgType)
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ func NewSlackNotifier(model *NotificationChannelConfig, t *template.Template, fn
|
|||||||
IconURL: model.Settings.Get("icon_url").MustString(),
|
IconURL: model.Settings.Get("icon_url").MustString(),
|
||||||
Token: token,
|
Token: token,
|
||||||
Text: model.Settings.Get("text").MustString(`{{ template "default.message" . }}`),
|
Text: model.Settings.Get("text").MustString(`{{ template "default.message" . }}`),
|
||||||
Title: model.Settings.Get("title").MustString(`{{ template "default.title" . }}`),
|
Title: model.Settings.Get("title").MustString(DefaultMessageTitleEmbed),
|
||||||
log: log.New("alerting.notifier.slack"),
|
log: log.New("alerting.notifier.slack"),
|
||||||
tmpl: t,
|
tmpl: t,
|
||||||
}, nil
|
}, nil
|
||||||
@@ -269,7 +269,7 @@ func (sn *SlackNotifier) buildSlackMessage(ctx context.Context, as []*types.Aler
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
if tmplErr != nil {
|
if tmplErr != nil {
|
||||||
sn.log.Debug("failed to template Slack message", "err", tmplErr.Error())
|
sn.log.Warn("failed to template Slack message", "err", tmplErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
mentionsBuilder := strings.Builder{}
|
mentionsBuilder := strings.Builder{}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func (tn *TeamsNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool,
|
|||||||
|
|
||||||
ruleURL := joinUrlPath(tn.tmpl.ExternalURL.String(), "/alerting/list", tn.log)
|
ruleURL := joinUrlPath(tn.tmpl.ExternalURL.String(), "/alerting/list", tn.log)
|
||||||
|
|
||||||
title := tmpl(`{{ template "default.title" . }}`)
|
title := tmpl(DefaultMessageTitleEmbed)
|
||||||
body := map[string]interface{}{
|
body := map[string]interface{}{
|
||||||
"@type": "MessageCard",
|
"@type": "MessageCard",
|
||||||
"@context": "http://schema.org/extensions",
|
"@context": "http://schema.org/extensions",
|
||||||
@@ -88,7 +88,7 @@ func (tn *TeamsNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool,
|
|||||||
|
|
||||||
u := tmpl(tn.URL)
|
u := tmpl(tn.URL)
|
||||||
if tmplErr != nil {
|
if tmplErr != nil {
|
||||||
tn.log.Debug("failed to template Teams message", "err", tmplErr.Error())
|
tn.log.Warn("failed to template Teams message", "err", tmplErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := json.Marshal(&body)
|
b, err := json.Marshal(&body)
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ func (tn *TelegramNotifier) buildTelegramMessage(ctx context.Context, as []*type
|
|||||||
|
|
||||||
message := tmpl(tn.Message)
|
message := tmpl(tn.Message)
|
||||||
if tmplErr != nil {
|
if tmplErr != nil {
|
||||||
tn.log.Debug("failed to template Telegram message", "err", tmplErr.Error())
|
tn.log.Warn("failed to template Telegram message", "err", tmplErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
msg["text"] = message
|
msg["text"] = message
|
||||||
|
|||||||
@@ -101,14 +101,14 @@ func (tn *ThreemaNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool
|
|||||||
// Build message
|
// Build message
|
||||||
message := fmt.Sprintf("%s%s\n\n*Message:*\n%s\n*URL:* %s\n",
|
message := fmt.Sprintf("%s%s\n\n*Message:*\n%s\n*URL:* %s\n",
|
||||||
stateEmoji,
|
stateEmoji,
|
||||||
tmpl(`{{ template "default.title" . }}`),
|
tmpl(DefaultMessageTitleEmbed),
|
||||||
tmpl(`{{ template "default.message" . }}`),
|
tmpl(`{{ template "default.message" . }}`),
|
||||||
path.Join(tn.tmpl.ExternalURL.String(), "/alerting/list"),
|
path.Join(tn.tmpl.ExternalURL.String(), "/alerting/list"),
|
||||||
)
|
)
|
||||||
data.Set("text", message)
|
data.Set("text", message)
|
||||||
|
|
||||||
if tmplErr != nil {
|
if tmplErr != nil {
|
||||||
tn.log.Debug("failed to template Threema message", "err", tmplErr.Error())
|
tn.log.Warn("failed to template Threema message", "err", tmplErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := &models.SendWebhookSync{
|
cmd := &models.SendWebhookSync{
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ func (vn *VictoropsNotifier) Notify(ctx context.Context, as ...*types.Alert) (bo
|
|||||||
bodyJSON := simplejson.New()
|
bodyJSON := simplejson.New()
|
||||||
bodyJSON.Set("message_type", messageType)
|
bodyJSON.Set("message_type", messageType)
|
||||||
bodyJSON.Set("entity_id", groupKey.Hash())
|
bodyJSON.Set("entity_id", groupKey.Hash())
|
||||||
bodyJSON.Set("entity_display_name", tmpl(`{{ template "default.title" . }}`))
|
bodyJSON.Set("entity_display_name", tmpl(DefaultMessageTitleEmbed))
|
||||||
bodyJSON.Set("timestamp", time.Now().Unix())
|
bodyJSON.Set("timestamp", time.Now().Unix())
|
||||||
bodyJSON.Set("state_message", tmpl(`{{ template "default.message" . }}`))
|
bodyJSON.Set("state_message", tmpl(`{{ template "default.message" . }}`))
|
||||||
bodyJSON.Set("monitoring_tool", "Grafana v"+setting.BuildVersion)
|
bodyJSON.Set("monitoring_tool", "Grafana v"+setting.BuildVersion)
|
||||||
@@ -97,7 +97,7 @@ func (vn *VictoropsNotifier) Notify(ctx context.Context, as ...*types.Alert) (bo
|
|||||||
|
|
||||||
u := tmpl(vn.URL)
|
u := tmpl(vn.URL)
|
||||||
if tmplErr != nil {
|
if tmplErr != nil {
|
||||||
vn.log.Debug("failed to template VictorOps message", "err", tmplErr.Error())
|
vn.log.Warn("failed to template VictorOps message", "err", tmplErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := bodyJSON.MarshalJSON()
|
b, err := bodyJSON.MarshalJSON()
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ func (wn *WebhookNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool
|
|||||||
GroupKey: groupKey.String(),
|
GroupKey: groupKey.String(),
|
||||||
TruncatedAlerts: numTruncated,
|
TruncatedAlerts: numTruncated,
|
||||||
OrgID: wn.orgID,
|
OrgID: wn.orgID,
|
||||||
Title: tmpl(`{{ template "default.title" . }}`),
|
Title: tmpl(DefaultMessageTitleEmbed),
|
||||||
Message: tmpl(`{{ template "default.message" . }}`),
|
Message: tmpl(`{{ template "default.message" . }}`),
|
||||||
}
|
}
|
||||||
if types.Alerts(as...).Status() == model.AlertFiring {
|
if types.Alerts(as...).Status() == model.AlertFiring {
|
||||||
@@ -102,7 +102,7 @@ func (wn *WebhookNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tmplErr != nil {
|
if tmplErr != nil {
|
||||||
wn.log.Debug("failed to template webhook message", "err", tmplErr.Error())
|
wn.log.Warn("failed to template webhook message", "err", tmplErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := json.Marshal(msg)
|
body, err := json.Marshal(msg)
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func (w *WeComNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool, e
|
|||||||
"msgtype": "markdown",
|
"msgtype": "markdown",
|
||||||
}
|
}
|
||||||
content := fmt.Sprintf("# %s\n%s\n",
|
content := fmt.Sprintf("# %s\n%s\n",
|
||||||
tmpl(`{{ template "default.title" . }}`),
|
tmpl(DefaultMessageTitleEmbed),
|
||||||
tmpl(w.Message),
|
tmpl(w.Message),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1487,6 +1487,22 @@ var expAvailableChannelJsonOutput = `
|
|||||||
"required": true,
|
"required": true,
|
||||||
"validationRule": "",
|
"validationRule": "",
|
||||||
"secure": false
|
"secure": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"element": "textarea",
|
||||||
|
"inputType": "",
|
||||||
|
"label": "Message",
|
||||||
|
"description": "",
|
||||||
|
"placeholder": "{{ template \"default.message\" . }}",
|
||||||
|
"propertyName": "message",
|
||||||
|
"selectOptions": null,
|
||||||
|
"showWhen": {
|
||||||
|
"field": "",
|
||||||
|
"is": ""
|
||||||
|
},
|
||||||
|
"required": false,
|
||||||
|
"validationRule": "",
|
||||||
|
"secure": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -81,6 +81,19 @@ export const grafanaNotifiersMock: NotifierDTO[] = [
|
|||||||
validationRule: '',
|
validationRule: '',
|
||||||
secure: false,
|
secure: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
element: 'textarea',
|
||||||
|
inputType: '',
|
||||||
|
label: 'Message',
|
||||||
|
description: '',
|
||||||
|
placeholder: '{{ template "default.message" . }}',
|
||||||
|
propertyName: 'message',
|
||||||
|
selectOptions: null,
|
||||||
|
showWhen: { field: '', is: '' },
|
||||||
|
required: false,
|
||||||
|
validationRule: '',
|
||||||
|
secure: false,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user