mirror of
https://github.com/TwiN/gatus.git
synced 2024-11-22 16:03:44 +01:00
e307d1ab35
* feat(alerting): Add group-specific webhook URL for discord Add group-specific webhook URL for discord alert Provides support for paging multiple Discords based on the group selector while keeping backward compatibility to the old Discords configuration manifest integration per team can be specified in the overrides sections in an array form. ref: #96 Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> * docs: update Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> * Update README.md * Update README.md * Update alerting/provider/discord/discord.go Co-authored-by: TwiN <twin@linux.com> * Update README.md Co-authored-by: TwiN <twin@linux.com> * test: revert testing name * Update alerting/provider/discord/discord_test.go Co-authored-by: TwiN <twin@linux.com> Co-authored-by: TwiN <twin@linux.com>
123 lines
3.9 KiB
Go
123 lines
3.9 KiB
Go
package discord
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
|
|
"github.com/TwiN/gatus/v3/alerting/alert"
|
|
"github.com/TwiN/gatus/v3/client"
|
|
"github.com/TwiN/gatus/v3/core"
|
|
)
|
|
|
|
// AlertProvider is the configuration necessary for sending an alert using Discord
|
|
type AlertProvider struct {
|
|
WebhookURL string `yaml:"webhook-url"`
|
|
|
|
// DefaultAlert is the default alert configuration to use for endpoints with an alert of the appropriate type
|
|
DefaultAlert *alert.Alert `yaml:"default-alert,omitempty"`
|
|
|
|
// Overrides is a list of Override that may be prioritized over the default configuration
|
|
Overrides []Override `yaml:"overrides,omitempty"`
|
|
}
|
|
|
|
// Override is a case under which the default integration is overridden
|
|
type Override struct {
|
|
Group string `yaml:"group"`
|
|
WebhookURL string `yaml:"webhook-url"`
|
|
}
|
|
|
|
// IsValid returns whether the provider's configuration is valid
|
|
func (provider *AlertProvider) IsValid() bool {
|
|
registeredGroups := make(map[string]bool)
|
|
if provider.Overrides != nil {
|
|
for _, override := range provider.Overrides {
|
|
if isAlreadyRegistered := registeredGroups[override.Group]; isAlreadyRegistered || override.Group == "" || len(override.WebhookURL) == 0 {
|
|
return false
|
|
}
|
|
registeredGroups[override.Group] = true
|
|
}
|
|
}
|
|
return len(provider.WebhookURL) > 0
|
|
}
|
|
|
|
// Send an alert using the provider
|
|
func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
|
|
buffer := bytes.NewBuffer([]byte(provider.buildRequestBody(endpoint, alert, result, resolved)))
|
|
request, err := http.NewRequest(http.MethodPost, provider.getWebhookURLForGroup(endpoint.Group), buffer)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
request.Header.Set("Content-Type", "application/json")
|
|
response, err := client.GetHTTPClient(nil).Do(request)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if response.StatusCode > 399 {
|
|
body, _ := io.ReadAll(response.Body)
|
|
return fmt.Errorf("call to provider alert returned status code %d: %s", response.StatusCode, string(body))
|
|
}
|
|
return err
|
|
}
|
|
|
|
// buildRequestBody builds the request body for the provider
|
|
func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) string {
|
|
var message, results string
|
|
var colorCode int
|
|
if resolved {
|
|
message = fmt.Sprintf("An alert for **%s** has been resolved after passing successfully %d time(s) in a row", endpoint.DisplayName(), alert.SuccessThreshold)
|
|
colorCode = 3066993
|
|
} else {
|
|
message = fmt.Sprintf("An alert for **%s** has been triggered due to having failed %d time(s) in a row", endpoint.DisplayName(), alert.FailureThreshold)
|
|
colorCode = 15158332
|
|
}
|
|
for _, conditionResult := range result.ConditionResults {
|
|
var prefix string
|
|
if conditionResult.Success {
|
|
prefix = ":white_check_mark:"
|
|
} else {
|
|
prefix = ":x:"
|
|
}
|
|
results += fmt.Sprintf("%s - `%s`\\n", prefix, conditionResult.Condition)
|
|
}
|
|
var description string
|
|
if alertDescription := alert.GetDescription(); len(alertDescription) > 0 {
|
|
description = ":\\n> " + alertDescription
|
|
}
|
|
return fmt.Sprintf(`{
|
|
"content": "",
|
|
"embeds": [
|
|
{
|
|
"title": ":helmet_with_white_cross: Gatus",
|
|
"description": "%s%s",
|
|
"color": %d,
|
|
"fields": [
|
|
{
|
|
"name": "Condition results",
|
|
"value": "%s",
|
|
"inline": false
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}`, message, description, colorCode, results)
|
|
}
|
|
|
|
// getWebhookURLForGroup returns the appropriate Webhook URL integration to for a given group
|
|
func (provider *AlertProvider) getWebhookURLForGroup(group string) string {
|
|
if provider.Overrides != nil {
|
|
for _, override := range provider.Overrides {
|
|
if group == override.Group {
|
|
return override.WebhookURL
|
|
}
|
|
}
|
|
}
|
|
return provider.WebhookURL
|
|
}
|
|
|
|
// GetDefaultAlert returns the provider's default alert configuration
|
|
func (provider AlertProvider) GetDefaultAlert() *alert.Alert {
|
|
return provider.DefaultAlert
|
|
}
|