Configurable logging levels (#16)
* Update screenshot to match current output * Log level is configurable * Alert name is provided in log line, where available. * Capitalise Discord, check err in integration test, and other syntax issues * Go formatting syntax fixes * Log the common alert name or group alert name, in that precedence
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 312 KiB |
@@ -10,7 +10,7 @@ This program is not a replacement to alertmanager, it accepts webhooks from aler
|
||||
|
||||
The standard "dataflow" should be:
|
||||
|
||||
```
|
||||
```text
|
||||
Prometheus -------------> alertmanager -------------------> alertmanager-discord
|
||||
|
||||
alerting: receivers:
|
||||
@@ -18,11 +18,6 @@ alerting: receivers:
|
||||
- static_configs: webhook_configs: - DISCORD_WEBHOOK=https://discordapp.com/api/we...
|
||||
- targets: - url: 'http://localhost:9094'
|
||||
- 127.0.0.1:9093
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
## Features
|
||||
@@ -44,30 +39,30 @@ alerting: receivers:
|
||||
|
||||
## Example alertmanager config
|
||||
|
||||
```
|
||||
```yaml
|
||||
global:
|
||||
# The smarthost and SMTP sender used for mail notifications.
|
||||
smtp_smarthost: 'localhost:25'
|
||||
smtp_from: 'alertmanager@example.org'
|
||||
smtp_auth_username: 'alertmanager'
|
||||
smtp_auth_password: 'password'
|
||||
smtp_smarthost: "localhost:25"
|
||||
smtp_from: "alertmanager@example.org"
|
||||
smtp_auth_username: "alertmanager"
|
||||
smtp_auth_password: "password"
|
||||
|
||||
# The directory from which notification templates are read.
|
||||
templates:
|
||||
- '/etc/alertmanager/template/*.tmpl'
|
||||
- "/etc/alertmanager/template/*.tmpl"
|
||||
|
||||
# The root route on which each incoming alert enters.
|
||||
route:
|
||||
group_by: ['alertname']
|
||||
group_by: ["alertname"]
|
||||
group_wait: 20s
|
||||
group_interval: 5m
|
||||
repeat_interval: 3h
|
||||
receiver: discord_webhook
|
||||
|
||||
receivers:
|
||||
- name: 'discord_webhook'
|
||||
- name: "discord_webhook"
|
||||
webhook_configs:
|
||||
- url: 'http://localhost:9094'
|
||||
- url: "http://localhost:9094"
|
||||
```
|
||||
|
||||
## Deployment
|
||||
@@ -88,9 +83,9 @@ discord_webhook_url: https://discord.com/api/webhooks/123456789123456789/abc
|
||||
go run . --configuration_file_path=/path/to/your/config.yaml
|
||||
```
|
||||
|
||||
### Docker
|
||||
### Docker or OCI-compatible container runtime
|
||||
|
||||
If you wish to deploy this to docker infra, you can find the docker hub repo here: https://hub.docker.com/r/speckle/alertmanager-discord/
|
||||
If you wish to deploy this to Docker, or similar OCI-compatible container runtime, you can pull the OCI image from the [Docker Hub repository](https://hub.docker.com/r/speckle/alertmanager-discord/).
|
||||
|
||||
### Kubernetes Helm Chart
|
||||
|
||||
@@ -169,4 +164,4 @@ go test ./... -v -cover -test.shuffle on
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
This repository is forked from https://github.com/benjojo/alertmanager-discord under the Apache 2.0 license
|
||||
This repository is forked from [benjojo/alertmanager-discord](https://github.com/benjojo/alertmanager-discord) under the Apache 2.0 license
|
||||
|
||||
+49
-26
@@ -5,7 +5,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
. "github.com/specklesystems/alertmanager-discord/pkg/flags"
|
||||
"github.com/specklesystems/alertmanager-discord/pkg/flags"
|
||||
"github.com/specklesystems/alertmanager-discord/pkg/server"
|
||||
"github.com/specklesystems/alertmanager-discord/pkg/version"
|
||||
|
||||
@@ -18,35 +18,30 @@ import (
|
||||
const (
|
||||
defaultConfigurationPath = "/etc/alertmanager-discord/config.yaml"
|
||||
defaultMaxBackoffTimeSeconds = 10
|
||||
defaultLogLevel = "info"
|
||||
)
|
||||
|
||||
var (
|
||||
configurationFilePath string
|
||||
webhookURL string
|
||||
listenAddress string
|
||||
logLevel string
|
||||
maximumBackoffTimeSeconds int
|
||||
)
|
||||
|
||||
func init() {
|
||||
viper.SetDefault(ConfigurationPathFlagKey, defaultConfigurationPath)
|
||||
defineConfigurationVariable(&configurationFilePath, rootCmd.Flags().StringVarP, flags.ConfigurationPathFlagKey, "c", defaultConfigurationPath, "Path to the configuration file.")
|
||||
defineConfigurationVariable(&webhookURL, rootCmd.Flags().StringVarP, flags.DiscordWebhookUrlFlagKey, "d", "", "Url to the Discord webhook API endpoint.")
|
||||
defineConfigurationVariable(&listenAddress, rootCmd.Flags().StringVarP, flags.ListenAddressFlagKey, "l", server.DefaultListenAddress, "The address (host:port) which the server will attempt to bind to and listen on.")
|
||||
defineConfigurationVariable(&logLevel, rootCmd.Flags().StringVarP, flags.LogLevelFlagKey, "", defaultLogLevel, "The minimum level of logging to be produced by the pod. Acceptable values, in ascending order, are 'trace', 'debug', 'info', 'warn', 'error', 'fatal', 'panic', or 'disabled'.")
|
||||
defineConfigurationVariable(&maximumBackoffTimeSeconds, rootCmd.Flags().IntVarP, flags.MaxBackoffTimeSecondsFlagKey, "", defaultMaxBackoffTimeSeconds, "The maximum elapsed duration (expressed as an integer number of seconds) to allow the Discord client to continue retrying to send messages to the Discord API.")
|
||||
}
|
||||
|
||||
viper.BindEnv(ConfigurationPathFlagKey, strings.ToUpper(ConfigurationPathFlagKey))
|
||||
rootCmd.Flags().StringVarP(&configurationFilePath, ConfigurationPathFlagKey, "c", defaultConfigurationPath, "Path to the configuration file.")
|
||||
viper.BindPFlag(ConfigurationPathFlagKey, rootCmd.Flags().Lookup(ConfigurationPathFlagKey))
|
||||
|
||||
viper.BindEnv(DiscordWebhookUrlFlagKey, strings.ToUpper(DiscordWebhookUrlFlagKey))
|
||||
rootCmd.Flags().StringVarP(&webhookURL, DiscordWebhookUrlFlagKey, "d", "", "Url to the Discord webhook API endpoint.")
|
||||
viper.BindPFlag(DiscordWebhookUrlFlagKey, rootCmd.Flags().Lookup(DiscordWebhookUrlFlagKey))
|
||||
|
||||
viper.SetDefault(ListenAddressFlagKey, server.DefaultListenAddress)
|
||||
viper.BindEnv(ListenAddressFlagKey, strings.ToUpper(ListenAddressFlagKey))
|
||||
rootCmd.Flags().StringVarP(&listenAddress, ListenAddressFlagKey, "l", "", "The address (host:port) which the server will attempt to bind to and listen on.")
|
||||
viper.BindPFlag(ListenAddressFlagKey, rootCmd.Flags().Lookup(ListenAddressFlagKey))
|
||||
|
||||
viper.SetDefault(MaxBackoffTimeSecondsFlagKey, defaultMaxBackoffTimeSeconds)
|
||||
viper.BindEnv(MaxBackoffTimeSecondsFlagKey, strings.ToUpper(MaxBackoffTimeSecondsFlagKey))
|
||||
rootCmd.Flags().IntVarP(&maximumBackoffTimeSeconds, MaxBackoffTimeSecondsFlagKey, "", defaultMaxBackoffTimeSeconds, "The maximum elapsed duration (expressed as an integer number of seconds) to allow the Discord client to continue retrying to send messages to the Discord API.")
|
||||
viper.BindPFlag(MaxBackoffTimeSecondsFlagKey, rootCmd.Flags().Lookup(MaxBackoffTimeSecondsFlagKey))
|
||||
func defineConfigurationVariable[K int | string](variable *K, flagParser func(*K, string, string, K, string), flagKey string, shorthand string, defaultValue K, description string) {
|
||||
viper.SetDefault(flagKey, defaultValue)
|
||||
viper.BindEnv(flagKey, strings.ToUpper(flagKey))
|
||||
flagParser(variable, flagKey, shorthand, defaultValue, description)
|
||||
viper.BindPFlag(flagKey, rootCmd.Flags().Lookup(flagKey))
|
||||
}
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
@@ -57,22 +52,27 @@ var rootCmd = &cobra.Command{
|
||||
translates the data to match Discord's message specifications,
|
||||
and forwards that to Discord's message API endpoint.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
||||
zerolog.TimeFieldFormat = time.RFC3339
|
||||
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||
|
||||
// these log messages are generated before the log level is set
|
||||
log.Debug().Msgf("Attempting to read from configuration file path: ('%s')", configurationFilePath)
|
||||
viper.SetConfigFile(configurationFilePath)
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
log.Info().Err(err).Msgf("Unable to read configuration file at path ('%s'). Attempting to parse command line arguments or environment variables, the command line argument has higher order of precedence.", configurationFilePath)
|
||||
}
|
||||
|
||||
if viper.GetString(DiscordWebhookUrlFlagKey) != "" {
|
||||
webhookURL = viper.GetString(DiscordWebhookUrlFlagKey)
|
||||
if viper.GetString(flags.DiscordWebhookUrlFlagKey) != "" {
|
||||
webhookURL = viper.GetString(flags.DiscordWebhookUrlFlagKey)
|
||||
}
|
||||
if viper.GetString(ListenAddressFlagKey) != "" {
|
||||
listenAddress = viper.GetString(ListenAddressFlagKey)
|
||||
if viper.GetString(flags.ListenAddressFlagKey) != "" {
|
||||
listenAddress = viper.GetString(flags.ListenAddressFlagKey)
|
||||
}
|
||||
if viper.GetString(MaxBackoffTimeSecondsFlagKey) != "" {
|
||||
maximumBackoffTimeSeconds = viper.GetInt(MaxBackoffTimeSecondsFlagKey)
|
||||
|
||||
setGlobalLogLevel(viper.GetString(flags.LogLevelFlagKey))
|
||||
|
||||
if viper.GetString(flags.MaxBackoffTimeSecondsFlagKey) != "" {
|
||||
maximumBackoffTimeSeconds = viper.GetInt(flags.MaxBackoffTimeSecondsFlagKey)
|
||||
}
|
||||
|
||||
amds := server.AlertManagerDiscordServer{
|
||||
@@ -100,3 +100,26 @@ func Execute() {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func setGlobalLogLevel(logLevel string) {
|
||||
switch logLevel {
|
||||
case "trace":
|
||||
zerolog.SetGlobalLevel(zerolog.TraceLevel)
|
||||
case "debug":
|
||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||||
case "info":
|
||||
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||
case "warn":
|
||||
zerolog.SetGlobalLevel(zerolog.WarnLevel)
|
||||
case "error":
|
||||
zerolog.SetGlobalLevel(zerolog.ErrorLevel)
|
||||
case "fatal":
|
||||
zerolog.SetGlobalLevel(zerolog.FatalLevel)
|
||||
case "panic":
|
||||
zerolog.SetGlobalLevel(zerolog.PanicLevel)
|
||||
case "disabled":
|
||||
zerolog.SetGlobalLevel(zerolog.Disabled)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ A Helm chart to deploy alertmanager-discord to Kubernetes
|
||||
| securityContext.readOnlyRootFilesystem | bool | `true` | |
|
||||
| securityContext.runAsNonRoot | bool | `true` | |
|
||||
| securityContext.runAsUser | int | `1000` | |
|
||||
| server.configuration.key | string | `"config.yaml"` | |
|
||||
| server.configuration.key | string | `"config.yaml"` | the key within the Kubernetes Secret. This key is expected to be a filename, as it will for the path for the configuration file when mounted to the container. |
|
||||
| server.configuration.name | string | `"discord-config"` | name of the Kubernetes Secret containing the configuration file, will be mounted to the container. Must be in the same namespace as this helm chart is deployed. |
|
||||
| service.port | int | `9094` | The port to which alertmanager should push alerts |
|
||||
| service.type | string | `"ClusterIP"` | |
|
||||
|
||||
@@ -55,6 +55,7 @@ server:
|
||||
configuration:
|
||||
# -- name of the Kubernetes Secret containing the configuration file, will be mounted to the container. Must be in the same namespace as this helm chart is deployed.
|
||||
name: discord-config
|
||||
# -- the key within the Kubernetes Secret. This key is expected to be a filename, as it will for the path for the configuration file when mounted to the container.
|
||||
key: config.yaml
|
||||
# within the config.yaml data, it should be yaml formatted with the key `discord_webhook_url`, and optionally keys `listen_address` & `max_backoff_time_seconds`. An example of the data expected can be found at ./test/test-config.yaml
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/specklesystems/alertmanager-discord/pkg/alertmanager"
|
||||
@@ -13,6 +14,7 @@ import (
|
||||
"github.com/specklesystems/alertmanager-discord/pkg/prometheus"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
@@ -24,9 +26,9 @@ type AlertForwarderHandler struct {
|
||||
af AlertForwarder
|
||||
}
|
||||
|
||||
func NewAlertForwarderHandler(client *http.Client, webhookURL string, maximumBackoffTimeSeconds time.Duration) *AlertForwarderHandler {
|
||||
func NewAlertForwarderHandler(client *http.Client, webhookURL string, maximumBackoffElapsedTime time.Duration) *AlertForwarderHandler {
|
||||
return &AlertForwarderHandler{
|
||||
af: NewAlertForwarder(client, webhookURL, maximumBackoffTimeSeconds),
|
||||
af: NewAlertForwarder(client, webhookURL, maximumBackoffElapsedTime),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,12 +40,20 @@ type AlertForwarder struct {
|
||||
client *discord.Client
|
||||
}
|
||||
|
||||
func NewAlertForwarder(client *http.Client, webhookURL string, maximumBackoffTimeSeconds time.Duration) AlertForwarder {
|
||||
func NewAlertForwarder(client *http.Client, webhookURL string, maximumBackoffElapsedTime time.Duration) AlertForwarder {
|
||||
return AlertForwarder{
|
||||
client: discord.NewClient(client, webhookURL, maximumBackoffTimeSeconds),
|
||||
client: discord.NewClient(client, webhookURL, maximumBackoffElapsedTime),
|
||||
}
|
||||
}
|
||||
|
||||
func (af *AlertForwarder) groupAlerts(amo *alertmanager.Out) map[string][]alertmanager.Alert {
|
||||
groupedAlerts := make(map[string][]alertmanager.Alert)
|
||||
for _, alert := range amo.Alerts {
|
||||
groupedAlerts[alert.Status] = append(groupedAlerts[alert.Status], alert)
|
||||
}
|
||||
return groupedAlerts
|
||||
}
|
||||
|
||||
func (af *AlertForwarder) sendWebhook(correlationId string, amo *alertmanager.Out, w http.ResponseWriter) {
|
||||
if len(amo.Alerts) < 1 {
|
||||
log.Debug().
|
||||
@@ -53,31 +63,35 @@ func (af *AlertForwarder) sendWebhook(correlationId string, amo *alertmanager.Ou
|
||||
return
|
||||
}
|
||||
|
||||
groupedAlerts := make(map[string][]alertmanager.Alert)
|
||||
for _, alert := range amo.Alerts {
|
||||
groupedAlerts[alert.Status] = append(groupedAlerts[alert.Status], alert)
|
||||
logger := zerolog.New(os.Stderr).With().
|
||||
Timestamp().
|
||||
Str(logging.FieldKeyCorrelationId, correlationId).Logger()
|
||||
if amo.CommonLabels.Alertname != "" {
|
||||
logger = logger.With().Str(logging.FieldKeyAlertName, amo.CommonLabels.Alertname).Logger()
|
||||
} else if amo.GroupLabels.Alertname != "" {
|
||||
logger = logger.With().Str(logging.FieldKeyAlertName, amo.GroupLabels.Alertname).Logger()
|
||||
}
|
||||
|
||||
failedToPublishAtLeastOne := false
|
||||
for status, alerts := range groupedAlerts {
|
||||
for status, alerts := range af.groupAlerts(amo) {
|
||||
DO := TranslateAlertManagerToDiscord(status, amo, alerts)
|
||||
|
||||
log.Info().
|
||||
logger.Info().
|
||||
Str(logging.FieldKeyEventType, logging.EventTypeRequestSending).
|
||||
Str(logging.FieldKeyCorrelationId, correlationId).
|
||||
Msg("Sending HTTP request to Discord.")
|
||||
res, err := af.client.PublishMessage(DO)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Error encountered when publishing message to discord: %w", err)
|
||||
log.Error().
|
||||
err = fmt.Errorf("failed to publish message to Discord: %w", err)
|
||||
logger.Error().
|
||||
Str(logging.FieldKeyCorrelationId, correlationId).
|
||||
Err(err).
|
||||
Msg("Error when attempting to publish message to discord.")
|
||||
Msg("Error when attempting to publish message to Discord.")
|
||||
failedToPublishAtLeastOne = true
|
||||
continue
|
||||
}
|
||||
|
||||
log.Info().
|
||||
logger.Info().
|
||||
Str(logging.FieldKeyEventType, logging.EventTypeResponseReceived).
|
||||
Str(logging.FieldKeyCorrelationId, correlationId).
|
||||
Msg("HTTP response received from Discord")
|
||||
@@ -124,7 +138,7 @@ or https://prometheus.io/docs/alerting/latest/configuration/#webhook_config`
|
||||
Msg("Sending HTTP request to Discord.")
|
||||
res, err := af.client.PublishMessage(DO)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error encountered when publishing message to discord: %w", err)
|
||||
return nil, fmt.Errorf("error encountered when publishing message to Discord: %w", err)
|
||||
}
|
||||
|
||||
log.Info().
|
||||
@@ -204,5 +218,4 @@ func (af *AlertForwarder) handleInvalidInput(correlationId string, b []byte, w h
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -17,13 +17,10 @@ func CheckWebhookURL(webhookURL string) (bool, *url.URL, error) {
|
||||
|
||||
parsedUrl, err := url.Parse(webhookURL)
|
||||
if err != nil {
|
||||
return false, &url.URL{}, fmt.Errorf("The Discord WebHook URL ('%s') cannot be parsed as a url: %w", webhookURL, err)
|
||||
return false, &url.URL{}, fmt.Errorf("the Discord WebHook URL ('%s') cannot be parsed as a url: %w", webhookURL, err)
|
||||
}
|
||||
|
||||
host, _, err := net.SplitHostPort(parsedUrl.Host)
|
||||
if err != nil {
|
||||
// return false, parsedUrl, fmt.Errorf("The Discord WebHook URL ('%s') host ('%s') cannot be separated into domain/ip and port components: %w", webhookURL, parsedUrl.Host, err)
|
||||
}
|
||||
host, _, _ := net.SplitHostPort(parsedUrl.Host)
|
||||
if host == "" {
|
||||
host = parsedUrl.Host
|
||||
}
|
||||
@@ -37,7 +34,7 @@ func CheckWebhookURL(webhookURL string) (bool, *url.URL, error) {
|
||||
|
||||
ok := re.Match([]byte(webhookURL))
|
||||
if !ok {
|
||||
return false, parsedUrl, fmt.Errorf("The Discord WebHook URL doesn't seem to be a valid Discord Webhook API url: '%s'", webhookURL)
|
||||
return false, parsedUrl, fmt.Errorf("the Discord WebHook URL doesn't seem to be a valid Discord Webhook API url: '%s'", webhookURL)
|
||||
}
|
||||
|
||||
return ok, parsedUrl, nil
|
||||
|
||||
@@ -8,17 +8,17 @@ import (
|
||||
var (
|
||||
RequestsToDiscordInFlight = promauto.NewGauge(prometheus.GaugeOpts{
|
||||
Name: "discord_client_requests_in_flight",
|
||||
Help: "The current number of http requests being sent by the discord client.",
|
||||
Help: "The current number of http requests being sent by the Discord client.",
|
||||
})
|
||||
|
||||
RequestsToDiscordTotal = promauto.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "discord_client_requests_total",
|
||||
Help: "The total number of http requests sent by the discord client.",
|
||||
Help: "The total number of http requests sent by the Discord client.",
|
||||
}, []string{"code", "method"})
|
||||
|
||||
RequestsToDiscordDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Name: "discord_client_request_duration_seconds",
|
||||
Help: "Duration of all http requests sent by the discord client.",
|
||||
Help: "Duration of all http requests sent by the Discord client.",
|
||||
Buckets: prometheus.DefBuckets,
|
||||
}, []string{"code"})
|
||||
)
|
||||
|
||||
@@ -5,4 +5,5 @@ const (
|
||||
DiscordWebhookUrlFlagKey = "discord_webhook_url"
|
||||
ListenAddressFlagKey = "listen_address"
|
||||
MaxBackoffTimeSecondsFlagKey = "max_backoff_time_seconds"
|
||||
LogLevelFlagKey = "log_level"
|
||||
)
|
||||
|
||||
@@ -6,6 +6,7 @@ const (
|
||||
FieldKeyHttpMethod = "method"
|
||||
FieldKeyHttpPath = "path"
|
||||
FieldKeyEventType = "event_type"
|
||||
FieldKeyAlertName = "alert_name"
|
||||
FieldKeyCorrelationId = "correlation_id"
|
||||
FieldKeyStatusCode = "status_code"
|
||||
)
|
||||
|
||||
@@ -22,11 +22,11 @@ const (
|
||||
)
|
||||
|
||||
func Test_Serve_HappyPath(t *testing.T) {
|
||||
// create a mock discord server to respond to our request
|
||||
// create a mock Discord server to respond to our request
|
||||
receivedRequest := make(chan bool, 1)
|
||||
mockDiscordServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Discord mock server will always return with Status Code 200 OK
|
||||
receivedRequest <- true // notify the channel that the discord server received the request
|
||||
receivedRequest <- true // notify the channel that the Discord server received the request
|
||||
}))
|
||||
defer mockDiscordServer.Close()
|
||||
|
||||
@@ -44,19 +44,23 @@ func Test_Serve_HappyPath(t *testing.T) {
|
||||
}
|
||||
|
||||
res, err := client.Get(fmt.Sprintf("http://%s/liveness", serverListenAddress))
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, res, "response to GET '/liveness' should not be nil")
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode, "GET liveness should return status code OK (200)")
|
||||
res, err = client.Get(fmt.Sprintf("http://%s/readiness", serverListenAddress))
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, res, "response to GET '/readiness' should not be nil")
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode, "GET readiness should return status code OK (200)")
|
||||
res, err = client.Get(fmt.Sprintf("http://%s/favicon.ico", serverListenAddress))
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, res, "response to GET '/favicon.ico' should not be nil")
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode, "GET favicon.ico should return status code OK (200)")
|
||||
res, err = client.Get(fmt.Sprintf("http://%s/metrics", serverListenAddress))
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, res, "response to GET '/metrics' should not be nil")
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode, "GET favicon.ico should return status code OK (200)")
|
||||
|
||||
// assert mock discord server received expected json
|
||||
// assert mock Discord server received expected json
|
||||
ao := alertmanager.Out{
|
||||
Alerts: []alertmanager.Alert{
|
||||
{
|
||||
@@ -68,6 +72,11 @@ func Test_Serve_HappyPath(t *testing.T) {
|
||||
}{
|
||||
Summary: "a_common_annotation_summary",
|
||||
},
|
||||
GroupLabels: struct {
|
||||
Alertname string `json:"alertname"`
|
||||
}{
|
||||
Alertname: "testAlertName",
|
||||
},
|
||||
}
|
||||
|
||||
aoJson, err := json.Marshal(ao)
|
||||
@@ -86,7 +95,7 @@ func Test_Serve_HappyPath(t *testing.T) {
|
||||
assert.NoError(t, err, "sending request to alertmanager-discord server.")
|
||||
assert.NotNil(t, res, "response to POST '/' should not be nil")
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode, "sending valid alertmanager data should expect http response status code")
|
||||
assert.True(t, <-receivedRequest, "Mock discord server should have received response") // will wait until the request is received
|
||||
assert.True(t, <-receivedRequest, "Mock Discord server should have received response") // will wait until the request is received
|
||||
|
||||
// TODO assert log lines were generated
|
||||
|
||||
|
||||
@@ -15,7 +15,9 @@ import (
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
const DefaultListenAddress = "0.0.0.0:9094"
|
||||
const (
|
||||
DefaultListenAddress = "0.0.0.0:9094"
|
||||
)
|
||||
const (
|
||||
FaviconPath = "/favicon.ico"
|
||||
LivenessPath = "/liveness"
|
||||
|
||||
Reference in New Issue
Block a user