Every handler in this package accepts slog attributes and then throws
them away: Handle never reads record.Attrs, and WithAttrs and WithGroup
return the receiver unchanged in ConsoleHandler, JSONHandler and
WebhookHandler alike. So slog.Info("casting", "device", d, "file", f)
emits the message and silently loses both fields, which makes properly
structured logging carry less information than the interpolated
log.Printf calls it replaces.
The test asserts on the bytes the handlers actually write - os.Stdout
for the console and JSON handlers, the posted body for the webhook
handler - rather than on internal state, because the output is where the
loss is observable. It covers record attributes, WithAttrs accumulation,
WithAttrs not mutating its receiver so sibling loggers cannot leak
attributes into each other, WithGroup qualification, slog.Group nesting,
and LogValuer resolution, for each handler and through MultiplexHandler.
It also pins the properties a fix must not get wrong on the way past. A
value the caller logged is read and never written to, even when a group
later claims the same key - for maps and for slices, through the record
path and the derived-logger path, in all three handlers. A duration is
a number of nanoseconds in the json payload and the readable "3s" form
on the console. The four slog.Handler contract edge cases hold: an empty
Attr is ignored, an empty group is elided with its key, a group with an
empty key is inlined, and WithGroup("") is a no-op. And the two rules
that follow from the json payload being an object hold too: the record's
own field names win a collision, and a repeated key keeps its last
value, where the console line keeps both.
This commit adds only the test, and it fails. The fix follows.
Refs: #19
24 KiB
24 KiB