Alerting: Option for Discord notifier to use webhook name (#40463)

* Added an option to discord notifier to use discord's webhook name (useful for customizing notifications).

* Support ngalert system with discord username toggle

* Added ngalert discord test

* Apply suggestions from code review

Co-authored-by: gotjosh <josue.abreu@gmail.com>

* Docs updated with discord username setting

* Fix api integration test

Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
Co-authored-by: gotjosh <josue.abreu@gmail.com>
This commit is contained in:
Skye 2021-10-26 11:55:10 -07:00 committed by GitHub
parent dfbb3c4e23
commit bce1011361
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 103 additions and 32 deletions

View File

@ -446,11 +446,12 @@ The following sections detail the supported settings and secure settings for eac
#### Alert notification `discord`
| Name | Secure setting |
| ---------- | -------------- |
| url | yes |
| avatar_url | |
| content | |
| Name | Secure setting |
| -------------------- | -------------- |
| url | yes |
| avatar_url | |
| content | |
| use_discord_username | |
#### Alert notification `slack`

View File

@ -227,11 +227,12 @@ In DingTalk PC Client:
To set up Discord, you must create a Discord channel webhook. For instructions on how to create the channel, refer to
[Intro to Webhooks](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks).
| Setting | Description |
| --------------- | --------------------------------------------------------------------------------- |
| Webhook URL | Discord webhook URL. |
| Message Content | Mention a group using @ or a user using <@ID> when notifying in a channel. |
| Avatar URL | Optionally, provide a URL to an image to use as the avatar for the bot's message. |
| Setting | Description |
| ------------------------------ | ----------------------------------------------------------------------------------------------------- |
| Webhook URL | Discord webhook URL. |
| Message Content | Mention a group using @ or a user using <@ID> when notifying in a channel. |
| Avatar URL | Optionally, provide a URL to an image to use as the avatar for the bot's message. |
| Use Discord's Webhook Username | Use the username configured in Discord's webhook settings. Otherwise, the username will be 'Grafana.' |
Alternately, use the [Slack](#slack) notifier by appending `/slack` to a Discord webhook URL.

View File

@ -47,6 +47,12 @@ func init() {
PropertyName: "url",
Required: true,
},
{
Label: "Use Discord's Webhook Username",
Description: "Use the username configured in Discord's webhook settings. Otherwise, the username will be 'Grafana'",
Element: alerting.ElementTypeCheckbox,
PropertyName: "use_discord_username",
},
},
})
}
@ -58,13 +64,15 @@ func newDiscordNotifier(model *models.AlertNotification, _ alerting.GetDecrypted
if url == "" {
return nil, alerting.ValidationError{Reason: "Could not find webhook url property in settings"}
}
useDiscordUsername := model.Settings.Get("use_discord_username").MustBool(false)
return &DiscordNotifier{
NotifierBase: NewNotifierBase(model),
Content: content,
AvatarURL: avatar,
WebhookURL: url,
log: log.New("alerting.notifier.discord"),
NotifierBase: NewNotifierBase(model),
Content: content,
AvatarURL: avatar,
WebhookURL: url,
log: log.New("alerting.notifier.discord"),
UseDiscordUsername: useDiscordUsername,
}, nil
}
@ -72,10 +80,11 @@ func newDiscordNotifier(model *models.AlertNotification, _ alerting.GetDecrypted
// notifications to discord.
type DiscordNotifier struct {
NotifierBase
Content string
AvatarURL string
WebhookURL string
log log.Logger
Content string
AvatarURL string
WebhookURL string
log log.Logger
UseDiscordUsername bool
}
// Notify send an alert notification to Discord.
@ -89,7 +98,9 @@ func (dn *DiscordNotifier) Notify(evalContext *alerting.EvalContext) error {
}
bodyJSON := simplejson.New()
bodyJSON.Set("username", "Grafana")
if !dn.UseDiscordUsername {
bodyJSON.Set("username", "Grafana")
}
if dn.Content != "" {
bodyJSON.Set("content", dn.Content)

View File

@ -694,6 +694,12 @@ func GetAvailableNotifiers() []*alerting.NotifierPlugin {
InputType: alerting.InputTypeText,
PropertyName: "avatar_url",
},
{
Label: "Use Discord's Webhook Username",
Description: "Use the username configured in Discord's webhook settings. Otherwise, the username will be 'Grafana'",
Element: alerting.ElementTypeCheckbox,
PropertyName: "use_discord_username",
},
},
},
{

View File

@ -18,11 +18,12 @@ import (
type DiscordNotifier struct {
*Base
log log.Logger
tmpl *template.Template
Content string
AvatarURL string
WebhookURL string
log log.Logger
tmpl *template.Template
Content string
AvatarURL string
WebhookURL string
UseDiscordUsername bool
}
func NewDiscordNotifier(model *NotificationChannelConfig, t *template.Template) (*DiscordNotifier, error) {
@ -37,6 +38,8 @@ func NewDiscordNotifier(model *NotificationChannelConfig, t *template.Template)
return nil, receiverInitError{Reason: "could not find webhook url property in settings", Cfg: *model}
}
useDiscordUsername := model.Settings.Get("use_discord_username").MustBool(false)
content := model.Settings.Get("message").MustString(`{{ template "default.message" . }}`)
return &DiscordNotifier{
@ -48,11 +51,12 @@ func NewDiscordNotifier(model *NotificationChannelConfig, t *template.Template)
Settings: model.Settings,
SecureSettings: model.SecureSettings,
}),
Content: content,
AvatarURL: avatarURL,
WebhookURL: discordURL,
log: log.New("alerting.notifier.discord"),
tmpl: t,
Content: content,
AvatarURL: avatarURL,
WebhookURL: discordURL,
log: log.New("alerting.notifier.discord"),
tmpl: t,
UseDiscordUsername: useDiscordUsername,
}, nil
}
@ -60,7 +64,10 @@ func (d DiscordNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool,
alerts := types.Alerts(as...)
bodyJSON := simplejson.New()
bodyJSON.Set("username", "Grafana")
if !d.UseDiscordUsername {
bodyJSON.Set("username", "Grafana")
}
var tmplErr error
tmpl, _ := TmplText(ctx, d.tmpl, as, d.log, &tmplErr)

View File

@ -100,6 +100,35 @@ func TestDiscordNotifier(t *testing.T) {
settings: `{}`,
expInitError: `failed to validate receiver "discord_testing" of type "discord": could not find webhook url property in settings`,
},
{
name: "Default config with one alert, use default discord username",
settings: `{
"url": "http://localhost",
"use_discord_username": true
}`,
alerts: []*types.Alert{
{
Alert: model.Alert{
Labels: model.LabelSet{"alertname": "alert1", "lbl1": "val1"},
Annotations: model.LabelSet{"ann1": "annv1", "__dashboardUid__": "abcd", "__panelId__": "efgh"},
},
},
},
expMsg: map[string]interface{}{
"content": "**Firing**\n\nLabels:\n - alertname = alert1\n - lbl1 = val1\nAnnotations:\n - ann1 = annv1\nSilence: http://localhost/alerting/silence/new?alertmanager=grafana&matchers=alertname%3Dalert1%2Clbl1%3Dval1\nDashboard: http://localhost/d/abcd\nPanel: http://localhost/d/abcd?viewPanel=efgh\n",
"embeds": []interface{}{map[string]interface{}{
"color": 1.4037554e+07,
"footer": map[string]interface{}{
"icon_url": "https://grafana.com/assets/img/fav32.png",
"text": "Grafana v",
},
"title": "[FIRING:1] (val1)",
"url": "http://localhost/alerting/list",
"type": "rich",
}},
},
expMsgError: nil,
},
}
for _, c := range cases {

View File

@ -1405,7 +1405,23 @@ var expAvailableChannelJsonOutput = `
"required": false,
"validationRule": "",
"secure": false
}
},
{
"element": "checkbox",
"inputType": "",
"label": "Use Discord's Webhook Username",
"description": "Use the username configured in Discord's webhook settings. Otherwise, the username will be 'Grafana'",
"placeholder": "",
"propertyName": "use_discord_username",
"selectOptions": null,
"showWhen": {
"field": "",
"is": ""
},
"required": false,
"validationRule": "",
"secure": false
}
]
},
{