Documentation on building a handler suggests testing using slog/slogtest, part of the Go release since 1.21.
While the verification suite includes tests patterned after those in slogtest,
an additional single test invokes the slogtest testing sequence (involving multiple tests).
Since this is a separate package, all error messages are returned at once.
This is the only warning that affects TestSlogTest and all of its error messages.
Log levels are actually numbers, with space between them for user-defined levels.
Handlers should properly handle numeric levels and math applied to level values.
Verify:
Default Level
INFO+1 is not enabled when WARN is set
Verify:
Default Level
INFO+1 is not enabled when WARN is set
Verify:
Level Configured
1 is not enabled when INFO is set
Verify:
Level Configured
1 is not enabled when INFO is set
Verify:
Level Different
5 is not enabled when WARN is set
Verify:
Level Different
5 is not enabled when WARN is set
Verify:
Level Var
INFO+1 is not enabled when INFO is set
Verify:
Level Var
5 is not enabled when WARN is enabled
NoReplAttr
HandlerOptions.ReplaceAttr not available
If HandlerOptions.ReplaceAttr
is provided it should be honored by the handler.
However, documentation on implementing handler methods seems to suggest it is optional.
too many attributes: 6, alpha == beta, change still exists, remove still exists
Verify:
Replace Attr Basic
too many attributes: 4
time field still exists
msg field still exists
source ==
Verify:
Replace Attr Fn Remove Empty Key
NoReplAttrBasic
HandlerOptions.ReplaceAttr not available for basic fields
Some handlers (e.g. phsym/zeroslog) support
HandlerOptions.ReplaceAttr
except for the four main fields time, level, msg, and source.
When that is the case it is better to use this (WarnNoReplAttrBasic) warning.
Source data logged as 'caller' instead of 'source'
Some handlers return source data as a single string on the caller field
in the format <file>:<line> where <file> and <line> correspond
to the File and Line fields of the source data group and Function is not provided.
{
"caller": "tests/benchmarks.go:96",
"level": "info",
"msg": "This is a message",
"time": "2025-02-16T01:36:56Z"
}
Verify:
Source Key
reflect/value.go:596
{
"caller": "reflect/value.go:596",
"level": "info",
"msg": "This is a message",
"time": "2025-02-16T01:41:19Z"
}
WithGroup
WithGroup doesn't embed following attributes into group
Complex log statements involving WithGroup require attributes to be attached to groups.
This warning represents situations where the attributes are attached to the wrong log group.
{
"first": "one",
"group": {},
"level": "info",
"msg": "This is a message",
"second": 2,
"third": "3",
"time": "2025-02-16T01:41:19Z"
}
Suggested
Duplicates
Duplicate field(s) found
Some handlers (e.g. slog.JSONHandler)
will output multiple occurrences of the same field name
if the logger is called with multiple instances of the same field,
generally by using WithAttrs and then the same fields in the eventual log call (e.g. Info).
This behavior is currently under debate
with no resolution at this time (2024-01-15) and a
release milestone of (currently unscheduled) Go 1.23,
(whereas Go Release 1.22
is currently expected in February 2024).
Verify:
Attribute Duplicate
map[alpha:2 charlie:3]
Verify:
Attribute With Duplicate
map[alpha:2 charlie:3]
DurationSeconds
slog.Duration() logs seconds instead of nanoseconds
The slog.JSONHandler uses nanoseconds for time.Duration but some other handlers use seconds.
^WithGroup().With()^ ends up at top level of log record instead of in the group
Almost all handlers treat logger.WithGroup(<name>).With(<attrs>) as writing <attrs> to the group <name>.
Some handlers write <attrs> to the top level of the log record.
Verify:
Group With Top
{
"group": {},
"key": "value",
"level": "info",
"msg": "This is a message",
"time": "2025-02-16T01:41:19Z"
}
LevelCase
Log level in lowercase
Each JSON log record contains the logging level of the log statement as a string.
Different handlers provide that string in uppercase or lowercase.
Documentation for slog.Level
says that its String() and MarshalJSON() methods will return uppercase
but UnmarshalJSON() will parse in a case-insensitive manner.
Verify:
Canceled Context
'info'
Verify:
Canceled Context
'info'
Verify:
Key Case
'debug'
Verify:
Key Case
'info'
Verify:
Key Case
'warn'
Verify:
Key Case
'error'
Verify:
Keys
'info'
Verify:
Source Key
'info'
Verify:
Zero PC
'info'
Verify:
Zero Time
'info'
TimeMillis
slog.Time() logs milliseconds instead of nanoseconds
The slog.JSONHandler uses nanoseconds for time.Time but some other handlers use milliseconds.
This does not apply to the basic time field, only attribute fields.
I can't find any supporting documentation or bug on this but
Go issue 59345 (see previous warning)
may have fixed this as well in Go 1.21.