1
0
mirror of https://github.com/TwiN/gatus.git synced 2026-02-15 16:10:05 +00:00

fix(alerting): Support custom slack title (#1079)

This commit is contained in:
mehdiMj
2025-09-21 03:51:46 +03:30
committed by GitHub
parent cd10b31ab5
commit e6576e9080
3 changed files with 38 additions and 17 deletions

View File

@@ -1903,9 +1903,10 @@ endpoints:
#### Configuring Slack alerts #### Configuring Slack alerts
| Parameter | Description | Default | | Parameter | Description | Default |
|:-----------------------------------|:-------------------------------------------------------------------------------------------|:--------------| |:-----------------------------------|:-------------------------------------------------------------------------------------------|:------------------------------------|
| `alerting.slack` | Configuration for alerts of type `slack` | `{}` | | `alerting.slack` | Configuration for alerts of type `slack` | `{}` |
| `alerting.slack.webhook-url` | Slack Webhook URL | Required `""` | | `alerting.slack.webhook-url` | Slack Webhook URL | Required `""` |
| `alerting.slack.title` | Title of the notification | `":helmet_with_white_cross: Gatus"` |
| `alerting.slack.default-alert` | Default alert configuration. <br />See [Setting a default alert](#setting-a-default-alert) | N/A | | `alerting.slack.default-alert` | Default alert configuration. <br />See [Setting a default alert](#setting-a-default-alert) | N/A |
| `alerting.slack.overrides` | List of overrides that may be prioritized over the default configuration | `[]` | | `alerting.slack.overrides` | List of overrides that may be prioritized over the default configuration | `[]` |
| `alerting.slack.overrides[].group` | Endpoint group for which the configuration will be overridden by this configuration | `""` | | `alerting.slack.overrides[].group` | Endpoint group for which the configuration will be overridden by this configuration | `""` |

View File

@@ -21,6 +21,7 @@ var (
type Config struct { type Config struct {
WebhookURL string `yaml:"webhook-url"` // Slack webhook URL WebhookURL string `yaml:"webhook-url"` // Slack webhook URL
Title string `yaml:"title,omitempty"` // Title of the message that will be sent
} }
func (cfg *Config) Validate() error { func (cfg *Config) Validate() error {
@@ -34,6 +35,9 @@ func (cfg *Config) Merge(override *Config) {
if len(override.WebhookURL) > 0 { if len(override.WebhookURL) > 0 {
cfg.WebhookURL = override.WebhookURL cfg.WebhookURL = override.WebhookURL
} }
if len(override.Title) > 0 {
cfg.Title = override.Title
}
} }
// AlertProvider is the configuration necessary for sending an alert using Slack // 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
if err != nil { if err != nil {
return err return err
} }
buffer := bytes.NewBuffer(provider.buildRequestBody(ep, alert, result, resolved)) buffer := bytes.NewBuffer(provider.buildRequestBody(cfg, ep, alert, result, resolved))
request, err := http.NewRequest(http.MethodPost, cfg.WebhookURL, buffer) request, err := http.NewRequest(http.MethodPost, cfg.WebhookURL, buffer)
if err != nil { if err != nil {
return err return err
@@ -111,7 +115,7 @@ type Field struct {
} }
// buildRequestBody builds the request body for the provider // buildRequestBody builds the request body for the provider
func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte { func (provider *AlertProvider) buildRequestBody(cfg *Config, ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
var message, color string var message, color string
if resolved { if resolved {
message = fmt.Sprintf("An alert for *%s* has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), alert.SuccessThreshold) 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
Text: "", Text: "",
Attachments: []Attachment{ Attachments: []Attachment{
{ {
Title: ":helmet_with_white_cross: Gatus", Title: cfg.Title,
Text: message + description, Text: message + description,
Short: false, Short: false,
Color: color, Color: color,
}, },
}, },
} }
if len(body.Attachments[0].Title) == 0 {
body.Attachments[0].Title = ":helmet_with_white_cross: Gatus"
}
if len(formattedConditionResults) > 0 { if len(formattedConditionResults) > 0 {
body.Attachments[0].Fields = append(body.Attachments[0].Fields, Field{ body.Attachments[0].Fields = append(body.Attachments[0].Fields, Field{
Title: "Condition results", Title: "Condition results",

View File

@@ -150,7 +150,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
}{ }{
{ {
Name: "triggered", Name: "triggered",
Provider: AlertProvider{}, Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com"}},
Endpoint: endpoint.Endpoint{Name: "name"}, Endpoint: endpoint.Endpoint{Name: "name"},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3}, Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false, Resolved: false,
@@ -158,7 +158,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
}, },
{ {
Name: "triggered-with-group", Name: "triggered-with-group",
Provider: AlertProvider{}, Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com"}},
Endpoint: endpoint.Endpoint{Name: "name", Group: "group"}, Endpoint: endpoint.Endpoint{Name: "name", Group: "group"},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3}, Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false, Resolved: false,
@@ -167,7 +167,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
{ {
Name: "triggered-with-no-conditions", Name: "triggered-with-no-conditions",
NoConditions: true, NoConditions: true,
Provider: AlertProvider{}, Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com"}},
Endpoint: endpoint.Endpoint{Name: "name"}, Endpoint: endpoint.Endpoint{Name: "name"},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3}, Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false, Resolved: false,
@@ -175,7 +175,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
}, },
{ {
Name: "resolved", Name: "resolved",
Provider: AlertProvider{}, Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com"}},
Endpoint: endpoint.Endpoint{Name: "name"}, Endpoint: endpoint.Endpoint{Name: "name"},
Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3}, Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: true, Resolved: true,
@@ -183,12 +183,20 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
}, },
{ {
Name: "resolved-with-group", Name: "resolved-with-group",
Provider: AlertProvider{}, Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com"}},
Endpoint: endpoint.Endpoint{Name: "name", Group: "group"}, Endpoint: endpoint.Endpoint{Name: "name", Group: "group"},
Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3}, Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: true, Resolved: true,
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}]}]}", 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}]}]}",
}, },
{
Name: "resolved-with-group-and-custom-title",
Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com", Title: "custom title"}},
Endpoint: endpoint.Endpoint{Name: "name", Group: "group"},
Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: true,
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}]}]}",
},
} }
for _, scenario := range scenarios { for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) { t.Run(scenario.Name, func(t *testing.T) {
@@ -199,7 +207,12 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
{Condition: "[STATUS] == 200", Success: scenario.Resolved}, {Condition: "[STATUS] == 200", Success: scenario.Resolved},
} }
} }
cfg, err := scenario.Provider.GetConfig(scenario.Endpoint.Group, &scenario.Alert)
if err != nil {
t.Fatal("couldn't get config:", err.Error())
}
body := scenario.Provider.buildRequestBody( body := scenario.Provider.buildRequestBody(
cfg,
&scenario.Endpoint, &scenario.Endpoint,
&scenario.Alert, &scenario.Alert,
&endpoint.Result{ &endpoint.Result{