From db7c516819932b834a2076c9f8ab1667d342a400 Mon Sep 17 00:00:00 2001 From: Greg Holmes Date: Fri, 4 Sep 2020 22:43:14 +0100 Subject: [PATCH] Add support for Twilio alerts (#7) --- README.md | 37 +++++++++++++++++++++++++++++++++++-- core/alert.go | 1 + core/alerting.go | 8 ++++++++ watchdog/watchdog.go | 24 ++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fc201804..c2798003 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ core applications: https://status.twinnation.org/ - [FAQ](#faq) - [Sending a GraphQL request](#sending-a-graphql-request) - [Configuring Slack alerts](#configuring-slack-alerts) + - [Configuring Twilio alerts](#configuring-twilio-alerts) - [Configuring custom alert](#configuring-custom-alerts) @@ -83,12 +84,17 @@ Note that you can also add environment variables in the your configuration file | `services[].graphql` | Whether to wrap the body in a query param (`{"query":"$body"}`) | `false` | | `services[].body` | Request body | `""` | | `services[].headers` | Request headers | `{}` | -| `services[].alerts[].type` | Type of alert. Valid types: `slack`, `custom` | Required `""` | +| `services[].alerts[].type` | Type of alert. Valid types: `slack`, `twilio`, `custom` | Required `""` | | `services[].alerts[].enabled` | Whether to enable the alert | `false` | | `services[].alerts[].threshold` | Number of failures in a row needed before triggering the alert | `3` | | `services[].alerts[].description` | Description of the alert. Will be included in the alert sent | `""` | | `alerting` | Configuration for alerting | `{}` | | `alerting.slack` | Webhook to use for alerts of type `slack` | `""` | +| `alerting.twilio` | Settings for alerts of type `twilio` | `""` | +| `alerting.twilio.sid` | Twilio account SID | Required `""` | +| `alerting.twilio.token` | Twilio auth token | Required `""` | +| `alerting.twilio.from` | Number to send Twilio alerts from | Required `""` | +| `alerting.twilio.to` | Number to send twilio alerts to | Required `""` | | `alerting.custom` | Configuration for custom actions on failure or alerts | `""` | | `alerting.custom.url` | Custom alerting request url | `""` | | `alerting.custom.body` | Custom alerting request body. | `""` | @@ -198,6 +204,33 @@ services: - "[RESPONSE_TIME] < 300" ``` +### Configuring Twilio alerts + +```yaml +alerting: + twilio: + sid: **** + token: **** + from: +1-234-567-8901 + to: +1-234-567-8901 +services: + - name: twinnation + interval: 30s + url: "https://twinnation.org/health" + alerts: + - type: twilio + enabled: true + description: "healthcheck failed 3 times in a row" + - type: twilio + enabled: true + threshold: 5 + description: "healthcheck failed 5 times in a row" + conditions: + - "[STATUS] == 200" + - "[BODY].status == UP" + - "[RESPONSE_TIME] < 300" +``` + ### Configuring custom alerts @@ -235,4 +268,4 @@ services: - "[STATUS] == 200" - "[BODY].status == UP" - "[RESPONSE_TIME] < 300" -``` \ No newline at end of file +``` diff --git a/core/alert.go b/core/alert.go index 6afc5342..bc8a12db 100644 --- a/core/alert.go +++ b/core/alert.go @@ -19,5 +19,6 @@ type AlertType string const ( SlackAlert AlertType = "slack" + TwilioAlert AlertType = "twilio" CustomAlert AlertType = "custom" ) diff --git a/core/alerting.go b/core/alerting.go index e4548ff9..9cd83b6a 100644 --- a/core/alerting.go +++ b/core/alerting.go @@ -10,9 +10,17 @@ import ( type AlertingConfig struct { Slack string `yaml:"slack"` + Twilio *TwilioAlertProvider `yaml:"twilio"` Custom *CustomAlertProvider `yaml:"custom"` } +type TwilioAlertProvider struct { + SID string `yaml:"sid"` + Token string `yaml:"token"` + From string `yaml:"from"` + To string `yaml:"to"` +} + type CustomAlertProvider struct { Url string `yaml:"url"` Method string `yaml:"method,omitempty"` diff --git a/watchdog/watchdog.go b/watchdog/watchdog.go index 5ed27f23..97707575 100644 --- a/watchdog/watchdog.go +++ b/watchdog/watchdog.go @@ -1,11 +1,13 @@ package watchdog import ( + "encoding/base64" "fmt" "github.com/TwinProduction/gatus/config" "github.com/TwinProduction/gatus/core" "github.com/TwinProduction/gatus/metric" "log" + "net/url" "sync" "time" ) @@ -71,6 +73,28 @@ func monitor(service *core.Service) { } else { log.Printf("[watchdog][monitor] Not sending Slack alert despite being triggered, because there is no Slack webhook configured") } + } else if alertTriggered.Type == core.TwilioAlert { + if len(cfg.Alerting.Twilio.Token) > 0 && + len(cfg.Alerting.Twilio.SID) > 0 && + len(cfg.Alerting.Twilio.From) > 0 && + len(cfg.Alerting.Twilio.To) > 0 { + log.Printf("[watchdog][monitor] Sending Twilio alert because alert with description=%s has been triggered", alertTriggered.Description) + alertProvider = &core.CustomAlertProvider{ + Url: fmt.Sprintf("https://api.twilio.com/2010-04-01/Accounts/%s/Messages.json", cfg.Alerting.Twilio.SID), + Method: "POST", + Body: url.Values{ + "To": {cfg.Alerting.Twilio.To}, + "From": {cfg.Alerting.Twilio.From}, + "Body": {fmt.Sprintf("%s - %s", service.Name, alertTriggered.Description)}, + }.Encode(), + Headers: map[string]string{ + "Content-Type": "application/x-www-form-urlencoded", + "Authorization": fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", cfg.Alerting.Twilio.SID, cfg.Alerting.Twilio.Token)))), + }, + } + } else { + log.Printf("[watchdog][monitor] Not sending Twilio alert despite being triggered, because twilio config settings missing") + } } else if alertTriggered.Type == core.CustomAlert { if cfg.Alerting.Custom != nil && len(cfg.Alerting.Custom.Url) > 0 { log.Printf("[watchdog][monitor] Sending custom alert because alert with description=%s has been triggered", alertTriggered.Description)