1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
From: Daniel Swarbrick <dswarbrick@debian.org>
Date: Thu, 19 Sep 2024 17:41:42 +0200
Subject: Work around slog logger breaking change
Origin: https://github.com/prometheus/exporter-toolkit/pull/240#issuecomment-2344348746
The migration to the Go standard library log/slog breaks backwards
compatibility, resulting in the build failure of more than 20 other
packages which currently depend on exporter-toolkit.
---
web/tls_config.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 57 insertions(+), 2 deletions(-)
diff --git a/web/tls_config.go b/web/tls_config.go
index 0730a93..53803a9 100644
--- a/web/tls_config.go
+++ b/web/tls_config.go
@@ -28,8 +28,10 @@ import (
"strings"
"github.com/coreos/go-systemd/v22/activation"
+ "github.com/go-kit/log"
"github.com/mdlayher/vsock"
config_util "github.com/prometheus/common/config"
+ "github.com/prometheus/common/promslog"
"golang.org/x/sync/errgroup"
"gopkg.in/yaml.v2"
)
@@ -283,7 +285,9 @@ func ServeMultiple(listeners []net.Listener, server *http.Server, flags *FlagCon
// Or instead uses systemd socket activated listeners if WebSystemdSocket in the
// FlagConfig is true.
// The FlagConfig is also passed on to ServeMultiple.
-func ListenAndServe(server *http.Server, flags *FlagConfig, logger *slog.Logger) error {
+func ListenAndServe(server *http.Server, flags *FlagConfig, origLogger any) error {
+ logger := getSlogger(origLogger)
+
if flags.WebSystemdSocket == nil && (flags.WebListenAddresses == nil || len(*flags.WebListenAddresses) == 0) {
return ErrNoListeners
}
@@ -343,7 +347,9 @@ func parseVsockPort(address string) (uint32, error) {
// Server starts the server on the given listener. Based on the file path
// WebConfigFile in the FlagConfig, TLS or basic auth could be enabled.
-func Serve(l net.Listener, server *http.Server, flags *FlagConfig, logger *slog.Logger) error {
+func Serve(l net.Listener, server *http.Server, flags *FlagConfig, origLogger any) error {
+ logger := getSlogger(origLogger)
+
logger.Info("Listening on", "address", l.Addr().String())
tlsConfigPath := *flags.WebConfigFile
if tlsConfigPath == "" {
@@ -514,3 +520,52 @@ func (tv *TLSVersion) MarshalYAML() (interface{}, error) {
func Listen(server *http.Server, flags *FlagConfig, logger *slog.Logger) error {
return ListenAndServe(server, flags, logger)
}
+
+// Workaround for backwards-incompatible change in v0.13.0, which breaks over 20 exporters in
+// Debian which currently depend on exporter-toolkit.
+func getSlogger(logger any) *slog.Logger {
+ // Since go-kit/log.Logger does not provide any means to ascertain the log format or level, the
+ // only option is to re-parse the command line args. However, without knowing the other flags
+ // that the caller application has defined, both kingpin and the Go standard library flag
+ // package will throw an error when they see an unknown flag. Therefore, we have to implement a
+ // very naive flag parser to get the log format and level (if specified) from os.Args. We can
+ // at least take some liberties with error checking in the knowledge that the caller
+ // application's kingpin parser has already vetted the args, and we should only make it this
+ // far if they are valid.
+ switch logger := logger.(type) {
+ case log.Logger:
+ config := &promslog.Config{
+ Format: promslog.NewFormat(),
+ Level: promslog.NewLevel(),
+ Style: promslog.GoKitStyle,
+ }
+
+ // Set defaults, in case no relevant flags were specified on command line.
+ config.Format.Set("logfmt")
+ config.Level.Set("info")
+
+ for i, arg := range os.Args {
+ if strings.HasPrefix(arg, "--log.format") {
+ if p := strings.IndexByte(arg, '='); p > 0 {
+ config.Format.Set(arg[p+1:])
+ } else {
+ config.Format.Set(os.Args[i+1])
+ }
+ }
+
+ if strings.HasPrefix(arg, "--log.level") {
+ if p := strings.IndexByte(arg, '='); p > 0 {
+ config.Level.Set(arg[p+1:])
+ } else {
+ config.Level.Set(os.Args[i+1])
+ }
+ }
+ }
+
+ return promslog.New(config)
+ case *slog.Logger:
+ return logger
+ default:
+ panic("unsupported logger type")
+ }
+}
|