From 21171cf6d6e04fa2a5642973e0c32a4a43e4a50b Mon Sep 17 00:00:00 2001 From: TJ Hoplock Date: Sun, 29 Sep 2024 12:08:22 -0400 Subject: [PATCH] chore!: adopt log/slog, drop go-kit/log Requires: prometheus/common#697 This PR includes: - linter updates to enable sloglint linter - Go dep updates for prometheus/{client_golang,common,exporter-toolkit} libs - refactorings to adopt log/slog in favor of go-kit/log The bulk of this PR was automated by the following script which is being used to aid in converting the various exporters/projects to use slog: https://gist.github.com/tjhop/49f96fb7ebbe55b12deee0b0312d8434 Builds and passes tests locally with go workspaces and up-to-date main branch of prometheus/common. Signed-off-by: TJ Hoplock --- cmd/memcached_exporter/main.go | 28 ++++++++++----------- go.mod | 2 -- go.sum | 4 --- pkg/exporter/exporter.go | 45 +++++++++++++++++----------------- pkg/exporter/exporter_test.go | 10 ++++---- scraper/scraper.go | 13 +++++----- scraper/scraper_test.go | 6 ++--- 7 files changed, 49 insertions(+), 59 deletions(-) diff --git a/cmd/memcached_exporter/main.go b/cmd/memcached_exporter/main.go index d6b3a10b..ddf1f276 100644 --- a/cmd/memcached_exporter/main.go +++ b/cmd/memcached_exporter/main.go @@ -21,14 +21,13 @@ import ( "strings" "github.com/alecthomas/kingpin/v2" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/collectors" versioncollector "github.com/prometheus/client_golang/prometheus/collectors/version" "github.com/prometheus/client_golang/prometheus/promhttp" promconfig "github.com/prometheus/common/config" - "github.com/prometheus/common/promlog" - "github.com/prometheus/common/promlog/flag" + "github.com/prometheus/common/promslog" + "github.com/prometheus/common/promslog/flag" "github.com/prometheus/common/version" "github.com/prometheus/exporter-toolkit/web" webflag "github.com/prometheus/exporter-toolkit/web/kingpinflag" @@ -53,15 +52,15 @@ func main() { scrapePath = kingpin.Flag("web.scrape-path", "Path under which to receive scrape requests.").Default("/scrape").String() ) - promlogConfig := &promlog.Config{} - flag.AddFlags(kingpin.CommandLine, promlogConfig) + promslogConfig := &promslog.Config{} + flag.AddFlags(kingpin.CommandLine, promslogConfig) kingpin.HelpFlag.Short('h') kingpin.Version(version.Print("memcached_exporter")) kingpin.Parse() - logger := promlog.New(promlogConfig) + logger := promslog.New(promslogConfig) - level.Info(logger).Log("msg", "Starting memcached_exporter", "version", version.Info()) - level.Info(logger).Log("msg", "Build context", "context", version.BuildContext()) + logger.Info("Starting memcached_exporter", "version", version.Info()) + logger.Info("Build context", "context", version.BuildContext()) var ( tlsConfig *tls.Config @@ -72,11 +71,10 @@ func main() { *serverName, _, err = net.SplitHostPort(*address) if err != nil { if strings.Contains(*address, "/") { - level.Error(logger).Log("msg", - "If --memcached.tls.enable is set and --memcached.address is a unix socket, "+ - "you must also specify --memcached.tls.server-name") + logger.Error("If --memcached.tls.enable is set and --memcached.address is a unix socket, " + + "you must also specify --memcached.tls.server-name") } else { - level.Error(logger).Log("msg", "Error parsing memcached address", "err", err) + logger.Error("Error parsing memcached address", "err", err) } os.Exit(1) } @@ -89,7 +87,7 @@ func main() { InsecureSkipVerify: *insecureSkipVerify, }) if err != nil { - level.Error(logger).Log("msg", "Failed to create TLS config", "err", err) + logger.Error("Failed to create TLS config", "err", err) os.Exit(1) } } @@ -126,7 +124,7 @@ func main() { } landingPage, err := web.NewLandingPage(landingConfig) if err != nil { - level.Error(logger).Log("err", err) + logger.Error("Error creating landing page", "err", err) os.Exit(1) } http.Handle("/", landingPage) @@ -134,7 +132,7 @@ func main() { srv := &http.Server{} if err := web.ListenAndServe(srv, webConfig, logger); err != nil { - level.Error(logger).Log("msg", "Error running HTTP server", "err", err) + logger.Error("Error running HTTP server", "err", err) os.Exit(1) } } diff --git a/go.mod b/go.mod index dec8cd12..e3c61c46 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.23.0 require ( github.com/alecthomas/kingpin/v2 v2.4.0 - github.com/go-kit/log v0.2.1 github.com/grobie/gomemcache v0.0.0-20230213081705-239240bbc445 github.com/prometheus/client_golang v1.20.4 github.com/prometheus/common v0.59.1 @@ -16,7 +15,6 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/mdlayher/socket v0.4.1 // indirect diff --git a/go.sum b/go.sum index d1401756..6e48bf49 100644 --- a/go.sum +++ b/go.sum @@ -11,10 +11,6 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= -github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= diff --git a/pkg/exporter/exporter.go b/pkg/exporter/exporter.go index 3f295f45..2e2ce657 100644 --- a/pkg/exporter/exporter.go +++ b/pkg/exporter/exporter.go @@ -16,13 +16,12 @@ package exporter import ( "crypto/tls" "errors" + "log/slog" "net" "strconv" "strings" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/grobie/gomemcache/memcache" "github.com/prometheus/client_golang/prometheus" ) @@ -39,7 +38,7 @@ var errKeyNotFound = errors.New("key not found") type Exporter struct { address string timeout time.Duration - logger log.Logger + logger *slog.Logger tlsConfig *tls.Config up *prometheus.Desc @@ -133,7 +132,7 @@ type Exporter struct { } // New returns an initialized exporter. -func New(server string, timeout time.Duration, logger log.Logger, tlsConfig *tls.Config) *Exporter { +func New(server string, timeout time.Duration, logger *slog.Logger, tlsConfig *tls.Config) *Exporter { return &Exporter{ address: server, timeout: timeout, @@ -770,7 +769,7 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) { c, err := memcache.New(e.address) if err != nil { ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 0) - level.Error(e.logger).Log("msg", "Failed to connect to memcached", "err", err) + e.logger.Error("Failed to connect to memcached", "err", err) return } c.Timeout = e.timeout @@ -779,12 +778,12 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) { up := float64(1) stats, err := c.Stats() if err != nil { - level.Error(e.logger).Log("msg", "Failed to collect stats from memcached", "err", err) + e.logger.Error("Failed to collect stats from memcached", "err", err) up = 0 } statsSettings, err := c.StatsSettings() if err != nil { - level.Error(e.logger).Log("msg", "Could not query stats settings", "err", err) + e.logger.Error("Could not query stats settings", "err", err) up = 0 } @@ -857,11 +856,11 @@ func (e *Exporter) parseStats(ch chan<- prometheus.Metric, stats map[net.Addr]me if cas, casErr := sum(s, "cas_misses", "cas_hits", "cas_badval"); casErr == nil { ch <- prometheus.MustNewConstMetric(e.commands, prometheus.CounterValue, setCmd-cas, "set", "hit") } else { - level.Error(e.logger).Log("msg", "Failed to parse cas", "err", casErr) + e.logger.Error("Failed to parse cas", "err", casErr) parseError = casErr } } else { - level.Error(e.logger).Log("msg", "Failed to parse set", "err", err) + e.logger.Error("Failed to parse set", "err", err) parseError = err } @@ -973,11 +972,11 @@ func (e *Exporter) parseStats(ch chan<- prometheus.Metric, stats map[net.Addr]me if slabCas, slabCasErr := sum(v, "cas_hits", "cas_badval"); slabCasErr == nil { ch <- prometheus.MustNewConstMetric(e.slabsCommands, prometheus.CounterValue, slabSetCmd-slabCas, slab, "set", "hit") } else { - level.Error(e.logger).Log("msg", "Failed to parse cas", "err", slabCasErr) + e.logger.Error("Failed to parse cas", "err", slabCasErr) parseError = slabCasErr } } else { - level.Error(e.logger).Log("msg", "Failed to parse set", "err", err) + e.logger.Error("Failed to parse set", "err", err) parseError = err } @@ -1038,7 +1037,7 @@ func (e *Exporter) parseTimevalAndNewMetric(ch chan<- prometheus.Metric, desc *p return e.extractValueAndNewMetric(ch, desc, valueType, parseTimeval, stats, key, labelValues...) } -func (e *Exporter) extractValueAndNewMetric(ch chan<- prometheus.Metric, desc *prometheus.Desc, valueType prometheus.ValueType, f func(map[string]string, string, log.Logger) (float64, error), stats map[string]string, key string, labelValues ...string) error { +func (e *Exporter) extractValueAndNewMetric(ch chan<- prometheus.Metric, desc *prometheus.Desc, valueType prometheus.ValueType, f func(map[string]string, string, *slog.Logger) (float64, error), stats map[string]string, key string, labelValues ...string) error { v, err := f(stats, key, e.logger) if err == errKeyNotFound { return nil @@ -1051,25 +1050,25 @@ func (e *Exporter) extractValueAndNewMetric(ch chan<- prometheus.Metric, desc *p return nil } -func parse(stats map[string]string, key string, logger log.Logger) (float64, error) { +func parse(stats map[string]string, key string, logger *slog.Logger) (float64, error) { value, ok := stats[key] if !ok { - level.Debug(logger).Log("msg", "Key not found", "key", key) + logger.Debug("Key not found", "key", key) return 0, errKeyNotFound } v, err := strconv.ParseFloat(value, 64) if err != nil { - level.Error(logger).Log("msg", "Failed to parse", "key", key, "value", value, "err", err) + logger.Error("Failed to parse", "key", key, "value", value, "err", err) return 0, err } return v, nil } -func parseBool(stats map[string]string, key string, logger log.Logger) (float64, error) { +func parseBool(stats map[string]string, key string, logger *slog.Logger) (float64, error) { value, ok := stats[key] if !ok { - level.Debug(logger).Log("msg", "Key not found", "key", key) + logger.Debug("Key not found", "key", key) return 0, errKeyNotFound } @@ -1079,33 +1078,33 @@ func parseBool(stats map[string]string, key string, logger log.Logger) (float64, case "no": return 0, nil default: - level.Error(logger).Log("msg", "Failed to parse", "key", key, "value", value) + logger.Error("Failed to parse", "key", key, "value", value) return 0, errors.New("failed parse a bool value") } } -func parseTimeval(stats map[string]string, key string, logger log.Logger) (float64, error) { +func parseTimeval(stats map[string]string, key string, logger *slog.Logger) (float64, error) { value, ok := stats[key] if !ok { - level.Debug(logger).Log("msg", "Key not found", "key", key) + logger.Debug("Key not found", "key", key) return 0, errKeyNotFound } values := strings.Split(value, ".") if len(values) != 2 { - level.Error(logger).Log("msg", "Failed to parse", "key", key, "value", value) + logger.Error("Failed to parse", "key", key, "value", value) return 0, errors.New("failed parse a timeval value") } seconds, err := strconv.ParseFloat(values[0], 64) if err != nil { - level.Error(logger).Log("msg", "Failed to parse", "key", key, "value", value, "err", err) + logger.Error("Failed to parse", "key", key, "value", value, "err", err) return 0, errors.New("failed parse a timeval value") } microseconds, err := strconv.ParseFloat(values[1], 64) if err != nil { - level.Error(logger).Log("msg", "Failed to parse", "key", key, "value", value, "err", err) + logger.Error("Failed to parse", "key", key, "value", value, "err", err) return 0, errors.New("failed parse a timeval value") } diff --git a/pkg/exporter/exporter_test.go b/pkg/exporter/exporter_test.go index 6ca0ac31..dae28437 100644 --- a/pkg/exporter/exporter_test.go +++ b/pkg/exporter/exporter_test.go @@ -18,8 +18,8 @@ import ( "testing" "time" - "github.com/go-kit/log" "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/promslog" ) func TestParseStatsSettings(t *testing.T) { @@ -46,7 +46,7 @@ func TestParseStatsSettings(t *testing.T) { }, } ch := make(chan prometheus.Metric, 100) - e := New("", 100*time.Millisecond, log.NewNopLogger(), nil) + e := New("", 100*time.Millisecond, promslog.NewNopLogger(), nil) if err := e.parseStatsSettings(ch, statsSettings); err != nil { t.Errorf("expect return error, error: %v", err) } @@ -69,7 +69,7 @@ func TestParseStatsSettings(t *testing.T) { }, } ch := make(chan prometheus.Metric, 100) - e := New("", 100*time.Millisecond, log.NewNopLogger(), nil) + e := New("", 100*time.Millisecond, promslog.NewNopLogger(), nil) if err := e.parseStatsSettings(ch, statsSettings); err == nil { t.Error("expect return error but not") } @@ -79,7 +79,7 @@ func TestParseStatsSettings(t *testing.T) { func TestParseTimeval(t *testing.T) { t.Run("Success", func(t *testing.T) { t.Parallel() - _, err := parseTimeval(map[string]string{"rusage_system": "3.5"}, "rusage_system", log.NewNopLogger()) + _, err := parseTimeval(map[string]string{"rusage_system": "3.5"}, "rusage_system", promslog.NewNopLogger()) if err != nil { t.Errorf("expect return error, error: %v", err) } @@ -87,7 +87,7 @@ func TestParseTimeval(t *testing.T) { t.Run("Failure", func(t *testing.T) { t.Parallel() - _, err := parseTimeval(map[string]string{"rusage_system": "35"}, "rusage_system", log.NewNopLogger()) + _, err := parseTimeval(map[string]string{"rusage_system": "35"}, "rusage_system", promslog.NewNopLogger()) if err == nil { t.Error("expect return error but not") } diff --git a/scraper/scraper.go b/scraper/scraper.go index f2480640..db8f094f 100644 --- a/scraper/scraper.go +++ b/scraper/scraper.go @@ -15,18 +15,17 @@ package scraper import ( "crypto/tls" + "log/slog" "net/http" "time" - "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/memcached_exporter/pkg/exporter" ) type Scraper struct { - logger log.Logger + logger *slog.Logger timeout time.Duration tlsConfig *tls.Config @@ -34,8 +33,8 @@ type Scraper struct { scrapeErrors prometheus.Counter } -func New(timeout time.Duration, logger log.Logger, tlsConfig *tls.Config) *Scraper { - level.Debug(logger).Log("msg", "Started scrapper") +func New(timeout time.Duration, logger *slog.Logger, tlsConfig *tls.Config) *Scraper { + logger.Debug("Started scrapper") return &Scraper{ logger: logger, timeout: timeout, @@ -54,12 +53,12 @@ func New(timeout time.Duration, logger log.Logger, tlsConfig *tls.Config) *Scrap func (s *Scraper) Handler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { target := r.URL.Query().Get("target") - level.Debug(s.logger).Log("msg", "scrapping memcached", "target", target) + s.logger.Debug("scrapping memcached", "target", target) s.scrapeCount.Inc() if target == "" { errorStr := "'target' parameter must be specified" - level.Warn(s.logger).Log("msg", errorStr) + s.logger.Warn(errorStr) http.Error(w, errorStr, http.StatusBadRequest) s.scrapeErrors.Inc() return diff --git a/scraper/scraper_test.go b/scraper/scraper_test.go index 6c7c4e84..44ed097c 100644 --- a/scraper/scraper_test.go +++ b/scraper/scraper_test.go @@ -20,14 +20,14 @@ import ( "testing" "time" - "github.com/go-kit/log" + "github.com/prometheus/common/promslog" ) func TestHandler(t *testing.T) { t.Run("Success", func(t *testing.T) { t.Parallel() - s := New(1*time.Second, log.NewNopLogger(), nil) + s := New(1*time.Second, promslog.NewNopLogger(), nil) req, err := http.NewRequest("GET", "/?target=127.0.0.1:11211", nil) @@ -55,7 +55,7 @@ func TestHandler(t *testing.T) { t.Run("No target", func(t *testing.T) { t.Parallel() - s := New(1*time.Second, log.NewNopLogger(), nil) + s := New(1*time.Second, promslog.NewNopLogger(), nil) req, err := http.NewRequest("GET", "/", nil)