Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d87c3d036 | ||
|
|
deec04bf0d | ||
|
|
958446050f | ||
|
|
88e94642d9 | ||
|
|
bc83a51907 | ||
|
|
08b8932331 | ||
|
|
9072d97bb8 | ||
|
|
cdd8a69669 | ||
|
|
3c14a02770 | ||
|
|
328ea83c25 | ||
|
|
ce986e8d1d | ||
|
|
31a4b484bf | ||
|
|
444d060736 |
+2
-2
@@ -4,7 +4,7 @@ name: test
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: test
|
- name: test
|
||||||
image: golang:1.15
|
image: golang:1.17
|
||||||
environment:
|
environment:
|
||||||
VERSION: ${DRONE_TAG:-${DRONE_COMMIT}}
|
VERSION: ${DRONE_TAG:-${DRONE_COMMIT}}
|
||||||
commands:
|
commands:
|
||||||
@@ -30,7 +30,7 @@ trigger:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: build all binaries
|
- name: build all binaries
|
||||||
image: golang:1.15
|
image: golang:1.17
|
||||||
environment:
|
environment:
|
||||||
VERSION: ${DRONE_TAG:-${DRONE_COMMIT}}
|
VERSION: ${DRONE_TAG:-${DRONE_COMMIT}}
|
||||||
commands:
|
commands:
|
||||||
|
|||||||
+13
-25
@@ -1,32 +1,22 @@
|
|||||||
---
|
---
|
||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
- asciicheck
|
- errname
|
||||||
- bodyclose
|
- errorlint
|
||||||
- dogsled
|
|
||||||
- dupl
|
|
||||||
- exhaustive
|
- exhaustive
|
||||||
- gochecknoinits
|
|
||||||
- gocognit
|
|
||||||
- gocritic
|
|
||||||
- gocyclo
|
|
||||||
- goerr113
|
|
||||||
- gofumpt
|
- gofumpt
|
||||||
- goimports
|
- goimports
|
||||||
- gomnd
|
- gomnd
|
||||||
- goprintffuncname
|
- goprintffuncname
|
||||||
# - gosec
|
|
||||||
# - ifshort
|
|
||||||
- interfacer
|
|
||||||
- maligned
|
|
||||||
- misspell
|
- misspell
|
||||||
- nakedret
|
- tagliatelle
|
||||||
- nestif
|
- tenv
|
||||||
- nlreturn
|
- testpackage
|
||||||
- noctx
|
- thelper
|
||||||
- unparam
|
- tparallel
|
||||||
|
- unconvert
|
||||||
|
- wrapcheck
|
||||||
- wsl
|
- wsl
|
||||||
# - errorlint
|
|
||||||
disable:
|
disable:
|
||||||
- gochecknoglobals
|
- gochecknoglobals
|
||||||
|
|
||||||
@@ -34,15 +24,13 @@ linters-settings:
|
|||||||
gosec:
|
gosec:
|
||||||
excludes:
|
excludes:
|
||||||
- G204
|
- G204
|
||||||
# gomnd:
|
tagliatelle:
|
||||||
# settings:
|
case:
|
||||||
# mnd:
|
rules:
|
||||||
# ignored-functions: math.*
|
yaml: snake
|
||||||
|
|
||||||
issues:
|
issues:
|
||||||
exclude-rules:
|
exclude-rules:
|
||||||
- path: _test\.go
|
- path: _test\.go
|
||||||
linters:
|
linters:
|
||||||
- errcheck
|
|
||||||
- gosec
|
- gosec
|
||||||
- maligned
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v3.4.0
|
rev: v4.4.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-added-large-files
|
- id: check-added-large-files
|
||||||
- id: check-yaml
|
- id: check-yaml
|
||||||
@@ -10,13 +10,11 @@ repos:
|
|||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: check-merge-conflict
|
- id: check-merge-conflict
|
||||||
- repo: git://github.com/dnephin/pre-commit-golang
|
- repo: https://github.com/golangci/golangci-lint
|
||||||
rev: v0.4.0
|
rev: v1.50.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: go-fmt
|
|
||||||
- id: go-imports
|
|
||||||
- id: golangci-lint
|
- id: golangci-lint
|
||||||
- repo: https://github.com/hadolint/hadolint
|
- repo: https://github.com/hadolint/hadolint
|
||||||
rev: v2.4.0
|
rev: v2.12.1-beta
|
||||||
hooks:
|
hooks:
|
||||||
- id: hadolint
|
- id: hadolint
|
||||||
|
|||||||
+2
-6
@@ -1,15 +1,11 @@
|
|||||||
ARG REPO=library
|
ARG REPO=library
|
||||||
FROM multiarch/qemu-user-static:4.2.0-2 as qemu-user-static
|
FROM ${REPO}/alpine:3.12
|
||||||
FROM ${REPO}/alpine:3.10
|
|
||||||
|
|
||||||
# Copying all qemu files because amd64 doesn't exist and cannot condional copy
|
|
||||||
COPY --from=qemu-user-static /usr/bin/qemu-* /usr/bin/
|
|
||||||
|
|
||||||
RUN mkdir /app
|
RUN mkdir /app
|
||||||
WORKDIR /app/
|
WORKDIR /app/
|
||||||
|
|
||||||
# Add common checking tools
|
# Add common checking tools
|
||||||
RUN apk --no-cache add bash=~5.0 curl=~7.66 jq=~1.6
|
RUN apk --no-cache add bash=~5.0 curl=~7.79 jq=~1.6
|
||||||
|
|
||||||
# Add minitor user for running as non-root
|
# Add minitor user for running as non-root
|
||||||
RUN addgroup -S minitor && adduser -S minitor -G minitor
|
RUN addgroup -S minitor && adduser -S minitor -G minitor
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
ARG REPO=library
|
ARG REPO=library
|
||||||
FROM golang:1.12-alpine AS builder
|
FROM golang:1.17 AS builder
|
||||||
|
|
||||||
RUN apk add --no-cache git=~2
|
|
||||||
|
|
||||||
RUN mkdir /app
|
RUN mkdir /app
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
@@ -16,7 +14,7 @@ ARG VERSION=dev
|
|||||||
ENV CGO_ENABLED=0 GOOS=linux GOARCH=${ARCH}
|
ENV CGO_ENABLED=0 GOOS=linux GOARCH=${ARCH}
|
||||||
RUN go build -ldflags "-X main.version=${VERSION}" -a -installsuffix nocgo -o minitor .
|
RUN go build -ldflags "-X main.version=${VERSION}" -a -installsuffix nocgo -o minitor .
|
||||||
|
|
||||||
FROM ${REPO}/alpine:3.10
|
FROM ${REPO}/alpine:3.12
|
||||||
RUN mkdir /app
|
RUN mkdir /app
|
||||||
WORKDIR /app/
|
WORKDIR /app/
|
||||||
|
|
||||||
@@ -24,7 +22,7 @@ WORKDIR /app/
|
|||||||
COPY --from=builder /app/minitor .
|
COPY --from=builder /app/minitor .
|
||||||
|
|
||||||
# Add common checking tools
|
# Add common checking tools
|
||||||
RUN apk --no-cache add bash=~5.0 curl=~7.66 jq=~1.6
|
RUN apk --no-cache add bash=~5.0 curl=~7.79 jq=~1.6
|
||||||
|
|
||||||
# Add minitor user for running as non-root
|
# Add minitor user for running as non-root
|
||||||
RUN addgroup -S minitor && adduser -S minitor -G minitor
|
RUN addgroup -S minitor && adduser -S minitor -G minitor
|
||||||
|
|||||||
@@ -55,6 +55,9 @@ The global configurations are:
|
|||||||
|key|value|
|
|key|value|
|
||||||
|---|---|
|
|---|---|
|
||||||
|`check_interval`|Maximum frequency to run checks for each monitor as duration, eg. 1m2s.|
|
|`check_interval`|Maximum frequency to run checks for each monitor as duration, eg. 1m2s.|
|
||||||
|
|`default_alert_after`|A default value used as an `alert_after` value for a monitor if not specified or 0.|
|
||||||
|
|`default_alert_down`|Default down alerts to used by a monitor in case none are provided.|
|
||||||
|
|`default_alert_up`|Default up alerts to used by a monitor in case none are provided.|
|
||||||
|`monitors`|List of all monitors. Detailed description below|
|
|`monitors`|List of all monitors. Detailed description below|
|
||||||
|`alerts`|List of all alerts. Detailed description below|
|
|`alerts`|List of all alerts. Detailed description below|
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ var errInvalidConfig = errors.New("Invalid configuration")
|
|||||||
// Config type is contains all provided user configuration
|
// Config type is contains all provided user configuration
|
||||||
type Config struct {
|
type Config struct {
|
||||||
CheckInterval SecondsOrDuration `yaml:"check_interval"`
|
CheckInterval SecondsOrDuration `yaml:"check_interval"`
|
||||||
|
DefaultAlertAfter int16 `yaml:"default_alert_after"`
|
||||||
|
DefaultAlertEvery *int16 `yaml:"default_alert_every"`
|
||||||
|
DefaultAlertDown []string `yaml:"default_alert_down"`
|
||||||
|
DefaultAlertUp []string `yaml:"default_alert_up"`
|
||||||
Monitors []*Monitor
|
Monitors []*Monitor
|
||||||
Alerts map[string]*Alert
|
Alerts map[string]*Alert
|
||||||
}
|
}
|
||||||
@@ -135,8 +139,27 @@ func (config Config) IsValid() (isValid bool) {
|
|||||||
|
|
||||||
// Init performs extra initialization on top of loading the config from file
|
// Init performs extra initialization on top of loading the config from file
|
||||||
func (config *Config) Init() (err error) {
|
func (config *Config) Init() (err error) {
|
||||||
|
for _, monitor := range config.Monitors {
|
||||||
|
if monitor.AlertAfter == 0 && config.DefaultAlertAfter > 0 {
|
||||||
|
monitor.AlertAfter = config.DefaultAlertAfter
|
||||||
|
}
|
||||||
|
|
||||||
|
if monitor.AlertEvery == nil && config.DefaultAlertEvery != nil {
|
||||||
|
monitor.AlertEvery = config.DefaultAlertEvery
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(monitor.AlertDown) == 0 && len(config.DefaultAlertDown) > 0 {
|
||||||
|
monitor.AlertDown = config.DefaultAlertDown
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(monitor.AlertUp) == 0 && len(config.DefaultAlertUp) > 0 {
|
||||||
|
monitor.AlertUp = config.DefaultAlertUp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for name, alert := range config.Alerts {
|
for name, alert := range config.Alerts {
|
||||||
alert.Name = name
|
alert.Name = name
|
||||||
|
|
||||||
if err = alert.BuildTemplates(); err != nil {
|
if err = alert.BuildTemplates(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ func TestLoadConfig(t *testing.T) {
|
|||||||
pyCompat bool
|
pyCompat bool
|
||||||
}{
|
}{
|
||||||
{"./test/valid-config.yml", false, "Valid config file", false},
|
{"./test/valid-config.yml", false, "Valid config file", false},
|
||||||
|
{"./test/valid-config-default-values.yml", false, "Valid config file with default values", false},
|
||||||
{"./test/valid-default-log-alert.yml", false, "Valid config file with default log alert PyCompat", true},
|
{"./test/valid-default-log-alert.yml", false, "Valid config file with default log alert PyCompat", true},
|
||||||
{"./test/valid-default-log-alert.yml", true, "Invalid config file no log alert", false},
|
{"./test/valid-default-log-alert.yml", true, "Invalid config file no log alert", false},
|
||||||
{"./test/does-not-exist", true, "Invalid config path", false},
|
{"./test/does-not-exist", true, "Invalid config path", false},
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ func sendAlerts(config *Config, monitor *Monitor, alertNotice *AlertNotice) erro
|
|||||||
"Received alert, but no alert mechanisms exist. MonitorName=%s IsUp=%t",
|
"Received alert, but no alert mechanisms exist. MonitorName=%s IsUp=%t",
|
||||||
alertNotice.MonitorName, alertNotice.IsUp,
|
alertNotice.MonitorName, alertNotice.IsUp,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, alertName := range alertNames {
|
for _, alertName := range alertNames {
|
||||||
@@ -66,10 +68,10 @@ func sendAlerts(config *Config, monitor *Monitor, alertNotice *AlertNotice) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
func checkMonitors(config *Config) error {
|
func checkMonitors(config *Config) error {
|
||||||
|
// TODO: Run this in goroutines and capture exceptions
|
||||||
for _, monitor := range config.Monitors {
|
for _, monitor := range config.Monitors {
|
||||||
if monitor.ShouldCheck() {
|
if monitor.ShouldCheck() {
|
||||||
success, alertNotice := monitor.Check()
|
success, alertNotice := monitor.Check()
|
||||||
|
|
||||||
hasAlert := alertNotice != nil
|
hasAlert := alertNotice != nil
|
||||||
|
|
||||||
// Track status metrics
|
// Track status metrics
|
||||||
@@ -77,7 +79,11 @@ func checkMonitors(config *Config) error {
|
|||||||
Metrics.CountCheck(monitor.Name, success, monitor.LastCheckMilliseconds(), hasAlert)
|
Metrics.CountCheck(monitor.Name, success, monitor.LastCheckMilliseconds(), hasAlert)
|
||||||
|
|
||||||
if alertNotice != nil {
|
if alertNotice != nil {
|
||||||
return sendAlerts(config, monitor, alertNotice)
|
err := sendAlerts(config, monitor, alertNotice)
|
||||||
|
// If there was an error in sending an alert, exit early and bubble it up
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,7 +98,7 @@ func main() {
|
|||||||
flag.BoolVar(&slog.DebugLevel, "debug", false, "Enables debug logs (default: false)")
|
flag.BoolVar(&slog.DebugLevel, "debug", false, "Enables debug logs (default: false)")
|
||||||
flag.BoolVar(&ExportMetrics, "metrics", false, "Enables prometheus metrics exporting (default: false)")
|
flag.BoolVar(&ExportMetrics, "metrics", false, "Enables prometheus metrics exporting (default: false)")
|
||||||
flag.BoolVar(&PyCompat, "py-compat", false, "Enables support for legacy Python Minitor config. Will eventually be removed. (default: false)")
|
flag.BoolVar(&PyCompat, "py-compat", false, "Enables support for legacy Python Minitor config. Will eventually be removed. (default: false)")
|
||||||
flag.IntVar(&MetricsPort, "metrics-port", 8080, "The port that Prometheus metrics should be exported on, if enabled. (default: 8080)")
|
flag.IntVar(&MetricsPort, "metrics-port", MetricsPort, "The port that Prometheus metrics should be exported on, if enabled. (default: 8080)")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
// Print version if flag is provided
|
// Print version if flag is provided
|
||||||
@@ -116,9 +122,7 @@ func main() {
|
|||||||
// Start main loop
|
// Start main loop
|
||||||
for {
|
for {
|
||||||
err = checkMonitors(&config)
|
err = checkMonitors(&config)
|
||||||
if err != nil {
|
slog.OnErrPanicf(err, "Error checking monitors")
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(config.CheckInterval.Value())
|
time.Sleep(config.CheckInterval.Value())
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-9
@@ -16,7 +16,7 @@ func TestCheckMonitors(t *testing.T) {
|
|||||||
{
|
{
|
||||||
config: Config{
|
config: Config{
|
||||||
Monitors: []*Monitor{
|
Monitors: []*Monitor{
|
||||||
&Monitor{
|
{
|
||||||
Name: "Success",
|
Name: "Success",
|
||||||
Command: CommandOrShell{Command: []string{"true"}},
|
Command: CommandOrShell{Command: []string{"true"}},
|
||||||
},
|
},
|
||||||
@@ -28,7 +28,7 @@ func TestCheckMonitors(t *testing.T) {
|
|||||||
{
|
{
|
||||||
config: Config{
|
config: Config{
|
||||||
Monitors: []*Monitor{
|
Monitors: []*Monitor{
|
||||||
&Monitor{
|
{
|
||||||
Name: "Failure",
|
Name: "Failure",
|
||||||
Command: CommandOrShell{Command: []string{"false"}},
|
Command: CommandOrShell{Command: []string{"false"}},
|
||||||
AlertAfter: 1,
|
AlertAfter: 1,
|
||||||
@@ -41,7 +41,7 @@ func TestCheckMonitors(t *testing.T) {
|
|||||||
{
|
{
|
||||||
config: Config{
|
config: Config{
|
||||||
Monitors: []*Monitor{
|
Monitors: []*Monitor{
|
||||||
&Monitor{
|
{
|
||||||
Name: "Success",
|
Name: "Success",
|
||||||
Command: CommandOrShell{Command: []string{"ls"}},
|
Command: CommandOrShell{Command: []string{"ls"}},
|
||||||
alertCount: 1,
|
alertCount: 1,
|
||||||
@@ -54,7 +54,7 @@ func TestCheckMonitors(t *testing.T) {
|
|||||||
{
|
{
|
||||||
config: Config{
|
config: Config{
|
||||||
Monitors: []*Monitor{
|
Monitors: []*Monitor{
|
||||||
&Monitor{
|
{
|
||||||
Name: "Failure",
|
Name: "Failure",
|
||||||
Command: CommandOrShell{Command: []string{"false"}},
|
Command: CommandOrShell{Command: []string{"false"}},
|
||||||
AlertDown: []string{"unknown"},
|
AlertDown: []string{"unknown"},
|
||||||
@@ -68,7 +68,7 @@ func TestCheckMonitors(t *testing.T) {
|
|||||||
{
|
{
|
||||||
config: Config{
|
config: Config{
|
||||||
Monitors: []*Monitor{
|
Monitors: []*Monitor{
|
||||||
&Monitor{
|
{
|
||||||
Name: "Success",
|
Name: "Success",
|
||||||
Command: CommandOrShell{Command: []string{"true"}},
|
Command: CommandOrShell{Command: []string{"true"}},
|
||||||
AlertUp: []string{"unknown"},
|
AlertUp: []string{"unknown"},
|
||||||
@@ -82,7 +82,7 @@ func TestCheckMonitors(t *testing.T) {
|
|||||||
{
|
{
|
||||||
config: Config{
|
config: Config{
|
||||||
Monitors: []*Monitor{
|
Monitors: []*Monitor{
|
||||||
&Monitor{
|
{
|
||||||
Name: "Failure",
|
Name: "Failure",
|
||||||
Command: CommandOrShell{Command: []string{"false"}},
|
Command: CommandOrShell{Command: []string{"false"}},
|
||||||
AlertDown: []string{"good"},
|
AlertDown: []string{"good"},
|
||||||
@@ -90,7 +90,7 @@ func TestCheckMonitors(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Alerts: map[string]*Alert{
|
Alerts: map[string]*Alert{
|
||||||
"good": &Alert{
|
"good": {
|
||||||
Command: CommandOrShell{Command: []string{"true"}},
|
Command: CommandOrShell{Command: []string{"true"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -101,7 +101,7 @@ func TestCheckMonitors(t *testing.T) {
|
|||||||
{
|
{
|
||||||
config: Config{
|
config: Config{
|
||||||
Monitors: []*Monitor{
|
Monitors: []*Monitor{
|
||||||
&Monitor{
|
{
|
||||||
Name: "Failure",
|
Name: "Failure",
|
||||||
Command: CommandOrShell{Command: []string{"false"}},
|
Command: CommandOrShell{Command: []string{"false"}},
|
||||||
AlertDown: []string{"bad"},
|
AlertDown: []string{"bad"},
|
||||||
@@ -109,7 +109,7 @@ func TestCheckMonitors(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Alerts: map[string]*Alert{
|
Alerts: map[string]*Alert{
|
||||||
"bad": &Alert{
|
"bad": {
|
||||||
Name: "bad",
|
Name: "bad",
|
||||||
Command: CommandOrShell{Command: []string{"false"}},
|
Command: CommandOrShell{Command: []string{"false"}},
|
||||||
},
|
},
|
||||||
|
|||||||
+7
-7
@@ -12,7 +12,7 @@ import (
|
|||||||
type Monitor struct { //nolint:maligned
|
type Monitor struct { //nolint:maligned
|
||||||
// Config values
|
// Config values
|
||||||
AlertAfter int16 `yaml:"alert_after"`
|
AlertAfter int16 `yaml:"alert_after"`
|
||||||
AlertEvery int16 `yaml:"alert_every"`
|
AlertEvery *int16 `yaml:"alert_every"`
|
||||||
CheckInterval SecondsOrDuration `yaml:"check_interval"`
|
CheckInterval SecondsOrDuration `yaml:"check_interval"`
|
||||||
Name string
|
Name string
|
||||||
AlertDown []string `yaml:"alert_down"`
|
AlertDown []string `yaml:"alert_down"`
|
||||||
@@ -129,16 +129,16 @@ func (monitor *Monitor) failure() (notice *AlertNotice) {
|
|||||||
|
|
||||||
// Use alert cadence to determine if we should alert
|
// Use alert cadence to determine if we should alert
|
||||||
switch {
|
switch {
|
||||||
case monitor.AlertEvery > 0:
|
case monitor.AlertEvery == nil, *monitor.AlertEvery == 0:
|
||||||
// Handle integer number of failures before alerting
|
|
||||||
if failureCount%monitor.AlertEvery == 0 {
|
|
||||||
notice = monitor.createAlertNotice(false)
|
|
||||||
}
|
|
||||||
case monitor.AlertEvery == 0:
|
|
||||||
// Handle alerting on first failure only
|
// Handle alerting on first failure only
|
||||||
if failureCount == 0 {
|
if failureCount == 0 {
|
||||||
notice = monitor.createAlertNotice(false)
|
notice = monitor.createAlertNotice(false)
|
||||||
}
|
}
|
||||||
|
case *monitor.AlertEvery > 0:
|
||||||
|
// Handle integer number of failures before alerting
|
||||||
|
if failureCount%*monitor.AlertEvery == 0 {
|
||||||
|
notice = monitor.createAlertNotice(false)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
// Handle negative numbers indicating an exponential backoff
|
// Handle negative numbers indicating an exponential backoff
|
||||||
if failureCount >= int16(math.Pow(2, float64(monitor.alertCount))-1) { //nolint:gomnd
|
if failureCount >= int16(math.Pow(2, float64(monitor.alertCount))-1) { //nolint:gomnd
|
||||||
|
|||||||
+26
-17
@@ -141,17 +141,19 @@ func TestMonitorSuccess(t *testing.T) {
|
|||||||
// TestMonitorFailureAlertAfter tests that alerts will not trigger until
|
// TestMonitorFailureAlertAfter tests that alerts will not trigger until
|
||||||
// hitting the threshold provided by AlertAfter
|
// hitting the threshold provided by AlertAfter
|
||||||
func TestMonitorFailureAlertAfter(t *testing.T) {
|
func TestMonitorFailureAlertAfter(t *testing.T) {
|
||||||
|
var alertEvery int16 = 1
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
monitor Monitor
|
monitor Monitor
|
||||||
expectNotice bool
|
expectNotice bool
|
||||||
name string
|
name string
|
||||||
}{
|
}{
|
||||||
{Monitor{AlertAfter: 1}, true, "Empty"}, // Defaults to true because and AlertEvery default to 0
|
{Monitor{AlertAfter: 1}, true, "Empty"}, // Defaults to true because and AlertEvery default to 0
|
||||||
{Monitor{failureCount: 0, AlertAfter: 1, AlertEvery: 1}, true, "Alert after 1: first failure"},
|
{Monitor{failureCount: 0, AlertAfter: 1, AlertEvery: &alertEvery}, true, "Alert after 1: first failure"},
|
||||||
{Monitor{failureCount: 1, AlertAfter: 1, AlertEvery: 1}, true, "Alert after 1: second failure"},
|
{Monitor{failureCount: 1, AlertAfter: 1, AlertEvery: &alertEvery}, true, "Alert after 1: second failure"},
|
||||||
{Monitor{failureCount: 0, AlertAfter: 20, AlertEvery: 1}, false, "Alert after 20: first failure"},
|
{Monitor{failureCount: 0, AlertAfter: 20, AlertEvery: &alertEvery}, false, "Alert after 20: first failure"},
|
||||||
{Monitor{failureCount: 19, AlertAfter: 20, AlertEvery: 1}, true, "Alert after 20: 20th failure"},
|
{Monitor{failureCount: 19, AlertAfter: 20, AlertEvery: &alertEvery}, true, "Alert after 20: 20th failure"},
|
||||||
{Monitor{failureCount: 20, AlertAfter: 20, AlertEvery: 1}, true, "Alert after 20: 21st failure"},
|
{Monitor{failureCount: 20, AlertAfter: 20, AlertEvery: &alertEvery}, true, "Alert after 20: 21st failure"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
@@ -172,6 +174,11 @@ func TestMonitorFailureAlertAfter(t *testing.T) {
|
|||||||
// TestMonitorFailureAlertEvery tests that alerts will trigger
|
// TestMonitorFailureAlertEvery tests that alerts will trigger
|
||||||
// on the expected intervals
|
// on the expected intervals
|
||||||
func TestMonitorFailureAlertEvery(t *testing.T) {
|
func TestMonitorFailureAlertEvery(t *testing.T) {
|
||||||
|
var alertEvery0, alertEvery1, alertEvery2 int16
|
||||||
|
alertEvery0 = 0
|
||||||
|
alertEvery1 = 1
|
||||||
|
alertEvery2 = 2
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
monitor Monitor
|
monitor Monitor
|
||||||
expectNotice bool
|
expectNotice bool
|
||||||
@@ -186,20 +193,20 @@ func TestMonitorFailureAlertEvery(t *testing.T) {
|
|||||||
|
|
||||||
For usabilty, this should be consistent. Consistent with what though? minitor-py? Or itself? Dun dun duuuunnnnn!
|
For usabilty, this should be consistent. Consistent with what though? minitor-py? Or itself? Dun dun duuuunnnnn!
|
||||||
*/
|
*/
|
||||||
{Monitor{AlertAfter: 1}, true, "Empty"}, // Defaults to true because AlertAfter and AlertEvery default to 0
|
{Monitor{AlertAfter: 1}, true, "Empty"}, // Defaults to true because AlertAfter and AlertEvery default to nil
|
||||||
// Alert first time only, after 1
|
// Alert first time only, after 1
|
||||||
{Monitor{failureCount: 0, AlertAfter: 1, AlertEvery: 0}, true, "Alert first time only after 1: first failure"},
|
{Monitor{failureCount: 0, AlertAfter: 1, AlertEvery: &alertEvery0}, true, "Alert first time only after 1: first failure"},
|
||||||
{Monitor{failureCount: 1, AlertAfter: 1, AlertEvery: 0}, false, "Alert first time only after 1: second failure"},
|
{Monitor{failureCount: 1, AlertAfter: 1, AlertEvery: &alertEvery0}, false, "Alert first time only after 1: second failure"},
|
||||||
{Monitor{failureCount: 2, AlertAfter: 1, AlertEvery: 0}, false, "Alert first time only after 1: third failure"},
|
{Monitor{failureCount: 2, AlertAfter: 1, AlertEvery: &alertEvery0}, false, "Alert first time only after 1: third failure"},
|
||||||
// Alert every time, after 1
|
// Alert every time, after 1
|
||||||
{Monitor{failureCount: 0, AlertAfter: 1, AlertEvery: 1}, true, "Alert every time after 1: first failure"},
|
{Monitor{failureCount: 0, AlertAfter: 1, AlertEvery: &alertEvery1}, true, "Alert every time after 1: first failure"},
|
||||||
{Monitor{failureCount: 1, AlertAfter: 1, AlertEvery: 1}, true, "Alert every time after 1: second failure"},
|
{Monitor{failureCount: 1, AlertAfter: 1, AlertEvery: &alertEvery1}, true, "Alert every time after 1: second failure"},
|
||||||
{Monitor{failureCount: 1, AlertAfter: 1, AlertEvery: 1}, true, "Alert every time after 1: third failure"},
|
{Monitor{failureCount: 2, AlertAfter: 1, AlertEvery: &alertEvery1}, true, "Alert every time after 1: third failure"},
|
||||||
// Alert every other time, after 1
|
// Alert every other time, after 1
|
||||||
{Monitor{failureCount: 0, AlertAfter: 1, AlertEvery: 2}, true, "Alert every other time after 1: first failure"},
|
{Monitor{failureCount: 0, AlertAfter: 1, AlertEvery: &alertEvery2}, true, "Alert every other time after 1: first failure"},
|
||||||
{Monitor{failureCount: 1, AlertAfter: 1, AlertEvery: 2}, false, "Alert every other time after 1: second failure"},
|
{Monitor{failureCount: 1, AlertAfter: 1, AlertEvery: &alertEvery2}, false, "Alert every other time after 1: second failure"},
|
||||||
{Monitor{failureCount: 2, AlertAfter: 1, AlertEvery: 2}, true, "Alert every other time after 1: third failure"},
|
{Monitor{failureCount: 2, AlertAfter: 1, AlertEvery: &alertEvery2}, true, "Alert every other time after 1: third failure"},
|
||||||
{Monitor{failureCount: 3, AlertAfter: 1, AlertEvery: 2}, false, "Alert every other time after 1: fourth failure"},
|
{Monitor{failureCount: 3, AlertAfter: 1, AlertEvery: &alertEvery2}, false, "Alert every other time after 1: fourth failure"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
@@ -220,6 +227,8 @@ func TestMonitorFailureAlertEvery(t *testing.T) {
|
|||||||
// TestMonitorFailureExponential tests that alerts will trigger
|
// TestMonitorFailureExponential tests that alerts will trigger
|
||||||
// with an exponential backoff after repeated failures
|
// with an exponential backoff after repeated failures
|
||||||
func TestMonitorFailureExponential(t *testing.T) {
|
func TestMonitorFailureExponential(t *testing.T) {
|
||||||
|
var alertEveryExp int16 = -1
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
expectNotice bool
|
expectNotice bool
|
||||||
name string
|
name string
|
||||||
@@ -236,7 +245,7 @@ func TestMonitorFailureExponential(t *testing.T) {
|
|||||||
|
|
||||||
// Unlike previous tests, this one requires a static Monitor with repeated
|
// Unlike previous tests, this one requires a static Monitor with repeated
|
||||||
// calls to the failure method
|
// calls to the failure method
|
||||||
monitor := Monitor{failureCount: 0, AlertAfter: 1, AlertEvery: -1}
|
monitor := Monitor{failureCount: 0, AlertAfter: 1, AlertEvery: &alertEveryExp}
|
||||||
|
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
log.Printf("Testing case %s", c.name)
|
log.Printf("Testing case %s", c.name)
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
check_interval: 1
|
||||||
|
default_alert_down: ["log_command"]
|
||||||
|
default_alert_after: 1
|
||||||
|
|
||||||
|
monitors:
|
||||||
|
- name: Command
|
||||||
|
command: ["echo", "$PATH"]
|
||||||
|
|
||||||
|
alerts:
|
||||||
|
log_command:
|
||||||
|
command: ["echo", "regular", '"command!!!"', "{{.MonitorName}}"]
|
||||||
Reference in New Issue
Block a user