Home

Warnings

Handlers
Bench Tests
Verify Tests
Required

Warnings that can be justified from requirements in the slog.Handler documentation.

EmptyAttributes Empty attribute(s) logged ("":null)

Handlers are supposed to avoid logging empty attributes.

GroupEmpty Empty (sub)group(s) logged

Handlers should not log groups (or subgroups) without fields, whether or not they have non-empty names.

GroupInline Group with empty key does not inline subfields

Handlers should expand groups named "" (the empty string) into the enclosing log record.

LevelVar Unable to change level during execution via LevelVar

Slog handlers can use LevelVar to specify the handler logging level. Unlike specifying a Level (which is actually an int), a LevelVar is supposed to be changeable during program execution.

Mismatch Logged record does not match expected

During benchmark testing the test is run once to see if the logged record matches expectations.

NotDisabled Logging was not properly disabled

During benchmark testing a Debug log line is made with the current level set to Info. This warning is thrown if there is any logged output.

Resolver LogValuer objects are not resolved

Handlers should resolve all objects implementing the LogValuer or Stringer interfaces. This is a powerful feature which can customize logging of objects and speed up logging by delaying argument resolution until logging time.

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.

WithGroupEmpty Empty WithGroup() logged

Handlers should not log WithGroup() groups with no fields, whether or not they have non-empty names.

ZeroPC SourceKey logged for zero PC

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.

ZeroTime Zero time is logged

Handlers should not log the basic time field if it is zero.

Implied

Warnings that seem to be implied by documentation but can't be considered required.

CanceledContext Canceled context blocks logging

"The context is provided to support applications that provide logging information along the call chain. In a break with usual Go practice, the Handle method should not treat a canceled context as a signal to stop work."

DefaultLevel Handler doesn't default to slog.LevelInfo

A new slog.Handler should default to slog.LevelInfo.

GroupAttrInfoTop Group-Attr-Info attributes end up at the top level.

Log records generated by:

    WithGroup('group1').Attr(attrs1...).Info(msg, attrs2...)

should have attrs2 within the group group1 (along with attrs1). The current handler places attrs2 at the top level. The preceding example applies to all of the "message" methods (e.g. Error(), Debug()). This sequence is verify specific, neither attrs1 and attrs2 can be empty or missing.

LevelMath Log levels are not properly treated as integers

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.

MessageKey Wrong message key (should be 'msg')

The field name of the "message" key should be msg.

NoEmptyName Attributes with empty names are not logged

Until documented otherwise, an attribute with an empty field name ("") should be logged.

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.

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.

ReplAttrGroup ReplaceAttr groups argument usage results in an error

A ReplaceAttribute function has two arguments: an array of strings representing group names and an attribute. The TestReplaceAttrGroup test checks to see if group names are properly passed. This test may fail due to unrelated causes that show up as warnings for other tests.

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.

SourceKey Source data not logged when AddSource flag set

Handlers should log source data when the slog.HandlerOptions.AddSource flag is set.

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.

Suggested

Warnings not mandated by any documentation or requirements.

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).

DurationMillis slog.Duration() logs milliseconds instead of nanoseconds

The slog.JSONHandler uses nanoseconds for time.Duration but some other handlers use seconds.

DurationSeconds slog.Duration() logs seconds instead of nanoseconds

The slog.JSONHandler uses nanoseconds for time.Duration but some other handlers use seconds.

DurationString slog.Duration() logs a string representation instead of nanoseconds

The slog.JSONHandler uses nanoseconds for time.Duration but some other handlers use a string representation.

GroupDuration

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.

GroupWithTop ^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.

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.

LevelWrong Log level is incorrect

The log level name is not what was expected (e.g. "WARNING" instead of "WARN"). This is different from the LevelCase warning which is from the right level name but the wrong character case.

StringAny map[string]any converted to strings in log records

The slog.JSONHandler converts Any objects that are map[string]any into JSON maps. Some handlers convert these Any objects into strings instead of maps.

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.

TimeSeconds slog.Time() logs seconds instead of nanoseconds

The slog.JSONHandler uses nanoseconds for time.Time but some other handlers use seconds. 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.

Administrative

Warnings that provide information about the tests or conflicts with other warnings.

NoHandlerCreation Test depends on unavailable handler creation

Some benchmark tests depend on access to a slog.Handler object. Some slog implementations create a slog.Logger but no slog.Handler. In this case the relevant benchmark tests can't be run.

SkippingTest Skipping test

A test has been skipped, likely due to the specification of some other warning.

TestError Test harness error

Some sort of error has occurred during testing. This will generally require a programming fix.

Undefined Undefined Warnings(s)

An attempt to call WarnOnly with an undefined warning. Warnings must be predefined to the Manager prior to use.

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.


Warnings vs. Handlers

chanchal/zaphandler
madkins/flash
madkins/replattr
madkins/sloggy
phsym/zeroslog
phuslu/slog
samber/slog-logrus
samber/slog-zap
samber/slog-zerolog
slog/JSONHandler
svcrunner/jsonlog
Required
EmptyAttributes 3 3 3 3
GroupEmpty 1
GroupInline 1 1 1 1
LevelVar 1
Mismatch
NotDisabled
Resolver 4 4 4
SlogTest 1 1 1 1 1 1
WithGroupEmpty 1 1
ZeroPC 1 1 1
ZeroTime 1 1 1 1
Implied
CanceledContext 1
DefaultLevel 2
GroupAttrInfoTop
LevelMath 8
MessageKey 7 7 7
NoEmptyName 4
NoReplAttr 3 7 7
NoReplAttrBasic 3 5 5 6
ReplAttrGroup
SourceCaller 2 2 2
SourceKey 2
WithGroup 2
Suggested
Duplicates 2 2 2 2 2 2 2 2
DurationMillis 1 1
DurationSeconds 1 1
DurationString 2
GroupDuration 1 1
GroupWithTop 1
LevelCase 10 11 10 11 11
LevelWrong 1
StringAny
TimeMillis 1 1 1 1
TimeSeconds
Administrative
NoHandlerCreation
SkippingTest
TestError
Undefined
Unused