Skip to content

Commit f72693d

Browse files
panjf2000jba
authored andcommitted
log/slog: generate valid JSON string with empty attributes in Groups
Fixes #62152 Change-Id: I1f76ab26eae3a44292ebe6003006258d5e31d50f Reviewed-on: https://go-review.googlesource.com/c/go/+/521135 Reviewed-by: Heschi Kreinick <[email protected]> Run-TryBot: Andy Pan <[email protected]> Reviewed-by: Jonathan Amsterdam <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 94f24fd commit f72693d

File tree

2 files changed

+65
-3
lines changed

2 files changed

+65
-3
lines changed

src/log/slog/handler.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,11 @@ func (h *commonHandler) withAttrs(as []Attr) *commonHandler {
233233
state := h2.newHandleState((*buffer.Buffer)(&h2.preformattedAttrs), false, "")
234234
defer state.free()
235235
state.prefix.WriteString(h.groupPrefix)
236-
if len(h2.preformattedAttrs) > 0 {
236+
if pfa := h2.preformattedAttrs; len(pfa) > 0 {
237237
state.sep = h.attrSep()
238+
if h2.json && pfa[len(pfa)-1] == '{' {
239+
state.sep = ""
240+
}
238241
}
239242
state.openGroups()
240243
for _, a := range as {
@@ -310,10 +313,13 @@ func (h *commonHandler) handle(r Record) error {
310313

311314
func (s *handleState) appendNonBuiltIns(r Record) {
312315
// preformatted Attrs
313-
if len(s.h.preformattedAttrs) > 0 {
316+
if pfa := s.h.preformattedAttrs; len(pfa) > 0 {
314317
s.buf.WriteString(s.sep)
315-
s.buf.Write(s.h.preformattedAttrs)
318+
s.buf.Write(pfa)
316319
s.sep = s.h.attrSep()
320+
if s.h.json && pfa[len(pfa)-1] == '{' {
321+
s.sep = ""
322+
}
317323
}
318324
// Attrs in Record -- unlike the built-in ones, they are in groups started
319325
// from WithGroup.

src/log/slog/handler_test.go

+56
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,62 @@ func TestJSONAndTextHandlers(t *testing.T) {
435435
wantText: `time.mins=3 time.secs=2 msg=message`,
436436
wantJSON: `{"time":{"mins":3,"secs":2},"msg":"message"}`,
437437
},
438+
{
439+
name: "replace empty 1",
440+
with: func(h Handler) Handler {
441+
return h.WithGroup("g").WithAttrs([]Attr{Int("a", 1)})
442+
},
443+
replace: func([]string, Attr) Attr { return Attr{} },
444+
attrs: []Attr{Group("h", Int("b", 2))},
445+
wantText: "",
446+
wantJSON: `{"g":{"h":{}}}`,
447+
},
448+
{
449+
name: "replace empty 2",
450+
with: func(h Handler) Handler {
451+
return h.WithGroup("g").WithAttrs([]Attr{Int("a", 1)}).WithGroup("h").WithAttrs([]Attr{Int("b", 2)})
452+
},
453+
replace: func([]string, Attr) Attr { return Attr{} },
454+
attrs: []Attr{Group("i", Int("c", 3))},
455+
wantText: "",
456+
wantJSON: `{"g":{"h":{"i":{}}}}`,
457+
},
458+
{
459+
name: "replace partial empty attrs 1",
460+
with: func(h Handler) Handler {
461+
return h.WithGroup("g").WithAttrs([]Attr{Int("a", 1)}).WithGroup("h").WithAttrs([]Attr{Int("b", 2)})
462+
},
463+
replace: func(groups []string, attr Attr) Attr {
464+
return removeKeys(TimeKey, LevelKey, MessageKey, "a")(groups, attr)
465+
},
466+
attrs: []Attr{Group("i", Int("c", 3))},
467+
wantText: "g.h.b=2 g.h.i.c=3",
468+
wantJSON: `{"g":{"h":{"b":2,"i":{"c":3}}}}`,
469+
},
470+
{
471+
name: "replace partial empty attrs 2",
472+
with: func(h Handler) Handler {
473+
return h.WithGroup("g").WithAttrs([]Attr{Int("a", 1)}).WithAttrs([]Attr{Int("n", 4)}).WithGroup("h").WithAttrs([]Attr{Int("b", 2)})
474+
},
475+
replace: func(groups []string, attr Attr) Attr {
476+
return removeKeys(TimeKey, LevelKey, MessageKey, "a", "b")(groups, attr)
477+
},
478+
attrs: []Attr{Group("i", Int("c", 3))},
479+
wantText: "g.n=4 g.h.i.c=3",
480+
wantJSON: `{"g":{"n":4,"h":{"i":{"c":3}}}}`,
481+
},
482+
{
483+
name: "replace partial empty attrs 3",
484+
with: func(h Handler) Handler {
485+
return h.WithGroup("g").WithAttrs([]Attr{Int("x", 0)}).WithAttrs([]Attr{Int("a", 1)}).WithAttrs([]Attr{Int("n", 4)}).WithGroup("h").WithAttrs([]Attr{Int("b", 2)})
486+
},
487+
replace: func(groups []string, attr Attr) Attr {
488+
return removeKeys(TimeKey, LevelKey, MessageKey, "a", "c")(groups, attr)
489+
},
490+
attrs: []Attr{Group("i", Int("c", 3))},
491+
wantText: "g.x=0 g.n=4 g.h.b=2",
492+
wantJSON: `{"g":{"x":0,"n":4,"h":{"b":2,"i":{}}}}`,
493+
},
438494
} {
439495
r := NewRecord(testTime, LevelInfo, "message", callerPC(2))
440496
line := strconv.Itoa(r.source().Line)

0 commit comments

Comments
 (0)