Skip to content

Commit e6576e9

Browse files
authored
fix(alerting): Support custom slack title (#1079)
1 parent cd10b31 commit e6576e9

File tree

3 files changed

+38
-17
lines changed

3 files changed

+38
-17
lines changed

README.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,14 +1902,15 @@ endpoints:
19021902

19031903

19041904
#### Configuring Slack alerts
1905-
| Parameter | Description | Default |
1906-
|:-----------------------------------|:-------------------------------------------------------------------------------------------|:--------------|
1907-
| `alerting.slack` | Configuration for alerts of type `slack` | `{}` |
1908-
| `alerting.slack.webhook-url` | Slack Webhook URL | Required `""` |
1909-
| `alerting.slack.default-alert` | Default alert configuration. <br />See [Setting a default alert](#setting-a-default-alert) | N/A |
1910-
| `alerting.slack.overrides` | List of overrides that may be prioritized over the default configuration | `[]` |
1911-
| `alerting.slack.overrides[].group` | Endpoint group for which the configuration will be overridden by this configuration | `""` |
1912-
| `alerting.slack.overrides[].*` | See `alerting.slack.*` parameters | `{}` |
1905+
| Parameter | Description | Default |
1906+
|:-----------------------------------|:-------------------------------------------------------------------------------------------|:------------------------------------|
1907+
| `alerting.slack` | Configuration for alerts of type `slack` | `{}` |
1908+
| `alerting.slack.webhook-url` | Slack Webhook URL | Required `""` |
1909+
| `alerting.slack.title` | Title of the notification | `":helmet_with_white_cross: Gatus"` |
1910+
| `alerting.slack.default-alert` | Default alert configuration. <br />See [Setting a default alert](#setting-a-default-alert) | N/A |
1911+
| `alerting.slack.overrides` | List of overrides that may be prioritized over the default configuration | `[]` |
1912+
| `alerting.slack.overrides[].group` | Endpoint group for which the configuration will be overridden by this configuration | `""` |
1913+
| `alerting.slack.overrides[].*` | See `alerting.slack.*` parameters | `{}` |
19131914

19141915
```yaml
19151916
alerting:

alerting/provider/slack/slack.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ var (
2020
)
2121

2222
type Config struct {
23-
WebhookURL string `yaml:"webhook-url"` // Slack webhook URL
23+
WebhookURL string `yaml:"webhook-url"` // Slack webhook URL
24+
Title string `yaml:"title,omitempty"` // Title of the message that will be sent
2425
}
2526

2627
func (cfg *Config) Validate() error {
@@ -34,6 +35,9 @@ func (cfg *Config) Merge(override *Config) {
3435
if len(override.WebhookURL) > 0 {
3536
cfg.WebhookURL = override.WebhookURL
3637
}
38+
if len(override.Title) > 0 {
39+
cfg.Title = override.Title
40+
}
3741
}
3842

3943
// AlertProvider is the configuration necessary for sending an alert using Slack
@@ -73,7 +77,7 @@ func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, r
7377
if err != nil {
7478
return err
7579
}
76-
buffer := bytes.NewBuffer(provider.buildRequestBody(ep, alert, result, resolved))
80+
buffer := bytes.NewBuffer(provider.buildRequestBody(cfg, ep, alert, result, resolved))
7781
request, err := http.NewRequest(http.MethodPost, cfg.WebhookURL, buffer)
7882
if err != nil {
7983
return err
@@ -111,7 +115,7 @@ type Field struct {
111115
}
112116

113117
// buildRequestBody builds the request body for the provider
114-
func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
118+
func (provider *AlertProvider) buildRequestBody(cfg *Config, ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
115119
var message, color string
116120
if resolved {
117121
message = fmt.Sprintf("An alert for *%s* has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), alert.SuccessThreshold)
@@ -138,13 +142,16 @@ func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *al
138142
Text: "",
139143
Attachments: []Attachment{
140144
{
141-
Title: ":helmet_with_white_cross: Gatus",
145+
Title: cfg.Title,
142146
Text: message + description,
143147
Short: false,
144148
Color: color,
145149
},
146150
},
147151
}
152+
if len(body.Attachments[0].Title) == 0 {
153+
body.Attachments[0].Title = ":helmet_with_white_cross: Gatus"
154+
}
148155
if len(formattedConditionResults) > 0 {
149156
body.Attachments[0].Fields = append(body.Attachments[0].Fields, Field{
150157
Title: "Condition results",

alerting/provider/slack/slack_test.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,15 +150,15 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
150150
}{
151151
{
152152
Name: "triggered",
153-
Provider: AlertProvider{},
153+
Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com"}},
154154
Endpoint: endpoint.Endpoint{Name: "name"},
155155
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
156156
Resolved: false,
157157
ExpectedBody: "{\"text\":\"\",\"attachments\":[{\"title\":\":helmet_with_white_cross: Gatus\",\"text\":\"An alert for *name* has been triggered due to having failed 3 time(s) in a row:\\n\\u003e description-1\",\"short\":false,\"color\":\"#DD0000\",\"fields\":[{\"title\":\"Condition results\",\"value\":\":x: - `[CONNECTED] == true`\\n:x: - `[STATUS] == 200`\\n\",\"short\":false}]}]}",
158158
},
159159
{
160160
Name: "triggered-with-group",
161-
Provider: AlertProvider{},
161+
Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com"}},
162162
Endpoint: endpoint.Endpoint{Name: "name", Group: "group"},
163163
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
164164
Resolved: false,
@@ -167,28 +167,36 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
167167
{
168168
Name: "triggered-with-no-conditions",
169169
NoConditions: true,
170-
Provider: AlertProvider{},
170+
Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com"}},
171171
Endpoint: endpoint.Endpoint{Name: "name"},
172172
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
173173
Resolved: false,
174174
ExpectedBody: "{\"text\":\"\",\"attachments\":[{\"title\":\":helmet_with_white_cross: Gatus\",\"text\":\"An alert for *name* has been triggered due to having failed 3 time(s) in a row:\\n\\u003e description-1\",\"short\":false,\"color\":\"#DD0000\"}]}",
175175
},
176176
{
177177
Name: "resolved",
178-
Provider: AlertProvider{},
178+
Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com"}},
179179
Endpoint: endpoint.Endpoint{Name: "name"},
180180
Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3},
181181
Resolved: true,
182182
ExpectedBody: "{\"text\":\"\",\"attachments\":[{\"title\":\":helmet_with_white_cross: Gatus\",\"text\":\"An alert for *name* has been resolved after passing successfully 5 time(s) in a row:\\n\\u003e description-2\",\"short\":false,\"color\":\"#36A64F\",\"fields\":[{\"title\":\"Condition results\",\"value\":\":white_check_mark: - `[CONNECTED] == true`\\n:white_check_mark: - `[STATUS] == 200`\\n\",\"short\":false}]}]}",
183183
},
184184
{
185185
Name: "resolved-with-group",
186-
Provider: AlertProvider{},
186+
Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com"}},
187187
Endpoint: endpoint.Endpoint{Name: "name", Group: "group"},
188188
Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3},
189189
Resolved: true,
190190
ExpectedBody: "{\"text\":\"\",\"attachments\":[{\"title\":\":helmet_with_white_cross: Gatus\",\"text\":\"An alert for *group/name* has been resolved after passing successfully 5 time(s) in a row:\\n\\u003e description-2\",\"short\":false,\"color\":\"#36A64F\",\"fields\":[{\"title\":\"Condition results\",\"value\":\":white_check_mark: - `[CONNECTED] == true`\\n:white_check_mark: - `[STATUS] == 200`\\n\",\"short\":false}]}]}",
191191
},
192+
{
193+
Name: "resolved-with-group-and-custom-title",
194+
Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com", Title: "custom title"}},
195+
Endpoint: endpoint.Endpoint{Name: "name", Group: "group"},
196+
Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3},
197+
Resolved: true,
198+
ExpectedBody: "{\"text\":\"\",\"attachments\":[{\"title\":\"custom title\",\"text\":\"An alert for *group/name* has been resolved after passing successfully 5 time(s) in a row:\\n\\u003e description-2\",\"short\":false,\"color\":\"#36A64F\",\"fields\":[{\"title\":\"Condition results\",\"value\":\":white_check_mark: - `[CONNECTED] == true`\\n:white_check_mark: - `[STATUS] == 200`\\n\",\"short\":false}]}]}",
199+
},
192200
}
193201
for _, scenario := range scenarios {
194202
t.Run(scenario.Name, func(t *testing.T) {
@@ -199,7 +207,12 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
199207
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
200208
}
201209
}
210+
cfg, err := scenario.Provider.GetConfig(scenario.Endpoint.Group, &scenario.Alert)
211+
if err != nil {
212+
t.Fatal("couldn't get config:", err.Error())
213+
}
202214
body := scenario.Provider.buildRequestBody(
215+
cfg,
203216
&scenario.Endpoint,
204217
&scenario.Alert,
205218
&endpoint.Result{

0 commit comments

Comments
 (0)