From 58a367276cfc99d6bbaf4a14e881976c2fc2e248 Mon Sep 17 00:00:00 2001 From: junya koyama Date: Sun, 4 Feb 2024 23:36:53 +0900 Subject: [PATCH] zapslog: fix handler state management problems. Signed-off-by: junya koyama --- exp/zapslog/handler.go | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/exp/zapslog/handler.go b/exp/zapslog/handler.go index 6445aca5f..6e6f491c1 100644 --- a/exp/zapslog/handler.go +++ b/exp/zapslog/handler.go @@ -26,6 +26,7 @@ import ( "context" "log/slog" "runtime" + "slices" "go.uber.org/zap" "go.uber.org/zap/internal/stacktrace" @@ -163,15 +164,19 @@ func (h *Handler) Handle(ctx context.Context, record slog.Record) error { } fields := make([]zapcore.Field, 0, record.NumAttrs()+1) + var addedNamespace bool record.Attrs(func(attr slog.Attr) bool { f := convertAttrToField(attr) - if h.holdGroup != "" && f != zap.Skip() { - fields = append(fields, zap.Namespace(h.holdGroup)) - h.holdGroup = "" + if !addedNamespace && f != zap.Skip() { + addedNamespace = true } fields = append(fields, f) return true }) + if h.holdGroup != "" && addedNamespace { + // group is before than other fields. + fields = slices.Insert(fields, 0, zap.Namespace(h.holdGroup)) + } ce.Write(fields...) return nil @@ -181,28 +186,41 @@ func (h *Handler) Handle(ctx context.Context, record slog.Record) error { // both the receiver's attributes and the arguments. func (h *Handler) WithAttrs(attrs []slog.Attr) slog.Handler { fields := make([]zapcore.Field, 0, len(attrs)+1) + var addedNamespace bool for _, attr := range attrs { f := convertAttrToField(attr) - if h.holdGroup != "" && f != zap.Skip() { - fields = append(fields, zap.Namespace(h.holdGroup)) - h.holdGroup = "" + if !addedNamespace && f != zap.Skip() { + addedNamespace = true } fields = append(fields, f) } + if h.holdGroup != "" && addedNamespace { + // group is before than other fields. + fields = slices.Insert(fields, 0, zap.Namespace(h.holdGroup)) + return h.withFieldsAndUpdateGroup("", fields...) + } 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 { - cloned := *h if h.holdGroup != "" { - cloned.core = h.core.With([]zapcore.Field{zap.Namespace(h.holdGroup)}) + return h.withFieldsAndUpdateGroup(group, zap.Namespace(h.holdGroup)) } + cloned := *h cloned.holdGroup = group return &cloned } +// withFieldsAndUpdateGroup returns a cloned Handler with the given fields and set new group. +func (h *Handler) withFieldsAndUpdateGroup(newGroup string, fields ...zapcore.Field) *Handler { + cloned := *h + cloned.core = h.core.With(fields) + cloned.holdGroup = newGroup + return &cloned +} + // withFields returns a cloned Handler with the given fields. func (h *Handler) withFields(fields ...zapcore.Field) *Handler { cloned := *h