diff --git a/src/log/slog/logger.go b/src/log/slog/logger.go index 10aa6a2b314..420cb5766bd 100644 --- a/src/log/slog/logger.go +++ b/src/log/slog/logger.go @@ -133,6 +133,16 @@ func (l *Logger) With(args ...any) *Logger { return c } +// WithAttrs is a more efficient version of [Logger.With] that accepts only Attrs. +func (l *Logger) WithAttrs(attrs ...Attr) *Logger { + if len(attrs) == 0 { + return l + } + c := l.clone() + c.handler = l.handler.WithAttrs(attrs) + return c +} + // WithGroup returns a Logger that starts a group, if name is non-empty. // The keys of all attributes added to the Logger will be qualified by the given // name. (How that qualification happens depends on the [Handler.WithGroup] @@ -161,6 +171,11 @@ func With(args ...any) *Logger { return Default().With(args...) } +// WithAttrs calls [Logger.WithAttrs] on the default logger. +func WithAttrs(attrs ...Attr) *Logger { + return Default().WithAttrs(attrs...) +} + // Enabled reports whether l emits log records at the given context and level. func (l *Logger) Enabled(ctx context.Context, level Level) bool { if ctx == nil { diff --git a/src/log/slog/logger_test.go b/src/log/slog/logger_test.go index bb1c8a16ea4..4903d8ee919 100644 --- a/src/log/slog/logger_test.go +++ b/src/log/slog/logger_test.go @@ -167,10 +167,11 @@ func TestAttrs(t *testing.T) { l1 := New(&captureHandler{}).With("a", 1) l2 := New(l1.Handler()).With("b", 2) - l2.Info("m", "c", 3) - h := l2.Handler().(*captureHandler) - check(h.attrs, Int("a", 1), Int("b", 2)) - check(attrsSlice(h.r), Int("c", 3)) + l3 := New(l2.Handler()).WithAttrs(Int("c", 3)) + l3.Info("m", "d", 4) + h := l3.Handler().(*captureHandler) + check(h.attrs, Int("a", 1), Int("b", 2), Int("c", 3)) + check(attrsSlice(h.r), Int("d", 4)) } func TestCallDepth(t *testing.T) {