diff --git a/.golangci.yml b/.golangci.yml index 662de5057..632ca1e2c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -162,7 +162,7 @@ issues: text: "Function 'buildConstructor' has too many statements" linters: - funlen - - path: pkg/tracing/haystack/logger.go + - path: pkg/logs/haystack.go linters: - goprintffuncname - path: pkg/tracing/tracing.go diff --git a/cmd/traefik/logger.go b/cmd/traefik/logger.go new file mode 100644 index 000000000..0c20d2bf0 --- /dev/null +++ b/cmd/traefik/logger.go @@ -0,0 +1,90 @@ +package main + +import ( + "io" + stdlog "log" + "os" + "strings" + "time" + + "github.com/natefinch/lumberjack" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" + "github.com/sirupsen/logrus" + "github.com/traefik/traefik/v2/pkg/config/static" + "github.com/traefik/traefik/v2/pkg/logs" +) + +func init() { + // hide the first logs before the setup of the logger. + zerolog.SetGlobalLevel(zerolog.ErrorLevel) +} + +func setupLogger(staticConfiguration *static.Configuration) { + // configure log format + w := getLogWriter(staticConfiguration) + + // configure log level + logLevel := getLogLevel(staticConfiguration) + + zerolog.SetGlobalLevel(logLevel) + + // create logger + logCtx := zerolog.New(w).With().Timestamp() + if logLevel <= zerolog.DebugLevel { + logCtx = logCtx.Caller() + } + + log.Logger = logCtx.Logger() + zerolog.DefaultContextLogger = &log.Logger + + // Global logrus replacement (related to lib like go-rancher-metadata, docker, etc.) + logrus.StandardLogger().Out = logs.NoLevel(log.Logger, zerolog.DebugLevel) + + // configure default standard log. + stdlog.SetFlags(stdlog.Lshortfile | stdlog.LstdFlags) + stdlog.SetOutput(logs.NoLevel(log.Logger, zerolog.DebugLevel)) +} + +func getLogWriter(staticConfiguration *static.Configuration) io.Writer { + var w io.Writer = os.Stderr + + if staticConfiguration.Log != nil && len(staticConfiguration.Log.FilePath) > 0 { + _, _ = os.Create(staticConfiguration.Log.FilePath) + w = &lumberjack.Logger{ + Filename: staticConfiguration.Log.FilePath, + MaxSize: staticConfiguration.Log.MaxSize, + MaxBackups: staticConfiguration.Log.MaxBackups, + MaxAge: staticConfiguration.Log.MaxAge, + Compress: true, + } + } + + if staticConfiguration.Log == nil || staticConfiguration.Log.Format != "json" { + w = zerolog.ConsoleWriter{ + Out: w, + TimeFormat: time.RFC3339, + NoColor: staticConfiguration.Log != nil && (staticConfiguration.Log.NoColor || len(staticConfiguration.Log.FilePath) > 0), + } + } + + return w +} + +func getLogLevel(staticConfiguration *static.Configuration) zerolog.Level { + levelStr := "error" + if staticConfiguration.Log != nil && staticConfiguration.Log.Level != "" { + levelStr = strings.ToLower(staticConfiguration.Log.Level) + } + + logLevel, err := zerolog.ParseLevel(strings.ToLower(levelStr)) + if err != nil { + log.Error().Err(err). + Str("logLevel", levelStr). + Msg("Unspecified or invalid log level, setting the level to default (ERROR)...") + + logLevel = zerolog.ErrorLevel + } + + return logLevel +} diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index db4148e5a..15fe3f1f1 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -9,7 +9,6 @@ import ( "net/http" "os" "os/signal" - "path/filepath" "sort" "strings" "syscall" @@ -18,6 +17,7 @@ import ( "github.com/coreos/go-systemd/daemon" "github.com/go-acme/lego/v4/challenge" gokitmetrics "github.com/go-kit/kit/metrics" + "github.com/rs/zerolog/log" "github.com/sirupsen/logrus" "github.com/spiffe/go-spiffe/v2/workloadapi" "github.com/traefik/paerser/cli" @@ -29,7 +29,7 @@ import ( "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/runtime" "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/metrics" "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" "github.com/traefik/traefik/v2/pkg/provider/acme" @@ -46,7 +46,6 @@ import ( "github.com/traefik/traefik/v2/pkg/tracing/jaeger" "github.com/traefik/traefik/v2/pkg/types" "github.com/traefik/traefik/v2/pkg/version" - "github.com/vulcand/oxy/roundrobin" ) func main() { @@ -88,27 +87,24 @@ Complete documentation is available at https://traefik.io`, } func runCmd(staticConfiguration *static.Configuration) error { - configureLogging(staticConfiguration) + setupLogger(staticConfiguration) http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment - if err := roundrobin.SetDefaultWeight(0); err != nil { - log.WithoutContext().Errorf("Could not set round robin default weight: %v", err) - } - staticConfiguration.SetEffectiveConfiguration() if err := staticConfiguration.ValidateConfiguration(); err != nil { return err } - log.WithoutContext().Infof("Traefik version %s built on %s", version.Version, version.BuildDate) + log.Info().Str("version", version.Version). + Msgf("Traefik version %s built on %s", version.Version, version.BuildDate) jsonConf, err := json.Marshal(staticConfiguration) if err != nil { - log.WithoutContext().Errorf("Could not marshal static configuration: %v", err) - log.WithoutContext().Debugf("Static configuration loaded [struct] %#v", staticConfiguration) + log.Error().Err(err).Msg("Could not marshal static configuration") + log.Debug().Interface("staticConfiguration", staticConfiguration).Msg("Static configuration loaded [struct]") } else { - log.WithoutContext().Debugf("Static configuration loaded %s", string(jsonConf)) + log.Debug().RawJSON("staticConfiguration", jsonConf).Msg("Static configuration loaded [json]") } if staticConfiguration.Global.CheckNewVersion { @@ -133,16 +129,16 @@ func runCmd(staticConfiguration *static.Configuration) error { sent, err := daemon.SdNotify(false, "READY=1") if !sent && err != nil { - log.WithoutContext().Errorf("Failed to notify: %v", err) + log.Error().Err(err).Msg("Failed to notify") } t, err := daemon.SdWatchdogEnabled(false) if err != nil { - log.WithoutContext().Errorf("Could not enable Watchdog: %v", err) + log.Error().Err(err).Msg("Could not enable Watchdog") } else if t != 0 { // Send a ping each half time given t /= 2 - log.WithoutContext().Infof("Watchdog activated with timer duration %s", t) + log.Info().Msgf("Watchdog activated with timer duration %s", t) safe.Go(func() { tick := time.Tick(t) for range tick { @@ -153,17 +149,17 @@ func runCmd(staticConfiguration *static.Configuration) error { if staticConfiguration.Ping == nil || errHealthCheck == nil { if ok, _ := daemon.SdNotify(false, "WATCHDOG=1"); !ok { - log.WithoutContext().Error("Fail to tick watchdog") + log.Error().Msg("Fail to tick watchdog") } } else { - log.WithoutContext().Error(errHealthCheck) + log.Error().Err(errHealthCheck).Send() } } }) } svr.Wait() - log.WithoutContext().Info("Shutting down") + log.Info().Msg("Shutting down") return nil } @@ -209,14 +205,14 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err } if staticConfiguration.Pilot != nil { - log.WithoutContext().Warn("Traefik Pilot has been removed.") + log.Warn().Msg("Traefik Pilot has been removed.") } // Plugins pluginBuilder, err := createPluginBuilder(staticConfiguration) if err != nil { - log.WithoutContext().WithError(err).Error("Plugins are disabled because an error has occurred.") + log.Error().Err(err).Msg("Plugins are disabled because an error has occurred.") } // Providers plugins @@ -259,9 +255,8 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err var spiffeX509Source *workloadapi.X509Source if staticConfiguration.Spiffe != nil && staticConfiguration.Spiffe.WorkloadAPIAddr != "" { - log.WithoutContext(). - WithField("workloadAPIAddr", staticConfiguration.Spiffe.WorkloadAPIAddr). - Info("Waiting on SPIFFE SVID delivery") + log.Info().Str("workloadAPIAddr", staticConfiguration.Spiffe.WorkloadAPIAddr). + Msg("Waiting on SPIFFE SVID delivery") spiffeX509Source, err = workloadapi.NewX509Source( ctx, @@ -274,8 +269,7 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err if err != nil { return nil, fmt.Errorf("unable to create SPIFFE x509 source: %w", err) } - - log.WithoutContext().Info("Successfully obtained SPIFFE SVID.") + log.Info().Msg("Successfully obtained SPIFFE SVID.") } roundTripperManager := service.NewRoundTripperManager(spiffeX509Source) @@ -365,7 +359,8 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err // "traefik-hub" is an allowed certificate resolver name in a Traefik Hub Experimental feature context. // It is used to activate its own certificate resolution, even though it is not a "classical" traefik certificate resolver. (staticConfiguration.Hub == nil || rt.TLS.CertResolver != "traefik-hub") { - log.WithoutContext().Errorf("Router %s uses a non-existent certificate resolver: %s", rtName, rt.TLS.CertResolver) + log.Error().Err(err).Str(logs.RouterName, rtName).Str("certificateResolver", rt.TLS.CertResolver). + Msg("Router uses a non-existent certificate resolver") } } }) @@ -411,7 +406,7 @@ func getDefaultsEntrypoints(staticConfiguration *static.Configuration) []string protocol, err := cfg.GetProtocol() if err != nil { // Should never happen because Traefik should not start if protocol is invalid. - log.WithoutContext().Errorf("Invalid protocol: %v", err) + log.Error().Err(err).Msg("Invalid protocol") } if protocol != "udp" && name != static.DefaultInternalEntryPointName { @@ -457,7 +452,7 @@ func initACMEProvider(c *static.Configuration, providerAggregator *aggregator.Pr } if err := providerAggregator.AddProvider(p); err != nil { - log.WithoutContext().Errorf("The ACME resolver %q is skipped from the resolvers list because: %v", name, err) + log.Error().Err(err).Str("resolver", name).Msg("The ACME resolve is skipped from the resolvers list") continue } @@ -482,7 +477,7 @@ func initTailscaleProviders(cfg *static.Configuration, providerAggregator *aggre tsProvider := &tailscale.Provider{ResolverName: name} if err := providerAggregator.AddProvider(tsProvider); err != nil { - log.WithoutContext().Errorf("Unable to create Tailscale provider %s: %v", name, err) + log.Error().Err(err).Str(logs.ProviderName, name).Msg("Unable to create Tailscale provider") continue } @@ -500,41 +495,46 @@ func registerMetricClients(metricsConfig *types.Metrics) []metrics.Registry { var registries []metrics.Registry if metricsConfig.Prometheus != nil { - ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "prometheus")) - prometheusRegister := metrics.RegisterPrometheus(ctx, metricsConfig.Prometheus) + logger := log.With().Str(logs.MetricsProviderName, "prometheus").Logger() + + prometheusRegister := metrics.RegisterPrometheus(logger.WithContext(context.Background()), metricsConfig.Prometheus) if prometheusRegister != nil { registries = append(registries, prometheusRegister) - log.FromContext(ctx).Debug("Configured Prometheus metrics") + logger.Debug().Msg("Configured Prometheus metrics") } } if metricsConfig.Datadog != nil { - ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "datadog")) - registries = append(registries, metrics.RegisterDatadog(ctx, metricsConfig.Datadog)) - log.FromContext(ctx).Debugf("Configured Datadog metrics: pushing to %s once every %s", + logger := log.With().Str(logs.MetricsProviderName, "datadog").Logger() + + registries = append(registries, metrics.RegisterDatadog(logger.WithContext(context.Background()), metricsConfig.Datadog)) + logger.Debug().Msgf("Configured Datadog metrics: pushing to %s once every %s", metricsConfig.Datadog.Address, metricsConfig.Datadog.PushInterval) } if metricsConfig.StatsD != nil { - ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "statsd")) - registries = append(registries, metrics.RegisterStatsd(ctx, metricsConfig.StatsD)) - log.FromContext(ctx).Debugf("Configured StatsD metrics: pushing to %s once every %s", + logger := log.With().Str(logs.MetricsProviderName, "statsd").Logger() + + registries = append(registries, metrics.RegisterStatsd(logger.WithContext(context.Background()), metricsConfig.StatsD)) + logger.Debug().Msgf("Configured StatsD metrics: pushing to %s once every %s", metricsConfig.StatsD.Address, metricsConfig.StatsD.PushInterval) } if metricsConfig.InfluxDB != nil { - ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "influxdb")) - registries = append(registries, metrics.RegisterInfluxDB(ctx, metricsConfig.InfluxDB)) - log.FromContext(ctx).Debugf("Configured InfluxDB metrics: pushing to %s once every %s", + logger := log.With().Str(logs.MetricsProviderName, "influxdb").Logger() + + registries = append(registries, metrics.RegisterInfluxDB(logger.WithContext(context.Background()), metricsConfig.InfluxDB)) + logger.Debug().Msgf("Configured InfluxDB metrics: pushing to %s once every %s", metricsConfig.InfluxDB.Address, metricsConfig.InfluxDB.PushInterval) } if metricsConfig.InfluxDB2 != nil { - ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "influxdb2")) - influxDB2Register := metrics.RegisterInfluxDB2(ctx, metricsConfig.InfluxDB2) + logger := log.With().Str(logs.MetricsProviderName, "influxdb2").Logger() + + influxDB2Register := metrics.RegisterInfluxDB2(logger.WithContext(context.Background()), metricsConfig.InfluxDB2) if influxDB2Register != nil { registries = append(registries, influxDB2Register) - log.FromContext(ctx).Debugf("Configured InfluxDB v2 metrics: pushing to %s (%s org/%s bucket) once every %s", + logger.Debug().Msgf("Configured InfluxDB v2 metrics: pushing to %s (%s org/%s bucket) once every %s", metricsConfig.InfluxDB2.Address, metricsConfig.InfluxDB2.Org, metricsConfig.InfluxDB2.Bucket, metricsConfig.InfluxDB2.PushInterval) } } @@ -563,7 +563,7 @@ func setupAccessLog(conf *types.AccessLog) *accesslog.Handler { accessLoggerMiddleware, err := accesslog.NewHandler(conf) if err != nil { - log.WithoutContext().Warnf("Unable to create access logger: %v", err) + log.Warn().Err(err).Msg("Unable to create access logger") return nil } @@ -583,7 +583,7 @@ func setupTracing(conf *static.Tracing) *tracing.Tracing { if conf.Zipkin != nil { if backend != nil { - log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Zipkin backend.") + log.Error().Msg("Multiple tracing backend are not supported: cannot create Zipkin backend.") } else { backend = conf.Zipkin } @@ -591,7 +591,7 @@ func setupTracing(conf *static.Tracing) *tracing.Tracing { if conf.Datadog != nil { if backend != nil { - log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Datadog backend.") + log.Error().Msg("Multiple tracing backend are not supported: cannot create Datadog backend.") } else { backend = conf.Datadog } @@ -599,7 +599,7 @@ func setupTracing(conf *static.Tracing) *tracing.Tracing { if conf.Instana != nil { if backend != nil { - log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Instana backend.") + log.Error().Msg("Multiple tracing backend are not supported: cannot create Instana backend.") } else { backend = conf.Instana } @@ -607,7 +607,7 @@ func setupTracing(conf *static.Tracing) *tracing.Tracing { if conf.Haystack != nil { if backend != nil { - log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Haystack backend.") + log.Error().Msg("Multiple tracing backend are not supported: cannot create Haystack backend.") } else { backend = conf.Haystack } @@ -615,14 +615,14 @@ func setupTracing(conf *static.Tracing) *tracing.Tracing { if conf.Elastic != nil { if backend != nil { - log.WithoutContext().Error("Multiple tracing backend are not supported: cannot create Elastic backend.") + log.Error().Msg("Multiple tracing backend are not supported: cannot create Elastic backend.") } else { backend = conf.Elastic } } if backend == nil { - log.WithoutContext().Debug("Could not initialize tracing, using Jaeger by default") + log.Debug().Msg("Could not initialize tracing, using Jaeger by default") defaultBackend := &jaeger.Config{} defaultBackend.SetDefaults() backend = defaultBackend @@ -630,65 +630,12 @@ func setupTracing(conf *static.Tracing) *tracing.Tracing { tracer, err := tracing.NewTracing(conf.ServiceName, conf.SpanNameLimit, backend) if err != nil { - log.WithoutContext().Warnf("Unable to create tracer: %v", err) + log.Warn().Err(err).Msg("Unable to create tracer") return nil } return tracer } -func configureLogging(staticConfiguration *static.Configuration) { - // configure default log flags - stdlog.SetFlags(stdlog.Lshortfile | stdlog.LstdFlags) - - // configure log level - // an explicitly defined log level always has precedence. if none is - // given and debug mode is disabled, the default is ERROR, and DEBUG - // otherwise. - levelStr := "error" - if staticConfiguration.Log != nil && staticConfiguration.Log.Level != "" { - levelStr = strings.ToLower(staticConfiguration.Log.Level) - } - - level, err := logrus.ParseLevel(levelStr) - if err != nil { - log.WithoutContext().Errorf("Error getting level: %v", err) - } - log.SetLevel(level) - - var logFile string - if staticConfiguration.Log != nil && len(staticConfiguration.Log.FilePath) > 0 { - logFile = staticConfiguration.Log.FilePath - } - - // configure log format - var formatter logrus.Formatter - if staticConfiguration.Log != nil && staticConfiguration.Log.Format == "json" { - formatter = &logrus.JSONFormatter{} - } else { - disableColors := len(logFile) > 0 - formatter = &logrus.TextFormatter{DisableColors: disableColors, FullTimestamp: true, DisableSorting: true} - } - log.SetFormatter(formatter) - - if len(logFile) > 0 { - dir := filepath.Dir(logFile) - - if err := os.MkdirAll(dir, 0o755); err != nil { - log.WithoutContext().Errorf("Failed to create log path %s: %s", dir, err) - } - - err = log.OpenFile(logFile) - logrus.RegisterExitHandler(func() { - if err := log.CloseFile(); err != nil { - log.WithoutContext().Errorf("Error while closing log: %v", err) - } - }) - if err != nil { - log.WithoutContext().Errorf("Error while opening log file %s: %v", logFile, err) - } - } -} - func checkNewVersion() { ticker := time.Tick(24 * time.Hour) safe.Go(func() { @@ -699,16 +646,16 @@ func checkNewVersion() { } func stats(staticConfiguration *static.Configuration) { - logger := log.WithoutContext() + logger := log.Info() if staticConfiguration.Global.SendAnonymousUsage { - logger.Info(`Stats collection is enabled.`) - logger.Info(`Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration.`) - logger.Info(`Help us improve Traefik by leaving this feature on :)`) - logger.Info(`More details on: https://doc.traefik.io/traefik/contributing/data-collection/`) + logger.Msg(`Stats collection is enabled.`) + logger.Msg(`Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration.`) + logger.Msg(`Help us improve Traefik by leaving this feature on :)`) + logger.Msg(`More details on: https://doc.traefik.io/traefik/contributing/data-collection/`) collect(staticConfiguration) } else { - logger.Info(` + logger.Msg(` Stats collection is disabled. Help us improve Traefik by turning this feature on :) More details on: https://doc.traefik.io/traefik/contributing/data-collection/ @@ -721,7 +668,7 @@ func collect(staticConfiguration *static.Configuration) { safe.Go(func() { for time.Sleep(10 * time.Minute); ; <-ticker { if err := collector.Collect(staticConfiguration); err != nil { - log.WithoutContext().Debug(err) + log.Debug().Err(err).Send() } } }) diff --git a/docs/content/observability/logs.md b/docs/content/observability/logs.md index e1beea2a5..806d37b05 100644 --- a/docs/content/observability/logs.md +++ b/docs/content/observability/logs.md @@ -64,7 +64,7 @@ log: #### `level` -By default, the `level` is set to `ERROR`. Alternative logging levels are `DEBUG`, `PANIC`, `FATAL`, `ERROR`, `WARN`, and `INFO`. +By default, the `level` is set to `ERROR`. Alternative logging levels are `TRACE`, `DEBUG`, `PANIC`, `FATAL`, `ERROR`, `WARN`, and `INFO`. ```yaml tab="File (YAML)" log: @@ -80,10 +80,101 @@ log: --log.level=DEBUG ``` +#### `noColor` + +When using the 'common' format, disables the colorized output. + +```yaml tab="File (YAML)" +log: + noColor: true +``` + +```toml tab="File (TOML)" +[log] + noColor = true +``` + +```bash tab="CLI" +--log.nocolor=true +``` + ## Log Rotation -Traefik will close and reopen its log files, assuming they're configured, on receipt of a USR1 signal. -This allows the logs to be rotated and processed by an external program, such as `logrotate`. +The rotation of the log files can be configured with the following options. -!!! warning - This does not work on Windows due to the lack of USR signals. +### `maxSize` + +`maxSize` is the maximum size in megabytes of the log file before it gets rotated. +It defaults to 100 megabytes. + +```yaml tab="File (YAML)" +log: + maxSize: 1 +``` + +```toml tab="File (TOML)" +[log] + maxSize = 1 +``` + +```bash tab="CLI" +--log.maxsize=1 +``` + +### `maxBackups` + +`maxBackups` is the maximum number of old log files to retain. +The default is to retain all old log files (though `maxAge` may still cause them to get deleted). + +```yaml tab="File (YAML)" +log: + maxBackups: 3 +``` + +```toml tab="File (TOML)" +[log] + maxBackups = 3 +``` + +```bash tab="CLI" +--log.maxbackups=3 +``` + +### `maxAge` + +`maxAge` is the maximum number of days to retain old log files based on the timestamp encoded in their filename. +Note that a day is defined as 24 hours and may not exactly correspond to calendar days due to daylight savings, leap seconds, etc. +The default is not to remove old log files based on age. + +```yaml tab="File (YAML)" +log: + maxAge: 3 +``` + +```toml tab="File (TOML)" +[log] + maxAge = 3 +``` + +```bash tab="CLI" +--log.maxage=3 +``` + +### `compress` + +`compress` determines if the rotated log files should be compressed using gzip. +The default is not to perform compression. + +```yaml tab="File (YAML)" +log: + compress: 3 +``` + +```toml tab="File (TOML)" +[log] + compress = 3 +``` + +```bash tab="CLI" +--log.compress=3 +``` diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index eb7831f52..88935c8cd 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -246,6 +246,9 @@ The TLS key for Traefik Proxy as a TLS client. `--log`: Traefik log settings. (Default: ```false```) +`--log.compress`: +Determines if the rotated log files should be compressed using gzip. (Default: ```false```) + `--log.filepath`: Traefik log file path. Stdout is used when omitted or empty. @@ -255,6 +258,18 @@ Traefik log format: json | common (Default: ```common```) `--log.level`: Log level set to traefik logs. (Default: ```ERROR```) +`--log.maxage`: +Maximum number of days to retain old log files based on the timestamp encoded in their filename. (Default: ```0```) + +`--log.maxbackups`: +Maximum number of old log files to retain. (Default: ```0```) + +`--log.maxsize`: +Maximum size in megabytes of the log file before it gets rotated. (Default: ```0```) + +`--log.nocolor`: +When using the 'common' format, disables the colorized output. (Default: ```false```) + `--metrics.datadog`: Datadog metrics exporter type. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index e23990497..0ea3aee87 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -246,6 +246,9 @@ The TLS key for Traefik Proxy as a TLS client. `TRAEFIK_LOG`: Traefik log settings. (Default: ```false```) +`TRAEFIK_LOG_COMPRESS`: +Determines if the rotated log files should be compressed using gzip. (Default: ```false```) + `TRAEFIK_LOG_FILEPATH`: Traefik log file path. Stdout is used when omitted or empty. @@ -255,6 +258,18 @@ Traefik log format: json | common (Default: ```common```) `TRAEFIK_LOG_LEVEL`: Log level set to traefik logs. (Default: ```ERROR```) +`TRAEFIK_LOG_MAXAGE`: +Maximum number of days to retain old log files based on the timestamp encoded in their filename. (Default: ```0```) + +`TRAEFIK_LOG_MAXBACKUPS`: +Maximum number of old log files to retain. (Default: ```0```) + +`TRAEFIK_LOG_MAXSIZE`: +Maximum size in megabytes of the log file before it gets rotated. (Default: ```0```) + +`TRAEFIK_LOG_NOCOLOR`: +When using the 'common' format, disables the colorized output. (Default: ```false```) + `TRAEFIK_METRICS_DATADOG`: Datadog metrics exporter type. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index 4f8f847f2..4782c6cc9 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -326,8 +326,13 @@ [log] level = "foobar" - filePath = "foobar" format = "foobar" + noColor = true + filePath = "foobar" + maxSize = 42 + maxBackups = 42 + maxAge = 42 + compress = true [accessLog] filePath = "foobar" diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index d668d7ac3..55bfbf131 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -352,8 +352,13 @@ ping: terminatingStatusCode: 42 log: level: foobar - filePath: foobar format: foobar + noColor: true + filePath: foobar + maxSize: 42 + maxBackups: 42 + maxAge: 42 + compress: true accessLog: filePath: foobar format: foobar diff --git a/go.mod b/go.mod index 8c15c0e84..b6ca40a0a 100644 --- a/go.mod +++ b/go.mod @@ -49,6 +49,7 @@ require ( github.com/mitchellh/copystructure v1.0.0 github.com/mitchellh/hashstructure v1.0.0 github.com/mitchellh/mapstructure v1.5.0 + github.com/natefinch/lumberjack v0.0.0-20201021141957-47ffae23317c github.com/opentracing/opentracing-go v1.2.0 github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5 github.com/openzipkin/zipkin-go v0.2.2 @@ -58,9 +59,10 @@ require ( github.com/prometheus/client_golang v1.12.2-0.20220704083116-e8f91604d835 github.com/prometheus/client_model v0.2.0 github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac - github.com/sirupsen/logrus v1.8.1 + github.com/rs/zerolog v1.28.0 + github.com/sirupsen/logrus v1.9.0 github.com/spiffe/go-spiffe/v2 v2.1.1 - github.com/stretchr/testify v1.8.0 + github.com/stretchr/testify v1.8.1 github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154 github.com/tailscale/tscert v0.0.0-20220316030059-54bbcb9f74e2 github.com/traefik/paerser v0.1.9 @@ -70,15 +72,15 @@ require ( github.com/unrolled/render v1.0.2 github.com/unrolled/secure v1.0.9 github.com/vdemeester/shakers v0.1.0 - github.com/vulcand/oxy v1.4.1 + github.com/vulcand/oxy/v2 v2.0.0-20221121151423-d5cb734e4467 github.com/vulcand/predicate v1.2.0 go.elastic.co/apm v1.13.1 go.elastic.co/apm/module/apmot v1.13.1 - golang.org/x/mod v0.4.2 - golang.org/x/net v0.0.0-20220927171203-f486391704dc - golang.org/x/text v0.3.7 + golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 + golang.org/x/net v0.1.0 + golang.org/x/text v0.4.0 golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 - golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 + golang.org/x/tools v0.1.12 google.golang.org/grpc v1.46.0 gopkg.in/DataDog/dd-trace-go.v1 v1.38.1 gopkg.in/fsnotify.v1 v1.4.7 @@ -141,7 +143,7 @@ require ( github.com/containerd/continuity v0.1.0 // indirect github.com/containerd/typeurl v1.0.2 // indirect github.com/coreos/go-semver v0.3.0 // indirect - github.com/coreos/go-systemd/v22 v22.3.2 // indirect + github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534 // indirect github.com/cpu/goacmedns v0.1.1 // indirect github.com/deepmap/oapi-codegen v1.9.1 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect @@ -292,7 +294,6 @@ require ( github.com/santhosh-tekuri/jsonschema v1.2.4 // indirect github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect - github.com/segmentio/fasthash v1.0.3 // indirect github.com/shopspring/decimal v1.2.0 // indirect github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect github.com/softlayer/softlayer-go v1.0.6 // indirect @@ -300,7 +301,7 @@ require ( github.com/spf13/cast v1.3.1 // indirect github.com/spf13/cobra v1.2.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/objx v0.4.0 // indirect + github.com/stretchr/objx v0.5.0 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 // indirect github.com/theupdateframework/notary v0.6.1 // indirect @@ -330,9 +331,9 @@ require ( golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 // indirect - golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect - golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect + golang.org/x/sys v0.1.0 // indirect + golang.org/x/term v0.1.0 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/api v0.44.0 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/go.sum b/go.sum index 7801b7c1b..cece3818e 100644 --- a/go.sum +++ b/go.sum @@ -488,8 +488,9 @@ github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pq github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534 h1:rtAn27wIbmOGUs7RIbVgPEjb31ehTVniDwPGXyMxm5U= +github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpu/goacmedns v0.1.1 h1:DM3H2NiN2oam7QljgGY5ygy4yDXhK5Z4JUnqaugs2C4= @@ -1553,6 +1554,8 @@ github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 h1:o6uBwrhM5C8Ll3MAAxrQxRHEu7FkapwTuI2WmL1rw4g= github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8= +github.com/natefinch/lumberjack v0.0.0-20201021141957-47ffae23317c h1:194MYKszq5DlJ73wpFuOTEsC/ryOOxt2F901D/07tec= +github.com/natefinch/lumberjack v0.0.0-20201021141957-47ffae23317c/go.mod h1:tanojtwrLPxkEzT+bGGz9kb6bm8+yVwgAE44c3v1Au4= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= @@ -1801,9 +1804,12 @@ github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XF github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.4.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY= +github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -1833,7 +1839,6 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUt github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= -github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/segmentio/kafka-go v0.4.29/go.mod h1:m1lXeqJtIFYZayv0shM/tjrAFljvWLTprxBHd+3PnaU= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= @@ -1875,8 +1880,9 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 h1:hp2CYQUINdZMHdvTdXtPOY2ainKl4IoMcpAXEf2xj3Q= @@ -1938,8 +1944,9 @@ github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -1950,8 +1957,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154 h1:XGopsea1Dw7ecQ8JscCNQXDGYAKDiWjDeXnpN/+BY9g= github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= @@ -2057,8 +2065,8 @@ github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgq github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= -github.com/vulcand/oxy v1.4.1 h1:8FUsbr5xhSJqNlSrpUBcw93WuZIEI9JUyvThB9YqqF8= -github.com/vulcand/oxy v1.4.1/go.mod h1:Yq8OBb0XWU/7nPSglwUH5LS2Pcp4yvad8SVayobZbSo= +github.com/vulcand/oxy/v2 v2.0.0-20221121151423-d5cb734e4467 h1:Dbv3KJLgwtDKLpCZzTf1ISeG5ZYudPaLfTdYi4O2dSU= +github.com/vulcand/oxy/v2 v2.0.0-20221121151423-d5cb734e4467/go.mod h1:0kOEB8mKzSeGHknF53gTM47UEvQnPoAPnM+58baqn2o= github.com/vulcand/predicate v1.2.0 h1:uFsW1gcnnR7R+QTID+FVcs0sSYlIGntoGOTb3rQJt50= github.com/vulcand/predicate v1.2.0/go.mod h1:VipoNYXny6c8N381zGUWkjuuNHiRbeAZhE7Qm9c+2GA= github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= @@ -2273,8 +2281,9 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2350,8 +2359,8 @@ golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220927171203-f486391704dc h1:FxpXZdoBqT8RjqTy6i1E8nXHhW21wK7ptQ/EPIGxzPQ= -golang.org/x/net v0.0.0-20220927171203-f486391704dc/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -2383,8 +2392,9 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2516,13 +2526,16 @@ golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2532,8 +2545,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2627,8 +2641,9 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 h1:BonxutuHCTL0rBDnZlKjpGIQFTjyUVTexFOdWkB6Fg0= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/integration/access_log_test.go b/integration/access_log_test.go index ac00e47a9..d2f5715db 100644 --- a/integration/access_log_test.go +++ b/integration/access_log_test.go @@ -12,8 +12,8 @@ import ( "time" "github.com/go-check/check" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/integration/try" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" checker "github.com/vdemeester/shakers" ) @@ -54,7 +54,7 @@ func (s *AccessLogSuite) TestAccessLog(c *check.C) { defer func() { traefikLog, err := os.ReadFile(traefikTestLogFile) c.Assert(err, checker.IsNil) - log.WithoutContext().Info(string(traefikLog)) + log.Info().Msg(string(traefikLog)) }() err := cmd.Start() @@ -262,7 +262,7 @@ func digestParts(resp *http.Response) map[string]string { func getMD5(data string) string { digest := md5.New() if _, err := digest.Write([]byte(data)); err != nil { - log.WithoutContext().Error(err) + log.Error().Err(err).Send() } return fmt.Sprintf("%x", digest.Sum(nil)) } @@ -270,7 +270,7 @@ func getMD5(data string) string { func getCnonce() string { b := make([]byte, 8) if _, err := io.ReadFull(rand.Reader, b); err != nil { - log.WithoutContext().Error(err) + log.Error().Err(err).Send() } return fmt.Sprintf("%x", b)[:16] } diff --git a/integration/fake_dns_server.go b/integration/fake_dns_server.go index f0dbfca1a..14aa295b0 100644 --- a/integration/fake_dns_server.go +++ b/integration/fake_dns_server.go @@ -6,7 +6,7 @@ import ( "os" "github.com/miekg/dns" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) type handler struct { @@ -17,14 +17,12 @@ type handler struct { // Simplified version of the Challenge Test Server from Boulder // https://github.com/letsencrypt/boulder/blob/a6597b9f120207eff192c3e4107a7e49972a0250/test/challtestsrv/dnsone.go#L40 func (s *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { - logger := log.WithoutContext() - m := new(dns.Msg) m.SetReply(r) m.Compress = false for _, q := range r.Question { - logger.Infof("Query -- [%s] %s", q.Name, dns.TypeToString[q.Qtype]) + log.Info().Msgf("Query -- [%s] %s", q.Name, dns.TypeToString[q.Qtype]) switch q.Qtype { case dns.TypeA: @@ -94,7 +92,7 @@ func (s *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { m.Ns = append(m.Ns, auth) if err := w.WriteMsg(m); err != nil { - logger.Fatalf("Failed to write message %v", err) + log.Fatal().Err(err).Msg("Failed to write message") } } @@ -106,9 +104,9 @@ func startFakeDNSServer(traefikIP string) *dns.Server { } go func() { - log.WithoutContext().Infof("Start a fake DNS server.") + log.Info().Msg("Start a fake DNS server.") if err := srv.ListenAndServe(); err != nil { - log.WithoutContext().Fatalf("Failed to set udp listener %v", err) + log.Fatal().Err(err).Msg("Failed to set udp listener") } }() diff --git a/integration/fixtures/acme/acme_base.toml b/integration/fixtures/acme/acme_base.toml index 75682d94b..01306cd70 100644 --- a/integration/fixtures/acme/acme_base.toml +++ b/integration/fixtures/acme/acme_base.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/acme/acme_domains.toml b/integration/fixtures/acme/acme_domains.toml index a88e634bc..a587ce7dc 100644 --- a/integration/fixtures/acme/acme_domains.toml +++ b/integration/fixtures/acme/acme_domains.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/acme/acme_multiple_resolvers.toml b/integration/fixtures/acme/acme_multiple_resolvers.toml index bd16de8c2..b2d41fae6 100644 --- a/integration/fixtures/acme/acme_multiple_resolvers.toml +++ b/integration/fixtures/acme/acme_multiple_resolvers.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/acme/acme_store_domains.toml b/integration/fixtures/acme/acme_store_domains.toml index 14bb799d9..22fa26de4 100644 --- a/integration/fixtures/acme/acme_store_domains.toml +++ b/integration/fixtures/acme/acme_store_domains.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/acme/acme_tcp.toml b/integration/fixtures/acme/acme_tcp.toml index 898eb859a..1cb7e7eaa 100644 --- a/integration/fixtures/acme/acme_tcp.toml +++ b/integration/fixtures/acme/acme_tcp.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/consul/simple.toml b/integration/fixtures/consul/simple.toml index d40f13db1..e47f45b34 100644 --- a/integration/fixtures/consul/simple.toml +++ b/integration/fixtures/consul/simple.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints.web] address = ":8000" diff --git a/integration/fixtures/consul_catalog/connect.toml b/integration/fixtures/consul_catalog/connect.toml index f093c499a..0b8d4b5d2 100644 --- a/integration/fixtures/consul_catalog/connect.toml +++ b/integration/fixtures/consul_catalog/connect.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/consul_catalog/connect_by_default.toml b/integration/fixtures/consul_catalog/connect_by_default.toml index 67f823ad4..f0c00b718 100644 --- a/integration/fixtures/consul_catalog/connect_by_default.toml +++ b/integration/fixtures/consul_catalog/connect_by_default.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/consul_catalog/connect_not_aware.toml b/integration/fixtures/consul_catalog/connect_not_aware.toml index 6a6c10d94..0efa4b880 100644 --- a/integration/fixtures/consul_catalog/connect_not_aware.toml +++ b/integration/fixtures/consul_catalog/connect_not_aware.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/consul_catalog/default_not_exposed.toml b/integration/fixtures/consul_catalog/default_not_exposed.toml index f47ba97db..6b5ce0b96 100644 --- a/integration/fixtures/consul_catalog/default_not_exposed.toml +++ b/integration/fixtures/consul_catalog/default_not_exposed.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/consul_catalog/simple.toml b/integration/fixtures/consul_catalog/simple.toml index 93265e7d9..435473c19 100644 --- a/integration/fixtures/consul_catalog/simple.toml +++ b/integration/fixtures/consul_catalog/simple.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/consul_catalog/simple_watch.toml b/integration/fixtures/consul_catalog/simple_watch.toml index 9f73dcaf1..701538657 100644 --- a/integration/fixtures/consul_catalog/simple_watch.toml +++ b/integration/fixtures/consul_catalog/simple_watch.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/custom_ping_termination_status_code.toml b/integration/fixtures/custom_ping_termination_status_code.toml index f234963ff..34a493f82 100644 --- a/integration/fixtures/custom_ping_termination_status_code.toml +++ b/integration/fixtures/custom_ping_termination_status_code.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] @@ -13,4 +14,4 @@ requestAcceptGraceTimeout = "10s" [ping] - terminatingStatusCode = 204 \ No newline at end of file + terminatingStatusCode = 204 diff --git a/integration/fixtures/docker/minimal.toml b/integration/fixtures/docker/minimal.toml index 8e6024d84..d12a5b519 100644 --- a/integration/fixtures/docker/minimal.toml +++ b/integration/fixtures/docker/minimal.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/docker/simple.toml b/integration/fixtures/docker/simple.toml index a2c0de53f..5248e67ef 100644 --- a/integration/fixtures/docker/simple.toml +++ b/integration/fixtures/docker/simple.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/error_pages/error.toml b/integration/fixtures/error_pages/error.toml index 12b38bca8..3e1e9f847 100644 --- a/integration/fixtures/error_pages/error.toml +++ b/integration/fixtures/error_pages/error.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/error_pages/simple.toml b/integration/fixtures/error_pages/simple.toml index a734098b9..a60f7393d 100644 --- a/integration/fixtures/error_pages/simple.toml +++ b/integration/fixtures/error_pages/simple.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/etcd/simple.toml b/integration/fixtures/etcd/simple.toml index f634fff60..995b087a1 100644 --- a/integration/fixtures/etcd/simple.toml +++ b/integration/fixtures/etcd/simple.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints.web] address = ":8000" diff --git a/integration/fixtures/file/56-simple-panic.toml b/integration/fixtures/file/56-simple-panic.toml index 09aadf0a1..b49084f7f 100644 --- a/integration/fixtures/file/56-simple-panic.toml +++ b/integration/fixtures/file/56-simple-panic.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/file/directory.toml b/integration/fixtures/file/directory.toml index b60354f0f..4896332d1 100644 --- a/integration/fixtures/file/directory.toml +++ b/integration/fixtures/file/directory.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/file/simple-hosts.toml b/integration/fixtures/file/simple-hosts.toml index e2f5485a1..22731d7bb 100644 --- a/integration/fixtures/file/simple-hosts.toml +++ b/integration/fixtures/file/simple-hosts.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/file/simple.toml b/integration/fixtures/file/simple.toml index 736eb4f2b..30ad3ef65 100644 --- a/integration/fixtures/file/simple.toml +++ b/integration/fixtures/file/simple.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/grpc/config.toml b/integration/fixtures/grpc/config.toml index 9d448ae5b..309c6dfcb 100644 --- a/integration/fixtures/grpc/config.toml +++ b/integration/fixtures/grpc/config.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [serversTransport] rootCAs = [ """{{ .CertContent }}""" ] diff --git a/integration/fixtures/grpc/config_h2c.toml b/integration/fixtures/grpc/config_h2c.toml index 683b72f58..76eb1d54d 100644 --- a/integration/fixtures/grpc/config_h2c.toml +++ b/integration/fixtures/grpc/config_h2c.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/grpc/config_h2c_termination.toml b/integration/fixtures/grpc/config_h2c_termination.toml index a51bcc21b..f902724dc 100644 --- a/integration/fixtures/grpc/config_h2c_termination.toml +++ b/integration/fixtures/grpc/config_h2c_termination.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.websecure] diff --git a/integration/fixtures/grpc/config_insecure.toml b/integration/fixtures/grpc/config_insecure.toml index 264360ad5..350e86cfc 100644 --- a/integration/fixtures/grpc/config_insecure.toml +++ b/integration/fixtures/grpc/config_insecure.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [serversTransport] insecureSkipVerify = true diff --git a/integration/fixtures/grpc/config_retry.toml b/integration/fixtures/grpc/config_retry.toml index 6f7a3a96a..c0dc5929c 100644 --- a/integration/fixtures/grpc/config_retry.toml +++ b/integration/fixtures/grpc/config_retry.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [serversTransport] rootCAs = [ """{{ .CertContent }}""" ] diff --git a/integration/fixtures/headers/basic.toml b/integration/fixtures/headers/basic.toml index 29b1eb79e..a28e6a7e1 100644 --- a/integration/fixtures/headers/basic.toml +++ b/integration/fixtures/headers/basic.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/headers/cors.toml b/integration/fixtures/headers/cors.toml index 3b0622e96..8f14c3a67 100644 --- a/integration/fixtures/headers/cors.toml +++ b/integration/fixtures/headers/cors.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/headers/secure.toml b/integration/fixtures/headers/secure.toml index 47404d616..6d6ad1cdc 100644 --- a/integration/fixtures/headers/secure.toml +++ b/integration/fixtures/headers/secure.toml @@ -7,6 +7,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/headers/secure_multiple.toml b/integration/fixtures/headers/secure_multiple.toml index 9603046e5..c84f98125 100644 --- a/integration/fixtures/headers/secure_multiple.toml +++ b/integration/fixtures/headers/secure_multiple.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/healthcheck/multiple-entrypoints.toml b/integration/fixtures/healthcheck/multiple-entrypoints.toml index 12bab7274..f2a6784ee 100644 --- a/integration/fixtures/healthcheck/multiple-entrypoints.toml +++ b/integration/fixtures/healthcheck/multiple-entrypoints.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.http1] diff --git a/integration/fixtures/healthcheck/multiple-routers-one-same-service.toml b/integration/fixtures/healthcheck/multiple-routers-one-same-service.toml index a2d4d5147..86243f825 100644 --- a/integration/fixtures/healthcheck/multiple-routers-one-same-service.toml +++ b/integration/fixtures/healthcheck/multiple-routers-one-same-service.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web1] diff --git a/integration/fixtures/healthcheck/port_overload.toml b/integration/fixtures/healthcheck/port_overload.toml index eb7accedd..2684d0ee8 100644 --- a/integration/fixtures/healthcheck/port_overload.toml +++ b/integration/fixtures/healthcheck/port_overload.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/healthcheck/propagate.toml b/integration/fixtures/healthcheck/propagate.toml index a5f11c2b4..1227bb4d8 100644 --- a/integration/fixtures/healthcheck/propagate.toml +++ b/integration/fixtures/healthcheck/propagate.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/healthcheck/propagate_no_healthcheck.toml b/integration/fixtures/healthcheck/propagate_no_healthcheck.toml index 6fb2a6432..4889bec1c 100644 --- a/integration/fixtures/healthcheck/propagate_no_healthcheck.toml +++ b/integration/fixtures/healthcheck/propagate_no_healthcheck.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/healthcheck/reload_with_healthcheck.toml b/integration/fixtures/healthcheck/reload_with_healthcheck.toml index d2e794c91..8e72e5db4 100644 --- a/integration/fixtures/healthcheck/reload_with_healthcheck.toml +++ b/integration/fixtures/healthcheck/reload_with_healthcheck.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/healthcheck/reload_without_healthcheck.toml b/integration/fixtures/healthcheck/reload_without_healthcheck.toml index 350cb4fd9..fa45f8b66 100644 --- a/integration/fixtures/healthcheck/reload_without_healthcheck.toml +++ b/integration/fixtures/healthcheck/reload_without_healthcheck.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/healthcheck/simple.toml b/integration/fixtures/healthcheck/simple.toml index a2338a8b0..219f81c44 100644 --- a/integration/fixtures/healthcheck/simple.toml +++ b/integration/fixtures/healthcheck/simple.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/http/simple.toml b/integration/fixtures/http/simple.toml index 36df1414a..b6136193e 100644 --- a/integration/fixtures/http/simple.toml +++ b/integration/fixtures/http/simple.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/https/clientca/https_1ca1config.toml b/integration/fixtures/https/clientca/https_1ca1config.toml index bfa9617ee..2b200ff20 100644 --- a/integration/fixtures/https/clientca/https_1ca1config.toml +++ b/integration/fixtures/https/clientca/https_1ca1config.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.websecure] diff --git a/integration/fixtures/https/clientca/https_2ca1config.toml b/integration/fixtures/https/clientca/https_2ca1config.toml index 5d2320416..78e8f67b8 100644 --- a/integration/fixtures/https/clientca/https_2ca1config.toml +++ b/integration/fixtures/https/clientca/https_2ca1config.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.websecure] @@ -49,4 +50,4 @@ [tls.options] [tls.options.default.clientAuth] - caFiles = ["fixtures/https/clientca/ca1and2.crt"] \ No newline at end of file + caFiles = ["fixtures/https/clientca/ca1and2.crt"] diff --git a/integration/fixtures/https/clientca/https_2ca2config.toml b/integration/fixtures/https/clientca/https_2ca2config.toml index 0530b52d2..1653970ad 100644 --- a/integration/fixtures/https/clientca/https_2ca2config.toml +++ b/integration/fixtures/https/clientca/https_2ca2config.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.websecure] diff --git a/integration/fixtures/https/dynamic_https_sni.toml b/integration/fixtures/https/dynamic_https_sni.toml index a06c7129a..9a3ce0251 100644 --- a/integration/fixtures/https/dynamic_https_sni.toml +++ b/integration/fixtures/https/dynamic_https_sni.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.websecure] diff --git a/integration/fixtures/https/dynamic_https_sni_default_cert.toml b/integration/fixtures/https/dynamic_https_sni_default_cert.toml index f954d9845..424f35781 100644 --- a/integration/fixtures/https/dynamic_https_sni_default_cert.toml +++ b/integration/fixtures/https/dynamic_https_sni_default_cert.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.websecure] diff --git a/integration/fixtures/https/https_domain_fronting.toml b/integration/fixtures/https/https_domain_fronting.toml index 80011ee8e..d60883b65 100644 --- a/integration/fixtures/https/https_domain_fronting.toml +++ b/integration/fixtures/https/https_domain_fronting.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints.websecure] address = ":4443" diff --git a/integration/fixtures/https/https_redirect.toml b/integration/fixtures/https/https_redirect.toml index 488e2bc00..52f2addb6 100644 --- a/integration/fixtures/https/https_redirect.toml +++ b/integration/fixtures/https/https_redirect.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/https/https_sni.toml b/integration/fixtures/https/https_sni.toml index bd034d468..5ea0dc268 100644 --- a/integration/fixtures/https/https_sni.toml +++ b/integration/fixtures/https/https_sni.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.websecure] diff --git a/integration/fixtures/https/https_sni_case_insensitive_dynamic.toml b/integration/fixtures/https/https_sni_case_insensitive_dynamic.toml index ef5814caf..718477cb3 100644 --- a/integration/fixtures/https/https_sni_case_insensitive_dynamic.toml +++ b/integration/fixtures/https/https_sni_case_insensitive_dynamic.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.websecure] diff --git a/integration/fixtures/https/https_sni_default_cert.toml b/integration/fixtures/https/https_sni_default_cert.toml index f954d9845..424f35781 100644 --- a/integration/fixtures/https/https_sni_default_cert.toml +++ b/integration/fixtures/https/https_sni_default_cert.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.websecure] diff --git a/integration/fixtures/https/https_sni_strict.toml b/integration/fixtures/https/https_sni_strict.toml index fca8d9656..c8e6af4ae 100644 --- a/integration/fixtures/https/https_sni_strict.toml +++ b/integration/fixtures/https/https_sni_strict.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.websecure] diff --git a/integration/fixtures/https/https_tls_options.toml b/integration/fixtures/https/https_tls_options.toml index e8eccf3a5..9eec70c17 100644 --- a/integration/fixtures/https/https_tls_options.toml +++ b/integration/fixtures/https/https_tls_options.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.websecure] diff --git a/integration/fixtures/https/rootcas/https.toml b/integration/fixtures/https/rootcas/https.toml index 37e450fc9..b2eff4091 100644 --- a/integration/fixtures/https/rootcas/https.toml +++ b/integration/fixtures/https/rootcas/https.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [serversTransport] # Use certificate in net/internal/testcert.go diff --git a/integration/fixtures/https/rootcas/https_with_file.toml b/integration/fixtures/https/rootcas/https_with_file.toml index 62a79ac11..3bb9c1bf4 100644 --- a/integration/fixtures/https/rootcas/https_with_file.toml +++ b/integration/fixtures/https/rootcas/https_with_file.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [serversTransport] # Use certificate in net/internal/testcert.go diff --git a/integration/fixtures/k8s_crd.toml b/integration/fixtures/k8s_crd.toml index 86e85ee91..f4e36a482 100644 --- a/integration/fixtures/k8s_crd.toml +++ b/integration/fixtures/k8s_crd.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [api] diff --git a/integration/fixtures/k8s_crd_label_selector.toml b/integration/fixtures/k8s_crd_label_selector.toml index ca7e51cbd..7e1edcae9 100644 --- a/integration/fixtures/k8s_crd_label_selector.toml +++ b/integration/fixtures/k8s_crd_label_selector.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [api] diff --git a/integration/fixtures/k8s_default.toml b/integration/fixtures/k8s_default.toml index f94ecf45b..baff67ac5 100644 --- a/integration/fixtures/k8s_default.toml +++ b/integration/fixtures/k8s_default.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [api] insecure = true diff --git a/integration/fixtures/k8s_gateway.toml b/integration/fixtures/k8s_gateway.toml index c0cc76e04..0649ab249 100644 --- a/integration/fixtures/k8s_gateway.toml +++ b/integration/fixtures/k8s_gateway.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [api] insecure = true diff --git a/integration/fixtures/k8s_ingress_label_selector.toml b/integration/fixtures/k8s_ingress_label_selector.toml index 86f411e98..8b38d9c21 100644 --- a/integration/fixtures/k8s_ingress_label_selector.toml +++ b/integration/fixtures/k8s_ingress_label_selector.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [api] insecure = true diff --git a/integration/fixtures/k8s_ingressclass.toml b/integration/fixtures/k8s_ingressclass.toml index 51848e026..a5293be3e 100644 --- a/integration/fixtures/k8s_ingressclass.toml +++ b/integration/fixtures/k8s_ingressclass.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [api] insecure = true diff --git a/integration/fixtures/marathon/simple.toml b/integration/fixtures/marathon/simple.toml index f8b4e7266..d43cdbc2e 100644 --- a/integration/fixtures/marathon/simple.toml +++ b/integration/fixtures/marathon/simple.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/mirror.toml b/integration/fixtures/mirror.toml index 55d0cf040..4c99f83b8 100644 --- a/integration/fixtures/mirror.toml +++ b/integration/fixtures/mirror.toml @@ -7,6 +7,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] diff --git a/integration/fixtures/multiple_provider.toml b/integration/fixtures/multiple_provider.toml index e5f972d38..a2684e2cc 100644 --- a/integration/fixtures/multiple_provider.toml +++ b/integration/fixtures/multiple_provider.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/multiprovider.toml b/integration/fixtures/multiprovider.toml index bc59d7fab..14aff0b8b 100644 --- a/integration/fixtures/multiprovider.toml +++ b/integration/fixtures/multiprovider.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [api] insecure = true diff --git a/integration/fixtures/proxy-protocol/with.toml b/integration/fixtures/proxy-protocol/with.toml index c47e97dc5..0c51207e0 100644 --- a/integration/fixtures/proxy-protocol/with.toml +++ b/integration/fixtures/proxy-protocol/with.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/proxy-protocol/without.toml b/integration/fixtures/proxy-protocol/without.toml index 71b982486..4346c9926 100644 --- a/integration/fixtures/proxy-protocol/without.toml +++ b/integration/fixtures/proxy-protocol/without.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/ratelimit/simple.toml b/integration/fixtures/ratelimit/simple.toml index aed8d0293..f89251cd9 100644 --- a/integration/fixtures/ratelimit/simple.toml +++ b/integration/fixtures/ratelimit/simple.toml @@ -7,6 +7,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/redis/simple.toml b/integration/fixtures/redis/simple.toml index 9fcfe670c..7864cfc28 100644 --- a/integration/fixtures/redis/simple.toml +++ b/integration/fixtures/redis/simple.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints.web] address = ":8000" diff --git a/integration/fixtures/reqacceptgrace.toml b/integration/fixtures/reqacceptgrace.toml index 945a7d168..1ffaf7e6d 100644 --- a/integration/fixtures/reqacceptgrace.toml +++ b/integration/fixtures/reqacceptgrace.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] diff --git a/integration/fixtures/rest/simple.toml b/integration/fixtures/rest/simple.toml index 8bf7ff14c..779ccffd0 100644 --- a/integration/fixtures/rest/simple.toml +++ b/integration/fixtures/rest/simple.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/rest/simple_secure.toml b/integration/fixtures/rest/simple_secure.toml index 312c8f628..a583eba6d 100644 --- a/integration/fixtures/rest/simple_secure.toml +++ b/integration/fixtures/rest/simple_secure.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/retry/backoff.toml b/integration/fixtures/retry/backoff.toml index a869c1c60..f9f56b73a 100644 --- a/integration/fixtures/retry/backoff.toml +++ b/integration/fixtures/retry/backoff.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/router_errors.toml b/integration/fixtures/router_errors.toml index c46c25f6e..7ef2be256 100644 --- a/integration/fixtures/router_errors.toml +++ b/integration/fixtures/router_errors.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.websecure] diff --git a/integration/fixtures/service_errors.toml b/integration/fixtures/service_errors.toml index be90ddf52..599f0b2ed 100644 --- a/integration/fixtures/service_errors.toml +++ b/integration/fixtures/service_errors.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.websecure] @@ -34,4 +35,4 @@ [http.services.service2] [http.services.service2.loadBalancer] [[http.services.service2.loadBalancer.servers]] - url = "http://127.0.0.1:9010" \ No newline at end of file + url = "http://127.0.0.1:9010" diff --git a/integration/fixtures/simple_auth.toml b/integration/fixtures/simple_auth.toml index 1edc7ea6b..64f3b18ee 100644 --- a/integration/fixtures/simple_auth.toml +++ b/integration/fixtures/simple_auth.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/simple_contenttype.toml b/integration/fixtures/simple_contenttype.toml index c76967f33..2743cd659 100644 --- a/integration/fixtures/simple_contenttype.toml +++ b/integration/fixtures/simple_contenttype.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] @@ -58,4 +59,4 @@ autoDetect=true [http.middlewares.noautodetect.contentType] -autoDetect=false \ No newline at end of file +autoDetect=false diff --git a/integration/fixtures/simple_stats.toml b/integration/fixtures/simple_stats.toml index eeb4c2533..4afe62839 100644 --- a/integration/fixtures/simple_stats.toml +++ b/integration/fixtures/simple_stats.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/simple_web.toml b/integration/fixtures/simple_web.toml index 1d17ccb57..ddb75e282 100644 --- a/integration/fixtures/simple_web.toml +++ b/integration/fixtures/simple_web.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/tcp/catch-all-no-tls-with-https.toml b/integration/fixtures/tcp/catch-all-no-tls-with-https.toml index 1b1071246..229a6bb00 100644 --- a/integration/fixtures/tcp/catch-all-no-tls-with-https.toml +++ b/integration/fixtures/tcp/catch-all-no-tls-with-https.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.tcp] diff --git a/integration/fixtures/tcp/catch-all-no-tls.toml b/integration/fixtures/tcp/catch-all-no-tls.toml index c052832e8..6ed733b5e 100644 --- a/integration/fixtures/tcp/catch-all-no-tls.toml +++ b/integration/fixtures/tcp/catch-all-no-tls.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.tcp] diff --git a/integration/fixtures/tcp/mixed.toml b/integration/fixtures/tcp/mixed.toml index eea3acabf..fccf30525 100644 --- a/integration/fixtures/tcp/mixed.toml +++ b/integration/fixtures/tcp/mixed.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.tcp] diff --git a/integration/fixtures/tcp/multi-tls-options.toml b/integration/fixtures/tcp/multi-tls-options.toml index f0b4a931c..877ebcc09 100644 --- a/integration/fixtures/tcp/multi-tls-options.toml +++ b/integration/fixtures/tcp/multi-tls-options.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.tcp] diff --git a/integration/fixtures/tcp/non-tls-fallback.toml b/integration/fixtures/tcp/non-tls-fallback.toml index 2043694a1..03d298a11 100644 --- a/integration/fixtures/tcp/non-tls-fallback.toml +++ b/integration/fixtures/tcp/non-tls-fallback.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.tcp] diff --git a/integration/fixtures/tcp/non-tls.toml b/integration/fixtures/tcp/non-tls.toml index 3b0b5efd5..df270f7e1 100644 --- a/integration/fixtures/tcp/non-tls.toml +++ b/integration/fixtures/tcp/non-tls.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.tcp] diff --git a/integration/fixtures/tcp/service_errors.toml b/integration/fixtures/tcp/service_errors.toml index b6949da71..98e552f6b 100644 --- a/integration/fixtures/tcp/service_errors.toml +++ b/integration/fixtures/tcp/service_errors.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.websecure] diff --git a/integration/fixtures/tcp/wrr.toml b/integration/fixtures/tcp/wrr.toml index b9d35e65c..b60164b67 100644 --- a/integration/fixtures/tcp/wrr.toml +++ b/integration/fixtures/tcp/wrr.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.tcp] diff --git a/integration/fixtures/throttling/simple.toml b/integration/fixtures/throttling/simple.toml index 889a35d09..668d4988b 100644 --- a/integration/fixtures/throttling/simple.toml +++ b/integration/fixtures/throttling/simple.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/timeout/forwarding_timeouts.toml b/integration/fixtures/timeout/forwarding_timeouts.toml index 0dc5d4933..363c02027 100644 --- a/integration/fixtures/timeout/forwarding_timeouts.toml +++ b/integration/fixtures/timeout/forwarding_timeouts.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [serversTransport.forwardingTimeouts] dialTimeout = "300ms" diff --git a/integration/fixtures/timeout/keepalive.toml b/integration/fixtures/timeout/keepalive.toml index a2b9637ef..421d7b639 100644 --- a/integration/fixtures/timeout/keepalive.toml +++ b/integration/fixtures/timeout/keepalive.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [serversTransport.forwardingTimeouts] idleConnTimeout = "{{ .IdleConnTimeout }}" diff --git a/integration/fixtures/tracing/simple-jaeger-collector.toml b/integration/fixtures/tracing/simple-jaeger-collector.toml index f5636d799..e858e2a57 100644 --- a/integration/fixtures/tracing/simple-jaeger-collector.toml +++ b/integration/fixtures/tracing/simple-jaeger-collector.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [api] insecure = true diff --git a/integration/fixtures/tracing/simple-jaeger.toml b/integration/fixtures/tracing/simple-jaeger.toml index 87a4fb67e..bf02ced6a 100644 --- a/integration/fixtures/tracing/simple-jaeger.toml +++ b/integration/fixtures/tracing/simple-jaeger.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [api] insecure = true diff --git a/integration/fixtures/tracing/simple-zipkin.toml b/integration/fixtures/tracing/simple-zipkin.toml index b5549bc15..ef935fa28 100644 --- a/integration/fixtures/tracing/simple-zipkin.toml +++ b/integration/fixtures/tracing/simple-zipkin.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [api] insecure = true diff --git a/integration/fixtures/udp/service_errors.toml b/integration/fixtures/udp/service_errors.toml index 3031f9f73..83564b1dc 100644 --- a/integration/fixtures/udp/service_errors.toml +++ b/integration/fixtures/udp/service_errors.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.websecure] diff --git a/integration/fixtures/udp/wrr.toml b/integration/fixtures/udp/wrr.toml index 463f2deba..f16515f51 100644 --- a/integration/fixtures/udp/wrr.toml +++ b/integration/fixtures/udp/wrr.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.udp] diff --git a/integration/fixtures/websocket/config.toml b/integration/fixtures/websocket/config.toml index 83a499ce7..5d97bcf43 100644 --- a/integration/fixtures/websocket/config.toml +++ b/integration/fixtures/websocket/config.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] [entryPoints.web] diff --git a/integration/fixtures/websocket/config_https.toml b/integration/fixtures/websocket/config_https.toml index 91549eeaa..cdc92b862 100644 --- a/integration/fixtures/websocket/config_https.toml +++ b/integration/fixtures/websocket/config_https.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [serversTransport] insecureSkipVerify=true diff --git a/integration/fixtures/wrr.toml b/integration/fixtures/wrr.toml index 67c6801fc..4f3fbc0b6 100644 --- a/integration/fixtures/wrr.toml +++ b/integration/fixtures/wrr.toml @@ -7,6 +7,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] diff --git a/integration/fixtures/wrr_sticky.toml b/integration/fixtures/wrr_sticky.toml index 0d63558c5..6bd76f2af 100644 --- a/integration/fixtures/wrr_sticky.toml +++ b/integration/fixtures/wrr_sticky.toml @@ -7,6 +7,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints] diff --git a/integration/fixtures/zookeeper/simple.toml b/integration/fixtures/zookeeper/simple.toml index 3b40dc169..e6fc06232 100644 --- a/integration/fixtures/zookeeper/simple.toml +++ b/integration/fixtures/zookeeper/simple.toml @@ -4,6 +4,7 @@ [log] level = "DEBUG" + noColor = true [entryPoints.web] address = ":8000" diff --git a/integration/grpc_test.go b/integration/grpc_test.go index ab1c7f899..a18975864 100644 --- a/integration/grpc_test.go +++ b/integration/grpc_test.go @@ -11,9 +11,9 @@ import ( "time" "github.com/go-check/check" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/integration/helloworld" "github.com/traefik/traefik/v2/integration/try" - "github.com/traefik/traefik/v2/pkg/log" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" @@ -52,7 +52,7 @@ func (s *myserver) StreamExample(in *helloworld.StreamExampleRequest, server hel } if err := server.Send(&helloworld.StreamExampleReply{Data: string(data)}); err != nil { - log.WithoutContext().Error(err) + log.Error().Err(err).Send() } <-s.stopStreamExample diff --git a/integration/integration_test.go b/integration/integration_test.go index af3d35ca1..d71409d38 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -8,6 +8,7 @@ import ( "flag" "fmt" "io/fs" + stdlog "log" "os" "os/exec" "path/filepath" @@ -27,7 +28,10 @@ import ( "github.com/docker/docker/client" "github.com/fatih/structs" "github.com/go-check/check" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" + "github.com/sirupsen/logrus" + "github.com/traefik/traefik/v2/pkg/logs" checker "github.com/vdemeester/shakers" ) @@ -38,12 +42,22 @@ var ( func Test(t *testing.T) { if !*integration { - log.WithoutContext().Info("Integration tests disabled.") + log.Info().Msg("Integration tests disabled.") return } - // TODO(mpl): very niche optimization: do not start tailscale if none of the - // wanted tests actually need it (e.g. KeepAliveSuite does not). + log.Logger = zerolog.New(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}). + With().Timestamp().Caller().Logger() + zerolog.SetGlobalLevel(zerolog.InfoLevel) + + // Global logrus replacement + logrus.StandardLogger().Out = logs.NoLevel(log.Logger, zerolog.DebugLevel) + + // configure default standard log. + stdlog.SetFlags(stdlog.Lshortfile | stdlog.LstdFlags) + stdlog.SetOutput(logs.NoLevel(log.Logger, zerolog.DebugLevel)) + + // TODO(mpl): very niche optimization: do not start tailscale if none of the wanted tests actually need it (e.g. KeepAliveSuite does not). var ( vpn *tailscaleNotSuite useVPN bool @@ -199,7 +213,7 @@ func (s *BaseSuite) cmdTraefik(args ...string) (*exec.Cmd, *bytes.Buffer) { func (s *BaseSuite) killCmd(cmd *exec.Cmd) { err := cmd.Process.Kill() if err != nil { - log.WithoutContext().Errorf("Kill: %v", err) + log.Error().Err(err).Msg("Kill") } time.Sleep(100 * time.Millisecond) @@ -221,40 +235,39 @@ func (s *BaseSuite) displayLogK3S() { if _, err := os.Stat(filePath); err == nil { content, errR := os.ReadFile(filePath) if errR != nil { - log.WithoutContext().Error(errR) + log.Error().Err(errR).Send() } - log.WithoutContext().Println(string(content)) + log.Print(string(content)) } - log.WithoutContext().Println() - log.WithoutContext().Println("################################") - log.WithoutContext().Println() + log.Print() + log.Print("################################") + log.Print() } func (s *BaseSuite) displayLogCompose(c *check.C) { if s.dockerComposeService == nil || s.composeProject == nil { - log.WithoutContext().Infof("%s: No docker compose logs.", c.TestName()) + log.Info().Str("testName", c.TestName()).Msg("No docker compose logs.") return } - log.WithoutContext().Infof("%s: docker compose logs: ", c.TestName()) + log.Info().Str("testName", c.TestName()).Msg("docker compose logs") - logWriter := log.WithoutContext().WriterLevel(log.GetLevel()) - logConsumer := formatter.NewLogConsumer(context.Background(), logWriter, false, true) + logConsumer := formatter.NewLogConsumer(context.Background(), logs.NoLevel(log.Logger, zerolog.InfoLevel), false, true) err := s.dockerComposeService.Logs(context.Background(), s.composeProject.Name, logConsumer, composeapi.LogOptions{}) c.Assert(err, checker.IsNil) - log.WithoutContext().Println() - log.WithoutContext().Println("################################") - log.WithoutContext().Println() + log.Print() + log.Print("################################") + log.Print() } func (s *BaseSuite) displayTraefikLog(c *check.C, output *bytes.Buffer) { if output == nil || output.Len() == 0 { - log.WithoutContext().Infof("%s: No Traefik logs.", c.TestName()) + log.Info().Str("testName", c.TestName()).Msg("No Traefik logs.") } else { - log.WithoutContext().Infof("%s: Traefik logs: ", c.TestName()) - log.WithoutContext().Infof(output.String()) + log.Info().Str("testName", c.TestName()). + Str("logs", output.String()).Msg("Traefik logs") } } @@ -351,7 +364,7 @@ func setupVPN(c *check.C, keyFile string) *tailscaleNotSuite { data, err := os.ReadFile(keyFile) if err != nil { if !errors.Is(err, fs.ErrNotExist) { - log.Fatal(err) + log.Fatal().Err(err).Send() } return nil } diff --git a/integration/k8s_test.go b/integration/k8s_test.go index 3762bf2b2..bfb73d93c 100644 --- a/integration/k8s_test.go +++ b/integration/k8s_test.go @@ -15,9 +15,9 @@ import ( "github.com/go-check/check" "github.com/pmezard/go-difflib/difflib" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/integration/try" "github.com/traefik/traefik/v2/pkg/api" - "github.com/traefik/traefik/v2/pkg/log" checker "github.com/vdemeester/shakers" ) @@ -57,7 +57,7 @@ func (s *K8sSuite) TearDownSuite(c *check.C) { for _, filename := range generatedFiles { if err := os.Remove(filename); err != nil { - log.WithoutContext().Warning(err) + log.Warn().Err(err).Send() } } } diff --git a/integration/log_rotation_test.go b/integration/log_rotation_test.go index 27cc6f370..241e09353 100644 --- a/integration/log_rotation_test.go +++ b/integration/log_rotation_test.go @@ -12,15 +12,12 @@ import ( "time" "github.com/go-check/check" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/integration/try" - "github.com/traefik/traefik/v2/pkg/log" checker "github.com/vdemeester/shakers" ) -const ( - traefikTestLogFileRotated = traefikTestLogFile + ".rotated" - traefikTestAccessLogFileRotated = traefikTestAccessLogFile + ".rotated" -) +const traefikTestAccessLogFileRotated = traefikTestAccessLogFile + ".rotated" // Log rotation integration test suite. type LogRotationSuite struct{ BaseSuite } @@ -35,14 +32,13 @@ func (s *LogRotationSuite) TearDownSuite(c *check.C) { generatedFiles := []string{ traefikTestLogFile, - traefikTestLogFileRotated, traefikTestAccessLogFile, traefikTestAccessLogFileRotated, } for _, filename := range generatedFiles { if err := os.Remove(filename); err != nil { - log.WithoutContext().Warning(err) + log.Warn().Err(err).Send() } } } @@ -104,48 +100,6 @@ func (s *LogRotationSuite) TestAccessLogRotation(c *check.C) { verifyEmptyErrorLog(c, traefikTestLogFile) } -func (s *LogRotationSuite) TestTraefikLogRotation(c *check.C) { - // Start Traefik - cmd, display := s.traefikCmd(withConfigFile("fixtures/traefik_log_config.toml")) - defer display(c) - defer displayTraefikLogFile(c, traefikTestLogFile) - - err := cmd.Start() - c.Assert(err, checker.IsNil) - defer s.killCmd(cmd) - - waitForTraefik(c, "server1") - - // Rename traefik log - err = os.Rename(traefikTestLogFile, traefikTestLogFileRotated) - c.Assert(err, checker.IsNil) - - // issue SIGUSR1 signal to server process - err = cmd.Process.Signal(syscall.SIGUSR1) - c.Assert(err, checker.IsNil) - - err = cmd.Process.Signal(syscall.SIGTERM) - c.Assert(err, checker.IsNil) - - // Allow time for switch to be processed - err = try.Do(3*time.Second, func() error { - _, err = os.Stat(traefikTestLogFile) - return err - }) - c.Assert(err, checker.IsNil) - - // we have at least 6 lines in traefik.log.rotated - lineCount := verifyLogLines(c, traefikTestLogFileRotated, 0, false) - - // GreaterOrEqualThan used to ensure test doesn't break - // If more log entries are output on startup - c.Assert(lineCount, checker.GreaterOrEqualThan, 5) - - // Verify traefik.log output as expected - lineCount = verifyLogLines(c, traefikTestLogFile, lineCount, false) - c.Assert(lineCount, checker.GreaterOrEqualThan, 7) -} - func logAccessLogFile(c *check.C, fileName string) { output, err := os.ReadFile(fileName) c.Assert(err, checker.IsNil) diff --git a/integration/simple_test.go b/integration/simple_test.go index fac915a27..287fe72e0 100644 --- a/integration/simple_test.go +++ b/integration/simple_test.go @@ -793,7 +793,7 @@ func (s *SimpleSuite) TestUDPServiceConfigErrors(c *check.C) { c.Assert(err, checker.IsNil) defer s.killCmd(cmd) - err = try.GetRequest("http://127.0.0.1:8080/api/udp/services", 1000*time.Millisecond, try.BodyContains(`["the udp service \"service1@file\" does not have any type defined"]`)) + err = try.GetRequest("http://127.0.0.1:8080/api/udp/services", 1000*time.Millisecond, try.BodyContains(`["the UDP service \"service1@file\" does not have any type defined"]`)) c.Assert(err, checker.IsNil) err = try.GetRequest("http://127.0.0.1:8080/api/udp/services/service1@file", 1000*time.Millisecond, try.BodyContains(`"status":"disabled"`)) diff --git a/integration/try/try.go b/integration/try/try.go index af54eb8f0..886459e1e 100644 --- a/integration/try/try.go +++ b/integration/try/try.go @@ -7,7 +7,7 @@ import ( "os" "time" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) const ( @@ -166,7 +166,7 @@ func doRequest(action timedAction, timeout time.Duration, request *http.Request, func applyCIMultiplier(timeout time.Duration) time.Duration { ci := os.Getenv("CI") if len(ci) > 0 { - log.Debug("Apply CI multiplier:", CITimeoutMultiplier) + log.Debug().Msgf("Apply CI multiplier: %d", CITimeoutMultiplier) return time.Duration(float64(timeout) * CITimeoutMultiplier) } return timeout diff --git a/internal/gendoc.go b/internal/gendoc.go index afc6320f9..397f700ee 100644 --- a/internal/gendoc.go +++ b/internal/gendoc.go @@ -10,12 +10,12 @@ import ( "strings" "github.com/BurntSushi/toml" + "github.com/rs/zerolog/log" "github.com/traefik/paerser/env" "github.com/traefik/paerser/flag" "github.com/traefik/paerser/generator" "github.com/traefik/paerser/parser" "github.com/traefik/traefik/v2/cmd" - "github.com/traefik/traefik/v2/pkg/log" ) func main() { @@ -27,7 +27,7 @@ func main() { } func genStaticConfDoc(outputFile, prefix string, encodeFn func(interface{}) ([]parser.Flat, error)) { - logger := log.WithoutContext().WithField("file", outputFile) + logger := log.With().Str("file", outputFile).Logger() element := &cmd.NewTraefikConfiguration().Configuration @@ -35,17 +35,17 @@ func genStaticConfDoc(outputFile, prefix string, encodeFn func(interface{}) ([]p flats, err := encodeFn(element) if err != nil { - logger.Fatal(err) + logger.Fatal().Err(err).Send() } err = os.RemoveAll(outputFile) if err != nil { - logger.Fatal(err) + logger.Fatal().Err(err).Send() } file, err := os.OpenFile(outputFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o666) if err != nil { - logger.Fatal(err) + logger.Fatal().Err(err).Send() } defer file.Close() @@ -86,7 +86,7 @@ THIS FILE MUST NOT BE EDITED BY HAND } if w.err != nil { - logger.Fatal(err) + logger.Fatal().Err(err).Send() } } @@ -108,19 +108,19 @@ func genKVDynConfDoc(outputFile string) { conf := map[string]interface{}{} _, err := toml.DecodeFile(dynConfPath, &conf) if err != nil { - log.Fatal(err) + log.Fatal().Err(err).Send() } file, err := os.Create(outputFile) if err != nil { - log.Fatal(err) + log.Fatal().Err(err).Send() } store := storeWriter{data: map[string]string{}} c := client{store: store} err = c.load("traefik", conf) if err != nil { - log.Fatal(err) + log.Fatal().Err(err).Send() } var keys []string diff --git a/pkg/api/handler.go b/pkg/api/handler.go index f0623d4cc..01ec20361 100644 --- a/pkg/api/handler.go +++ b/pkg/api/handler.go @@ -7,10 +7,10 @@ import ( "strings" "github.com/gorilla/mux" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/runtime" "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/version" ) @@ -138,7 +138,7 @@ func (h Handler) getRuntimeConfiguration(rw http.ResponseWriter, request *http.R err := json.NewEncoder(rw).Encode(result) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() http.Error(rw, err.Error(), http.StatusInternalServerError) } } diff --git a/pkg/api/handler_entrypoint.go b/pkg/api/handler_entrypoint.go index 38801e8c7..104ab3853 100644 --- a/pkg/api/handler_entrypoint.go +++ b/pkg/api/handler_entrypoint.go @@ -8,8 +8,8 @@ import ( "strconv" "github.com/gorilla/mux" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/log" ) type entryPointRepresentation struct { @@ -43,7 +43,7 @@ func (h Handler) getEntryPoints(rw http.ResponseWriter, request *http.Request) { err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } @@ -66,7 +66,7 @@ func (h Handler) getEntryPoint(rw http.ResponseWriter, request *http.Request) { err := json.NewEncoder(rw).Encode(result) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } diff --git a/pkg/api/handler_http.go b/pkg/api/handler_http.go index b2643cdfa..ebf35d206 100644 --- a/pkg/api/handler_http.go +++ b/pkg/api/handler_http.go @@ -9,8 +9,8 @@ import ( "strings" "github.com/gorilla/mux" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/tls" ) @@ -93,7 +93,7 @@ func (h Handler) getRouters(rw http.ResponseWriter, request *http.Request) { err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } @@ -113,7 +113,7 @@ func (h Handler) getRouter(rw http.ResponseWriter, request *http.Request) { err := json.NewEncoder(rw).Encode(result) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } @@ -145,7 +145,7 @@ func (h Handler) getServices(rw http.ResponseWriter, request *http.Request) { err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } @@ -165,7 +165,7 @@ func (h Handler) getService(rw http.ResponseWriter, request *http.Request) { err := json.NewEncoder(rw).Encode(result) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } @@ -197,7 +197,7 @@ func (h Handler) getMiddlewares(rw http.ResponseWriter, request *http.Request) { err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } @@ -217,7 +217,7 @@ func (h Handler) getMiddleware(rw http.ResponseWriter, request *http.Request) { err := json.NewEncoder(rw).Encode(result) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } diff --git a/pkg/api/handler_overview.go b/pkg/api/handler_overview.go index d04abbc87..7f423b09f 100644 --- a/pkg/api/handler_overview.go +++ b/pkg/api/handler_overview.go @@ -5,9 +5,9 @@ import ( "net/http" "reflect" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/runtime" "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/log" ) type schemeOverview struct { @@ -62,7 +62,7 @@ func (h Handler) getOverview(rw http.ResponseWriter, request *http.Request) { err := json.NewEncoder(rw).Encode(result) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } diff --git a/pkg/api/handler_tcp.go b/pkg/api/handler_tcp.go index 390e1179c..8efb13068 100644 --- a/pkg/api/handler_tcp.go +++ b/pkg/api/handler_tcp.go @@ -9,8 +9,8 @@ import ( "strings" "github.com/gorilla/mux" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/log" ) type tcpRouterRepresentation struct { @@ -86,7 +86,7 @@ func (h Handler) getTCPRouters(rw http.ResponseWriter, request *http.Request) { err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } @@ -106,7 +106,7 @@ func (h Handler) getTCPRouter(rw http.ResponseWriter, request *http.Request) { err := json.NewEncoder(rw).Encode(result) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } @@ -138,7 +138,7 @@ func (h Handler) getTCPServices(rw http.ResponseWriter, request *http.Request) { err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } @@ -158,7 +158,7 @@ func (h Handler) getTCPService(rw http.ResponseWriter, request *http.Request) { err := json.NewEncoder(rw).Encode(result) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } @@ -190,7 +190,7 @@ func (h Handler) getTCPMiddlewares(rw http.ResponseWriter, request *http.Request err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } @@ -210,7 +210,7 @@ func (h Handler) getTCPMiddleware(rw http.ResponseWriter, request *http.Request) err := json.NewEncoder(rw).Encode(result) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } diff --git a/pkg/api/handler_udp.go b/pkg/api/handler_udp.go index 4cfe465d9..13adfafea 100644 --- a/pkg/api/handler_udp.go +++ b/pkg/api/handler_udp.go @@ -9,8 +9,8 @@ import ( "strings" "github.com/gorilla/mux" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/log" ) type udpRouterRepresentation struct { @@ -70,7 +70,7 @@ func (h Handler) getUDPRouters(rw http.ResponseWriter, request *http.Request) { err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } @@ -90,7 +90,7 @@ func (h Handler) getUDPRouter(rw http.ResponseWriter, request *http.Request) { err := json.NewEncoder(rw).Encode(result) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } @@ -122,7 +122,7 @@ func (h Handler) getUDPServices(rw http.ResponseWriter, request *http.Request) { err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } @@ -142,7 +142,7 @@ func (h Handler) getUDPService(rw http.ResponseWriter, request *http.Request) { err := json.NewEncoder(rw).Encode(result) if err != nil { - log.FromContext(request.Context()).Error(err) + log.Ctx(request.Context()).Error().Err(err).Send() writeError(rw, err.Error(), http.StatusInternalServerError) } } diff --git a/pkg/cli/loader_env.go b/pkg/cli/loader_env.go index f40b342a2..d7412c5d3 100644 --- a/pkg/cli/loader_env.go +++ b/pkg/cli/loader_env.go @@ -5,9 +5,9 @@ import ( "os" "strings" + "github.com/rs/zerolog/log" "github.com/traefik/paerser/cli" "github.com/traefik/paerser/env" - "github.com/traefik/traefik/v2/pkg/log" ) // EnvLoader loads a configuration from all the environment variables prefixed with "TRAEFIK_". @@ -21,11 +21,11 @@ func (e *EnvLoader) Load(_ []string, cmd *cli.Command) (bool, error) { } if err := env.Decode(vars, env.DefaultNamePrefix, cmd.Configuration); err != nil { - log.WithoutContext().Debug("environment variables", strings.Join(vars, ", ")) - return false, fmt.Errorf("failed to decode configuration from environment variables: %w ", err) + log.Debug().Msgf("environment variables: %s", strings.Join(vars, ", ")) + return false, fmt.Errorf("failed to decode configuration from environment variables: %w", err) } - log.WithoutContext().Println("Configuration loaded from environment variables.") + log.Print("Configuration loaded from environment variables") return true, nil } diff --git a/pkg/cli/loader_file.go b/pkg/cli/loader_file.go index f01eb763f..f5f11fa51 100644 --- a/pkg/cli/loader_file.go +++ b/pkg/cli/loader_file.go @@ -4,10 +4,10 @@ import ( "os" "strings" + "github.com/rs/zerolog/log" "github.com/traefik/paerser/cli" "github.com/traefik/paerser/file" "github.com/traefik/paerser/flag" - "github.com/traefik/traefik/v2/pkg/log" ) // FileLoader loads a configuration from a file. @@ -52,11 +52,10 @@ func (f *FileLoader) Load(args []string, cmd *cli.Command) (bool, error) { return false, nil } - logger := log.WithoutContext() - logger.Printf("Configuration loaded from file: %s", configFile) + log.Printf("Configuration loaded from file: %s", configFile) content, _ := os.ReadFile(configFile) - logger.Debug(string(content)) + log.Debug().Str("configFile", configFile).Bytes("content", content).Send() return true, nil } diff --git a/pkg/cli/loader_flag.go b/pkg/cli/loader_flag.go index 097ff03a5..15136ad19 100644 --- a/pkg/cli/loader_flag.go +++ b/pkg/cli/loader_flag.go @@ -3,9 +3,9 @@ package cli import ( "fmt" + "github.com/rs/zerolog/log" "github.com/traefik/paerser/cli" "github.com/traefik/paerser/flag" - "github.com/traefik/traefik/v2/pkg/log" ) // FlagLoader loads configuration from flags. @@ -21,7 +21,7 @@ func (*FlagLoader) Load(args []string, cmd *cli.Command) (bool, error) { return false, fmt.Errorf("failed to decode configuration from flags: %w", err) } - log.WithoutContext().Println("Configuration loaded from flags.") + log.Print("Configuration loaded from flags") return true, nil } diff --git a/pkg/collector/collector.go b/pkg/collector/collector.go index 50ce0666d..49f679a93 100644 --- a/pkg/collector/collector.go +++ b/pkg/collector/collector.go @@ -10,8 +10,8 @@ import ( "time" "github.com/mitchellh/hashstructure" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/redactor" "github.com/traefik/traefik/v2/pkg/version" ) @@ -49,7 +49,7 @@ func createBody(staticConfiguration *static.Configuration) (*bytes.Buffer, error return nil, err } - log.WithoutContext().Infof("Anonymous stats sent to %s: %s", collectorURL, anonConfig) + log.Debug().Msgf("Anonymous stats sent to %s: %s", collectorURL, anonConfig) hashConf, err := hashstructure.Hash(staticConfiguration, nil) if err != nil { diff --git a/pkg/config/runtime/runtime.go b/pkg/config/runtime/runtime.go index 713541538..842072279 100644 --- a/pkg/config/runtime/runtime.go +++ b/pkg/config/runtime/runtime.go @@ -4,8 +4,9 @@ import ( "sort" "strings" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" ) // Status of the router/service. @@ -116,8 +117,6 @@ func (c *Configuration) PopulateUsedBy() { return } - logger := log.WithoutContext() - for routerName, routerInfo := range c.Routers { // lazily initialize Status in case caller forgot to do it if routerInfo.Status == "" { @@ -126,7 +125,7 @@ func (c *Configuration) PopulateUsedBy() { providerName := getProviderName(routerName) if providerName == "" { - logger.WithField(log.RouterName, routerName).Error("router name is not fully qualified") + log.Error().Str(logs.RouterName, routerName).Msg("Router name is not fully qualified") continue } @@ -171,7 +170,7 @@ func (c *Configuration) PopulateUsedBy() { providerName := getProviderName(routerName) if providerName == "" { - logger.WithField(log.RouterName, routerName).Error("tcp router name is not fully qualified") + log.Error().Str(logs.RouterName, routerName).Msg("TCP router name is not fully qualified") continue } @@ -208,7 +207,7 @@ func (c *Configuration) PopulateUsedBy() { providerName := getProviderName(routerName) if providerName == "" { - logger.WithField(log.RouterName, routerName).Error("udp router name is not fully qualified") + log.Error().Str(logs.RouterName, routerName).Msg("UDP router name is not fully qualified") continue } diff --git a/pkg/config/runtime/runtime_http.go b/pkg/config/runtime/runtime_http.go index 1361c701c..788a23a26 100644 --- a/pkg/config/runtime/runtime_http.go +++ b/pkg/config/runtime/runtime_http.go @@ -6,8 +6,9 @@ import ( "sort" "sync" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" ) // GetRoutersByEntryPoints returns all the http routers by entry points name and routers name. @@ -19,14 +20,14 @@ func (c *Configuration) GetRoutersByEntryPoints(ctx context.Context, entryPoints continue } - logger := log.FromContext(log.With(ctx, log.Str(log.RouterName, rtName))) + logger := log.Ctx(ctx).With().Str(logs.RouterName, rtName).Logger() entryPointsCount := 0 for _, entryPointName := range rt.EntryPoints { if !contains(entryPoints, entryPointName) { rt.AddError(fmt.Errorf("entryPoint %q doesn't exist", entryPointName), false) - logger.WithField(log.EntryPointName, entryPointName). - Errorf("entryPoint %q doesn't exist", entryPointName) + logger.Error().Str(logs.EntryPointName, entryPointName). + Msg("EntryPoint doesn't exist") continue } @@ -42,7 +43,7 @@ func (c *Configuration) GetRoutersByEntryPoints(ctx context.Context, entryPoints if entryPointsCount == 0 { rt.AddError(fmt.Errorf("no valid entryPoint for this router"), true) - logger.Error("no valid entryPoint for this router") + logger.Error().Msg("No valid entryPoint for this router") } rt.Using = unique(rt.Using) diff --git a/pkg/config/runtime/runtime_tcp.go b/pkg/config/runtime/runtime_tcp.go index 72a8b3a14..665da4525 100644 --- a/pkg/config/runtime/runtime_tcp.go +++ b/pkg/config/runtime/runtime_tcp.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" ) // GetTCPRoutersByEntryPoints returns all the tcp routers by entry points name and routers name. @@ -13,14 +14,14 @@ func (c *Configuration) GetTCPRoutersByEntryPoints(ctx context.Context, entryPoi entryPointsRouters := make(map[string]map[string]*TCPRouterInfo) for rtName, rt := range c.TCPRouters { - logger := log.FromContext(log.With(ctx, log.Str(log.RouterName, rtName))) + logger := log.Ctx(ctx).With().Str(logs.RouterName, rtName).Logger() entryPointsCount := 0 for _, entryPointName := range rt.EntryPoints { if !contains(entryPoints, entryPointName) { rt.AddError(fmt.Errorf("entryPoint %q doesn't exist", entryPointName), false) - logger.WithField(log.EntryPointName, entryPointName). - Errorf("entryPoint %q doesn't exist", entryPointName) + logger.Error().Str(logs.EntryPointName, entryPointName). + Msg("EntryPoint doesn't exist") continue } @@ -36,7 +37,7 @@ func (c *Configuration) GetTCPRoutersByEntryPoints(ctx context.Context, entryPoi if entryPointsCount == 0 { rt.AddError(fmt.Errorf("no valid entryPoint for this router"), true) - logger.Error("no valid entryPoint for this router") + logger.Error().Msg("No valid entryPoint for this router") } } diff --git a/pkg/config/runtime/runtime_udp.go b/pkg/config/runtime/runtime_udp.go index f75922c04..ed9a44814 100644 --- a/pkg/config/runtime/runtime_udp.go +++ b/pkg/config/runtime/runtime_udp.go @@ -4,8 +4,9 @@ import ( "context" "fmt" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" ) // GetUDPRoutersByEntryPoints returns all the UDP routers by entry points name and routers name. @@ -13,11 +14,11 @@ func (c *Configuration) GetUDPRoutersByEntryPoints(ctx context.Context, entryPoi entryPointsRouters := make(map[string]map[string]*UDPRouterInfo) for rtName, rt := range c.UDPRouters { - logger := log.FromContext(log.With(ctx, log.Str(log.RouterName, rtName))) + logger := log.Ctx(ctx).With().Str(logs.RouterName, rtName).Logger() eps := rt.EntryPoints if len(eps) == 0 { - logger.Debugf("No entryPoint defined for this router, using the default one(s) instead: %+v", entryPoints) + logger.Debug().Msgf("No entryPoint defined for this router, using the default one(s) instead: %+v", entryPoints) eps = entryPoints } @@ -25,8 +26,8 @@ func (c *Configuration) GetUDPRoutersByEntryPoints(ctx context.Context, entryPoi for _, entryPointName := range eps { if !contains(entryPoints, entryPointName) { rt.AddError(fmt.Errorf("entryPoint %q doesn't exist", entryPointName), false) - logger.WithField(log.EntryPointName, entryPointName). - Errorf("entryPoint %q doesn't exist", entryPointName) + logger.Error().Str(logs.EntryPointName, entryPointName). + Msg("EntryPoint doesn't exist") continue } @@ -42,7 +43,7 @@ func (c *Configuration) GetUDPRoutersByEntryPoints(ctx context.Context, entryPoi if entryPointsCount == 0 { rt.AddError(fmt.Errorf("no valid entryPoint for this router"), true) - logger.Error("no valid entryPoint for this router") + logger.Error().Msg("No valid entryPoint for this router") } } diff --git a/pkg/config/static/hub.go b/pkg/config/static/hub.go index ee78de975..5cf97ae32 100644 --- a/pkg/config/static/hub.go +++ b/pkg/config/static/hub.go @@ -3,7 +3,8 @@ package static import ( "errors" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider/hub" ) @@ -18,7 +19,9 @@ func (c *Configuration) initHubProvider() error { ep.SetDefaults() ep.Address = ":9901" c.EntryPoints[hub.TunnelEntrypoint] = &ep - log.WithoutContext().Infof("The entryPoint %q is created on port 9901 to allow exposition of services.", hub.TunnelEntrypoint) + + log.Info().Str(logs.EntryPointName, hub.TunnelEntrypoint). + Msg("The entryPoint is created on port 9901 to allow exposition of services.") } if c.Hub.TLS == nil { @@ -34,7 +37,7 @@ func (c *Configuration) initHubProvider() error { } if c.Hub.TLS.Insecure { - log.WithoutContext().Warn("Hub is in `insecure` mode. Do not run in production with this setup.") + log.Warn().Msg("Hub is in `insecure` mode. Do not run in production with this setup.") } if _, ok := c.EntryPoints[hub.APIEntrypoint]; !ok { @@ -42,7 +45,9 @@ func (c *Configuration) initHubProvider() error { ep.SetDefaults() ep.Address = ":9900" c.EntryPoints[hub.APIEntrypoint] = &ep - log.WithoutContext().Infof("The entryPoint %q is created on port 9900 to allow Traefik to communicate with the Hub Agent for Traefik.", hub.APIEntrypoint) + + log.Info().Str(logs.EntryPointName, hub.APIEntrypoint). + Msg("The entryPoint is created on port 9900 to allow Traefik to communicate with the Hub Agent for Traefik.") } c.EntryPoints[hub.APIEntrypoint].HTTP.TLS = &TLSConfig{ diff --git a/pkg/config/static/static_config.go b/pkg/config/static/static_config.go index 4a2558b8b..dad5f9f5b 100644 --- a/pkg/config/static/static_config.go +++ b/pkg/config/static/static_config.go @@ -2,14 +2,14 @@ package static import ( "fmt" - stdlog "log" "strings" "time" legolog "github.com/go-acme/lego/v4/log" - "github.com/sirupsen/logrus" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/ping" acmeprovider "github.com/traefik/traefik/v2/pkg/provider/acme" "github.com/traefik/traefik/v2/pkg/provider/consulcatalog" @@ -242,9 +242,9 @@ func (c *Configuration) SetEffectiveConfiguration() { if c.Hub != nil { if err := c.initHubProvider(); err != nil { c.Hub = nil - log.WithoutContext().Errorf("Unable to activate the Hub provider: %v", err) + log.Error().Err(err).Msg("Unable to activate the Hub provider") } else { - log.WithoutContext().Debugf("Experimental Hub provider has been activated.") + log.Debug().Msg("Experimental Hub provider has been activated") } } @@ -278,14 +278,15 @@ func (c *Configuration) SetEffectiveConfiguration() { for epName, ep := range c.EntryPoints { if ep.HTTP3 != nil { ep.HTTP3 = nil - log.WithoutContext().Debugf("Disabling HTTP3 configuration for entryPoint %q: HTTP3 is disabled in the experimental configuration section", epName) + log.Debug().Str(logs.EntryPointName, epName). + Msgf("Disabling HTTP3 configuration for entryPoint %q: HTTP3 is disabled in the experimental configuration section", epName) } } } // Configure Gateway API provider if c.Providers.KubernetesGateway != nil { - log.WithoutContext().Debugf("Experimental Kubernetes Gateway provider has been activated") + log.Debug().Msg("Experimental Kubernetes Gateway provider has been activated") entryPoints := make(map[string]gateway.Entrypoint) for epName, entryPoint := range c.EntryPoints { entryPoints[epName] = gateway.Entrypoint{Address: entryPoint.GetAddress(), HasHTTPTLSConf: entryPoint.HTTP.TLS != nil} @@ -319,7 +320,8 @@ func (c *Configuration) initACMEProvider() { } } - legolog.Logger = stdlog.New(log.WithoutContext().WriterLevel(logrus.DebugLevel), "legolog: ", 0) + logger := logs.NoLevel(log.Logger, zerolog.DebugLevel).With().Str("lib", "lego").Logger() + legolog.Logger = logs.NewLogrusWrapper(logger) } // ValidateConfiguration validate that configuration is coherent. @@ -366,15 +368,13 @@ func getSafeACMECAServer(caServerSrc string) string { if strings.HasPrefix(caServerSrc, "https://acme-v01.api.letsencrypt.org") { caServer := strings.Replace(caServerSrc, "v01", "v02", 1) - log.WithoutContext(). - Warnf("The CA server %[1]q refers to a v01 endpoint of the ACME API, please change to %[2]q. Fallback to %[2]q.", caServerSrc, caServer) + log.Warn().Msgf("The CA server %[1]q refers to a v01 endpoint of the ACME API, please change to %[2]q. Fallback to %[2]q.", caServerSrc, caServer) return caServer } if strings.HasPrefix(caServerSrc, "https://acme-staging.api.letsencrypt.org") { caServer := strings.Replace(caServerSrc, "https://acme-staging.api.letsencrypt.org", "https://acme-staging-v02.api.letsencrypt.org", 1) - log.WithoutContext(). - Warnf("The CA server %[1]q refers to a v01 endpoint of the ACME API, please change to %[2]q. Fallback to %[2]q.", caServerSrc, caServer) + log.Warn().Msgf("The CA server %[1]q refers to a v01 endpoint of the ACME API, please change to %[2]q. Fallback to %[2]q.", caServerSrc, caServer) return caServer } diff --git a/pkg/healthcheck/healthcheck.go b/pkg/healthcheck/healthcheck.go index ca9a91069..ef19e30cb 100644 --- a/pkg/healthcheck/healthcheck.go +++ b/pkg/healthcheck/healthcheck.go @@ -11,9 +11,9 @@ import ( "time" gokitmetrics "github.com/go-kit/kit/metrics" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/log" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" @@ -55,22 +55,22 @@ type ServiceHealthChecker struct { } func NewServiceHealthChecker(ctx context.Context, metrics metricsHealthCheck, config *dynamic.ServerHealthCheck, service StatusSetter, info *runtime.ServiceInfo, transport http.RoundTripper, targets map[string]*url.URL) *ServiceHealthChecker { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) interval := time.Duration(config.Interval) if interval <= 0 { - logger.Error("Health check interval smaller than zero") + logger.Error().Msg("Health check interval smaller than zero") interval = time.Duration(dynamic.DefaultHealthCheckInterval) } timeout := time.Duration(config.Timeout) if timeout <= 0 { - logger.Error("Health check timeout smaller than zero") + logger.Error().Msg("Health check timeout smaller than zero") timeout = time.Duration(dynamic.DefaultHealthCheckTimeout) } if timeout >= interval { - logger.Warnf("Health check timeout should be lower than the health check interval. Interval set to timeout + 1 second (%s).", interval) + logger.Warn().Msgf("Health check timeout should be lower than the health check interval. Interval set to timeout + 1 second (%s).", interval) interval = timeout + time.Second } @@ -122,10 +122,10 @@ func (shc *ServiceHealthChecker) Launch(ctx context.Context) { return } - log.FromContext(ctx). - WithField("targetURL", target.String()). - WithError(err). - Warn("Health check failed.") + log.Ctx(ctx).Warn(). + Str("targetURL", target.String()). + Err(err). + Msg("Health check failed.") up = false serverUpMetricValue = float64(0) diff --git a/pkg/log/deprecated.go b/pkg/log/deprecated.go deleted file mode 100644 index 3bde3f841..000000000 --- a/pkg/log/deprecated.go +++ /dev/null @@ -1,133 +0,0 @@ -package log - -import ( - "bufio" - "io" - "runtime" - - "github.com/sirupsen/logrus" -) - -// Debug logs a message at level Debug on the standard logger. -// Deprecated: use log.FromContext(ctx).Debug(...) instead. -func Debug(args ...interface{}) { - mainLogger.Debug(args...) -} - -// Debugf logs a message at level Debug on the standard logger. -// Deprecated: use log.FromContext(ctx).Debugf(...) instead. -func Debugf(format string, args ...interface{}) { - mainLogger.Debugf(format, args...) -} - -// Info logs a message at level Info on the standard logger. -// Deprecated: use log.FromContext(ctx).Info(...) instead. -func Info(args ...interface{}) { - mainLogger.Info(args...) -} - -// Infof logs a message at level Info on the standard logger. -// Deprecated: use log.FromContext(ctx).Infof(...) instead. -func Infof(format string, args ...interface{}) { - mainLogger.Infof(format, args...) -} - -// Warn logs a message at level Warn on the standard logger. -// Deprecated: use log.FromContext(ctx).Warn(...) instead. -func Warn(args ...interface{}) { - mainLogger.Warn(args...) -} - -// Warnf logs a message at level Warn on the standard logger. -// Deprecated: use log.FromContext(ctx).Warnf(...) instead. -func Warnf(format string, args ...interface{}) { - mainLogger.Warnf(format, args...) -} - -// Error logs a message at level Error on the standard logger. -// Deprecated: use log.FromContext(ctx).Error(...) instead. -func Error(args ...interface{}) { - mainLogger.Error(args...) -} - -// Errorf logs a message at level Error on the standard logger. -// Deprecated: use log.FromContext(ctx).Errorf(...) instead. -func Errorf(format string, args ...interface{}) { - mainLogger.Errorf(format, args...) -} - -// Panic logs a message at level Panic on the standard logger. -// Deprecated: use log.FromContext(ctx).Panic(...) instead. -func Panic(args ...interface{}) { - mainLogger.Panic(args...) -} - -// Fatal logs a message at level Fatal on the standard logger. -// Deprecated: use log.FromContext(ctx).Fatal(...) instead. -func Fatal(args ...interface{}) { - mainLogger.Fatal(args...) -} - -// Fatalf logs a message at level Fatal on the standard logger. -// Deprecated: use log.FromContext(ctx).Fatalf(...) instead. -func Fatalf(format string, args ...interface{}) { - mainLogger.Fatalf(format, args...) -} - -// AddHook adds a hook to the standard logger hooks. -func AddHook(hook logrus.Hook) { - logrus.AddHook(hook) -} - -// CustomWriterLevel logs writer for a specific level. (with a custom scanner buffer size.) -// adapted from github.com/Sirupsen/logrus/writer.go. -func CustomWriterLevel(level logrus.Level, maxScanTokenSize int) *io.PipeWriter { - reader, writer := io.Pipe() - - var printFunc func(args ...interface{}) - - switch level { - case logrus.DebugLevel: - printFunc = Debug - case logrus.InfoLevel: - printFunc = Info - case logrus.WarnLevel: - printFunc = Warn - case logrus.ErrorLevel: - printFunc = Error - case logrus.FatalLevel: - printFunc = Fatal - case logrus.PanicLevel: - printFunc = Panic - default: - printFunc = mainLogger.Print - } - - go writerScanner(reader, maxScanTokenSize, printFunc) - runtime.SetFinalizer(writer, writerFinalizer) - - return writer -} - -// extract from github.com/Sirupsen/logrus/writer.go -// Hack the buffer size. -func writerScanner(reader io.ReadCloser, scanTokenSize int, printFunc func(args ...interface{})) { - scanner := bufio.NewScanner(reader) - - if scanTokenSize > bufio.MaxScanTokenSize { - buf := make([]byte, bufio.MaxScanTokenSize) - scanner.Buffer(buf, scanTokenSize) - } - - for scanner.Scan() { - printFunc(scanner.Text()) - } - if err := scanner.Err(); err != nil { - Errorf("Error while reading from Writer: %s", err) - } - reader.Close() -} - -func writerFinalizer(writer *io.PipeWriter) { - writer.Close() -} diff --git a/pkg/log/log.go b/pkg/log/log.go deleted file mode 100644 index 999a5e1fd..000000000 --- a/pkg/log/log.go +++ /dev/null @@ -1,144 +0,0 @@ -package log - -import ( - "context" - "fmt" - "io" - "os" - - "github.com/sirupsen/logrus" -) - -type contextKey int - -const ( - loggerKey contextKey = iota -) - -// Logger the Traefik logger. -type Logger interface { - logrus.FieldLogger - WriterLevel(logrus.Level) *io.PipeWriter -} - -var ( - mainLogger Logger - logFilePath string - logFile *os.File -) - -func init() { - mainLogger = logrus.StandardLogger() - logrus.SetOutput(os.Stdout) -} - -// SetLogger sets the logger. -func SetLogger(l Logger) { - mainLogger = l -} - -// SetOutput sets the standard logger output. -func SetOutput(out io.Writer) { - logrus.SetOutput(out) -} - -// SetFormatter sets the standard logger formatter. -func SetFormatter(formatter logrus.Formatter) { - logrus.SetFormatter(formatter) -} - -// SetLevel sets the standard logger level. -func SetLevel(level logrus.Level) { - logrus.SetLevel(level) -} - -// GetLevel returns the standard logger level. -func GetLevel() logrus.Level { - return logrus.GetLevel() -} - -// Str adds a string field. -func Str(key, value string) func(logrus.Fields) { - return func(fields logrus.Fields) { - fields[key] = value - } -} - -// With Adds fields. -func With(ctx context.Context, opts ...func(logrus.Fields)) context.Context { - logger := FromContext(ctx) - - fields := make(logrus.Fields) - for _, opt := range opts { - opt(fields) - } - logger = logger.WithFields(fields) - - return context.WithValue(ctx, loggerKey, logger) -} - -// FromContext Gets the logger from context. -func FromContext(ctx context.Context) Logger { - if ctx == nil { - panic("nil context") - } - - logger, ok := ctx.Value(loggerKey).(Logger) - if !ok { - logger = mainLogger - } - - return logger -} - -// WithoutContext Gets the main logger. -func WithoutContext() Logger { - return mainLogger -} - -// OpenFile opens the log file using the specified path. -func OpenFile(path string) error { - logFilePath = path - - var err error - logFile, err = os.OpenFile(logFilePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0o666) - if err != nil { - return err - } - - SetOutput(logFile) - return nil -} - -// CloseFile closes the log and sets the Output to stdout. -func CloseFile() error { - logrus.SetOutput(os.Stdout) - - if logFile != nil { - return logFile.Close() - } - return nil -} - -// RotateFile closes and reopens the log file to allow for rotation by an external source. -// If the log isn't backed by a file then it does nothing. -func RotateFile() error { - logger := FromContext(context.Background()) - - if logFile == nil && logFilePath == "" { - logger.Debug("Traefik log is not writing to a file, ignoring rotate request") - return nil - } - - if logFile != nil { - defer func(f *os.File) { - _ = f.Close() - }(logFile) - } - - if err := OpenFile(logFilePath); err != nil { - return fmt.Errorf("error opening log file: %w", err) - } - - return nil -} diff --git a/pkg/log/log_test.go b/pkg/log/log_test.go deleted file mode 100644 index c81724ff3..000000000 --- a/pkg/log/log_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package log - -import ( - "bytes" - "context" - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestLog(t *testing.T) { - testCases := []struct { - desc string - fields map[string]string - expected string - }{ - { - desc: "Log with one field", - fields: map[string]string{ - "foo": "bar", - }, - expected: ` level=error msg="message test" foo=bar$`, - }, - { - desc: "Log with two fields", - fields: map[string]string{ - "foo": "bar", - "oof": "rab", - }, - expected: ` level=error msg="message test" foo=bar oof=rab$`, - }, - { - desc: "Log without field", - fields: map[string]string{}, - expected: ` level=error msg="message test"$`, - }, - } - - for _, test := range testCases { - test := test - t.Run(test.desc, func(t *testing.T) { - var buffer bytes.Buffer - SetOutput(&buffer) - - ctx := context.Background() - - for key, value := range test.fields { - ctx = With(ctx, Str(key, value)) - } - - FromContext(ctx).Error("message test") - - assert.Regexp(t, test.expected, strings.TrimSpace(buffer.String())) - }) - } -} diff --git a/pkg/logs/aws.go b/pkg/logs/aws.go new file mode 100644 index 000000000..a4cc27469 --- /dev/null +++ b/pkg/logs/aws.go @@ -0,0 +1,16 @@ +package logs + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/rs/zerolog" +) + +func NewAWSWrapper(logger zerolog.Logger) aws.LoggerFunc { + if logger.GetLevel() > zerolog.DebugLevel { + return func(args ...interface{}) {} + } + + return func(args ...interface{}) { + logger.Debug().CallerSkipFrame(2).MsgFunc(msgFunc(args...)) + } +} diff --git a/pkg/logs/aws_test.go b/pkg/logs/aws_test.go new file mode 100644 index 000000000..6b38a680a --- /dev/null +++ b/pkg/logs/aws_test.go @@ -0,0 +1,17 @@ +package logs + +import ( + "os" + "testing" + "time" + + "github.com/rs/zerolog" +) + +func TestNewAWSWrapper(t *testing.T) { + out := zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339} + + logger := NewAWSWrapper(zerolog.New(out).With().Caller().Logger()) + + logger.Log("foo") +} diff --git a/pkg/logs/datadog.go b/pkg/logs/datadog.go new file mode 100644 index 000000000..f6fac925f --- /dev/null +++ b/pkg/logs/datadog.go @@ -0,0 +1,15 @@ +package logs + +import "github.com/rs/zerolog" + +type DatadogLogger struct { + logger zerolog.Logger +} + +func NewDatadogLogger(logger zerolog.Logger) *DatadogLogger { + return &DatadogLogger{logger: logger} +} + +func (d DatadogLogger) Log(msg string) { + d.logger.Debug().CallerSkipFrame(1).Msg(msg) +} diff --git a/pkg/logs/datadog_test.go b/pkg/logs/datadog_test.go new file mode 100644 index 000000000..a5aded73e --- /dev/null +++ b/pkg/logs/datadog_test.go @@ -0,0 +1,17 @@ +package logs + +import ( + "os" + "testing" + "time" + + "github.com/rs/zerolog" +) + +func TestNewDatadogLogger(t *testing.T) { + out := zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339} + + logger := NewDatadogLogger(zerolog.New(out).With().Caller().Logger()) + + logger.Log("foo") +} diff --git a/pkg/logs/elastic.go b/pkg/logs/elastic.go new file mode 100644 index 000000000..557ebf194 --- /dev/null +++ b/pkg/logs/elastic.go @@ -0,0 +1,19 @@ +package logs + +import "github.com/rs/zerolog" + +type ElasticLogger struct { + logger zerolog.Logger +} + +func NewElasticLogger(logger zerolog.Logger) *ElasticLogger { + return &ElasticLogger{logger: logger} +} + +func (l ElasticLogger) Debugf(format string, args ...interface{}) { + l.logger.Debug().CallerSkipFrame(1).Msgf(format, args...) +} + +func (l ElasticLogger) Errorf(format string, args ...interface{}) { + l.logger.Error().CallerSkipFrame(1).Msgf(format, args...) +} diff --git a/pkg/logs/elastic_test.go b/pkg/logs/elastic_test.go new file mode 100644 index 000000000..9e7a2aee3 --- /dev/null +++ b/pkg/logs/elastic_test.go @@ -0,0 +1,17 @@ +package logs + +import ( + "os" + "testing" + "time" + + "github.com/rs/zerolog" +) + +func TestNewElasticLogger(t *testing.T) { + out := zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339} + + logger := NewElasticLogger(zerolog.New(out).With().Caller().Logger()) + + logger.Errorf("foo") +} diff --git a/pkg/log/fields.go b/pkg/logs/fields.go similarity index 90% rename from pkg/log/fields.go rename to pkg/logs/fields.go index ff113f6c9..27e05198f 100644 --- a/pkg/log/fields.go +++ b/pkg/logs/fields.go @@ -1,4 +1,4 @@ -package log +package logs // Log entry names. const ( @@ -12,6 +12,7 @@ const ( MetricsProviderName = "metricsProviderName" TracingProviderName = "tracingProviderName" ServerName = "serverName" + ServerIndex = "serverIndex" TLSStoreName = "tlsStoreName" ServersTransportName = "serversTransport" ) diff --git a/pkg/logs/gokit.go b/pkg/logs/gokit.go new file mode 100644 index 000000000..9940d861f --- /dev/null +++ b/pkg/logs/gokit.go @@ -0,0 +1,17 @@ +package logs + +import ( + kitlog "github.com/go-kit/kit/log" + "github.com/rs/zerolog" +) + +func NewGoKitWrapper(logger zerolog.Logger) kitlog.LoggerFunc { + if logger.GetLevel() > zerolog.DebugLevel { + return func(args ...interface{}) error { return nil } + } + + return func(args ...interface{}) error { + logger.Debug().CallerSkipFrame(2).MsgFunc(msgFunc(args...)) + return nil + } +} diff --git a/pkg/logs/gokit_test.go b/pkg/logs/gokit_test.go new file mode 100644 index 000000000..51a639812 --- /dev/null +++ b/pkg/logs/gokit_test.go @@ -0,0 +1,17 @@ +package logs + +import ( + "os" + "testing" + "time" + + "github.com/rs/zerolog" +) + +func TestNewGoKitWrapper(t *testing.T) { + out := zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339} + + logger := NewGoKitWrapper(zerolog.New(out).With().Caller().Logger()) + + _ = logger.Log("foo") +} diff --git a/pkg/logs/haystack.go b/pkg/logs/haystack.go new file mode 100644 index 000000000..6f3db7361 --- /dev/null +++ b/pkg/logs/haystack.go @@ -0,0 +1,28 @@ +package logs + +import ( + "github.com/rs/zerolog" +) + +type HaystackLogger struct { + logger zerolog.Logger +} + +func NewHaystackLogger(logger zerolog.Logger) *HaystackLogger { + return &HaystackLogger{logger: logger} +} + +// Error prints the error message. +func (l HaystackLogger) Error(format string, v ...interface{}) { + l.logger.Error().CallerSkipFrame(1).Msgf(format, v...) +} + +// Info prints the info message. +func (l HaystackLogger) Info(format string, v ...interface{}) { + l.logger.Info().CallerSkipFrame(1).Msgf(format, v...) +} + +// Debug prints the info message. +func (l HaystackLogger) Debug(format string, v ...interface{}) { + l.logger.Debug().CallerSkipFrame(1).Msgf(format, v...) +} diff --git a/pkg/logs/haystack_test.go b/pkg/logs/haystack_test.go new file mode 100644 index 000000000..c66a9b972 --- /dev/null +++ b/pkg/logs/haystack_test.go @@ -0,0 +1,17 @@ +package logs + +import ( + "os" + "testing" + "time" + + "github.com/rs/zerolog" +) + +func TestNewHaystackLogger(t *testing.T) { + out := zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339} + + logger := NewHaystackLogger(zerolog.New(out).With().Caller().Logger()) + + logger.Info("foo") +} diff --git a/pkg/logs/instana.go b/pkg/logs/instana.go new file mode 100644 index 000000000..be4f522d6 --- /dev/null +++ b/pkg/logs/instana.go @@ -0,0 +1,29 @@ +package logs + +import ( + "github.com/rs/zerolog" +) + +type InstanaLogger struct { + logger zerolog.Logger +} + +func NewInstanaLogger(logger zerolog.Logger) *InstanaLogger { + return &InstanaLogger{logger: logger} +} + +func (l InstanaLogger) Debug(args ...interface{}) { + l.logger.Debug().CallerSkipFrame(1).MsgFunc(msgFunc(args...)) +} + +func (l InstanaLogger) Info(args ...interface{}) { + l.logger.Info().CallerSkipFrame(1).MsgFunc(msgFunc(args...)) +} + +func (l InstanaLogger) Warn(args ...interface{}) { + l.logger.Warn().CallerSkipFrame(1).MsgFunc(msgFunc(args...)) +} + +func (l InstanaLogger) Error(args ...interface{}) { + l.logger.Error().CallerSkipFrame(1).MsgFunc(msgFunc(args...)) +} diff --git a/pkg/logs/instana_test.go b/pkg/logs/instana_test.go new file mode 100644 index 000000000..827f5a45b --- /dev/null +++ b/pkg/logs/instana_test.go @@ -0,0 +1,17 @@ +package logs + +import ( + "os" + "testing" + "time" + + "github.com/rs/zerolog" +) + +func TestNewInstanaLogger(t *testing.T) { + out := zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339} + + logger := NewInstanaLogger(zerolog.New(out).With().Caller().Logger()) + + logger.Info("foo") +} diff --git a/pkg/logs/jaeger.go b/pkg/logs/jaeger.go new file mode 100644 index 000000000..2faedc2fb --- /dev/null +++ b/pkg/logs/jaeger.go @@ -0,0 +1,23 @@ +package logs + +import ( + "github.com/rs/zerolog" +) + +// JaegerLogger is an implementation of the Logger interface that delegates to traefik log. +type JaegerLogger struct { + logger zerolog.Logger +} + +func NewJaegerLogger(logger zerolog.Logger) *JaegerLogger { + return &JaegerLogger{logger: logger} +} + +func (l *JaegerLogger) Error(msg string) { + l.logger.Error().CallerSkipFrame(1).Msg(msg) +} + +// Infof logs a message at debug priority. +func (l *JaegerLogger) Infof(msg string, args ...interface{}) { + l.logger.Debug().CallerSkipFrame(1).Msgf(msg, args...) +} diff --git a/pkg/logs/jaeger_test.go b/pkg/logs/jaeger_test.go new file mode 100644 index 000000000..768e8c777 --- /dev/null +++ b/pkg/logs/jaeger_test.go @@ -0,0 +1,17 @@ +package logs + +import ( + "os" + "testing" + "time" + + "github.com/rs/zerolog" +) + +func TestNewJaegerLogger(t *testing.T) { + out := zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339} + + logger := NewJaegerLogger(zerolog.New(out).With().Caller().Logger()) + + logger.Infof("foo") +} diff --git a/pkg/logs/log.go b/pkg/logs/log.go new file mode 100644 index 000000000..f83dc3be6 --- /dev/null +++ b/pkg/logs/log.go @@ -0,0 +1,35 @@ +package logs + +import ( + "fmt" + + "github.com/rs/zerolog" +) + +func NoLevel(logger zerolog.Logger, level zerolog.Level) zerolog.Logger { + return logger.Hook(NewNoLevelHook(logger.GetLevel(), level)) +} + +type NoLevelHook struct { + minLevel zerolog.Level + level zerolog.Level +} + +func NewNoLevelHook(minLevel zerolog.Level, level zerolog.Level) *NoLevelHook { + return &NoLevelHook{minLevel: minLevel, level: level} +} + +func (n NoLevelHook) Run(e *zerolog.Event, level zerolog.Level, _ string) { + if n.minLevel > n.level { + e.Discard() + return + } + + if level == zerolog.NoLevel { + e.Str("level", n.level.String()) + } +} + +func msgFunc(i ...any) func() string { + return func() string { return fmt.Sprint(i...) } +} diff --git a/pkg/logs/log_test.go b/pkg/logs/log_test.go new file mode 100644 index 000000000..14d749fad --- /dev/null +++ b/pkg/logs/log_test.go @@ -0,0 +1,17 @@ +package logs + +import ( + "os" + "testing" + "time" + + "github.com/rs/zerolog" +) + +func TestNoLevel(t *testing.T) { + out := zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339} + + logger := NoLevel(zerolog.New(out).With().Caller().Logger(), zerolog.DebugLevel) + + logger.Info().Msg("foo") +} diff --git a/pkg/logs/logrus.go b/pkg/logs/logrus.go new file mode 100644 index 000000000..68de8555b --- /dev/null +++ b/pkg/logs/logrus.go @@ -0,0 +1,49 @@ +package logs + +import ( + "github.com/rs/zerolog" +) + +type LogrusStdWrapper struct { + logger zerolog.Logger +} + +func NewLogrusWrapper(logger zerolog.Logger) *LogrusStdWrapper { + return &LogrusStdWrapper{logger: logger} +} + +func (l LogrusStdWrapper) Print(args ...interface{}) { + l.logger.Debug().CallerSkipFrame(1).MsgFunc(msgFunc(args...)) +} + +func (l LogrusStdWrapper) Printf(s string, args ...interface{}) { + l.logger.Debug().CallerSkipFrame(1).Msgf(s, args...) +} + +func (l LogrusStdWrapper) Println(args ...interface{}) { + l.logger.Debug().CallerSkipFrame(1).MsgFunc(msgFunc(args...)) +} + +func (l LogrusStdWrapper) Fatal(args ...interface{}) { + l.logger.Fatal().CallerSkipFrame(1).MsgFunc(msgFunc(args...)) +} + +func (l LogrusStdWrapper) Fatalf(s string, args ...interface{}) { + l.logger.Fatal().CallerSkipFrame(1).Msgf(s, args...) +} + +func (l LogrusStdWrapper) Fatalln(args ...interface{}) { + l.logger.Fatal().CallerSkipFrame(1).MsgFunc(msgFunc(args...)) +} + +func (l LogrusStdWrapper) Panic(args ...interface{}) { + l.logger.Panic().CallerSkipFrame(1).MsgFunc(msgFunc(args...)) +} + +func (l LogrusStdWrapper) Panicf(s string, args ...interface{}) { + l.logger.Panic().CallerSkipFrame(1).Msgf(s, args...) +} + +func (l LogrusStdWrapper) Panicln(args ...interface{}) { + l.logger.Panic().CallerSkipFrame(1).MsgFunc(msgFunc(args...)) +} diff --git a/pkg/logs/logrus_test.go b/pkg/logs/logrus_test.go new file mode 100644 index 000000000..cc3155044 --- /dev/null +++ b/pkg/logs/logrus_test.go @@ -0,0 +1,17 @@ +package logs + +import ( + "os" + "testing" + "time" + + "github.com/rs/zerolog" +) + +func TestNewLogrusStdWrapper(t *testing.T) { + out := zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339} + + logger := NewLogrusWrapper(zerolog.New(out).With().Caller().Logger()) + + logger.Println("foo") +} diff --git a/pkg/logs/oxy.go b/pkg/logs/oxy.go new file mode 100644 index 000000000..6f0f90aed --- /dev/null +++ b/pkg/logs/oxy.go @@ -0,0 +1,27 @@ +package logs + +import "github.com/rs/zerolog" + +type OxyWrapper struct { + logger zerolog.Logger +} + +func NewOxyWrapper(logger zerolog.Logger) *OxyWrapper { + return &OxyWrapper{logger: logger} +} + +func (l OxyWrapper) Debug(s string, i ...interface{}) { + l.logger.Debug().CallerSkipFrame(1).Msgf(s, i...) +} + +func (l OxyWrapper) Info(s string, i ...interface{}) { + l.logger.Info().CallerSkipFrame(1).Msgf(s, i...) +} + +func (l OxyWrapper) Warn(s string, i ...interface{}) { + l.logger.Warn().CallerSkipFrame(1).Msgf(s, i...) +} + +func (l OxyWrapper) Error(s string, i ...interface{}) { + l.logger.Error().CallerSkipFrame(1).Msgf(s, i...) +} diff --git a/pkg/logs/oxy_test.go b/pkg/logs/oxy_test.go new file mode 100644 index 000000000..4ce102893 --- /dev/null +++ b/pkg/logs/oxy_test.go @@ -0,0 +1,17 @@ +package logs + +import ( + "os" + "testing" + "time" + + "github.com/rs/zerolog" +) + +func TestNewOxyWrapper(t *testing.T) { + out := zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339} + + logger := NewOxyWrapper(zerolog.New(out).With().Caller().Logger()) + + logger.Info("foo") +} diff --git a/pkg/metrics/datadog.go b/pkg/metrics/datadog.go index 596bc700d..fce4c4cc4 100644 --- a/pkg/metrics/datadog.go +++ b/pkg/metrics/datadog.go @@ -4,9 +4,9 @@ import ( "context" "time" - kitlog "github.com/go-kit/kit/log" "github.com/go-kit/kit/metrics/dogstatsd" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/types" ) @@ -58,10 +58,7 @@ func RegisterDatadog(ctx context.Context, config *types.Datadog) Registry { config.Prefix = defaultMetricsPrefix } - datadogClient = dogstatsd.New(config.Prefix+".", kitlog.LoggerFunc(func(keyvals ...interface{}) error { - log.WithoutContext().WithField(log.MetricsProviderName, "datadog").Info(keyvals...) - return nil - })) + datadogClient = dogstatsd.New(config.Prefix+".", logs.NewGoKitWrapper(log.Logger.With().Str(logs.MetricsProviderName, "datadog").Logger())) initDatadogClient(ctx, config) diff --git a/pkg/metrics/influxdb.go b/pkg/metrics/influxdb.go index f9f5485b7..d90ec75fc 100644 --- a/pkg/metrics/influxdb.go +++ b/pkg/metrics/influxdb.go @@ -8,10 +8,10 @@ import ( "regexp" "time" - kitlog "github.com/go-kit/kit/log" "github.com/go-kit/kit/metrics/influx" influxdb "github.com/influxdata/influxdb1-client/v2" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/types" ) @@ -112,30 +112,30 @@ func RegisterInfluxDB(ctx context.Context, config *types.InfluxDB) Registry { // initInfluxDBClient creates a influxDBClient. func initInfluxDBClient(ctx context.Context, config *types.InfluxDB) *influx.Influx { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) // TODO deprecated: move this switch into configuration.SetEffectiveConfiguration when web provider will be removed. switch config.Protocol { case protocolUDP: if len(config.Database) > 0 || len(config.RetentionPolicy) > 0 { - logger.Warn("Database and RetentionPolicy options have no effect with UDP.") + logger.Warn().Msg("Database and RetentionPolicy options have no effect with UDP.") config.Database = "" config.RetentionPolicy = "" } case protocolHTTP: if u, err := url.Parse(config.Address); err == nil { if u.Scheme != "http" && u.Scheme != "https" { - logger.Warnf("InfluxDB address %s should specify a scheme (http or https): falling back on HTTP.", config.Address) + logger.Warn().Msgf("InfluxDB address %s should specify a scheme (http or https): falling back on HTTP.", config.Address) config.Address = "http://" + config.Address } } else { - logger.Errorf("Unable to parse the InfluxDB address %v: falling back on UDP.", err) + logger.Error().Err(err).Msg("Unable to parse the InfluxDB address: falling back on UDP.") config.Protocol = protocolUDP config.Database = "" config.RetentionPolicy = "" } default: - logger.Warnf("Unsupported protocol %s: falling back on UDP.", config.Protocol) + logger.Warn().Msgf("Unsupported protocol %s: falling back on UDP.", config.Protocol) config.Protocol = protocolUDP config.Database = "" config.RetentionPolicy = "" @@ -147,10 +147,8 @@ func initInfluxDBClient(ctx context.Context, config *types.InfluxDB) *influx.Inf Database: config.Database, RetentionPolicy: config.RetentionPolicy, }, - kitlog.LoggerFunc(func(keyvals ...interface{}) error { - log.WithoutContext().WithField(log.MetricsProviderName, "influxdb").Info(keyvals...) - return nil - })) + logs.NewGoKitWrapper(*logger), + ) } // initInfluxDBTicker initializes metrics pusher. @@ -190,10 +188,10 @@ func (w *influxDBWriter) Write(bp influxdb.BatchPoints) error { defer c.Close() if writeErr := c.Write(bp); writeErr != nil { - ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "influxdb")) - log.FromContext(ctx).Errorf("Error while writing to InfluxDB: %s", writeErr.Error()) + logger := log.With().Str(logs.MetricsProviderName, "influxdb").Logger() + logger.Error().Err(writeErr).Msg("Error while writing to InfluxDB") - if handleErr := w.handleWriteError(ctx, c, writeErr); handleErr != nil { + if handleErr := w.handleWriteError(logger.WithContext(context.Background()), c, writeErr); handleErr != nil { return handleErr } // Retry write after successful handling of writeErr @@ -232,9 +230,9 @@ func (w *influxDBWriter) handleWriteError(ctx context.Context, c influxdb.Client qStr = fmt.Sprintf("%s WITH NAME \"%s\"", qStr, w.config.RetentionPolicy) } - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) - logger.Debugf("InfluxDB database not found: attempting to create one with %s", qStr) + logger.Debug().Msgf("InfluxDB database not found: attempting to create one with %s", qStr) q := influxdb.NewQuery(qStr, "", "") response, queryErr := c.Query(q) @@ -242,10 +240,10 @@ func (w *influxDBWriter) handleWriteError(ctx context.Context, c influxdb.Client queryErr = response.Error() } if queryErr != nil { - logger.Errorf("Error while creating the InfluxDB database %s", queryErr) + logger.Error().Err(queryErr).Msg("Error while creating the InfluxDB database") return queryErr } - logger.Debugf("Successfully created the InfluxDB database %s", w.config.Database) + logger.Debug().Msgf("Successfully created the InfluxDB database %s", w.config.Database) return nil } diff --git a/pkg/metrics/influxdb2.go b/pkg/metrics/influxdb2.go index 27be18f2a..6cf02e8f7 100644 --- a/pkg/metrics/influxdb2.go +++ b/pkg/metrics/influxdb2.go @@ -5,14 +5,14 @@ import ( "errors" "time" - kitlog "github.com/go-kit/kit/log" "github.com/go-kit/kit/metrics/influx" influxdb2 "github.com/influxdata/influxdb-client-go/v2" influxdb2api "github.com/influxdata/influxdb-client-go/v2/api" "github.com/influxdata/influxdb-client-go/v2/api/write" influxdb2log "github.com/influxdata/influxdb-client-go/v2/log" influxdb "github.com/influxdata/influxdb1-client/v2" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/types" ) @@ -25,10 +25,12 @@ var ( // RegisterInfluxDB2 creates metrics exporter for InfluxDB2. func RegisterInfluxDB2(ctx context.Context, config *types.InfluxDB2) Registry { + logger := log.Ctx(ctx) + if influxDB2Client == nil { var err error if influxDB2Client, err = newInfluxDB2Client(config); err != nil { - log.FromContext(ctx).Error(err) + logger.Error().Err(err).Send() return nil } } @@ -37,10 +39,7 @@ func RegisterInfluxDB2(ctx context.Context, config *types.InfluxDB2) Registry { influxDB2Store = influx.New( config.AdditionalLabels, influxdb.BatchPointsConfig{}, - kitlog.LoggerFunc(func(kv ...interface{}) error { - log.FromContext(ctx).Error(kv...) - return nil - }), + logs.NewGoKitWrapper(*logger), ) influxDB2Ticker = time.NewTicker(time.Duration(config.PushInterval)) @@ -127,14 +126,13 @@ type influxDB2Writer struct { } func (w influxDB2Writer) Write(bp influxdb.BatchPoints) error { - ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "influxdb2")) - logger := log.FromContext(ctx) + logger := log.With().Str(logs.MetricsProviderName, "influxdb2").Logger() wps := make([]*write.Point, 0, len(bp.Points())) for _, p := range bp.Points() { fields, err := p.Fields() if err != nil { - logger.Errorf("Error while getting %s point fields: %s", p.Name(), err) + logger.Error().Err(err).Msgf("Error while getting %s point fields", p.Name()) continue } @@ -146,5 +144,7 @@ func (w influxDB2Writer) Write(bp influxdb.BatchPoints) error { )) } + ctx := logger.WithContext(context.Background()) + return w.wc.WritePoint(ctx, wps...) } diff --git a/pkg/metrics/prometheus.go b/pkg/metrics/prometheus.go index 324864087..edad9e6f7 100644 --- a/pkg/metrics/prometheus.go +++ b/pkg/metrics/prometheus.go @@ -11,8 +11,8 @@ import ( stdprometheus "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/collectors" "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/types" ) @@ -90,14 +90,14 @@ func RegisterPrometheus(ctx context.Context, config *types.Prometheus) Registry if err := promRegistry.Register(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{})); err != nil { var arErr stdprometheus.AlreadyRegisteredError if !errors.As(err, &arErr) { - log.FromContext(ctx).Warn("ProcessCollector is already registered") + log.Ctx(ctx).Warn().Msg("ProcessCollector is already registered") } } if err := promRegistry.Register(collectors.NewGoCollector()); err != nil { var arErr stdprometheus.AlreadyRegisteredError if !errors.As(err, &arErr) { - log.FromContext(ctx).Warn("GoCollector is already registered") + log.Ctx(ctx).Warn().Msg("GoCollector is already registered") } } @@ -306,15 +306,15 @@ func registerPromState(ctx context.Context) bool { return true } - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) var arErr stdprometheus.AlreadyRegisteredError if errors.As(err, &arErr) { - logger.Debug("Prometheus collector already registered.") + logger.Debug().Msg("Prometheus collector already registered.") return true } - logger.Errorf("Unable to register Traefik to Prometheus: %v", err) + logger.Error().Err(err).Msg("Unable to register Traefik to Prometheus") return false } diff --git a/pkg/metrics/statsd.go b/pkg/metrics/statsd.go index c84a7cf5a..2a1c80a9c 100644 --- a/pkg/metrics/statsd.go +++ b/pkg/metrics/statsd.go @@ -4,9 +4,9 @@ import ( "context" "time" - kitlog "github.com/go-kit/kit/log" "github.com/go-kit/kit/metrics/statsd" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/types" ) @@ -55,10 +55,7 @@ func RegisterStatsd(ctx context.Context, config *types.Statsd) Registry { config.Prefix = defaultMetricsPrefix } - statsdClient = statsd.New(config.Prefix+".", kitlog.LoggerFunc(func(keyvals ...interface{}) error { - log.WithoutContext().WithField(log.MetricsProviderName, "statsd").Info(keyvals...) - return nil - })) + statsdClient = statsd.New(config.Prefix+".", logs.NewGoKitWrapper(*log.Ctx(ctx))) if statsdTicker == nil { statsdTicker = initStatsdTicker(ctx, config) diff --git a/pkg/middlewares/accesslog/field_middleware.go b/pkg/middlewares/accesslog/field_middleware.go index b37e0dda9..a7a63f683 100644 --- a/pkg/middlewares/accesslog/field_middleware.go +++ b/pkg/middlewares/accesslog/field_middleware.go @@ -4,9 +4,10 @@ import ( "net/http" "time" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/middlewares/capture" - "github.com/vulcand/oxy/utils" + "github.com/vulcand/oxy/v2/utils" ) // FieldApply function hook to add data in accesslog. @@ -57,7 +58,7 @@ func AddOriginFields(rw http.ResponseWriter, req *http.Request, next http.Handle ctx := req.Context() capt, err := capture.FromContext(ctx) if err != nil { - log.FromContext(log.With(ctx, log.Str(log.MiddlewareType, "AccessLogs"))).Errorf("Could not get Capture: %v", err) + log.Ctx(ctx).Error().Err(err).Str(logs.MiddlewareType, "AccessLogs").Msg("Could not get Capture") return } diff --git a/pkg/middlewares/accesslog/logger.go b/pkg/middlewares/accesslog/logger.go index e5ade7b48..5c5b95dad 100644 --- a/pkg/middlewares/accesslog/logger.go +++ b/pkg/middlewares/accesslog/logger.go @@ -16,9 +16,10 @@ import ( "time" "github.com/containous/alice" + "github.com/rs/zerolog/log" "github.com/sirupsen/logrus" ptypes "github.com/traefik/paerser/types" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/middlewares/capture" traefiktls "github.com/traefik/traefik/v2/pkg/tls" "github.com/traefik/traefik/v2/pkg/types" @@ -94,7 +95,7 @@ func NewHandler(config *types.AccessLog) (*Handler, error) { case JSONFormat: formatter = new(logrus.JSONFormatter) default: - log.WithoutContext().Errorf("unsupported access log format: %q, defaulting to common format instead.", config.Format) + log.Error().Msgf("Unsupported access log format: %q, defaulting to common format instead.", config.Format) formatter = new(CommonLogFormatter) } @@ -125,7 +126,7 @@ func NewHandler(config *types.AccessLog) (*Handler, error) { if config.Filters != nil { if httpCodeRanges, err := types.NewHTTPCodeRanges(config.Filters.StatusCodes); err != nil { - log.WithoutContext().Errorf("Failed to create new HTTP code ranges: %s", err) + log.Error().Err(err).Msg("Failed to create new HTTP code ranges") } else { logHandler.httpCodeRanges = httpCodeRanges } @@ -233,9 +234,7 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request, next http ctx := req.Context() capt, err := capture.FromContext(ctx) if err != nil { - log.FromContext(log.With(ctx, log.Str(log.MiddlewareType, "AccessLogs"))). - WithError(err). - Errorf("Could not get Capture") + log.Ctx(ctx).Error().Err(err).Str(logs.MiddlewareType, "AccessLogs").Msg("Could not get Capture") return } diff --git a/pkg/middlewares/addprefix/add_prefix.go b/pkg/middlewares/addprefix/add_prefix.go index 13e4f9284..83c4b0648 100644 --- a/pkg/middlewares/addprefix/add_prefix.go +++ b/pkg/middlewares/addprefix/add_prefix.go @@ -7,7 +7,6 @@ import ( "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/tracing" ) @@ -25,7 +24,7 @@ type addPrefix struct { // New creates a new handler. func New(ctx context.Context, next http.Handler, config dynamic.AddPrefix, name string) (http.Handler, error) { - log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware") var result *addPrefix if len(config.Prefix) > 0 { @@ -46,16 +45,16 @@ func (a *addPrefix) GetTracingInformation() (string, ext.SpanKindEnum) { } func (a *addPrefix) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - logger := log.FromContext(middlewares.GetLoggerCtx(req.Context(), a.name, typeName)) + logger := middlewares.GetLogger(req.Context(), a.name, typeName) oldURLPath := req.URL.Path req.URL.Path = ensureLeadingSlash(a.prefix + req.URL.Path) - logger.Debugf("URL.Path is now %s (was %s).", req.URL.Path, oldURLPath) + logger.Debug().Msgf("URL.Path is now %s (was %s).", req.URL.Path, oldURLPath) if req.URL.RawPath != "" { oldURLRawPath := req.URL.RawPath req.URL.RawPath = ensureLeadingSlash(a.prefix + req.URL.RawPath) - logger.Debugf("URL.RawPath is now %s (was %s).", req.URL.RawPath, oldURLRawPath) + logger.Debug().Msgf("URL.RawPath is now %s (was %s).", req.URL.RawPath, oldURLRawPath) } req.RequestURI = req.URL.RequestURI() diff --git a/pkg/middlewares/auth/basic_auth.go b/pkg/middlewares/auth/basic_auth.go index b14a08061..b67eaf643 100644 --- a/pkg/middlewares/auth/basic_auth.go +++ b/pkg/middlewares/auth/basic_auth.go @@ -10,7 +10,6 @@ import ( goauth "github.com/abbot/go-http-auth" "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" "github.com/traefik/traefik/v2/pkg/tracing" @@ -31,7 +30,8 @@ type basicAuth struct { // NewBasic creates a basicAuth middleware. func NewBasic(ctx context.Context, next http.Handler, authConfig dynamic.BasicAuth, name string) (http.Handler, error) { - log.FromContext(middlewares.GetLoggerCtx(ctx, name, basicTypeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, name, basicTypeName).Debug().Msg("Creating middleware") + users, err := getUsers(authConfig.UsersFile, authConfig.Users, basicUserParser) if err != nil { return nil, err @@ -60,7 +60,7 @@ func (b *basicAuth) GetTracingInformation() (string, ext.SpanKindEnum) { } func (b *basicAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - logger := log.FromContext(middlewares.GetLoggerCtx(req.Context(), b.name, basicTypeName)) + logger := middlewares.GetLogger(req.Context(), b.name, basicTypeName) user, password, ok := req.BasicAuth() if ok { @@ -76,14 +76,14 @@ func (b *basicAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } if !ok { - logger.Debug("Authentication failed") + logger.Debug().Msg("Authentication failed") tracing.SetErrorWithEvent(req, "Authentication failed") b.auth.RequireAuth(rw, req) return } - logger.Debug("Authentication succeeded") + logger.Debug().Msg("Authentication succeeded") req.URL.User = url.User(user) if b.headerField != "" { @@ -91,7 +91,7 @@ func (b *basicAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } if b.removeHeader { - logger.Debug("Removing authorization header") + logger.Debug().Msg("Removing authorization header") req.Header.Del(authorizationHeader) } b.next.ServeHTTP(rw, req) diff --git a/pkg/middlewares/auth/digest_auth.go b/pkg/middlewares/auth/digest_auth.go index 454a97295..214e968ee 100644 --- a/pkg/middlewares/auth/digest_auth.go +++ b/pkg/middlewares/auth/digest_auth.go @@ -10,7 +10,6 @@ import ( goauth "github.com/abbot/go-http-auth" "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" "github.com/traefik/traefik/v2/pkg/tracing" @@ -31,7 +30,8 @@ type digestAuth struct { // NewDigest creates a digest auth middleware. func NewDigest(ctx context.Context, next http.Handler, authConfig dynamic.DigestAuth, name string) (http.Handler, error) { - log.FromContext(middlewares.GetLoggerCtx(ctx, name, digestTypeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, name, digestTypeName).Debug().Msg("Creating middleware") + users, err := getUsers(authConfig.UsersFile, authConfig.Users, digestUserParser) if err != nil { return nil, err @@ -59,7 +59,7 @@ func (d *digestAuth) GetTracingInformation() (string, ext.SpanKindEnum) { } func (d *digestAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - logger := log.FromContext(middlewares.GetLoggerCtx(req.Context(), d.name, digestTypeName)) + logger := middlewares.GetLogger(req.Context(), d.name, digestTypeName) username, authinfo := d.auth.CheckAuth(req) if username == "" { @@ -77,19 +77,19 @@ func (d *digestAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } if authinfo != nil && *authinfo == "stale" { - logger.Debug("Digest authentication failed, possibly because out of order requests") + logger.Debug().Msg("Digest authentication failed, possibly because out of order requests") tracing.SetErrorWithEvent(req, "Digest authentication failed, possibly because out of order requests") d.auth.RequireAuthStale(rw, req) return } - logger.Debug("Digest authentication failed") + logger.Debug().Msg("Digest authentication failed") tracing.SetErrorWithEvent(req, "Digest authentication failed") d.auth.RequireAuth(rw, req) return } - logger.Debug("Digest authentication succeeded") + logger.Debug().Msg("Digest authentication succeeded") req.URL.User = url.User(username) logData := accesslog.GetLogData(req) @@ -102,7 +102,7 @@ func (d *digestAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } if d.removeHeader { - logger.Debug("Removing the Authorization header") + logger.Debug().Msg("Removing the Authorization header") req.Header.Del(authorizationHeader) } d.next.ServeHTTP(rw, req) diff --git a/pkg/middlewares/auth/forward.go b/pkg/middlewares/auth/forward.go index a0cee86ce..b6adb3cb1 100644 --- a/pkg/middlewares/auth/forward.go +++ b/pkg/middlewares/auth/forward.go @@ -13,12 +13,11 @@ import ( "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/middlewares/connectionheader" "github.com/traefik/traefik/v2/pkg/tracing" - "github.com/vulcand/oxy/forward" - "github.com/vulcand/oxy/utils" + "github.com/vulcand/oxy/v2/forward" + "github.com/vulcand/oxy/v2/utils" ) const ( @@ -52,7 +51,7 @@ type forwardAuth struct { // NewForward creates a forward auth middleware. func NewForward(ctx context.Context, next http.Handler, config dynamic.ForwardAuth, name string) (http.Handler, error) { - log.FromContext(middlewares.GetLoggerCtx(ctx, name, forwardedTypeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, name, forwardedTypeName).Debug().Msg("Creating middleware") fa := &forwardAuth{ address: config.Address, @@ -98,13 +97,13 @@ func (fa *forwardAuth) GetTracingInformation() (string, ext.SpanKindEnum) { } func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - logger := log.FromContext(middlewares.GetLoggerCtx(req.Context(), fa.name, forwardedTypeName)) + logger := middlewares.GetLogger(req.Context(), fa.name, forwardedTypeName) forwardReq, err := http.NewRequest(http.MethodGet, fa.address, nil) tracing.LogRequest(tracing.GetSpan(req), forwardReq) if err != nil { logMessage := fmt.Sprintf("Error calling %s. Cause %s", fa.address, err) - logger.Debug(logMessage) + logger.Debug().Msg(logMessage) tracing.SetErrorWithEvent(req, logMessage) rw.WriteHeader(http.StatusInternalServerError) @@ -120,7 +119,7 @@ func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { forwardResponse, forwardErr := fa.client.Do(forwardReq) if forwardErr != nil { logMessage := fmt.Sprintf("Error calling %s. Cause: %s", fa.address, forwardErr) - logger.Debug(logMessage) + logger.Debug().Msg(logMessage) tracing.SetErrorWithEvent(req, logMessage) rw.WriteHeader(http.StatusInternalServerError) @@ -130,7 +129,7 @@ func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { body, readError := io.ReadAll(forwardResponse.Body) if readError != nil { logMessage := fmt.Sprintf("Error reading body %s. Cause: %s", fa.address, readError) - logger.Debug(logMessage) + logger.Debug().Msg(logMessage) tracing.SetErrorWithEvent(req, logMessage) rw.WriteHeader(http.StatusInternalServerError) @@ -141,7 +140,7 @@ func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { // Pass the forward response's body and selected headers if it // didn't return a response within the range of [200, 300). if forwardResponse.StatusCode < http.StatusOK || forwardResponse.StatusCode >= http.StatusMultipleChoices { - logger.Debugf("Remote error %s. StatusCode: %d", fa.address, forwardResponse.StatusCode) + logger.Debug().Msgf("Remote error %s. StatusCode: %d", fa.address, forwardResponse.StatusCode) utils.CopyHeaders(rw.Header(), forwardResponse.Header) utils.RemoveHeaders(rw.Header(), hopHeaders...) @@ -152,7 +151,7 @@ func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if err != nil { if !errors.Is(err, http.ErrNoLocation) { logMessage := fmt.Sprintf("Error reading response location header %s. Cause: %s", fa.address, err) - logger.Debug(logMessage) + logger.Debug().Msg(logMessage) tracing.SetErrorWithEvent(req, logMessage) rw.WriteHeader(http.StatusInternalServerError) @@ -167,7 +166,7 @@ func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { rw.WriteHeader(forwardResponse.StatusCode) if _, err = rw.Write(body); err != nil { - logger.Error(err) + logger.Error().Err(err).Send() } return } diff --git a/pkg/middlewares/auth/forward_test.go b/pkg/middlewares/auth/forward_test.go index 1aeb5ef9a..4e17f7ff5 100644 --- a/pkg/middlewares/auth/forward_test.go +++ b/pkg/middlewares/auth/forward_test.go @@ -16,7 +16,7 @@ import ( tracingMiddleware "github.com/traefik/traefik/v2/pkg/middlewares/tracing" "github.com/traefik/traefik/v2/pkg/testhelpers" "github.com/traefik/traefik/v2/pkg/tracing" - "github.com/vulcand/oxy/forward" + "github.com/vulcand/oxy/v2/forward" ) func TestForwardAuthFail(t *testing.T) { diff --git a/pkg/middlewares/buffering/buffering.go b/pkg/middlewares/buffering/buffering.go index 5f6ea6b47..300052460 100644 --- a/pkg/middlewares/buffering/buffering.go +++ b/pkg/middlewares/buffering/buffering.go @@ -5,11 +5,12 @@ import ( "net/http" "github.com/opentracing/opentracing-go/ext" + "github.com/rs/zerolog" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/tracing" - oxybuffer "github.com/vulcand/oxy/buffer" + oxybuffer "github.com/vulcand/oxy/v2/buffer" ) const ( @@ -23,9 +24,9 @@ type buffer struct { // New creates a buffering middleware. func New(ctx context.Context, next http.Handler, config dynamic.Buffering, name string) (http.Handler, error) { - logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)) - logger.Debug("Creating middleware") - logger.Debugf("Setting up buffering: request limits: %d (mem), %d (max), response limits: %d (mem), %d (max) with retry: '%s'", + logger := middlewares.GetLogger(ctx, name, typeName) + logger.Debug().Msg("Creating middleware") + logger.Debug().Msgf("Setting up buffering: request limits: %d (mem), %d (max), response limits: %d (mem), %d (max) with retry: '%s'", config.MemRequestBodyBytes, config.MaxRequestBodyBytes, config.MemResponseBodyBytes, config.MaxResponseBodyBytes, config.RetryExpression) oxyBuffer, err := oxybuffer.New( @@ -34,7 +35,9 @@ func New(ctx context.Context, next http.Handler, config dynamic.Buffering, name oxybuffer.MaxRequestBodyBytes(config.MaxRequestBodyBytes), oxybuffer.MemResponseBodyBytes(config.MemResponseBodyBytes), oxybuffer.MaxResponseBodyBytes(config.MaxResponseBodyBytes), - oxybuffer.CondSetter(len(config.RetryExpression) > 0, oxybuffer.Retry(config.RetryExpression)), + oxybuffer.Logger(logs.NewOxyWrapper(*logger)), + oxybuffer.Verbose(logger.GetLevel() == zerolog.TraceLevel), + oxybuffer.Cond(len(config.RetryExpression) > 0, oxybuffer.Retry(config.RetryExpression)), ) if err != nil { return nil, err diff --git a/pkg/middlewares/chain/chain.go b/pkg/middlewares/chain/chain.go index 1f0419893..e5fd9aa93 100644 --- a/pkg/middlewares/chain/chain.go +++ b/pkg/middlewares/chain/chain.go @@ -6,7 +6,6 @@ import ( "github.com/containous/alice" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" ) @@ -20,7 +19,7 @@ type chainBuilder interface { // New creates a chain middleware. func New(ctx context.Context, next http.Handler, config dynamic.Chain, builder chainBuilder, name string) (http.Handler, error) { - log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware") middlewareChain := builder.BuildChain(ctx, config.Middlewares) return middlewareChain.Then(next) diff --git a/pkg/middlewares/circuitbreaker/circuit_breaker.go b/pkg/middlewares/circuitbreaker/circuit_breaker.go index 77b489e7b..8e3f3339b 100644 --- a/pkg/middlewares/circuitbreaker/circuit_breaker.go +++ b/pkg/middlewares/circuitbreaker/circuit_breaker.go @@ -6,11 +6,13 @@ import ( "time" "github.com/opentracing/opentracing-go/ext" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/tracing" - "github.com/vulcand/oxy/cbreaker" + "github.com/vulcand/oxy/v2/cbreaker" ) const typeName = "CircuitBreaker" @@ -24,19 +26,21 @@ type circuitBreaker struct { func New(ctx context.Context, next http.Handler, confCircuitBreaker dynamic.CircuitBreaker, name string) (http.Handler, error) { expression := confCircuitBreaker.Expression - logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)) - logger.Debug("Creating middleware") - logger.Debugf("Setting up with expression: %s", expression) + logger := middlewares.GetLogger(ctx, name, typeName) + logger.Debug().Msg("Creating middleware") + logger.Debug().Msgf("Setting up with expression: %s", expression) - cbOpts := []cbreaker.CircuitBreakerOption{ + cbOpts := []cbreaker.Option{ cbreaker.Fallback(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { tracing.SetErrorWithEvent(req, "blocked by circuit-breaker (%q)", expression) rw.WriteHeader(http.StatusServiceUnavailable) if _, err := rw.Write([]byte(http.StatusText(http.StatusServiceUnavailable))); err != nil { - log.FromContext(req.Context()).Error(err) + log.Ctx(req.Context()).Error().Err(err).Send() } })), + cbreaker.Logger(logs.NewOxyWrapper(*logger)), + cbreaker.Verbose(logger.GetLevel() == zerolog.TraceLevel), } if confCircuitBreaker.CheckPeriod > 0 { @@ -55,6 +59,7 @@ func New(ctx context.Context, next http.Handler, confCircuitBreaker dynamic.Circ if err != nil { return nil, err } + return &circuitBreaker{ circuitBreaker: oxyCircuitBreaker, name: name, diff --git a/pkg/middlewares/compress/compress.go b/pkg/middlewares/compress/compress.go index 55caa51b0..4db054d65 100644 --- a/pkg/middlewares/compress/compress.go +++ b/pkg/middlewares/compress/compress.go @@ -10,7 +10,6 @@ import ( "github.com/klauspost/compress/gzhttp" "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/middlewares/compress/brotli" "github.com/traefik/traefik/v2/pkg/tracing" @@ -35,7 +34,7 @@ type compress struct { // New creates a new compress middleware. func New(ctx context.Context, next http.Handler, conf dynamic.Compress, name string) (http.Handler, error) { - log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware") excludes := []string{"application/grpc"} for _, v := range conf.ExcludedContentTypes { @@ -74,7 +73,7 @@ func New(ctx context.Context, next http.Handler, conf dynamic.Compress, name str } func (c *compress) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - logger := log.FromContext(middlewares.GetLoggerCtx(req.Context(), c.name, typeName)) + logger := middlewares.GetLogger(req.Context(), c.name, typeName) if req.Method == http.MethodHead { c.next.ServeHTTP(rw, req) @@ -83,7 +82,7 @@ func (c *compress) ServeHTTP(rw http.ResponseWriter, req *http.Request) { mediaType, _, err := mime.ParseMediaType(req.Header.Get("Content-Type")) if err != nil { - logger.WithError(err).Debug("Unable to parse MIME type") + logger.Debug().Err(err).Msg("Unable to parse MIME type") } // Notably for text/event-stream requests the response should not be compressed. diff --git a/pkg/middlewares/customerrors/custom_errors.go b/pkg/middlewares/customerrors/custom_errors.go index e98dfd7d6..55684f82e 100644 --- a/pkg/middlewares/customerrors/custom_errors.go +++ b/pkg/middlewares/customerrors/custom_errors.go @@ -12,11 +12,10 @@ import ( "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/tracing" "github.com/traefik/traefik/v2/pkg/types" - "github.com/vulcand/oxy/utils" + "github.com/vulcand/oxy/v2/utils" ) // Compile time validation that the response recorder implements http interfaces correctly. @@ -42,7 +41,7 @@ type customErrors struct { // New creates a new custom error pages middleware. func New(ctx context.Context, next http.Handler, config dynamic.ErrorPage, serviceBuilder serviceBuilder, name string) (http.Handler, error) { - log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware") httpCodeRanges, err := types.NewHTTPCodeRanges(config.Status) if err != nil { @@ -68,11 +67,10 @@ func (c *customErrors) GetTracingInformation() (string, ext.SpanKindEnum) { } func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - ctx := middlewares.GetLoggerCtx(req.Context(), c.name, typeName) - logger := log.FromContext(ctx) + logger := middlewares.GetLogger(req.Context(), c.name, typeName) if c.backendHandler == nil { - logger.Error("Error pages: no backend handler.") + logger.Error().Msg("Error pages: no backend handler.") tracing.SetErrorWithEvent(req, "Error pages: no backend handler.") c.next.ServeHTTP(rw, req) return @@ -86,7 +84,7 @@ func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) { // check the recorder code against the configured http status code ranges code := catcher.getCode() - logger.Debugf("Caught HTTP Status Code %d, returning error page", code) + logger.Debug().Msgf("Caught HTTP Status Code %d, returning error page", code) var query string if len(c.backendQuery) > 0 { @@ -97,7 +95,7 @@ func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) { pageReq, err := newRequest("http://" + req.Host + query) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() http.Error(rw, http.StatusText(code), code) return } diff --git a/pkg/middlewares/extractor.go b/pkg/middlewares/extractor.go index 559ab4ff7..6766132c9 100644 --- a/pkg/middlewares/extractor.go +++ b/pkg/middlewares/extractor.go @@ -6,9 +6,9 @@ import ( "fmt" "net/http" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" - "github.com/vulcand/oxy/utils" + "github.com/vulcand/oxy/v2/utils" ) // GetSourceExtractor returns the SourceExtractor function corresponding to the given sourceMatcher. @@ -35,26 +35,26 @@ func GetSourceExtractor(ctx context.Context, sourceMatcher *dynamic.SourceCriter } } - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) if sourceMatcher.IPStrategy != nil { strategy, err := sourceMatcher.IPStrategy.Get() if err != nil { return nil, err } - logger.Debug("Using IPStrategy") + logger.Debug().Msg("Using IPStrategy") return utils.ExtractorFunc(func(req *http.Request) (string, int64, error) { return strategy.GetIP(req), 1, nil }), nil } if sourceMatcher.RequestHeaderName != "" { - logger.Debug("Using RequestHeaderName") + logger.Debug().Msg("Using RequestHeaderName") return utils.NewExtractor(fmt.Sprintf("request.header.%s", sourceMatcher.RequestHeaderName)) } if sourceMatcher.RequestHost { - logger.Debug("Using RequestHost") + logger.Debug().Msg("Using RequestHost") return utils.NewExtractor("request.host") } diff --git a/pkg/middlewares/grpcweb/grpcweb.go b/pkg/middlewares/grpcweb/grpcweb.go index b5dffe6f0..e0813fed9 100644 --- a/pkg/middlewares/grpcweb/grpcweb.go +++ b/pkg/middlewares/grpcweb/grpcweb.go @@ -6,7 +6,6 @@ import ( "github.com/improbable-eng/grpc-web/go/grpcweb" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" ) @@ -14,7 +13,7 @@ const typeName = "grpc-web" // New builds a new gRPC web request converter. func New(ctx context.Context, next http.Handler, config dynamic.GrpcWeb, name string) http.Handler { - log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware") return grpcweb.WrapHandler(next, grpcweb.WithCorsForRegisteredEndpointsOnly(false), grpcweb.WithOriginFunc(func(origin string) bool { for _, originCfg := range config.AllowOrigins { diff --git a/pkg/middlewares/headers/header.go b/pkg/middlewares/headers/header.go index 7c5a99af5..99556fdd0 100644 --- a/pkg/middlewares/headers/header.go +++ b/pkg/middlewares/headers/header.go @@ -8,8 +8,9 @@ import ( "strconv" "strings" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" ) // Header is a middleware that helps setup a few basic security features. @@ -28,7 +29,8 @@ func NewHeader(next http.Handler, cfg dynamic.Headers) (*Header, error) { hasCustomHeaders := cfg.HasCustomHeadersDefined() hasCorsHeaders := cfg.HasCorsHeadersDefined() - ctx := log.With(context.Background(), log.Str(log.MiddlewareType, typeName)) + ctx := log.With().Str(logs.MiddlewareType, typeName).Logger().WithContext(context.Background()) + handleDeprecation(ctx, &cfg) regexes := make([]*regexp.Regexp, len(cfg.AccessControlAllowOriginListRegex)) diff --git a/pkg/middlewares/headers/headers.go b/pkg/middlewares/headers/headers.go index 503944f24..dc4518768 100644 --- a/pkg/middlewares/headers/headers.go +++ b/pkg/middlewares/headers/headers.go @@ -7,8 +7,8 @@ import ( "net/http" "github.com/opentracing/opentracing-go/ext" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/middlewares/connectionheader" "github.com/traefik/traefik/v2/pkg/tracing" @@ -19,20 +19,22 @@ const ( ) func handleDeprecation(ctx context.Context, cfg *dynamic.Headers) { + logger := log.Ctx(ctx).Warn() + if cfg.SSLRedirect { - log.FromContext(ctx).Warn("SSLRedirect is deprecated, please use entrypoint redirection instead.") + logger.Msg("SSLRedirect is deprecated, please use entrypoint redirection instead.") } if cfg.SSLTemporaryRedirect { - log.FromContext(ctx).Warn("SSLTemporaryRedirect is deprecated, please use entrypoint redirection instead.") + logger.Msg("SSLTemporaryRedirect is deprecated, please use entrypoint redirection instead.") } if cfg.SSLHost != "" { - log.FromContext(ctx).Warn("SSLHost is deprecated, please use RedirectRegex middleware instead.") + logger.Msg("SSLHost is deprecated, please use RedirectRegex middleware instead.") } if cfg.SSLForceHost { - log.FromContext(ctx).Warn("SSLForceHost is deprecated, please use RedirectScheme middleware instead.") + logger.Msg("SSLForceHost is deprecated, please use RedirectScheme middleware instead.") } if cfg.FeaturePolicy != "" { - log.FromContext(ctx).Warn("FeaturePolicy is deprecated, please use PermissionsPolicy header instead.") + logger.Msg("FeaturePolicy is deprecated, please use PermissionsPolicy header instead.") } } @@ -44,9 +46,10 @@ type headers struct { // New creates a Headers middleware. func New(ctx context.Context, next http.Handler, cfg dynamic.Headers, name string) (http.Handler, error) { // HeaderMiddleware -> SecureMiddleWare -> next - mCtx := middlewares.GetLoggerCtx(ctx, name, typeName) - logger := log.FromContext(mCtx) - logger.Debug("Creating middleware") + logger := middlewares.GetLogger(ctx, name, typeName) + logger.Debug().Msg("Creating middleware") + + mCtx := logger.WithContext(ctx) handleDeprecation(mCtx, &cfg) @@ -62,13 +65,13 @@ func New(ctx context.Context, next http.Handler, cfg dynamic.Headers, name strin nextHandler := next if hasSecureHeaders { - logger.Debugf("Setting up secureHeaders from %v", cfg) + logger.Debug().Msgf("Setting up secureHeaders from %v", cfg) handler = newSecure(next, cfg, name) nextHandler = handler } if hasCustomHeaders || hasCorsHeaders { - logger.Debugf("Setting up customHeaders/Cors from %v", cfg) + logger.Debug().Msgf("Setting up customHeaders/Cors from %v", cfg) h, err := NewHeader(nextHandler, cfg) if err != nil { return nil, err diff --git a/pkg/middlewares/headers/responsewriter.go b/pkg/middlewares/headers/responsewriter.go index 893af32c8..e50277ce9 100644 --- a/pkg/middlewares/headers/responsewriter.go +++ b/pkg/middlewares/headers/responsewriter.go @@ -6,7 +6,7 @@ import ( "net" "net/http" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) type responseModifier struct { @@ -55,7 +55,7 @@ func (r *responseModifier) WriteHeader(code int) { // we are propagating when we are called in Write, but we're logging anyway, // because we could be called from another place which does not take care of // checking w.modifierErr. - log.WithoutContext().Errorf("Error when applying response modifier: %v", err) + log.Error().Err(err).Msg("Error when applying response modifier") r.rw.WriteHeader(http.StatusInternalServerError) return } diff --git a/pkg/middlewares/inflightreq/inflight_req.go b/pkg/middlewares/inflightreq/inflight_req.go index fb235dd85..c34982bef 100644 --- a/pkg/middlewares/inflightreq/inflight_req.go +++ b/pkg/middlewares/inflightreq/inflight_req.go @@ -6,11 +6,12 @@ import ( "net/http" "github.com/opentracing/opentracing-go/ext" + "github.com/rs/zerolog" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/tracing" - "github.com/vulcand/oxy/connlimit" + "github.com/vulcand/oxy/v2/connlimit" ) const ( @@ -25,8 +26,10 @@ type inFlightReq struct { // New creates a max request middleware. // If no source criterion is provided in the config, it defaults to RequestHost. func New(ctx context.Context, next http.Handler, config dynamic.InFlightReq, name string) (http.Handler, error) { - ctxLog := log.With(ctx, log.Str(log.MiddlewareName, name), log.Str(log.MiddlewareType, typeName)) - log.FromContext(ctxLog).Debug("Creating middleware") + logger := middlewares.GetLogger(ctx, name, typeName) + logger.Debug().Msg("Creating middleware") + + ctxLog := logger.WithContext(ctx) if config.SourceCriterion == nil || config.SourceCriterion.IPStrategy == nil && @@ -41,7 +44,9 @@ func New(ctx context.Context, next http.Handler, config dynamic.InFlightReq, nam return nil, fmt.Errorf("error creating requests limiter: %w", err) } - handler, err := connlimit.New(next, sourceMatcher, config.Amount) + handler, err := connlimit.New(next, sourceMatcher, config.Amount, + connlimit.Logger(logs.NewOxyWrapper(*logger)), + connlimit.Verbose(logger.GetLevel() == zerolog.TraceLevel)) if err != nil { return nil, fmt.Errorf("error creating connection limit: %w", err) } diff --git a/pkg/middlewares/ipallowlist/ip_allowlist.go b/pkg/middlewares/ipallowlist/ip_allowlist.go index d700a9279..b9ddaf94b 100644 --- a/pkg/middlewares/ipallowlist/ip_allowlist.go +++ b/pkg/middlewares/ipallowlist/ip_allowlist.go @@ -7,9 +7,9 @@ import ( "net/http" "github.com/opentracing/opentracing-go/ext" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/ip" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/tracing" ) @@ -28,8 +28,8 @@ type ipAllowLister struct { // New builds a new IPAllowLister given a list of CIDR-Strings to allow. func New(ctx context.Context, next http.Handler, config dynamic.IPAllowList, name string) (http.Handler, error) { - logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)) - logger.Debug("Creating middleware") + logger := middlewares.GetLogger(ctx, name, typeName) + logger.Debug().Msg("Creating middleware") if len(config.SourceRange) == 0 { return nil, errors.New("sourceRange is empty, IPAllowLister not created") @@ -45,7 +45,7 @@ func New(ctx context.Context, next http.Handler, config dynamic.IPAllowList, nam return nil, err } - logger.Debugf("Setting up IPAllowLister with sourceRange: %s", config.SourceRange) + logger.Debug().Msgf("Setting up IPAllowLister with sourceRange: %s", config.SourceRange) return &ipAllowLister{ strategy: strategy, @@ -60,19 +60,19 @@ func (al *ipAllowLister) GetTracingInformation() (string, ext.SpanKindEnum) { } func (al *ipAllowLister) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - ctx := middlewares.GetLoggerCtx(req.Context(), al.name, typeName) - logger := log.FromContext(ctx) + logger := middlewares.GetLogger(req.Context(), al.name, typeName) + ctx := logger.WithContext(req.Context()) clientIP := al.strategy.GetIP(req) err := al.allowLister.IsAuthorized(clientIP) if err != nil { msg := fmt.Sprintf("Rejecting IP %s: %v", clientIP, err) - logger.Debug(msg) + logger.Debug().Msg(msg) tracing.SetErrorWithEvent(req, msg) reject(ctx, rw) return } - logger.Debugf("Accepting IP %s", clientIP) + logger.Debug().Msgf("Accepting IP %s", clientIP) al.next.ServeHTTP(rw, req) } @@ -83,6 +83,6 @@ func reject(ctx context.Context, rw http.ResponseWriter) { rw.WriteHeader(statusCode) _, err := rw.Write([]byte(http.StatusText(statusCode))) if err != nil { - log.FromContext(ctx).Error(err) + log.Ctx(ctx).Error().Err(err).Send() } } diff --git a/pkg/middlewares/metrics/metrics.go b/pkg/middlewares/metrics/metrics.go index 4286da165..b04a49c85 100644 --- a/pkg/middlewares/metrics/metrics.go +++ b/pkg/middlewares/metrics/metrics.go @@ -10,7 +10,7 @@ import ( "github.com/containous/alice" gokitmetrics "github.com/go-kit/kit/metrics" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/metrics" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/middlewares/capture" @@ -44,7 +44,7 @@ type metricsMiddleware struct { // NewEntryPointMiddleware creates a new metrics middleware for an Entrypoint. func NewEntryPointMiddleware(ctx context.Context, next http.Handler, registry metrics.Registry, entryPointName string) http.Handler { - log.FromContext(middlewares.GetLoggerCtx(ctx, nameEntrypoint, typeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, nameEntrypoint, typeName).Debug().Msg("Creating middleware") return &metricsMiddleware{ next: next, @@ -60,7 +60,7 @@ func NewEntryPointMiddleware(ctx context.Context, next http.Handler, registry me // NewRouterMiddleware creates a new metrics middleware for a Router. func NewRouterMiddleware(ctx context.Context, next http.Handler, registry metrics.Registry, routerName string, serviceName string) http.Handler { - log.FromContext(middlewares.GetLoggerCtx(ctx, nameRouter, typeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, nameRouter, typeName).Debug().Msg("Creating middleware") return &metricsMiddleware{ next: next, @@ -76,7 +76,7 @@ func NewRouterMiddleware(ctx context.Context, next http.Handler, registry metric // NewServiceMiddleware creates a new metrics middleware for a Service. func NewServiceMiddleware(ctx context.Context, next http.Handler, registry metrics.Registry, serviceName string) http.Handler { - log.FromContext(middlewares.GetLoggerCtx(ctx, nameService, typeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, nameService, typeName).Debug().Msg("Creating middleware") return &metricsMiddleware{ next: next, @@ -129,10 +129,12 @@ func (m *metricsMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Request) capt, err := capture.FromContext(ctx) if err != nil { + with := log.Ctx(ctx).With() for i := 0; i < len(m.baseLabels); i += 2 { - ctx = log.With(ctx, log.Str(m.baseLabels[i], m.baseLabels[i+1])) + with = with.Str(m.baseLabels[i], m.baseLabels[i+1]) } - log.FromContext(ctx).WithError(err).Errorf("Could not get Capture") + logger := with.Logger() + logger.Error().Err(err).Msg("Could not get Capture") return } @@ -223,7 +225,7 @@ func containsHeader(req *http.Request, name, value string) bool { //nolint:usestdlibvars func getMethod(r *http.Request) string { if !utf8.ValidString(r.Method) { - log.WithoutContext().Warnf("Invalid HTTP method encoding: %s", r.Method) + log.Warn().Msgf("Invalid HTTP method encoding: %s", r.Method) return "NON_UTF8_HTTP_METHOD" } diff --git a/pkg/middlewares/middleware.go b/pkg/middlewares/middleware.go index d5689704b..32aadf29a 100644 --- a/pkg/middlewares/middleware.go +++ b/pkg/middlewares/middleware.go @@ -3,10 +3,17 @@ package middlewares import ( "context" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" ) -// GetLoggerCtx creates a logger context with the middleware fields. -func GetLoggerCtx(ctx context.Context, middleware, middlewareType string) context.Context { - return log.With(ctx, log.Str(log.MiddlewareName, middleware), log.Str(log.MiddlewareType, middlewareType)) +// GetLogger creates a logger with the middleware fields. +func GetLogger(ctx context.Context, middleware, middlewareType string) *zerolog.Logger { + logger := log.Ctx(ctx).With(). + Str(logs.MiddlewareName, middleware). + Str(logs.MiddlewareType, middlewareType). + Logger() + + return &logger } diff --git a/pkg/middlewares/passtlsclientcert/pass_tls_client_cert.go b/pkg/middlewares/passtlsclientcert/pass_tls_client_cert.go index cddf0ad32..3f0f80423 100644 --- a/pkg/middlewares/passtlsclientcert/pass_tls_client_cert.go +++ b/pkg/middlewares/passtlsclientcert/pass_tls_client_cert.go @@ -12,8 +12,8 @@ import ( "strings" "github.com/opentracing/opentracing-go/ext" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/tracing" ) @@ -130,7 +130,7 @@ type passTLSClientCert struct { // New constructs a new PassTLSClientCert instance from supplied frontend header struct. func New(ctx context.Context, next http.Handler, config dynamic.PassTLSClientCert, name string) (http.Handler, error) { - log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware") return &passTLSClientCert{ next: next, @@ -145,14 +145,14 @@ func (p *passTLSClientCert) GetTracingInformation() (string, ext.SpanKindEnum) { } func (p *passTLSClientCert) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - ctx := middlewares.GetLoggerCtx(req.Context(), p.name, typeName) - logger := log.FromContext(ctx) + logger := middlewares.GetLogger(req.Context(), p.name, typeName) + ctx := logger.WithContext(req.Context()) if p.pem { if req.TLS != nil && len(req.TLS.PeerCertificates) > 0 { req.Header.Set(xForwardedTLSClientCert, getCertificates(ctx, req.TLS.PeerCertificates)) } else { - logger.Warn("Tried to extract a certificate on a request without mutual TLS") + logger.Warn().Msg("Tried to extract a certificate on a request without mutual TLS") } } @@ -161,7 +161,7 @@ func (p *passTLSClientCert) ServeHTTP(rw http.ResponseWriter, req *http.Request) headerContent := p.getCertInfo(ctx, req.TLS.PeerCertificates) req.Header.Set(xForwardedTLSClientCertInfo, url.QueryEscape(headerContent)) } else { - logger.Warn("Tried to extract a certificate on a request without mutual TLS") + logger.Warn().Msg("Tried to extract a certificate on a request without mutual TLS") } } @@ -318,7 +318,7 @@ func writePart(ctx context.Context, content io.StringWriter, entry, prefix strin if len(entry) > 0 { _, err := content.WriteString(fmt.Sprintf("%s=%s%s", prefix, entry, subFieldSeparator)) if err != nil { - log.FromContext(ctx).Error(err) + log.Ctx(ctx).Error().Err(err).Send() } } } @@ -347,7 +347,7 @@ func getCertificates(ctx context.Context, certs []*x509.Certificate) string { func extractCertificate(ctx context.Context, cert *x509.Certificate) string { certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) if certPEM == nil { - log.FromContext(ctx).Error("Cannot extract the certificate content") + log.Ctx(ctx).Error().Msg("Cannot extract the certificate content") return "" } diff --git a/pkg/middlewares/ratelimiter/rate_limiter.go b/pkg/middlewares/ratelimiter/rate_limiter.go index 403c97199..303b20e8e 100644 --- a/pkg/middlewares/ratelimiter/rate_limiter.go +++ b/pkg/middlewares/ratelimiter/rate_limiter.go @@ -10,11 +10,11 @@ import ( "github.com/mailgun/ttlmap" "github.com/opentracing/opentracing-go/ext" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/tracing" - "github.com/vulcand/oxy/utils" + "github.com/vulcand/oxy/v2/utils" "golang.org/x/time/rate" ) @@ -45,8 +45,10 @@ type rateLimiter struct { // New returns a rate limiter middleware. func New(ctx context.Context, next http.Handler, config dynamic.RateLimit, name string) (http.Handler, error) { - ctxLog := log.With(ctx, log.Str(log.MiddlewareName, name), log.Str(log.MiddlewareType, typeName)) - log.FromContext(ctxLog).Debug("Creating middleware") + logger := middlewares.GetLogger(ctx, name, typeName) + logger.Debug().Msg("Creating middleware") + + ctxLog := logger.WithContext(ctx) if config.SourceCriterion == nil || config.SourceCriterion.IPStrategy == nil && @@ -122,19 +124,19 @@ func (rl *rateLimiter) GetTracingInformation() (string, ext.SpanKindEnum) { return rl.name, tracing.SpanKindNoneEnum } -func (rl *rateLimiter) ServeHTTP(w http.ResponseWriter, r *http.Request) { - ctx := middlewares.GetLoggerCtx(r.Context(), rl.name, typeName) - logger := log.FromContext(ctx) +func (rl *rateLimiter) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + logger := middlewares.GetLogger(req.Context(), rl.name, typeName) + ctx := logger.WithContext(req.Context()) - source, amount, err := rl.sourceMatcher.Extract(r) + source, amount, err := rl.sourceMatcher.Extract(req) if err != nil { - logger.Errorf("could not extract source of request: %v", err) - http.Error(w, "could not extract source of request", http.StatusInternalServerError) + logger.Error().Err(err).Msg("Could not extract source of request") + http.Error(rw, "could not extract source of request", http.StatusInternalServerError) return } if amount != 1 { - logger.Infof("ignoring token bucket amount > 1: %d", amount) + logger.Info().Msgf("ignoring token bucket amount > 1: %d", amount) } var bucket *rate.Limiter @@ -148,8 +150,8 @@ func (rl *rateLimiter) ServeHTTP(w http.ResponseWriter, r *http.Request) { // because we want to update the expiryTime everytime we get the source, // as the expiryTime is supposed to reflect the activity (or lack thereof) on that source. if err := rl.buckets.Set(source, bucket, rl.ttl); err != nil { - logger.Errorf("could not insert/update bucket: %v", err) - http.Error(w, "could not insert/update bucket", http.StatusInternalServerError) + logger.Error().Err(err).Msg("Could not insert/update bucket") + http.Error(rw, "could not insert/update bucket", http.StatusInternalServerError) return } @@ -159,19 +161,19 @@ func (rl *rateLimiter) ServeHTTP(w http.ResponseWriter, r *http.Request) { // However, for now we take advantage of this behavior to provide the no-limit ratelimiter when config.Average is 0. res := bucket.Reserve() if !res.OK() { - http.Error(w, "No bursty traffic allowed", http.StatusTooManyRequests) + http.Error(rw, "No bursty traffic allowed", http.StatusTooManyRequests) return } delay := res.Delay() if delay > rl.maxDelay { res.Cancel() - rl.serveDelayError(ctx, w, delay) + rl.serveDelayError(ctx, rw, delay) return } time.Sleep(delay) - rl.next.ServeHTTP(w, r) + rl.next.ServeHTTP(rw, req) } func (rl *rateLimiter) serveDelayError(ctx context.Context, w http.ResponseWriter, delay time.Duration) { @@ -180,6 +182,6 @@ func (rl *rateLimiter) serveDelayError(ctx context.Context, w http.ResponseWrite w.WriteHeader(http.StatusTooManyRequests) if _, err := w.Write([]byte(http.StatusText(http.StatusTooManyRequests))); err != nil { - log.FromContext(ctx).Errorf("could not serve 429: %v", err) + log.Ctx(ctx).Error().Err(err).Msg("Could not serve 429") } } diff --git a/pkg/middlewares/ratelimiter/rate_limiter_test.go b/pkg/middlewares/ratelimiter/rate_limiter_test.go index 26d18580b..ac73fc2ec 100644 --- a/pkg/middlewares/ratelimiter/rate_limiter_test.go +++ b/pkg/middlewares/ratelimiter/rate_limiter_test.go @@ -14,7 +14,7 @@ import ( ptypes "github.com/traefik/paerser/types" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/testhelpers" - "github.com/vulcand/oxy/utils" + "github.com/vulcand/oxy/v2/utils" ) func TestNewRateLimiter(t *testing.T) { diff --git a/pkg/middlewares/recovery/recovery.go b/pkg/middlewares/recovery/recovery.go index 753a5801b..90e0b3659 100644 --- a/pkg/middlewares/recovery/recovery.go +++ b/pkg/middlewares/recovery/recovery.go @@ -5,7 +5,6 @@ import ( "net/http" "runtime" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" ) @@ -20,7 +19,7 @@ type recovery struct { // New creates recovery middleware. func New(ctx context.Context, next http.Handler) (http.Handler, error) { - log.FromContext(middlewares.GetLoggerCtx(ctx, middlewareName, typeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, middlewareName, typeName).Debug().Msg("Creating middleware") return &recovery{ next: next, @@ -32,19 +31,19 @@ func (re *recovery) ServeHTTP(rw http.ResponseWriter, req *http.Request) { re.next.ServeHTTP(rw, req) } -func recoverFunc(rw http.ResponseWriter, r *http.Request) { +func recoverFunc(rw http.ResponseWriter, req *http.Request) { if err := recover(); err != nil { - logger := log.FromContext(middlewares.GetLoggerCtx(r.Context(), middlewareName, typeName)) + logger := middlewares.GetLogger(req.Context(), middlewareName, typeName) if !shouldLogPanic(err) { - logger.Debugf("Request has been aborted [%s - %s]: %v", r.RemoteAddr, r.URL, err) + logger.Debug().Msgf("Request has been aborted [%s - %s]: %v", req.RemoteAddr, req.URL, err) return } - logger.Errorf("Recovered from panic in HTTP handler [%s - %s]: %+v", r.RemoteAddr, r.URL, err) + logger.Error().Msgf("Recovered from panic in HTTP handler [%s - %s]: %+v", req.RemoteAddr, req.URL, err) const size = 64 << 10 buf := make([]byte, size) buf = buf[:runtime.Stack(buf, false)] - logger.Errorf("Stack: %s", buf) + logger.Error().Msgf("Stack: %s", buf) http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } diff --git a/pkg/middlewares/redirect/redirect.go b/pkg/middlewares/redirect/redirect.go index e09611e37..a48053f8a 100644 --- a/pkg/middlewares/redirect/redirect.go +++ b/pkg/middlewares/redirect/redirect.go @@ -7,7 +7,7 @@ import ( "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v2/pkg/tracing" - "github.com/vulcand/oxy/utils" + "github.com/vulcand/oxy/v2/utils" ) const ( diff --git a/pkg/middlewares/redirect/redirect_regex.go b/pkg/middlewares/redirect/redirect_regex.go index bc4ae3843..62e5dc986 100644 --- a/pkg/middlewares/redirect/redirect_regex.go +++ b/pkg/middlewares/redirect/redirect_regex.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" ) @@ -14,9 +13,9 @@ const typeRegexName = "RedirectRegex" // NewRedirectRegex creates a redirect middleware. func NewRedirectRegex(ctx context.Context, next http.Handler, conf dynamic.RedirectRegex, name string) (http.Handler, error) { - logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeRegexName)) - logger.Debug("Creating middleware") - logger.Debugf("Setting up redirection from %s to %s", conf.Regex, conf.Replacement) + logger := middlewares.GetLogger(ctx, name, typeRegexName) + logger.Debug().Msg("Creating middleware") + logger.Debug().Msgf("Setting up redirection from %s to %s", conf.Regex, conf.Replacement) return newRedirect(next, conf.Regex, conf.Replacement, conf.Permanent, rawURL, name) } diff --git a/pkg/middlewares/redirect/redirect_scheme.go b/pkg/middlewares/redirect/redirect_scheme.go index 063d6c4bc..b828ff287 100644 --- a/pkg/middlewares/redirect/redirect_scheme.go +++ b/pkg/middlewares/redirect/redirect_scheme.go @@ -8,7 +8,6 @@ import ( "strings" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" ) @@ -20,9 +19,9 @@ const ( // NewRedirectScheme creates a new RedirectScheme middleware. func NewRedirectScheme(ctx context.Context, next http.Handler, conf dynamic.RedirectScheme, name string) (http.Handler, error) { - logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeSchemeName)) - logger.Debug("Creating middleware") - logger.Debugf("Setting up redirection to %s %s", conf.Scheme, conf.Port) + logger := middlewares.GetLogger(ctx, name, typeSchemeName) + logger.Debug().Msg("Creating middleware") + logger.Debug().Msgf("Setting up redirection to %s %s", conf.Scheme, conf.Port) if len(conf.Scheme) == 0 { return nil, errors.New("you must provide a target scheme") diff --git a/pkg/middlewares/replacepath/replace_path.go b/pkg/middlewares/replacepath/replace_path.go index d730a931c..e19361056 100644 --- a/pkg/middlewares/replacepath/replace_path.go +++ b/pkg/middlewares/replacepath/replace_path.go @@ -7,7 +7,6 @@ import ( "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/tracing" ) @@ -27,7 +26,7 @@ type replacePath struct { // New creates a new replace path middleware. func New(ctx context.Context, next http.Handler, config dynamic.ReplacePath, name string) (http.Handler, error) { - log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware") return &replacePath{ next: next, @@ -52,7 +51,7 @@ func (r *replacePath) ServeHTTP(rw http.ResponseWriter, req *http.Request) { var err error req.URL.Path, err = url.PathUnescape(req.URL.RawPath) if err != nil { - log.FromContext(middlewares.GetLoggerCtx(context.Background(), r.name, typeName)).Error(err) + middlewares.GetLogger(context.Background(), r.name, typeName).Error().Err(err).Send() http.Error(rw, err.Error(), http.StatusInternalServerError) return } diff --git a/pkg/middlewares/replacepathregex/replace_path_regex.go b/pkg/middlewares/replacepathregex/replace_path_regex.go index fea6fa2de..2f2621b8c 100644 --- a/pkg/middlewares/replacepathregex/replace_path_regex.go +++ b/pkg/middlewares/replacepathregex/replace_path_regex.go @@ -10,7 +10,6 @@ import ( "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/middlewares/replacepath" "github.com/traefik/traefik/v2/pkg/tracing" @@ -28,7 +27,7 @@ type replacePathRegex struct { // New creates a new replace path regex middleware. func New(ctx context.Context, next http.Handler, config dynamic.ReplacePathRegex, name string) (http.Handler, error) { - log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware") exp, err := regexp.Compile(strings.TrimSpace(config.Regex)) if err != nil { @@ -63,7 +62,7 @@ func (rp *replacePathRegex) ServeHTTP(rw http.ResponseWriter, req *http.Request) var err error req.URL.Path, err = url.PathUnescape(req.URL.RawPath) if err != nil { - log.FromContext(middlewares.GetLoggerCtx(context.Background(), rp.name, typeName)).Error(err) + middlewares.GetLogger(context.Background(), rp.name, typeName).Error().Err(err).Send() http.Error(rw, err.Error(), http.StatusInternalServerError) return } diff --git a/pkg/middlewares/requestdecorator/hostresolver.go b/pkg/middlewares/requestdecorator/hostresolver.go index 40eee21f7..d600360a7 100644 --- a/pkg/middlewares/requestdecorator/hostresolver.go +++ b/pkg/middlewares/requestdecorator/hostresolver.go @@ -10,7 +10,7 @@ import ( "github.com/miekg/dns" "github.com/patrickmn/go-cache" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) type cnameResolv struct { @@ -46,12 +46,12 @@ func (hr *Resolver) CNAMEFlatten(ctx context.Context, host string) string { return value.(string) } - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) cacheDuration := 0 * time.Second for depth := 0; depth < hr.ResolvDepth; depth++ { resolv, err := cnameResolve(ctx, request, hr.ResolvConfig) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() break } if resolv == nil { @@ -66,7 +66,7 @@ func (hr *Resolver) CNAMEFlatten(ctx context.Context, host string) string { } if err := hr.cache.Add(host, result, cacheDuration); err != nil { - logger.Error(err) + logger.Error().Err(err).Send() } return result @@ -88,7 +88,7 @@ func cnameResolve(ctx context.Context, host, resolvPath string) (*cnameResolv, e for _, server := range config.Servers { tempRecord, err := getRecord(client, m, server, config.Port) if err != nil { - log.FromContext(ctx).Errorf("Failed to resolve host %s: %v", host, err) + log.Ctx(ctx).Error().Err(err).Msgf("Failed to resolve host %s", host) continue } result = append(result, tempRecord) diff --git a/pkg/middlewares/retry/retry.go b/pkg/middlewares/retry/retry.go index a05ced970..b9f3b6af7 100644 --- a/pkg/middlewares/retry/retry.go +++ b/pkg/middlewares/retry/retry.go @@ -14,7 +14,6 @@ import ( "github.com/cenkalti/backoff/v4" "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/tracing" ) @@ -46,7 +45,7 @@ type retry struct { // New returns a new retry middleware. func New(ctx context.Context, next http.Handler, config dynamic.Retry, listener Listener, name string) (http.Handler, error) { - log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware") if config.Attempts <= 0 { return nil, fmt.Errorf("incorrect (or empty) value for attempt (%d)", config.Attempts) @@ -106,19 +105,19 @@ func (r *retry) ServeHTTP(rw http.ResponseWriter, req *http.Request) { return fmt.Errorf("attempt %d failed", attempts-1) } + logger := middlewares.GetLogger(req.Context(), r.name, typeName) + backOff := backoff.WithContext(r.newBackOff(), req.Context()) notify := func(err error, d time.Duration) { - log.FromContext(middlewares.GetLoggerCtx(req.Context(), r.name, typeName)). - Debugf("New attempt %d for request: %v", attempts, req.URL) + logger.Debug().Msgf("New attempt %d for request: %v", attempts, req.URL) r.listener.Retried(req, attempts) } err := backoff.RetryNotify(operation, backOff, notify) if err != nil { - log.FromContext(middlewares.GetLoggerCtx(req.Context(), r.name, typeName)). - Debugf("Final retry attempt failed: %v", err.Error()) + logger.Debug().Err(err).Msg("Final retry attempt failed") } } diff --git a/pkg/middlewares/snicheck/snicheck.go b/pkg/middlewares/snicheck/snicheck.go index e18b605cb..27f8148d1 100644 --- a/pkg/middlewares/snicheck/snicheck.go +++ b/pkg/middlewares/snicheck/snicheck.go @@ -5,7 +5,7 @@ import ( "net/http" "strings" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator" traefiktls "github.com/traefik/traefik/v2/pkg/tls" ) @@ -36,11 +36,11 @@ func (s SNICheck) ServeHTTP(rw http.ResponseWriter, req *http.Request) { tlsOptionSNI := findTLSOptionName(s.tlsOptionsForHost, serverName, false) if tlsOptionHeader != tlsOptionSNI { - log.WithoutContext(). - WithField("host", host). - WithField("req.Host", req.Host). - WithField("req.TLS.ServerName", req.TLS.ServerName). - Debugf("TLS options difference: SNI:%s, Header:%s", tlsOptionSNI, tlsOptionHeader) + log.Debug(). + Str("host", host). + Str("req.Host", req.Host). + Str("req.TLS.ServerName", req.TLS.ServerName). + Msgf("TLS options difference: SNI:%s, Header:%s", tlsOptionSNI, tlsOptionHeader) http.Error(rw, http.StatusText(http.StatusMisdirectedRequest), http.StatusMisdirectedRequest) return } diff --git a/pkg/middlewares/stripprefix/strip_prefix.go b/pkg/middlewares/stripprefix/strip_prefix.go index 406b13ab2..38caa7e3a 100644 --- a/pkg/middlewares/stripprefix/strip_prefix.go +++ b/pkg/middlewares/stripprefix/strip_prefix.go @@ -7,7 +7,6 @@ import ( "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/tracing" ) @@ -28,7 +27,7 @@ type stripPrefix struct { // New creates a new strip prefix middleware. func New(ctx context.Context, next http.Handler, config dynamic.StripPrefix, name string) (http.Handler, error) { - log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware") return &stripPrefix{ prefixes: config.Prefixes, forceSlash: config.ForceSlash, diff --git a/pkg/middlewares/stripprefixregex/strip_prefix_regex.go b/pkg/middlewares/stripprefixregex/strip_prefix_regex.go index ee0722ad3..debeba16d 100644 --- a/pkg/middlewares/stripprefixregex/strip_prefix_regex.go +++ b/pkg/middlewares/stripprefixregex/strip_prefix_regex.go @@ -8,7 +8,6 @@ import ( "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/middlewares/stripprefix" "github.com/traefik/traefik/v2/pkg/tracing" @@ -27,7 +26,7 @@ type stripPrefixRegex struct { // New builds a new StripPrefixRegex middleware. func New(ctx context.Context, next http.Handler, config dynamic.StripPrefixRegex, name string) (http.Handler, error) { - log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware") stripPrefix := stripPrefixRegex{ next: next, diff --git a/pkg/middlewares/tcp/inflightconn/inflight_conn.go b/pkg/middlewares/tcp/inflightconn/inflight_conn.go index ddbb4bdab..6213d4e42 100644 --- a/pkg/middlewares/tcp/inflightconn/inflight_conn.go +++ b/pkg/middlewares/tcp/inflightconn/inflight_conn.go @@ -7,7 +7,6 @@ import ( "sync" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/tcp" ) @@ -26,8 +25,8 @@ type inFlightConn struct { // New creates a max connections middleware. // The connections are identified and grouped by remote IP. func New(ctx context.Context, next tcp.Handler, config dynamic.TCPInFlightConn, name string) (tcp.Handler, error) { - logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)) - logger.Debug("Creating middleware") + logger := middlewares.GetLogger(ctx, name, typeName) + logger.Debug().Msg("Creating middleware") return &inFlightConn{ name: name, @@ -39,18 +38,17 @@ func New(ctx context.Context, next tcp.Handler, config dynamic.TCPInFlightConn, // ServeTCP serves the given TCP connection. func (i *inFlightConn) ServeTCP(conn tcp.WriteCloser) { - ctx := middlewares.GetLoggerCtx(context.Background(), i.name, typeName) - logger := log.FromContext(ctx) + logger := middlewares.GetLogger(context.Background(), i.name, typeName) ip, _, err := net.SplitHostPort(conn.RemoteAddr().String()) if err != nil { - logger.Errorf("Cannot parse IP from remote addr: %v", err) + logger.Error().Err(err).Msg("Cannot parse IP from remote addr") conn.Close() return } if err = i.increment(ip); err != nil { - logger.Errorf("Connection rejected: %v", err) + logger.Error().Err(err).Msg("Connection rejected") conn.Close() return } diff --git a/pkg/middlewares/tcp/ipallowlist/ip_allowlist.go b/pkg/middlewares/tcp/ipallowlist/ip_allowlist.go index dd5d14d43..e2a513cf0 100644 --- a/pkg/middlewares/tcp/ipallowlist/ip_allowlist.go +++ b/pkg/middlewares/tcp/ipallowlist/ip_allowlist.go @@ -7,7 +7,6 @@ import ( "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/ip" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/tcp" ) @@ -25,8 +24,8 @@ type ipAllowLister struct { // New builds a new TCP IPAllowLister given a list of CIDR-Strings to allow. func New(ctx context.Context, next tcp.Handler, config dynamic.TCPIPAllowList, name string) (tcp.Handler, error) { - logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)) - logger.Debug("Creating middleware") + logger := middlewares.GetLogger(ctx, name, typeName) + logger.Debug().Msg("Creating middleware") if len(config.SourceRange) == 0 { return nil, errors.New("sourceRange is empty, IPAllowLister not created") @@ -37,7 +36,7 @@ func New(ctx context.Context, next tcp.Handler, config dynamic.TCPIPAllowList, n return nil, fmt.Errorf("cannot parse CIDRs %s: %w", config.SourceRange, err) } - logger.Debugf("Setting up IPAllowLister with sourceRange: %s", config.SourceRange) + logger.Debug().Msgf("Setting up IPAllowLister with sourceRange: %s", config.SourceRange) return &ipAllowLister{ allowLister: checker, @@ -47,19 +46,18 @@ func New(ctx context.Context, next tcp.Handler, config dynamic.TCPIPAllowList, n } func (al *ipAllowLister) ServeTCP(conn tcp.WriteCloser) { - ctx := middlewares.GetLoggerCtx(context.Background(), al.name, typeName) - logger := log.FromContext(ctx) + logger := middlewares.GetLogger(context.Background(), al.name, typeName) addr := conn.RemoteAddr().String() err := al.allowLister.IsAuthorized(addr) if err != nil { - logger.Errorf("Connection from %s rejected: %v", addr, err) + logger.Error().Err(err).Msgf("Connection from %s rejected", addr) conn.Close() return } - logger.Debugf("Connection from %s accepted", addr) + logger.Debug().Msgf("Connection from %s accepted", addr) al.next.ServeTCP(conn) } diff --git a/pkg/middlewares/tracing/entrypoint.go b/pkg/middlewares/tracing/entrypoint.go index 71a1da6d3..d665823a2 100644 --- a/pkg/middlewares/tracing/entrypoint.go +++ b/pkg/middlewares/tracing/entrypoint.go @@ -7,7 +7,6 @@ import ( "github.com/containous/alice" "github.com/opentracing/opentracing-go" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/tracing" ) @@ -18,7 +17,7 @@ const ( // NewEntryPoint creates a new middleware that the incoming request. func NewEntryPoint(ctx context.Context, t *tracing.Tracing, entryPointName string, next http.Handler) http.Handler { - log.FromContext(middlewares.GetLoggerCtx(ctx, "tracing", entryPointTypeName)).Debug("Creating middleware") + middlewares.GetLogger(ctx, "tracing", entryPointTypeName).Debug().Msg("Creating middleware") return &entryPointMiddleware{ entryPoint: entryPointName, @@ -36,8 +35,8 @@ type entryPointMiddleware struct { func (e *entryPointMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Request) { spanCtx, err := e.Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(req.Header)) if err != nil { - log.FromContext(middlewares.GetLoggerCtx(req.Context(), "tracing", entryPointTypeName)). - Debugf("Failed to extract the context: %v", err) + middlewares.GetLogger(req.Context(), "tracing", entryPointTypeName). + Debug().Err(err).Msg("Failed to extract the context") } span, req, finish := e.StartSpanf(req, ext.SpanKindRPCServerEnum, "EntryPoint", []string{e.entryPoint, req.Host}, " ", ext.RPCServerOption(spanCtx)) diff --git a/pkg/middlewares/tracing/forwarder.go b/pkg/middlewares/tracing/forwarder.go index b57f62330..2ebf5fe77 100644 --- a/pkg/middlewares/tracing/forwarder.go +++ b/pkg/middlewares/tracing/forwarder.go @@ -5,7 +5,7 @@ import ( "net/http" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/tracing" ) @@ -22,8 +22,8 @@ type forwarderMiddleware struct { // NewForwarder creates a new forwarder middleware that traces the outgoing request. func NewForwarder(ctx context.Context, router, service string, next http.Handler) http.Handler { - log.FromContext(middlewares.GetLoggerCtx(ctx, "tracing", forwarderTypeName)). - Debugf("Added outgoing tracing middleware %s", service) + middlewares.GetLogger(ctx, "tracing", forwarderTypeName). + Debug().Str(logs.ServiceName, service).Msg("Added outgoing tracing middleware") return &forwarderMiddleware{ router: router, diff --git a/pkg/middlewares/tracing/wrapper.go b/pkg/middlewares/tracing/wrapper.go index 9386bd14e..e13209d54 100644 --- a/pkg/middlewares/tracing/wrapper.go +++ b/pkg/middlewares/tracing/wrapper.go @@ -6,7 +6,8 @@ import ( "github.com/containous/alice" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/tracing" ) @@ -28,7 +29,7 @@ func Wrap(ctx context.Context, constructor alice.Constructor) alice.Constructor if traceableHandler, ok := handler.(Traceable); ok { name, spanKind := traceableHandler.GetTracingInformation() - log.FromContext(ctx).WithField(log.MiddlewareName, name).Debug("Adding tracing to middleware") + log.Ctx(ctx).Debug().Str(logs.MiddlewareName, name).Msg("Adding tracing to middleware") return NewWrapper(handler, name, spanKind), nil } return handler, nil diff --git a/pkg/muxer/http/mux.go b/pkg/muxer/http/mux.go index fefab67a9..16f6e69fe 100644 --- a/pkg/muxer/http/mux.go +++ b/pkg/muxer/http/mux.go @@ -7,8 +7,8 @@ import ( "unicode/utf8" "github.com/gorilla/mux" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/ip" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator" "github.com/traefik/traefik/v2/pkg/rules" "github.com/vulcand/predicate" @@ -143,7 +143,7 @@ func host(route *mux.Route, hosts ...string) error { if len(reqHost) == 0 { // If the request is an HTTP/1.0 request, then a Host may not be defined. if req.ProtoAtLeast(1, 1) { - log.FromContext(req.Context()).Warnf("Could not retrieve CanonizedHost, rejecting %s", req.Host) + log.Ctx(req.Context()).Warn().Msgf("Could not retrieve CanonizedHost, rejecting %s", req.Host) } return false @@ -155,7 +155,7 @@ func host(route *mux.Route, hosts ...string) error { if strings.EqualFold(reqHost, host) || strings.EqualFold(flatH, host) { return true } - log.FromContext(req.Context()).Debugf("CNAMEFlattening: request %s which resolved to %s, is not matched to route %s", reqHost, flatH, host) + log.Ctx(req.Context()).Debug().Msgf("CNAMEFlattening: request %s which resolved to %s, is not matched to route %s", reqHost, flatH, host) } return false } @@ -197,7 +197,7 @@ func clientIP(route *mux.Route, clientIPs ...string) error { route.MatcherFunc(func(req *http.Request, _ *mux.RouteMatch) bool { ok, err := checker.Contains(strategy.GetIP(req)) if err != nil { - log.FromContext(req.Context()).Warnf("\"ClientIP\" matcher: could not match remote address : %w", err) + log.Ctx(req.Context()).Warn().Err(err).Msg("\"ClientIP\" matcher: could not match remote address") return false } diff --git a/pkg/muxer/tcp/mux.go b/pkg/muxer/tcp/mux.go index e21dfc75d..6d7421119 100644 --- a/pkg/muxer/tcp/mux.go +++ b/pkg/muxer/tcp/mux.go @@ -11,8 +11,8 @@ import ( "strings" "github.com/go-acme/lego/v4/challenge/tlsalpn01" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/ip" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/rules" "github.com/traefik/traefik/v2/pkg/tcp" "github.com/traefik/traefik/v2/pkg/types" @@ -246,7 +246,7 @@ type matchersTree struct { func (m *matchersTree) match(meta ConnData) bool { if m == nil { // This should never happen as it should have been detected during parsing. - log.WithoutContext().Warnf("Rule matcher is nil") + log.Warn().Msg("Rule matcher is nil") return false } @@ -261,7 +261,7 @@ func (m *matchersTree) match(meta ConnData) bool { return m.left.match(meta) && m.right.match(meta) default: // This should never happen as it should have been detected during parsing. - log.WithoutContext().Warnf("Invalid rule operator %s", m.operator) + log.Warn().Msgf("Invalid rule operator %s", m.operator) return false } } @@ -279,7 +279,7 @@ func clientIP(tree *matchersTree, clientIPs ...string) error { ok, err := checker.Contains(meta.remoteIP) if err != nil { - log.WithoutContext().Warnf("\"ClientIP\" matcher: could not match remote address: %v", err) + log.Warn().Err(err).Msg("\"ClientIP\" matcher: could not match remote address") return false } return ok diff --git a/pkg/plugins/builder.go b/pkg/plugins/builder.go index cf99b0e6b..aa3d4c982 100644 --- a/pkg/plugins/builder.go +++ b/pkg/plugins/builder.go @@ -6,8 +6,9 @@ import ( "net/http" "os" - "github.com/sirupsen/logrus" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/yaegi/interp" "github.com/traefik/yaegi/stdlib" ) @@ -35,12 +36,13 @@ func NewBuilder(client *Client, plugins map[string]Descriptor, localPlugins map[ return nil, fmt.Errorf("%s: failed to read manifest: %w", desc.ModuleName, err) } - logger := log.WithoutContext().WithFields(logrus.Fields{"plugin": "plugin-" + pName, "module": desc.ModuleName}) + logger := log.With().Str("plugin", "plugin-"+pName).Str("module", desc.ModuleName).Logger() + i := interp.New(interp.Options{ GoPath: client.GoPath(), Env: os.Environ(), - Stdout: logger.WriterLevel(logrus.DebugLevel), - Stderr: logger.WriterLevel(logrus.ErrorLevel), + Stdout: logs.NoLevel(logger, zerolog.DebugLevel), + Stderr: logs.NoLevel(logger, zerolog.ErrorLevel), }) err = i.Use(stdlib.Symbols) @@ -83,12 +85,13 @@ func NewBuilder(client *Client, plugins map[string]Descriptor, localPlugins map[ return nil, fmt.Errorf("%s: failed to read manifest: %w", desc.ModuleName, err) } - logger := log.WithoutContext().WithFields(logrus.Fields{"plugin": "plugin-" + pName, "module": desc.ModuleName}) + logger := log.With().Str("plugin", "plugin-"+pName).Str("module", desc.ModuleName).Logger() + i := interp.New(interp.Options{ GoPath: localGoPath, Env: os.Environ(), - Stdout: logger.WriterLevel(logrus.DebugLevel), - Stderr: logger.WriterLevel(logrus.ErrorLevel), + Stdout: logs.NoLevel(logger, zerolog.DebugLevel), + Stderr: logs.NoLevel(logger, zerolog.ErrorLevel), }) err = i.Use(stdlib.Symbols) diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go index fdfb9fbce..1ebaf9cfa 100644 --- a/pkg/plugins/plugins.go +++ b/pkg/plugins/plugins.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/hashicorp/go-multierror" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) const localGoPath = "./plugins-local/" @@ -27,7 +27,7 @@ func SetupRemotePlugins(client *Client, plugins map[string]Descriptor) error { ctx := context.Background() for pAlias, desc := range plugins { - log.FromContext(ctx).Debugf("loading of plugin: %s: %s@%s", pAlias, desc.ModuleName, desc.Version) + log.Ctx(ctx).Debug().Msgf("Loading of plugin: %s: %s@%s", pAlias, desc.ModuleName, desc.Version) hash, err := client.Download(ctx, desc.ModuleName, desc.Version) if err != nil { diff --git a/pkg/plugins/providers.go b/pkg/plugins/providers.go index abec8d1b8..ea024c836 100644 --- a/pkg/plugins/providers.go +++ b/pkg/plugins/providers.go @@ -9,8 +9,9 @@ import ( "strings" "github.com/mitchellh/mapstructure" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/yaegi/interp" @@ -158,21 +159,21 @@ func (p *Provider) Init() error { func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error { defer func() { if err := recover(); err != nil { - log.WithoutContext().WithField(log.ProviderName, p.name).Errorf("panic inside the plugin %v", err) + log.Error().Str(logs.ProviderName, p.name).Msgf("Panic inside the plugin %v", err) } }() cfgChan := make(chan json.Marshaler) pool.GoCtx(func(ctx context.Context) { - logger := log.FromContext(log.With(ctx, log.Str(log.ProviderName, p.name))) + logger := log.Ctx(ctx).With().Str(logs.ProviderName, p.name).Logger() for { select { case <-ctx.Done(): err := p.pp.Stop() if err != nil { - logger.Errorf("failed to stop the provider: %v", err) + logger.Error().Err(err).Msg("Failed to stop the provider") } return @@ -180,14 +181,14 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. case cfgPg := <-cfgChan: marshalJSON, err := cfgPg.MarshalJSON() if err != nil { - logger.Errorf("failed to marshal configuration: %v", err) + logger.Error().Err(err).Msg("Failed to marshal configuration") continue } cfg := &dynamic.Configuration{} err = json.Unmarshal(marshalJSON, cfg) if err != nil { - logger.Errorf("failed to unmarshal configuration: %v", err) + logger.Error().Err(err).Msg("Failed to unmarshal configuration") continue } diff --git a/pkg/provider/acme/account.go b/pkg/provider/acme/account.go index 4f12e14a2..6bac6c186 100644 --- a/pkg/provider/acme/account.go +++ b/pkg/provider/acme/account.go @@ -9,7 +9,8 @@ import ( "github.com/go-acme/lego/v4/certcrypto" "github.com/go-acme/lego/v4/registration" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" ) // Account is used to store lets encrypt registration info. @@ -56,8 +57,8 @@ func (a *Account) GetRegistration() *registration.Resource { func (a *Account) GetPrivateKey() crypto.PrivateKey { privateKey, err := x509.ParsePKCS1PrivateKey(a.PrivateKey) if err != nil { - log.WithoutContext().WithField(log.ProviderName, "acme"). - Errorf("Cannot unmarshal private key %+v: %v", a.PrivateKey, err) + log.Error().Str(logs.ProviderName, "acme"). + Err(err).Msgf("Cannot unmarshal private key %+v", a.PrivateKey) return nil } @@ -66,7 +67,7 @@ func (a *Account) GetPrivateKey() crypto.PrivateKey { // GetKeyType used to determine which algo to used. func GetKeyType(ctx context.Context, value string) certcrypto.KeyType { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) switch value { case "EC256": @@ -80,10 +81,10 @@ func GetKeyType(ctx context.Context, value string) certcrypto.KeyType { case "RSA8192": return certcrypto.RSA8192 case "": - logger.Infof("The key type is empty. Use default key type %v.", certcrypto.RSA4096) + logger.Info().Msgf("The key type is empty. Use default key type %v.", certcrypto.RSA4096) return certcrypto.RSA4096 default: - logger.Infof("Unable to determine the key type value %q: falling back on %v.", value, certcrypto.RSA4096) + logger.Info().Msgf("Unable to determine the key type value %q: falling back on %v.", value, certcrypto.RSA4096) return certcrypto.RSA4096 } } diff --git a/pkg/provider/acme/challenge_http.go b/pkg/provider/acme/challenge_http.go index a6eaf32d9..80d6a6c67 100644 --- a/pkg/provider/acme/challenge_http.go +++ b/pkg/provider/acme/challenge_http.go @@ -13,7 +13,8 @@ import ( "github.com/cenkalti/backoff/v4" "github.com/go-acme/lego/v4/challenge/http01" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/safe" ) @@ -70,12 +71,11 @@ func (c *ChallengeHTTP) Timeout() (timeout, interval time.Duration) { } func (c *ChallengeHTTP) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - ctx := log.With(req.Context(), log.Str(log.ProviderName, "acme")) - logger := log.FromContext(ctx) + logger := log.Ctx(req.Context()).With().Str(logs.ProviderName, "acme").Logger() token, err := getPathParam(req.URL) if err != nil { - logger.Errorf("Unable to get token: %v.", err) + logger.Error().Err(err).Msg("Unable to get token") rw.WriteHeader(http.StatusNotFound) return } @@ -83,16 +83,16 @@ func (c *ChallengeHTTP) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if token != "" { domain, _, err := net.SplitHostPort(req.Host) if err != nil { - logger.Debugf("Unable to split host and port: %v. Fallback to request host.", err) + logger.Debug().Err(err).Msg("Unable to split host and port. Fallback to request host.") domain = req.Host } - tokenValue := c.getTokenValue(ctx, token, domain) + tokenValue := c.getTokenValue(logger.WithContext(req.Context()), token, domain) if len(tokenValue) > 0 { rw.WriteHeader(http.StatusOK) _, err = rw.Write(tokenValue) if err != nil { - logger.Errorf("Unable to write token: %v", err) + logger.Error().Err(err).Msg("Unable to write token") } return } @@ -102,8 +102,8 @@ func (c *ChallengeHTTP) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } func (c *ChallengeHTTP) getTokenValue(ctx context.Context, token, domain string) []byte { - logger := log.FromContext(ctx) - logger.Debugf("Retrieving the ACME challenge for %s (token %q)...", domain, token) + logger := log.Ctx(ctx) + logger.Debug().Msgf("Retrieving the ACME challenge for %s (token %q)...", domain, token) var result []byte @@ -125,14 +125,14 @@ func (c *ChallengeHTTP) getTokenValue(ctx context.Context, token, domain string) } notify := func(err error, time time.Duration) { - logger.Errorf("Error getting challenge for token retrying in %s", time) + logger.Error().Msgf("Error getting challenge for token retrying in %s", time) } ebo := backoff.NewExponentialBackOff() ebo.MaxElapsedTime = 60 * time.Second err := backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify) if err != nil { - logger.Errorf("Cannot retrieve the ACME challenge for %s (token %q): %v", domain, token, err) + logger.Error().Err(err).Msgf("Cannot retrieve the ACME challenge for %s (token %q)", domain, token) return []byte{} } diff --git a/pkg/provider/acme/challenge_tls.go b/pkg/provider/acme/challenge_tls.go index 6249bc52e..a53f83f2b 100644 --- a/pkg/provider/acme/challenge_tls.go +++ b/pkg/provider/acme/challenge_tls.go @@ -6,8 +6,9 @@ import ( "time" "github.com/go-acme/lego/v4/challenge/tlsalpn01" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/safe" traefiktls "github.com/traefik/traefik/v2/pkg/tls" "github.com/traefik/traefik/v2/pkg/types" @@ -36,8 +37,8 @@ func NewChallengeTLSALPN() *ChallengeTLSALPN { // Present presents a challenge to obtain new ACME certificate. func (c *ChallengeTLSALPN) Present(domain, _, keyAuth string) error { - logger := log.WithoutContext().WithField(log.ProviderName, providerNameALPN) - logger.Debugf("TLS Challenge Present temp certificate for %s", domain) + logger := log.With().Str(logs.ProviderName, providerNameALPN).Logger() + logger.Debug().Msgf("TLS Challenge Present temp certificate for %s", domain) certPEMBlock, keyPEMBlock, err := tlsalpn01.ChallengeBlocks(domain, keyAuth) if err != nil { @@ -71,7 +72,7 @@ func (c *ChallengeTLSALPN) Present(domain, _, keyAuth string) error { err = c.CleanUp(domain, "", keyAuth) if err != nil { - logger.Errorf("Failed to clean up TLS challenge: %v", err) + logger.Error().Err(err).Msg("Failed to clean up TLS challenge") } return fmt.Errorf("timeout %s", t) @@ -83,8 +84,8 @@ func (c *ChallengeTLSALPN) Present(domain, _, keyAuth string) error { // CleanUp cleans the challenges when certificate is obtained. func (c *ChallengeTLSALPN) CleanUp(domain, _, keyAuth string) error { - log.WithoutContext().WithField(log.ProviderName, providerNameALPN). - Debugf("TLS Challenge CleanUp temp certificate for %s", domain) + log.Debug().Str(logs.ProviderName, providerNameALPN). + Msgf("TLS Challenge CleanUp temp certificate for %s", domain) c.muCerts.Lock() delete(c.certs, keyAuth) diff --git a/pkg/provider/acme/local_store.go b/pkg/provider/acme/local_store.go index 33084b320..57a26207b 100644 --- a/pkg/provider/acme/local_store.go +++ b/pkg/provider/acme/local_store.go @@ -6,7 +6,8 @@ import ( "os" "sync" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/safe" ) @@ -52,7 +53,7 @@ func (s *LocalStore) get(resolverName string) (*StoredData, error) { } if hasData { - logger := log.WithoutContext().WithField(log.ProviderName, "acme") + logger := log.With().Str(logs.ProviderName, "acme").Logger() f, err := os.Open(s.filename) if err != nil { @@ -76,7 +77,7 @@ func (s *LocalStore) get(resolverName string) (*StoredData, error) { for _, storedData := range s.storedData { for _, certificate := range storedData.Certificates { if len(certificate.Certificate.Certificate) == 0 || len(certificate.Key) == 0 { - logger.Debugf("Deleting empty certificate %v for %v", certificate, certificate.Domain.ToStrArray()) + logger.Debug().Msgf("Deleting empty certificate %v for %v", certificate, certificate.Domain.ToStrArray()) continue } certificates = append(certificates, certificate) @@ -101,16 +102,16 @@ func (s *LocalStore) get(resolverName string) (*StoredData, error) { // listenSaveAction listens to a chan to store ACME data in json format into `LocalStore.filename`. func (s *LocalStore) listenSaveAction() { safe.Go(func() { - logger := log.WithoutContext().WithField(log.ProviderName, "acme") + logger := log.With().Str(logs.ProviderName, "acme").Logger() for object := range s.saveDataChan { data, err := json.MarshalIndent(object, "", " ") if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() } err = os.WriteFile(s.filename, data, 0o600) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() } } }) diff --git a/pkg/provider/acme/provider.go b/pkg/provider/acme/provider.go index be211ab04..e57c84d5b 100644 --- a/pkg/provider/acme/provider.go +++ b/pkg/provider/acme/provider.go @@ -19,9 +19,10 @@ import ( "github.com/go-acme/lego/v4/lego" "github.com/go-acme/lego/v4/providers/dns" "github.com/go-acme/lego/v4/registration" + "github.com/rs/zerolog/log" ptypes "github.com/traefik/paerser/types" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" httpmuxer "github.com/traefik/traefik/v2/pkg/muxer/http" tcpmuxer "github.com/traefik/traefik/v2/pkg/muxer/tcp" "github.com/traefik/traefik/v2/pkg/safe" @@ -131,8 +132,7 @@ func (p *Provider) ListenConfiguration(config dynamic.Configuration) { // Init for compatibility reason the BaseProvider implements an empty Init. func (p *Provider) Init() error { - ctx := log.With(context.Background(), log.Str(log.ProviderName, p.ResolverName+".acme")) - logger := log.FromContext(ctx) + logger := log.With().Str(logs.ProviderName, p.ResolverName+".acme").Logger() if len(p.Configuration.Storage) == 0 { return errors.New("unable to initialize ACME provider with no storage location for the certificates") @@ -149,8 +149,8 @@ func (p *Provider) Init() error { } // Reset Account if caServer changed, thus registration URI can be updated - if p.account != nil && p.account.Registration != nil && !isAccountMatchingCaServer(ctx, p.account.Registration.URI, p.CAServer) { - logger.Info("Account URI does not match the current CAServer. The account will be reset.") + if p.account != nil && p.account.Registration != nil && !isAccountMatchingCaServer(logger.WithContext(context.Background()), p.account.Registration.URI, p.CAServer) { + logger.Info().Msg("Account URI does not match the current CAServer. The account will be reset.") p.account = nil } @@ -169,17 +169,17 @@ func (p *Provider) Init() error { } func isAccountMatchingCaServer(ctx context.Context, accountURI, serverURI string) bool { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) aru, err := url.Parse(accountURI) if err != nil { - logger.Infof("Unable to parse account.Registration URL: %v", err) + logger.Info().Err(err).Str("registrationURL", accountURI).Msg("Unable to parse account.Registration URL") return false } cau, err := url.Parse(serverURI) if err != nil { - logger.Infof("Unable to parse CAServer URL: %v", err) + logger.Info().Err(err).Str("caServerURL", serverURI).Msg("Unable to parse CAServer URL") return false } @@ -194,9 +194,9 @@ func (p *Provider) ThrottleDuration() time.Duration { // Provide allows the file provider to provide configurations to traefik // using the given Configuration channel. func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error { - ctx := log.With(context.Background(), - log.Str(log.ProviderName, p.ResolverName+".acme"), - log.Str("ACME CA", p.Configuration.CAServer)) + logger := log.With().Str(logs.ProviderName, p.ResolverName+".acme").Str("acmeCA", p.Configuration.CAServer). + Logger() + ctx := logger.WithContext(context.Background()) p.pool = pool @@ -211,7 +211,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. p.configurationChan <- msg renewPeriod, renewInterval := getCertificateRenewDurations(p.CertificatesDuration) - log.FromContext(ctx).Debugf("Attempt to renew certificates %q before expiry and check every %q", + logger.Debug().Msgf("Attempt to renew certificates %q before expiry and check every %q", renewPeriod, renewInterval) p.renewCertificates(ctx, renewPeriod) @@ -236,8 +236,9 @@ func (p *Provider) getClient() (*lego.Client, error) { p.clientMutex.Lock() defer p.clientMutex.Unlock() - ctx := log.With(context.Background(), log.Str(log.ProviderName, p.ResolverName+".acme")) - logger := log.FromContext(ctx) + logger := log.With().Str(logs.ProviderName, p.ResolverName+".acme").Logger() + + ctx := logger.WithContext(context.Background()) if p.client != nil { return p.client, nil @@ -248,13 +249,13 @@ func (p *Provider) getClient() (*lego.Client, error) { return nil, err } - logger.Debug("Building ACME client...") + logger.Debug().Msg("Building ACME client...") caServer := lego.LEDirectoryProduction if len(p.CAServer) > 0 { caServer = p.CAServer } - logger.Debug(caServer) + logger.Debug().Msg(caServer) config := lego.NewConfig(account) config.CADirURL = caServer @@ -290,7 +291,7 @@ func (p *Provider) getClient() (*lego.Client, error) { } if p.DNSChallenge != nil && len(p.DNSChallenge.Provider) > 0 { - logger.Debugf("Using DNS Challenge provider: %s", p.DNSChallenge.Provider) + logger.Debug().Msgf("Using DNS Challenge provider: %s", p.DNSChallenge.Provider) var provider challenge.Provider provider, err = dns.NewDNSChallengeProviderByName(p.DNSChallenge.Provider) @@ -302,7 +303,7 @@ func (p *Provider) getClient() (*lego.Client, error) { dns01.CondOption(len(p.DNSChallenge.Resolvers) > 0, dns01.AddRecursiveNameservers(p.DNSChallenge.Resolvers)), dns01.WrapPreCheck(func(domain, fqdn, value string, check dns01.PreCheckFunc) (bool, error) { if p.DNSChallenge.DelayBeforeCheck > 0 { - logger.Debugf("Delaying %d rather than validating DNS propagation now.", p.DNSChallenge.DelayBeforeCheck) + logger.Debug().Msgf("Delaying %d rather than validating DNS propagation now.", p.DNSChallenge.DelayBeforeCheck) time.Sleep(time.Duration(p.DNSChallenge.DelayBeforeCheck)) } @@ -319,7 +320,7 @@ func (p *Provider) getClient() (*lego.Client, error) { } if p.HTTPChallenge != nil && len(p.HTTPChallenge.EntryPoint) > 0 { - logger.Debug("Using HTTP Challenge provider.") + logger.Debug().Msg("Using HTTP Challenge provider.") err = client.Challenge.SetHTTP01Provider(p.HTTPChallengeProvider) if err != nil { @@ -328,7 +329,7 @@ func (p *Provider) getClient() (*lego.Client, error) { } if p.TLSChallenge != nil { - logger.Debug("Using TLS Challenge provider.") + logger.Debug().Msg("Using TLS Challenge provider.") err = client.Challenge.SetTLSALPN01Provider(p.TLSChallengeProvider) if err != nil { @@ -358,30 +359,30 @@ func (p *Provider) initAccount(ctx context.Context) (*Account, error) { } func (p *Provider) register(ctx context.Context, client *lego.Client) (*registration.Resource, error) { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) if p.EAB != nil { - logger.Info("Register with external account binding...") + logger.Info().Msg("Register with external account binding...") eabOptions := registration.RegisterEABOptions{TermsOfServiceAgreed: true, Kid: p.EAB.Kid, HmacEncoded: p.EAB.HmacEncoded} return client.Registration.RegisterWithExternalAccountBinding(eabOptions) } - logger.Info("Register...") + logger.Info().Msg("Register...") return client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true}) } func (p *Provider) resolveDomains(ctx context.Context, domains []string, tlsStore string) { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) if len(domains) == 0 { - logger.Debug("No domain parsed in provider ACME") + logger.Debug().Msg("No domain parsed in provider ACME") return } - logger.Debugf("Trying to challenge certificate for domain %v found in HostSNI rule", domains) + logger.Debug().Msgf("Trying to challenge certificate for domain %v found in HostSNI rule", domains) var domain types.Domain if len(domains) > 0 { @@ -393,20 +394,22 @@ func (p *Provider) resolveDomains(ctx context.Context, domains []string, tlsStor safe.Go(func() { dom, cert, err := p.resolveCertificate(ctx, domain, tlsStore) if err != nil { - logger.Errorf("Unable to obtain ACME certificate for domains %q: %v", strings.Join(domains, ","), err) + logger.Error().Err(err).Strs("domains", domains).Msg("Unable to obtain ACME certificate for domains") return } err = p.addCertificateForDomain(dom, cert, tlsStore) if err != nil { - logger.WithError(err).Error("Error adding certificate for domain") + logger.Error().Err(err).Strs("domains", dom.ToStrArray()).Msg("Error adding certificate for domains") } }) } } func (p *Provider) watchNewDomains(ctx context.Context) { - ctx = log.With(ctx, log.Str(log.ProviderName, p.ResolverName+".acme")) + rootLogger := log.Ctx(ctx).With().Str(logs.ProviderName, p.ResolverName+".acme").Logger() + ctx = rootLogger.WithContext(ctx) + p.pool.GoCtx(func(ctxPool context.Context) { for { select { @@ -417,8 +420,8 @@ func (p *Provider) watchNewDomains(ctx context.Context) { continue } - ctxRouter := log.With(ctx, log.Str(log.RouterName, routerName), log.Str(log.Rule, route.Rule)) - logger := log.FromContext(ctxRouter) + logger := rootLogger.With().Str(logs.RouterName, routerName).Str(logs.Rule, route.Rule).Logger() + ctxRouter := logger.WithContext(ctx) if len(route.TLS.Domains) > 0 { domains := deleteUnnecessaryDomains(ctxRouter, route.TLS.Domains) @@ -427,20 +430,20 @@ func (p *Provider) watchNewDomains(ctx context.Context) { safe.Go(func() { dom, cert, err := p.resolveCertificate(ctx, domain, traefiktls.DefaultTLSStoreName) if err != nil { - logger.WithError(err).Errorf("Unable to obtain ACME certificate for domains %q", strings.Join(domain.ToStrArray(), ",")) + logger.Error().Err(err).Strs("domains", domain.ToStrArray()).Msg("Unable to obtain ACME certificate for domains") return } err = p.addCertificateForDomain(dom, cert, traefiktls.DefaultTLSStoreName) if err != nil { - logger.WithError(err).Error("Error adding certificate for domain") + logger.Error().Err(err).Strs("domains", dom.ToStrArray()).Msg("Error adding certificate for domains") } }) } } else { domains, err := tcpmuxer.ParseHostSNI(route.Rule) if err != nil { - logger.WithError(err).Errorf("Error parsing domains in provider ACME") + logger.Error().Err(err).Msg("Error parsing domains in provider ACME") continue } p.resolveDomains(ctxRouter, domains, traefiktls.DefaultTLSStoreName) @@ -454,8 +457,8 @@ func (p *Provider) watchNewDomains(ctx context.Context) { continue } - ctxRouter := log.With(ctx, log.Str(log.RouterName, routerName), log.Str(log.Rule, route.Rule)) - logger := log.FromContext(ctxRouter) + logger := rootLogger.With().Str(logs.RouterName, routerName).Str(logs.Rule, route.Rule).Logger() + ctxRouter := logger.WithContext(ctx) if len(route.TLS.Domains) > 0 { domains := deleteUnnecessaryDomains(ctxRouter, route.TLS.Domains) @@ -464,20 +467,20 @@ func (p *Provider) watchNewDomains(ctx context.Context) { safe.Go(func() { dom, cert, err := p.resolveCertificate(ctx, domain, traefiktls.DefaultTLSStoreName) if err != nil { - logger.WithError(err).Errorf("Unable to obtain ACME certificate for domains %q", strings.Join(domain.ToStrArray(), ",")) + logger.Error().Err(err).Strs("domains", domain.ToStrArray()).Msg("Unable to obtain ACME certificate for domains") return } err = p.addCertificateForDomain(dom, cert, traefiktls.DefaultTLSStoreName) if err != nil { - logger.WithError(err).Error("Error adding certificate for domain") + logger.Error().Err(err).Strs("domains", dom.ToStrArray()).Msg("Error adding certificate for domain") } }) } } else { domains, err := httpmuxer.ParseDomains(route.Rule) if err != nil { - logger.WithError(err).Errorf("Error parsing domains in provider ACME") + logger.Error().Err(err).Msg("Error parsing domains in provider ACME") continue } p.resolveDomains(ctxRouter, domains, traefiktls.DefaultTLSStoreName) @@ -490,11 +493,10 @@ func (p *Provider) watchNewDomains(ctx context.Context) { } for tlsStoreName, tlsStore := range config.TLS.Stores { - ctxTLSStore := log.With(ctx, log.Str(log.TLSStoreName, tlsStoreName)) - logger := log.FromContext(ctxTLSStore) + logger := rootLogger.With().Str(logs.TLSStoreName, tlsStoreName).Logger() if tlsStore.DefaultCertificate != nil && tlsStore.DefaultGeneratedCert != nil { - logger.Warn("defaultCertificate and defaultGeneratedCert cannot be defined at the same time.") + logger.Warn().Msg("defaultCertificate and defaultGeneratedCert cannot be defined at the same time.") } // Gives precedence to the user defined default certificate. @@ -503,7 +505,7 @@ func (p *Provider) watchNewDomains(ctx context.Context) { } if tlsStore.DefaultGeneratedCert.Domain == nil || tlsStore.DefaultGeneratedCert.Resolver == "" { - logger.Warn("default generated certificate domain or resolver is missing.") + logger.Warn().Msg("default generated certificate domain or resolver is missing.") continue } @@ -513,18 +515,18 @@ func (p *Provider) watchNewDomains(ctx context.Context) { validDomains, err := p.sanitizeDomains(ctx, *tlsStore.DefaultGeneratedCert.Domain) if err != nil { - logger.WithError(err).Errorf("domains validation: %s", strings.Join(tlsStore.DefaultGeneratedCert.Domain.ToStrArray(), ",")) + logger.Error().Err(err).Strs("domains", tlsStore.DefaultGeneratedCert.Domain.ToStrArray()).Msg("domains validation") } if p.certExists(validDomains) { - logger.Debug("Default ACME certificate generation is not required.") + logger.Debug().Msg("Default ACME certificate generation is not required.") continue } safe.Go(func() { cert, err := p.resolveDefaultCertificate(ctx, validDomains) if err != nil { - logger.WithError(err).Errorf("Unable to obtain ACME certificate for domain %q", strings.Join(validDomains, ",")) + logger.Error().Err(err).Strs("domains", validDomains).Msgf("Unable to obtain ACME certificate for domain") return } @@ -537,7 +539,7 @@ func (p *Provider) watchNewDomains(ctx context.Context) { err = p.addCertificateForDomain(domain, cert, traefiktls.DefaultTLSStoreName) if err != nil { - logger.WithError(err).Error("Error adding certificate for domain") + logger.Error().Err(err).Msg("Error adding certificate for domain") } }) } @@ -549,7 +551,7 @@ func (p *Provider) watchNewDomains(ctx context.Context) { } func (p *Provider) resolveDefaultCertificate(ctx context.Context, domains []string) (*certificate.Resource, error) { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) p.resolvingDomainsMutex.Lock() @@ -571,7 +573,7 @@ func (p *Provider) resolveDefaultCertificate(ctx context.Context, domains []stri defer p.removeResolvingDomains(append(domains, domainKey)) - logger.Debugf("Loading ACME certificates %+v...", domains) + logger.Debug().Msgf("Loading ACME certificates %+v...", domains) client, err := p.getClient() if err != nil { @@ -596,7 +598,7 @@ func (p *Provider) resolveDefaultCertificate(ctx context.Context, domains []stri return nil, fmt.Errorf("certificate for domains %v is empty: %v", domains, cert) } - logger.Debugf("Default certificate obtained for domains %+v", domains) + logger.Debug().Msgf("Default certificate obtained for domains %+v", domains) return cert, nil } @@ -615,8 +617,8 @@ func (p *Provider) resolveCertificate(ctx context.Context, domain types.Domain, defer p.removeResolvingDomains(uncheckedDomains) - logger := log.FromContext(ctx) - logger.Debugf("Loading ACME certificates %+v...", uncheckedDomains) + logger := log.Ctx(ctx) + logger.Debug().Msgf("Loading ACME certificates %+v...", uncheckedDomains) client, err := p.getClient() if err != nil { @@ -641,7 +643,7 @@ func (p *Provider) resolveCertificate(ctx context.Context, domain types.Domain, return types.Domain{}, nil, fmt.Errorf("certificate for domains %v is empty: %v", uncheckedDomains, cert) } - logger.Debugf("Certificates obtained for domains %+v", uncheckedDomains) + logger.Debug().Msgf("Certificates obtained for domains %+v", uncheckedDomains) domain = types.Domain{Main: uncheckedDomains[0]} if len(uncheckedDomains) > 1 { @@ -712,7 +714,7 @@ func getCertificateRenewDurations(certificatesDuration int) (time.Duration, time func deleteUnnecessaryDomains(ctx context.Context, domains []types.Domain) []types.Domain { var newDomains []types.Domain - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) for idxDomainToCheck, domainToCheck := range domains { keepDomain := true @@ -724,7 +726,7 @@ func deleteUnnecessaryDomains(ctx context.Context, domains []types.Domain) []typ if reflect.DeepEqual(domain, domainToCheck) { if idxDomainToCheck > idxDomain { - logger.Warnf("The domain %v is duplicated in the configuration but will be process by ACME provider only once.", domainToCheck) + logger.Warn().Msgf("The domain %v is duplicated in the configuration but will be process by ACME provider only once.", domainToCheck) keepDomain = false } break @@ -736,11 +738,11 @@ func deleteUnnecessaryDomains(ctx context.Context, domains []types.Domain) []typ for _, domainProcessed := range domainToCheck.ToStrArray() { if idxDomain < idxDomainToCheck && isDomainAlreadyChecked(domainProcessed, domain.ToStrArray()) { // The domain is duplicated in a CN - logger.Warnf("Domain %q is duplicated in the configuration or validated by the domain %v. It will be processed once.", domainProcessed, domain) + logger.Warn().Msgf("Domain %q is duplicated in the configuration or validated by the domain %v. It will be processed once.", domainProcessed, domain) continue } else if domain.Main != domainProcessed && strings.HasPrefix(domain.Main, "*") && isDomainAlreadyChecked(domainProcessed, []string{domain.Main}) { // Check if a wildcard can validate the domain - logger.Warnf("Domain %q will not be processed by ACME provider because it is validated by the wildcard %q", domainProcessed, domain.Main) + logger.Warn().Msgf("Domain %q will not be processed by ACME provider because it is validated by the wildcard %q", domainProcessed, domain.Main) continue } newDomainsToCheck = append(newDomainsToCheck, domainProcessed) @@ -791,9 +793,9 @@ func (p *Provider) buildMessage() dynamic.Message { } func (p *Provider) renewCertificates(ctx context.Context, renewPeriod time.Duration) { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) - logger.Info("Testing certificate renew...") + logger.Info().Msg("Testing certificate renew...") p.certificatesMu.RLock() @@ -811,11 +813,11 @@ func (p *Provider) renewCertificates(ctx context.Context, renewPeriod time.Durat for _, cert := range certificates { client, err := p.getClient() if err != nil { - logger.WithError(err).Infof("Error renewing certificate from LE : %+v", cert.Domain) + logger.Info().Err(err).Msgf("Error renewing certificate from LE : %+v", cert.Domain) continue } - logger.Infof("Renewing certificate from LE : %+v", cert.Domain) + logger.Info().Msgf("Renewing certificate from LE : %+v", cert.Domain) renewedCert, err := client.Certificate.Renew(certificate.Resource{ Domain: cert.Domain.Main, @@ -823,18 +825,18 @@ func (p *Provider) renewCertificates(ctx context.Context, renewPeriod time.Durat Certificate: cert.Certificate.Certificate, }, true, ocspMustStaple, p.PreferredChain) if err != nil { - logger.WithError(err).Errorf("Error renewing certificate from LE: %v", cert.Domain) + logger.Error().Err(err).Msgf("Error renewing certificate from LE: %v", cert.Domain) continue } if len(renewedCert.Certificate) == 0 || len(renewedCert.PrivateKey) == 0 { - logger.Errorf("domains %v renew certificate with no value: %v", cert.Domain.ToStrArray(), cert) + logger.Error().Msgf("domains %v renew certificate with no value: %v", cert.Domain.ToStrArray(), cert) continue } err = p.addCertificateForDomain(cert.Domain, renewedCert, cert.Store) if err != nil { - logger.WithError(err).Error("Error adding certificate for domain") + logger.Error().Err(err).Msg("Error adding certificate for domain") } } } @@ -842,7 +844,7 @@ func (p *Provider) renewCertificates(ctx context.Context, renewPeriod time.Durat // Get provided certificate which check a domains list (Main and SANs) // from static and dynamic provided certificates. func (p *Provider) getUncheckedDomains(ctx context.Context, domainsToCheck []string, tlsStore string) []string { - log.FromContext(ctx).Debugf("Looking for provided certificate(s) to validate %q...", domainsToCheck) + log.Ctx(ctx).Debug().Msgf("Looking for provided certificate(s) to validate %q...", domainsToCheck) var allDomains []string store := p.tlsManager.GetStore(tlsStore) @@ -884,21 +886,24 @@ func searchUncheckedDomains(ctx context.Context, domainsToCheck, existentDomains } } - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) if len(uncheckedDomains) == 0 { - logger.Debugf("No ACME certificate generation required for domains %q.", domainsToCheck) + logger.Debug().Strs("domains", domainsToCheck).Msg("No ACME certificate generation required for domains") } else { - logger.Debugf("Domains %q need ACME certificates generation for domains %q.", domainsToCheck, strings.Join(uncheckedDomains, ",")) + logger.Debug().Strs("domains", domainsToCheck).Msgf("Domains need ACME certificates generation for domains %q.", strings.Join(uncheckedDomains, ",")) } return uncheckedDomains } func getX509Certificate(ctx context.Context, cert *Certificate) (*x509.Certificate, error) { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) tlsCert, err := tls.X509KeyPair(cert.Certificate, cert.Key) if err != nil { - logger.WithError(err).Errorf("Failed to load TLS key pair from ACME certificate for domain %q (SAN : %q), certificate will be renewed", cert.Domain.Main, strings.Join(cert.Domain.SANs, ",")) + logger.Error().Err(err). + Str("domain", cert.Domain.Main). + Strs("SANs", cert.Domain.SANs). + Msg("Failed to load TLS key pair from ACME certificate for domain, certificate will be renewed") return nil, err } @@ -906,7 +911,10 @@ func getX509Certificate(ctx context.Context, cert *Certificate) (*x509.Certifica if crt == nil { crt, err = x509.ParseCertificate(tlsCert.Certificate[0]) if err != nil { - logger.WithError(err).Errorf("Failed to parse TLS key pair from ACME certificate for domain %q (SAN : %q), certificate will be renewed", cert.Domain.Main, strings.Join(cert.Domain.SANs, ",")) + logger.Error().Err(err). + Str("domain", cert.Domain.Main). + Strs("SANs", cert.Domain.SANs). + Msg("Failed to parse TLS key pair from ACME certificate for domain, certificate will be renewed") } } @@ -935,7 +943,7 @@ func (p *Provider) sanitizeDomains(ctx context.Context, domain types.Domain) ([] canonicalDomain := types.CanonicalDomain(dom) cleanDomain := dns01.UnFqdn(canonicalDomain) if canonicalDomain != cleanDomain { - log.FromContext(ctx).Warnf("FQDN detected, please remove the trailing dot: %s", canonicalDomain) + log.Ctx(ctx).Warn().Msgf("FQDN detected, please remove the trailing dot: %s", canonicalDomain) } cleanDomains = append(cleanDomains, cleanDomain) diff --git a/pkg/provider/aggregator/aggregator.go b/pkg/provider/aggregator/aggregator.go index 3ddb1c3f2..8001711fc 100644 --- a/pkg/provider/aggregator/aggregator.go +++ b/pkg/provider/aggregator/aggregator.go @@ -4,9 +4,9 @@ import ( "context" "time" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/provider/file" "github.com/traefik/traefik/v2/pkg/provider/traefik" @@ -148,7 +148,7 @@ func NewProviderAggregator(conf static.Providers) ProviderAggregator { func (p *ProviderAggregator) quietAddProvider(provider provider.Provider) { err := p.AddProvider(provider) if err != nil { - log.WithoutContext().Errorf("Error while initializing provider %T: %v", provider, err) + log.Error().Err(err).Msgf("Error while initializing provider %T", provider) } } @@ -201,14 +201,14 @@ func (p ProviderAggregator) Provide(configurationChan chan<- dynamic.Message, po func (p ProviderAggregator) launchProvider(configurationChan chan<- dynamic.Message, pool *safe.Pool, prd provider.Provider) { jsonConf, err := redactor.RemoveCredentials(prd) if err != nil { - log.WithoutContext().Debugf("Cannot marshal the provider configuration %T: %v", prd, err) + log.Debug().Err(err).Msgf("Cannot marshal the provider configuration %T", prd) } - log.WithoutContext().Infof("Starting provider %T", prd) - log.WithoutContext().Debugf("%T provider configuration: %s", prd, jsonConf) + log.Info().Msgf("Starting provider %T", prd) + log.Debug().RawJSON("config", []byte(jsonConf)).Msgf("%T provider configuration", prd) if err := maybeThrottledProvide(prd, p.providersThrottleDuration)(configurationChan, pool); err != nil { - log.WithoutContext().Errorf("Cannot start the provider %T: %v", prd, err) + log.Error().Err(err).Msgf("Cannot start the provider %T", prd) return } } diff --git a/pkg/provider/configuration.go b/pkg/provider/configuration.go index 1000e696f..c0119c885 100644 --- a/pkg/provider/configuration.go +++ b/pkg/provider/configuration.go @@ -10,13 +10,14 @@ import ( "unicode" "github.com/Masterminds/sprig/v3" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" ) // Merge Merges multiple configurations. func Merge(ctx context.Context, configurations map[string]*dynamic.Configuration) *dynamic.Configuration { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) configuration := &dynamic.Configuration{ HTTP: &dynamic.HTTPConfiguration{ @@ -136,56 +137,56 @@ func Merge(ctx context.Context, configurations map[string]*dynamic.Configuration } for serviceName := range servicesToDelete { - logger.WithField(log.ServiceName, serviceName). - Errorf("Service defined multiple times with different configurations in %v", services[serviceName]) + logger.Error().Str(logs.ServiceName, serviceName). + Msgf("Service defined multiple times with different configurations in %v", services[serviceName]) delete(configuration.HTTP.Services, serviceName) } for routerName := range routersToDelete { - logger.WithField(log.RouterName, routerName). - Errorf("Router defined multiple times with different configurations in %v", routers[routerName]) + logger.Error().Str(logs.RouterName, routerName). + Msgf("Router defined multiple times with different configurations in %v", routers[routerName]) delete(configuration.HTTP.Routers, routerName) } for transportName := range transportsToDelete { - logger.WithField(log.ServersTransportName, transportName). - Errorf("ServersTransport defined multiple times with different configurations in %v", transports[transportName]) + logger.Error().Str(logs.ServersTransportName, transportName). + Msgf("ServersTransport defined multiple times with different configurations in %v", transports[transportName]) delete(configuration.HTTP.ServersTransports, transportName) } for serviceName := range servicesTCPToDelete { - logger.WithField(log.ServiceName, serviceName). - Errorf("Service TCP defined multiple times with different configurations in %v", servicesTCP[serviceName]) + logger.Error().Str(logs.ServiceName, serviceName). + Msgf("Service TCP defined multiple times with different configurations in %v", servicesTCP[serviceName]) delete(configuration.TCP.Services, serviceName) } for routerName := range routersTCPToDelete { - logger.WithField(log.RouterName, routerName). - Errorf("Router TCP defined multiple times with different configurations in %v", routersTCP[routerName]) + logger.Error().Str(logs.RouterName, routerName). + Msgf("Router TCP defined multiple times with different configurations in %v", routersTCP[routerName]) delete(configuration.TCP.Routers, routerName) } for serviceName := range servicesUDPToDelete { - logger.WithField(log.ServiceName, serviceName). - Errorf("UDP service defined multiple times with different configurations in %v", servicesUDP[serviceName]) + logger.Error().Str(logs.ServiceName, serviceName). + Msgf("UDP service defined multiple times with different configurations in %v", servicesUDP[serviceName]) delete(configuration.UDP.Services, serviceName) } for routerName := range routersUDPToDelete { - logger.WithField(log.RouterName, routerName). - Errorf("UDP router defined multiple times with different configurations in %v", routersUDP[routerName]) + logger.Error().Str(logs.RouterName, routerName). + Msgf("UDP router defined multiple times with different configurations in %v", routersUDP[routerName]) delete(configuration.UDP.Routers, routerName) } for middlewareName := range middlewaresToDelete { - logger.WithField(log.MiddlewareName, middlewareName). - Errorf("Middleware defined multiple times with different configurations in %v", middlewares[middlewareName]) + logger.Error().Str(logs.MiddlewareName, middlewareName). + Msgf("Middleware defined multiple times with different configurations in %v", middlewares[middlewareName]) delete(configuration.HTTP.Middlewares, middlewareName) } for middlewareName := range middlewaresTCPToDelete { - logger.WithField(log.MiddlewareName, middlewareName). - Errorf("TCP Middleware defined multiple times with different configurations in %v", middlewaresTCP[middlewareName]) + logger.Error().Str(logs.MiddlewareName, middlewareName). + Msgf("TCP Middleware defined multiple times with different configurations in %v", middlewaresTCP[middlewareName]) delete(configuration.TCP.Middlewares, middlewareName) } @@ -342,18 +343,19 @@ func MakeDefaultRuleTemplate(defaultRule string, funcMap template.FuncMap) (*tem // BuildTCPRouterConfiguration Builds a router configuration. func BuildTCPRouterConfiguration(ctx context.Context, configuration *dynamic.TCPConfiguration) { for routerName, router := range configuration.Routers { - loggerRouter := log.FromContext(ctx).WithField(log.RouterName, routerName) + loggerRouter := log.Ctx(ctx).With().Str(logs.RouterName, routerName).Logger() + if len(router.Rule) == 0 { delete(configuration.Routers, routerName) - loggerRouter.Errorf("Empty rule") + loggerRouter.Error().Msg("Empty rule") continue } if len(router.Service) == 0 { if len(configuration.Services) > 1 { delete(configuration.Routers, routerName) - loggerRouter. - Error("Could not define the service name for the router: too many services") + loggerRouter.Error(). + Msg("Could not define the service name for the router: too many services") continue } @@ -367,7 +369,8 @@ func BuildTCPRouterConfiguration(ctx context.Context, configuration *dynamic.TCP // BuildUDPRouterConfiguration Builds a router configuration. func BuildUDPRouterConfiguration(ctx context.Context, configuration *dynamic.UDPConfiguration) { for routerName, router := range configuration.Routers { - loggerRouter := log.FromContext(ctx).WithField(log.RouterName, routerName) + loggerRouter := log.Ctx(ctx).With().Str(logs.RouterName, routerName).Logger() + if len(router.Service) > 0 { continue } @@ -375,7 +378,7 @@ func BuildUDPRouterConfiguration(ctx context.Context, configuration *dynamic.UDP if len(configuration.Services) > 1 { delete(configuration.Routers, routerName) loggerRouter. - Error("Could not define the service name for the router: too many services") + Error().Msg("Could not define the service name for the router: too many services") continue } @@ -390,7 +393,7 @@ func BuildUDPRouterConfiguration(ctx context.Context, configuration *dynamic.UDP func BuildRouterConfiguration(ctx context.Context, configuration *dynamic.HTTPConfiguration, defaultRouterName string, defaultRuleTpl *template.Template, model interface{}) { if len(configuration.Routers) == 0 { if len(configuration.Services) > 1 { - log.FromContext(ctx).Info("Could not create a router for the container: too many services") + log.Ctx(ctx).Info().Msg("Could not create a router for the container: too many services") } else { configuration.Routers = make(map[string]*dynamic.Router) configuration.Routers[defaultRouterName] = &dynamic.Router{} @@ -398,18 +401,19 @@ func BuildRouterConfiguration(ctx context.Context, configuration *dynamic.HTTPCo } for routerName, router := range configuration.Routers { - loggerRouter := log.FromContext(ctx).WithField(log.RouterName, routerName) + loggerRouter := log.Ctx(ctx).With().Str(logs.RouterName, routerName).Logger() + if len(router.Rule) == 0 { writer := &bytes.Buffer{} if err := defaultRuleTpl.Execute(writer, model); err != nil { - loggerRouter.Errorf("Error while parsing default rule: %v", err) + loggerRouter.Error().Err(err).Msg("Error while parsing default rule") delete(configuration.Routers, routerName) continue } router.Rule = writer.String() if len(router.Rule) == 0 { - loggerRouter.Error("Undefined rule") + loggerRouter.Error().Msg("Undefined rule") delete(configuration.Routers, routerName) continue } @@ -418,8 +422,8 @@ func BuildRouterConfiguration(ctx context.Context, configuration *dynamic.HTTPCo if len(router.Service) == 0 { if len(configuration.Services) > 1 { delete(configuration.Routers, routerName) - loggerRouter. - Error("Could not define the service name for the router: too many services") + loggerRouter.Error(). + Msg("Could not define the service name for the router: too many services") continue } diff --git a/pkg/provider/consulcatalog/config.go b/pkg/provider/consulcatalog/config.go index aaa2aa724..af8e7830c 100644 --- a/pkg/provider/consulcatalog/config.go +++ b/pkg/provider/consulcatalog/config.go @@ -10,9 +10,10 @@ import ( "strings" "github.com/hashicorp/consul/api" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/label" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/provider/constraints" ) @@ -22,17 +23,17 @@ func (p *Provider) buildConfiguration(ctx context.Context, items []itemData, cer for _, item := range items { svcName := provider.Normalize(item.Node + "-" + item.Name + "-" + item.ID) - ctxSvc := log.With(ctx, log.Str(log.ServiceName, svcName)) + + logger := log.Ctx(ctx).With().Str(logs.ServiceName, svcName).Logger() + ctxSvc := logger.WithContext(ctx) if !p.keepContainer(ctxSvc, item) { continue } - logger := log.FromContext(ctxSvc) - confFromLabel, err := label.DecodeConfiguration(item.Labels) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } @@ -41,7 +42,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, items []itemData, cer tcpOrUDP = true if err := p.buildTCPServiceConfiguration(item, confFromLabel.TCP); err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } @@ -52,7 +53,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, items []itemData, cer tcpOrUDP = true if err := p.buildUDPServiceConfiguration(item, confFromLabel.UDP); err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } provider.BuildUDPRouterConfiguration(ctxSvc, confFromLabel.UDP) @@ -77,7 +78,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, items []itemData, cer } if err = p.buildServiceConfiguration(item, confFromLabel.HTTP); err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } @@ -98,30 +99,30 @@ func (p *Provider) buildConfiguration(ctx context.Context, items []itemData, cer } func (p *Provider) keepContainer(ctx context.Context, item itemData) bool { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) if !item.ExtraConf.Enable { - logger.Debug("Filtering disabled item") + logger.Debug().Msg("Filtering disabled item") return false } if !p.ConnectAware && item.ExtraConf.ConsulCatalog.Connect { - logger.Debugf("Filtering out Connect aware item, Connect support is not enabled") + logger.Debug().Msg("Filtering out Connect aware item, Connect support is not enabled") return false } matches, err := constraints.MatchTags(item.Tags, p.Constraints) if err != nil { - logger.Errorf("Error matching constraint expressions: %v", err) + logger.Error().Err(err).Msg("Error matching constraint expressions") return false } if !matches { - logger.Debugf("Container pruned by constraint expressions: %q", p.Constraints) + logger.Debug().Msgf("Container pruned by constraint expressions: %q", p.Constraints) return false } if item.Status != api.HealthPassing && item.Status != api.HealthWarning { - logger.Debug("Filtering unhealthy or starting item") + logger.Debug().Msg("Filtering unhealthy or starting item") return false } diff --git a/pkg/provider/consulcatalog/consul_catalog.go b/pkg/provider/consulcatalog/consul_catalog.go index effd67cac..dc0b82267 100644 --- a/pkg/provider/consulcatalog/consul_catalog.go +++ b/pkg/provider/consulcatalog/consul_catalog.go @@ -11,11 +11,12 @@ import ( "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/api/watch" "github.com/hashicorp/go-hclog" - "github.com/sirupsen/logrus" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" ptypes "github.com/traefik/paerser/types" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/job" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/provider/constraints" "github.com/traefik/traefik/v2/pkg/safe" @@ -58,7 +59,7 @@ func (p *ProviderBuilder) BuildProviders() []*Provider { // We can warn about that, because we've already made sure before that // Namespace and Namespaces are mutually exclusive. if p.Namespace != "" { - log.WithoutContext().Warnf("Namespace option is deprecated, please use the Namespaces option instead.") + log.Warn().Msg("Namespace option is deprecated, please use the Namespaces option instead.") } if len(p.Namespaces) == 0 { @@ -166,8 +167,8 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } pool.GoCtx(func(routineCtx context.Context) { - ctxLog := log.With(routineCtx, log.Str(log.ProviderName, p.name)) - logger := log.FromContext(ctxLog) + logger := log.Ctx(routineCtx).With().Str(logs.ProviderName, p.name).Logger() + ctxLog := logger.WithContext(routineCtx) operation := func() error { ctx, cancel := context.WithCancel(ctxLog) @@ -194,7 +195,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. // that gets resolved before the certificates are available // will cause an error condition. if p.ConnectAware && !certInfo.isReady() { - logger.Infof("Waiting for Connect certificate before building first configuration") + logger.Info().Msg("Waiting for Connect certificate before building first configuration") select { case <-ctx.Done(): return nil @@ -242,12 +243,12 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } notify := func(err error, time time.Duration) { - logger.Errorf("Provider connection error %+v, retrying in %s", err, time) + logger.Error().Err(err).Msgf("Provider connection error, retrying in %s", time) } err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctxLog), notify) if err != nil { - logger.Errorf("Cannot connect to consul catalog server %+v", err) + logger.Error().Err(err).Msg("Cannot connect to consul catalog server") } }) @@ -281,32 +282,32 @@ func (p *Provider) getConsulServicesData(ctx context.Context) ([]itemData, error var data []itemData for name, tags := range serviceNames { - logger := log.FromContext(log.With(ctx, log.Str("serviceName", name))) + logger := log.Ctx(ctx).With().Str("serviceName", name).Logger() extraConf, err := p.getExtraConf(tagsToNeutralLabels(tags, p.Prefix)) if err != nil { - logger.Errorf("Skip service: %v", err) + logger.Error().Err(err).Msg("Skip service") continue } if !extraConf.Enable { - logger.Debug("Filtering disabled item") + logger.Debug().Msg("Filtering disabled item") continue } matches, err := constraints.MatchTags(tags, p.Constraints) if err != nil { - logger.Errorf("Error matching constraint expressions: %v", err) + logger.Error().Err(err).Msg("Error matching constraint expressions") continue } if !matches { - logger.Debugf("Container pruned by constraint expressions: %q", p.Constraints) + logger.Debug().Msgf("Container pruned by constraint expressions: %q", p.Constraints) continue } if !p.ConnectAware && extraConf.ConsulCatalog.Connect { - logger.Debugf("Filtering out Connect aware item, Connect support is not enabled") + logger.Debug().Msg("Filtering out Connect aware item, Connect support is not enabled") continue } @@ -346,7 +347,7 @@ func (p *Provider) getConsulServicesData(ctx context.Context) ([]itemData, error extraConf, err := p.getExtraConf(item.Labels) if err != nil { - log.FromContext(ctx).Errorf("Skip item %s: %v", item.Name, err) + log.Ctx(ctx).Error().Err(err).Msgf("Skip item %s", item.Name) continue } item.ExtraConf = extraConf @@ -424,8 +425,9 @@ func (p *Provider) watchServices(ctx context.Context) error { logger := hclog.New(&hclog.LoggerOptions{ Name: "consulcatalog", - Level: hclog.LevelFromString(logrus.GetLevel().String()), + Level: hclog.LevelFromString(log.Logger.GetLevel().String()), JSONFormat: true, + Output: logs.NoLevel(log.Logger, zerolog.DebugLevel), }) errChan := make(chan error, 2) @@ -455,13 +457,13 @@ func (p *Provider) watchServices(ctx context.Context) error { func rootsWatchHandler(ctx context.Context, dest chan<- []string) func(watch.BlockingParamVal, interface{}) { return func(_ watch.BlockingParamVal, raw interface{}) { if raw == nil { - log.FromContext(ctx).Errorf("Root certificate watcher called with nil") + log.Ctx(ctx).Error().Msg("Root certificate watcher called with nil") return } v, ok := raw.(*api.CARootList) if !ok || v == nil { - log.FromContext(ctx).Errorf("Invalid result for root certificate watcher") + log.Ctx(ctx).Error().Msg("Invalid result for root certificate watcher") return } @@ -485,13 +487,13 @@ type keyPair struct { func leafWatcherHandler(ctx context.Context, dest chan<- keyPair) func(watch.BlockingParamVal, interface{}) { return func(_ watch.BlockingParamVal, raw interface{}) { if raw == nil { - log.FromContext(ctx).Errorf("Leaf certificate watcher called with nil") + log.Ctx(ctx).Error().Msg("Leaf certificate watcher called with nil") return } v, ok := raw.(*api.LeafCert) if !ok || v == nil { - log.FromContext(ctx).Errorf("Invalid result for leaf certificate watcher") + log.Ctx(ctx).Error().Msg("Invalid result for leaf certificate watcher") return } @@ -531,8 +533,9 @@ func (p *Provider) watchConnectTLS(ctx context.Context) error { hclogger := hclog.New(&hclog.LoggerOptions{ Name: "consulcatalog", - Level: hclog.LevelFromString(logrus.GetLevel().String()), + Level: hclog.LevelFromString(log.Logger.GetLevel().String()), JSONFormat: true, + Output: logs.NoLevel(log.Logger, zerolog.DebugLevel), }) errChan := make(chan error, 2) @@ -573,7 +576,7 @@ func (p *Provider) watchConnectTLS(ctx context.Context) error { leaf: leafCerts, } if newCertInfo.isReady() && !newCertInfo.equals(certInfo) { - log.FromContext(ctx).Debugf("Updating connect certs for service %s", p.ServiceName) + log.Ctx(ctx).Debug().Msgf("Updating connect certs for service %s", p.ServiceName) certInfo = newCertInfo diff --git a/pkg/provider/docker/config.go b/pkg/provider/docker/config.go index f006d7b57..e23575caf 100644 --- a/pkg/provider/docker/config.go +++ b/pkg/provider/docker/config.go @@ -9,9 +9,10 @@ import ( dockertypes "github.com/docker/docker/api/types" "github.com/docker/go-connections/nat" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/label" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/provider/constraints" ) @@ -21,17 +22,17 @@ func (p *Provider) buildConfiguration(ctx context.Context, containersInspected [ for _, container := range containersInspected { containerName := getServiceName(container) + "-" + container.ID - ctxContainer := log.With(ctx, log.Str("container", containerName)) + + logger := log.Ctx(ctx).With().Str("container", containerName).Logger() + ctxContainer := logger.WithContext(ctx) if !p.keepContainer(ctxContainer, container) { continue } - logger := log.FromContext(ctxContainer) - confFromLabel, err := label.DecodeConfiguration(container.Labels) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } @@ -41,7 +42,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, containersInspected [ err := p.buildTCPServiceConfiguration(ctxContainer, container, confFromLabel.TCP) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } provider.BuildTCPRouterConfiguration(ctxContainer, confFromLabel.TCP) @@ -52,7 +53,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, containersInspected [ err := p.buildUDPServiceConfiguration(ctxContainer, container, confFromLabel.UDP) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } provider.BuildUDPRouterConfiguration(ctxContainer, confFromLabel.UDP) @@ -67,7 +68,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, containersInspected [ err = p.buildServiceConfiguration(ctxContainer, container, confFromLabel.HTTP) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } @@ -106,7 +107,7 @@ func (p *Provider) buildTCPServiceConfiguration(ctx context.Context, container d } for name, service := range configuration.Services { - ctx := log.With(ctx, log.Str(log.ServiceName, name)) + ctx := log.Ctx(ctx).With().Str(logs.ServiceName, name).Logger().WithContext(ctx) if err := p.addServerTCP(ctx, container, service.LoadBalancer); err != nil { return fmt.Errorf("service %q error: %w", name, err) } @@ -130,7 +131,7 @@ func (p *Provider) buildUDPServiceConfiguration(ctx context.Context, container d } for name, service := range configuration.Services { - ctx := log.With(ctx, log.Str(log.ServiceName, name)) + ctx := log.Ctx(ctx).With().Str(logs.ServiceName, name).Logger().WithContext(ctx) if err := p.addServerUDP(ctx, container, service.LoadBalancer); err != nil { return fmt.Errorf("service %q error: %w", name, err) } @@ -156,7 +157,7 @@ func (p *Provider) buildServiceConfiguration(ctx context.Context, container dock } for name, service := range configuration.Services { - ctx := log.With(ctx, log.Str(log.ServiceName, name)) + ctx := log.Ctx(ctx).With().Str(logs.ServiceName, name).Logger().WithContext(ctx) if err := p.addServer(ctx, container, service.LoadBalancer); err != nil { return fmt.Errorf("service %q error: %w", name, err) } @@ -166,25 +167,25 @@ func (p *Provider) buildServiceConfiguration(ctx context.Context, container dock } func (p *Provider) keepContainer(ctx context.Context, container dockerData) bool { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) if !container.ExtraConf.Enable { - logger.Debug("Filtering disabled container") + logger.Debug().Msg("Filtering disabled container") return false } matches, err := constraints.MatchLabels(container.Labels, p.Constraints) if err != nil { - logger.Errorf("Error matching constraints expression: %v", err) + logger.Error().Err(err).Msg("Error matching constraints expression") return false } if !matches { - logger.Debugf("Container pruned by constraint expression: %q", p.Constraints) + logger.Debug().Msgf("Container pruned by constraint expression: %q", p.Constraints) return false } if !p.AllowEmptyServices && container.Health != "" && container.Health != dockertypes.Healthy { - logger.Debug("Filtering unhealthy or starting container") + logger.Debug().Msg("Filtering unhealthy or starting container") return false } @@ -274,7 +275,7 @@ func (p *Provider) addServer(ctx context.Context, container dockerData, loadBala } func (p *Provider) getIPPort(ctx context.Context, container dockerData, serverPort string) (string, string, error) { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) var ip, port string usedBound := false @@ -283,9 +284,9 @@ func (p *Provider) getIPPort(ctx context.Context, container dockerData, serverPo portBinding, err := p.getPortBinding(container, serverPort) switch { case err != nil: - logger.Infof("Unable to find a binding for container %q, falling back on its internal IP/Port.", container.Name) + logger.Info().Msgf("Unable to find a binding for container %q, falling back on its internal IP/Port.", container.Name) case portBinding.HostIP == "0.0.0.0" || len(portBinding.HostIP) == 0: - logger.Infof("Cannot determine the IP address (got %q) for %q's binding, falling back on its internal IP/Port.", portBinding.HostIP, container.Name) + logger.Info().Msgf("Cannot determine the IP address (got %q) for %q's binding, falling back on its internal IP/Port.", portBinding.HostIP, container.Name) default: ip = portBinding.HostIP port = portBinding.HostPort @@ -306,7 +307,7 @@ func (p *Provider) getIPPort(ctx context.Context, container dockerData, serverPo } func (p Provider) getIPAddress(ctx context.Context, container dockerData) string { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) if container.ExtraConf.Docker.Network != "" { settings := container.NetworkSettings @@ -316,7 +317,7 @@ func (p Provider) getIPAddress(ctx context.Context, container dockerData) string return network.Addr } - logger.Warnf("Could not find network named '%s' for container '%s'! Maybe you're missing the project's prefix in the label? Defaulting to first available network.", container.ExtraConf.Docker.Network, container.Name) + logger.Warn().Msgf("Could not find network named '%s' for container '%s'! Maybe you're missing the project's prefix in the label? Defaulting to first available network.", container.ExtraConf.Docker.Network, container.Name) } } @@ -336,14 +337,14 @@ func (p Provider) getIPAddress(ctx context.Context, container dockerData) string if container.NetworkSettings.NetworkMode.IsContainer() { dockerClient, err := p.createClient() if err != nil { - logger.Warnf("Unable to get IP address: %s", err) + logger.Warn().Err(err).Msg("Unable to get IP address") return "" } connectedContainer := container.NetworkSettings.NetworkMode.ConnectedContainer() containerInspected, err := dockerClient.ContainerInspect(context.Background(), connectedContainer) if err != nil { - logger.Warnf("Unable to get IP address for container %s : Failed to inspect container ID %s, error: %s", container.Name, connectedContainer, err) + logger.Warn().Err(err).Msgf("Unable to get IP address for container %s: failed to inspect container ID %s", container.Name, connectedContainer) return "" } @@ -352,7 +353,7 @@ func (p Provider) getIPAddress(ctx context.Context, container dockerData) string containerParsed := parseContainer(containerInspected) extraConf, err := p.getConfiguration(containerParsed) if err != nil { - logger.Warnf("Unable to get IP address for container %s : failed to get extra configuration for container %s: %s", container.Name, containerInspected.Name, err) + logger.Warn().Err(err).Msgf("Unable to get IP address for container %s : failed to get extra configuration for container %s", container.Name, containerInspected.Name) return "" } @@ -368,7 +369,7 @@ func (p Provider) getIPAddress(ctx context.Context, container dockerData) string return network.Addr } - logger.Warn("Unable to find the IP address.") + logger.Warn().Msg("Unable to find the IP address.") return "" } diff --git a/pkg/provider/docker/docker.go b/pkg/provider/docker/docker.go index 0516620ce..eefd737ad 100644 --- a/pkg/provider/docker/docker.go +++ b/pkg/provider/docker/docker.go @@ -23,10 +23,11 @@ import ( "github.com/docker/docker/client" "github.com/docker/go-connections/nat" "github.com/docker/go-connections/sockets" + "github.com/rs/zerolog/log" ptypes "github.com/traefik/paerser/types" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/job" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/types" @@ -162,7 +163,7 @@ func (p *Provider) getClientOpts() ([]client.Opt, error) { } if p.TLS != nil { - ctx := log.With(context.Background(), log.Str(log.ProviderName, "docker")) + ctx := log.With().Str(logs.ProviderName, "docker").Logger().WithContext(context.Background()) conf, err := p.TLS.CreateTLSConfig(ctx) if err != nil { @@ -191,40 +192,41 @@ func (p *Provider) getClientOpts() ([]client.Opt, error) { // Provide allows the docker provider to provide configurations to traefik using the given configuration channel. func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error { pool.GoCtx(func(routineCtx context.Context) { - ctxLog := log.With(routineCtx, log.Str(log.ProviderName, "docker")) - logger := log.FromContext(ctxLog) + logger := log.Ctx(routineCtx).With().Str(logs.ProviderName, "docker").Logger() + ctxLog := logger.WithContext(routineCtx) operation := func() error { var err error ctx, cancel := context.WithCancel(ctxLog) defer cancel() - - ctx = log.With(ctx, log.Str(log.ProviderName, "docker")) + ctx = log.Ctx(ctx).With().Str(logs.ProviderName, "docker").Logger().WithContext(ctx) dockerClient, err := p.createClient() if err != nil { - logger.Errorf("Failed to create a client for docker, error: %s", err) + logger.Error().Err(err).Msg("Failed to create a client for docker, error") return err } defer dockerClient.Close() serverVersion, err := dockerClient.ServerVersion(ctx) if err != nil { - logger.Errorf("Failed to retrieve information of the docker client and server host: %s", err) + logger.Error().Err(err).Msg("Failed to retrieve information of the docker client and server host") return err } - logger.Debugf("Provider connection established with docker %s (API %s)", serverVersion.Version, serverVersion.APIVersion) + + logger.Debug().Msgf("Provider connection established with docker %s (API %s)", serverVersion.Version, serverVersion.APIVersion) + var dockerDataList []dockerData if p.SwarmMode { dockerDataList, err = p.listServices(ctx, dockerClient) if err != nil { - logger.Errorf("Failed to list services for docker swarm mode, error %s", err) + logger.Error().Err(err).Msg("Failed to list services for docker swarm mode") return err } } else { dockerDataList, err = p.listContainers(ctx, dockerClient) if err != nil { - logger.Errorf("Failed to list containers for docker, error %s", err) + logger.Error().Err(err).Msg("Failed to list containers for docker") return err } } @@ -242,8 +244,8 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. ticker := time.NewTicker(time.Duration(p.SwarmModeRefreshSeconds)) pool.GoCtx(func(ctx context.Context) { - ctx = log.With(ctx, log.Str(log.ProviderName, "docker")) - logger := log.FromContext(ctx) + logger := log.Ctx(ctx).With().Str(logs.ProviderName, "docker").Logger() + ctx = logger.WithContext(ctx) defer close(errChan) for { @@ -251,7 +253,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. case <-ticker.C: services, err := p.listServices(ctx, dockerClient) if err != nil { - logger.Errorf("Failed to list services for docker swarm mode, error %s", err) + logger.Error().Err(err).Msg("Failed to list services for docker swarm mode") errChan <- err return } @@ -282,10 +284,10 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } startStopHandle := func(m eventtypes.Message) { - logger.Debugf("Provider event received %+v", m) + logger.Debug().Msgf("Provider event received %+v", m) containers, err := p.listContainers(ctx, dockerClient) if err != nil { - logger.Errorf("Failed to list containers for docker, error %s", err) + logger.Error().Err(err).Msg("Failed to list containers for docker") // Call cancel to get out of the monitor return } @@ -314,7 +316,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } case err := <-errc: if errors.Is(err, io.EOF) { - logger.Debug("Provider event stream closed") + logger.Debug().Msg("Provider event stream closed") } return err case <-ctx.Done(): @@ -327,11 +329,11 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } notify := func(err error, time time.Duration) { - logger.Errorf("Provider connection error %+v, retrying in %s", err, time) + logger.Error().Err(err).Msgf("Provider connection error, retrying in %s", time) } err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctxLog), notify) if err != nil { - logger.Errorf("Cannot connect to docker server %+v", err) + logger.Error().Err(err).Msg("Cannot connect to docker server") } }) @@ -354,7 +356,7 @@ func (p *Provider) listContainers(ctx context.Context, dockerClient client.Conta extraConf, err := p.getConfiguration(dData) if err != nil { - log.FromContext(ctx).Errorf("Skip container %s: %v", getServiceName(dData), err) + log.Ctx(ctx).Error().Err(err).Msgf("Skip container %s", getServiceName(dData)) continue } dData.ExtraConf = extraConf @@ -367,7 +369,7 @@ func (p *Provider) listContainers(ctx context.Context, dockerClient client.Conta func inspectContainers(ctx context.Context, dockerClient client.ContainerAPIClient, containerID string) dockerData { containerInspected, err := dockerClient.ContainerInspect(ctx, containerID) if err != nil { - log.FromContext(ctx).Warnf("Failed to inspect container %s, error: %s", containerID, err) + log.Ctx(ctx).Warn().Err(err).Msgf("Failed to inspect container %s", containerID) return dockerData{} } @@ -428,7 +430,7 @@ func parseContainer(container dockertypes.ContainerJSON) dockerData { } func (p *Provider) listServices(ctx context.Context, dockerClient client.APIClient) ([]dockerData, error) { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) serviceList, err := dockerClient.ServiceList(ctx, dockertypes.ServiceListOptions{}) if err != nil { @@ -450,7 +452,7 @@ func (p *Provider) listServices(ctx context.Context, dockerClient client.APIClie networkList, err := dockerClient.NetworkList(ctx, dockertypes.NetworkListOptions{Filters: networkListArgs}) if err != nil { - logger.Debugf("Failed to network inspect on client for docker, error: %s", err) + logger.Debug().Err(err).Msg("Failed to network inspect on client for docker") return nil, err } @@ -466,7 +468,7 @@ func (p *Provider) listServices(ctx context.Context, dockerClient client.APIClie for _, service := range serviceList { dData, err := p.parseService(ctx, service, networkMap) if err != nil { - logger.Errorf("Skip container %s: %v", getServiceName(dData), err) + logger.Error().Err(err).Msgf("Skip container %s", getServiceName(dData)) continue } @@ -478,7 +480,7 @@ func (p *Provider) listServices(ctx context.Context, dockerClient client.APIClie isGlobalSvc := service.Spec.Mode.Global != nil dockerDataListTasks, err = listTasks(ctx, dockerClient, service.ID, dData, networkMap, isGlobalSvc) if err != nil { - logger.Warn(err) + logger.Warn().Err(err).Send() } else { dockerDataList = append(dockerDataList, dockerDataListTasks...) } @@ -488,7 +490,7 @@ func (p *Provider) listServices(ctx context.Context, dockerClient client.APIClie } func (p *Provider) parseService(ctx context.Context, service swarmtypes.Service, networkMap map[string]*dockertypes.NetworkResource) (dockerData, error) { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) dData := dockerData{ ID: service.ID, @@ -507,7 +509,7 @@ func (p *Provider) parseService(ctx context.Context, service swarmtypes.Service, if service.Spec.EndpointSpec != nil { if service.Spec.EndpointSpec.Mode == swarmtypes.ResolutionModeDNSRR { if dData.ExtraConf.Docker.LBSwarm { - logger.Warnf("Ignored %s endpoint-mode not supported, service name: %s. Fallback to Traefik load balancing", swarmtypes.ResolutionModeDNSRR, service.Spec.Annotations.Name) + logger.Warn().Msgf("Ignored %s endpoint-mode not supported, service name: %s. Fallback to Traefik load balancing", swarmtypes.ResolutionModeDNSRR, service.Spec.Annotations.Name) } } else if service.Spec.EndpointSpec.Mode == swarmtypes.ResolutionModeVIP { dData.NetworkSettings.Networks = make(map[string]*networkData) @@ -523,10 +525,10 @@ func (p *Provider) parseService(ctx context.Context, service swarmtypes.Service, } dData.NetworkSettings.Networks[network.Name] = network } else { - logger.Debugf("No virtual IPs found in network %s", virtualIP.NetworkID) + logger.Debug().Msgf("No virtual IPs found in network %s", virtualIP.NetworkID) } } else { - logger.Debugf("Network not found, id: %s", virtualIP.NetworkID) + logger.Debug().Msgf("Network not found, id: %s", virtualIP.NetworkID) } } } @@ -591,7 +593,7 @@ func parseTasks(ctx context.Context, task swarmtypes.Task, serviceDockerData doc dData.NetworkSettings.Networks[network.Name] = network } } else { - log.FromContext(ctx).Debugf("No IP addresses found for network %s", virtualIP.Network.ID) + log.Ctx(ctx).Debug().Msgf("No IP addresses found for network %s", virtualIP.Network.ID) } } } diff --git a/pkg/provider/ecs/config.go b/pkg/provider/ecs/config.go index 8c9362514..8dbdf1550 100644 --- a/pkg/provider/ecs/config.go +++ b/pkg/provider/ecs/config.go @@ -10,9 +10,9 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/docker/go-connections/nat" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/label" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/provider/constraints" ) @@ -22,17 +22,16 @@ func (p *Provider) buildConfiguration(ctx context.Context, instances []ecsInstan for _, instance := range instances { instanceName := getServiceName(instance) + "-" + instance.ID - ctxContainer := log.With(ctx, log.Str("ecs-instance", instanceName)) + logger := log.Ctx(ctx).With().Str("ecs-instance", instanceName).Logger() + ctxContainer := logger.WithContext(ctx) if !p.filterInstance(ctxContainer, instance) { continue } - logger := log.FromContext(ctxContainer) - confFromLabel, err := label.DecodeConfiguration(instance.Labels) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } @@ -42,7 +41,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, instances []ecsInstan err := p.buildTCPServiceConfiguration(instance, confFromLabel.TCP) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } provider.BuildTCPRouterConfiguration(ctxContainer, confFromLabel.TCP) @@ -53,7 +52,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, instances []ecsInstan err := p.buildUDPServiceConfiguration(instance, confFromLabel.UDP) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } provider.BuildUDPRouterConfiguration(ctxContainer, confFromLabel.UDP) @@ -68,7 +67,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, instances []ecsInstan err = p.buildServiceConfiguration(ctxContainer, instance, confFromLabel.HTTP) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } @@ -156,40 +155,40 @@ func (p *Provider) buildServiceConfiguration(_ context.Context, instance ecsInst } func (p *Provider) filterInstance(ctx context.Context, instance ecsInstance) bool { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) if instance.machine == nil { - logger.Debug("Filtering ecs instance with nil machine") + logger.Debug().Msg("Filtering ecs instance with nil machine") return false } if strings.ToLower(instance.machine.state) != ec2.InstanceStateNameRunning { - logger.Debugf("Filtering ecs instance with an incorrect state %s (%s) (state = %s)", instance.Name, instance.ID, instance.machine.state) + logger.Debug().Msgf("Filtering ecs instance with an incorrect state %s (%s) (state = %s)", instance.Name, instance.ID, instance.machine.state) return false } if instance.machine.healthStatus == "UNHEALTHY" { - logger.Debugf("Filtering unhealthy ecs instance %s (%s)", instance.Name, instance.ID) + logger.Debug().Msgf("Filtering unhealthy ecs instance %s (%s)", instance.Name, instance.ID) return false } if len(instance.machine.privateIP) == 0 { - logger.Debugf("Filtering ecs instance without an ip address %s (%s)", instance.Name, instance.ID) + logger.Debug().Msgf("Filtering ecs instance without an ip address %s (%s)", instance.Name, instance.ID) return false } if !instance.ExtraConf.Enable { - logger.Debugf("Filtering disabled ecs instance %s (%s)", instance.Name, instance.ID) + logger.Debug().Msgf("Filtering disabled ecs instance %s (%s)", instance.Name, instance.ID) return false } matches, err := constraints.MatchLabels(instance.Labels, p.Constraints) if err != nil { - logger.Errorf("Error matching constraint expression: %v", err) + logger.Error().Err(err).Msg("Error matching constraint expression") return false } if !matches { - logger.Debugf("Container pruned by constraint expression: %q", p.Constraints) + logger.Debug().Msgf("Container pruned by constraint expression: %q", p.Constraints) return false } diff --git a/pkg/provider/ecs/ecs.go b/pkg/provider/ecs/ecs.go index fa7d2185a..ac78b5d6f 100644 --- a/pkg/provider/ecs/ecs.go +++ b/pkg/provider/ecs/ecs.go @@ -17,9 +17,11 @@ import ( "github.com/aws/aws-sdk-go/service/ssm" "github.com/cenkalti/backoff/v4" "github.com/patrickmn/go-cache" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/job" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/safe" ) @@ -99,7 +101,7 @@ func (p *Provider) Init() error { return nil } -func (p *Provider) createClient(logger log.Logger) (*awsClient, error) { +func (p *Provider) createClient(logger zerolog.Logger) (*awsClient, error) { sess, err := session.NewSessionWithOptions(session.Options{ SharedConfigState: session.SharedConfigEnable, }) @@ -109,7 +111,7 @@ func (p *Provider) createClient(logger log.Logger) (*awsClient, error) { ec2meta := ec2metadata.New(sess) if p.Region == "" && ec2meta.Available() { - logger.Infoln("No region provided, querying instance metadata endpoint...") + logger.Info().Msg("No region provided, querying instance metadata endpoint...") identity, err := ec2meta.GetInstanceIdentityDocument() if err != nil { return nil, err @@ -137,9 +139,7 @@ func (p *Provider) createClient(logger log.Logger) (*awsClient, error) { cfg.Region = &p.Region } - cfg.WithLogger(aws.LoggerFunc(func(args ...interface{}) { - logger.Debug(args...) - })) + cfg.WithLogger(logs.NewAWSWrapper(logger)) return &awsClient{ ecs.New(sess, cfg), @@ -151,8 +151,8 @@ func (p *Provider) createClient(logger log.Logger) (*awsClient, error) { // Provide configuration to traefik from ECS. func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error { pool.GoCtx(func(routineCtx context.Context) { - ctxLog := log.With(routineCtx, log.Str(log.ProviderName, "ecs")) - logger := log.FromContext(ctxLog) + logger := log.Ctx(routineCtx).With().Str(logs.ProviderName, "ecs").Logger() + ctxLog := logger.WithContext(routineCtx) operation := func() error { awsClient, err := p.createClient(logger) @@ -183,11 +183,11 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } notify := func(err error, time time.Duration) { - logger.Errorf("Provider connection error %+v, retrying in %s", err, time) + logger.Error().Err(err).Msgf("Provider connection error, retrying in %s", time) } err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), routineCtx), notify) if err != nil { - logger.Errorf("Cannot connect to Provider api %+v", err) + logger.Error().Err(err).Msg("Cannot connect to Provider api") } }) @@ -211,7 +211,7 @@ func (p *Provider) loadConfiguration(ctx context.Context, client *awsClient, con // Find all running Provider tasks in a cluster, also collect the task definitions (for docker labels) // and the EC2 instance data. func (p *Provider) listInstances(ctx context.Context, client *awsClient) ([]ecsInstance, error) { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) var clustersArn []*string var clusters []string @@ -242,7 +242,7 @@ func (p *Provider) listInstances(ctx context.Context, client *awsClient) ([]ecsI var instances []ecsInstance - logger.Debugf("ECS Clusters: %s", clusters) + logger.Debug().Msgf("ECS Clusters: %s", clusters) for _, c := range clusters { input := &ecs.ListTasksInput{ Cluster: &c, @@ -257,11 +257,11 @@ func (p *Provider) listInstances(ctx context.Context, client *awsClient) ([]ecsI Cluster: &c, }) if err != nil { - logger.Errorf("Unable to describe tasks for %v", page.TaskArns) + logger.Error().Msgf("Unable to describe tasks for %v", page.TaskArns) } else { for _, t := range resp.Tasks { if p.HealthyTasksOnly && aws.StringValue(t.HealthStatus) != ecs.HealthStatusHealthy { - logger.Debugf("Skipping unhealthy task %s", aws.StringValue(t.TaskArn)) + logger.Debug().Msgf("Skipping unhealthy task %s", aws.StringValue(t.TaskArn)) continue } @@ -314,7 +314,7 @@ func (p *Provider) listInstances(ctx context.Context, client *awsClient) ([]ecsI } if containerDefinition == nil { - logger.Debugf("Unable to find container definition for %s", aws.StringValue(container.Name)) + logger.Debug().Msgf("Unable to find container definition for %s", aws.StringValue(container.Name)) continue } @@ -344,7 +344,7 @@ func (p *Provider) listInstances(ctx context.Context, client *awsClient) ([]ecsI } else { miContainerInstance := miInstances[aws.StringValue(task.ContainerInstanceArn)] if containerInstance == nil && miContainerInstance == nil { - logger.Errorf("Unable to find container instance information for %s", aws.StringValue(container.Name)) + logger.Error().Msgf("Unable to find container instance information for %s", aws.StringValue(container.Name)) continue } @@ -383,7 +383,7 @@ func (p *Provider) listInstances(ctx context.Context, client *awsClient) ([]ecsI extraConf, err := p.getConfiguration(instance) if err != nil { - log.FromContext(ctx).Errorf("Skip container %s: %w", getServiceName(instance), err) + logger.Error().Err(err).Msgf("Skip container %s", getServiceName(instance)) continue } instance.ExtraConf = extraConf @@ -525,13 +525,13 @@ func (p *Provider) lookupEc2Instances(ctx context.Context, client *awsClient, cl } func (p *Provider) lookupTaskDefinitions(ctx context.Context, client *awsClient, taskDefArns map[string]*ecs.Task) (map[string]*ecs.TaskDefinition, error) { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) taskDef := make(map[string]*ecs.TaskDefinition) for arn, task := range taskDefArns { if definition, ok := existingTaskDefCache.Get(arn); ok { taskDef[arn] = definition.(*ecs.TaskDefinition) - logger.Debugf("Found cached task definition for %s. Skipping the call", arn) + logger.Debug().Msgf("Found cached task definition for %s. Skipping the call", arn) } else { resp, err := client.ecs.DescribeTaskDefinitionWithContext(ctx, &ecs.DescribeTaskDefinitionInput{ TaskDefinition: task.TaskDefinitionArn, diff --git a/pkg/provider/file/file.go b/pkg/provider/file/file.go index 08ee0896d..839986cf8 100644 --- a/pkg/provider/file/file.go +++ b/pkg/provider/file/file.go @@ -11,9 +11,10 @@ import ( "text/template" "github.com/Masterminds/sprig/v3" + "github.com/rs/zerolog/log" "github.com/traefik/paerser/file" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/tls" @@ -75,7 +76,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. // BuildConfiguration loads configuration either from file or a directory // specified by 'Filename'/'Directory' and returns a 'Configuration' object. func (p *Provider) BuildConfiguration() (*dynamic.Configuration, error) { - ctx := log.With(context.Background(), log.Str(log.ProviderName, providerName)) + ctx := log.With().Str(logs.ProviderName, providerName).Logger().WithContext(context.Background()) if len(p.Directory) > 0 { return p.loadFileConfigFromDirectory(ctx, p.Directory, nil) @@ -117,7 +118,7 @@ func (p *Provider) addWatcher(pool *safe.Pool, directory string, configurationCh callback(configurationChan, evt) } case err := <-watcher.Errors: - log.WithoutContext().WithField(log.ProviderName, providerName).Errorf("Watcher event error: %s", err) + log.Error().Str(logs.ProviderName, providerName).Err(err).Msg("Watcher event error") } } }) @@ -130,16 +131,16 @@ func (p *Provider) watcherCallback(configurationChan chan<- dynamic.Message, eve watchItem = p.Directory } - logger := log.WithoutContext().WithField(log.ProviderName, providerName) + logger := log.With().Str(logs.ProviderName, providerName).Logger() if _, err := os.Stat(watchItem); err != nil { - logger.Errorf("Unable to watch %s : %v", watchItem, err) + logger.Error().Err(err).Msgf("Unable to watch %s", watchItem) return } configuration, err := p.BuildConfiguration() if err != nil { - logger.Errorf("Error occurred during watcher callback: %s", err) + logger.Error().Err(err).Msg("Error occurred during watcher callback") return } @@ -176,7 +177,7 @@ func (p *Provider) loadFileConfig(ctx context.Context, filename string, parseTem for _, caFile := range options.ClientAuth.CAFiles { content, err := caFile.Read() if err != nil { - log.FromContext(ctx).Error(err) + log.Ctx(ctx).Error().Err(err).Send() continue } @@ -197,14 +198,14 @@ func (p *Provider) loadFileConfig(ctx context.Context, filename string, parseTem content, err := store.DefaultCertificate.CertFile.Read() if err != nil { - log.FromContext(ctx).Error(err) + log.Ctx(ctx).Error().Err(err).Send() continue } store.DefaultCertificate.CertFile = tls.FileOrContent(content) content, err = store.DefaultCertificate.KeyFile.Read() if err != nil { - log.FromContext(ctx).Error(err) + log.Ctx(ctx).Error().Err(err).Send() continue } store.DefaultCertificate.KeyFile = tls.FileOrContent(content) @@ -221,14 +222,14 @@ func (p *Provider) loadFileConfig(ctx context.Context, filename string, parseTem for _, cert := range st.Certificates { content, err := cert.CertFile.Read() if err != nil { - log.FromContext(ctx).Error(err) + log.Ctx(ctx).Error().Err(err).Send() continue } cert.CertFile = tls.FileOrContent(content) content, err = cert.KeyFile.Read() if err != nil { - log.FromContext(ctx).Error(err) + log.Ctx(ctx).Error().Err(err).Send() continue } cert.KeyFile = tls.FileOrContent(content) @@ -242,7 +243,7 @@ func (p *Provider) loadFileConfig(ctx context.Context, filename string, parseTem for _, rootCA := range st.RootCAs { content, err := rootCA.Read() if err != nil { - log.FromContext(ctx).Error(err) + log.Ctx(ctx).Error().Err(err).Send() continue } @@ -261,14 +262,14 @@ func flattenCertificates(ctx context.Context, tlsConfig *dynamic.TLSConfiguratio for _, cert := range tlsConfig.Certificates { content, err := cert.Certificate.CertFile.Read() if err != nil { - log.FromContext(ctx).Error(err) + log.Ctx(ctx).Error().Err(err).Send() continue } cert.Certificate.CertFile = tls.FileOrContent(string(content)) content, err = cert.Certificate.KeyFile.Read() if err != nil { - log.FromContext(ctx).Error(err) + log.Ctx(ctx).Error().Err(err).Send() continue } cert.Certificate.KeyFile = tls.FileOrContent(string(content)) @@ -312,10 +313,10 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st configTLSMaps := make(map[*tls.CertAndStores]struct{}) for _, item := range fileList { - logger := log.FromContext(log.With(ctx, log.Str("filename", item.Name()))) + logger := log.Ctx(ctx).With().Str("filename", item.Name()).Logger() if item.IsDir() { - configuration, err = p.loadFileConfigFromDirectory(ctx, filepath.Join(directory, item.Name()), configuration) + configuration, err = p.loadFileConfigFromDirectory(logger.WithContext(ctx), filepath.Join(directory, item.Name()), configuration) if err != nil { return configuration, fmt.Errorf("unable to load content configuration from subdirectory %s: %w", item, err) } @@ -330,14 +331,14 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st } var c *dynamic.Configuration - c, err = p.loadFileConfig(ctx, filepath.Join(directory, item.Name()), true) + c, err = p.loadFileConfig(logger.WithContext(ctx), filepath.Join(directory, item.Name()), true) if err != nil { return configuration, fmt.Errorf("%s: %w", filepath.Join(directory, item.Name()), err) } for name, conf := range c.HTTP.Routers { if _, exists := configuration.HTTP.Routers[name]; exists { - logger.WithField(log.RouterName, name).Warn("HTTP router already configured, skipping") + logger.Warn().Str(logs.RouterName, name).Msg("HTTP router already configured, skipping") } else { configuration.HTTP.Routers[name] = conf } @@ -345,7 +346,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st for name, conf := range c.HTTP.Middlewares { if _, exists := configuration.HTTP.Middlewares[name]; exists { - logger.WithField(log.MiddlewareName, name).Warn("HTTP middleware already configured, skipping") + logger.Warn().Str(logs.MiddlewareName, name).Msg("HTTP middleware already configured, skipping") } else { configuration.HTTP.Middlewares[name] = conf } @@ -353,7 +354,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st for name, conf := range c.HTTP.Services { if _, exists := configuration.HTTP.Services[name]; exists { - logger.WithField(log.ServiceName, name).Warn("HTTP service already configured, skipping") + logger.Warn().Str(logs.ServiceName, name).Msg("HTTP service already configured, skipping") } else { configuration.HTTP.Services[name] = conf } @@ -361,7 +362,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st for name, conf := range c.HTTP.ServersTransports { if _, exists := configuration.HTTP.ServersTransports[name]; exists { - logger.WithField(log.ServersTransportName, name).Warn("HTTP servers transport already configured, skipping") + logger.Warn().Str(logs.ServersTransportName, name).Msg("HTTP servers transport already configured, skipping") } else { configuration.HTTP.ServersTransports[name] = conf } @@ -369,7 +370,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st for name, conf := range c.TCP.Routers { if _, exists := configuration.TCP.Routers[name]; exists { - logger.WithField(log.RouterName, name).Warn("TCP router already configured, skipping") + logger.Warn().Str(logs.RouterName, name).Msg("TCP router already configured, skipping") } else { configuration.TCP.Routers[name] = conf } @@ -377,7 +378,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st for name, conf := range c.TCP.Middlewares { if _, exists := configuration.TCP.Middlewares[name]; exists { - logger.WithField(log.MiddlewareName, name).Warn("TCP middleware already configured, skipping") + logger.Warn().Str(logs.MiddlewareName, name).Msg("TCP middleware already configured, skipping") } else { configuration.TCP.Middlewares[name] = conf } @@ -385,7 +386,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st for name, conf := range c.TCP.Services { if _, exists := configuration.TCP.Services[name]; exists { - logger.WithField(log.ServiceName, name).Warn("TCP service already configured, skipping") + logger.Warn().Str(logs.ServiceName, name).Msg("TCP service already configured, skipping") } else { configuration.TCP.Services[name] = conf } @@ -393,7 +394,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st for name, conf := range c.UDP.Routers { if _, exists := configuration.UDP.Routers[name]; exists { - logger.WithField(log.RouterName, name).Warn("UDP router already configured, skipping") + logger.Warn().Str(logs.RouterName, name).Msg("UDP router already configured, skipping") } else { configuration.UDP.Routers[name] = conf } @@ -401,7 +402,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st for name, conf := range c.UDP.Services { if _, exists := configuration.UDP.Services[name]; exists { - logger.WithField(log.ServiceName, name).Warn("UDP service already configured, skipping") + logger.Warn().Str(logs.ServiceName, name).Msg("UDP service already configured, skipping") } else { configuration.UDP.Services[name] = conf } @@ -409,7 +410,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st for _, conf := range c.TLS.Certificates { if _, exists := configTLSMaps[conf]; exists { - logger.Warnf("TLS configuration %v already configured, skipping", conf) + logger.Warn().Msgf("TLS configuration %v already configured, skipping", conf) } else { configTLSMaps[conf] = struct{}{} } @@ -417,7 +418,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st for name, conf := range c.TLS.Options { if _, exists := configuration.TLS.Options[name]; exists { - logger.Warnf("TLS options %v already configured, skipping", name) + logger.Warn().Msgf("TLS options %v already configured, skipping", name) } else { if configuration.TLS.Options == nil { configuration.TLS.Options = map[string]tls.Options{} @@ -428,7 +429,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st for name, conf := range c.TLS.Stores { if _, exists := configuration.TLS.Stores[name]; exists { - logger.Warnf("TLS store %v already configured, skipping", name) + logger.Warn().Msgf("TLS store %v already configured, skipping", name) } else { if configuration.TLS.Stores == nil { configuration.TLS.Stores = map[string]tls.Store{} @@ -478,9 +479,9 @@ func (p *Provider) CreateConfiguration(ctx context.Context, filename string, fun renderedTemplate := buffer.String() if p.DebugLogGeneratedTemplate { - logger := log.FromContext(ctx) - logger.Debugf("Template content: %s", tmplContent) - logger.Debugf("Rendering results: %s", renderedTemplate) + logger := log.Ctx(ctx) + logger.Debug().Msgf("Template content: %s", tmplContent) + logger.Debug().Msgf("Rendering results: %s", renderedTemplate) } return p.decodeConfiguration(filename, renderedTemplate) diff --git a/pkg/provider/http/http.go b/pkg/provider/http/http.go index 4d21cfb19..776c9de1b 100644 --- a/pkg/provider/http/http.go +++ b/pkg/provider/http/http.go @@ -9,11 +9,12 @@ import ( "time" "github.com/cenkalti/backoff/v4" + "github.com/rs/zerolog/log" "github.com/traefik/paerser/file" ptypes "github.com/traefik/paerser/types" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/job" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/tls" @@ -71,8 +72,8 @@ func (p *Provider) Init() error { // Provide allows the provider to provide configurations to traefik using the given configuration channel. func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error { pool.GoCtx(func(routineCtx context.Context) { - ctxLog := log.With(routineCtx, log.Str(log.ProviderName, "http")) - logger := log.FromContext(ctxLog) + logger := log.Ctx(routineCtx).With().Str(logs.ProviderName, "http").Logger() + ctxLog := logger.WithContext(routineCtx) operation := func() error { if err := p.updateConfiguration(configurationChan); err != nil { @@ -96,11 +97,11 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } notify := func(err error, time time.Duration) { - logger.Errorf("Provider connection error %+v, retrying in %s", err, time) + logger.Error().Err(err).Msgf("Provider connection error, retrying in %s", time) } err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctxLog), notify) if err != nil { - logger.Errorf("Cannot connect to server endpoint %+v", err) + logger.Error().Err(err).Msg("Cannot connect to server endpoint") } }) diff --git a/pkg/provider/hub/handler.go b/pkg/provider/hub/handler.go index 83d15dfb9..23cc47b1e 100644 --- a/pkg/provider/hub/handler.go +++ b/pkg/provider/hub/handler.go @@ -9,8 +9,8 @@ import ( "net/url" "sync/atomic" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" ) type handler struct { @@ -59,7 +59,7 @@ func (h *handler) handleConfig(rw http.ResponseWriter, req *http.Request) { payload := &configRequest{Configuration: emptyDynamicConfiguration()} if err := json.NewDecoder(req.Body).Decode(payload); err != nil { err = fmt.Errorf("decoding config request: %w", err) - log.WithoutContext().Errorf("Handling config: %v", err) + log.Error().Err(err).Msg("Handling config") http.Error(rw, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } @@ -88,14 +88,14 @@ func (h *handler) handleDiscoverIP(rw http.ResponseWriter, req *http.Request) { if err := h.doDiscoveryReq(req.Context(), xff, port, nonce); err != nil { err = fmt.Errorf("doing discovery request: %w", err) - log.WithoutContext().Errorf("Handling IP discovery: %v", err) + log.Error().Err(err).Msg("Handling IP discovery") http.Error(rw, http.StatusText(http.StatusBadGateway), http.StatusBadGateway) return } if err := json.NewEncoder(rw).Encode(xff); err != nil { err = fmt.Errorf("encoding discover ip response: %w", err) - log.WithoutContext().Errorf("Handling IP discovery: %v", err) + log.Error().Err(err).Msg("Handling IP discovery") http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } @@ -136,7 +136,7 @@ func (h *handler) handleState(rw http.ResponseWriter, req *http.Request) { } if err := json.NewEncoder(rw).Encode(resp); err != nil { err = fmt.Errorf("encoding last config received response: %w", err) - log.WithoutContext().Errorf("Handling state: %v", err) + log.Error().Err(err).Msg("Handling state") http.Error(rw, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } diff --git a/pkg/provider/hub/hub.go b/pkg/provider/hub/hub.go index 106a097e2..07fc50d30 100644 --- a/pkg/provider/hub/hub.go +++ b/pkg/provider/hub/hub.go @@ -8,8 +8,9 @@ import ( "net" "net/http" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/safe" ttls "github.com/traefik/traefik/v2/pkg/tls" @@ -67,7 +68,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, _ *safe.Poo // if/when Provide lifecycle differs with Traefik lifecycle. go func() { if err = p.server.Serve(listener); err != nil { - log.WithoutContext().WithField(log.ProviderName, "hub").Errorf("Unexpected error while running server: %v", err) + log.Error().Str(logs.ProviderName, "hub").Err(err).Msg("Unexpected error while running server") return } }() diff --git a/pkg/provider/kubernetes/crd/client.go b/pkg/provider/kubernetes/crd/client.go index 4dfd4d8a3..0b40a91aa 100644 --- a/pkg/provider/kubernetes/crd/client.go +++ b/pkg/provider/kubernetes/crd/client.go @@ -8,7 +8,7 @@ import ( "runtime" "time" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/informers/externalversions" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" @@ -220,7 +220,7 @@ func (c *clientWrapper) GetIngressRoutes() []*v1alpha1.IngressRoute { for ns, factory := range c.factoriesCrd { ings, err := factory.Traefik().V1alpha1().IngressRoutes().Lister().List(labels.Everything()) if err != nil { - log.Errorf("Failed to list ingress routes in namespace %s: %v", ns, err) + log.Error().Err(err).Msgf("Failed to list ingress routes in namespace %s", ns) } result = append(result, ings...) } @@ -234,7 +234,7 @@ func (c *clientWrapper) GetIngressRouteTCPs() []*v1alpha1.IngressRouteTCP { for ns, factory := range c.factoriesCrd { ings, err := factory.Traefik().V1alpha1().IngressRouteTCPs().Lister().List(labels.Everything()) if err != nil { - log.Errorf("Failed to list tcp ingress routes in namespace %s: %v", ns, err) + log.Error().Err(err).Msgf("Failed to list tcp ingress routes in namespace %s", ns) } result = append(result, ings...) } @@ -248,7 +248,7 @@ func (c *clientWrapper) GetIngressRouteUDPs() []*v1alpha1.IngressRouteUDP { for ns, factory := range c.factoriesCrd { ings, err := factory.Traefik().V1alpha1().IngressRouteUDPs().Lister().List(labels.Everything()) if err != nil { - log.Errorf("Failed to list udp ingress routes in namespace %s: %v", ns, err) + log.Error().Err(err).Msgf("Failed to list udp ingress routes in namespace %s", ns) } result = append(result, ings...) } @@ -262,7 +262,7 @@ func (c *clientWrapper) GetMiddlewares() []*v1alpha1.Middleware { for ns, factory := range c.factoriesCrd { middlewares, err := factory.Traefik().V1alpha1().Middlewares().Lister().List(labels.Everything()) if err != nil { - log.Errorf("Failed to list middlewares in namespace %s: %v", ns, err) + log.Error().Err(err).Msgf("Failed to list middlewares in namespace %s", ns) } result = append(result, middlewares...) } @@ -276,7 +276,7 @@ func (c *clientWrapper) GetMiddlewareTCPs() []*v1alpha1.MiddlewareTCP { for ns, factory := range c.factoriesCrd { middlewares, err := factory.Traefik().V1alpha1().MiddlewareTCPs().Lister().List(labels.Everything()) if err != nil { - log.Errorf("Failed to list TCP middlewares in namespace %s: %v", ns, err) + log.Error().Err(err).Msgf("Failed to list TCP middlewares in namespace %s", ns) } result = append(result, middlewares...) } @@ -302,7 +302,7 @@ func (c *clientWrapper) GetTraefikServices() []*v1alpha1.TraefikService { for ns, factory := range c.factoriesCrd { ings, err := factory.Traefik().V1alpha1().TraefikServices().Lister().List(labels.Everything()) if err != nil { - log.Errorf("Failed to list Traefik services in namespace %s: %v", ns, err) + log.Error().Err(err).Msgf("Failed to list Traefik services in namespace %s", ns) } result = append(result, ings...) } @@ -310,14 +310,14 @@ func (c *clientWrapper) GetTraefikServices() []*v1alpha1.TraefikService { return result } -// GetServersTransport returns all ServersTransport. +// GetServersTransports returns all ServersTransport. func (c *clientWrapper) GetServersTransports() []*v1alpha1.ServersTransport { var result []*v1alpha1.ServersTransport for ns, factory := range c.factoriesCrd { serversTransports, err := factory.Traefik().V1alpha1().ServersTransports().Lister().List(labels.Everything()) if err != nil { - log.Errorf("Failed to list servers transport in namespace %s: %v", ns, err) + log.Error().Err(err).Msgf("Failed to list servers transport in namespace %s", ns) } result = append(result, serversTransports...) } @@ -332,7 +332,7 @@ func (c *clientWrapper) GetTLSOptions() []*v1alpha1.TLSOption { for ns, factory := range c.factoriesCrd { options, err := factory.Traefik().V1alpha1().TLSOptions().Lister().List(labels.Everything()) if err != nil { - log.Errorf("Failed to list tls options in namespace %s: %v", ns, err) + log.Error().Err(err).Msgf("Failed to list tls options in namespace %s", ns) } result = append(result, options...) } @@ -347,7 +347,7 @@ func (c *clientWrapper) GetTLSStores() []*v1alpha1.TLSStore { for ns, factory := range c.factoriesCrd { stores, err := factory.Traefik().V1alpha1().TLSStores().Lister().List(labels.Everything()) if err != nil { - log.Errorf("Failed to list tls stores in namespace %s: %v", ns, err) + log.Error().Err(err).Msgf("Failed to list tls stores in namespace %s", ns) } result = append(result, stores...) } diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index 31366ba7c..00eb9a4e0 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -17,10 +17,11 @@ import ( "github.com/cenkalti/backoff/v4" "github.com/mitchellh/hashstructure" + "github.com/rs/zerolog/log" ptypes "github.com/traefik/paerser/types" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/job" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" "github.com/traefik/traefik/v2/pkg/safe" @@ -62,7 +63,7 @@ func (p *Provider) newK8sClient(ctx context.Context) (*clientWrapper, error) { if err != nil { return nil, fmt.Errorf("invalid label selector: %q", p.LabelSelector) } - log.FromContext(ctx).Infof("label selector is: %q", p.LabelSelector) + log.Ctx(ctx).Info().Msgf("label selector is: %q", p.LabelSelector) withEndpoint := "" if p.Endpoint != "" { @@ -72,13 +73,13 @@ func (p *Provider) newK8sClient(ctx context.Context) (*clientWrapper, error) { var client *clientWrapper switch { case os.Getenv("KUBERNETES_SERVICE_HOST") != "" && os.Getenv("KUBERNETES_SERVICE_PORT") != "": - log.FromContext(ctx).Infof("Creating in-cluster Provider client%s", withEndpoint) + log.Ctx(ctx).Info().Msgf("Creating in-cluster Provider client%s", withEndpoint) client, err = newInClusterClient(p.Endpoint) case os.Getenv("KUBECONFIG") != "": - log.FromContext(ctx).Infof("Creating cluster-external Provider client from KUBECONFIG %s", os.Getenv("KUBECONFIG")) + log.Ctx(ctx).Info().Msgf("Creating cluster-external Provider client from KUBECONFIG %s", os.Getenv("KUBECONFIG")) client, err = newExternalClusterClientFromFile(os.Getenv("KUBECONFIG")) default: - log.FromContext(ctx).Infof("Creating cluster-external Provider client%s", withEndpoint) + log.Ctx(ctx).Info().Msgf("Creating cluster-external Provider client%s", withEndpoint) client, err = newExternalClusterClient(p.Endpoint, p.Token, p.CertAuthFilePath) } @@ -98,8 +99,8 @@ func (p *Provider) Init() error { // Provide allows the k8s provider to provide configurations to traefik // using the given configuration channel. func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error { - ctxLog := log.With(context.Background(), log.Str(log.ProviderName, providerName)) - logger := log.FromContext(ctxLog) + logger := log.With().Str(logs.ProviderName, providerName).Logger() + ctxLog := logger.WithContext(context.Background()) k8sClient, err := p.newK8sClient(ctxLog) if err != nil { @@ -107,18 +108,18 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } if p.AllowCrossNamespace { - logger.Warn("Cross-namespace reference between IngressRoutes and resources is enabled, please ensure that this is expected (see AllowCrossNamespace option)") + logger.Warn().Msg("Cross-namespace reference between IngressRoutes and resources is enabled, please ensure that this is expected (see AllowCrossNamespace option)") } if p.AllowExternalNameServices { - logger.Warn("ExternalName service loading is enabled, please ensure that this is expected (see AllowExternalNameServices option)") + logger.Warn().Msg("ExternalName service loading is enabled, please ensure that this is expected (see AllowExternalNameServices option)") } pool.GoCtx(func(ctxPool context.Context) { operation := func() error { eventsChan, err := k8sClient.WatchAll(p.Namespaces, ctxPool.Done()) if err != nil { - logger.Errorf("Error watching kubernetes events: %v", err) + logger.Error().Err(err).Msg("Error watching kubernetes events") timer := time.NewTimer(1 * time.Second) select { case <-timer.C: @@ -147,9 +148,9 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. confHash, err := hashstructure.Hash(conf, nil) switch { case err != nil: - logger.Error("Unable to hash the configuration") + logger.Error().Err(err).Msg("Unable to hash the configuration") case p.lastConfiguration.Get() == confHash: - logger.Debugf("Skipping Kubernetes event kind %T", event) + logger.Debug().Msgf("Skipping Kubernetes event kind %T", event) default: p.lastConfiguration.Set(confHash) configurationChan <- dynamic.Message{ @@ -167,11 +168,11 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } notify := func(err error, time time.Duration) { - logger.Errorf("Provider connection error: %v; retrying in %s", err, time) + logger.Error().Err(err).Msgf("Provider connection error, retrying in %s", time) } err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctxPool), notify) if err != nil { - logger.Errorf("Cannot connect to Provider: %v", err) + logger.Error().Err(err).Msg("Cannot connect to Provider") } }) @@ -200,29 +201,30 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) for _, middleware := range client.GetMiddlewares() { id := provider.Normalize(makeID(middleware.Namespace, middleware.Name)) - ctxMid := log.With(ctx, log.Str(log.MiddlewareName, id)) + logger := log.Ctx(ctx).With().Str(logs.MiddlewareName, id).Logger() + ctxMid := logger.WithContext(ctx) basicAuth, err := createBasicAuthMiddleware(client, middleware.Namespace, middleware.Spec.BasicAuth) if err != nil { - log.FromContext(ctxMid).Errorf("Error while reading basic auth middleware: %v", err) + logger.Error().Err(err).Msg("Error while reading basic auth middleware") continue } digestAuth, err := createDigestAuthMiddleware(client, middleware.Namespace, middleware.Spec.DigestAuth) if err != nil { - log.FromContext(ctxMid).Errorf("Error while reading digest auth middleware: %v", err) + logger.Error().Err(err).Msg("Error while reading digest auth middleware") continue } forwardAuth, err := createForwardAuthMiddleware(client, middleware.Namespace, middleware.Spec.ForwardAuth) if err != nil { - log.FromContext(ctxMid).Errorf("Error while reading forward auth middleware: %v", err) + logger.Error().Err(err).Msg("Error while reading forward auth middleware") continue } errorPage, errorPageService, err := p.createErrorPageMiddleware(client, middleware.Namespace, middleware.Spec.Errors) if err != nil { - log.FromContext(ctxMid).Errorf("Error while reading error page middleware: %v", err) + logger.Error().Err(err).Msg("Error while reading error page middleware") continue } @@ -234,25 +236,25 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) plugin, err := createPluginMiddleware(client, middleware.Namespace, middleware.Spec.Plugin) if err != nil { - log.FromContext(ctxMid).Errorf("Error while reading plugins middleware: %v", err) + logger.Error().Err(err).Msg("Error while reading plugins middleware") continue } rateLimit, err := createRateLimitMiddleware(middleware.Spec.RateLimit) if err != nil { - log.FromContext(ctxMid).Errorf("Error while reading rateLimit middleware: %v", err) + logger.Error().Err(err).Msg("Error while reading rateLimit middleware") continue } retry, err := createRetryMiddleware(middleware.Spec.Retry) if err != nil { - log.FromContext(ctxMid).Errorf("Error while reading retry middleware: %v", err) + logger.Error().Err(err).Msg("Error while reading retry middleware") continue } circuitBreaker, err := createCircuitBreakerMiddleware(middleware.Spec.CircuitBreaker) if err != nil { - log.FromContext(ctxMid).Errorf("Error while reading circuit breaker middleware: %v", err) + logger.Error().Err(err).Msg("Error while reading circuit breaker middleware") continue } @@ -298,20 +300,20 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) for _, service := range client.GetTraefikServices() { err := cb.buildTraefikService(ctx, service, conf.HTTP.Services) if err != nil { - log.FromContext(ctx).WithField(log.ServiceName, service.Name). - Errorf("Error while building TraefikService: %v", err) + log.Ctx(ctx).Error().Str(logs.ServiceName, service.Name).Err(err). + Msg("Error while building TraefikService") continue } } for _, serversTransport := range client.GetServersTransports() { - logger := log.FromContext(ctx).WithField(log.ServersTransportName, serversTransport.Name) + logger := log.Ctx(ctx).With().Str(logs.ServersTransportName, serversTransport.Name).Logger() var rootCAs []tls.FileOrContent for _, secret := range serversTransport.Spec.RootCAsSecrets { caSecret, err := loadCASecret(serversTransport.Namespace, secret, client) if err != nil { - logger.Errorf("Error while loading rootCAs %s: %v", secret, err) + logger.Error().Err(err).Msgf("Error while loading rootCAs %s", secret) continue } @@ -322,7 +324,7 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) for _, secret := range serversTransport.Spec.CertificatesSecrets { tlsSecret, tlsKey, err := loadAuthTLSSecret(serversTransport.Namespace, secret, client) if err != nil { - logger.Errorf("Error while loading certificates %s: %v", secret, err) + logger.Error().Err(err).Msgf("Error while loading certificates %s", secret) continue } @@ -339,35 +341,35 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) if serversTransport.Spec.ForwardingTimeouts.DialTimeout != nil { err := forwardingTimeout.DialTimeout.Set(serversTransport.Spec.ForwardingTimeouts.DialTimeout.String()) if err != nil { - logger.Errorf("Error while reading DialTimeout: %v", err) + logger.Error().Err(err).Msg("Error while reading DialTimeout") } } if serversTransport.Spec.ForwardingTimeouts.ResponseHeaderTimeout != nil { err := forwardingTimeout.ResponseHeaderTimeout.Set(serversTransport.Spec.ForwardingTimeouts.ResponseHeaderTimeout.String()) if err != nil { - logger.Errorf("Error while reading ResponseHeaderTimeout: %v", err) + logger.Error().Err(err).Msg("Error while reading ResponseHeaderTimeout") } } if serversTransport.Spec.ForwardingTimeouts.IdleConnTimeout != nil { err := forwardingTimeout.IdleConnTimeout.Set(serversTransport.Spec.ForwardingTimeouts.IdleConnTimeout.String()) if err != nil { - logger.Errorf("Error while reading IdleConnTimeout: %v", err) + logger.Error().Err(err).Msg("Error while reading IdleConnTimeout") } } if serversTransport.Spec.ForwardingTimeouts.ReadIdleTimeout != nil { err := forwardingTimeout.ReadIdleTimeout.Set(serversTransport.Spec.ForwardingTimeouts.ReadIdleTimeout.String()) if err != nil { - logger.Errorf("Error while reading ReadIdleTimeout: %v", err) + logger.Error().Err(err).Msg("Error while reading ReadIdleTimeout") } } if serversTransport.Spec.ForwardingTimeouts.PingTimeout != nil { err := forwardingTimeout.PingTimeout.Set(serversTransport.Spec.ForwardingTimeouts.PingTimeout.String()) if err != nil { - logger.Errorf("Error while reading PingTimeout: %v", err) + logger.Error().Err(err).Msg("Error while reading PingTimeout") } } } @@ -414,8 +416,8 @@ func getServicePort(svc *corev1.Service, port intstr.IntOrString) (*corev1.Servi } if hasValidPort { - log.WithoutContext(). - Warnf("The port %s from IngressRoute doesn't match with ports defined in the ExternalName service %s/%s.", port, svc.Namespace, svc.Name) + log.Warn().Msgf("The port %s from IngressRoute doesn't match with ports defined in the ExternalName service %s/%s.", + &port, svc.Namespace, svc.Name) } return &corev1.ServicePort{Port: port.IntVal}, nil @@ -811,8 +813,7 @@ func createChainMiddleware(ctx context.Context, namespace string, chain *v1alpha for _, mi := range chain.Middlewares { if strings.Contains(mi.Name, providerNamespaceSeparator) { if len(mi.Namespace) > 0 { - log.FromContext(ctx). - Warnf("namespace %q is ignored in cross-provider context", mi.Namespace) + log.Ctx(ctx).Warn().Msgf("namespace %q is ignored in cross-provider context", mi.Namespace) } mds = append(mds, mi.Name) continue @@ -838,24 +839,24 @@ func buildTLSOptions(ctx context.Context, client Client) map[string]tls.Options var nsDefault []string for _, tlsOption := range tlsOptionsCRD { - logger := log.FromContext(log.With(ctx, log.Str("tlsOption", tlsOption.Name), log.Str("namespace", tlsOption.Namespace))) + logger := log.Ctx(ctx).With().Str("tlsOption", tlsOption.Name).Str("namespace", tlsOption.Namespace).Logger() var clientCAs []tls.FileOrContent for _, secretName := range tlsOption.Spec.ClientAuth.SecretNames { secret, exists, err := client.GetSecret(tlsOption.Namespace, secretName) if err != nil { - logger.Errorf("Failed to fetch secret %s/%s: %v", tlsOption.Namespace, secretName, err) + logger.Error().Err(err).Msgf("Failed to fetch secret %s/%s", tlsOption.Namespace, secretName) continue } if !exists { - logger.Warnf("Secret %s/%s does not exist", tlsOption.Namespace, secretName) + logger.Warn().Msgf("Secret %s/%s does not exist", tlsOption.Namespace, secretName) continue } cert, err := getCABlocks(secret, tlsOption.Namespace, secretName) if err != nil { - logger.Errorf("Failed to extract CA from secret %s/%s: %v", tlsOption.Namespace, secretName, err) + logger.Error().Err(err).Msgf("Failed to extract CA from secret %s/%s", tlsOption.Namespace, secretName) continue } @@ -890,7 +891,7 @@ func buildTLSOptions(ctx context.Context, client Client) map[string]tls.Options if len(nsDefault) > 1 { delete(tlsOptions, tls.DefaultTLSConfigName) - log.FromContext(ctx).Errorf("Default TLS Options defined in multiple namespaces: %v", nsDefault) + log.Ctx(ctx).Error().Msgf("Default TLS Options defined in multiple namespaces: %v", nsDefault) } return tlsOptions @@ -907,7 +908,7 @@ func buildTLSStores(ctx context.Context, client Client) (map[string]tls.Store, m tlsConfigs := make(map[string]*tls.CertAndStores) for _, t := range tlsStoreCRD { - logger := log.FromContext(log.With(ctx, log.Str("TLSStore", t.Name), log.Str("namespace", t.Namespace))) + logger := log.Ctx(ctx).With().Str("TLSStore", t.Name).Str("namespace", t.Namespace).Logger() id := makeID(t.Namespace, t.Name) @@ -924,17 +925,17 @@ func buildTLSStores(ctx context.Context, client Client) (map[string]tls.Store, m secret, exists, err := client.GetSecret(t.Namespace, secretName) if err != nil { - logger.Errorf("Failed to fetch secret %s/%s: %v", t.Namespace, secretName, err) + logger.Error().Err(err).Msgf("Failed to fetch secret %s/%s", t.Namespace, secretName) continue } if !exists { - logger.Errorf("Secret %s/%s does not exist", t.Namespace, secretName) + logger.Error().Msgf("Secret %s/%s does not exist", t.Namespace, secretName) continue } cert, key, err := getCertificateBlocks(secret, t.Namespace, secretName) if err != nil { - logger.Errorf("Could not get certificate blocks: %v", err) + logger.Error().Err(err).Msg("Could not get certificate blocks") continue } @@ -952,7 +953,7 @@ func buildTLSStores(ctx context.Context, client Client) (map[string]tls.Store, m } if err := buildCertificates(client, id, t.Namespace, t.Spec.Certificates, tlsConfigs); err != nil { - logger.Errorf("Failed to load certificates: %v", err) + logger.Error().Err(err).Msg("Failed to load certificates") continue } @@ -961,7 +962,7 @@ func buildTLSStores(ctx context.Context, client Client) (map[string]tls.Store, m if len(nsDefault) > 1 { delete(tlsStores, tls.DefaultTLSStoreName) - log.FromContext(ctx).Errorf("Default TLS Stores defined in multiple namespaces: %v", nsDefault) + log.Ctx(ctx).Error().Msgf("Default TLS Stores defined in multiple namespaces: %v", nsDefault) } return tlsStores, tlsConfigs @@ -1117,7 +1118,7 @@ func throttleEvents(ctx context.Context, throttleDuration time.Duration, pool *s default: // We already have an event in eventsChanBuffered, so we'll do a refresh as soon as our throttle allows us to. // It's fine to drop the event and keep whatever's in the buffer -- we don't do different things for different events - log.FromContext(ctx).Debugf("Dropping event kind %T due to throttling", nextEvent) + log.Ctx(ctx).Debug().Msgf("Dropping event kind %T due to throttling", nextEvent) } } } diff --git a/pkg/provider/kubernetes/crd/kubernetes_http.go b/pkg/provider/kubernetes/crd/kubernetes_http.go index 2fd8f17e6..fa8bed11d 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_http.go +++ b/pkg/provider/kubernetes/crd/kubernetes_http.go @@ -8,8 +8,9 @@ import ( "strconv" "strings" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" "github.com/traefik/traefik/v2/pkg/tls" @@ -32,8 +33,7 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli } for _, ingressRoute := range client.GetIngressRoutes() { - ctxRt := log.With(ctx, log.Str("ingress", ingressRoute.Name), log.Str("namespace", ingressRoute.Namespace)) - logger := log.FromContext(ctxRt) + logger := log.Ctx(ctx).With().Str("ingress", ingressRoute.Name).Str("namespace", ingressRoute.Namespace).Logger() // TODO keep the name ingressClass? if !shouldProcessIngress(p.IngressClass, ingressRoute.Annotations[annotationKubernetesIngressClass]) { @@ -42,7 +42,7 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli err := getTLSHTTP(ctx, ingressRoute, client, tlsConfigs) if err != nil { - logger.Errorf("Error configuring TLS: %v", err) + logger.Error().Err(err).Msg("Error configuring TLS") } ingressName := ingressRoute.Name @@ -59,24 +59,24 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli for _, route := range ingressRoute.Spec.Routes { if route.Kind != "Rule" { - logger.Errorf("Unsupported match kind: %s. Only \"Rule\" is supported for now.", route.Kind) + logger.Error().Msgf("Unsupported match kind: %s. Only \"Rule\" is supported for now.", route.Kind) continue } if len(route.Match) == 0 { - logger.Errorf("Empty match rule") + logger.Error().Msg("Empty match rule") continue } serviceKey, err := makeServiceKey(route.Match, ingressName) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } mds, err := p.makeMiddlewareKeys(ctx, ingressRoute.Namespace, route.Middlewares) if err != nil { - logger.Errorf("Failed to create middleware keys: %v", err) + logger.Error().Err(err).Msg("Failed to create middleware keys") continue } @@ -92,13 +92,13 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli errBuild := cb.buildServicesLB(ctx, ingressRoute.Namespace, spec, serviceName, conf.Services) if errBuild != nil { - logger.Error(errBuild) + logger.Error().Err(errBuild).Send() continue } } else if len(route.Services) == 1 { fullName, serversLB, err := cb.nameAndService(ctx, ingressRoute.Namespace, route.Services[0].LoadBalancerSpec) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } @@ -134,12 +134,12 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli tlsOptionsName = makeID(ns, tlsOptionsName) } else if len(ns) > 0 { logger. - WithField("TLSOption", ingressRoute.Spec.TLS.Options.Name). - Warnf("Namespace %q is ignored in cross-provider context", ns) + Warn().Str("TLSOption", ingressRoute.Spec.TLS.Options.Name). + Msgf("Namespace %q is ignored in cross-provider context", ns) } if !isNamespaceAllowed(p.AllowCrossNamespace, ingressRoute.Namespace, ns) { - logger.Errorf("TLSOption %s/%s is not in the IngressRoute namespace %s", + logger.Error().Msgf("TLSOption %s/%s is not in the IngressRoute namespace %s", ns, ingressRoute.Spec.TLS.Options.Name, ingressRoute.Namespace) continue } @@ -170,9 +170,9 @@ func (p *Provider) makeMiddlewareKeys(ctx context.Context, ingRouteNamespace str if strings.Contains(name, providerNamespaceSeparator) { if len(mi.Namespace) > 0 { - log.FromContext(ctx). - WithField(log.MiddlewareName, mi.Name). - Warnf("namespace %q is ignored in cross-provider context", mi.Namespace) + log.Ctx(ctx). + Warn().Str(logs.MiddlewareName, mi.Name). + Msgf("namespace %q is ignored in cross-provider context", mi.Namespace) } mds = append(mds, name) @@ -439,7 +439,7 @@ func (c configBuilder) loadServers(parentNamespace string, svc v1alpha1.LoadBala // it generates and returns the configuration part for such a service, // so that the caller can add it to the global config map. func (c configBuilder) nameAndService(ctx context.Context, parentNamespace string, service v1alpha1.LoadBalancerSpec) (string, *dynamic.Service, error) { - svcCtx := log.With(ctx, log.Str(log.ServiceName, service.Name)) + svcCtx := log.Ctx(ctx).With().Str(logs.ServiceName, service.Name).Logger().WithContext(ctx) namespace := namespaceOrFallback(service, parentNamespace) @@ -488,7 +488,7 @@ func fullServiceName(ctx context.Context, namespace string, service v1alpha1.Loa } if service.Namespace != "" { - log.FromContext(ctx).Warnf("namespace %q is ignored in cross-provider context", service.Namespace) + log.Ctx(ctx).Warn().Msgf("namespace %q is ignored in cross-provider context", service.Namespace) } return provider.Normalize(name) + providerNamespaceSeparator + pName @@ -507,7 +507,7 @@ func getTLSHTTP(ctx context.Context, ingressRoute *v1alpha1.IngressRoute, k8sCli return nil } if ingressRoute.Spec.TLS.SecretName == "" { - log.FromContext(ctx).Debugf("No secret name provided") + log.Ctx(ctx).Debug().Msg("No secret name provided") return nil } diff --git a/pkg/provider/kubernetes/crd/kubernetes_tcp.go b/pkg/provider/kubernetes/crd/kubernetes_tcp.go index cb3be3f3a..bdb11ee33 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_tcp.go +++ b/pkg/provider/kubernetes/crd/kubernetes_tcp.go @@ -8,8 +8,9 @@ import ( "strconv" "strings" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" "github.com/traefik/traefik/v2/pkg/tls" @@ -24,7 +25,7 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client } for _, ingressRouteTCP := range client.GetIngressRouteTCPs() { - logger := log.FromContext(log.With(ctx, log.Str("ingress", ingressRouteTCP.Name), log.Str("namespace", ingressRouteTCP.Namespace))) + logger := log.Ctx(ctx).With().Str("ingress", ingressRouteTCP.Name).Str("namespace", ingressRouteTCP.Namespace).Logger() if !shouldProcessIngress(p.IngressClass, ingressRouteTCP.Annotations[annotationKubernetesIngressClass]) { continue @@ -33,7 +34,7 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client if ingressRouteTCP.Spec.TLS != nil && !ingressRouteTCP.Spec.TLS.Passthrough { err := getTLSTCP(ctx, ingressRouteTCP, client, tlsConfigs) if err != nil { - logger.Errorf("Error configuring TLS: %v", err) + logger.Error().Err(err).Msg("Error configuring TLS") } } @@ -44,19 +45,19 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client for _, route := range ingressRouteTCP.Spec.Routes { if len(route.Match) == 0 { - logger.Errorf("Empty match rule") + logger.Error().Msg("Empty match rule") continue } key, err := makeServiceKey(route.Match, ingressName) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } mds, err := p.makeMiddlewareTCPKeys(ctx, ingressRouteTCP.Namespace, route.Middlewares) if err != nil { - logger.Errorf("Failed to create middleware keys: %v", err) + logger.Error().Err(err).Msg("Failed to create middleware keys") continue } @@ -65,10 +66,11 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client for _, service := range route.Services { balancerServerTCP, err := p.createLoadBalancerServerTCP(client, ingressRouteTCP.Namespace, service) if err != nil { - logger. - WithField("serviceName", service.Name). - WithField("servicePort", service.Port). - Errorf("Cannot create service: %v", err) + logger.Error(). + Str("serviceName", service.Name). + Stringer("servicePort", &service.Port). + Err(err). + Msg("Cannot create service") continue } @@ -119,13 +121,13 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client } tlsOptionsName = makeID(ns, tlsOptionsName) } else if len(ns) > 0 { - logger. - WithField("TLSOption", ingressRouteTCP.Spec.TLS.Options.Name). - Warnf("Namespace %q is ignored in cross-provider context", ns) + logger.Warn(). + Str("TLSOption", ingressRouteTCP.Spec.TLS.Options.Name). + Msgf("Namespace %q is ignored in cross-provider context", ns) } if !isNamespaceAllowed(p.AllowCrossNamespace, ingressRouteTCP.Namespace, ns) { - logger.Errorf("TLSOption %s/%s is not in the IngressRouteTCP namespace %s", + logger.Error().Msgf("TLSOption %s/%s is not in the IngressRouteTCP namespace %s", ns, ingressRouteTCP.Spec.TLS.Options.Name, ingressRouteTCP.Namespace) continue } @@ -147,9 +149,9 @@ func (p *Provider) makeMiddlewareTCPKeys(ctx context.Context, ingRouteTCPNamespa for _, mi := range middlewares { if strings.Contains(mi.Name, providerNamespaceSeparator) { if len(mi.Namespace) > 0 { - log.FromContext(ctx). - WithField(log.MiddlewareName, mi.Name). - Warnf("namespace %q is ignored in cross-provider context", mi.Namespace) + log.Ctx(ctx).Warn(). + Str(logs.MiddlewareName, mi.Name). + Msgf("Namespace %q is ignored in cross-provider context", mi.Namespace) } mds = append(mds, mi.Name) continue @@ -275,7 +277,7 @@ func getTLSTCP(ctx context.Context, ingressRoute *v1alpha1.IngressRouteTCP, k8sC return nil } if ingressRoute.Spec.TLS.SecretName == "" { - log.FromContext(ctx).Debugf("No secret name provided") + log.Ctx(ctx).Debug().Msg("No secret name provided") return nil } diff --git a/pkg/provider/kubernetes/crd/kubernetes_udp.go b/pkg/provider/kubernetes/crd/kubernetes_udp.go index 7e6b47ae5..2589ebb0f 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_udp.go +++ b/pkg/provider/kubernetes/crd/kubernetes_udp.go @@ -7,8 +7,8 @@ import ( "net" "strconv" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" corev1 "k8s.io/api/core/v1" ) @@ -20,7 +20,7 @@ func (p *Provider) loadIngressRouteUDPConfiguration(ctx context.Context, client } for _, ingressRouteUDP := range client.GetIngressRouteUDPs() { - logger := log.FromContext(log.With(ctx, log.Str("ingress", ingressRouteUDP.Name), log.Str("namespace", ingressRouteUDP.Namespace))) + logger := log.Ctx(ctx).With().Str("ingress", ingressRouteUDP.Name).Str("namespace", ingressRouteUDP.Namespace).Logger() if !shouldProcessIngress(p.IngressClass, ingressRouteUDP.Annotations[annotationKubernetesIngressClass]) { continue @@ -38,10 +38,11 @@ func (p *Provider) loadIngressRouteUDPConfiguration(ctx context.Context, client for _, service := range route.Services { balancerServerUDP, err := p.createLoadBalancerServerUDP(client, ingressRouteUDP.Namespace, service) if err != nil { - logger. - WithField("serviceName", service.Name). - WithField("servicePort", service.Port). - Errorf("Cannot create service: %v", err) + logger.Error(). + Str("serviceName", service.Name). + Stringer("servicePort", &service.Port). + Err(err). + Msg("Cannot create service") continue } diff --git a/pkg/provider/kubernetes/gateway/client.go b/pkg/provider/kubernetes/gateway/client.go index e8317e45f..5ad1772bb 100644 --- a/pkg/provider/kubernetes/gateway/client.go +++ b/pkg/provider/kubernetes/gateway/client.go @@ -7,7 +7,7 @@ import ( "os" "time" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" corev1 "k8s.io/api/core/v1" kubeerror "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -252,7 +252,7 @@ func (c *clientWrapper) GetNamespaces(selector labels.Selector) ([]string, error var namespaces []string for _, namespace := range ns { if !c.isWatchedNamespace(namespace.Name) { - log.WithoutContext().Warnf("Namespace %q is not within watched namespaces", selector, namespace) + log.Warn().Msgf("Namespace %q is not within %q watched namespaces", selector, namespace) continue } namespaces = append(namespaces, namespace.Name) @@ -264,7 +264,7 @@ func (c *clientWrapper) GetHTTPRoutes(namespaces []string) ([]*v1alpha2.HTTPRout var httpRoutes []*v1alpha2.HTTPRoute for _, namespace := range namespaces { if !c.isWatchedNamespace(namespace) { - log.WithoutContext().Warnf("Failed to get HTTPRoutes: %q is not within watched namespaces", namespace) + log.Warn().Msgf("Failed to get HTTPRoutes: %q is not within watched namespaces", namespace) continue } @@ -274,7 +274,7 @@ func (c *clientWrapper) GetHTTPRoutes(namespaces []string) ([]*v1alpha2.HTTPRout } if len(routes) == 0 { - log.WithoutContext().Debugf("No HTTPRoutes found in namespace %q", namespace) + log.Debug().Msgf("No HTTPRoutes found in namespace %q", namespace) continue } @@ -288,7 +288,7 @@ func (c *clientWrapper) GetTCPRoutes(namespaces []string) ([]*v1alpha2.TCPRoute, var tcpRoutes []*v1alpha2.TCPRoute for _, namespace := range namespaces { if !c.isWatchedNamespace(namespace) { - log.WithoutContext().Warnf("Failed to get TCPRoutes: %q is not within watched namespaces", namespace) + log.Warn().Msgf("Failed to get TCPRoutes: %q is not within watched namespaces", namespace) continue } @@ -298,7 +298,7 @@ func (c *clientWrapper) GetTCPRoutes(namespaces []string) ([]*v1alpha2.TCPRoute, } if len(routes) == 0 { - log.WithoutContext().Debugf("No TCPRoutes found in namespace %q", namespace) + log.Debug().Msgf("No TCPRoutes found in namespace %q", namespace) continue } @@ -311,7 +311,7 @@ func (c *clientWrapper) GetTLSRoutes(namespaces []string) ([]*v1alpha2.TLSRoute, var tlsRoutes []*v1alpha2.TLSRoute for _, namespace := range namespaces { if !c.isWatchedNamespace(namespace) { - log.WithoutContext().Warnf("Failed to get TLSRoutes: %q is not within watched namespaces", namespace) + log.Warn().Msgf("Failed to get TLSRoutes: %q is not within watched namespaces", namespace) continue } @@ -321,7 +321,7 @@ func (c *clientWrapper) GetTLSRoutes(namespaces []string) ([]*v1alpha2.TLSRoute, } if len(routes) == 0 { - log.WithoutContext().Debugf("No TLSRoutes found in namespace %q", namespace) + log.Debug().Msgf("No TLSRoutes found in namespace %q", namespace) continue } @@ -336,7 +336,7 @@ func (c *clientWrapper) GetGateways() []*v1alpha2.Gateway { for ns, factory := range c.factoriesGateway { gateways, err := factory.Gateway().V1alpha2().Gateways().Lister().List(labels.Everything()) if err != nil { - log.WithoutContext().Errorf("Failed to list Gateways in namespace %s: %v", ns, err) + log.Error().Err(err).Msgf("Failed to list Gateways in namespace %s", ns) continue } result = append(result, gateways...) diff --git a/pkg/provider/kubernetes/gateway/kubernetes.go b/pkg/provider/kubernetes/gateway/kubernetes.go index e9da54570..7bc3dc754 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes.go +++ b/pkg/provider/kubernetes/gateway/kubernetes.go @@ -15,10 +15,11 @@ import ( "github.com/cenkalti/backoff/v4" "github.com/hashicorp/go-multierror" "github.com/mitchellh/hashstructure" + "github.com/rs/zerolog/log" ptypes "github.com/traefik/paerser/types" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/job" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" traefikv1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" "github.com/traefik/traefik/v2/pkg/safe" @@ -67,24 +68,19 @@ func (p *Provider) newK8sClient(ctx context.Context) (*clientWrapper, error) { return nil, fmt.Errorf("invalid label selector: %q", p.LabelSelector) } - logger := log.FromContext(ctx) - logger.Infof("label selector is: %q", p.LabelSelector) - - withEndpoint := "" - if p.Endpoint != "" { - withEndpoint = fmt.Sprintf(" with endpoint %s", p.Endpoint) - } + logger := log.Ctx(ctx) + logger.Info().Msgf("Label selector is: %q", p.LabelSelector) var client *clientWrapper switch { case os.Getenv("KUBERNETES_SERVICE_HOST") != "" && os.Getenv("KUBERNETES_SERVICE_PORT") != "": - logger.Infof("Creating in-cluster Provider client%s", withEndpoint) + logger.Info().Str("endpoint", p.Endpoint).Msg("Creating in-cluster Provider client") client, err = newInClusterClient(p.Endpoint) case os.Getenv("KUBECONFIG") != "": - logger.Infof("Creating cluster-external Provider client from KUBECONFIG %s", os.Getenv("KUBECONFIG")) + logger.Info().Msgf("Creating cluster-external Provider client from KUBECONFIG %s", os.Getenv("KUBECONFIG")) client, err = newExternalClusterClientFromFile(os.Getenv("KUBECONFIG")) default: - logger.Infof("Creating cluster-external Provider client%s", withEndpoint) + logger.Info().Str("endpoint", p.Endpoint).Msg("Creating cluster-external Provider client") client, err = newExternalClusterClient(p.Endpoint, p.Token, p.CertAuthFilePath) } @@ -104,8 +100,8 @@ func (p *Provider) Init() error { // Provide allows the k8s provider to provide configurations to traefik using the given configuration channel. func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error { - ctxLog := log.With(context.Background(), log.Str(log.ProviderName, providerName)) - logger := log.FromContext(ctxLog) + logger := log.With().Str(logs.ProviderName, providerName).Logger() + ctxLog := logger.WithContext(context.Background()) k8sClient, err := p.newK8sClient(ctxLog) if err != nil { @@ -116,7 +112,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. operation := func() error { eventsChan, err := k8sClient.WatchAll(p.Namespaces, ctxPool.Done()) if err != nil { - logger.Errorf("Error watching kubernetes events: %v", err) + logger.Error().Err(err).Msg("Error watching kubernetes events") timer := time.NewTimer(1 * time.Second) select { case <-timer.C: @@ -145,9 +141,9 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. confHash, err := hashstructure.Hash(conf, nil) switch { case err != nil: - logger.Error("Unable to hash the configuration") + logger.Error().Msg("Unable to hash the configuration") case p.lastConfiguration.Get() == confHash: - logger.Debugf("Skipping Kubernetes event kind %T", event) + logger.Debug().Msgf("Skipping Kubernetes event kind %T", event) default: p.lastConfiguration.Set(confHash) configurationChan <- dynamic.Message{ @@ -165,11 +161,11 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } notify := func(err error, time time.Duration) { - logger.Errorf("Provider connection error: %v; retrying in %s", err, time) + logger.Error().Err(err).Msgf("Provider connection error, retrying in %s", time) } err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctxPool), notify) if err != nil { - logger.Errorf("Cannot connect to Provider: %v", err) + logger.Error().Err(err).Msg("Cannot connect to Provider") } }) @@ -178,13 +174,13 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. // TODO Handle errors and update resources statuses (gatewayClass, gateway). func (p *Provider) loadConfigurationFromGateway(ctx context.Context, client Client) *dynamic.Configuration { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) gatewayClassNames := map[string]struct{}{} gatewayClasses, err := client.GetGatewayClasses() if err != nil { - logger.Errorf("Cannot find GatewayClasses: %v", err) + logger.Error().Err(err).Msg("Cannot find GatewayClasses") return &dynamic.Configuration{ UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -215,7 +211,7 @@ func (p *Provider) loadConfigurationFromGateway(ctx context.Context, client Clie LastTransitionTime: metav1.Now(), }) if err != nil { - logger.Errorf("Failed to update %s condition: %v", v1alpha2.GatewayClassConditionStatusAccepted, err) + logger.Error().Err(err).Msgf("Failed to update %s condition", v1alpha2.GatewayClassConditionStatusAccepted) } } } @@ -224,8 +220,8 @@ func (p *Provider) loadConfigurationFromGateway(ctx context.Context, client Clie // TODO check if we can only use the default filtering mechanism for _, gateway := range client.GetGateways() { - ctxLog := log.With(ctx, log.Str("gateway", gateway.Name), log.Str("namespace", gateway.Namespace)) - logger := log.FromContext(ctxLog) + logger := log.Ctx(ctx).With().Str("gateway", gateway.Name).Str("namespace", gateway.Namespace).Logger() + ctxLog := logger.WithContext(ctx) if _, ok := gatewayClassNames[string(gateway.Spec.GatewayClassName)]; !ok { continue @@ -233,7 +229,7 @@ func (p *Provider) loadConfigurationFromGateway(ctx context.Context, client Clie cfg, err := p.createGatewayConf(ctxLog, client, gateway) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } @@ -315,7 +311,7 @@ func (p *Provider) createGatewayConf(ctx context.Context, client Client, gateway } func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *v1alpha2.Gateway, conf *dynamic.Configuration, tlsConfigs map[string]*tls.CertAndStores) []v1alpha2.ListenerStatus { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) listenerStatuses := make([]v1alpha2.ListenerStatus, len(gateway.Spec.Listeners)) allocatedListeners := make(map[string]struct{}) @@ -407,7 +403,7 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway * if isTLSPassthrough && len(listener.TLS.CertificateRefs) > 0 { // https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.GatewayTLSConfig - logger.Warnf("In case of Passthrough TLS mode, no TLS settings take effect as the TLS session from the client is NOT terminated at the Gateway") + logger.Warn().Msg("In case of Passthrough TLS mode, no TLS settings take effect as the TLS session from the client is NOT terminated at the Gateway") } // Allowed configurations: @@ -684,7 +680,7 @@ func gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener v1alpha } if len(routes) == 0 { - log.FromContext(ctx).Debugf("No HTTPRoutes found") + log.Ctx(ctx).Debug().Msg("No HTTPRoutes found") return nil } @@ -825,7 +821,7 @@ func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2. } if len(routes) == 0 { - log.FromContext(ctx).Debugf("No TCPRoutes found") + log.Ctx(ctx).Debug().Msg("No TCPRoutes found") return nil } @@ -955,7 +951,7 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2. } if len(routes) == 0 { - log.FromContext(ctx).Debugf("No TLSRoutes found") + log.Ctx(ctx).Debug().Msg("No TLSRoutes found") return nil } @@ -1466,7 +1462,7 @@ func loadServices(client Client, namespace string, backendRefs []v1alpha2.HTTPBa // "DroppedRoutes" reason. The gateway status for this route // should be updated with a condition that describes the error // more specifically. - log.WithoutContext().Errorf("A multiple ports Kubernetes Service cannot be used if unspecified backendRef.Port") + log.Error().Msg("A multiple ports Kubernetes Service cannot be used if unspecified backendRef.Port") continue } @@ -1587,7 +1583,7 @@ func loadTCPServices(client Client, namespace string, backendRefs []v1alpha2.Bac // "DroppedRoutes" reason. The gateway status for this route // should be updated with a condition that describes the error // more specifically. - log.WithoutContext().Errorf("A multiple ports Kubernetes Service cannot be used if unspecified backendRef.Port") + log.Error().Msg("A multiple ports Kubernetes Service cannot be used if unspecified backendRef.Port") continue } @@ -1684,7 +1680,7 @@ func throttleEvents(ctx context.Context, throttleDuration time.Duration, pool *s default: // We already have an event in eventsChanBuffered, so we'll do a refresh as soon as our throttle allows us to. // It's fine to drop the event and keep whatever's in the buffer -- we don't do different things for different events - log.FromContext(ctx).Debugf("Dropping event kind %T due to throttling", nextEvent) + log.Ctx(ctx).Debug().Msgf("Dropping event kind %T due to throttling", nextEvent) } } } diff --git a/pkg/provider/kubernetes/ingress/client.go b/pkg/provider/kubernetes/ingress/client.go index b9759b1f0..eccd39657 100644 --- a/pkg/provider/kubernetes/ingress/client.go +++ b/pkg/provider/kubernetes/ingress/client.go @@ -10,7 +10,7 @@ import ( "time" "github.com/hashicorp/go-version" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/k8s" traefikversion "github.com/traefik/traefik/v2/pkg/version" corev1 "k8s.io/api/core/v1" @@ -246,7 +246,7 @@ func (c *clientWrapper) GetIngresses() []*networkingv1.Ingress { // networking listNew, err := factory.Networking().V1().Ingresses().Lister().List(labels.Everything()) if err != nil { - log.WithoutContext().Errorf("Failed to list ingresses in namespace %s: %v", ns, err) + log.Error().Err(err).Msgf("Failed to list ingresses in namespace %s", ns) continue } @@ -257,14 +257,14 @@ func (c *clientWrapper) GetIngresses() []*networkingv1.Ingress { // networking beta list, err := factory.Networking().V1beta1().Ingresses().Lister().List(labels.Everything()) if err != nil { - log.WithoutContext().Errorf("Failed to list ingresses in namespace %s: %v", ns, err) + log.Error().Err(err).Msgf("Failed to list ingresses in namespace %s", ns) continue } for _, ing := range list { n, err := toNetworkingV1(ing) if err != nil { - log.WithoutContext().Errorf("Failed to convert ingress %s from networking/v1beta1 to networking/v1: %v", ns, err) + log.Error().Err(err).Msgf("Failed to convert ingress %s from networking/v1beta1 to networking/v1", ns) continue } @@ -366,10 +366,10 @@ func (c *clientWrapper) UpdateIngressStatus(src *networkingv1.Ingress, ingStatus return fmt.Errorf("failed to get ingress %s/%s: %w", src.Namespace, src.Name, err) } - logger := log.WithoutContext().WithField("namespace", ing.Namespace).WithField("ingress", ing.Name) + logger := log.With().Str("namespace", ing.Namespace).Str("ingress", ing.Name).Logger() if isLoadBalancerIngressEquals(ing.Status.LoadBalancer.Ingress, ingStatus) { - logger.Debug("Skipping ingress status update") + logger.Debug().Msg("Skipping ingress status update") return nil } @@ -384,7 +384,7 @@ func (c *clientWrapper) UpdateIngressStatus(src *networkingv1.Ingress, ingStatus return fmt.Errorf("failed to update ingress status %s/%s: %w", src.Namespace, src.Name, err) } - logger.Info("Updated ingress status") + logger.Info().Msg("Updated ingress status") return nil } @@ -394,10 +394,10 @@ func (c *clientWrapper) updateIngressStatusOld(src *networkingv1.Ingress, ingSta return fmt.Errorf("failed to get ingress %s/%s: %w", src.Namespace, src.Name, err) } - logger := log.WithoutContext().WithField("namespace", ing.Namespace).WithField("ingress", ing.Name) + logger := log.With().Str("namespace", ing.Namespace).Str("ingress", ing.Name).Logger() if isLoadBalancerIngressEquals(ing.Status.LoadBalancer.Ingress, ingStatus) { - logger.Debug("Skipping ingress status update") + logger.Debug().Msg("Skipping ingress status update") return nil } @@ -411,7 +411,7 @@ func (c *clientWrapper) updateIngressStatusOld(src *networkingv1.Ingress, ingSta if err != nil { return fmt.Errorf("failed to update ingress status %s/%s: %w", src.Namespace, src.Name, err) } - logger.Info("Updated ingress status") + logger.Info().Msg("Updated ingress status") return nil } @@ -484,7 +484,7 @@ func (c *clientWrapper) GetIngressClasses() ([]*networkingv1.IngressClass, error if ic.Spec.Controller == traefikDefaultIngressClassController { icN, err := toNetworkingV1IngressClass(ic) if err != nil { - log.WithoutContext().Errorf("Failed to convert ingress class %s from networking/v1beta1 to networking/v1: %v", ic.Name, err) + log.Error().Err(err).Msgf("Failed to convert ingress class %s from networking/v1beta1 to networking/v1", ic.Name) continue } ics = append(ics, icN) diff --git a/pkg/provider/kubernetes/ingress/kubernetes.go b/pkg/provider/kubernetes/ingress/kubernetes.go index 4677b8b5d..502c7cbe9 100644 --- a/pkg/provider/kubernetes/ingress/kubernetes.go +++ b/pkg/provider/kubernetes/ingress/kubernetes.go @@ -15,10 +15,11 @@ import ( "github.com/cenkalti/backoff/v4" "github.com/mitchellh/hashstructure" + "github.com/rs/zerolog/log" ptypes "github.com/traefik/paerser/types" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/job" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/tls" @@ -62,9 +63,9 @@ func (p *Provider) newK8sClient(ctx context.Context) (*clientWrapper, error) { return nil, fmt.Errorf("invalid ingress label selector: %q", p.LabelSelector) } - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) - logger.Infof("ingress label selector is: %q", p.LabelSelector) + logger.Info().Msgf("ingress label selector is: %q", p.LabelSelector) withEndpoint := "" if p.Endpoint != "" { @@ -74,13 +75,13 @@ func (p *Provider) newK8sClient(ctx context.Context) (*clientWrapper, error) { var cl *clientWrapper switch { case os.Getenv("KUBERNETES_SERVICE_HOST") != "" && os.Getenv("KUBERNETES_SERVICE_PORT") != "": - logger.Infof("Creating in-cluster Provider client%s", withEndpoint) + logger.Info().Msgf("Creating in-cluster Provider client%s", withEndpoint) cl, err = newInClusterClient(p.Endpoint) case os.Getenv("KUBECONFIG") != "": - logger.Infof("Creating cluster-external Provider client from KUBECONFIG %s", os.Getenv("KUBECONFIG")) + logger.Info().Msgf("Creating cluster-external Provider client from KUBECONFIG %s", os.Getenv("KUBECONFIG")) cl, err = newExternalClusterClientFromFile(os.Getenv("KUBECONFIG")) default: - logger.Infof("Creating cluster-external Provider client%s", withEndpoint) + logger.Info().Msgf("Creating cluster-external Provider client%s", withEndpoint) cl, err = newExternalClusterClient(p.Endpoint, p.Token, p.CertAuthFilePath) } @@ -100,8 +101,8 @@ func (p *Provider) Init() error { // Provide allows the k8s provider to provide configurations to traefik // using the given configuration channel. func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error { - ctxLog := log.With(context.Background(), log.Str(log.ProviderName, "kubernetes")) - logger := log.FromContext(ctxLog) + logger := log.With().Str(logs.ProviderName, "kubernetes").Logger() + ctxLog := logger.WithContext(context.Background()) k8sClient, err := p.newK8sClient(ctxLog) if err != nil { @@ -109,14 +110,14 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } if p.AllowExternalNameServices { - logger.Warn("ExternalName service loading is enabled, please ensure that this is expected (see AllowExternalNameServices option)") + logger.Warn().Msg("ExternalName service loading is enabled, please ensure that this is expected (see AllowExternalNameServices option)") } pool.GoCtx(func(ctxPool context.Context) { operation := func() error { eventsChan, err := k8sClient.WatchAll(p.Namespaces, ctxPool.Done()) if err != nil { - logger.Errorf("Error watching kubernetes events: %v", err) + logger.Error().Err(err).Msg("Error watching kubernetes events") timer := time.NewTimer(1 * time.Second) select { case <-timer.C: @@ -147,9 +148,9 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. confHash, err := hashstructure.Hash(conf, nil) switch { case err != nil: - logger.Error("Unable to hash the configuration") + logger.Error().Msg("Unable to hash the configuration") case p.lastConfiguration.Get() == confHash: - logger.Debugf("Skipping Kubernetes event kind %T", event) + logger.Debug().Msgf("Skipping Kubernetes event kind %T", event) default: p.lastConfiguration.Set(confHash) configurationChan <- dynamic.Message{ @@ -167,12 +168,12 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } notify := func(err error, time time.Duration) { - logger.Errorf("Provider connection error: %s; retrying in %s", err, time) + logger.Error().Err(err).Msgf("Provider connection error, retrying in %s", time) } err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctxPool), notify) if err != nil { - logger.Errorf("Cannot connect to Provider: %s", err) + logger.Error().Err(err).Msg("Cannot connect to Provider") } }) @@ -196,7 +197,7 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl if supportsIngressClass(serverVersion) { ics, err := client.GetIngressClasses() if err != nil { - log.FromContext(ctx).Warnf("Failed to list ingress classes: %v", err) + log.Ctx(ctx).Warn().Err(err).Msg("Failed to list ingress classes") } if p.IngressClass != "" { @@ -210,7 +211,8 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl certConfigs := make(map[string]*tls.CertAndStores) for _, ingress := range ingresses { - ctx = log.With(ctx, log.Str("ingress", ingress.Name), log.Str("namespace", ingress.Namespace)) + logger := log.Ctx(ctx).With().Str("ingress", ingress.Name).Str("namespace", ingress.Namespace).Logger() + ctx = logger.WithContext(ctx) if !p.shouldProcessIngress(ingress, ingressClasses) { continue @@ -218,35 +220,36 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl rtConfig, err := parseRouterConfig(ingress.Annotations) if err != nil { - log.FromContext(ctx).Errorf("Failed to parse annotations: %v", err) + logger.Error().Err(err).Msg("Failed to parse annotations") continue } err = getCertificates(ctx, ingress, client, certConfigs) if err != nil { - log.FromContext(ctx).Errorf("Error configuring TLS: %v", err) + logger.Error().Err(err).Msg("Error configuring TLS") } if len(ingress.Spec.Rules) == 0 && ingress.Spec.DefaultBackend != nil { if _, ok := conf.HTTP.Services["default-backend"]; ok { - log.FromContext(ctx).Error("The default backend already exists.") + logger.Error().Msg("The default backend already exists.") continue } service, err := p.loadService(client, ingress.Namespace, *ingress.Spec.DefaultBackend) if err != nil { - log.FromContext(ctx). - WithField("serviceName", ingress.Spec.DefaultBackend.Service.Name). - WithField("servicePort", ingress.Spec.DefaultBackend.Service.Port.String()). - Errorf("Cannot create service: %v", err) + logger.Error(). + Str("serviceName", ingress.Spec.DefaultBackend.Service.Name). + Str("servicePort", ingress.Spec.DefaultBackend.Service.Port.String()). + Err(err). + Msg("Cannot create service") continue } if len(service.LoadBalancer.Servers) == 0 && !p.AllowEmptyServices { - log.FromContext(ctx). - WithField("serviceName", ingress.Spec.DefaultBackend.Service.Name). - WithField("servicePort", ingress.Spec.DefaultBackend.Service.Port.String()). - Errorf("Skipping service: no endpoints found") + logger.Error(). + Str("serviceName", ingress.Spec.DefaultBackend.Service.Name). + Str("servicePort", ingress.Spec.DefaultBackend.Service.Port.String()). + Msg("Skipping service: no endpoints found") continue } @@ -270,7 +273,7 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl for _, rule := range ingress.Spec.Rules { if err := p.updateIngressStatus(ingress, client); err != nil { - log.FromContext(ctx).Errorf("Error while updating ingress status: %v", err) + logger.Error().Err(err).Msg("Error while updating ingress status") } if rule.HTTP == nil { @@ -280,18 +283,19 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl for _, pa := range rule.HTTP.Paths { service, err := p.loadService(client, ingress.Namespace, pa.Backend) if err != nil { - log.FromContext(ctx). - WithField("serviceName", pa.Backend.Service.Name). - WithField("servicePort", pa.Backend.Service.Port.String()). - Errorf("Cannot create service: %v", err) + logger.Error(). + Str("serviceName", pa.Backend.Service.Name). + Str("servicePort", pa.Backend.Service.Port.String()). + Err(err). + Msg("Cannot create service") continue } if len(service.LoadBalancer.Servers) == 0 && !p.AllowEmptyServices { - log.FromContext(ctx). - WithField("serviceName", pa.Backend.Service.Name). - WithField("servicePort", pa.Backend.Service.Port.String()). - Errorf("Skipping service: no endpoints found") + logger.Error(). + Str("serviceName", pa.Backend.Service.Name). + Str("servicePort", pa.Backend.Service.Port.String()). + Msg("Skipping service: no endpoints found") continue } @@ -315,12 +319,12 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl continue } - log.FromContext(ctx).Debugf("Multiple routers are defined with the same key %q, generating hashes to avoid conflicts", routerKey) + logger.Debug().Msgf("Multiple routers are defined with the same key %q, generating hashes to avoid conflicts", routerKey) for _, router := range conflictingRouters { key, err := makeRouterKeyWithHash(routerKey, router.Rule) if err != nil { - log.FromContext(ctx).Error(err) + logger.Error().Err(err).Send() continue } @@ -367,7 +371,7 @@ func (p *Provider) updateIngressStatus(ing *networkingv1.Ingress, k8sClient Clie if exists && service.Status.LoadBalancer.Ingress == nil { // service exists, but has no Load Balancer status - log.Debugf("Skipping updating Ingress %s/%s due to service %s having no status set", ing.Namespace, ing.Name, p.IngressEndpoint.PublishedService) + log.Debug().Msgf("Skipping updating Ingress %s/%s due to service %s having no status set", ing.Namespace, ing.Name, p.IngressEndpoint.PublishedService) return nil } @@ -405,7 +409,7 @@ func buildHostRule(host string) string { func getCertificates(ctx context.Context, ingress *networkingv1.Ingress, k8sClient Client, tlsConfigs map[string]*tls.CertAndStores) error { for _, t := range ingress.Spec.TLS { if t.SecretName == "" { - log.FromContext(ctx).Debugf("Skipping TLS sub-section: No secret name provided") + log.Ctx(ctx).Debug().Msg("Skipping TLS sub-section: No secret name provided") continue } @@ -673,7 +677,7 @@ func throttleEvents(ctx context.Context, throttleDuration time.Duration, pool *s // do a refresh as soon as our throttle allows us to. It's fine // to drop the event and keep whatever's in the buffer -- we // don't do different things for different events. - log.FromContext(ctx).Debugf("Dropping event kind %T due to throttling", nextEvent) + log.Ctx(ctx).Debug().Msgf("Dropping event kind %T due to throttling", nextEvent) } } } diff --git a/pkg/provider/kubernetes/k8s/parser.go b/pkg/provider/kubernetes/k8s/parser.go index 6a3e94f7b..6b1f43b76 100644 --- a/pkg/provider/kubernetes/k8s/parser.go +++ b/pkg/provider/kubernetes/k8s/parser.go @@ -5,7 +5,7 @@ import ( "regexp" "strings" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes/scheme" ) @@ -28,7 +28,7 @@ func MustParseYaml(content []byte) []runtime.Object { } if !acceptedK8sTypes.MatchString(groupVersionKind.Kind) { - log.WithoutContext().Debugf("The custom-roles configMap contained K8s object types which are not supported! Skipping object with type: %s", groupVersionKind.Kind) + log.Debug().Msgf("The custom-roles configMap contained K8s object types which are not supported! Skipping object with type: %s", groupVersionKind.Kind) } else { retVal = append(retVal, obj) } diff --git a/pkg/provider/kv/consul/consul.go b/pkg/provider/kv/consul/consul.go index 86aac23bf..6b4b5a5fb 100644 --- a/pkg/provider/kv/consul/consul.go +++ b/pkg/provider/kv/consul/consul.go @@ -7,7 +7,7 @@ import ( "time" "github.com/kvtools/consul" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/provider/kv" "github.com/traefik/traefik/v2/pkg/types" @@ -41,7 +41,7 @@ func (p *ProviderBuilder) BuildProviders() []*Provider { // We can warn about that, because we've already made sure before that // Namespace and Namespaces are mutually exclusive. if p.Namespace != "" { - log.WithoutContext().Warnf("Namespace option is deprecated, please use the Namespaces option instead.") + log.Warn().Msg("Namespace option is deprecated, please use the Namespaces option instead.") } if len(p.Namespaces) == 0 { diff --git a/pkg/provider/kv/kv.go b/pkg/provider/kv/kv.go index 3bbf201f9..abc25a84d 100644 --- a/pkg/provider/kv/kv.go +++ b/pkg/provider/kv/kv.go @@ -10,10 +10,11 @@ import ( "github.com/cenkalti/backoff/v4" "github.com/kvtools/valkeyrie" "github.com/kvtools/valkeyrie/store" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/kv" "github.com/traefik/traefik/v2/pkg/job" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/safe" ) @@ -34,7 +35,7 @@ func (p *Provider) SetDefaults() { // Init the provider. func (p *Provider) Init(storeType, name string, config valkeyrie.Config) error { - ctx := log.With(context.Background(), log.Str(log.ProviderName, name)) + ctx := log.With().Str(logs.ProviderName, name).Logger().WithContext(context.Background()) p.name = name @@ -50,8 +51,8 @@ func (p *Provider) Init(storeType, name string, config valkeyrie.Config) error { // Provide allows the docker provider to provide configurations to traefik using the given configuration channel. func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error { - ctx := log.With(context.Background(), log.Str(log.ProviderName, p.name)) - logger := log.FromContext(ctx) + logger := log.With().Str(logs.ProviderName, p.name).Logger() + ctx := logger.WithContext(context.Background()) operation := func() error { if _, err := p.kvClient.Exists(ctx, path.Join(p.RootKey, "qmslkjdfmqlskdjfmqlksjazçueznbvbwzlkajzebvkwjdcqmlsfj"), nil); err != nil { @@ -61,8 +62,9 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } notify := func(err error, time time.Duration) { - logger.Errorf("KV connection error: %+v, retrying in %s", err, time) + logger.Error().Err(err).Msgf("KV connection error, retrying in %s", time) } + err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctx), notify) if err != nil { return fmt.Errorf("cannot connect to KV server: %w", err) @@ -70,7 +72,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. configuration, err := p.buildConfiguration(ctx) if err != nil { - logger.Errorf("Cannot build the configuration: %v", err) + logger.Error().Err(err).Msg("Cannot build the configuration") } else { configurationChan <- dynamic.Message{ ProviderName: p.name, @@ -79,11 +81,11 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } pool.GoCtx(func(ctxPool context.Context) { - ctxLog := log.With(ctxPool, log.Str(log.ProviderName, p.name)) + ctxLog := logger.With().Str(logs.ProviderName, p.name).Logger().WithContext(ctxPool) err := p.watchKv(ctxLog, configurationChan) if err != nil { - logger.Errorf("Cannot watch KV store: %v", err) + logger.Error().Err(err).Msg("Cannot watch KV store") } }) @@ -122,7 +124,7 @@ func (p *Provider) watchKv(ctx context.Context, configurationChan chan<- dynamic } notify := func(err error, time time.Duration) { - log.FromContext(ctx).Errorf("KV connection error: %+v, retrying in %s", err, time) + log.Ctx(ctx).Error().Err(err).Msgf("KV connection error, retrying in %s", time) } err := backoff.RetryNotify(safe.OperationWithRecover(operation), diff --git a/pkg/provider/kv/storewrapper.go b/pkg/provider/kv/storewrapper.go index 2a7b9aad7..382c99804 100644 --- a/pkg/provider/kv/storewrapper.go +++ b/pkg/provider/kv/storewrapper.go @@ -4,7 +4,7 @@ import ( "context" "github.com/kvtools/valkeyrie/store" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) type storeWrapper struct { @@ -12,7 +12,7 @@ type storeWrapper struct { } func (s *storeWrapper) Put(ctx context.Context, key string, value []byte, options *store.WriteOptions) error { - log.WithoutContext().Debugf("Put: %s", key, string(value)) + log.Debug().Msgf("Put: %s %s", key, string(value)) if s.Store == nil { return nil @@ -21,7 +21,7 @@ func (s *storeWrapper) Put(ctx context.Context, key string, value []byte, option } func (s *storeWrapper) Get(ctx context.Context, key string, options *store.ReadOptions) (*store.KVPair, error) { - log.WithoutContext().Debugf("Get: %s", key) + log.Debug().Msgf("Get: %s", key) if s.Store == nil { return nil, nil @@ -30,7 +30,7 @@ func (s *storeWrapper) Get(ctx context.Context, key string, options *store.ReadO } func (s *storeWrapper) Delete(ctx context.Context, key string) error { - log.WithoutContext().Debugf("Delete: %s", key) + log.Debug().Msgf("Delete: %s", key) if s.Store == nil { return nil @@ -39,7 +39,7 @@ func (s *storeWrapper) Delete(ctx context.Context, key string) error { } func (s *storeWrapper) Exists(ctx context.Context, key string, options *store.ReadOptions) (bool, error) { - log.WithoutContext().Debugf("Exists: %s", key) + log.Debug().Msgf("Exists: %s", key) if s.Store == nil { return true, nil @@ -48,7 +48,7 @@ func (s *storeWrapper) Exists(ctx context.Context, key string, options *store.Re } func (s *storeWrapper) Watch(ctx context.Context, key string, options *store.ReadOptions) (<-chan *store.KVPair, error) { - log.WithoutContext().Debugf("Watch: %s", key) + log.Debug().Msgf("Watch: %s", key) if s.Store == nil { return nil, nil @@ -57,7 +57,7 @@ func (s *storeWrapper) Watch(ctx context.Context, key string, options *store.Rea } func (s *storeWrapper) WatchTree(ctx context.Context, directory string, options *store.ReadOptions) (<-chan []*store.KVPair, error) { - log.WithoutContext().Debugf("WatchTree: %s", directory) + log.Debug().Msgf("WatchTree: %s", directory) if s.Store == nil { return nil, nil @@ -66,7 +66,7 @@ func (s *storeWrapper) WatchTree(ctx context.Context, directory string, options } func (s *storeWrapper) NewLock(ctx context.Context, key string, options *store.LockOptions) (store.Locker, error) { - log.WithoutContext().Debugf("NewLock: %s", key) + log.Debug().Msgf("NewLock: %s", key) if s.Store == nil { return nil, nil @@ -75,7 +75,7 @@ func (s *storeWrapper) NewLock(ctx context.Context, key string, options *store.L } func (s *storeWrapper) List(ctx context.Context, directory string, options *store.ReadOptions) ([]*store.KVPair, error) { - log.WithoutContext().Debugf("List: %s", directory) + log.Debug().Msgf("List: %s", directory) if s.Store == nil { return nil, nil @@ -84,7 +84,7 @@ func (s *storeWrapper) List(ctx context.Context, directory string, options *stor } func (s *storeWrapper) DeleteTree(ctx context.Context, directory string) error { - log.WithoutContext().Debugf("DeleteTree: %s", directory) + log.Debug().Msgf("DeleteTree: %s", directory) if s.Store == nil { return nil @@ -93,7 +93,7 @@ func (s *storeWrapper) DeleteTree(ctx context.Context, directory string) error { } func (s *storeWrapper) AtomicPut(ctx context.Context, key string, value []byte, previous *store.KVPair, options *store.WriteOptions) (bool, *store.KVPair, error) { - log.WithoutContext().Debugf("AtomicPut: %s", key, string(value), previous) + log.Debug().Msgf("AtomicPut: %s %s %v", key, string(value), previous) if s.Store == nil { return true, nil, nil @@ -102,7 +102,7 @@ func (s *storeWrapper) AtomicPut(ctx context.Context, key string, value []byte, } func (s *storeWrapper) AtomicDelete(ctx context.Context, key string, previous *store.KVPair) (bool, error) { - log.WithoutContext().Debugf("AtomicDelete: %s", key, previous) + log.Debug().Msgf("AtomicDelete: %s %v", key, previous) if s.Store == nil { return true, nil @@ -111,7 +111,7 @@ func (s *storeWrapper) AtomicDelete(ctx context.Context, key string, previous *s } func (s *storeWrapper) Close() error { - log.WithoutContext().Debugf("Close") + log.Debug().Msg("Close") if s.Store == nil { return nil diff --git a/pkg/provider/marathon/config.go b/pkg/provider/marathon/config.go index 4f9216e9b..939505351 100644 --- a/pkg/provider/marathon/config.go +++ b/pkg/provider/marathon/config.go @@ -10,9 +10,9 @@ import ( "strings" "github.com/gambol99/go-marathon" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/label" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/provider/constraints" ) @@ -21,12 +21,12 @@ func (p *Provider) buildConfiguration(ctx context.Context, applications *maratho configurations := make(map[string]*dynamic.Configuration) for _, app := range applications.Apps { - ctxApp := log.With(ctx, log.Str("applicationID", app.ID)) - logger := log.FromContext(ctxApp) + logger := log.Ctx(ctx).With().Str("applicationID", app.ID).Logger() + ctxApp := logger.WithContext(ctx) extraConf, err := p.getConfiguration(app) if err != nil { - logger.Errorf("Skip application: %v", err) + logger.Error().Err(err).Msg("Skip application") continue } @@ -45,7 +45,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, applications *maratho confFromLabel, err := label.DecodeConfiguration(labels) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } @@ -55,7 +55,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, applications *maratho err := p.buildTCPServiceConfiguration(ctxApp, app, extraConf, confFromLabel.TCP) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } provider.BuildTCPRouterConfiguration(ctxApp, confFromLabel.TCP) @@ -66,7 +66,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, applications *maratho err := p.buildUDPServiceConfiguration(ctxApp, app, extraConf, confFromLabel.UDP) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() } else { provider.BuildUDPRouterConfiguration(ctxApp, confFromLabel.UDP) } @@ -81,7 +81,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, applications *maratho err = p.buildServiceConfiguration(ctxApp, app, extraConf, confFromLabel.HTTP) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } @@ -109,7 +109,8 @@ func getServiceName(app marathon.Application) string { func (p *Provider) buildServiceConfiguration(ctx context.Context, app marathon.Application, extraConf configuration, conf *dynamic.HTTPConfiguration) error { appName := getServiceName(app) - appCtx := log.With(ctx, log.Str("ApplicationID", appName)) + + logger := log.Ctx(ctx).With().Str("applicationName", appName).Logger() if len(conf.Services) == 0 { conf.Services = make(map[string]*dynamic.Service) @@ -136,7 +137,7 @@ func (p *Provider) buildServiceConfiguration(ctx context.Context, app marathon.A } server, err := p.getServer(app, *task, extraConf, defaultServer) if err != nil { - log.FromContext(appCtx).Errorf("Skip task: %v", err) + logger.Error().Err(err).Msg("Skip task") continue } servers = append(servers, server) @@ -152,7 +153,8 @@ func (p *Provider) buildServiceConfiguration(ctx context.Context, app marathon.A func (p *Provider) buildTCPServiceConfiguration(ctx context.Context, app marathon.Application, extraConf configuration, conf *dynamic.TCPConfiguration) error { appName := getServiceName(app) - appCtx := log.With(ctx, log.Str("ApplicationID", appName)) + + logger := log.Ctx(ctx).With().Str("applicationName", appName).Logger() if len(conf.Services) == 0 { conf.Services = make(map[string]*dynamic.TCPService) @@ -176,7 +178,7 @@ func (p *Provider) buildTCPServiceConfiguration(ctx context.Context, app maratho if p.taskFilter(ctx, *task, app) { server, err := p.getTCPServer(app, *task, extraConf, defaultServer) if err != nil { - log.FromContext(appCtx).Errorf("Skip task: %v", err) + logger.Error().Err(err).Msg("Skip task") continue } servers = append(servers, server) @@ -193,7 +195,7 @@ func (p *Provider) buildTCPServiceConfiguration(ctx context.Context, app maratho func (p *Provider) buildUDPServiceConfiguration(ctx context.Context, app marathon.Application, extraConf configuration, conf *dynamic.UDPConfiguration) error { appName := getServiceName(app) - appCtx := log.With(ctx, log.Str("ApplicationID", appName)) + logger := log.Ctx(ctx).With().Str("applicationName", appName).Logger() if len(conf.Services) == 0 { conf.Services = make(map[string]*dynamic.UDPService) @@ -217,7 +219,7 @@ func (p *Provider) buildUDPServiceConfiguration(ctx context.Context, app maratho if p.taskFilter(ctx, *task, app) { server, err := p.getUDPServer(app, *task, extraConf, defaultServer) if err != nil { - log.FromContext(appCtx).Errorf("Skip task: %v", err) + logger.Error().Err(err).Msg("Skip task") continue } servers = append(servers, server) @@ -233,22 +235,22 @@ func (p *Provider) buildUDPServiceConfiguration(ctx context.Context, app maratho } func (p *Provider) keepApplication(ctx context.Context, extraConf configuration, labels map[string]string) bool { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) // Filter disabled application. if !extraConf.Enable { - logger.Debug("Filtering disabled Marathon application") + logger.Debug().Msg("Filtering disabled Marathon application") return false } // Filter by constraints. matches, err := constraints.MatchLabels(labels, p.Constraints) if err != nil { - logger.Errorf("Error matching constraints expression: %v", err) + logger.Error().Err(err).Msg("Error matching constraints expression") return false } if !matches { - logger.Debugf("Marathon application filtered by constraint expression: %q", p.Constraints) + logger.Debug().Msgf("Marathon application filtered by constraint expression: %q", p.Constraints) return false } @@ -261,7 +263,7 @@ func (p *Provider) taskFilter(ctx context.Context, task marathon.Task, applicati } if ready := p.readyChecker.Do(task, application); !ready { - log.FromContext(ctx).Infof("Filtering unready task %s from application %s", task.ID, application.ID) + log.Ctx(ctx).Info().Msgf("Filtering unready task %s from application %s", task.ID, application.ID) return false } diff --git a/pkg/provider/marathon/marathon.go b/pkg/provider/marathon/marathon.go index aab469785..423573e66 100644 --- a/pkg/provider/marathon/marathon.go +++ b/pkg/provider/marathon/marathon.go @@ -11,11 +11,12 @@ import ( "github.com/cenkalti/backoff/v4" "github.com/gambol99/go-marathon" - "github.com/sirupsen/logrus" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" ptypes "github.com/traefik/paerser/types" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/job" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/types" @@ -23,9 +24,8 @@ import ( const ( // DefaultTemplateRule The default template for the default rule. - DefaultTemplateRule = "Host(`{{ normalize .Name }}`)" - traceMaxScanTokenSize = 1024 * 1024 - marathonEventIDs = marathon.EventIDApplications | + DefaultTemplateRule = "Host(`{{ normalize .Name }}`)" + marathonEventIDs = marathon.EventIDApplications | marathon.EventIDAddHealthCheck | marathon.EventIDDeploymentSuccess | marathon.EventIDDeploymentFailed | @@ -108,23 +108,25 @@ func (p *Provider) Init() error { // Provide allows the marathon provider to provide configurations to traefik // using the given configuration channel. func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error { - ctx := log.With(context.Background(), log.Str(log.ProviderName, "marathon")) - logger := log.FromContext(ctx) + logger := log.With().Str(logs.ProviderName, "marathon").Logger() + ctx := logger.WithContext(context.Background()) operation := func() error { confg := marathon.NewDefaultConfig() confg.URL = p.Endpoint confg.EventsTransport = marathon.EventsTransportSSE + if p.Trace { - confg.LogOutput = log.CustomWriterLevel(logrus.DebugLevel, traceMaxScanTokenSize) + confg.LogOutput = logs.NoLevel(logger, zerolog.DebugLevel) } + if p.Basic != nil { confg.HTTPBasicAuthUser = p.Basic.HTTPBasicAuthUser confg.HTTPBasicPassword = p.Basic.HTTPBasicPassword } var rc *readinessChecker if p.RespectReadinessChecks { - logger.Debug("Enabling Marathon readiness checker") + logger.Debug().Msg("Enabling Marathon readiness checker") rc = defaultReadinessChecker(p.Trace) } p.readyChecker = rc @@ -149,7 +151,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } client, err := marathon.NewClient(confg) if err != nil { - logger.Errorf("Failed to create a client for marathon, error: %s", err) + logger.Error().Err(err).Msg("Failed to create a client for marathon") return err } p.marathonClient = client @@ -157,7 +159,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. if p.Watch { update, err := client.AddEventsListener(marathonEventIDs) if err != nil { - logger.Errorf("Failed to register for events, %s", err) + logger.Error().Err(err).Msg("Failed to register for events") return err } pool.GoCtx(func(ctxPool context.Context) { @@ -167,7 +169,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. case <-ctxPool.Done(): return case event := <-update: - logger.Debugf("Received provider event %s", event) + logger.Debug().Msgf("Received provider event %s", event) conf := p.getConfigurations(ctx) if conf != nil { @@ -190,11 +192,11 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } notify := func(err error, time time.Duration) { - logger.Errorf("Provider connection error %+v, retrying in %s", err, time) + logger.Error().Err(err).Msgf("Provider connection error, retrying in %s", time) } err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctx), notify) if err != nil { - logger.Errorf("Cannot connect to Provider server: %+v", err) + logger.Error().Err(err).Msg("Cannot connect to Provider server") } return nil } @@ -202,7 +204,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. func (p *Provider) getConfigurations(ctx context.Context) *dynamic.Configuration { applications, err := p.getApplications() if err != nil { - log.FromContext(ctx).Errorf("Failed to retrieve Marathon applications: %v", err) + log.Ctx(ctx).Error().Err(err).Msg("Failed to retrieve Marathon applications") return nil } diff --git a/pkg/provider/marathon/readiness.go b/pkg/provider/marathon/readiness.go index df6559968..76785df13 100644 --- a/pkg/provider/marathon/readiness.go +++ b/pkg/provider/marathon/readiness.go @@ -4,7 +4,7 @@ import ( "time" "github.com/gambol99/go-marathon" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) const ( @@ -98,7 +98,7 @@ func (rc *readinessChecker) Do(task marathon.Task, app marathon.Application) boo // An unparseable start time should never occur; if it does, we assume the // problem should be surfaced as quickly as possible, which is easiest if // we shun the task from rotation. - log.Warnf("Failed to parse start-time %s of task %s from application %s: %s (assuming unready)", task.StartedAt, task.ID, app.ID, err) + log.Warn().Err(err).Msgf("Failed to parse start-time %s of task %s from application %s (assuming unready)", task.StartedAt, task.ID, app.ID) return false } @@ -117,6 +117,6 @@ func (rc *readinessChecker) Do(task marathon.Task, app marathon.Application) boo func (rc *readinessChecker) tracef(format string, args ...interface{}) { if rc.traceLogging { - log.Debugf(readinessLogHeader+format, args...) + log.Debug().Msgf(readinessLogHeader+format, args...) } } diff --git a/pkg/provider/nomad/config.go b/pkg/provider/nomad/config.go index d53de0009..a31b8ee21 100644 --- a/pkg/provider/nomad/config.go +++ b/pkg/provider/nomad/config.go @@ -10,9 +10,10 @@ import ( "strconv" "strings" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/label" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/provider/constraints" ) @@ -22,18 +23,18 @@ func (p *Provider) buildConfig(ctx context.Context, items []item) *dynamic.Confi for _, i := range items { svcName := provider.Normalize(i.Node + "-" + i.Name + "-" + i.ID) - ctxSvc := log.With(ctx, log.Str(log.ServiceName, svcName)) + logger := log.Ctx(ctx).With().Str(logs.ServiceName, svcName).Logger() + ctxSvc := logger.WithContext(ctx) if !p.keepItem(ctxSvc, i) { continue } - logger := log.FromContext(ctx) labels := tagsToLabels(i.Tags, p.Prefix) config, err := label.DecodeConfiguration(labels) if err != nil { - logger.Errorf("Failed to decode configuration: %v", err) + logger.Error().Err(err).Msg("Failed to decode configuration") continue } @@ -42,7 +43,7 @@ func (p *Provider) buildConfig(ctx context.Context, items []item) *dynamic.Confi if len(config.TCP.Routers) > 0 || len(config.TCP.Services) > 0 { tcpOrUDP = true if err := p.buildTCPConfig(i, config.TCP); err != nil { - logger.Errorf("Failed to build TCP service configuration: %v", err) + logger.Error().Err(err).Msg("Failed to build TCP service configuration") continue } provider.BuildTCPRouterConfiguration(ctxSvc, config.TCP) @@ -51,7 +52,7 @@ func (p *Provider) buildConfig(ctx context.Context, items []item) *dynamic.Confi if len(config.UDP.Routers) > 0 || len(config.UDP.Services) > 0 { tcpOrUDP = true if err := p.buildUDPConfig(i, config.UDP); err != nil { - logger.Errorf("Failed to build UDP service configuration: %v", err) + logger.Error().Err(err).Msg("Failed to build UDP service configuration") continue } provider.BuildUDPRouterConfiguration(ctxSvc, config.UDP) @@ -67,7 +68,7 @@ func (p *Provider) buildConfig(ctx context.Context, items []item) *dynamic.Confi // configure http service if err := p.buildServiceConfig(i, config.HTTP); err != nil { - logger.Errorf("Failed to build HTTP service configuration: %v", err) + logger.Error().Err(err).Msg("Failed to build HTTP service configuration") continue } @@ -148,20 +149,20 @@ func (p *Provider) buildServiceConfig(i item, configuration *dynamic.HTTPConfigu // TODO: check whether it is mandatory to filter again. func (p *Provider) keepItem(ctx context.Context, i item) bool { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) if !i.ExtraConf.Enable { - logger.Debug("Filtering disabled item") + logger.Debug().Msg("Filtering disabled item") return false } matches, err := constraints.MatchTags(i.Tags, p.Constraints) if err != nil { - logger.Errorf("Error matching constraint expressions: %v", err) + logger.Error().Err(err).Msg("Error matching constraint expressions") return false } if !matches { - logger.Debugf("Filtering out item due to constraints: %q", p.Constraints) + logger.Debug().Msgf("Filtering out item due to constraints: %q", p.Constraints) return false } diff --git a/pkg/provider/nomad/nomad.go b/pkg/provider/nomad/nomad.go index e321c05a5..12cba4939 100644 --- a/pkg/provider/nomad/nomad.go +++ b/pkg/provider/nomad/nomad.go @@ -10,10 +10,11 @@ import ( "github.com/cenkalti/backoff/v4" "github.com/hashicorp/nomad/api" + "github.com/rs/zerolog/log" ptypes "github.com/traefik/paerser/types" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/job" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/provider/constraints" "github.com/traefik/traefik/v2/pkg/safe" @@ -59,7 +60,7 @@ type ProviderBuilder struct { // BuildProviders builds Nomad provider instances for the given namespaces configuration. func (p *ProviderBuilder) BuildProviders() []*Provider { if p.Namespace != "" { - log.WithoutContext().Warnf("Namespace option is deprecated, please use the Namespaces option instead.") + log.Warn().Msg("Namespace option is deprecated, please use the Namespaces option instead.") } if len(p.Namespaces) == 0 { @@ -154,8 +155,8 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } pool.GoCtx(func(routineCtx context.Context) { - ctxLog := log.With(routineCtx, log.Str(log.ProviderName, p.name)) - logger := log.FromContext(ctxLog) + logger := log.Ctx(routineCtx).With().Str(logs.ProviderName, p.name).Logger() + ctxLog := logger.WithContext(routineCtx) operation := func() error { ctx, cancel := context.WithCancel(ctxLog) @@ -186,7 +187,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } failure := func(err error, d time.Duration) { - logger.Errorf("Provider connection error %+v, retrying in %s", err, d) + logger.Error().Err(err).Msgf("Provider connection error, retrying in %s", d) } if retryErr := backoff.RetryNotify( @@ -194,7 +195,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctxLog), failure, ); retryErr != nil { - logger.Errorf("Cannot connect to Nomad server %+v", retryErr) + logger.Error().Err(retryErr).Msg("Cannot connect to Nomad server") } }) @@ -273,22 +274,22 @@ func (p *Provider) getNomadServiceData(ctx context.Context) ([]item, error) { for _, stub := range stubs { for _, service := range stub.Services { - logger := log.FromContext(log.With(ctx, log.Str("serviceName", service.ServiceName))) + logger := log.Ctx(ctx).With().Str("serviceName", service.ServiceName).Logger() extraConf := p.getExtraConf(service.Tags) if !extraConf.Enable { - logger.Debug("Filter Nomad service that is not enabled") + logger.Debug().Msg("Filter Nomad service that is not enabled") continue } matches, err := constraints.MatchTags(service.Tags, p.Constraints) if err != nil { - logger.Errorf("Error matching constraint expressions: %v", err) + logger.Error().Err(err).Msg("Error matching constraint expressions") continue } if !matches { - logger.Debugf("Filter Nomad service not matching constraints: %q", p.Constraints) + logger.Debug().Msgf("Filter Nomad service not matching constraints: %q", p.Constraints) continue } diff --git a/pkg/provider/rancher/config.go b/pkg/provider/rancher/config.go index 1f16e5e6f..1b0d5339d 100644 --- a/pkg/provider/rancher/config.go +++ b/pkg/provider/rancher/config.go @@ -7,9 +7,9 @@ import ( "net" "strings" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/label" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/provider/constraints" ) @@ -18,17 +18,16 @@ func (p *Provider) buildConfiguration(ctx context.Context, services []rancherDat configurations := make(map[string]*dynamic.Configuration) for _, service := range services { - ctxService := log.With(ctx, log.Str("service", service.Name)) + logger := log.Ctx(ctx).With().Str("service", service.Name).Logger() + ctxService := logger.WithContext(ctx) if !p.keepService(ctx, service) { continue } - logger := log.FromContext(ctxService) - confFromLabel, err := label.DecodeConfiguration(service.Labels) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } @@ -38,7 +37,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, services []rancherDat err := p.buildTCPServiceConfiguration(ctxService, service, confFromLabel.TCP) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } provider.BuildTCPRouterConfiguration(ctxService, confFromLabel.TCP) @@ -49,7 +48,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, services []rancherDat err := p.buildUDPServiceConfiguration(ctxService, service, confFromLabel.UDP) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } provider.BuildUDPRouterConfiguration(ctxService, confFromLabel.UDP) @@ -64,7 +63,7 @@ func (p *Provider) buildConfiguration(ctx context.Context, services []rancherDat err = p.buildServiceConfiguration(ctx, service, confFromLabel.HTTP) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } @@ -151,30 +150,30 @@ func (p *Provider) buildServiceConfiguration(ctx context.Context, service ranche } func (p *Provider) keepService(ctx context.Context, service rancherData) bool { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) if !service.ExtraConf.Enable { - logger.Debug("Filtering disabled service.") + logger.Debug().Msg("Filtering disabled service") return false } matches, err := constraints.MatchLabels(service.Labels, p.Constraints) if err != nil { - logger.Errorf("Error matching constraint expression: %v", err) + logger.Error().Err(err).Msg("Error matching constraint expression") return false } if !matches { - logger.Debugf("Service pruned by constraint expression: %q", p.Constraints) + logger.Debug().Msgf("Service pruned by constraint expression: %q", p.Constraints) return false } if p.EnableServiceHealthFilter { if service.Health != "" && service.Health != healthy && service.Health != updatingHealthy { - logger.Debugf("Filtering service %s with healthState of %s \n", service.Name, service.Health) + logger.Debug().Msgf("Filtering service %s with healthState of %s", service.Name, service.Health) return false } if service.State != "" && service.State != active && service.State != updatingActive && service.State != upgraded && service.State != upgrading { - logger.Debugf("Filtering service %s with state of %s \n", service.Name, service.State) + logger.Debug().Msgf("Filtering service %s with state of %s", service.Name, service.State) return false } } @@ -183,7 +182,7 @@ func (p *Provider) keepService(ctx context.Context, service rancherData) bool { } func (p *Provider) addServerTCP(ctx context.Context, service rancherData, loadBalancer *dynamic.TCPServersLoadBalancer) error { - log.FromContext(ctx).Debugf("Trying to add servers for service %s \n", service.Name) + log.Ctx(ctx).Debug().Msgf("Trying to add servers for service %s", service.Name) if loadBalancer == nil { return errors.New("load-balancer is not defined") @@ -217,7 +216,7 @@ func (p *Provider) addServerTCP(ctx context.Context, service rancherData, loadBa } func (p *Provider) addServerUDP(ctx context.Context, service rancherData, loadBalancer *dynamic.UDPServersLoadBalancer) error { - log.FromContext(ctx).Debugf("Trying to add servers for service %s \n", service.Name) + log.Ctx(ctx).Debug().Msgf("Trying to add servers for service %s", service.Name) if loadBalancer == nil { return errors.New("load-balancer is not defined") @@ -251,7 +250,7 @@ func (p *Provider) addServerUDP(ctx context.Context, service rancherData, loadBa } func (p *Provider) addServers(ctx context.Context, service rancherData, loadBalancer *dynamic.ServersLoadBalancer) error { - log.FromContext(ctx).Debugf("Trying to add servers for service %s \n", service.Name) + log.Ctx(ctx).Debug().Msgf("Trying to add servers for service %s", service.Name) if loadBalancer == nil { return errors.New("load-balancer is not defined") diff --git a/pkg/provider/rancher/rancher.go b/pkg/provider/rancher/rancher.go index 8de7ad862..8f74dcc21 100644 --- a/pkg/provider/rancher/rancher.go +++ b/pkg/provider/rancher/rancher.go @@ -8,9 +8,10 @@ import ( "github.com/cenkalti/backoff/v4" rancher "github.com/rancher/go-rancher-metadata/metadata" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/job" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/safe" ) @@ -86,7 +87,7 @@ func (p *Provider) createClient(ctx context.Context) (rancher.Client, error) { metadataServiceURL := fmt.Sprintf("http://rancher-metadata.rancher.internal/%s", p.Prefix) client, err := rancher.NewClientAndWait(metadataServiceURL) if err != nil { - log.FromContext(ctx).Errorf("Failed to create Rancher metadata service client: %v", err) + log.Ctx(ctx).Error().Err(err).Msg("Failed to create Rancher metadata service client") return nil, err } @@ -96,20 +97,20 @@ func (p *Provider) createClient(ctx context.Context) (rancher.Client, error) { // Provide allows the rancher provider to provide configurations to traefik using the given configuration channel. func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error { pool.GoCtx(func(routineCtx context.Context) { - ctxLog := log.With(routineCtx, log.Str(log.ProviderName, "rancher")) - logger := log.FromContext(ctxLog) + logger := log.Ctx(routineCtx).With().Str(logs.ProviderName, "rancher").Logger() + ctxLog := logger.WithContext(routineCtx) operation := func() error { client, err := p.createClient(ctxLog) if err != nil { - logger.Errorf("Failed to create the metadata client metadata service: %v", err) + logger.Error().Err(err).Msg("Failed to create the metadata client metadata service") return err } updateConfiguration := func(_ string) { stacks, err := client.GetStacks() if err != nil { - logger.Errorf("Failed to query Rancher metadata service: %v", err) + logger.Error().Err(err).Msg("Failed to query Rancher metadata service") return } @@ -139,11 +140,11 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } notify := func(err error, time time.Duration) { - logger.Errorf("Provider connection error %+v, retrying in %s", err, time) + logger.Error().Err(err).Msgf("Provider connection error, retrying in %s", time) } err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctxLog), notify) if err != nil { - logger.Errorf("Cannot connect to Provider server: %+v", err) + logger.Error().Err(err).Msg("Cannot connect to Provider server") } }) @@ -160,7 +161,7 @@ func (p *Provider) intervalPoll(ctx context.Context, client rancher.Client, upda case <-ticker.C: newVersion, err := client.GetVersion() if err != nil { - log.FromContext(ctx).Errorf("Failed to create Rancher metadata service client: %v", err) + log.Ctx(ctx).Error().Err(err).Msg("Failed to create Rancher metadata service client") } else if version != newVersion { version = newVersion updateConfiguration(version) @@ -174,15 +175,15 @@ func (p *Provider) intervalPoll(ctx context.Context, client rancher.Client, upda func (p *Provider) parseMetadataSourcedRancherData(ctx context.Context, stacks []rancher.Stack) (rancherDataList []rancherData) { for _, stack := range stacks { for _, service := range stack.Services { - ctxSvc := log.With(ctx, log.Str("stack", stack.Name), log.Str("service", service.Name)) - logger := log.FromContext(ctxSvc) + logger := log.Ctx(ctx).With().Str("stack", stack.Name).Str("service", service.Name).Logger() + ctxSvc := logger.WithContext(ctx) servicePort := "" if len(service.Ports) > 0 { servicePort = service.Ports[0] } for _, port := range service.Ports { - logger.Debugf("Set Port %s", port) + logger.Debug().Msgf("Set Port %s", port) } var containerIPAddresses []string @@ -202,7 +203,7 @@ func (p *Provider) parseMetadataSourcedRancherData(ctx context.Context, stacks [ extraConf, err := p.getConfiguration(service) if err != nil { - logger.Errorf("Skip container %s: %v", service.Name, err) + logger.Error().Err(err).Msgf("Skip container %s", service.Name) continue } @@ -215,15 +216,15 @@ func (p *Provider) parseMetadataSourcedRancherData(ctx context.Context, stacks [ } func containerFilter(ctx context.Context, name, healthState, state string) bool { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) if healthState != "" && healthState != healthy && healthState != updatingHealthy { - logger.Debugf("Filtering container %s with healthState of %s", name, healthState) + logger.Debug().Msgf("Filtering container %s with healthState of %s", name, healthState) return false } if state != "" && state != running && state != updatingRunning && state != upgraded { - logger.Debugf("Filtering container %s with state of %s", name, state) + logger.Debug().Msgf("Filtering container %s with state of %s", name, state) return false } diff --git a/pkg/provider/rest/rest.go b/pkg/provider/rest/rest.go index 14be6ab65..f375bd1db 100644 --- a/pkg/provider/rest/rest.go +++ b/pkg/provider/rest/rest.go @@ -6,8 +6,8 @@ import ( "net/http" "github.com/gorilla/mux" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/safe" "github.com/unrolled/render" @@ -48,14 +48,14 @@ func (p *Provider) ServeHTTP(rw http.ResponseWriter, req *http.Request) { configuration := new(dynamic.Configuration) if err := json.NewDecoder(req.Body).Decode(configuration); err != nil { - log.WithoutContext().Errorf("Error parsing configuration %+v", err) + log.Error().Err(err).Msg("Error parsing configuration") http.Error(rw, fmt.Sprintf("%+v", err), http.StatusBadRequest) return } p.configurationChan <- dynamic.Message{ProviderName: "rest", Configuration: configuration} if err := templatesRenderer.JSON(rw, http.StatusOK, configuration); err != nil { - log.WithoutContext().Error(err) + log.Error().Err(err).Send() } } diff --git a/pkg/provider/tailscale/provider.go b/pkg/provider/tailscale/provider.go index 6c7c99c9c..a807dfdcf 100644 --- a/pkg/provider/tailscale/provider.go +++ b/pkg/provider/tailscale/provider.go @@ -9,9 +9,10 @@ import ( "sync" "time" + "github.com/rs/zerolog/log" "github.com/tailscale/tscert" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/muxer/http" "github.com/traefik/traefik/v2/pkg/muxer/tcp" "github.com/traefik/traefik/v2/pkg/safe" @@ -56,21 +57,20 @@ func (p *Provider) HandleConfigUpdate(cfg dynamic.Configuration) { func (p *Provider) Provide(dynMessages chan<- dynamic.Message, pool *safe.Pool) error { p.dynMessages = dynMessages - fields := log.Str(log.ProviderName, p.ResolverName+".tailscale") + logger := log.With().Str(logs.ProviderName, p.ResolverName+".tailscale").Logger() pool.GoCtx(func(ctx context.Context) { - p.watchDomains(log.With(ctx, fields)) + p.watchDomains(logger.WithContext(ctx)) }) pool.GoCtx(func(ctx context.Context) { - p.renewCertificates(log.With(ctx, fields)) + p.renewCertificates(logger.WithContext(ctx)) }) return nil } -// watchDomains watches for Tailscale domain certificates that should be -// fetched from the Tailscale daemon. +// watchDomains watches for Tailscale domain certificates that should be fetched from the Tailscale daemon. func (p *Provider) watchDomains(ctx context.Context) { for { select { @@ -110,9 +110,9 @@ func (p *Provider) renewCertificates(ctx context.Context) { for domain, cert := range p.certByDomain { tlsCert, err := cert.GetCertificateFromBytes() if err != nil { - log.FromContext(ctx). - WithError(err). - Errorf("Unable to get certificate for domain %s", domain) + log.Ctx(ctx). + Err(err). + Msgf("Unable to get certificate for domain %s", domain) continue } @@ -139,7 +139,7 @@ func (p *Provider) renewCertificates(ctx context.Context) { // findDomains goes through the given dynamic.Configuration and returns all // Tailscale-specific domains found. func (p *Provider) findDomains(ctx context.Context, cfg dynamic.Configuration) []string { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) var domains []string @@ -162,7 +162,7 @@ func (p *Provider) findDomains(ctx context.Context, cfg dynamic.Configuration) [ parsedDomains, err := http.ParseDomains(router.Rule) if err != nil { - logger.Errorf("Unable to parse HTTP router domains: %v", err) + logger.Error().Err(err).Msg("Unable to parse HTTP router domains") continue } @@ -189,7 +189,7 @@ func (p *Provider) findDomains(ctx context.Context, cfg dynamic.Configuration) [ parsedDomains, err := tcp.ParseHostSNI(router.Rule) if err != nil { - logger.Errorf("Unable to parse TCP router domains: %v", err) + logger.Error().Err(err).Msg("Unable to parse TCP router domains") continue } @@ -241,16 +241,16 @@ func (p *Provider) purgeUnusedCerts(domains []string) bool { // fetchCerts fetches the certificates for the provided domains from the // Tailscale daemon. func (p *Provider) fetchCerts(ctx context.Context, domains []string) { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) for _, domain := range domains { cert, key, err := tscert.CertPair(ctx, domain) if err != nil { - logger.WithError(err).Errorf("Unable to fetch certificate for domain %q", domain) + logger.Error().Err(err).Msgf("Unable to fetch certificate for domain %q", domain) continue } - logger.Debugf("Fetched certificate for domain %q", domain) + logger.Debug().Msgf("Fetched certificate for domain %q", domain) p.certByDomainMu.Lock() p.certByDomain[domain] = traefiktls.Certificate{ @@ -300,7 +300,7 @@ func (p *Provider) sendDynamicConfig() { // sanitizeDomains removes duplicated and invalid Tailscale subdomains, from // the provided list. func sanitizeDomains(ctx context.Context, domains []string) []string { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) seen := map[string]struct{}{} @@ -311,7 +311,7 @@ func sanitizeDomains(ctx context.Context, domains []string) []string { } if !isTailscaleDomain(domain) { - logger.Errorf("Domain %s is not a valid Tailscale domain", domain) + logger.Error().Msgf("Domain %s is not a valid Tailscale domain", domain) continue } diff --git a/pkg/provider/traefik/internal.go b/pkg/provider/traefik/internal.go index 2ced41e85..175ce07b9 100644 --- a/pkg/provider/traefik/internal.go +++ b/pkg/provider/traefik/internal.go @@ -8,9 +8,10 @@ import ( "regexp" "time" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/tls" @@ -37,7 +38,7 @@ func (i Provider) ThrottleDuration() time.Duration { // Provide allows the provider to provide configurations to traefik using the given configuration channel. func (i *Provider) Provide(configurationChan chan<- dynamic.Message, _ *safe.Pool) error { - ctx := log.With(context.Background(), log.Str(log.ProviderName, "internal")) + ctx := log.With().Str(logs.ProviderName, "internal").Logger().WithContext(context.Background()) configurationChan <- dynamic.Message{ ProviderName: "internal", @@ -118,17 +119,17 @@ func (i *Provider) redirection(ctx context.Context, cfg *dynamic.Configuration) continue } - logger := log.FromContext(log.With(ctx, log.Str(log.EntryPointName, name))) + logger := log.Ctx(ctx).With().Str(logs.EntryPointName, name).Logger() def := ep.HTTP.Redirections if def.EntryPoint == nil || def.EntryPoint.To == "" { - logger.Error("Unable to create redirection: the entry point or the port is missing") + logger.Error().Msg("Unable to create redirection: the entry point or the port is missing") continue } port, err := i.getRedirectPort(name, def) if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() continue } diff --git a/pkg/redactor/redactor_config_test.go b/pkg/redactor/redactor_config_test.go index 3ae6c0303..33f215232 100644 --- a/pkg/redactor/redactor_config_test.go +++ b/pkg/redactor/redactor_config_test.go @@ -845,9 +845,13 @@ func TestDo_staticConfiguration(t *testing.T) { } config.Log = &types.TraefikLog{ - Level: "Level", - FilePath: "/foo/path", - Format: "json", + Level: "Level", + Format: "json", + FilePath: "/foo/path", + MaxSize: 5, + MaxAge: 3, + MaxBackups: 4, + Compress: true, } config.AccessLog = &types.AccessLog{ diff --git a/pkg/redactor/testdata/anonymized-static-config.json b/pkg/redactor/testdata/anonymized-static-config.json index 79ca15a67..8810d16c8 100644 --- a/pkg/redactor/testdata/anonymized-static-config.json +++ b/pkg/redactor/testdata/anonymized-static-config.json @@ -336,8 +336,12 @@ }, "log": { "level": "Level", + "format": "json", "filePath": "xxxx", - "format": "json" + "maxSize": 5, + "maxAge": 3, + "maxBackups": 4, + "compress": true }, "accessLog": { "filePath": "xxxx", @@ -466,4 +470,4 @@ } } } -} +} \ No newline at end of file diff --git a/pkg/safe/routine.go b/pkg/safe/routine.go index 71af2530d..ab6913c87 100644 --- a/pkg/safe/routine.go +++ b/pkg/safe/routine.go @@ -7,7 +7,7 @@ import ( "sync" "github.com/cenkalti/backoff/v4" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) type routineCtx func(ctx context.Context) @@ -61,9 +61,8 @@ func GoWithRecover(goroutine func(), customRecover func(err interface{})) { } func defaultRecoverGoroutine(err interface{}) { - logger := log.WithoutContext() - logger.Errorf("Error in Go routine: %s", err) - logger.Errorf("Stack: %s", debug.Stack()) + log.Error().Interface("error", err).Msg("Error in Go routine") + log.Error().Msgf("Stack: %s", debug.Stack()) } // OperationWithRecover wrap a backoff operation in a Recover. diff --git a/pkg/server/aggregator.go b/pkg/server/aggregator.go index 4b50829e8..ecf332b1f 100644 --- a/pkg/server/aggregator.go +++ b/pkg/server/aggregator.go @@ -2,8 +2,9 @@ package server import ( "github.com/go-acme/lego/v4/challenge/tlsalpn01" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/server/provider" "github.com/traefik/traefik/v2/pkg/tls" ) @@ -40,9 +41,10 @@ func mergeConfiguration(configurations dynamic.Configurations, defaultEntryPoint if configuration.HTTP != nil { for routerName, router := range configuration.HTTP.Routers { if len(router.EntryPoints) == 0 { - log.WithoutContext(). - WithField(log.RouterName, routerName). - Debugf("No entryPoint defined for this router, using the default one(s) instead: %+v", defaultEntryPoints) + log.Debug(). + Str(logs.RouterName, routerName). + Strs(logs.EntryPointName, defaultEntryPoints). + Msg("No entryPoint defined for this router, using the default one(s) instead") router.EntryPoints = defaultEntryPoints } @@ -65,9 +67,9 @@ func mergeConfiguration(configurations dynamic.Configurations, defaultEntryPoint if configuration.TCP != nil { for routerName, router := range configuration.TCP.Routers { if len(router.EntryPoints) == 0 { - log.WithoutContext(). - WithField(log.RouterName, routerName). - Debugf("No entryPoint defined for this TCP router, using the default one(s) instead: %+v", defaultEntryPoints) + log.Debug(). + Str(logs.RouterName, routerName). + Msgf("No entryPoint defined for this TCP router, using the default one(s) instead: %+v", defaultEntryPoints) router.EntryPoints = defaultEntryPoints } conf.TCP.Routers[provider.MakeQualifiedName(pvd, routerName)] = router @@ -120,14 +122,14 @@ func mergeConfiguration(configurations dynamic.Configurations, defaultEntryPoint } if len(defaultTLSStoreProviders) > 1 { - log.WithoutContext().Errorf("Default TLS Stores defined multiple times in %v", defaultTLSOptionProviders) + log.Error().Msgf("Default TLS Stores defined multiple times in %v", defaultTLSOptionProviders) delete(conf.TLS.Stores, tls.DefaultTLSStoreName) } if len(defaultTLSOptionProviders) == 0 { conf.TLS.Options[tls.DefaultTLSConfigName] = tls.DefaultTLSOptions } else if len(defaultTLSOptionProviders) > 1 { - log.WithoutContext().Errorf("Default TLS Options defined multiple times in %v", defaultTLSOptionProviders) + log.Error().Msgf("Default TLS Options defined multiple times in %v", defaultTLSOptionProviders) // We do not set an empty tls.TLS{} as above so that we actually get a "cascading failure" later on, // i.e. routers depending on this missing TLS option will fail to initialize as well. delete(conf.TLS.Options, tls.DefaultTLSConfigName) diff --git a/pkg/server/configurationwatcher.go b/pkg/server/configurationwatcher.go index 4d6798694..64446ef95 100644 --- a/pkg/server/configurationwatcher.go +++ b/pkg/server/configurationwatcher.go @@ -5,9 +5,10 @@ import ( "encoding/json" "reflect" - "github.com/sirupsen/logrus" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/tls" @@ -68,14 +69,12 @@ func (c *ConfigurationWatcher) AddListener(listener func(dynamic.Configuration)) } func (c *ConfigurationWatcher) startProviderAggregator() { - logger := log.WithoutContext() - - logger.Infof("Starting provider aggregator %T", c.providerAggregator) + log.Info().Msgf("Starting provider aggregator %T", c.providerAggregator) safe.Go(func() { err := c.providerAggregator.Provide(c.allProvidersConfigs, c.routinesPool) if err != nil { - logger.Errorf("Error starting provider aggregator %T: %s", c.providerAggregator, err) + log.Error().Err(err).Msgf("Error starting provider aggregator %T", c.providerAggregator) } }) } @@ -108,15 +107,15 @@ func (c *ConfigurationWatcher) receiveConfigurations(ctx context.Context) { return } - logger := log.WithoutContext().WithField(log.ProviderName, configMsg.ProviderName) + logger := log.Ctx(ctx).With().Str(logs.ProviderName, configMsg.ProviderName).Logger() if configMsg.Configuration == nil { - logger.Debug("Skipping nil configuration.") + logger.Debug().Msg("Skipping nil configuration") continue } if isEmptyConfiguration(configMsg.Configuration) { - logger.Debug("Skipping empty configuration.") + logger.Debug().Msg("Skipping empty configuration") continue } @@ -124,7 +123,7 @@ func (c *ConfigurationWatcher) receiveConfigurations(ctx context.Context) { if reflect.DeepEqual(newConfigurations[configMsg.ProviderName], configMsg.Configuration) { // no change, do nothing - logger.Debug("Skipping unchanged configuration.") + logger.Debug().Msg("Skipping unchanged configuration") continue } @@ -177,8 +176,8 @@ func (c *ConfigurationWatcher) applyConfigurations(ctx context.Context) { } } -func logConfiguration(logger log.Logger, configMsg dynamic.Message) { - if log.GetLevel() != logrus.DebugLevel { +func logConfiguration(logger zerolog.Logger, configMsg dynamic.Message) { + if logger.GetLevel() > zerolog.DebugLevel { return } @@ -212,10 +211,10 @@ func logConfiguration(logger log.Logger, configMsg dynamic.Message) { jsonConf, err := json.Marshal(copyConf) if err != nil { - logger.Errorf("Could not marshal dynamic configuration: %v", err) - logger.Debugf("Configuration received: [struct] %#v", copyConf) + logger.Error().Err(err).Msg("Could not marshal dynamic configuration") + logger.Debug().Msgf("Configuration received: [struct] %#v", copyConf) } else { - logger.Debugf("Configuration received: %s", string(jsonConf)) + logger.Debug().RawJSON("config", jsonConf).Msg("Configuration received") } } diff --git a/pkg/server/cookie/cookie.go b/pkg/server/cookie/cookie.go index 718e0ce15..44f6b59f7 100644 --- a/pkg/server/cookie/cookie.go +++ b/pkg/server/cookie/cookie.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) const cookieNameLength = 6 @@ -27,7 +27,7 @@ func GenerateName(backendName string) string { _, err := hash.Write(data) if err != nil { // Impossible case - log.WithoutContext().Errorf("Fail to create cookie name: %v", err) + log.Error().Err(err).Msg("Fail to create cookie name") } return fmt.Sprintf("_%x", hash.Sum(nil))[:cookieNameLength] diff --git a/pkg/server/middleware/chainbuilder.go b/pkg/server/middleware/chainbuilder.go index c5c833606..57d8385c5 100644 --- a/pkg/server/middleware/chainbuilder.go +++ b/pkg/server/middleware/chainbuilder.go @@ -4,7 +4,7 @@ import ( "context" "github.com/containous/alice" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/metrics" "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" "github.com/traefik/traefik/v2/pkg/middlewares/capture" @@ -56,7 +56,7 @@ func (c *ChainBuilder) Build(ctx context.Context, entryPointName string) alice.C func (c *ChainBuilder) Close() { if c.accessLoggerMiddleware != nil { if err := c.accessLoggerMiddleware.Close(); err != nil { - log.WithoutContext().Errorf("Could not close the access log file: %s", err) + log.Error().Err(err).Msg("Could not close the access log file") } } diff --git a/pkg/server/provider/provider.go b/pkg/server/provider/provider.go index be46c1201..b3ef5092f 100644 --- a/pkg/server/provider/provider.go +++ b/pkg/server/provider/provider.go @@ -4,7 +4,7 @@ import ( "context" "strings" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) type contextKey int @@ -17,7 +17,7 @@ const ( func AddInContext(ctx context.Context, elementName string) context.Context { parts := strings.Split(elementName, "@") if len(parts) == 1 { - log.FromContext(ctx).Debugf("Could not find a provider for %s.", elementName) + log.Ctx(ctx).Debug().Msgf("Could not find a provider for %s", elementName) return ctx } diff --git a/pkg/server/router/router.go b/pkg/server/router/router.go index e4acdef94..e3b34d7e5 100644 --- a/pkg/server/router/router.go +++ b/pkg/server/router/router.go @@ -6,8 +6,9 @@ import ( "net/http" "github.com/containous/alice" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/metrics" "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" metricsMiddle "github.com/traefik/traefik/v2/pkg/middlewares/metrics" @@ -63,19 +64,21 @@ func (m *Manager) BuildHandlers(rootCtx context.Context, entryPoints []string, t for entryPointName, routers := range m.getHTTPRouters(rootCtx, entryPoints, tls) { entryPointName := entryPointName - ctx := log.With(rootCtx, log.Str(log.EntryPointName, entryPointName)) + + logger := log.Ctx(rootCtx).With().Str(logs.EntryPointName, entryPointName).Logger() + ctx := logger.WithContext(rootCtx) handler, err := m.buildEntryPointHandler(ctx, routers) if err != nil { - log.FromContext(ctx).Error(err) + logger.Error().Err(err).Send() continue } handlerWithAccessLog, err := alice.New(func(next http.Handler) (http.Handler, error) { - return accesslog.NewFieldHandler(next, log.EntryPointName, entryPointName, accesslog.AddOriginFields), nil + return accesslog.NewFieldHandler(next, logs.EntryPointName, entryPointName, accesslog.AddOriginFields), nil }).Then(handler) if err != nil { - log.FromContext(ctx).Error(err) + logger.Error().Err(err).Send() entryPointHandlers[entryPointName] = handler } else { entryPointHandlers[entryPointName] = handlerWithAccessLog @@ -83,7 +86,8 @@ func (m *Manager) BuildHandlers(rootCtx context.Context, entryPoints []string, t } for _, entryPointName := range entryPoints { - ctx := log.With(rootCtx, log.Str(log.EntryPointName, entryPointName)) + logger := log.Ctx(rootCtx).With().Str(logs.EntryPointName, entryPointName).Logger() + ctx := logger.WithContext(rootCtx) handler, ok := entryPointHandlers[entryPointName] if !ok || handler == nil { @@ -92,7 +96,7 @@ func (m *Manager) BuildHandlers(rootCtx context.Context, entryPoints []string, t handlerWithMiddlewares, err := m.chainBuilder.Build(ctx, entryPointName).Then(handler) if err != nil { - log.FromContext(ctx).Error(err) + logger.Error().Err(err).Send() continue } entryPointHandlers[entryPointName] = handlerWithMiddlewares @@ -108,20 +112,20 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string } for routerName, routerConfig := range configs { - ctxRouter := log.With(provider.AddInContext(ctx, routerName), log.Str(log.RouterName, routerName)) - logger := log.FromContext(ctxRouter) + logger := log.Ctx(ctx).With().Str(logs.RouterName, routerName).Logger() + ctxRouter := logger.WithContext(provider.AddInContext(ctx, routerName)) handler, err := m.buildRouterHandler(ctxRouter, routerName, routerConfig) if err != nil { routerConfig.AddError(err, true) - logger.Error(err) + logger.Error().Err(err).Send() continue } err = muxer.AddRoute(routerConfig.Rule, routerConfig.Priority, handler) if err != nil { routerConfig.AddError(err, true) - logger.Error(err) + logger.Error().Err(err).Send() continue } } @@ -150,7 +154,7 @@ func (m *Manager) buildRouterHandler(ctx context.Context, routerName string, rou return accesslog.NewFieldHandler(next, accesslog.RouterName, routerName, nil), nil }).Then(handler) if err != nil { - log.FromContext(ctx).Error(err) + log.Ctx(ctx).Error().Err(err).Send() m.routerHandlers[routerName] = handler } else { m.routerHandlers[routerName] = handlerWithAccessLog diff --git a/pkg/server/router/tcp/manager.go b/pkg/server/router/tcp/manager.go index ff92f3112..2b4f1d504 100644 --- a/pkg/server/router/tcp/manager.go +++ b/pkg/server/router/tcp/manager.go @@ -7,8 +7,9 @@ import ( "fmt" "net/http" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/middlewares/snicheck" httpmuxer "github.com/traefik/traefik/v2/pkg/muxer/http" tcpmuxer "github.com/traefik/traefik/v2/pkg/muxer/tcp" @@ -77,11 +78,12 @@ func (m *Manager) BuildHandlers(rootCtx context.Context, entryPoints []string) m routers := entryPointsRouters[entryPointName] - ctx := log.With(rootCtx, log.Str(log.EntryPointName, entryPointName)) + logger := log.Ctx(rootCtx).With().Str(logs.EntryPointName, entryPointName).Logger() + ctx := logger.WithContext(rootCtx) handler, err := m.buildEntryPointHandler(ctx, routers, entryPointsRoutersHTTP[entryPointName], m.httpHandlers[entryPointName], m.httpsHandlers[entryPointName]) if err != nil { - log.FromContext(ctx).Error(err) + logger.Error().Err(err).Send() continue } entryPointHandlers[entryPointName] = handler @@ -105,7 +107,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string defaultTLSConf, err := m.tlsManager.Get(traefiktls.DefaultTLSStoreName, traefiktls.DefaultTLSConfigName) if err != nil { - log.FromContext(ctx).Errorf("Error during the build of the default TLS configuration: %v", err) + log.Ctx(ctx).Error().Err(err).Msg("Error during the build of the default TLS configuration") } // Keyed by domain. The source of truth for doing SNI checking, and for what TLS @@ -125,8 +127,8 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string continue } - ctxRouter := log.With(provider.AddInContext(ctx, routerHTTPName), log.Str(log.RouterName, routerHTTPName)) - logger := log.FromContext(ctxRouter) + logger := log.Ctx(ctx).With().Str(logs.RouterName, routerHTTPName).Logger() + ctxRouter := logger.WithContext(provider.AddInContext(ctx, routerHTTPName)) tlsOptionsName := traefiktls.DefaultTLSConfigName if len(routerHTTPConfig.TLS.Options) > 0 && routerHTTPConfig.TLS.Options != traefiktls.DefaultTLSConfigName { @@ -137,7 +139,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string if err != nil { routerErr := fmt.Errorf("invalid rule %s, error: %w", routerHTTPConfig.Rule, err) routerHTTPConfig.AddError(routerErr, true) - logger.Error(routerErr) + logger.Error().Err(routerErr).Send() continue } @@ -173,13 +175,13 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string // # When a request for "/foo" comes, even though it won't be routed by // httpRouter2, if its SNI is set to foo.com, myTLSOptions will be used for the TLS // connection. Otherwise, it will fallback to the default TLS config. - logger.Warnf("No domain found in rule %v, the TLS options applied for this router will depend on the SNI of each request", routerHTTPConfig.Rule) + logger.Warn().Msgf("No domain found in rule %v, the TLS options applied for this router will depend on the SNI of each request", routerHTTPConfig.Rule) } tlsConf, err := m.tlsManager.Get(traefiktls.DefaultTLSStoreName, tlsOptionsName) if err != nil { routerHTTPConfig.AddError(err, true) - logger.Error(err) + logger.Error().Err(err).Send() continue } @@ -206,7 +208,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string router.SetHTTPSHandler(sniCheck, defaultTLSConf) - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) for hostSNI, tlsConfigs := range tlsOptionsForHostSNI { if len(tlsConfigs) == 1 { var optionsName string @@ -217,7 +219,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string break } - logger.Debugf("Adding route for %s with TLS options %s", hostSNI, optionsName) + logger.Debug().Msgf("Adding route for %s with TLS options %s", hostSNI, optionsName) router.AddHTTPTLSConfig(hostSNI, config) } else { @@ -227,34 +229,34 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string routers = append(routers, v.routerName) } - logger.Warnf("Found different TLS options for routers on the same host %v, so using the default TLS options instead for these routers: %#v", hostSNI, routers) + logger.Warn().Msgf("Found different TLS options for routers on the same host %v, so using the default TLS options instead for these routers: %#v", hostSNI, routers) router.AddHTTPTLSConfig(hostSNI, defaultTLSConf) } } for routerName, routerConfig := range configs { - ctxRouter := log.With(provider.AddInContext(ctx, routerName), log.Str(log.RouterName, routerName)) - logger := log.FromContext(ctxRouter) + logger := log.Ctx(ctx).With().Str(logs.RouterName, routerName).Logger() + ctxRouter := logger.WithContext(provider.AddInContext(ctx, routerName)) if routerConfig.Service == "" { err := errors.New("the service is missing on the router") routerConfig.AddError(err, true) - logger.Error(err) + logger.Error().Err(err).Send() continue } if routerConfig.Rule == "" { err := errors.New("router has no rule") routerConfig.AddError(err, true) - logger.Error(err) + logger.Error().Err(err).Send() continue } handler, err := m.buildTCPHandler(ctxRouter, routerConfig) if err != nil { routerConfig.AddError(err, true) - logger.Error(err) + logger.Error().Err(err).Send() continue } @@ -262,7 +264,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string if err != nil { routerErr := fmt.Errorf("invalid rule: %q , %w", routerConfig.Rule, err) routerConfig.AddError(routerErr, true) - logger.Error(routerErr) + logger.Error().Err(routerErr).Send() continue } @@ -271,23 +273,23 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string if len(domains) > 0 && routerConfig.TLS == nil && domains[0] != "*" { routerErr := fmt.Errorf("invalid rule: %q , has HostSNI matcher, but no TLS on router", routerConfig.Rule) routerConfig.AddError(routerErr, true) - logger.Error(routerErr) + logger.Error().Err(routerErr).Send() } if routerConfig.TLS == nil { - logger.Debugf("Adding route for %q", routerConfig.Rule) + logger.Debug().Msgf("Adding route for %q", routerConfig.Rule) if err := router.AddRoute(routerConfig.Rule, routerConfig.Priority, handler); err != nil { routerConfig.AddError(err, true) - logger.Error(err) + logger.Error().Err(err).Send() } continue } if routerConfig.TLS.Passthrough { - logger.Debugf("Adding Passthrough route for %q", routerConfig.Rule) + logger.Debug().Msgf("Adding Passthrough route for %q", routerConfig.Rule) if err := router.AddRouteTLS(routerConfig.Rule, routerConfig.Priority, handler, nil); err != nil { routerConfig.AddError(err, true) - logger.Error(err) + logger.Error().Err(err).Send() } continue } @@ -299,7 +301,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string asciiError := fmt.Errorf("invalid domain name value %q, non-ASCII characters are not allowed", domain) routerConfig.AddError(asciiError, true) - logger.Error(asciiError) + logger.Error().Err(asciiError).Send() } tlsOptionsName := routerConfig.TLS.Options @@ -315,7 +317,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string tlsConf, err := m.tlsManager.Get(traefiktls.DefaultTLSStoreName, tlsOptionsName) if err != nil { routerConfig.AddError(err, true) - logger.Error(err) + logger.Error().Err(err).Send() continue } @@ -333,10 +335,10 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string // it's all good. Otherwise, we would have to do as for HTTPS, i.e. disallow // different TLS configs for the same HostSNIs. - logger.Debugf("Adding TLS route for %q", routerConfig.Rule) + logger.Debug().Msgf("Adding TLS route for %q", routerConfig.Rule) if err := router.AddRouteTLS(routerConfig.Rule, routerConfig.Priority, handler, tlsConf); err != nil { routerConfig.AddError(err, true) - logger.Error(err) + logger.Error().Err(err).Send() } } diff --git a/pkg/server/router/tcp/postgres.go b/pkg/server/router/tcp/postgres.go index 857efb3ab..b79c3762f 100644 --- a/pkg/server/router/tcp/postgres.go +++ b/pkg/server/router/tcp/postgres.go @@ -6,7 +6,7 @@ import ( "errors" "sync" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" tcpmuxer "github.com/traefik/traefik/v2/pkg/muxer/tcp" "github.com/traefik/traefik/v2/pkg/tcp" ) @@ -25,7 +25,7 @@ func isPostgres(br *bufio.Reader) (bool, error) { for i := 1; i < len(PostgresStartTLSMsg)+1; i++ { peeked, err := br.Peek(i) if err != nil { - log.WithoutContext().Errorf("Error while Peeking first bytes: %s", err) + log.Error().Err(err).Msg("Error while Peeking first bytes") return false, err } @@ -67,7 +67,7 @@ func (r *Router) servePostgres(conn tcp.WriteCloser) { connData, err := tcpmuxer.NewConnData(hello.serverName, conn, hello.protos) if err != nil { - log.WithoutContext().Errorf("Error while reading TCP connection data: %v", err) + log.Error().Err(err).Msg("Error while reading TCP connection data") conn.Close() return } diff --git a/pkg/server/router/tcp/router.go b/pkg/server/router/tcp/router.go index 841d52ae8..895124523 100644 --- a/pkg/server/router/tcp/router.go +++ b/pkg/server/router/tcp/router.go @@ -10,7 +10,7 @@ import ( "net/http" "time" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" tcpmuxer "github.com/traefik/traefik/v2/pkg/muxer/tcp" "github.com/traefik/traefik/v2/pkg/tcp" ) @@ -88,7 +88,7 @@ func (r *Router) ServeTCP(conn tcp.WriteCloser) { if r.muxerTCP.HasRoutes() && !r.muxerTCPTLS.HasRoutes() && !r.muxerHTTPS.HasRoutes() { connData, err := tcpmuxer.NewConnData("", conn, nil) if err != nil { - log.WithoutContext().Errorf("Error while reading TCP connection data: %v", err) + log.Error().Err(err).Msg("Error while reading TCP connection data") conn.Close() return } @@ -128,17 +128,17 @@ func (r *Router) ServeTCP(conn tcp.WriteCloser) { // Remove read/write deadline and delegate this to underlying tcp server (for now only handled by HTTP Server) err = conn.SetReadDeadline(time.Time{}) if err != nil { - log.WithoutContext().Errorf("Error while setting read deadline: %v", err) + log.Error().Err(err).Msg("Error while setting read deadline") } err = conn.SetWriteDeadline(time.Time{}) if err != nil { - log.WithoutContext().Errorf("Error while setting write deadline: %v", err) + log.Error().Err(err).Msg("Error while setting write deadline") } connData, err := tcpmuxer.NewConnData(hello.serverName, conn, hello.protos) if err != nil { - log.WithoutContext().Errorf("Error while reading TCP connection data: %v", err) + log.Error().Err(err).Msg("Error while reading TCP connection data") conn.Close() return } @@ -263,7 +263,7 @@ func (r *Router) SetHTTPSForwarder(handler tcp.Handler) { Config: tlsConf, }) if err != nil { - log.WithoutContext().Errorf("Error while adding route for host: %v", err) + log.Error().Err(err).Msg("Error while adding route for host") } } @@ -326,7 +326,7 @@ func clientHelloInfo(br *bufio.Reader) (*clientHello, error) { if err != nil { var opErr *net.OpError if !errors.Is(err, io.EOF) && (!errors.As(err, &opErr) || opErr.Timeout()) { - log.WithoutContext().Errorf("Error while Peeking first byte: %s", err) + log.Error().Err(err).Msg("Error while Peeking first byte") } return nil, err } @@ -353,7 +353,7 @@ func clientHelloInfo(br *bufio.Reader) (*clientHello, error) { const recordHeaderLen = 5 hdr, err = br.Peek(recordHeaderLen) if err != nil { - log.Errorf("Error while Peeking hello: %s", err) + log.Error().Err(err).Msg("Error while Peeking hello") return &clientHello{ peeked: getPeeked(br), }, nil @@ -367,7 +367,7 @@ func clientHelloInfo(br *bufio.Reader) (*clientHello, error) { helloBytes, err := br.Peek(recordHeaderLen + recLen) if err != nil { - log.Errorf("Error while Hello: %s", err) + log.Error().Err(err).Msg("Error while Hello") return &clientHello{ isTLS: true, peeked: getPeeked(br), @@ -396,7 +396,7 @@ func clientHelloInfo(br *bufio.Reader) (*clientHello, error) { func getPeeked(br *bufio.Reader) string { peeked, err := br.Peek(br.Buffered()) if err != nil { - log.Errorf("Could not get anything: %s", err) + log.Error().Err(err).Msg("Could not get anything") return "" } return string(peeked) diff --git a/pkg/server/router/udp/router.go b/pkg/server/router/udp/router.go index 75bea883a..0a5303eff 100644 --- a/pkg/server/router/udp/router.go +++ b/pkg/server/router/udp/router.go @@ -5,8 +5,9 @@ import ( "errors" "sort" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/server/provider" udpservice "github.com/traefik/traefik/v2/pkg/server/service/udp" "github.com/traefik/traefik/v2/pkg/udp" @@ -46,10 +47,11 @@ func (m *Manager) BuildHandlers(rootCtx context.Context, entryPoints []string) m routers := entryPointsRouters[entryPointName] - ctx := log.With(rootCtx, log.Str(log.EntryPointName, entryPointName)) + logger := log.Ctx(rootCtx).With().Str(logs.EntryPointName, entryPointName).Logger() + ctx := logger.WithContext(rootCtx) if len(routers) > 1 { - log.FromContext(ctx).Warn("Config has more than one udp router for a given entrypoint.") + logger.Warn().Msg("Config has more than one udp router for a given entrypoint.") } handlers := m.buildEntryPointHandlers(ctx, routers) @@ -76,21 +78,20 @@ func (m *Manager) buildEntryPointHandlers(ctx context.Context, configs map[strin for _, routerName := range rtNames { routerConfig := configs[routerName] - - ctxRouter := log.With(provider.AddInContext(ctx, routerName), log.Str(log.RouterName, routerName)) - logger := log.FromContext(ctxRouter) + logger := log.Ctx(ctx).With().Str(logs.RouterName, routerName).Logger() + ctxRouter := logger.WithContext(provider.AddInContext(ctx, routerName)) if routerConfig.Service == "" { err := errors.New("the service is missing on the udp router") routerConfig.AddError(err, true) - logger.Error(err) + logger.Error().Err(err).Send() continue } handler, err := m.serviceManager.BuildUDP(ctxRouter, routerConfig.Service) if err != nil { routerConfig.AddError(err, true) - logger.Error(err) + logger.Error().Err(err).Send() continue } diff --git a/pkg/server/routerfactory.go b/pkg/server/routerfactory.go index d2f0420f4..d3e0f877b 100644 --- a/pkg/server/routerfactory.go +++ b/pkg/server/routerfactory.go @@ -3,9 +3,9 @@ package server import ( "context" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/runtime" "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/metrics" "github.com/traefik/traefik/v2/pkg/server/middleware" tcpmiddleware "github.com/traefik/traefik/v2/pkg/server/middleware/tcp" @@ -44,7 +44,7 @@ func NewRouterFactory(staticConfiguration static.Configuration, managerFactory * protocol, err := cfg.GetProtocol() if err != nil { // Should never happen because Traefik should not start if protocol is invalid. - log.WithoutContext().Errorf("Invalid protocol: %v", err) + log.Error().Err(err).Msg("Invalid protocol") } if protocol == "udp" { diff --git a/pkg/server/server.go b/pkg/server/server.go index 722258db6..edd0cdb02 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -7,7 +7,7 @@ import ( "os/signal" "time" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/metrics" "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" "github.com/traefik/traefik/v2/pkg/safe" @@ -53,9 +53,9 @@ func NewServer(routinesPool *safe.Pool, entryPoints TCPEntryPoints, entryPointsU func (s *Server) Start(ctx context.Context) { go func() { <-ctx.Done() - logger := log.FromContext(ctx) - logger.Info("I have to go...") - logger.Info("Stopping server gracefully") + logger := log.Ctx(ctx) + logger.Info().Msg("I have to go...") + logger.Info().Msg("Stopping server gracefully") s.Stop() }() @@ -73,7 +73,7 @@ func (s *Server) Wait() { // Stop stops the server. func (s *Server) Stop() { - defer log.WithoutContext().Info("Server stopped") + defer log.Info().Msg("Server stopped") s.tcpEntryPoints.Stop() s.udpEntryPoints.Stop() diff --git a/pkg/server/server_entrypoint_tcp.go b/pkg/server/server_entrypoint_tcp.go index 5d7095768..2fd4380f8 100644 --- a/pkg/server/server_entrypoint_tcp.go +++ b/pkg/server/server_entrypoint_tcp.go @@ -16,10 +16,11 @@ import ( "github.com/containous/alice" "github.com/pires/go-proxyproto" - "github.com/sirupsen/logrus" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/static" "github.com/traefik/traefik/v2/pkg/ip" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/middlewares" "github.com/traefik/traefik/v2/pkg/middlewares/forwardedheaders" "github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator" @@ -32,8 +33,6 @@ import ( "golang.org/x/net/http2/h2c" ) -var httpServerLogger = stdlog.New(log.WithoutContext().WriterLevel(logrus.DebugLevel), "", 0) - type httpForwarder struct { net.Listener connChan chan net.Conn @@ -79,7 +78,7 @@ func NewTCPEntryPoints(entryPointsConfig static.EntryPoints, hostResolverConfig continue } - ctx := log.With(context.Background(), log.Str(log.EntryPointName, entryPointName)) + ctx := log.With().Str(logs.EntryPointName, entryPointName).Logger().WithContext(context.Background()) serverEntryPointsTCP[entryPointName], err = NewTCPEntryPoint(ctx, config, hostResolverConfig) if err != nil { @@ -92,7 +91,7 @@ func NewTCPEntryPoints(entryPointsConfig static.EntryPoints, hostResolverConfig // Start the server entry points. func (eps TCPEntryPoints) Start() { for entryPointName, serverEntryPoint := range eps { - ctx := log.With(context.Background(), log.Str(log.EntryPointName, entryPointName)) + ctx := log.With().Str(logs.EntryPointName, entryPointName).Logger().WithContext(context.Background()) go serverEntryPoint.Start(ctx) } } @@ -107,10 +106,10 @@ func (eps TCPEntryPoints) Stop() { go func(entryPointName string, entryPoint *TCPEntryPoint) { defer wg.Done() - ctx := log.With(context.Background(), log.Str(log.EntryPointName, entryPointName)) - entryPoint.Shutdown(ctx) + logger := log.With().Str(logs.EntryPointName, entryPointName).Logger() + entryPoint.Shutdown(logger.WithContext(context.Background())) - log.FromContext(ctx).Debugf("Entry point %s closed", entryPointName) + logger.Debug().Msg("Entrypoint closed") }(epn, ep) } @@ -184,8 +183,8 @@ func NewTCPEntryPoint(ctx context.Context, configuration *static.EntryPoint, hos // Start starts the TCP server. func (e *TCPEntryPoint) Start(ctx context.Context) { - logger := log.FromContext(ctx) - logger.Debug("Starting TCP Server") + logger := log.Ctx(ctx) + logger.Debug().Msg("Starting TCP Server") if e.http3Server != nil { go func() { _ = e.http3Server.Start() }() @@ -194,7 +193,7 @@ func (e *TCPEntryPoint) Start(ctx context.Context) { for { conn, err := e.listener.Accept() if err != nil { - logger.Error(err) + logger.Error().Err(err).Send() var opErr *net.OpError if errors.As(err, &opErr) && opErr.Temporary() { @@ -224,14 +223,14 @@ func (e *TCPEntryPoint) Start(ctx context.Context) { if e.transportConfiguration.RespondingTimeouts.ReadTimeout > 0 { err := writeCloser.SetReadDeadline(time.Now().Add(time.Duration(e.transportConfiguration.RespondingTimeouts.ReadTimeout))) if err != nil { - logger.Errorf("Error while setting read deadline: %v", err) + logger.Error().Err(err).Msg("Error while setting read deadline") } } if e.transportConfiguration.RespondingTimeouts.WriteTimeout > 0 { err = writeCloser.SetWriteDeadline(time.Now().Add(time.Duration(e.transportConfiguration.RespondingTimeouts.WriteTimeout))) if err != nil { - logger.Errorf("Error while setting write deadline: %v", err) + logger.Error().Err(err).Msg("Error while setting write deadline") } } @@ -242,17 +241,17 @@ func (e *TCPEntryPoint) Start(ctx context.Context) { // Shutdown stops the TCP connections. func (e *TCPEntryPoint) Shutdown(ctx context.Context) { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) reqAcceptGraceTimeOut := time.Duration(e.transportConfiguration.LifeCycle.RequestAcceptGraceTimeout) if reqAcceptGraceTimeOut > 0 { - logger.Infof("Waiting %s for incoming requests to cease", reqAcceptGraceTimeOut) + logger.Info().Msgf("Waiting %s for incoming requests to cease", reqAcceptGraceTimeOut) time.Sleep(reqAcceptGraceTimeOut) } graceTimeOut := time.Duration(e.transportConfiguration.LifeCycle.GraceTimeOut) ctx, cancel := context.WithTimeout(ctx, graceTimeOut) - logger.Debugf("Waiting %s seconds before killing connections.", graceTimeOut) + logger.Debug().Msgf("Waiting %s seconds before killing connections", graceTimeOut) var wg sync.WaitGroup @@ -263,13 +262,15 @@ func (e *TCPEntryPoint) Shutdown(ctx context.Context) { return } if errors.Is(ctx.Err(), context.DeadlineExceeded) { - logger.Debugf("Server failed to shutdown within deadline because: %s", err) + logger.Debug().Err(err).Msg("Server failed to shutdown within deadline") if err = server.Close(); err != nil { - logger.Error(err) + logger.Error().Err(err).Send() } return } - logger.Error(err) + + logger.Error().Err(err).Send() + // We expect Close to fail again because Shutdown most likely failed when trying to close a listener. // We still call it however, to make sure that all connections get closed as well. server.Close() @@ -299,7 +300,7 @@ func (e *TCPEntryPoint) Shutdown(ctx context.Context) { return } if errors.Is(ctx.Err(), context.DeadlineExceeded) { - logger.Debugf("Server failed to shutdown before deadline because: %s", err) + logger.Debug().Err(err).Msg("Server failed to shutdown before deadline") } e.tracker.Close() }() @@ -381,8 +382,7 @@ func (ln tcpKeepAliveListener) Accept() (net.Conn, error) { } if err := tc.SetKeepAlivePeriod(3 * time.Minute); err != nil { - // Some systems, such as OpenBSD, have no user-settable per-socket TCP - // keepalive options. + // Some systems, such as OpenBSD, have no user-settable per-socket TCP keepalive options. if !errors.Is(err, syscall.ENOPROTOOPT) { return nil, err } @@ -395,7 +395,7 @@ func buildProxyProtocolListener(ctx context.Context, entryPoint *static.EntryPoi proxyListener := &proxyproto.Listener{Listener: listener} if entryPoint.ProxyProtocol.Insecure { - log.FromContext(ctx).Infof("Enabling ProxyProtocol without trusted IPs: Insecure") + log.Ctx(ctx).Info().Msg("Enabling ProxyProtocol without trusted IPs: Insecure") return proxyListener, nil } @@ -411,13 +411,13 @@ func buildProxyProtocolListener(ctx context.Context, entryPoint *static.EntryPoi } if !checker.ContainsIP(ipAddr.IP) { - log.FromContext(ctx).Debugf("IP %s is not in trusted IPs list, ignoring ProxyProtocol Headers and bypass connection", ipAddr.IP) + log.Ctx(ctx).Debug().Msgf("IP %s is not in trusted IPs list, ignoring ProxyProtocol Headers and bypass connection", ipAddr.IP) return proxyproto.IGNORE, nil } return proxyproto.USE, nil } - log.FromContext(ctx).Infof("Enabling ProxyProtocol for trusted IPs %v", entryPoint.ProxyProtocol.TrustedIPs) + log.Ctx(ctx).Info().Msgf("Enabling ProxyProtocol for trusted IPs %v", entryPoint.ProxyProtocol.TrustedIPs) return proxyListener, nil } @@ -492,7 +492,7 @@ func (c *connectionTracker) Close() { defer c.lock.Unlock() for conn := range c.conns { if err := conn.Close(); err != nil { - log.WithoutContext().Errorf("Error while closing connection: %v", err) + log.Error().Err(err).Msg("Error while closing connection") } delete(c.conns, conn) } @@ -545,7 +545,7 @@ func createHTTPServer(ctx context.Context, ln net.Listener, configuration *stati serverHTTP := &http.Server{ Handler: handler, - ErrorLog: httpServerLogger, + ErrorLog: stdlog.New(logs.NoLevel(log.Logger, zerolog.DebugLevel), "", 0), ReadTimeout: time.Duration(configuration.Transport.RespondingTimeouts.ReadTimeout), WriteTimeout: time.Duration(configuration.Transport.RespondingTimeouts.WriteTimeout), IdleTimeout: time.Duration(configuration.Transport.RespondingTimeouts.IdleTimeout), @@ -569,7 +569,7 @@ func createHTTPServer(ctx context.Context, ln net.Listener, configuration *stati go func() { err := serverHTTP.Serve(listener) if err != nil && !errors.Is(err, http.ErrServerClosed) { - log.FromContext(ctx).Errorf("Error while starting server: %v", err) + log.Ctx(ctx).Error().Err(err).Msg("Error while starting server") } }() return &httpServer{ diff --git a/pkg/server/server_entrypoint_tcp_http3.go b/pkg/server/server_entrypoint_tcp_http3.go index 0f11b82b9..99755d6d7 100644 --- a/pkg/server/server_entrypoint_tcp_http3.go +++ b/pkg/server/server_entrypoint_tcp_http3.go @@ -10,8 +10,8 @@ import ( "sync" "github.com/lucas-clemente/quic-go/http3" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/log" tcprouter "github.com/traefik/traefik/v2/pkg/server/router/tcp" ) @@ -56,7 +56,7 @@ func newHTTP3Server(ctx context.Context, configuration *static.EntryPoint, https httpsServer.Server.(*http.Server).Handler = http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { if err := h3.Server.SetQuicHeaders(rw.Header()); err != nil { - log.FromContext(ctx).Errorf("Failed to set HTTP3 headers: %v", err) + log.Ctx(ctx).Error().Err(err).Msg("Failed to set HTTP3 headers") } previousHandler.ServeHTTP(rw, req) diff --git a/pkg/server/server_entrypoint_udp.go b/pkg/server/server_entrypoint_udp.go index 163a719af..1aa4c38c3 100644 --- a/pkg/server/server_entrypoint_udp.go +++ b/pkg/server/server_entrypoint_udp.go @@ -7,8 +7,9 @@ import ( "sync" "time" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/static" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/udp" ) @@ -40,7 +41,7 @@ func NewUDPEntryPoints(cfg static.EntryPoints) (UDPEntryPoints, error) { // Start commences the listening for all the entry points. func (eps UDPEntryPoints) Start() { for entryPointName, ep := range eps { - ctx := log.With(context.Background(), log.Str(log.EntryPointName, entryPointName)) + ctx := log.With().Str(logs.EntryPointName, entryPointName).Logger().WithContext(context.Background()) go ep.Start(ctx) } } @@ -55,10 +56,10 @@ func (eps UDPEntryPoints) Stop() { go func(entryPointName string, entryPoint *UDPEntryPoint) { defer wg.Done() - ctx := log.With(context.Background(), log.Str(log.EntryPointName, entryPointName)) - entryPoint.Shutdown(ctx) + logger := log.With().Str(logs.EntryPointName, entryPointName).Logger() + entryPoint.Shutdown(logger.WithContext(context.Background())) - log.FromContext(ctx).Debugf("Entry point %s closed", entryPointName) + logger.Debug().Msg("Entry point closed") }(epn, ep) } @@ -72,7 +73,8 @@ func (eps UDPEntryPoints) Switch(handlers map[string]udp.Handler) { ep.Switch(handler) continue } - log.WithoutContext().Errorf("EntryPoint %q does not exist", epName) + + log.Error().Str(logs.EntryPointName, epName).Msg("EntryPoint does not exist") } } @@ -100,7 +102,7 @@ func NewUDPEntryPoint(cfg *static.EntryPoint) (*UDPEntryPoint, error) { // Start commences the listening for ep. func (ep *UDPEntryPoint) Start(ctx context.Context) { - log.FromContext(ctx).Debug("Start UDP Server") + log.Ctx(ctx).Debug().Msg("Start UDP Server") for { conn, err := ep.listener.Accept() if err != nil { @@ -116,17 +118,17 @@ func (ep *UDPEntryPoint) Start(ctx context.Context) { // releases associated resources, but only after it has waited for a graceTimeout, // if any was configured. func (ep *UDPEntryPoint) Shutdown(ctx context.Context) { - logger := log.FromContext(ctx) + logger := log.Ctx(ctx) reqAcceptGraceTimeOut := time.Duration(ep.transportConfiguration.LifeCycle.RequestAcceptGraceTimeout) if reqAcceptGraceTimeOut > 0 { - logger.Infof("Waiting %s for incoming requests to cease", reqAcceptGraceTimeOut) + logger.Info().Msgf("Waiting %s for incoming requests to cease", reqAcceptGraceTimeOut) time.Sleep(reqAcceptGraceTimeOut) } graceTimeOut := time.Duration(ep.transportConfiguration.LifeCycle.GraceTimeOut) if err := ep.listener.Shutdown(graceTimeOut); err != nil { - logger.Error(err) + logger.Error().Err(err).Send() } } diff --git a/pkg/server/server_signals.go b/pkg/server/server_signals.go index d1ad8d51a..0987abb30 100644 --- a/pkg/server/server_signals.go +++ b/pkg/server/server_signals.go @@ -8,7 +8,7 @@ import ( "os/signal" "syscall" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) func (s *Server) configureSignals() { @@ -22,17 +22,13 @@ func (s *Server) listenSignals(ctx context.Context) { return case sig := <-s.signals: if sig == syscall.SIGUSR1 { - log.WithoutContext().Infof("Closing and re-opening log files for rotation: %+v", sig) + log.Info().Msgf("Closing and re-opening log files for rotation: %+v", sig) if s.accessLoggerMiddleware != nil { if err := s.accessLoggerMiddleware.Rotate(); err != nil { - log.WithoutContext().Errorf("Error rotating access log: %v", err) + log.Error().Err(err).Msg("Error rotating access log") } } - - if err := log.RotateFile(); err != nil { - log.WithoutContext().Errorf("Error rotating traefik log: %v", err) - } } } } diff --git a/pkg/server/service/loadbalancer/failover/failover.go b/pkg/server/service/loadbalancer/failover/failover.go index 06d9fecd7..972d38672 100644 --- a/pkg/server/service/loadbalancer/failover/failover.go +++ b/pkg/server/service/loadbalancer/failover/failover.go @@ -6,8 +6,8 @@ import ( "net/http" "sync" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" ) // Failover is an http.Handler that can forward requests to the fallback handler @@ -90,11 +90,11 @@ func (f *Failover) SetHandlerStatus(ctx context.Context, up bool) { if up == f.handlerStatus { // We're still with the same status, no need to propagate. - log.FromContext(ctx).Debugf("Still %s, no need to propagate", status) + log.Ctx(ctx).Debug().Msgf("Still %s, no need to propagate", status) return } - log.FromContext(ctx).Debugf("Propagating new %s status", status) + log.Ctx(ctx).Debug().Msgf("Propagating new %s status", status) f.handlerStatus = up for _, fn := range f.updaters { @@ -125,11 +125,11 @@ func (f *Failover) SetFallbackHandlerStatus(ctx context.Context, up bool) { if up == f.fallbackStatus { // We're still with the same status, no need to propagate. - log.FromContext(ctx).Debugf("Still %s, no need to propagate", status) + log.Ctx(ctx).Debug().Msgf("Still %s, no need to propagate", status) return } - log.FromContext(ctx).Debugf("Propagating new %s status", status) + log.Ctx(ctx).Debug().Msgf("Propagating new %s status", status) f.fallbackStatus = up for _, fn := range f.updaters { diff --git a/pkg/server/service/loadbalancer/mirror/mirror.go b/pkg/server/service/loadbalancer/mirror/mirror.go index f0d12a952..cb77b7280 100644 --- a/pkg/server/service/loadbalancer/mirror/mirror.go +++ b/pkg/server/service/loadbalancer/mirror/mirror.go @@ -11,9 +11,9 @@ import ( "net/http" "sync" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/healthcheck" - "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" "github.com/traefik/traefik/v2/pkg/safe" ) @@ -82,18 +82,18 @@ func (m *Mirroring) ServeHTTP(rw http.ResponseWriter, req *http.Request) { return } - logger := log.FromContext(req.Context()) + logger := log.Ctx(req.Context()) rr, bytesRead, err := newReusableRequest(req, m.maxBodySize) if err != nil && !errors.Is(err, errBodyTooLarge) { - http.Error(rw, http.StatusText(http.StatusInternalServerError)+ - fmt.Sprintf("error creating reusable request: %v", err), http.StatusInternalServerError) + http.Error(rw, fmt.Sprintf("%s: creating reusable request: %v", + http.StatusText(http.StatusInternalServerError), err), http.StatusInternalServerError) return } if errors.Is(err, errBodyTooLarge) { req.Body = io.NopCloser(io.MultiReader(bytes.NewReader(bytesRead), req.Body)) m.handler.ServeHTTP(rw, req) - logger.Debug("no mirroring, request body larger than allowed size") + logger.Debug().Msg("No mirroring, request body larger than allowed size") return } @@ -102,7 +102,7 @@ func (m *Mirroring) ServeHTTP(rw http.ResponseWriter, req *http.Request) { select { case <-req.Context().Done(): // No mirroring if request has been canceled during main handler ServeHTTP - logger.Warn("no mirroring, request has been canceled during main handler ServeHTTP") + logger.Warn().Msg("No mirroring, request has been canceled during main handler ServeHTTP") return default: } @@ -179,7 +179,7 @@ func (b blackHoleResponseWriter) Write(data []byte) (int, error) { return len(data), nil } -func (b blackHoleResponseWriter) WriteHeader(statusCode int) {} +func (b blackHoleResponseWriter) WriteHeader(_ int) {} type contextStopPropagation struct { context.Context diff --git a/pkg/server/service/loadbalancer/wrr/wrr.go b/pkg/server/service/loadbalancer/wrr/wrr.go index 803764f49..ed89dfb31 100644 --- a/pkg/server/service/loadbalancer/wrr/wrr.go +++ b/pkg/server/service/loadbalancer/wrr/wrr.go @@ -7,8 +7,8 @@ import ( "net/http" "sync" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" ) type namedHandler struct { @@ -105,7 +105,9 @@ func (b *Balancer) SetStatus(ctx context.Context, childName string, up bool) { if up { status = "UP" } - log.FromContext(ctx).Debugf("Setting status of %s to %v", childName, status) + + log.Ctx(ctx).Debug().Msgf("Setting status of %s to %v", childName, status) + if up { b.status[childName] = struct{}{} } else { @@ -121,12 +123,12 @@ func (b *Balancer) SetStatus(ctx context.Context, childName string, up bool) { // No Status Change if upBefore == upAfter { // We're still with the same status, no need to propagate - log.FromContext(ctx).Debugf("Still %s, no need to propagate", status) + log.Ctx(ctx).Debug().Msgf("Still %s, no need to propagate", status) return } // Status Change - log.FromContext(ctx).Debugf("Propagating new %s status", status) + log.Ctx(ctx).Debug().Msgf("Propagating new %s status", status) for _, fn := range b.updaters { fn(upAfter) } @@ -168,7 +170,7 @@ func (b *Balancer) nextServer() (*namedHandler, error) { } } - log.WithoutContext().Debugf("Service selected by WRR: %s", handler.name) + log.Debug().Msgf("Service selected by WRR: %s", handler.name) return handler, nil } @@ -177,7 +179,7 @@ func (b *Balancer) ServeHTTP(w http.ResponseWriter, req *http.Request) { cookie, err := req.Cookie(b.stickyCookie.name) if err != nil && !errors.Is(err, http.ErrNoCookie) { - log.WithoutContext().Warnf("Error while reading cookie: %v", err) + log.Warn().Err(err).Msg("Error while reading cookie") } if err == nil && cookie != nil { diff --git a/pkg/server/service/proxy.go b/pkg/server/service/proxy.go index 43a2c0f28..58f5e7081 100644 --- a/pkg/server/service/proxy.go +++ b/pkg/server/service/proxy.go @@ -11,7 +11,7 @@ import ( "strings" "time" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" "golang.org/x/net/http/httpguts" ) @@ -115,12 +115,12 @@ func errorHandler(w http.ResponseWriter, req *http.Request, err error) { } } - logger := log.FromContext(req.Context()) - logger.Debugf("'%d %s' caused by: %v", statusCode, statusText(statusCode), err) + logger := log.Ctx(req.Context()) + logger.Debug().Err(err).Msgf("%d %s", statusCode, statusText(statusCode)) w.WriteHeader(statusCode) if _, werr := w.Write([]byte(statusText(statusCode))); werr != nil { - logger.Debugf("Error while writing status code", werr) + logger.Debug().Err(werr).Msg("Error while writing status code") } } diff --git a/pkg/server/service/roundtripper.go b/pkg/server/service/roundtripper.go index b155a5632..a4c01ef06 100644 --- a/pkg/server/service/roundtripper.go +++ b/pkg/server/service/roundtripper.go @@ -11,12 +11,12 @@ import ( "sync" "time" + "github.com/rs/zerolog/log" "github.com/spiffe/go-spiffe/v2/bundle/x509bundle" "github.com/spiffe/go-spiffe/v2/spiffeid" "github.com/spiffe/go-spiffe/v2/spiffetls/tlsconfig" "github.com/spiffe/go-spiffe/v2/svid/x509svid" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" traefiktls "github.com/traefik/traefik/v2/pkg/tls" "golang.org/x/net/http2" ) @@ -74,7 +74,7 @@ func (r *RoundTripperManager) Update(newConfigs map[string]*dynamic.ServersTrans var err error r.roundTrippers[configName], err = r.createRoundTripper(newConfig) if err != nil { - log.WithoutContext().Errorf("Could not configure HTTP Transport %s, fallback on default transport: %v", configName, err) + log.Error().Err(err).Msgf("Could not configure HTTP Transport %s, fallback on default transport", configName) r.roundTrippers[configName] = http.DefaultTransport } } @@ -87,7 +87,7 @@ func (r *RoundTripperManager) Update(newConfigs map[string]*dynamic.ServersTrans var err error r.roundTrippers[newConfigName], err = r.createRoundTripper(newConfig) if err != nil { - log.WithoutContext().Errorf("Could not configure HTTP Transport %s, fallback on default transport: %v", newConfigName, err) + log.Error().Err(err).Msgf("Could not configure HTTP Transport %s, fallback on default transport", newConfigName) r.roundTrippers[newConfigName] = http.DefaultTransport } } @@ -95,7 +95,7 @@ func (r *RoundTripperManager) Update(newConfigs map[string]*dynamic.ServersTrans r.configs = newConfigs } -// Get get a roundtripper by name. +// Get gets a roundtripper by name. func (r *RoundTripperManager) Get(name string) (http.RoundTripper, error) { if len(name) == 0 { name = "default@internal" @@ -195,7 +195,7 @@ func createRootCACertPool(rootCAs []traefiktls.FileOrContent) *x509.CertPool { for _, cert := range rootCAs { certContent, err := cert.Read() if err != nil { - log.WithoutContext().Error("Error while read RootCAs", err) + log.Error().Err(err).Msg("Error while read RootCAs") continue } roots.AppendCertsFromPEM(certContent) diff --git a/pkg/server/service/service.go b/pkg/server/service/service.go index d872a3607..d4295b9c6 100644 --- a/pkg/server/service/service.go +++ b/pkg/server/service/service.go @@ -13,10 +13,11 @@ import ( "strings" "time" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/runtime" "github.com/traefik/traefik/v2/pkg/healthcheck" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/metrics" "github.com/traefik/traefik/v2/pkg/middlewares/accesslog" metricsMiddle "github.com/traefik/traefik/v2/pkg/middlewares/metrics" @@ -64,10 +65,10 @@ func NewManager(configs map[string]*runtime.ServiceInfo, metricsRegistry metrics // BuildHTTP Creates a http.Handler for a service configuration. func (m *Manager) BuildHTTP(rootCtx context.Context, serviceName string) (http.Handler, error) { - ctx := log.With(rootCtx, log.Str(log.ServiceName, serviceName)) + serviceName = provider.GetQualifiedName(rootCtx, serviceName) - serviceName = provider.GetQualifiedName(ctx, serviceName) - ctx = provider.AddInContext(ctx, serviceName) + ctx := log.Ctx(rootCtx).With().Str(logs.ServiceName, serviceName).Logger(). + WithContext(provider.AddInContext(rootCtx, serviceName)) handler, ok := m.services[serviceName] if ok { @@ -241,7 +242,8 @@ func (m *Manager) getWRRServiceHandler(ctx context.Context, serviceName string, return nil, fmt.Errorf("cannot register %v as updater for %v: %w", childName, serviceName, err) } - log.FromContext(ctx).Debugf("Child service %v will update parent %v on status change", childName, serviceName) + log.Ctx(ctx).Debug().Str("parent", serviceName).Str("child", childName). + Msg("Child service will update parent on status change") } return balancer, nil @@ -250,8 +252,8 @@ func (m *Manager) getWRRServiceHandler(ctx context.Context, serviceName string, func (m *Manager) getLoadBalancerServiceHandler(ctx context.Context, serviceName string, info *runtime.ServiceInfo) (http.Handler, error) { service := info.LoadBalancer - logger := log.FromContext(ctx) - logger.Debug("Creating load-balancer") + logger := log.Ctx(ctx) + logger.Debug().Msg("Creating load-balancer") // TODO: should we keep this config value as Go is now handling stream response correctly? flushInterval := dynamic.DefaultFlushInterval @@ -292,7 +294,8 @@ func (m *Manager) getLoadBalancerServiceHandler(ctx context.Context, serviceName return nil, fmt.Errorf("error parsing server URL %s: %w", server.URL, err) } - logger.WithField(log.ServerName, proxyName).Debugf("Creating server %s", target) + logger.Debug().Str(logs.ServerName, proxyName).Stringer("target", target). + Msg("Creating server") proxy := buildSingleHostProxy(target, passHostHeader, time.Duration(flushInterval), roundTripper, m.bufferPool) @@ -330,8 +333,8 @@ func (m *Manager) getLoadBalancerServiceHandler(ctx context.Context, serviceName // LaunchHealthCheck launches the health checks. func (m *Manager) LaunchHealthCheck(ctx context.Context) { for serviceName, hc := range m.healthCheckers { - ctx = log.With(ctx, log.Str(log.ServiceName, serviceName)) - go hc.Launch(ctx) + logger := log.Ctx(ctx).With().Str(logs.ServiceName, serviceName).Logger() + go hc.Launch(logger.WithContext(ctx)) } } diff --git a/pkg/server/service/tcp/service.go b/pkg/server/service/tcp/service.go index e7dc4dbc6..d099af501 100644 --- a/pkg/server/service/tcp/service.go +++ b/pkg/server/service/tcp/service.go @@ -8,8 +8,9 @@ import ( "net" "time" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/server/provider" "github.com/traefik/traefik/v2/pkg/tcp" ) @@ -31,8 +32,9 @@ func NewManager(conf *runtime.Configuration) *Manager { // BuildTCP Creates a tcp.Handler for a service configuration. func (m *Manager) BuildTCP(rootCtx context.Context, serviceName string) (tcp.Handler, error) { serviceQualifiedName := provider.GetQualifiedName(rootCtx, serviceName) + + logger := log.Ctx(rootCtx).With().Str(logs.ServiceName, serviceQualifiedName).Logger() ctx := provider.AddInContext(rootCtx, serviceQualifiedName) - ctx = log.With(ctx, log.Str(log.ServiceName, serviceName)) conf, ok := m.configs[serviceQualifiedName] if !ok { @@ -45,7 +47,6 @@ func (m *Manager) BuildTCP(rootCtx context.Context, serviceName string) (tcp.Han return nil, err } - logger := log.FromContext(ctx) switch { case conf.LoadBalancer != nil: loadBalancer := tcp.NewWRRLoadBalancer() @@ -56,34 +57,43 @@ func (m *Manager) BuildTCP(rootCtx context.Context, serviceName string) (tcp.Han } duration := time.Duration(*conf.LoadBalancer.TerminationDelay) * time.Millisecond - for name, server := range shuffle(conf.LoadBalancer.Servers, m.rand) { + for index, server := range shuffle(conf.LoadBalancer.Servers, m.rand) { + srvLogger := logger.With(). + Int(logs.ServerIndex, index). + Str("serverAddress", server.Address).Logger() + if _, _, err := net.SplitHostPort(server.Address); err != nil { - logger.Errorf("In service %q: %v", serviceQualifiedName, err) + srvLogger.Error().Err(err).Msg("Failed to split host port") continue } handler, err := tcp.NewProxy(server.Address, duration, conf.LoadBalancer.ProxyProtocol) if err != nil { - logger.Errorf("In service %q server %q: %v", serviceQualifiedName, server.Address, err) + srvLogger.Error().Err(err).Msg("Failed to create server") continue } loadBalancer.AddServer(handler) - logger.WithField(log.ServerName, name).Debugf("Creating TCP server %d at %s", name, server.Address) + logger.Debug().Msg("Creating TCP server") } + return loadBalancer, nil + case conf.Weighted != nil: loadBalancer := tcp.NewWRRLoadBalancer() for _, service := range shuffle(conf.Weighted.Services, m.rand) { - handler, err := m.BuildTCP(rootCtx, service.Name) + handler, err := m.BuildTCP(ctx, service.Name) if err != nil { - logger.Errorf("In service %q: %v", serviceQualifiedName, err) + logger.Error().Err(err).Msg("Failed to build TCP handler") return nil, err } + loadBalancer.AddWeightServer(handler, service.Weight) } + return loadBalancer, nil + default: err := fmt.Errorf("the service %q does not have any type defined", serviceQualifiedName) conf.AddError(err, true) diff --git a/pkg/server/service/udp/service.go b/pkg/server/service/udp/service.go index f388a7824..7d15c19ff 100644 --- a/pkg/server/service/udp/service.go +++ b/pkg/server/service/udp/service.go @@ -8,8 +8,9 @@ import ( "net" "time" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/runtime" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/server/provider" "github.com/traefik/traefik/v2/pkg/udp" ) @@ -31,12 +32,13 @@ func NewManager(conf *runtime.Configuration) *Manager { // BuildUDP creates the UDP handler for the given service name. func (m *Manager) BuildUDP(rootCtx context.Context, serviceName string) (udp.Handler, error) { serviceQualifiedName := provider.GetQualifiedName(rootCtx, serviceName) + + logger := log.Ctx(rootCtx).With().Str(logs.ServiceName, serviceQualifiedName).Logger() ctx := provider.AddInContext(rootCtx, serviceQualifiedName) - ctx = log.With(ctx, log.Str(log.ServiceName, serviceName)) conf, ok := m.configs[serviceQualifiedName] if !ok { - return nil, fmt.Errorf("the udp service %q does not exist", serviceQualifiedName) + return nil, fmt.Errorf("the UDP service %q does not exist", serviceQualifiedName) } if conf.LoadBalancer != nil && conf.Weighted != nil { @@ -45,41 +47,49 @@ func (m *Manager) BuildUDP(rootCtx context.Context, serviceName string) (udp.Han return nil, err } - logger := log.FromContext(ctx) switch { case conf.LoadBalancer != nil: loadBalancer := udp.NewWRRLoadBalancer() - for name, server := range shuffle(conf.LoadBalancer.Servers, m.rand) { + for index, server := range shuffle(conf.LoadBalancer.Servers, m.rand) { + srvLogger := logger.With(). + Int(logs.ServerIndex, index). + Str("serverAddress", server.Address).Logger() + if _, _, err := net.SplitHostPort(server.Address); err != nil { - logger.Errorf("In udp service %q: %v", serviceQualifiedName, err) + srvLogger.Error().Err(err).Msg("Failed to split host port") continue } handler, err := udp.NewProxy(server.Address) if err != nil { - logger.Errorf("In udp service %q server %q: %v", serviceQualifiedName, server.Address, err) + srvLogger.Error().Err(err).Msg("Failed to create server") continue } loadBalancer.AddServer(handler) - logger.WithField(log.ServerName, name).Debugf("Creating UDP server %d at %s", name, server.Address) + srvLogger.Debug().Msg("Creating UDP server") } + return loadBalancer, nil + case conf.Weighted != nil: loadBalancer := udp.NewWRRLoadBalancer() for _, service := range shuffle(conf.Weighted.Services, m.rand) { - handler, err := m.BuildUDP(rootCtx, service.Name) + handler, err := m.BuildUDP(ctx, service.Name) if err != nil { - logger.Errorf("In udp service %q: %v", serviceQualifiedName, err) + logger.Error().Err(err).Msg("Failed to build UDP handler") return nil, err } + loadBalancer.AddWeightedServer(handler, service.Weight) } + return loadBalancer, nil + default: - err := fmt.Errorf("the udp service %q does not have any type defined", serviceQualifiedName) + err := fmt.Errorf("the UDP service %q does not have any type defined", serviceQualifiedName) conf.AddError(err, true) return nil, err } diff --git a/pkg/server/service/udp/service_test.go b/pkg/server/service/udp/service_test.go index 0f06c1feb..335a13a24 100644 --- a/pkg/server/service/udp/service_test.go +++ b/pkg/server/service/udp/service_test.go @@ -23,7 +23,7 @@ func TestManager_BuildUDP(t *testing.T) { desc: "without configuration", serviceName: "test", configs: nil, - expectedError: `the udp service "test" does not exist`, + expectedError: `the UDP service "test" does not exist`, }, { desc: "missing lb configuration", @@ -33,7 +33,7 @@ func TestManager_BuildUDP(t *testing.T) { UDPService: &dynamic.UDPService{}, }, }, - expectedError: `the udp service "test" does not have any type defined`, + expectedError: `the UDP service "test" does not have any type defined`, }, { desc: "no such host, server is skipped, error is logged", diff --git a/pkg/tcp/proxy.go b/pkg/tcp/proxy.go index 8887bb91d..525c43c4b 100644 --- a/pkg/tcp/proxy.go +++ b/pkg/tcp/proxy.go @@ -9,8 +9,8 @@ import ( "time" "github.com/pires/go-proxyproto" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/config/dynamic" - "github.com/traefik/traefik/v2/pkg/log" ) // Proxy forwards a TCP request to a TCP service. @@ -48,14 +48,14 @@ func NewProxy(address string, terminationDelay time.Duration, proxyProtocol *dyn // ServeTCP forwards the connection to a service. func (p *Proxy) ServeTCP(conn WriteCloser) { - log.WithoutContext().Debugf("Handling connection from %s to %s", conn.RemoteAddr(), p.address) + log.Debug().Msgf("Handling connection from %s to %s", conn.RemoteAddr(), p.address) // needed because of e.g. server.trackedConnection defer conn.Close() connBackend, err := p.dialBackend() if err != nil { - log.WithoutContext().Errorf("Error while connecting to backend: %v", err) + log.Error().Err(err).Msg("Error while connecting to backend") return } @@ -66,7 +66,7 @@ func (p *Proxy) ServeTCP(conn WriteCloser) { if p.proxyProtocol != nil && p.proxyProtocol.Version > 0 && p.proxyProtocol.Version < 3 { header := proxyproto.HeaderProxyFromAddrs(byte(p.proxyProtocol.Version), conn.RemoteAddr(), conn.LocalAddr()) if _, err := header.WriteTo(connBackend); err != nil { - log.WithoutContext().Errorf("Error while writing proxy protocol headers to backend connection: %v", err) + log.Error().Err(err).Msg("Error while writing proxy protocol headers to backend connection") return } } @@ -80,9 +80,9 @@ func (p *Proxy) ServeTCP(conn WriteCloser) { // This allows to not report an RST packet sent by the peer as an error, // as it is an abrupt but possible end for the TCP session if isReadConnResetError(err) { - log.WithoutContext().Debugf("Error during connection: %v", err) + log.Debug().Err(err).Msg("Error during connection") } else { - log.WithoutContext().Errorf("Error during connection: %v", err) + log.Error().Err(err).Msg("Error during connection") } } @@ -95,7 +95,7 @@ func (p Proxy) dialBackend() (*net.TCPConn, error) { return net.DialTCP("tcp", nil, p.tcpAddr) } - log.WithoutContext().Debugf("Dial with lookup to address %s", p.address) + log.Debug().Msgf("Dial with lookup to address %s", p.address) // Dial with DNS lookup for host based addresses. conn, err := net.Dial("tcp", p.address) @@ -119,7 +119,7 @@ func (p Proxy) connCopy(dst, src WriteCloser, errCh chan error) { // In that case, logging the error is superfluous, // as in the first place we should not have needed to call CloseWrite. if !isSocketNotConnectedError(errClose) { - log.WithoutContext().Debugf("Error while terminating connection: %v", errClose) + log.Debug().Err(errClose).Msg("Error while terminating connection") } return @@ -128,7 +128,7 @@ func (p Proxy) connCopy(dst, src WriteCloser, errCh chan error) { if p.terminationDelay >= 0 { err := dst.SetReadDeadline(time.Now().Add(p.terminationDelay)) if err != nil { - log.WithoutContext().Debugf("Error while setting deadline: %v", err) + log.Debug().Err(err).Msg("Error while setting deadline") } } } diff --git a/pkg/tcp/wrr_load_balancer.go b/pkg/tcp/wrr_load_balancer.go index 236fd8007..d494e0abf 100644 --- a/pkg/tcp/wrr_load_balancer.go +++ b/pkg/tcp/wrr_load_balancer.go @@ -4,7 +4,7 @@ import ( "fmt" "sync" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) type server struct { @@ -34,7 +34,7 @@ func (b *WRRLoadBalancer) ServeTCP(conn WriteCloser) { b.lock.Unlock() if err != nil { - log.WithoutContext().Errorf("Error during load balancing: %v", err) + log.Error().Err(err).Msg("Error during load balancing") conn.Close() return } diff --git a/pkg/tls/certificate.go b/pkg/tls/certificate.go index 25559a22e..7cddcd526 100644 --- a/pkg/tls/certificate.go +++ b/pkg/tls/certificate.go @@ -10,7 +10,7 @@ import ( "sort" "strings" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) var ( @@ -63,7 +63,7 @@ func (c Certificates) GetCertificates() []tls.Certificate { for _, certificate := range c { cert, err := certificate.GetCertificate() if err != nil { - log.WithoutContext().Debugf("Error while getting certificate: %v", err) + log.Debug().Err(err).Msg("Error while getting certificate") continue } @@ -153,9 +153,9 @@ func (c *Certificate) AppendCertificate(certs map[string]map[string]*tls.Certifi } } if certExists { - log.Debugf("Skipping addition of certificate for domain(s) %q, to TLS Store %s, as it already exists for this store.", certKey, storeName) + log.Debug().Msgf("Skipping addition of certificate for domain(s) %q, to TLS Store %s, as it already exists for this store.", certKey, storeName) } else { - log.Debugf("Adding certificate for domain(s) %s", certKey) + log.Debug().Msgf("Adding certificate for domain(s) %s", certKey) certs[storeName][certKey] = &tlsCert } diff --git a/pkg/tls/certificate_store.go b/pkg/tls/certificate_store.go index 1a954a0e0..353efc95c 100644 --- a/pkg/tls/certificate_store.go +++ b/pkg/tls/certificate_store.go @@ -9,7 +9,7 @@ import ( "time" "github.com/patrickmn/go-cache" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" "github.com/traefik/traefik/v2/pkg/safe" ) @@ -40,7 +40,7 @@ func (c CertificateStore) getDefaultCertificateDomains() []string { x509Cert, err := x509.ParseCertificate(c.DefaultCertificate.Certificate[0]) if err != nil { - log.WithoutContext().Errorf("Could not parse default certificate: %v", err) + log.Error().Err(err).Msg("Could not parse default certificate") return allCerts } @@ -81,7 +81,7 @@ func (c *CertificateStore) GetBestCertificate(clientHello *tls.ClientHelloInfo) // If no ServerName is provided, Check for local IP address matches host, _, err := net.SplitHostPort(clientHello.Conn.LocalAddr().String()) if err != nil { - log.WithoutContext().Debugf("Could not split host/port: %v", err) + log.Debug().Err(err).Msg("Could not split host/port") } serverName = strings.TrimSpace(host) } diff --git a/pkg/tls/tlsmanager.go b/pkg/tls/tlsmanager.go index 0c7daa992..74fb9ee20 100644 --- a/pkg/tls/tlsmanager.go +++ b/pkg/tls/tlsmanager.go @@ -11,8 +11,8 @@ import ( "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/challenge/tlsalpn01" - "github.com/sirupsen/logrus" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/tls/generate" "github.com/traefik/traefik/v2/pkg/types" ) @@ -86,15 +86,15 @@ func (m *Manager) UpdateConfigs(ctx context.Context, stores map[string]Store, co storesCertificates := make(map[string]map[string]*tls.Certificate) for _, conf := range certs { if len(conf.Stores) == 0 { - if log.GetLevel() >= logrus.DebugLevel { - log.FromContext(ctx).Debugf("No store is defined to add the certificate %s, it will be added to the default store.", + log.Ctx(ctx).Debug().MsgFunc(func() string { + return fmt.Sprintf("No store is defined to add the certificate %s, it will be added to the default store", conf.Certificate.GetTruncatedCertificateName()) - } + }) conf.Stores = []string{DefaultTLSStoreName} } for _, store := range conf.Stores { - ctxStore := log.With(ctx, log.Str(log.TLSStoreName, store)) + logger := log.Ctx(ctx).With().Str(logs.TLSStoreName, store).Logger() if _, ok := m.storesConfig[store]; !ok { m.storesConfig[store] = Store{} @@ -102,7 +102,7 @@ func (m *Manager) UpdateConfigs(ctx context.Context, stores map[string]Store, co err := conf.Certificate.AppendCertificate(storesCertificates, store) if err != nil { - log.FromContext(ctxStore).Errorf("Unable to append certificate %s to store: %v", conf.Certificate.GetTruncatedCertificateName(), err) + logger.Error().Err(err).Msgf("Unable to append certificate %s to store", conf.Certificate.GetTruncatedCertificateName()) } } } @@ -122,11 +122,12 @@ func (m *Manager) UpdateConfigs(ctx context.Context, stores map[string]Store, co continue } - ctxStore := log.With(ctx, log.Str(log.TLSStoreName, storeName)) + logger := log.Ctx(ctx).With().Str(logs.TLSStoreName, storeName).Logger() + ctxStore := logger.WithContext(ctx) certificate, err := getDefaultCertificate(ctxStore, storeConfig, st) if err != nil { - log.FromContext(ctxStore).Errorf("Error while creating certificate store: %v", err) + logger.Error().Err(err).Msg("Error while creating certificate store") } st.DefaultCertificate = certificate @@ -187,7 +188,7 @@ func (m *Manager) Get(storeName, configName string) (*tls.Config, error) { if isACMETLS(clientHello) { certificate := acmeTLSStore.GetBestCertificate(clientHello) if certificate == nil { - log.WithoutContext().Debugf("TLS: no certificate for TLSALPN challenge: %s", domainToCheck) + log.Debug().Msgf("TLS: no certificate for TLSALPN challenge: %s", domainToCheck) // We want the user to eventually get the (alertUnrecognizedName) "unrecognized // name" error. // Unfortunately, if we returned an error here, since we can't use @@ -210,19 +211,19 @@ func (m *Manager) Get(storeName, configName string) (*tls.Config, error) { } if sniStrict { - log.WithoutContext().Debugf("TLS: strict SNI enabled - No certificate found for domain: %q, closing connection", domainToCheck) + log.Debug().Msgf("TLS: strict SNI enabled - No certificate found for domain: %q, closing connection", domainToCheck) // Same comment as above, as in the isACMETLS case. return nil, nil } if store == nil { - log.WithoutContext().Errorf("TLS: No certificate store found with this name: %q, closing connection", storeName) + log.Error().Msgf("TLS: No certificate store found with this name: %q, closing connection", storeName) // Same comment as above, as in the isACMETLS case. return nil, nil } - log.WithoutContext().Debugf("Serving default certificate for request: %q", domainToCheck) + log.Debug().Msgf("Serving default certificate for request: %q", domainToCheck) return store.DefaultCertificate, nil } @@ -296,7 +297,7 @@ func getDefaultCertificate(ctx context.Context, tlsStore Store, st *CertificateS return defaultACMECert, nil } - log.FromContext(ctx).Debug("No default certificate, fallback to the internal generated certificate") + log.Ctx(ctx).Debug().Msg("No default certificate, fallback to the internal generated certificate") return defaultCert, nil } diff --git a/pkg/tracing/datadog/datadog.go b/pkg/tracing/datadog/datadog.go index f8878943f..74b68d65c 100644 --- a/pkg/tracing/datadog/datadog.go +++ b/pkg/tracing/datadog/datadog.go @@ -7,7 +7,8 @@ import ( "strings" "github.com/opentracing/opentracing-go" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" ddtracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentracer" datadog "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" ) @@ -46,6 +47,8 @@ func (c *Config) SetDefaults() { // Setup sets up the tracer. func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error) { + logger := log.With().Str(logs.TracingProviderName, Name).Logger() + opts := []datadog.StartOption{ datadog.WithAgentAddr(c.LocalAgentHostPort), datadog.WithServiceName(serviceName), @@ -56,6 +59,7 @@ func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error PriorityHeader: c.SamplingPriorityHeaderName, BaggagePrefix: c.BagagePrefixHeaderName, })), + datadog.WithLogger(logs.NewDatadogLogger(logger)), } for k, v := range c.GlobalTags { @@ -63,7 +67,7 @@ func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error } if c.GlobalTag != "" { - log.WithoutContext().Warn(`Datadog: option "globalTag" is deprecated, please use "globalTags" instead.`) + logger.Warn().Msg(`Datadog: option "globalTag" is deprecated, please use "globalTags" instead.`) key, value, _ := strings.Cut(c.GlobalTag, ":") @@ -76,12 +80,13 @@ func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error if c.PrioritySampling { opts = append(opts, datadog.WithPrioritySampling()) } + tracer := ddtracer.New(opts...) // Without this, child spans are getting the NOOP tracer opentracing.SetGlobalTracer(tracer) - log.WithoutContext().Debug("Datadog tracer configured") + logger.Debug().Msg("Datadog tracer configured") return tracer, nil, nil } diff --git a/pkg/tracing/elastic/elastic.go b/pkg/tracing/elastic/elastic.go index fa385376b..967f5fcb0 100644 --- a/pkg/tracing/elastic/elastic.go +++ b/pkg/tracing/elastic/elastic.go @@ -5,7 +5,8 @@ import ( "net/url" "github.com/opentracing/opentracing-go" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" "github.com/traefik/traefik/v2/pkg/version" "go.elastic.co/apm" "go.elastic.co/apm/module/apmot" @@ -59,13 +60,15 @@ func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error return nil, nil, err } - tracer.SetLogger(log.WithoutContext()) + logger := log.With().Str(logs.TracingProviderName, Name).Logger() + tracer.SetLogger(logs.NewElasticLogger(logger)) + otTracer := apmot.New(apmot.WithTracer(tracer)) // Without this, child spans are getting the NOOP tracer opentracing.SetGlobalTracer(otTracer) - log.WithoutContext().Debug("Elastic tracer configured") + log.Debug().Msg("Elastic tracer configured") return otTracer, nil, nil } diff --git a/pkg/tracing/haystack/haystack.go b/pkg/tracing/haystack/haystack.go index 3990e58d2..9c64dd36b 100644 --- a/pkg/tracing/haystack/haystack.go +++ b/pkg/tracing/haystack/haystack.go @@ -7,7 +7,8 @@ import ( "github.com/ExpediaDotCom/haystack-client-go" "github.com/opentracing/opentracing-go" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" ) // Name sets the name of this tracer. @@ -48,6 +49,8 @@ func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error port = c.LocalAgentPort } + logger := log.With().Str(logs.TracingProviderName, Name).Logger() + tracer, closer := haystack.NewTracer(serviceName, haystack.NewAgentDispatcher(host, port, 3*time.Second, 1000), haystack.TracerOptionsFactory.Tag(tag[0], value), haystack.TracerOptionsFactory.Propagator(opentracing.HTTPHeaders, @@ -57,13 +60,13 @@ func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error SpanIDKEYName: c.SpanIDHeaderName, BaggagePrefixKEYName: c.BaggagePrefixHeaderName, }, haystack.DefaultCodex{})), - haystack.TracerOptionsFactory.Logger(&haystackLogger{logger: log.WithoutContext()}), + haystack.TracerOptionsFactory.Logger(logs.NewHaystackLogger(logger)), ) // Without this, child spans are getting the NOOP tracer opentracing.SetGlobalTracer(tracer) - log.WithoutContext().Debug("haystack tracer configured") + log.Debug().Msg("haystack tracer configured") return tracer, closer, nil } diff --git a/pkg/tracing/haystack/logger.go b/pkg/tracing/haystack/logger.go deleted file mode 100644 index 7635bd821..000000000 --- a/pkg/tracing/haystack/logger.go +++ /dev/null @@ -1,24 +0,0 @@ -package haystack - -import ( - "github.com/traefik/traefik/v2/pkg/log" -) - -type haystackLogger struct { - logger log.Logger -} - -// Error prints the error message. -func (l haystackLogger) Error(format string, v ...interface{}) { - l.logger.Errorf(format, v...) -} - -// Info prints the info message. -func (l haystackLogger) Info(format string, v ...interface{}) { - l.logger.Infof(format, v...) -} - -// Debug prints the info message. -func (l haystackLogger) Debug(format string, v ...interface{}) { - l.logger.Debugf(format, v...) -} diff --git a/pkg/tracing/instana/instana.go b/pkg/tracing/instana/instana.go index c7f538426..39c664468 100644 --- a/pkg/tracing/instana/instana.go +++ b/pkg/tracing/instana/instana.go @@ -5,7 +5,8 @@ import ( instana "github.com/instana/go-sensor" "github.com/opentracing/opentracing-go" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" ) // Name sets the name of this tracer. @@ -40,6 +41,9 @@ func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error logLevel = instana.Debug } + logger := log.With().Str(logs.TracingProviderName, Name).Logger() + instana.SetLogger(logs.NewInstanaLogger(logger)) + tracer := instana.NewTracerWithOptions(&instana.Options{ Service: serviceName, LogLevel: logLevel, @@ -51,7 +55,7 @@ func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error // Without this, child spans are getting the NOOP tracer opentracing.SetGlobalTracer(tracer) - log.WithoutContext().Debug("Instana tracer configured") + logger.Debug().Msg("Instana tracer configured") return tracer, nil, nil } diff --git a/pkg/tracing/jaeger/jaeger.go b/pkg/tracing/jaeger/jaeger.go index 9f5b90026..206c206de 100644 --- a/pkg/tracing/jaeger/jaeger.go +++ b/pkg/tracing/jaeger/jaeger.go @@ -5,7 +5,8 @@ import ( "io" "github.com/opentracing/opentracing-go" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v2/pkg/logs" jaegercli "github.com/uber/jaeger-client-go" jaegercfg "github.com/uber/jaeger-client-go/config" "github.com/uber/jaeger-client-go/zipkin" @@ -88,8 +89,10 @@ func (c *Config) Setup(componentName string) (opentracing.Tracer, io.Closer, err jMetricsFactory := jaegermet.NullFactory + logger := log.With().Str(logs.TracingProviderName, Name).Logger() + opts := []jaegercfg.Option{ - jaegercfg.Logger(newJaegerLogger()), + jaegercfg.Logger(logs.NewJaegerLogger(logger)), jaegercfg.Metrics(jMetricsFactory), jaegercfg.Gen128Bit(c.Gen128Bit), } @@ -112,10 +115,10 @@ func (c *Config) Setup(componentName string) (opentracing.Tracer, io.Closer, err opts..., ) if err != nil { - log.WithoutContext().Warnf("Could not initialize jaeger tracer: %v", err) + logger.Warn().Err(err).Msg("Could not initialize jaeger tracer") return nil, nil, err } - log.WithoutContext().Debug("Jaeger tracer configured") + logger.Debug().Msg("Jaeger tracer configured") return opentracing.GlobalTracer(), closer, nil } diff --git a/pkg/tracing/jaeger/logger.go b/pkg/tracing/jaeger/logger.go deleted file mode 100644 index 4aad3de77..000000000 --- a/pkg/tracing/jaeger/logger.go +++ /dev/null @@ -1,26 +0,0 @@ -package jaeger - -import ( - "github.com/sirupsen/logrus" - "github.com/traefik/traefik/v2/pkg/log" -) - -// jaegerLogger is an implementation of the Logger interface that delegates to traefik log. -type jaegerLogger struct { - logger logrus.FieldLogger -} - -func newJaegerLogger() *jaegerLogger { - return &jaegerLogger{ - logger: log.WithoutContext().WithField(log.TracingProviderName, "jaeger"), - } -} - -func (l *jaegerLogger) Error(msg string) { - l.logger.Errorf("Tracing jaeger error: %s", msg) -} - -// Infof logs a message at debug priority. -func (l *jaegerLogger) Infof(msg string, args ...interface{}) { - l.logger.Debugf(msg, args...) -} diff --git a/pkg/tracing/operation_name.go b/pkg/tracing/operation_name.go index e6194e31e..70694747b 100644 --- a/pkg/tracing/operation_name.go +++ b/pkg/tracing/operation_name.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) // TraceNameHashLength defines the number of characters to use from the head of the generated hash. @@ -22,7 +22,7 @@ func generateOperationName(prefix string, parts []string, sep string, spanLimit if spanLimit > 0 && len(name) > spanLimit { if spanLimit < maxLength { - log.WithoutContext().Warnf("SpanNameLimit cannot be lesser than %d: falling back on %d, maxLength, maxLength+3", maxLength) + log.Warn().Msgf("SpanNameLimit cannot be lesser than %d: falling back on %d", maxLength, maxLength+3) spanLimit = maxLength + 3 } @@ -58,7 +58,7 @@ func computeHash(name string) string { hash := sha256.New() if _, err := hash.Write(data); err != nil { // Impossible case - log.WithoutContext().WithField("OperationName", name).Errorf("Failed to create Span name hash for %s: %v", name, err) + log.Error().Str("OperationName", name).Err(err).Msgf("Failed to create Span name hash for %s", name) } return fmt.Sprintf("%x", hash.Sum(nil))[:TraceNameHashLength] diff --git a/pkg/tracing/tracing.go b/pkg/tracing/tracing.go index f951fc1a3..d8923f510 100644 --- a/pkg/tracing/tracing.go +++ b/pkg/tracing/tracing.go @@ -9,7 +9,7 @@ import ( "github.com/opentracing/opentracing-go" "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) type contextKey int @@ -99,7 +99,7 @@ func (t *Tracing) Close() { if t.closer != nil { err := t.closer.Close() if err != nil { - log.WithoutContext().Warn(err) + log.Warn().Err(err).Send() } } } @@ -136,7 +136,7 @@ func InjectRequestHeaders(r *http.Request) { opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(r.Header)) if err != nil { - log.FromContext(r.Context()).Error(err) + log.Ctx(r.Context()).Error().Err(err).Send() } } } diff --git a/pkg/tracing/zipkin/zipkin.go b/pkg/tracing/zipkin/zipkin.go index 96974a305..598f38037 100644 --- a/pkg/tracing/zipkin/zipkin.go +++ b/pkg/tracing/zipkin/zipkin.go @@ -8,7 +8,7 @@ import ( zipkinot "github.com/openzipkin-contrib/zipkin-go-opentracing" "github.com/openzipkin/zipkin-go" "github.com/openzipkin/zipkin-go/reporter/http" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) // Name sets the name of this tracer. @@ -65,7 +65,7 @@ func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error // Without this, child spans are getting the NOOP tracer opentracing.SetGlobalTracer(tracer) - log.WithoutContext().Debug("Zipkin tracer configured") + log.Debug().Msg("Zipkin tracer configured") return tracer, reporter, nil } diff --git a/pkg/types/logs.go b/pkg/types/logs.go index 2c932e487..657e56102 100644 --- a/pkg/types/logs.go +++ b/pkg/types/logs.go @@ -21,9 +21,15 @@ const ( // TraefikLog holds the configuration settings for the traefik logger. type TraefikLog struct { - Level string `description:"Log level set to traefik logs." json:"level,omitempty" toml:"level,omitempty" yaml:"level,omitempty" export:"true"` - FilePath string `description:"Traefik log file path. Stdout is used when omitted or empty." json:"filePath,omitempty" toml:"filePath,omitempty" yaml:"filePath,omitempty"` - Format string `description:"Traefik log format: json | common" json:"format,omitempty" toml:"format,omitempty" yaml:"format,omitempty" export:"true"` + Level string `description:"Log level set to traefik logs." json:"level,omitempty" toml:"level,omitempty" yaml:"level,omitempty" export:"true"` + Format string `description:"Traefik log format: json | common" json:"format,omitempty" toml:"format,omitempty" yaml:"format,omitempty" export:"true"` + NoColor bool `description:"When using the 'common' format, disables the colorized output." json:"noColor,omitempty" toml:"noColor,omitempty" yaml:"noColor,omitempty" export:"true"` + + FilePath string `description:"Traefik log file path. Stdout is used when omitted or empty." json:"filePath,omitempty" toml:"filePath,omitempty" yaml:"filePath,omitempty"` + MaxSize int `description:"Maximum size in megabytes of the log file before it gets rotated." json:"maxSize,omitempty" toml:"maxSize,omitempty" yaml:"maxSize,omitempty" export:"true"` + MaxAge int `description:"Maximum number of days to retain old log files based on the timestamp encoded in their filename." json:"maxAge,omitempty" toml:"maxAge,omitempty" yaml:"maxAge,omitempty" export:"true"` + MaxBackups int `description:"Maximum number of old log files to retain." json:"maxBackups,omitempty" toml:"maxBackups,omitempty" yaml:"maxBackups,omitempty" export:"true"` + Compress bool `description:"Determines if the rotated log files should be compressed using gzip." json:"compress,omitempty" toml:"compress,omitempty" yaml:"compress,omitempty" export:"true"` } // SetDefaults sets the default values. diff --git a/pkg/types/tls.go b/pkg/types/tls.go index 61cf5346c..2b5457be2 100644 --- a/pkg/types/tls.go +++ b/pkg/types/tls.go @@ -8,7 +8,7 @@ import ( "fmt" "os" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) // +k8s:deepcopy-gen=true @@ -27,12 +27,12 @@ type ClientTLS struct { // CreateTLSConfig creates a TLS config from ClientTLS structures. func (c *ClientTLS) CreateTLSConfig(ctx context.Context) (*tls.Config, error) { if c == nil { - log.FromContext(ctx).Warnf("clientTLS is nil") + log.Ctx(ctx).Warn().Msg("clientTLS is nil") return nil, nil } if c.CAOptional { - log.FromContext(ctx).Warn("CAOptional is deprecated, TLS client authentication is a server side option.") + log.Ctx(ctx).Warn().Msg("CAOptional is deprecated, TLS client authentication is a server side option.") } // Not initialized, to rely on system bundle. diff --git a/pkg/udp/proxy.go b/pkg/udp/proxy.go index 8ccbfda4b..31f64a5ce 100644 --- a/pkg/udp/proxy.go +++ b/pkg/udp/proxy.go @@ -4,7 +4,7 @@ import ( "io" "net" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) // Proxy is a reverse-proxy implementation of the Handler interface. @@ -20,14 +20,14 @@ func NewProxy(address string) (*Proxy, error) { // ServeUDP implements the Handler interface. func (p *Proxy) ServeUDP(conn *Conn) { - log.WithoutContext().Debugf("Handling connection from %s to %s", conn.rAddr, p.target) + log.Debug().Msgf("Handling connection from %s to %s", conn.rAddr, p.target) // needed because of e.g. server.trackedConnection defer conn.Close() connBackend, err := net.Dial("udp", p.target) if err != nil { - log.WithoutContext().Errorf("Error while connecting to backend: %v", err) + log.Error().Err(err).Msg("Error while connecting to backend") return } @@ -40,7 +40,7 @@ func (p *Proxy) ServeUDP(conn *Conn) { err = <-errChan if err != nil { - log.WithoutContext().Errorf("Error while serving UDP: %v", err) + log.Error().Err(err).Msg("Error while serving UDP") } <-errChan @@ -55,6 +55,6 @@ func connCopy(dst io.WriteCloser, src io.Reader, errCh chan error) { errCh <- err if err := dst.Close(); err != nil { - log.WithoutContext().Debugf("Error while terminating connection: %v", err) + log.Debug().Err(err).Msg("Error while terminating connection") } } diff --git a/pkg/udp/wrr_load_balancer.go b/pkg/udp/wrr_load_balancer.go index 7dd2a9c07..03fe059e1 100644 --- a/pkg/udp/wrr_load_balancer.go +++ b/pkg/udp/wrr_load_balancer.go @@ -4,7 +4,7 @@ import ( "fmt" "sync" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" ) type server struct { @@ -34,7 +34,7 @@ func (b *WRRLoadBalancer) ServeUDP(conn *Conn) { b.lock.Unlock() if err != nil { - log.WithoutContext().Errorf("Error during load balancing: %v", err) + log.Error().Err(err).Msg("Error during load balancing") conn.Close() return } diff --git a/pkg/version/version.go b/pkg/version/version.go index 49b4f9e1e..72472fcc9 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -9,7 +9,7 @@ import ( "github.com/google/go-github/v28/github" "github.com/gorilla/mux" goversion "github.com/hashicorp/go-version" - "github.com/traefik/traefik/v2/pkg/log" + "github.com/rs/zerolog/log" "github.com/unrolled/render" ) @@ -48,7 +48,7 @@ func (v Handler) Append(router *mux.Router) { } if err := templatesRenderer.JSON(response, http.StatusOK, v); err != nil { - log.WithoutContext().Error(err) + log.Error().Err(err).Send() } }) } @@ -59,38 +59,36 @@ func CheckNewVersion() { return } - logger := log.WithoutContext() - client := github.NewClient(nil) updateURL, err := url.Parse("https://update.traefik.io/") if err != nil { - logger.Warnf("Error checking new version: %s", err) + log.Warn().Err(err).Msg("Error checking new version") return } client.BaseURL = updateURL releases, resp, err := client.Repositories.ListReleases(context.Background(), "traefik", "traefik", nil) if err != nil { - logger.Warnf("Error checking new version: %s", err) + log.Warn().Err(err).Msg("Error checking new version") return } if resp.StatusCode != http.StatusOK { - logger.Warnf("Error checking new version: status=%s", resp.Status) + log.Warn().Msgf("Error checking new version: status=%s", resp.Status) return } currentVersion, err := goversion.NewVersion(Version) if err != nil { - logger.Warnf("Error checking new version: %s", err) + log.Warn().Err(err).Msg("Error checking new version") return } for _, release := range releases { releaseVersion, err := goversion.NewVersion(*release.TagName) if err != nil { - logger.Warnf("Error checking new version: %s", err) + log.Warn().Err(err).Msg("Error checking new version") return } @@ -99,7 +97,7 @@ func CheckNewVersion() { } if releaseVersion.GreaterThan(currentVersion) { - logger.Warnf("A new release has been found: %s. Please consider updating.", releaseVersion.String()) + log.Warn().Err(err).Msgf("A new release has been found: %s. Please consider updating.", releaseVersion.String()) return } }