-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Gologshim runtime controlled handler #3419
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
Gologshim runtime controlled handler #3419
Conversation
gammazero
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this makes the code cleaner/clearer. Your call @lidel
wire gologshim to go-log's slog bridge via init() in cmd/ipfs/kubo/start.go update go-libp2p to v0.44.1-0.20251029234611-789d14c6effe see libp2p/go-libp2p#3419
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works for us also, pushed docs + some thoughts below:
On the trade-off here
Original #3418 (commit ea2c010 before merging this PR into that one) required no changes in existing apps, just updating both go-log and go-libp2p to latest versions. That was all end user would have to do to restore logs.
This PR requires every legacy application that used both go-log and go-libp2p to add this extra code (if they use automatic slog bridge):
import (
"github.com/libp2p/go-libp2p/gologshim"
)
func init() {
// After go-log's init() runs and installs slog bridge,
// tell gologshim to use it
handler := slog.Default().Handler()
// Verify it's go-log's bridge
type goLogBridge interface {
GoLogBridge()
}
if _, ok := handler.(goLogBridge); !ok {
panic("aborting startup: slog.Default() is not go-log's bridge, logs would be missing due to incorrect wiring")
}
// use the implicit go-log bridge
gologshim.SetDefaultHandler(handler)
}or this, if they dont touch slog default:
import (
logging "github.com/ipfs/go-log/v2"
"github.com/libp2p/go-libp2p/gologshim"
)
func init() {
// use the explicit go-log bridge
gologshim.SetDefaultHandler(golog.SlogHandler())
}If this is the price to pay to fix logs, we can do the above in Kubo, Rainbow and every other application Shipyard maintains, but everyone else will be missing logs unless they do the same.
Just a trade-off decision.
Next steps
@MarcoPolo lgtm, i've tested this PR in ipfs/kubo#11039 and it also works for us (with the above extra code).
Up to you if you prefer implicit or explicit.
- If you prefer explicit, feel free to merge this PR into #3418, and then merge that (#3419+#3418).
- If you are ok with implicit detection, this PR can be closed and only merge #3418
Either way, we would appreciate a release with a fix 🙏
I don't follow, do you mind explaining a bit more? Where are you calling |
|
@MarcoPolo I wrote an (wip draft) explainer in ipfs/go-log#176 for go-log users, check "Slog integration" section in
go-log already called What we added to that This has to be done because we dont want to lose any slog entries in go-lang apps, nor want to have different formatting from libraries that use slog. Going forward, various libraries may switch to slog, and we dont want to have regressions like the one go-libp2p caused when it switched to slog. In the future, we may decide to switch the go-log backend from zap to slog, but the fact we call
The
The goal was to unbreak existing users without asking them to change any code. If go-libp2p forces our hand to add extra call for |
Are you expecting to have all other libraries add the goLogBridge interface check? I'm not sure that makes sense. I think setting the default log handler is something that should be owned by the application, not by a library that could possibly be a transitive dependency of another library. I don't mind merging this change, but this will change again if/when we move away from global loggers to passing loggers explicitly. At that point applications would need to pass go-log explicitly to go-libp2p anyways, and any init trick won't work. |
7a7ab1b to
326593e
Compare
add SlogHandler() function that returns go-log's slog.Handler directly. this allows applications to wire slog-based libraries to go-log even when GOLOG_CAPTURE_DEFAULT_SLOG=false. the bridge is now always created during SetupLogging(), but only installed as slog.Default() when automatic capture is enabled. use atomic.Pointer[slog.Handler] for thread-safe access without locks, following idiomatic Go patterns for single-writer, multiple-reader scenarios. benefits: - works when GOLOG_CAPTURE_DEFAULT_SLOG=false - more explicit API (no indirection through slog.Default()) - simpler application code (no duck-typing verification needed) - thread-safe without mutex overhead addresses feedback from libp2p/go-libp2p#3419
change GOLOG_CAPTURE_DEFAULT_SLOG to default to false, requiring explicit opt-in for automatic slog.Default() capture. applications wanting slog integration must now explicitly call slog.SetDefault(slog.New(golog.SlogHandler())). rationale: - go-libp2p decided to use explicit wiring (gologshim.SetDefaultHandler) rather than relying on automatic slog.Default() capture - automatic capture was the original motivation for default=true, but is no longer needed - makes go-log a better Go library by not modifying global state by default - follows Go best practice: libraries should not call slog.SetDefault() - opt-in is better than opt-out for invasive features changes: - setup.go: change condition from != "false" to == "true" - README.md: updated documentation to show explicit setup pattern, reposition GOLOG_CAPTURE_DEFAULT_SLOG as development/opt-in feature - tests: updated expectations to match new default behavior references: - #176 (comment) - libp2p/go-libp2p#3419 (review)
lidel, take a look and let me know your thoughts. This is targeting your branch.
This removes the goLogBridge interface check and having to modify the default slog logger. Instead you explicitly set the handler via
gologshim.SetDefaultHandler.