A Go linter that ensures consistent code style when using log/slog.
sloglint is part of golangci-lint, and this is the recommended way to use it.
# .golangci.yaml
linters:
enable:
- sloglintAlternatively, you can download a prebuilt binary from the Releases page to use sloglint standalone.
For log/slog functions:
For log messages:
For log arguments:
For log keys:
The checks for log messages, arguments, and keys can also be used to analyze custom functions.
Report the use of global loggers.
Alternatively, only report the use of the slog.Default() logger.
slog.Info("a user has logged in")
// sloglint: global logger should not be used# .golangci.yaml
linters:
settings:
sloglint:
no-global: "all" # Or "default".Report the use of functions without a context.Context.
Alternatively, only report their use if a context exists within the scope of the outermost function.
slog.Info("a user has logged in")
// sloglint: InfoContext should be used instead# .golangci.yaml
linters:
settings:
sloglint:
context: "all" # Or "scope".This check partially supports autofix.
Suggest using slog.DiscardHandler when possible.
slog.NewJSONHandler(io.Discard, nil)
// sloglint: use slog.DiscardHandler insteadThis check is enabled by default and supports autofix.
Report dynamic log messages, such as those that are built with fmt.Sprintf.
slog.Info(fmt.Sprintf("a user with id %d has logged in", 42))
// sloglint: message should be a string literal or a constant# .golangci.yaml
linters:
settings:
sloglint:
static-msg: trueReport log messages that do not match a particular style.
The supported styles are lowercased (the first letter is lowercase) and capitalized (the first letter is uppercase).
slog.Info("A user has logged in")
// sloglint: message should be lowercased# .golangci.yaml
linters:
settings:
sloglint:
msg-style: "lowercased" # Or "capitalized".Report the use of both key-value pairs and attributes within a single function call.
slog.Info("a user has logged in", "user_id", 42, slog.String("ip_address", "192.0.2.0"))
// sloglint: key-value pairs and attributes should not be mixedThis check is enabled by default.
Report any use of attributes as function call arguments.
slog.Info("a user has logged in", slog.Int("user_id", 42))
// sloglint: attributes should not be used# .golangci.yaml
linters:
settings:
sloglint:
kv-only: trueReport any use of key-value pairs as function call arguments.
slog.Info("a user has logged in", "user_id", 42)
// sloglint: key-value pairs should not be used# .golangci.yaml
linters:
settings:
sloglint:
attr-only: trueReport two or more arguments on the same line. A key-value pair is considered a single argument.
slog.Info("a user has logged in", "user_id", 42, "ip_address", "192.0.2.0")
// sloglint: arguments should be put on separate lines# .golangci.yaml
linters:
settings:
sloglint:
args-on-sep-lines: trueReport the use of string literals as log keys.
slog.Info("a user has logged in", "user_id", 42)
// sloglint: the "user_id" key should be a constant# .golangci.yaml
linters:
settings:
sloglint:
no-raw-keys: trueReport the use of log keys that are not explicitly allowed.
slog.Info("a user has logged in", "id", 42)
// sloglint: the "id" key is not allowed and should not be used# .golangci.yaml
linters:
settings:
sloglint:
allowed-keys:
- user_idReport the use of forbidden log keys.
When using the standard slog.JSONHandler or slog.TextHandler,
you may want to forbid the time, level, msg, and source keys,
as these will be written by the handler.
slog.Info("a user has logged in", "time", time.Now())
// sloglint: the "time" key is forbidden and should not be used# .golangci.yaml
linters:
settings:
sloglint:
forbidden-keys:
- time
- level
- msg
- sourceReport log keys that do not match a particular naming case.
The supported cases are snake_case, kebab-case, camelCase, and PascalCase.
slog.Info("a user has logged in", "user-id", 42)
// sloglint: keys should be written in snake_case# .golangci.yaml
linters:
settings:
sloglint:
key-naming-case: "snake" # Or "kebab", "camel", "pascal".This check supports autofix.
Analyze custom functions in addition to the standard log/slog functions.
The following function properties must be specified:
- The full name of the function, including the package, e.g.
log/slog.Info. If the function is a method, the receiver type must be wrapped in parentheses, e.g.(*log/slog.Logger).Info. - The position of the
msg stringargument in the function signature, starting from 0. If there is no message in the function, a negative value must be passed. - The position of the
args ...anyargument in the function signature, starting from 0. If there are no arguments in the function, a negative value must be passed.
Here's an example for the exp/slog package, the predecessor of log/slog.
# .golangci.yaml
linters:
settings:
sloglint:
custom-funcs:
- name: "(*golang.org/x/exp/slog.Logger).InfoContext"
msg-pos: 1
args-pos: 2