{
"group": {
"hidden": {},
"pi": 3.141592653589793
},
"level": "info",
"msg": "This is a message",
"time": "2025-02-16T01:41:19Z"
}
Verify:
Resolve Group With
{
"group": {
"hidden": {},
"pi": 3.141592653589793
},
"level": "info",
"msg": "This is a message",
"time": "2025-02-16T01:41:19Z"
}
Verify:
Resolve Valuer
{
"hidden": {},
"level": "info",
"msg": "This is a message",
"time": "2025-02-16T01:41:19Z"
}
Verify:
Resolve With
{
"hidden": {},
"level": "info",
"msg": "This is a message",
"time": "2025-02-16T01:41:19Z"
}
SlogTest
Failure of embedded slog/slogtest
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.
The slog.Record.PC field can be loaded with a program counter (PC).
This is normally done by the slog.Logger code.
If the PC is non-zero and the slog.HandlerOptions.AddSource flag is set
the source field will contain a slog.Source record
containing the function name, file name, and file line at which the log record was generated.
If the PC is zero then this field and its associated group should not be logged.
{
"level": "info",
"msg": "This is a message",
"time": "2025-02-16T01:41:19Z"
}
Implied
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.
Verify:
Replace Attr Basic
too many attributes: 4
time field still exists
msg field still exists
source ==
Verify:
Replace Attr Fn Level Case
level value not null
Verify:
Replace Attr Fn Multi
{
"group": {
"alpha": "OMEGA",
"pi": 3.141592653589793,
"subGroup": {
"e": 2.718281828459045,
"goober": "snoofus",
"la la la": "omega",
"oneMore": {
"alpha": "omega",
"gibbering": "moontic",
"phi": 1.618033988749895
}
}
},
"level": "info",
"msg": "This is a message",
"time": "2025-02-16T01:41:19Z"
}
Verify:
Replace Attr Fn Remove Empty Key
Verify:
Replace Attr Fn Remove Time
time value not empty string
SourceCaller
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.
Some handlers that change the way time.Duration objects are logged (see warnings DurationMillis and DurationSeconds)
only manage to make the change at the top level of the logged record, duration objects in groups are still in nanoseconds.
Verify:
Group Duration
29002.000000 != 29002000000000.000000
{
"group": {
"inner": 29002000000000
},
"level": "info",
"msg": "This is a message",
"outer": 29002,
"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:
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'
NoEmptyName
Attributes with empty names are not logged
Until documented otherwise, an attribute with an empty field name ("") and a non-nil value should be logged.
{
"first": "one",
"level": "info",
"msg": "This is a message",
"pi": 3.141592653589793,
"time": "2025-02-16T01:41:19Z"
}
Verify:
Attribute With Empty Name
{
"first": "one",
"level": "info",
"msg": "This is a message",
"pi": 3.141592653589793,
"time": "2025-02-16T01:41:19Z"
}
Verify:
Attributes Not Empty
{
"first": "one",
"level": "info",
"msg": "This is a message",
"pi": 3.141592653589793,
"time": "2025-02-16T01:41:19Z"
}
Verify:
Attributes With Not Empty
{
"first": "one",
"level": "info",
"msg": "This is a message",
"pi": 3.141592653589793,
"second": 2,
"time": "2025-02-16T01:41:19Z"
}
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.
Verify:
Log Attributes
2025-02-16T01:41:19Z
Administrative
Unused
Unused Warnings(s)
If a warning is specified but the condition is not actually present
one of these warnings will be issued with the specified warning.
These are intended to help clean out unnecessary WarnOnly settings
from a test suite as issues are fixed in the tested handler.