logging: route controller-runtime binaries through slog (retire zap) - #535
logging: route controller-runtime binaries through slog (retire zap)#535Philip Lombardi (plombardi89) wants to merge 4 commits into
Conversation
Route controller-runtime's logr logging through slog (logr.FromSlogHandler(slog.Default().Handler())) instead of the kubebuilder-default zap dev-mode backend, matching metalman (cmd/metalman/main.go) and the agent (cmd/agent/internal/cmd/context.go) and the rest of the repo, which standardize on log/slog. Behavior change: slog.Default() is an Info-level handler, and logr V(n) maps to slog level -n, so logr V(1)+ logs (for example the migration reaper's routine V(1) lines) are now suppressed by default rather than printed. zap dev-mode previously pinned the level to Debug, which rendered V-level verbosity ineffective; with slog, V(1) becomes a real quiet lever. Unifying the remaining zap-based controller binaries (machina, machine-ops-controller, playpen-operator) onto slog is tracked separately.
There was a problem hiding this comment.
Pull request overview
This PR updates unbounded-operator to route controller-runtime logging through the repository-standard log/slog stack (via logr.FromSlogHandler) instead of the kubebuilder zap backend. This aligns the operator’s logging behavior with other binaries (e.g., metalman, agent) and makes logr verbosity levels (V(n)) meaningful by default.
Changes:
- Switch controller-runtime logger initialization from
zap.New(zap.UseDevMode(true))tologr.FromSlogHandler(slog.Default().Handler()). - Drop the operator’s controller-runtime zap logger import and add
log/slog+github.com/go-logr/logrimports. - Document the intended verbosity behavior (
V(1)+suppressed under the default Info-level slog handler) inline.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Follow the operator's switch by moving the last zap-based controller binaries onto slog, so the whole repo logs through log/slog. Each replaces ctrl.SetLogger(zap.New(zap.UseDevMode(true))) with ctrl.SetLogger(logr.FromSlogHandler(slog.Default().Handler())) - cmd/machina/machina/controller/manager.go - cmd/machine-ops-controller/main.go - cmd/playpen-operator/main.go - e2e/operator/reaper_e2e_test.go and slice_window_e2e_test.go (log.IntoContext) No source file imports sigs.k8s.io/controller-runtime/pkg/log/zap anymore, so go mod tidy drops github.com/go-logr/zapr. go.uber.org/zap remains only as a transitive dependency of go-libp2p-kad-dht (via internal/gantry/discovery), not of our logging. Behavior change (same as the operator): slog.Default() is an Info-level handler and logr V(n) maps to slog level -n, so logr V(1)+ logs are now suppressed by default rather than printed under zap dev-mode. Closes #534
| github.com/fxamacker/cbor/v2 v2.9.0 // indirect | ||
| github.com/go-errors/errors v1.4.2 // indirect | ||
| github.com/go-logr/stdr v1.2.2 // indirect | ||
| github.com/go-logr/zapr v1.3.0 // indirect | ||
| github.com/go-ole/go-ole v1.2.6 // indirect |
There was a problem hiding this comment.
go mod tidy was run and both files already reflect its output - go mod tidy -diff reports no pending changes, so CI's tidy-check passes as-is.
go.sum keeps github.com/go-logr/zapr on purpose: it is still in the module graph via sigs.k8s.io/controller-runtime@v0.24.1, which requires zapr in its own go.mod (go mod graph shows sigs.k8s.io/controller-runtime@v0.24.1 github.com/go-logr/zapr@v1.3.0). go.sum must carry checksums for every module in the graph, not just direct requirements. What changed here is only that zapr is no longer a direct dependency, so it correctly leaves the go.mod require block while its go.sum checksums remain. Removing those lines manually would make go mod tidy re-add them and fail the tidy-check.
| // Route controller-runtime's logr logging through slog, consistent with the | ||
| // rest of the repo (metalman, agent). slog.Default() is an Info-level | ||
| // handler, so logr V(1)+ maps to sub-Info slog levels and is suppressed by | ||
| // default. |
Summary
Routes all controller-runtime binaries through
sloginstead of the kubebuilder-default zap backend, so the whole repo logs throughlog/slog(matchingmetalmanand theagent). Each site swaps:controller-runtime's logging facade is
logr, so a manager must set somelogr.Logger;logr.FromSlogHandleradapts an slog handler to satisfy it (minimal form, mirroringcmd/metalman/main.go).Changed sites
cmd/unbounded-operator/main.gocmd/machina/machina/controller/manager.gocmd/machine-ops-controller/main.gocmd/playpen-operator/main.goe2e/operator/reaper_e2e_test.go,e2e/operator/slice_window_e2e_test.go(log.IntoContext)Dependency cleanup
No source file imports
sigs.k8s.io/controller-runtime/pkg/log/zapanymore, sogo mod tidydropsgithub.com/go-logr/zapr.go.uber.org/zapremains only as a transitive dependency ofgo-libp2p-kad-dht(viainternal/gantry/discovery), not of our logging.Behavior change
slog.Default()is an Info-level handler, and logrV(n)maps to slog level-n, so logrV(1)+logs (e.g. the migration reaper's routineV(1)lines) are now suppressed by default rather than printed.zap.New(zap.UseDevMode(true))previously pinned the level to Debug, which madeV-level verbosity ineffective. With slog,V(1)becomes a real quiet lever - which also unblocks the fix in #533 (BootstrapMaintainer log churn).Testing
go build ./...,go vet -tags=e2e ./e2e/operator/...,make fmt,make lint(0 issues),go test ./cmd/... ./internal/operator/...all pass.Closes #534
Refs #533