-
Notifications
You must be signed in to change notification settings - Fork 18k
log/slog: Custom Handler breaks when using With() and loses parent attributes #71116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
CC @jba. |
Logger.With should call Handler.WithAttrs. It's doing that for TestHandler, but since TestHandler embeds another handler, it's the embedded handler's WithAttr method that's getting called. In other words, it's Go's embedding rule that is doing the bypassing here, not anything in slog. Some suggestions before writing your own handler:
|
One more thing: I would avoid embedding when writing a middleware handler; it is too confusing (as you've seen). Instead put the handler in a named field:
and call it when you want to delegate to it. |
Amazing! Thank you, @jba, for the quick answer! You are right. I got myself confused with this. I've applied your recommendation for my case which fixed my problem. |
I've just hit the same wall in #73057: #73057 (comment) |
Go version
go1.23.3 darwin/arm64
Output of
go env
in your module/workspace:What did you do?
When implementing a custom
slog.Handler
, the middleware pattern breaks in two significant ways. First, callingWith()
on a logger completely bypasses any custom Handle implementation, falling back to only the wrapped handler. This means any middleware logic in custom handlers stops working as soon as attributes are added viaWith()
.Second, even if we try to work around the first issue by creating a new handler from the existing one, the attributes set through
With()
become inaccessible viaRecord.Attrs()
. While these attributes still appear in the final log output through the wrapped handler, middleware can no longer access them programmatically.These behaviors prevent proper implementation of logging middleware that needs to process all records with their complete context, such as forwarding logs to external services like Sentry.
What did you see happen?
To Reproduce
Here's a minimal example demonstrating both issues:
What did you expect to see?
These issues make it impossible to implement proper logging middleware that needs to:
Process all log records consistently, regardless of how they were created
Access the complete set of attributes for each record
Forward complete log context to external services
For example, when implementing Sentry integration, we cannot reliably capture all log records or their full context, leading to incomplete error reporting.
The text was updated successfully, but these errors were encountered: