Skip to content

Commit

Permalink
zapslog: Ignore groups if empty Record uber-go#1401
Browse files Browse the repository at this point in the history
Signed-off-by: junya koyama <arukiidou@yahoo.co.jp>
  • Loading branch information
arukiidou committed Feb 2, 2024
1 parent e575540 commit 28b05cb
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 4 deletions.
26 changes: 22 additions & 4 deletions exp/zapslog/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"context"
"log/slog"
"runtime"
"slices"

"go.uber.org/zap"
"go.uber.org/zap/internal/stacktrace"
Expand All @@ -39,6 +40,7 @@ type Handler struct {
addCaller bool
addStackAt slog.Level
callerSkip int
holdGroup string // holds latest group.
}

// NewHandler builds a [Handler] that writes to the supplied [zapcore.Core]
Expand Down Expand Up @@ -161,11 +163,17 @@ func (h *Handler) Handle(ctx context.Context, record slog.Record) error {
ce.Stack = stacktrace.Take(3 + h.callerSkip)
}

fields := make([]zapcore.Field, 0, record.NumAttrs())
fields := make([]zapcore.Field, 0, record.NumAttrs()+1)
record.Attrs(func(attr slog.Attr) bool {
fields = append(fields, convertAttrToField(attr))
f := convertAttrToField(attr)
if h.holdGroup != "" && f != zap.Skip() {
fields = slices.Insert(fields, 0, zap.Namespace(h.holdGroup))
h.holdGroup = ""
}
fields = append(fields, f)
return true
})

ce.Write(fields...)
return nil
}
Expand All @@ -175,15 +183,25 @@ func (h *Handler) Handle(ctx context.Context, record slog.Record) error {
func (h *Handler) WithAttrs(attrs []slog.Attr) slog.Handler {
fields := make([]zapcore.Field, 0, len(attrs))
for _, attr := range attrs {
fields = append(fields, convertAttrToField(attr))
f := convertAttrToField(attr)
if h.holdGroup != "" && f != zap.Skip() {
fields = slices.Insert(fields, 0, zap.Namespace(h.holdGroup))
h.holdGroup = ""
}
fields = append(fields, f)
}
return h.withFields(fields...)
}

// WithGroup returns a new Handler with the given group appended to
// the receiver's existing groups.
func (h *Handler) WithGroup(group string) slog.Handler {
return h.withFields(zap.Namespace(group))
cloned := *h
if h.holdGroup != "" {
cloned.core = h.core.With([]zapcore.Field{zap.Namespace(group)})
}
cloned.holdGroup = group
return &cloned
}

// withFields returns a cloned Handler with the given fields.
Expand Down
30 changes: 30 additions & 0 deletions exp/zapslog/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,36 @@ func TestInlineGroup(t *testing.T) {
})
}

func TestWithGroup(t *testing.T) {
t.Parallel()
fac, observedLogs := observer.New(zapcore.DebugLevel)
t.Run("empty-group-record", func(t *testing.T) {
sl := slog.New(NewHandler(fac))
sl.With("a", "b").WithGroup("G").With("c", "d").WithGroup("H").Info("msg")

logs := observedLogs.TakeAll()
require.Len(t, logs, 1, "Expected exactly one entry to be logged")
entry := logs[0]
assert.Equal(t, "", entry.LoggerName, "Unexpected logger name")
assert.Equal(t, map[string]any{
"G": map[string]any{
"c": "d",
},
"a": "b",
}, logs[0].ContextMap(), "Unexpected context")
})
t.Run("only-records-to-ignore", func(t *testing.T) {
sl := slog.New(NewHandler(fac))
sl.WithGroup("H").With(slog.Attr{}).Info("msg")

logs := observedLogs.TakeAll()
require.Len(t, logs, 1, "Expected exactly one entry to be logged")
entry := logs[0]
assert.Equal(t, "", entry.LoggerName, "Unexpected logger name")
assert.Equal(t, map[string]any{}, logs[0].ContextMap(), "Unexpected context")
})
}

type Token string

func (Token) LogValue() slog.Value {
Expand Down

0 comments on commit 28b05cb

Please sign in to comment.