Replace log with slog
This commit is contained in:
parent
f0e179851f
commit
fda9e1bfc3
@ -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
|
||||
|
16
alert.go
16
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
|
||||
}
|
||||
|
22
config.go
22
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 {
|
||||
|
1
go.mod
1
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
|
||||
)
|
||||
|
2
go.sum
2
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=
|
||||
|
39
main.go
39
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()
|
||||
}
|
||||
|
||||
|
34
monitor.go
34
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
|
||||
}
|
||||
|
||||
|
2
util.go
2
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:]...)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user