diff --git a/README.md b/README.md index aac11d0..65be87d 100644 --- a/README.md +++ b/README.md @@ -149,7 +149,6 @@ For the time being, legacy configs for the Python version of Minitor should be c Future, potentially breaking changes - - [ ] Implement leveled logging (maybe glog or logrus) - [ ] Consider value of templating vs injecting values into Env variables - [ ] Async checking - [ ] Revisit metrics and see if they all make sense diff --git a/alert.go b/alert.go index 6adec02..5931a41 100644 --- a/alert.go +++ b/alert.go @@ -3,11 +3,12 @@ package main import ( "bytes" "fmt" - "log" "os/exec" "strings" "text/template" "time" + + "git.iamthefij.com/iamthefij/slog" ) // Alert is a config driven mechanism for sending a notice @@ -45,9 +46,9 @@ func (alert *Alert) BuildTemplates() error { "{last_success}", "{{.LastSuccess}}", "{monitor_name}", "{{.MonitorName}}", ) - if LogDebug { - log.Printf("DEBUG: Building template for alert %s", alert.Name) - } + + slog.Debugf("Building template for alert %s", alert.Name) + if alert.commandTemplate == nil && alert.Command.Command != nil { alert.commandTemplate = []*template.Template{} for i, cmdPart := range alert.Command.Command { @@ -75,7 +76,8 @@ func (alert *Alert) BuildTemplates() error { // Send will send an alert notice by executing the command template func (alert Alert) Send(notice AlertNotice) (outputStr string, err error) { - log.Printf("INFO: Sending alert %s for %s", alert.Name, notice.MonitorName) + slog.Infof("Sending alert %s for %s", alert.Name, notice.MonitorName) + var cmd *exec.Cmd if alert.commandTemplate != nil { command := []string{} @@ -110,9 +112,7 @@ func (alert Alert) Send(notice AlertNotice) (outputStr string, err error) { var output []byte output, err = cmd.CombinedOutput() outputStr = string(output) - if LogDebug { - log.Printf("DEBUG: Alert output for: %s\n---\n%s\n---", alert.Name, outputStr) - } + slog.Debugf("Alert output for: %s\n---\n%s\n---", alert.Name, outputStr) return outputStr, err } diff --git a/config.go b/config.go index 6783658..43a6086 100644 --- a/config.go +++ b/config.go @@ -3,8 +3,8 @@ package main import ( "errors" "io/ioutil" - "log" + "git.iamthefij.com/iamthefij/slog" "gopkg.in/yaml.v2" ) @@ -53,32 +53,36 @@ func (config Config) IsValid() (isValid bool) { // Validate alerts if config.Alerts == nil || len(config.Alerts) == 0 { // This should never happen because there is a default alert named 'log' for now - log.Printf("ERROR: Invalid alert configuration: Must provide at least one alert") + slog.Errorf("Invalid alert configuration: Must provide at least one alert") + isValid = false } for _, alert := range config.Alerts { if !alert.IsValid() { - log.Printf("ERROR: Invalid alert configuration: %s", alert.Name) + slog.Errorf("Invalid alert configuration: %s", alert.Name) + isValid = false } } // Validate monitors if config.Monitors == nil || len(config.Monitors) == 0 { - log.Printf("ERROR: Invalid monitor configuration: Must provide at least one monitor") + slog.Errorf("Invalid monitor configuration: Must provide at least one monitor") + isValid = false } for _, monitor := range config.Monitors { if !monitor.IsValid() { - log.Printf("ERROR: Invalid monitor configuration: %s", monitor.Name) + slog.Errorf("Invalid monitor configuration: %s", monitor.Name) + isValid = false } // Check that all Monitor alerts actually exist for _, isUp := range []bool{true, false} { for _, alertName := range monitor.GetAlertNames(isUp) { if _, ok := config.Alerts[alertName]; !ok { - log.Printf( - "ERROR: Invalid monitor configuration: %s. Unknown alert %s", + slog.Errorf( + "Invalid monitor configuration: %s. Unknown alert %s", monitor.Name, alertName, ) isValid = false @@ -114,9 +118,7 @@ func LoadConfig(filePath string) (config Config, err error) { return } - if LogDebug { - log.Printf("DEBUG: Config values:\n%v\n", config) - } + slog.Debugf("Config values:\n%v\n", config) // Add log alert if not present if PyCompat { diff --git a/go.mod b/go.mod index f8c4c81..7542551 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module git.iamthefij.com/iamthefij/minitor-go go 1.15 require ( + git.iamthefij.com/iamthefij/slog v1.3.0 github.com/prometheus/client_golang v1.2.1 gopkg.in/yaml.v2 v2.2.4 ) diff --git a/go.sum b/go.sum index 8980eef..033ad7f 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +git.iamthefij.com/iamthefij/slog v1.3.0 h1:4Hu5PQvDrW5e3FrTS3q2iIXW0iPvhNY/9qJsqDR3K3I= +git.iamthefij.com/iamthefij/slog v1.3.0/go.mod h1:1RUj4hcCompZkAxXCRfUX786tb3cM/Zpkn97dGfUfbg= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= diff --git a/main.go b/main.go index 26c6102..0f33158 100644 --- a/main.go +++ b/main.go @@ -3,14 +3,12 @@ package main import ( "flag" "fmt" - "log" "time" + + "git.iamthefij.com/iamthefij/slog" ) var ( - // LogDebug will control whether debug messsages should be logged - LogDebug = false - // ExportMetrics will track whether or not we want to export metrics to prometheus ExportMetrics = false // MetricsPort is the port to expose metrics on @@ -38,14 +36,12 @@ func checkMonitors(config *Config) error { // Should probably consider refactoring everything below here if alertNotice != nil { - if LogDebug { - log.Printf("DEBUG: Recieved an alert notice from %s", alertNotice.MonitorName) - } + slog.Debugf("Received an alert notice from %s", alertNotice.MonitorName) alertNames := monitor.GetAlertNames(alertNotice.IsUp) if alertNames == nil { // This should only happen for a recovery alert. AlertDown is validated not empty - log.Printf( - "WARNING: Recieved alert, but no alert mechanisms exist. MonitorName=%s IsUp=%t", + slog.Warningf( + "Received alert, but no alert mechanisms exist. MonitorName=%s IsUp=%t", alertNotice.MonitorName, alertNotice.IsUp, ) } @@ -53,8 +49,8 @@ func checkMonitors(config *Config) error { if alert, ok := config.Alerts[alertName]; ok { output, err := alert.Send(*alertNotice) if err != nil { - log.Printf( - "ERROR: Alert '%s' failed. result=%v: output=%s", + slog.Errorf( + "Alert '%s' failed. result=%v: output=%s", alert.Name, err, output, @@ -71,7 +67,8 @@ func checkMonitors(config *Config) error { Metrics.CountAlert(monitor.Name, alert.Name) } else { // This case should never actually happen since we validate against it - log.Printf("ERROR: Unknown alert for monitor %s: %s", alertNotice.MonitorName, alertName) + slog.Errorf("Unknown alert for monitor %s: %s", alertNotice.MonitorName, alertName) + return fmt.Errorf("Unknown alert for monitor %s: %s", alertNotice.MonitorName, alertName) } } @@ -83,30 +80,30 @@ func checkMonitors(config *Config) error { } func main() { - // Get debug flag - flag.BoolVar(&LogDebug, "debug", false, "Enables debug logs (default: false)") + showVersion := flag.Bool("version", false, "Display the version of minitor and exit") + configPath := flag.String("config", "config.yml", "Alternate configuration path (default: config.yml)") + + flag.BoolVar(&slog.DebugLevel, "debug", false, "Enables debug logs (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.IntVar(&MetricsPort, "metrics-port", 8080, "The port that Prometheus metrics should be exported on, if enabled. (default: 8080)") - var showVersion = flag.Bool("version", false, "Display the version of minitor and exit") - var configPath = flag.String("config", "config.yml", "Alternate configuration path (default: config.yml)") flag.Parse() // Print version if flag is provided if *showVersion { - log.Println("Minitor version:", version) + fmt.Println("Minitor version:", version) + return } // Load configuration config, err := LoadConfig(*configPath) - if err != nil { - log.Fatalf("Error loading config: %v", err) - } + slog.OnErrFatalf(err, "Error loading config: %v", err) // Serve metrics exporter, if specified if ExportMetrics { - log.Println("INFO: Exporting metrics to Prometheus") + slog.Infof("Exporting metrics to Prometheus") + go ServeMetrics() } diff --git a/monitor.go b/monitor.go index d74bcda..e1717e7 100644 --- a/monitor.go +++ b/monitor.go @@ -1,10 +1,11 @@ package main import ( - "log" "math" "os/exec" "time" + + "git.iamthefij.com/iamthefij/slog" ) // Monitor represents a particular periodic check of a command @@ -66,17 +67,11 @@ func (monitor *Monitor) Check() (bool, *AlertNotice) { alertNotice = monitor.failure() } - if LogDebug { - log.Printf("DEBUG: Command output: %s", monitor.lastOutput) - } - if err != nil { - if LogDebug { - log.Printf("DEBUG: Command result: %v", err) - } - } + slog.Debugf("Command output: %s", monitor.lastOutput) + slog.OnErrWarnf(err, "Command result: %v", err) - log.Printf( - "INFO: %s success=%t, alert=%t", + slog.Infof( + "%s success=%t, alert=%t", monitor.Name, isSuccess, alertNotice != nil, @@ -106,15 +101,14 @@ func (monitor *Monitor) failure() (notice *AlertNotice) { monitor.failureCount++ // If we haven't hit the minimum failures, we can exit if monitor.failureCount < monitor.getAlertAfter() { - if LogDebug { - log.Printf( - "DEBUG: %s failed but did not hit minimum failures. "+ - "Count: %v alert after: %v", - monitor.Name, - monitor.failureCount, - monitor.getAlertAfter(), - ) - } + slog.Debugf( + "%s failed but did not hit minimum failures. "+ + "Count: %v alert after: %v", + monitor.Name, + monitor.failureCount, + monitor.getAlertAfter(), + ) + return } diff --git a/util.go b/util.go index fbff395..16d5edb 100644 --- a/util.go +++ b/util.go @@ -8,7 +8,7 @@ import ( // ShellCommand takes a string and executes it as a command using `sh` func ShellCommand(command string) *exec.Cmd { shellCommand := []string{"sh", "-c", strings.TrimSpace(command)} - //log.Printf("Shell command: %v", shellCommand) + return exec.Command(shellCommand[0], shellCommand[1:]...) }