From df76aaede4b741e9436ced76dea71946d8f29684 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 30 Jul 2023 22:35:31 +0200 Subject: [PATCH 01/12] removes/docker: remove unnecessary conversion (unconvert) Signed-off-by: Sebastiaan van Stijn (cherry picked from commit e2ad5a985ef287fbde825a252de2bf71d30dffb5) Signed-off-by: Sebastiaan van Stijn --- remotes/docker/resolver.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/remotes/docker/resolver.go b/remotes/docker/resolver.go index 96110a1887f5..3d6c0182f1b1 100644 --- a/remotes/docker/resolver.go +++ b/remotes/docker/resolver.go @@ -673,7 +673,7 @@ func requestFields(req *http.Request) log.Fields { } } - return log.Fields(fields) + return fields } func responseFields(resp *http.Response) log.Fields { @@ -691,7 +691,7 @@ func responseFields(resp *http.Response) log.Fields { } } - return log.Fields(fields) + return fields } // IsLocalhost checks if the registry host is local. From 6621e08887d94b90d3c9b3756acff02573cdc147 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 16 Jul 2023 21:17:05 +0200 Subject: [PATCH 02/12] log: remove testify dependency Testify was only used for a basic assertion. Remove the dependency, in preparation of (potentially) moving this package to a separate module. Signed-off-by: Sebastiaan van Stijn (cherry picked from commit 6fe7e03b80e1185ccf2e16c53420a1f2b9171ebd) Signed-off-by: Sebastiaan van Stijn --- log/context_test.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/log/context_test.go b/log/context_test.go index 718302c6fac7..c641aea6574a 100644 --- a/log/context_test.go +++ b/log/context_test.go @@ -18,15 +18,20 @@ package log import ( "context" + "reflect" "testing" - - "github.com/stretchr/testify/assert" ) func TestLoggerContext(t *testing.T) { + const expected = "one" ctx := context.Background() - - ctx = WithLogger(ctx, G(ctx).WithField("test", "one")) - assert.Equal(t, GetLogger(ctx).Data["test"], "one") - assert.Same(t, G(ctx), GetLogger(ctx)) // these should be the same. + ctx = WithLogger(ctx, G(ctx).WithField("test", expected)) + if actual := GetLogger(ctx).Data["test"]; actual != expected { + t.Errorf("expected: %v, got: %v", expected, actual) + } + a := G(ctx) + b := GetLogger(ctx) + if !reflect.DeepEqual(a, b) || a != b { + t.Errorf("should be the same: %+v, %+v", a, b) + } } From bfdce4ce4bc922ab4990a71f4a5f31a8e2c0224d Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 16 Jul 2023 21:58:38 +0200 Subject: [PATCH 03/12] log: SetFormat: include returns in switch Signed-off-by: Sebastiaan van Stijn (cherry picked from commit 40ee5fb11b852ff05d7e054465f8fa524874e8a2) Signed-off-by: Sebastiaan van Stijn --- log/context.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/log/context.go b/log/context.go index b63c602f424a..dbf967984914 100644 --- a/log/context.go +++ b/log/context.go @@ -89,15 +89,15 @@ func SetFormat(format string) error { TimestampFormat: RFC3339NanoFixed, FullTimestamp: true, }) + return nil case JSONFormat: logrus.SetFormatter(&logrus.JSONFormatter{ TimestampFormat: RFC3339NanoFixed, }) + return nil default: return fmt.Errorf("unknown log format: %s", format) } - - return nil } // WithLogger returns a new context with the provided logger. Use in From 7aa4f8fdccea58b2816fe7fe818653100cadfb98 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 16 Jul 2023 22:35:44 +0200 Subject: [PATCH 04/12] log: WithLogger: remove redundant intermediate var Signed-off-by: Sebastiaan van Stijn (cherry picked from commit 4a36022e204bae87a06d34e2ea9232e7eac43f32) Signed-off-by: Sebastiaan van Stijn --- log/context.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/log/context.go b/log/context.go index dbf967984914..ab9f501329c5 100644 --- a/log/context.go +++ b/log/context.go @@ -103,8 +103,7 @@ func SetFormat(format string) error { // WithLogger returns a new context with the provided logger. Use in // combination with logger.WithField(s) for great effect. func WithLogger(ctx context.Context, logger *logrus.Entry) context.Context { - e := logger.WithContext(ctx) - return context.WithValue(ctx, loggerKey{}, e) + return context.WithValue(ctx, loggerKey{}, logger.WithContext(ctx)) } // GetLogger retrieves the current logger from the context. If no logger is From e8e086e02bbcb078297302bc77a126647606c898 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 16 Jul 2023 22:07:33 +0200 Subject: [PATCH 05/12] log: group "enum" consts and touch-up docs Also updated the level descriptions with their documentation from logrus. Signed-off-by: Sebastiaan van Stijn (cherry picked from commit 0b6333a412cb79b8fcb718cdc82a29bfc45b708d) Signed-off-by: Sebastiaan van Stijn --- log/context.go | 63 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/log/context.go b/log/context.go index ab9f501329c5..7d45348b7769 100644 --- a/log/context.go +++ b/log/context.go @@ -34,38 +34,42 @@ var ( L = logrus.NewEntry(logrus.StandardLogger()) ) -type ( - loggerKey struct{} +type loggerKey struct{} - // Fields type to pass to `WithFields`, alias from `logrus`. - Fields = logrus.Fields +// Fields type to pass to "WithFields". +type Fields = logrus.Fields - // Level is a logging level - Level = logrus.Level -) - -const ( - // RFC3339NanoFixed is time.RFC3339Nano with nanoseconds padded using zeros to - // ensure the formatted time is always the same number of characters. - RFC3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00" +// RFC3339NanoFixed is [time.RFC3339Nano] with nanoseconds padded using +// zeros to ensure the formatted time is always the same number of +// characters. +const RFC3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00" - // TextFormat represents the text logging format - TextFormat = "text" +// Level is a logging level. +type Level = logrus.Level - // JSONFormat represents the JSON logging format - JSONFormat = "json" - - // TraceLevel level. - TraceLevel = logrus.TraceLevel +// Supported log levels. +const ( + // TraceLevel level. Designates finer-grained informational events + // than [DebugLevel]. + TraceLevel Level = logrus.TraceLevel - // DebugLevel level. - DebugLevel = logrus.DebugLevel + // DebugLevel level. Usually only enabled when debugging. Very verbose + // logging. + DebugLevel Level = logrus.DebugLevel - // InfoLevel level. - InfoLevel = logrus.InfoLevel + // InfoLevel level. General operational entries about what's going on + // inside the application. + InfoLevel Level = logrus.InfoLevel ) -// SetLevel sets log level globally. +// SetLevel sets log level globally. It returns an error if the given +// level is not supported. +// +// level can be one of: +// +// - "trace" ([TraceLevel]) +// - "debug" ([DebugLevel]) +// - "info" ([InfoLevel]) func SetLevel(level string) error { lvl, err := logrus.ParseLevel(level) if err != nil { @@ -81,7 +85,16 @@ func GetLevel() Level { return logrus.GetLevel() } -// SetFormat sets log output format +// Supported log output formats. +const ( + // TextFormat represents the text logging format. + TextFormat = "text" + + // JSONFormat represents the JSON logging format. + JSONFormat = "json" +) + +// SetFormat sets the log output format ([TextFormat] or [JSONFormat]). func SetFormat(format string) error { switch format { case TextFormat: From 93b6cb78456b642a5470b24e9ec1fca17ec12e49 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 30 Jul 2023 19:12:33 +0200 Subject: [PATCH 06/12] log: add all log-levels that are accepted While other log-levels are not currently used in containerd itself, they can be returned by `GetLevel()`, and are accepted (no error) by `SetLevel()`. We should either accept those values, or produce an error (in `SetLevel()`), but given that there's other ways to set the log-level, we should probably acknowledge that this package is a transitional package, and still closely tied to logrus (for the time being). Signed-off-by: Sebastiaan van Stijn (cherry picked from commit 81ac648d91ad5e42f9087c63be37e25e31b3da37) Signed-off-by: Sebastiaan van Stijn --- log/context.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/log/context.go b/log/context.go index 7d45348b7769..ee94d55e02d2 100644 --- a/log/context.go +++ b/log/context.go @@ -60,6 +60,21 @@ const ( // InfoLevel level. General operational entries about what's going on // inside the application. InfoLevel Level = logrus.InfoLevel + + // WarnLevel level. Non-critical entries that deserve eyes. + WarnLevel Level = logrus.WarnLevel + + // ErrorLevel level. Logs errors that should definitely be noted. + // Commonly used for hooks to send errors to an error tracking service. + ErrorLevel Level = logrus.ErrorLevel + + // FatalLevel level. Logs and then calls "logger.Exit(1)". It exits + // even if the logging level is set to Panic. + FatalLevel Level = logrus.FatalLevel + + // PanicLevel level. This is the highest level of severity. Logs and + // then calls panic with the message passed to Debug, Info, ... + PanicLevel Level = logrus.PanicLevel ) // SetLevel sets log level globally. It returns an error if the given @@ -70,6 +85,10 @@ const ( // - "trace" ([TraceLevel]) // - "debug" ([DebugLevel]) // - "info" ([InfoLevel]) +// - "warn" ([WarnLevel]) +// - "error" ([ErrorLevel]) +// - "fatal" ([FatalLevel]) +// - "panic" ([PanicLevel]) func SetLevel(level string) error { lvl, err := logrus.ParseLevel(level) if err != nil { From dbbe28b7d1cc6137ed9fff1bcd8ed5e3ec442059 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 30 Jul 2023 18:36:33 +0200 Subject: [PATCH 07/12] log: define G() as a function instead of a variable The `G` variable is exported, and not expected to be overwritten externally. Defining it as a function also documents it as a function on https://pkg.go.dev, instead of a variable; https://pkg.go.dev/github.com/containerd/containerd@v1.6.22/log#pkg-variables Note that (while the godoc suggests otherwise) I made `GetLogger` an alias for `G`, as `G` is the most commonly used function (not the other way round), although I don't think there's a performance gain in doing so. Signed-off-by: Sebastiaan van Stijn (cherry picked from commit 778ac302b27278b25bb2dabfc1cda99780cbc60b) Signed-off-by: Sebastiaan van Stijn --- log/context.go | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/log/context.go b/log/context.go index ee94d55e02d2..a6075a8ce6ce 100644 --- a/log/context.go +++ b/log/context.go @@ -23,16 +23,8 @@ import ( "github.com/sirupsen/logrus" ) -var ( - // G is an alias for GetLogger. - // - // We may want to define this locally to a package to get package tagged log - // messages. - G = GetLogger - - // L is an alias for the standard logger. - L = logrus.NewEntry(logrus.StandardLogger()) -) +// L is an alias for the standard logger. +var L = logrus.NewEntry(logrus.StandardLogger()) type loggerKey struct{} @@ -141,11 +133,13 @@ func WithLogger(ctx context.Context, logger *logrus.Entry) context.Context { // GetLogger retrieves the current logger from the context. If no logger is // available, the default logger is returned. func GetLogger(ctx context.Context) *logrus.Entry { - logger := ctx.Value(loggerKey{}) + return G(ctx) +} - if logger == nil { - return L.WithContext(ctx) +// G is a shorthand for [GetLogger]. +func G(ctx context.Context) *logrus.Entry { + if logger := ctx.Value(loggerKey{}); logger != nil { + return logger.(*logrus.Entry) } - - return logger.(*logrus.Entry) + return L.WithContext(ctx) } From 0a79e67e4f7bff1128c81ee14a8b2a74a8c55c51 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 16 Jul 2023 22:32:38 +0200 Subject: [PATCH 08/12] log: define OutputFormat type Strong-type the format. Signed-off-by: Sebastiaan van Stijn (cherry picked from commit dd67240f1b6c74148e21b35b6f143f6088e96f52) Signed-off-by: Sebastiaan van Stijn --- cmd/containerd/command/main.go | 2 +- log/context.go | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/cmd/containerd/command/main.go b/cmd/containerd/command/main.go index 922b54f8f091..3b8e9739ee78 100644 --- a/cmd/containerd/command/main.go +++ b/cmd/containerd/command/main.go @@ -357,7 +357,7 @@ func setLogLevel(context *cli.Context, config *srvconfig.Config) error { } func setLogFormat(config *srvconfig.Config) error { - f := config.Debug.Format + f := log.OutputFormat(config.Debug.Format) if f == "" { f = log.TextFormat } diff --git a/log/context.go b/log/context.go index a6075a8ce6ce..57aac5c7d7ba 100644 --- a/log/context.go +++ b/log/context.go @@ -96,17 +96,20 @@ func GetLevel() Level { return logrus.GetLevel() } +// OutputFormat specifies a log output format. +type OutputFormat string + // Supported log output formats. const ( // TextFormat represents the text logging format. - TextFormat = "text" + TextFormat OutputFormat = "text" // JSONFormat represents the JSON logging format. - JSONFormat = "json" + JSONFormat OutputFormat = "json" ) // SetFormat sets the log output format ([TextFormat] or [JSONFormat]). -func SetFormat(format string) error { +func SetFormat(format OutputFormat) error { switch format { case TextFormat: logrus.SetFormatter(&logrus.TextFormatter{ From 707ca94d890dbea1be767312483522a98f6c5969 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 30 Jul 2023 21:18:16 +0200 Subject: [PATCH 09/12] log: add log.Entry type Don't return logrus types from exported functions. Signed-off-by: Sebastiaan van Stijn (cherry picked from commit 634a4a1bbf9aa55330fa59feed4e2e66872ac5cf) Signed-off-by: Sebastiaan van Stijn --- log/context.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/log/context.go b/log/context.go index 57aac5c7d7ba..4767e934723b 100644 --- a/log/context.go +++ b/log/context.go @@ -31,6 +31,14 @@ type loggerKey struct{} // Fields type to pass to "WithFields". type Fields = logrus.Fields +// Entry is a logging entry. It contains all the fields passed with +// [Entry.WithFields]. It's finally logged when Trace, Debug, Info, Warn, +// Error, Fatal or Panic is called on it. These objects can be reused and +// passed around as much as you wish to avoid field duplication. +// +// Entry is a transitional type, and currently an alias for [logrus.Entry]. +type Entry = logrus.Entry + // RFC3339NanoFixed is [time.RFC3339Nano] with nanoseconds padded using // zeros to ensure the formatted time is always the same number of // characters. @@ -129,20 +137,20 @@ func SetFormat(format OutputFormat) error { // WithLogger returns a new context with the provided logger. Use in // combination with logger.WithField(s) for great effect. -func WithLogger(ctx context.Context, logger *logrus.Entry) context.Context { +func WithLogger(ctx context.Context, logger *Entry) context.Context { return context.WithValue(ctx, loggerKey{}, logger.WithContext(ctx)) } // GetLogger retrieves the current logger from the context. If no logger is // available, the default logger is returned. -func GetLogger(ctx context.Context) *logrus.Entry { +func GetLogger(ctx context.Context) *Entry { return G(ctx) } // G is a shorthand for [GetLogger]. -func G(ctx context.Context) *logrus.Entry { +func G(ctx context.Context) *Entry { if logger := ctx.Value(loggerKey{}); logger != nil { - return logger.(*logrus.Entry) + return logger.(*Entry) } return L.WithContext(ctx) } From 932795f4526ad4dd5d76e2d9b4c1daeaeab19172 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 30 Jul 2023 21:21:46 +0200 Subject: [PATCH 10/12] log: make Fields type a generic map[string]any Decouple it from logrus, but with the same type. Signed-off-by: Sebastiaan van Stijn (cherry picked from commit 238da2c525a9bbf3c8d09e153e1348d09ff0ecde) Signed-off-by: Sebastiaan van Stijn --- log/context.go | 2 +- log/context_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/log/context.go b/log/context.go index 4767e934723b..c3af052801fe 100644 --- a/log/context.go +++ b/log/context.go @@ -29,7 +29,7 @@ var L = logrus.NewEntry(logrus.StandardLogger()) type loggerKey struct{} // Fields type to pass to "WithFields". -type Fields = logrus.Fields +type Fields = map[string]any // Entry is a logging entry. It contains all the fields passed with // [Entry.WithFields]. It's finally logged when Trace, Debug, Info, Warn, diff --git a/log/context_test.go b/log/context_test.go index c641aea6574a..1b6d4a6cf7ab 100644 --- a/log/context_test.go +++ b/log/context_test.go @@ -20,6 +20,8 @@ import ( "context" "reflect" "testing" + + "github.com/sirupsen/logrus" ) func TestLoggerContext(t *testing.T) { @@ -35,3 +37,27 @@ func TestLoggerContext(t *testing.T) { t.Errorf("should be the same: %+v, %+v", a, b) } } + +func TestCompat(t *testing.T) { + expected := Fields{ + "hello1": "world1", + "hello2": "world2", + "hello3": "world3", + } + + l := G(context.TODO()) + l = l.WithFields(logrus.Fields{"hello1": "world1"}) + l = l.WithFields(Fields{"hello2": "world2"}) + l = l.WithFields(map[string]any{"hello3": "world3"}) + if !reflect.DeepEqual(Fields(l.Data), expected) { + t.Errorf("expected: (%[1]T) %+[1]v, got: (%[2]T) %+[2]v", expected, l.Data) + } + + l2 := L + l2 = l2.WithFields(logrus.Fields{"hello1": "world1"}) + l2 = l2.WithFields(Fields{"hello2": "world2"}) + l2 = l2.WithFields(map[string]any{"hello3": "world3"}) + if !reflect.DeepEqual(Fields(l2.Data), expected) { + t.Errorf("expected: (%[1]T) %+[1]v, got: (%[2]T) %+[2]v", expected, l2.Data) + } +} From 01445bb7386b98271b383b76e3d9007dabee03e8 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 30 Jul 2023 22:23:38 +0200 Subject: [PATCH 11/12] log: add package documentation and summary of package's purpose Add a package doc to (try to) describe the purpose of this package, and to describe the purpose (and expectations) of aliases provided by the package. > Package log provides types and functions related to logging, passing > loggers through a context, and attaching context to the logger. > > # Transitional types > > This package contains various types that are aliases for types in [logrus]. > These aliases are intended for transitioning away from hard-coding logrus > as logging implementation. Consumers of this package are encouraged to use > the type-aliases from this package instead of directly using their logrus > equivalent. > > The intent is to replace these aliases with locally defined types and > interfaces once all consumers are no longer directly importing logrus > types. > > IMPORTANT: due to the transitional purpose of this package, it is not > guaranteed for the full logrus API to be provided in the future. As > outlined, these aliases are provided as a step to transition away from > a specific implementation which, as a result, exposes the full logrus API. > While no decisions have been made on the ultimate design and interface > provided by this package, we do not expect carrying "less common" features. Signed-off-by: Sebastiaan van Stijn (cherry picked from commit 6baff1694fe79312b04555972dc0b0557c542fcf) Signed-off-by: Sebastiaan van Stijn --- log/context.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/log/context.go b/log/context.go index c3af052801fe..52687e28ca35 100644 --- a/log/context.go +++ b/log/context.go @@ -14,6 +14,27 @@ limitations under the License. */ +// Package log provides types and functions related to logging, passing +// loggers through a context, and attaching context to the logger. +// +// # Transitional types +// +// This package contains various types that are aliases for types in [logrus]. +// These aliases are intended for transitioning away from hard-coding logrus +// as logging implementation. Consumers of this package are encouraged to use +// the type-aliases from this package instead of directly using their logrus +// equivalent. +// +// The intent is to replace these aliases with locally defined types and +// interfaces once all consumers are no longer directly importing logrus +// types. +// +// IMPORTANT: due to the transitional purpose of this package, it is not +// guaranteed for the full logrus API to be provided in the future. As +// outlined, these aliases are provided as a step to transition away from +// a specific implementation which, as a result, exposes the full logrus API. +// While no decisions have been made on the ultimate design and interface +// provided by this package, we do not expect carrying "less common" features. package log import ( From 2a9ae3c51132080940d40343175e0d3eb2a111fc Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 30 Jul 2023 23:07:20 +0200 Subject: [PATCH 12/12] log: swap logrus functions with their equivalent on default logger [`logrus.SetLevel()`][1], [`logrus.GetLevel()`][2] and [`logrus.SetFormatter()`][3] are all convenience functions to configure logrus' standardlogger, which is the logger to which we hold a reference in the Entry configured on [`log.L`][4]. This patch: - swaps calls to `logrus.SetLevel`, `logrus.GetLevel` and `logrus.SetFormatter` for their equivalents on `log.L`. This makes it clearer what `SetLevel` does, and makes sure that we set the log-level of the logger / entry we define in our package (even if that would be swapped with a different instance). - removes the use of `logrus.NewEntry` with directly constructing a `Entry`, using the local `Entry` alias (anticipating we can swap that type in future). [1]: https://github.com/sirupsen/logrus/blob/dd1b4c2e81afc5c255f216a722b012ed26be57df/exported.go#L34C1-L37 [2]: https://github.com/sirupsen/logrus/blob/dd1b4c2e81afc5c255f216a722b012ed26be57df/exported.go#L39-L42 [3]: https://github.com/sirupsen/logrus/blob/dd1b4c2e81afc5c255f216a722b012ed26be57df/exported.go#L23-L26 [4]: https://github.com/sirupsen/logrus/blob/dd1b4c2e81afc5c255f216a722b012ed26be57df/exported.go#L9-L16 Signed-off-by: Sebastiaan van Stijn (cherry picked from commit 85a2c9a01bd82888e18990cdf63323892227556a) Signed-off-by: Sebastiaan van Stijn --- log/context.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/log/context.go b/log/context.go index 52687e28ca35..14ff2a59c57a 100644 --- a/log/context.go +++ b/log/context.go @@ -45,7 +45,11 @@ import ( ) // L is an alias for the standard logger. -var L = logrus.NewEntry(logrus.StandardLogger()) +var L = &Entry{ + Logger: logrus.StandardLogger(), + // Default is three fields plus a little extra room. + Data: make(Fields, 6), +} type loggerKey struct{} @@ -116,13 +120,13 @@ func SetLevel(level string) error { return err } - logrus.SetLevel(lvl) + L.Logger.SetLevel(lvl) return nil } // GetLevel returns the current log level. func GetLevel() Level { - return logrus.GetLevel() + return L.Logger.GetLevel() } // OutputFormat specifies a log output format. @@ -141,13 +145,13 @@ const ( func SetFormat(format OutputFormat) error { switch format { case TextFormat: - logrus.SetFormatter(&logrus.TextFormatter{ + L.Logger.SetFormatter(&logrus.TextFormatter{ TimestampFormat: RFC3339NanoFixed, FullTimestamp: true, }) return nil case JSONFormat: - logrus.SetFormatter(&logrus.JSONFormatter{ + L.Logger.SetFormatter(&logrus.JSONFormatter{ TimestampFormat: RFC3339NanoFixed, }) return nil