diff --git a/README.md b/README.md
index f9724df4..3e607978 100644
--- a/README.md
+++ b/README.md
@@ -1902,14 +1902,15 @@ endpoints:
#### Configuring Slack alerts
-| Parameter | Description | Default |
-|:-----------------------------------|:-------------------------------------------------------------------------------------------|:--------------|
-| `alerting.slack` | Configuration for alerts of type `slack` | `{}` |
-| `alerting.slack.webhook-url` | Slack Webhook URL | Required `""` |
-| `alerting.slack.default-alert` | Default alert configuration.
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[].group` | Endpoint group for which the configuration will be overridden by this configuration | `""` |
-| `alerting.slack.overrides[].*` | See `alerting.slack.*` parameters | `{}` |
+| Parameter | Description | Default |
+|:-----------------------------------|:-------------------------------------------------------------------------------------------|:------------------------------------|
+| `alerting.slack` | Configuration for alerts of type `slack` | `{}` |
+| `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.
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[].group` | Endpoint group for which the configuration will be overridden by this configuration | `""` |
+| `alerting.slack.overrides[].*` | See `alerting.slack.*` parameters | `{}` |
```yaml
alerting:
diff --git a/alerting/provider/slack/slack.go b/alerting/provider/slack/slack.go
index e8f5376f..2cef6d3c 100644
--- a/alerting/provider/slack/slack.go
+++ b/alerting/provider/slack/slack.go
@@ -20,7 +20,8 @@ var (
)
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 {
@@ -34,6 +35,9 @@ func (cfg *Config) Merge(override *Config) {
if len(override.WebhookURL) > 0 {
cfg.WebhookURL = override.WebhookURL
}
+ if len(override.Title) > 0 {
+ cfg.Title = override.Title
+ }
}
// 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 {
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)
if err != nil {
return err
@@ -111,7 +115,7 @@ type Field struct {
}
// 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
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)
@@ -138,13 +142,16 @@ func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *al
Text: "",
Attachments: []Attachment{
{
- Title: ":helmet_with_white_cross: Gatus",
+ Title: cfg.Title,
Text: message + description,
Short: false,
Color: color,
},
},
}
+ if len(body.Attachments[0].Title) == 0 {
+ body.Attachments[0].Title = ":helmet_with_white_cross: Gatus"
+ }
if len(formattedConditionResults) > 0 {
body.Attachments[0].Fields = append(body.Attachments[0].Fields, Field{
Title: "Condition results",
diff --git a/alerting/provider/slack/slack_test.go b/alerting/provider/slack/slack_test.go
index aa9bd1d3..b696f695 100644
--- a/alerting/provider/slack/slack_test.go
+++ b/alerting/provider/slack/slack_test.go
@@ -150,7 +150,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
}{
{
Name: "triggered",
- Provider: AlertProvider{},
+ Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com"}},
Endpoint: endpoint.Endpoint{Name: "name"},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false,
@@ -158,7 +158,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
},
{
Name: "triggered-with-group",
- Provider: AlertProvider{},
+ Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com"}},
Endpoint: endpoint.Endpoint{Name: "name", Group: "group"},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false,
@@ -167,7 +167,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
{
Name: "triggered-with-no-conditions",
NoConditions: true,
- Provider: AlertProvider{},
+ Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com"}},
Endpoint: endpoint.Endpoint{Name: "name"},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false,
@@ -175,7 +175,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
},
{
Name: "resolved",
- Provider: AlertProvider{},
+ Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com"}},
Endpoint: endpoint.Endpoint{Name: "name"},
Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: true,
@@ -183,12 +183,20 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
},
{
Name: "resolved-with-group",
- Provider: AlertProvider{},
+ Provider: AlertProvider{DefaultConfig: Config{WebhookURL: "http://example.com"}},
Endpoint: endpoint.Endpoint{Name: "name", Group: "group"},
Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3},
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}]}]}",
},
+ {
+ 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 {
t.Run(scenario.Name, func(t *testing.T) {
@@ -199,7 +207,12 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
{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(
+ cfg,
&scenario.Endpoint,
&scenario.Alert,
&endpoint.Result{