diff --git a/main.go b/main.go index 97249e2..7dcfbe5 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "errors" "flag" "fmt" + "strings" "time" "git.iamthefij.com/iamthefij/slog" @@ -91,9 +92,38 @@ func checkMonitors(config *Config) error { return nil } +func sendFirstRunAlerts(config *Config, alertNames []string) error { + for _, alertName := range alertNames { + var err error + + alert, ok := config.Alerts[alertName] + if !ok { + err = fmt.Errorf("unknown alert %s: %w", alertName, errUnknownAlert) + } + + if err == nil { + _, err = alert.Send(AlertNotice{ + AlertCount: 0, + FailureCount: 0, + IsUp: true, + LastSuccess: time.Now(), + MonitorName: fmt.Sprintf("First Run Alert Test: %s", alert.Name), + LastCheckOutput: "", + }) + } + + if err != nil { + return err + } + } + + return nil +} + func main() { showVersion := flag.Bool("version", false, "Display the version of minitor and exit") configPath := flag.String("config", "config.yml", "Alternate configuration path (default: config.yml)") + firstRunAlerts := flag.String("first-run-alerts", "", "List of alerts to run on startup. This can help determine unhealthy alerts early on. (default \"\")") flag.BoolVar(&slog.DebugLevel, "debug", false, "Enables debug logs (default: false)") flag.BoolVar(&ExportMetrics, "metrics", false, "Enables prometheus metrics exporting (default: false)") @@ -119,6 +149,14 @@ func main() { go ServeMetrics() } + if *firstRunAlerts != "" { + alertNames := strings.Split(*firstRunAlerts, ",") + + err = sendFirstRunAlerts(&config, alertNames) + + slog.OnErrPanicf(err, "Error running first run alerts") + } + // Start main loop for { err = checkMonitors(&config) diff --git a/main_test.go b/main_test.go index 9bc11d7..54504ee 100644 --- a/main_test.go +++ b/main_test.go @@ -134,3 +134,64 @@ func TestCheckMonitors(t *testing.T) { } } } + +func TestFirstRunAlerts(t *testing.T) { + cases := []struct { + config Config + expectErr bool + firstRunAlerts []string + name string + }{ + { + config: Config{}, + expectErr: false, + firstRunAlerts: []string{}, + name: "Empty", + }, + { + config: Config{}, + expectErr: true, + firstRunAlerts: []string{"missing"}, + name: "Unknown", + }, + { + config: Config{ + Alerts: map[string]*Alert{ + "good": { + Command: CommandOrShell{Command: []string{"true"}}, + }, + }, + }, + expectErr: false, + firstRunAlerts: []string{"good"}, + name: "Successful alert", + }, + { + config: Config{ + Alerts: map[string]*Alert{ + "bad": { + Name: "bad", + Command: CommandOrShell{Command: []string{"false"}}, + }, + }, + }, + expectErr: true, + firstRunAlerts: []string{"bad"}, + name: "Failed alert", + }, + } + + for _, c := range cases { + err := c.config.Init() + if err != nil { + t.Errorf("sendFirstRunAlerts(%s): unexpected error reading config: %v", c.name, err) + } + + err = sendFirstRunAlerts(&c.config, c.firstRunAlerts) + if err == nil && c.expectErr { + t.Errorf("sendFirstRunAlerts(%s): Expected error, the code did not error", c.name) + } else if err != nil && !c.expectErr { + t.Errorf("sendFirstRunAlerts(%s): Did not expect an error, but we got one anyway: %v", c.name, err) + } + } +}