1
0
Fork 0
mirror of https://github.com/chainguard-dev/clog synced 2026-07-06 22:12:46 +00:00

Wrap context-aware handlers + values around loggers by default. (#31)

Previously, we didn't allowed you to provide any handler you wanted,
which didn't quite meet expectations for using clog. This changes the
behavior to always wrap the logger with a context handler.

Additionally, when a new logger is created any values present in the
context are added to the logger, which should allow the values to be
preserved even if the default slog funcs are used.
This commit is contained in:
Billy Lynch 2025-01-24 10:21:37 -05:00 committed by GitHub
parent 71baa290ad
commit 7b8abfef8a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 59 additions and 5 deletions

View file

@ -17,7 +17,7 @@ type Logger struct {
// DefaultLogger returns a new logger that uses the default [slog.Logger].
func DefaultLogger() *Logger {
return NewLogger(slog.Default())
return NewLogger(nil)
}
// NewLogger returns a new logger that wraps the given [slog.Logger] with the default context.
@ -28,7 +28,11 @@ func NewLogger(l *slog.Logger) *Logger {
// NewLoggerWithContext returns a new logger that wraps the given [slog.Logger].
func NewLoggerWithContext(ctx context.Context, l *slog.Logger) *Logger {
if l == nil {
l = slog.Default()
l = slog.New(NewHandler(slog.Default().Handler()))
}
// Attach any existing context values onto the logger.
for k, v := range get(ctx) {
l = l.With(k, v)
}
return &Logger{
ctx: ctx,
@ -38,12 +42,12 @@ func NewLoggerWithContext(ctx context.Context, l *slog.Logger) *Logger {
// New returns a new logger that wraps the given [slog.Handler].
func New(h slog.Handler) *Logger {
return NewLogger(slog.New(h))
return NewWithContext(context.Background(), h)
}
// New returns a new logger that wraps the given [slog.Handler].
func NewWithContext(ctx context.Context, h slog.Handler) *Logger {
return NewLoggerWithContext(ctx, slog.New(h))
return NewLoggerWithContext(ctx, slog.New(NewHandler(h)))
}
// With calls [Logger.With] on the default logger.
@ -180,5 +184,5 @@ func FromContext(ctx context.Context) *Logger {
Logger: logger,
}
}
return NewLoggerWithContext(ctx, slog.Default())
return NewLoggerWithContext(ctx, nil)
}

View file

@ -126,3 +126,53 @@ func TestWith(t *testing.T) {
t.Errorf("want %v, got %v", want, ctx)
}
}
func TestDefaultHandler(t *testing.T) {
old := slog.Default()
defer func() {
slog.SetDefault(old)
}()
b := new(bytes.Buffer)
slog.SetDefault(slog.New(slog.NewJSONHandler(b, testopts)))
t.Run("Info", func(t *testing.T) {
FromContext(WithValues(context.Background(), "a", "b")).Info("")
want := map[string]any{
"level": "INFO",
"msg": "",
"a": "b",
}
var got map[string]any
if err := json.Unmarshal(b.Bytes(), &got); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(want, got) {
t.Errorf("want %v, got %v", want, got)
}
})
b.Reset()
t.Run("InfoContext", func(t *testing.T) {
// Set logger with original value
ctx := WithValues(context.Background(), "a", "b")
logger := FromContext(ctx)
// Override value in request context - we expect this to overwrite the original value set in the logger
logger.InfoContext(WithValues(ctx, "a", "c"), "")
want := map[string]any{
"level": "INFO",
"msg": "",
"a": "c",
}
var got map[string]any
if err := json.Unmarshal(b.Bytes(), &got); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(want, got) {
t.Errorf("want %v, got %v", want, got)
}
})
}