From 1e88576a17d6f3305da8b7d562b82c8113a4c1b3 Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Sat, 14 Sep 2024 13:46:00 +0200 Subject: [PATCH] feat: replace go-kit logger by slog --- Makefile | 2 +- changelog/unreleased/logging-library.md | 7 ++++ pkg/action/metrics.go | 9 ++-- pkg/action/server.go | 56 ++++++++----------------- pkg/command/command.go | 11 +---- pkg/command/health.go | 11 ++--- pkg/command/setup.go | 40 +++++++++--------- pkg/exporter/dashboard.go | 12 +++--- pkg/exporter/security_group.go | 15 +++---- pkg/exporter/server.go | 15 +++---- pkg/exporter/snapshot.go | 15 +++---- pkg/exporter/volume.go | 15 +++---- pkg/middleware/recoverer.go | 9 ++-- 13 files changed, 88 insertions(+), 129 deletions(-) create mode 100644 changelog/unreleased/logging-library.md diff --git a/Makefile b/Makefile index b04ac54..d4a805e 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ endif GOBUILD ?= CGO_ENABLED=0 go build PACKAGES ?= $(shell go list ./...) -SOURCES ?= $(shell find . -name "*.go" -type f) +SOURCES ?= $(shell find . -name "*.go" -type f -not -path ./.devenv/\* -not -path ./.direnv/\*) GENERATE ?= $(PACKAGES) TAGS ?= netgo diff --git a/changelog/unreleased/logging-library.md b/changelog/unreleased/logging-library.md new file mode 100644 index 0000000..11d4ebb --- /dev/null +++ b/changelog/unreleased/logging-library.md @@ -0,0 +1,7 @@ +Change: Switch to official logging library + +Since there have been a structured logger part of the Go standard library we +thought it's time to replace the library with that. Be aware that log messages +should change a little bit. + +https://github.com/promhippie/scw_exporter/issues/104 diff --git a/pkg/action/metrics.go b/pkg/action/metrics.go index 2215d0c..c819a2f 100644 --- a/pkg/action/metrics.go +++ b/pkg/action/metrics.go @@ -2,9 +2,8 @@ package action import ( "fmt" + "log/slog" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/collectors" "github.com/promhippie/scw_exporter/pkg/version" @@ -49,11 +48,9 @@ func init() { } type promLogger struct { - logger log.Logger + logger *slog.Logger } func (pl promLogger) Println(v ...interface{}) { - level.Error(pl.logger).Log( - "msg", fmt.Sprintln(v...), - ) + pl.logger.Error(fmt.Sprintln(v...)) } diff --git a/pkg/action/server.go b/pkg/action/server.go index cb998a0..0b42408 100644 --- a/pkg/action/server.go +++ b/pkg/action/server.go @@ -4,14 +4,13 @@ import ( "context" "fmt" "io" + "log/slog" "net/http" "os" "os/signal" "time" "github.com/go-chi/chi/v5" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/oklog/run" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/exporter-toolkit/web" @@ -23,9 +22,8 @@ import ( ) // Server handles the server sub-command. -func Server(cfg *config.Config, logger log.Logger) error { - level.Info(logger).Log( - "msg", "Launching Scaleway Exporter", +func Server(cfg *config.Config, logger *slog.Logger) error { + logger.Info("Launching Scaleway Exporter", "version", version.String, "revision", version.Revision, "date", version.Date, @@ -35,8 +33,7 @@ func Server(cfg *config.Config, logger log.Logger) error { accessKey, err := config.Value(cfg.Target.AccessKey) if err != nil { - level.Error(logger).Log( - "msg", "Failed to load access key from file", + logger.Error("Failed to load access key from file", "err", err, ) @@ -46,8 +43,7 @@ func Server(cfg *config.Config, logger log.Logger) error { secretKey, err := config.Value(cfg.Target.SecretKey) if err != nil { - level.Error(logger).Log( - "msg", "Failed to load secret key from file", + logger.Error("Failed to load secret key from file", "err", err, ) @@ -88,8 +84,7 @@ func Server(cfg *config.Config, logger log.Logger) error { ) if err != nil { - level.Error(logger).Log( - "msg", "Failed to parse region", + logger.Error("Failed to parse region", "err", err, ) @@ -107,8 +102,7 @@ func Server(cfg *config.Config, logger log.Logger) error { ) if err != nil { - level.Error(logger).Log( - "msg", "Failed to parse zone", + logger.Error("Failed to parse zone", "err", err, ) @@ -125,8 +119,7 @@ func Server(cfg *config.Config, logger log.Logger) error { ) if err != nil { - level.Error(logger).Log( - "msg", "Failed to initialize Scaleway client", + logger.Error("Failed to initialize Scaleway client", "err", err, ) @@ -144,9 +137,8 @@ func Server(cfg *config.Config, logger log.Logger) error { } gr.Add(func() error { - level.Info(logger).Log( - "msg", "Starting metrics server", - "addr", cfg.Server.Addr, + logger.Info("Starting metrics server", + "address", cfg.Server.Addr, ) return web.ListenAndServe( @@ -163,16 +155,14 @@ func Server(cfg *config.Config, logger log.Logger) error { defer cancel() if err := server.Shutdown(ctx); err != nil { - level.Error(logger).Log( - "msg", "Failed to shutdown metrics gracefully", + logger.Error("Failed to shutdown metrics gracefully", "err", err, ) return } - level.Info(logger).Log( - "msg", "Metrics shutdown gracefully", + logger.Info("Metrics shutdown gracefully", "reason", reason, ) }) @@ -195,7 +185,7 @@ func Server(cfg *config.Config, logger log.Logger) error { return gr.Run() } -func handler(cfg *config.Config, logger log.Logger, client *scw.Client) *chi.Mux { +func handler(cfg *config.Config, logger *slog.Logger, client *scw.Client) *chi.Mux { mux := chi.NewRouter() mux.Use(middleware.Recoverer(logger)) mux.Use(middleware.RealIP) @@ -207,9 +197,7 @@ func handler(cfg *config.Config, logger log.Logger, client *scw.Client) *chi.Mux } if cfg.Collector.Dashboard { - level.Debug(logger).Log( - "msg", "Dashboard collector registered", - ) + logger.Debug("Dashboard collector registered") registry.MustRegister(exporter.NewDashboardCollector( logger, @@ -221,9 +209,7 @@ func handler(cfg *config.Config, logger log.Logger, client *scw.Client) *chi.Mux } if cfg.Collector.SecurityGroups { - level.Debug(logger).Log( - "msg", "Security group collector registered", - ) + logger.Debug("Security group collector registered") registry.MustRegister(exporter.NewSecurityGroupCollector( logger, @@ -235,9 +221,7 @@ func handler(cfg *config.Config, logger log.Logger, client *scw.Client) *chi.Mux } if cfg.Collector.Servers { - level.Debug(logger).Log( - "msg", "Server collector registered", - ) + logger.Debug("Server collector registered") registry.MustRegister(exporter.NewServerCollector( logger, @@ -249,9 +233,7 @@ func handler(cfg *config.Config, logger log.Logger, client *scw.Client) *chi.Mux } if cfg.Collector.Snapshots { - level.Debug(logger).Log( - "msg", "Snaptshot collector registered", - ) + logger.Debug("Snaptshot collector registered") registry.MustRegister(exporter.NewSnapshotCollector( logger, @@ -263,9 +245,7 @@ func handler(cfg *config.Config, logger log.Logger, client *scw.Client) *chi.Mux } if cfg.Collector.Volumes { - level.Debug(logger).Log( - "msg", "Volume collector registered", - ) + logger.Debug("Volume collector registered") registry.MustRegister(exporter.NewVolumeCollector( logger, diff --git a/pkg/command/command.go b/pkg/command/command.go index e1c0fb0..c231491 100644 --- a/pkg/command/command.go +++ b/pkg/command/command.go @@ -5,7 +5,6 @@ import ( "os" "time" - "github.com/go-kit/log/level" "github.com/promhippie/scw_exporter/pkg/action" "github.com/promhippie/scw_exporter/pkg/config" "github.com/promhippie/scw_exporter/pkg/version" @@ -34,18 +33,12 @@ func Run() error { logger := setupLogger(cfg) if cfg.Target.AccessKey == "" { - level.Error(logger).Log( - "msg", "Missing required scw.access-key", - ) - + logger.Error("Missing required scw.access-key") return fmt.Errorf("missing required scw.access-key") } if cfg.Target.SecretKey == "" { - level.Error(logger).Log( - "msg", "Missing required scw.secret-key", - ) - + logger.Error("Missing required scw.secret-key") return fmt.Errorf("missing required scw.secret-key") } diff --git a/pkg/command/health.go b/pkg/command/health.go index 730f284..8dadf31 100644 --- a/pkg/command/health.go +++ b/pkg/command/health.go @@ -4,7 +4,6 @@ import ( "fmt" "net/http" - "github.com/go-kit/log/level" "github.com/promhippie/scw_exporter/pkg/config" "github.com/urfave/cli/v2" ) @@ -26,8 +25,7 @@ func Health(cfg *config.Config) *cli.Command { ) if err != nil { - level.Error(logger).Log( - "msg", "Failed to request health check", + logger.Error("Failed to request health check", "err", err, ) @@ -37,8 +35,7 @@ func Health(cfg *config.Config) *cli.Command { defer resp.Body.Close() if resp.StatusCode != 200 { - level.Error(logger).Log( - "msg", "Health check seems to be in bad state", + logger.Error("Health check seems to be in bad state", "err", err, "code", resp.StatusCode, ) @@ -46,6 +43,10 @@ func Health(cfg *config.Config) *cli.Command { return err } + logger.Debug("Health check seems to be fine", + "code", resp.StatusCode, + ) + return nil }, } diff --git a/pkg/command/setup.go b/pkg/command/setup.go index c5edbdd..8ae1d68 100644 --- a/pkg/command/setup.go +++ b/pkg/command/setup.go @@ -1,42 +1,40 @@ package command import ( + "log/slog" "os" "strings" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/promhippie/scw_exporter/pkg/config" ) -func setupLogger(cfg *config.Config) log.Logger { - var logger log.Logger - +func setupLogger(cfg *config.Config) *slog.Logger { if cfg.Logs.Pretty { - logger = log.NewSyncLogger( - log.NewLogfmtLogger(os.Stdout), - ) - } else { - logger = log.NewSyncLogger( - log.NewJSONLogger(os.Stdout), + return slog.New( + slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ + Level: loggerLevel(cfg), + }), ) } + return slog.New( + slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ + Level: loggerLevel(cfg), + }), + ) +} + +func loggerLevel(cfg *config.Config) slog.Leveler { switch strings.ToLower(cfg.Logs.Level) { case "error": - logger = level.NewFilter(logger, level.AllowError()) + return slog.LevelError case "warn": - logger = level.NewFilter(logger, level.AllowWarn()) + return slog.LevelWarn case "info": - logger = level.NewFilter(logger, level.AllowInfo()) + return slog.LevelInfo case "debug": - logger = level.NewFilter(logger, level.AllowDebug()) - default: - logger = level.NewFilter(logger, level.AllowInfo()) + return slog.LevelDebug } - return log.With( - logger, - "ts", log.DefaultTimestampUTC, - ) + return slog.LevelInfo } diff --git a/pkg/exporter/dashboard.go b/pkg/exporter/dashboard.go index 8f10a6d..fbeb80b 100644 --- a/pkg/exporter/dashboard.go +++ b/pkg/exporter/dashboard.go @@ -1,10 +1,9 @@ package exporter import ( + "log/slog" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/promhippie/scw_exporter/pkg/config" "github.com/scaleway/scaleway-sdk-go/api/instance/v1" @@ -15,7 +14,7 @@ import ( type DashboardCollector struct { client *scw.Client instance *instance.API - logger log.Logger + logger *slog.Logger failures *prometheus.CounterVec duration *prometheus.HistogramVec config config.Target @@ -40,7 +39,7 @@ type DashboardCollector struct { } // NewDashboardCollector returns a new DashboardCollector. -func NewDashboardCollector(logger log.Logger, client *scw.Client, failures *prometheus.CounterVec, duration *prometheus.HistogramVec, cfg config.Target) *DashboardCollector { +func NewDashboardCollector(logger *slog.Logger, client *scw.Client, failures *prometheus.CounterVec, duration *prometheus.HistogramVec, cfg config.Target) *DashboardCollector { if failures != nil { failures.WithLabelValues("dashboard").Add(0) } @@ -49,7 +48,7 @@ func NewDashboardCollector(logger log.Logger, client *scw.Client, failures *prom collector := &DashboardCollector{ client: client, instance: instance.NewAPI(client), - logger: log.With(logger, "collector", "dashboard"), + logger: logger.With("collector", "dashboard"), failures: failures, duration: duration, config: cfg, @@ -209,8 +208,7 @@ func (c *DashboardCollector) Collect(ch chan<- prometheus.Metric) { c.duration.WithLabelValues("dashboard").Observe(time.Since(now).Seconds()) if err != nil { - level.Error(c.logger).Log( - "msg", "Failed to fetch dashboard", + c.logger.Error("Failed to fetch dashboard", "zone", zone, "err", err, ) diff --git a/pkg/exporter/security_group.go b/pkg/exporter/security_group.go index 30bb3f6..e2d95ea 100644 --- a/pkg/exporter/security_group.go +++ b/pkg/exporter/security_group.go @@ -1,10 +1,9 @@ package exporter import ( + "log/slog" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/promhippie/scw_exporter/pkg/config" @@ -16,7 +15,7 @@ import ( type SecurityGroupCollector struct { client *scw.Client instance *instance.API - logger log.Logger + logger *slog.Logger failures *prometheus.CounterVec duration *prometheus.HistogramVec config config.Target @@ -35,7 +34,7 @@ type SecurityGroupCollector struct { } // NewSecurityGroupCollector returns a new SecurityGroupCollector. -func NewSecurityGroupCollector(logger log.Logger, client *scw.Client, failures *prometheus.CounterVec, duration *prometheus.HistogramVec, cfg config.Target) *SecurityGroupCollector { +func NewSecurityGroupCollector(logger *slog.Logger, client *scw.Client, failures *prometheus.CounterVec, duration *prometheus.HistogramVec, cfg config.Target) *SecurityGroupCollector { if failures != nil { failures.WithLabelValues("security_group").Add(0) } @@ -44,7 +43,7 @@ func NewSecurityGroupCollector(logger log.Logger, client *scw.Client, failures * collector := &SecurityGroupCollector{ client: client, instance: instance.NewAPI(client), - logger: log.With(logger, "collector", "security_group"), + logger: logger.With("collector", "security_group"), failures: failures, duration: duration, config: cfg, @@ -156,8 +155,7 @@ func (c *SecurityGroupCollector) Collect(ch chan<- prometheus.Metric) { c.duration.WithLabelValues("security_group").Observe(time.Since(now).Seconds()) if err != nil { - level.Error(c.logger).Log( - "msg", "Failed to fetch security groups", + c.logger.Error("Failed to fetch security groups", "zone", zone, "err", err, ) @@ -166,8 +164,7 @@ func (c *SecurityGroupCollector) Collect(ch chan<- prometheus.Metric) { return } - level.Debug(c.logger).Log( - "msg", "Fetched security groups", + c.logger.Debug("Fetched security groups", "zone", zone, "count", resp.TotalCount, ) diff --git a/pkg/exporter/server.go b/pkg/exporter/server.go index 81b6340..915fa9a 100644 --- a/pkg/exporter/server.go +++ b/pkg/exporter/server.go @@ -1,10 +1,9 @@ package exporter import ( + "log/slog" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/promhippie/scw_exporter/pkg/config" @@ -16,7 +15,7 @@ import ( type ServerCollector struct { client *scw.Client instance *instance.API - logger log.Logger + logger *slog.Logger failures *prometheus.CounterVec duration *prometheus.HistogramVec config config.Target @@ -31,7 +30,7 @@ type ServerCollector struct { } // NewServerCollector returns a new ServerCollector. -func NewServerCollector(logger log.Logger, client *scw.Client, failures *prometheus.CounterVec, duration *prometheus.HistogramVec, cfg config.Target) *ServerCollector { +func NewServerCollector(logger *slog.Logger, client *scw.Client, failures *prometheus.CounterVec, duration *prometheus.HistogramVec, cfg config.Target) *ServerCollector { if failures != nil { failures.WithLabelValues("server").Add(0) } @@ -40,7 +39,7 @@ func NewServerCollector(logger log.Logger, client *scw.Client, failures *prometh collector := &ServerCollector{ client: client, instance: instance.NewAPI(client), - logger: log.With(logger, "collector", "server"), + logger: logger.With("collector", "server"), failures: failures, duration: duration, config: cfg, @@ -120,8 +119,7 @@ func (c *ServerCollector) Collect(ch chan<- prometheus.Metric) { c.duration.WithLabelValues("server").Observe(time.Since(now).Seconds()) if err != nil { - level.Error(c.logger).Log( - "msg", "Failed to fetch servers", + c.logger.Error("Failed to fetch servers", "zone", zone, "err", err, ) @@ -130,8 +128,7 @@ func (c *ServerCollector) Collect(ch chan<- prometheus.Metric) { return } - level.Debug(c.logger).Log( - "msg", "Fetched servers", + c.logger.Debug("Fetched servers", "zone", zone, "count", resp.TotalCount, ) diff --git a/pkg/exporter/snapshot.go b/pkg/exporter/snapshot.go index d0d8be3..336902e 100644 --- a/pkg/exporter/snapshot.go +++ b/pkg/exporter/snapshot.go @@ -1,10 +1,9 @@ package exporter import ( + "log/slog" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/promhippie/scw_exporter/pkg/config" @@ -16,7 +15,7 @@ import ( type SnapshotCollector struct { client *scw.Client instance *instance.API - logger log.Logger + logger *slog.Logger failures *prometheus.CounterVec duration *prometheus.HistogramVec config config.Target @@ -32,7 +31,7 @@ type SnapshotCollector struct { } // NewSnapshotCollector returns a new SnapshotCollector. -func NewSnapshotCollector(logger log.Logger, client *scw.Client, failures *prometheus.CounterVec, duration *prometheus.HistogramVec, cfg config.Target) *SnapshotCollector { +func NewSnapshotCollector(logger *slog.Logger, client *scw.Client, failures *prometheus.CounterVec, duration *prometheus.HistogramVec, cfg config.Target) *SnapshotCollector { if failures != nil { failures.WithLabelValues("snapshot").Add(0) } @@ -41,7 +40,7 @@ func NewSnapshotCollector(logger log.Logger, client *scw.Client, failures *prome collector := &SnapshotCollector{ client: client, instance: instance.NewAPI(client), - logger: log.With(logger, "collector", "snapshot"), + logger: logger.With("collector", "snapshot"), failures: failures, duration: duration, config: cfg, @@ -129,8 +128,7 @@ func (c *SnapshotCollector) Collect(ch chan<- prometheus.Metric) { c.duration.WithLabelValues("snapshot").Observe(time.Since(now).Seconds()) if err != nil { - level.Error(c.logger).Log( - "msg", "Failed to fetch snapshots", + c.logger.Error("Failed to fetch snapshots", "zone", zone, "err", err, ) @@ -139,8 +137,7 @@ func (c *SnapshotCollector) Collect(ch chan<- prometheus.Metric) { return } - level.Debug(c.logger).Log( - "msg", "Fetched snapshots", + c.logger.Debug("Fetched snapshots", "zone", zone, "count", resp.TotalCount, ) diff --git a/pkg/exporter/volume.go b/pkg/exporter/volume.go index 1ad22a9..4dc937c 100644 --- a/pkg/exporter/volume.go +++ b/pkg/exporter/volume.go @@ -1,10 +1,9 @@ package exporter import ( + "log/slog" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/promhippie/scw_exporter/pkg/config" @@ -16,7 +15,7 @@ import ( type VolumeCollector struct { client *scw.Client instance *instance.API - logger log.Logger + logger *slog.Logger failures *prometheus.CounterVec duration *prometheus.HistogramVec config config.Target @@ -32,7 +31,7 @@ type VolumeCollector struct { } // NewVolumeCollector returns a new VolumeCollector. -func NewVolumeCollector(logger log.Logger, client *scw.Client, failures *prometheus.CounterVec, duration *prometheus.HistogramVec, cfg config.Target) *VolumeCollector { +func NewVolumeCollector(logger *slog.Logger, client *scw.Client, failures *prometheus.CounterVec, duration *prometheus.HistogramVec, cfg config.Target) *VolumeCollector { if failures != nil { failures.WithLabelValues("volume").Add(0) } @@ -41,7 +40,7 @@ func NewVolumeCollector(logger log.Logger, client *scw.Client, failures *prometh collector := &VolumeCollector{ client: client, instance: instance.NewAPI(client), - logger: log.With(logger, "collector", "volume"), + logger: logger.With("collector", "volume"), failures: failures, duration: duration, config: cfg, @@ -129,8 +128,7 @@ func (c *VolumeCollector) Collect(ch chan<- prometheus.Metric) { c.duration.WithLabelValues("volume").Observe(time.Since(now).Seconds()) if err != nil { - level.Error(c.logger).Log( - "msg", "Failed to fetch volumes", + c.logger.Error("Failed to fetch volumes", "zone", zone, "err", err, ) @@ -139,8 +137,7 @@ func (c *VolumeCollector) Collect(ch chan<- prometheus.Metric) { return } - level.Debug(c.logger).Log( - "msg", "Fetched volumes", + c.logger.Debug("Fetched volumes", "zone", zone, "count", resp.TotalCount, ) diff --git a/pkg/middleware/recoverer.go b/pkg/middleware/recoverer.go index 1cc2dab..95f9de1 100644 --- a/pkg/middleware/recoverer.go +++ b/pkg/middleware/recoverer.go @@ -1,21 +1,18 @@ package middleware import ( + "log/slog" "net/http" "runtime/debug" - - "github.com/go-kit/log" - "github.com/go-kit/log/level" ) // Recoverer initializes a recoverer middleware. -func Recoverer(logger log.Logger) func(next http.Handler) http.Handler { +func Recoverer(logger *slog.Logger) func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { defer func() { if rvr := recover(); rvr != nil { - level.Error(logger).Log( - "msg", rvr.(string), + logger.Error(rvr.(string), "trace", string(debug.Stack()), )