mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Add support for configuring avatar URL for the Discord notifier (#33355)
Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com>
This commit is contained in:
parent
66e2624ae0
commit
badec6c6ad
@ -437,6 +437,14 @@ The following sections detail the supported settings and secure settings for eac
|
|||||||
| sound | |
|
| sound | |
|
||||||
| okSound | |
|
| okSound | |
|
||||||
|
|
||||||
|
#### Alert notification `discord`
|
||||||
|
|
||||||
|
| Name | Secure setting |
|
||||||
|
| -------------- | -------------- |
|
||||||
|
| url | yes |
|
||||||
|
| avatar_url | |
|
||||||
|
| message | |
|
||||||
|
|
||||||
#### Alert notification `slack`
|
#### Alert notification `slack`
|
||||||
|
|
||||||
| Name | Secure setting |
|
| Name | Secure setting |
|
||||||
|
@ -52,7 +52,7 @@ Alert rule evaluation interval | Send reminders every | Reminder sent every (aft
|
|||||||
Name | Type | Supports images | Support alert rule tags
|
Name | Type | Supports images | Support alert rule tags
|
||||||
-----|------|---------------- | -----------------------
|
-----|------|---------------- | -----------------------
|
||||||
[DingDing](#dingdingdingtalk) | `dingding` | yes, external only | no
|
[DingDing](#dingdingdingtalk) | `dingding` | yes, external only | no
|
||||||
Discord | `discord` | yes | no
|
[Discord](#discord) | `discord` | yes | no
|
||||||
[Email](#email) | `email` | yes | no
|
[Email](#email) | `email` | yes | no
|
||||||
[Google Hangouts Chat](#google-hangouts-chat) | `googlechat` | yes, external only | no
|
[Google Hangouts Chat](#google-hangouts-chat) | `googlechat` | yes, external only | no
|
||||||
Hipchat | `hipchat` | yes, external only | no
|
Hipchat | `hipchat` | yes, external only | no
|
||||||
@ -220,6 +220,19 @@ In DingTalk PC Client:
|
|||||||
|
|
||||||
6. There will be a Webhook URL in the panel, looks like this: https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxx. Copy this URL to the Grafana DingTalk setting page and then click "finish".
|
6. There will be a Webhook URL in the panel, looks like this: https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxx. Copy this URL to the Grafana DingTalk setting page and then click "finish".
|
||||||
|
|
||||||
|
### Discord
|
||||||
|
|
||||||
|
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) f.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Alternately, use the [Slack](#slack) notifier by appending `/slack` to a Discord webhook URL.
|
||||||
|
|
||||||
### Kafka
|
### Kafka
|
||||||
|
|
||||||
Notifications can be sent to a Kafka topic from Grafana using the [Kafka REST Proxy](https://docs.confluent.io/1.0/kafka-rest/docs/index.html).
|
Notifications can be sent to a Kafka topic from Grafana using the [Kafka REST Proxy](https://docs.confluent.io/1.0/kafka-rest/docs/index.html).
|
||||||
|
@ -25,6 +25,13 @@ func init() {
|
|||||||
Factory: newDiscordNotifier,
|
Factory: newDiscordNotifier,
|
||||||
Heading: "Discord settings",
|
Heading: "Discord settings",
|
||||||
Options: []alerting.NotifierOption{
|
Options: []alerting.NotifierOption{
|
||||||
|
{
|
||||||
|
Label: "Avatar URL",
|
||||||
|
Element: alerting.ElementTypeInput,
|
||||||
|
InputType: alerting.InputTypeText,
|
||||||
|
Description: "Provide a URL to an image to use as the avatar for the bot's message",
|
||||||
|
PropertyName: "avatar_url",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Label: "Message Content",
|
Label: "Message Content",
|
||||||
Description: "Mention a group using @ or a user using <@ID> when notifying in a channel",
|
Description: "Mention a group using @ or a user using <@ID> when notifying in a channel",
|
||||||
@ -45,6 +52,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newDiscordNotifier(model *models.AlertNotification) (alerting.Notifier, error) {
|
func newDiscordNotifier(model *models.AlertNotification) (alerting.Notifier, error) {
|
||||||
|
avatar := model.Settings.Get("avatar_url").MustString()
|
||||||
content := model.Settings.Get("content").MustString()
|
content := model.Settings.Get("content").MustString()
|
||||||
url := model.Settings.Get("url").MustString()
|
url := model.Settings.Get("url").MustString()
|
||||||
if url == "" {
|
if url == "" {
|
||||||
@ -54,6 +62,7 @@ func newDiscordNotifier(model *models.AlertNotification) (alerting.Notifier, err
|
|||||||
return &DiscordNotifier{
|
return &DiscordNotifier{
|
||||||
NotifierBase: NewNotifierBase(model),
|
NotifierBase: NewNotifierBase(model),
|
||||||
Content: content,
|
Content: content,
|
||||||
|
AvatarURL: avatar,
|
||||||
WebhookURL: url,
|
WebhookURL: url,
|
||||||
log: log.New("alerting.notifier.discord"),
|
log: log.New("alerting.notifier.discord"),
|
||||||
}, nil
|
}, nil
|
||||||
@ -64,6 +73,7 @@ func newDiscordNotifier(model *models.AlertNotification) (alerting.Notifier, err
|
|||||||
type DiscordNotifier struct {
|
type DiscordNotifier struct {
|
||||||
NotifierBase
|
NotifierBase
|
||||||
Content string
|
Content string
|
||||||
|
AvatarURL string
|
||||||
WebhookURL string
|
WebhookURL string
|
||||||
log log.Logger
|
log log.Logger
|
||||||
}
|
}
|
||||||
@ -85,6 +95,10 @@ func (dn *DiscordNotifier) Notify(evalContext *alerting.EvalContext) error {
|
|||||||
bodyJSON.Set("content", dn.Content)
|
bodyJSON.Set("content", dn.Content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if dn.AvatarURL != "" {
|
||||||
|
bodyJSON.Set("avatar_url", dn.AvatarURL)
|
||||||
|
}
|
||||||
|
|
||||||
fields := make([]map[string]interface{}, 0)
|
fields := make([]map[string]interface{}, 0)
|
||||||
|
|
||||||
for _, evt := range evalContext.EvalMatches {
|
for _, evt := range evalContext.EvalMatches {
|
||||||
|
@ -28,6 +28,7 @@ func TestDiscordNotifier(t *testing.T) {
|
|||||||
Convey("settings should trigger incident", func() {
|
Convey("settings should trigger incident", func() {
|
||||||
json := `
|
json := `
|
||||||
{
|
{
|
||||||
|
"avatar_url": "https://grafana.com/img/fav32.png",
|
||||||
"content": "@everyone Please check this notification",
|
"content": "@everyone Please check this notification",
|
||||||
"url": "https://web.hook/"
|
"url": "https://web.hook/"
|
||||||
}`
|
}`
|
||||||
@ -45,6 +46,7 @@ func TestDiscordNotifier(t *testing.T) {
|
|||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(discordNotifier.Name, ShouldEqual, "discord_testing")
|
So(discordNotifier.Name, ShouldEqual, "discord_testing")
|
||||||
So(discordNotifier.Type, ShouldEqual, "discord")
|
So(discordNotifier.Type, ShouldEqual, "discord")
|
||||||
|
So(discordNotifier.AvatarURL, ShouldEqual, "https://grafana.com/img/fav32.png")
|
||||||
So(discordNotifier.Content, ShouldEqual, "@everyone Please check this notification")
|
So(discordNotifier.Content, ShouldEqual, "@everyone Please check this notification")
|
||||||
So(discordNotifier.WebhookURL, ShouldEqual, "https://web.hook/")
|
So(discordNotifier.WebhookURL, ShouldEqual, "https://web.hook/")
|
||||||
})
|
})
|
||||||
|
@ -688,6 +688,12 @@ func GetAvailableNotifiers() []*alerting.NotifierPlugin {
|
|||||||
PropertyName: "url",
|
PropertyName: "url",
|
||||||
Required: true,
|
Required: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Label: "Avatar URL",
|
||||||
|
Element: alerting.ElementTypeInput,
|
||||||
|
InputType: alerting.InputTypeText,
|
||||||
|
PropertyName: "avatar_url",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -24,6 +24,7 @@ type DiscordNotifier struct {
|
|||||||
log log.Logger
|
log log.Logger
|
||||||
tmpl *template.Template
|
tmpl *template.Template
|
||||||
Content string
|
Content string
|
||||||
|
AvatarURL string
|
||||||
WebhookURL string
|
WebhookURL string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,6 +33,8 @@ func NewDiscordNotifier(model *NotificationChannelConfig, t *template.Template)
|
|||||||
return nil, alerting.ValidationError{Reason: "No Settings Supplied"}
|
return nil, alerting.ValidationError{Reason: "No Settings Supplied"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
avatarURL := model.Settings.Get("avatar_url").MustString()
|
||||||
|
|
||||||
discordURL := model.Settings.Get("url").MustString()
|
discordURL := model.Settings.Get("url").MustString()
|
||||||
if discordURL == "" {
|
if discordURL == "" {
|
||||||
return nil, alerting.ValidationError{Reason: "Could not find webhook url property in settings"}
|
return nil, alerting.ValidationError{Reason: "Could not find webhook url property in settings"}
|
||||||
@ -49,6 +52,7 @@ func NewDiscordNotifier(model *NotificationChannelConfig, t *template.Template)
|
|||||||
SecureSettings: model.SecureSettings,
|
SecureSettings: model.SecureSettings,
|
||||||
}),
|
}),
|
||||||
Content: content,
|
Content: content,
|
||||||
|
AvatarURL: avatarURL,
|
||||||
WebhookURL: discordURL,
|
WebhookURL: discordURL,
|
||||||
log: log.New("alerting.notifier.discord"),
|
log: log.New("alerting.notifier.discord"),
|
||||||
tmpl: t,
|
tmpl: t,
|
||||||
@ -70,6 +74,10 @@ func (d DiscordNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool,
|
|||||||
bodyJSON.Set("content", tmpl(d.Content))
|
bodyJSON.Set("content", tmpl(d.Content))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.AvatarURL != "" {
|
||||||
|
bodyJSON.Set("avatar_url", tmpl(d.AvatarURL))
|
||||||
|
}
|
||||||
|
|
||||||
footer := map[string]interface{}{
|
footer := map[string]interface{}{
|
||||||
"text": "Grafana v" + setting.BuildVersion,
|
"text": "Grafana v" + setting.BuildVersion,
|
||||||
"icon_url": "https://grafana.com/assets/img/fav32.png",
|
"icon_url": "https://grafana.com/assets/img/fav32.png",
|
||||||
|
@ -64,6 +64,7 @@ func TestDiscordNotifier(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "Custom config with multiple alerts",
|
name: "Custom config with multiple alerts",
|
||||||
settings: `{
|
settings: `{
|
||||||
|
"avatar_url": "https://grafana.com/assets/img/fav32.png",
|
||||||
"url": "http://localhost",
|
"url": "http://localhost",
|
||||||
"message": "{{ len .Alerts.Firing }} alerts are firing, {{ len .Alerts.Resolved }} are resolved"
|
"message": "{{ len .Alerts.Firing }} alerts are firing, {{ len .Alerts.Resolved }} are resolved"
|
||||||
}`,
|
}`,
|
||||||
@ -81,7 +82,8 @@ func TestDiscordNotifier(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
expMsg: map[string]interface{}{
|
expMsg: map[string]interface{}{
|
||||||
"content": "2 alerts are firing, 0 are resolved",
|
"avatar_url": "https://grafana.com/assets/img/fav32.png",
|
||||||
|
"content": "2 alerts are firing, 0 are resolved",
|
||||||
"embeds": []interface{}{map[string]interface{}{
|
"embeds": []interface{}{map[string]interface{}{
|
||||||
"color": 1.4037554e+07,
|
"color": 1.4037554e+07,
|
||||||
"footer": map[string]interface{}{
|
"footer": map[string]interface{}{
|
||||||
|
@ -1385,6 +1385,22 @@ var expAvailableChannelJsonOutput = `
|
|||||||
"required": true,
|
"required": true,
|
||||||
"validationRule": "",
|
"validationRule": "",
|
||||||
"secure": false
|
"secure": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Avatar URL",
|
||||||
|
"description": "",
|
||||||
|
"element": "input",
|
||||||
|
"inputType": "text",
|
||||||
|
"placeholder": "",
|
||||||
|
"propertyName": "avatar_url",
|
||||||
|
"selectOptions": null,
|
||||||
|
"showWhen": {
|
||||||
|
"field": "",
|
||||||
|
"is": ""
|
||||||
|
},
|
||||||
|
"required": false,
|
||||||
|
"validationRule": "",
|
||||||
|
"secure": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user