From e6a47349a385f8d817c449a029d7205b74c4da23 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 14 Aug 2026 10:43:43 +0200 Subject: [PATCH] log: allow SetLevel to accept Level values Make SetLevel generic so callers can pass either a string or a Level directly. Keep the existing string parsing behavior and global logger level synchronization unchanged. Signed-off-by: Sebastiaan van Stijn --- context.go | 31 +++++++++++++++++------ context_test.go | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 7 deletions(-) diff --git a/context.go b/context.go index 3b1ca86..b573b42 100644 --- a/context.go +++ b/context.go @@ -109,10 +109,16 @@ const ( PanicLevel Level = logrus.PanicLevel ) -// SetLevel sets log level globally. It returns an error if the given -// level is not supported. +// levelValue is a log level accepted by [SetLevel]. +type levelValue interface { + string | Level +} + +// SetLevel sets the global log level. +// +// The level may be specified as a string or a [Level]. // -// level can be one of: +// String levels are parsed using [logrus.ParseLevel] and may be one of: // // - "trace" ([TraceLevel]) // - "debug" ([DebugLevel]) @@ -121,10 +127,21 @@ const ( // - "error" ([ErrorLevel]) // - "fatal" ([FatalLevel]) // - "panic" ([PanicLevel]) -func SetLevel(level string) error { - lvl, err := logrus.ParseLevel(level) - if err != nil { - return err +// +// SetLevel returns an error if a string level is not supported. +func SetLevel[T levelValue](level T) error { + var lvl Level + + switch l := any(level).(type) { + case string: + var err error + lvl, err = logrus.ParseLevel(l) + if err != nil { + return err + } + + case Level: + lvl = l } L.Logger.SetLevel(lvl) diff --git a/context_test.go b/context_test.go index 1b6d4a6..62e0c76 100644 --- a/context_test.go +++ b/context_test.go @@ -61,3 +61,69 @@ func TestCompat(t *testing.T) { t.Errorf("expected: (%[1]T) %+[1]v, got: (%[2]T) %+[2]v", expected, l2.Data) } } + +func TestSetLevel(t *testing.T) { + oldLevel := L.Logger.GetLevel() + t.Cleanup(func() { + L.Logger.SetLevel(oldLevel) + }) + + tests := []struct { + str string + level Level + }{ + { + str: "trace", + level: TraceLevel, + }, + { + str: "debug", + level: DebugLevel, + }, + { + str: "info", + level: InfoLevel, + }, + { + str: "warn", + level: WarnLevel, + }, + { + str: "error", + level: ErrorLevel, + }, + { + str: "fatal", + level: FatalLevel, + }, + { + str: "panic", + level: PanicLevel, + }, + } + + for _, tc := range tests { + t.Run(tc.str, func(t *testing.T) { + inputs := []struct { + doc string + set func() error + }{ + {doc: "string", set: func() error { return SetLevel(tc.str) }}, + {doc: "Level", set: func() error { return SetLevel(tc.level) }}, + } + + for _, input := range inputs { + t.Run(input.doc, func(t *testing.T) { + L.Logger.SetLevel(InfoLevel) + + if err := input.set(); err != nil { + t.Fatal(err) + } + if got := L.Logger.GetLevel(); got != tc.level { + t.Fatalf("got %v, want %v", got, tc.level) + } + }) + } + }) + } +}