You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
log.NewZapFrom(logger *zap.Logger) creates a GoAkt Logger backed by a *zap.Logger you already own, mirroring the existing log.NewSlogFrom. This lets you share one zap instance across GoAkt and the rest of your application without coupling them to GoAkt's log package, and without GoAkt dictating the encoding, outputs, or level.
GoAkt's leveled methods wrap the logger and add one stack frame, so NewZapFrom derives a child logger with zap.AddCallerSkip(1); if the supplied logger has caller annotation enabled (zap.AddCaller), the reported caller points at your call site rather than into GoAkt's log package. The supplied logger is not modified (zap loggers are immutable). Because the caller owns the output destinations, LogOutput returns nil and Flush delegates to the logger's Sync (swallowing the benign sync errors console streams return on some platforms).
🐛 Fixes
NewZap no longer hijacks the global zap logger
log.NewZap called zap.ReplaceGlobals, mutating process-global zap state every time it ran, including at package init for the DebugLogger and DefaultLogger vars. Any application constructing its own NewZap(...) silently overwrote the host program's global zap logger, and the installed global carried GoAkt's AddCallerSkip(1) (calibrated for GoAkt's wrapper), so direct zap.L() / zap.S() usage elsewhere reported caller information off by one frame. The ReplaceGlobals call has been removed; nothing in GoAkt reads the zap global, so this changes no observable behavior for GoAkt callers while leaving the host application's global logger untouched.
♻️ Refactors
Slimmer log.Logger interface
The log.Logger interface has been trimmed to align with modern Go logging practice (the log/slog design philosophy): a logging abstraction should not let a library terminate the host process, and it should not leak backend internals. The following methods were removed from the interface:
Fatal(...any) / Fatalf(string, ...any)
Panic(...any) / Panicf(string, ...any)
LogOutput() []io.Writer
The level methods (Info/Infof/InfoContext/InfofContext and the Warn/Error/Debug equivalents), Enabled, With, LogLevel, Flush, and StdLogger are unchanged. The concrete implementations (Slog, Zap, and the discard logger) still exposeFatal/Panic/LogOutput as methods, so application code that holds a concrete type keeps working.
Level.String() now returns "invalid" (instead of an empty string) for InvalidLevel and any unrecognized level. The numeric values of the level constants are unchanged.
⚠️ Migration
You hold the interface (log.Logger) and call Fatal/Fatalf/Panic/Panicf. Log at error level and then halt explicitly:
You hold a concrete logger (e.g. the value returned by log.NewZap / log.NewSlog, or log.DefaultLogger). No change is required; Fatal/Panic/LogOutput remain available on the concrete type.
You call LogOutput() through the interface. Either keep a reference to the concrete type, or track the writers you passed into the constructor yourself.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
✨ New Additions
log.NewZapFromlog.NewZapFrom(logger *zap.Logger)creates a GoAktLoggerbacked by a*zap.Loggeryou already own, mirroring the existinglog.NewSlogFrom. This lets you share one zap instance across GoAkt and the rest of your application without coupling them to GoAkt'slogpackage, and without GoAkt dictating the encoding, outputs, or level.GoAkt's leveled methods wrap the logger and add one stack frame, so
NewZapFromderives a child logger withzap.AddCallerSkip(1); if the supplied logger has caller annotation enabled (zap.AddCaller), the reportedcallerpoints at your call site rather than into GoAkt'slogpackage. The supplied logger is not modified (zap loggers are immutable). Because the caller owns the output destinations,LogOutputreturnsnilandFlushdelegates to the logger'sSync(swallowing the benign sync errors console streams return on some platforms).🐛 Fixes
NewZapno longer hijacks the global zap loggerlog.NewZapcalledzap.ReplaceGlobals, mutating process-global zap state every time it ran, including at package init for theDebugLoggerandDefaultLoggervars. Any application constructing its ownNewZap(...)silently overwrote the host program's global zap logger, and the installed global carried GoAkt'sAddCallerSkip(1)(calibrated for GoAkt's wrapper), so directzap.L()/zap.S()usage elsewhere reported caller information off by one frame. TheReplaceGlobalscall has been removed; nothing in GoAkt reads the zap global, so this changes no observable behavior for GoAkt callers while leaving the host application's global logger untouched.♻️ Refactors
Slimmer
log.LoggerinterfaceThe
log.Loggerinterface has been trimmed to align with modern Go logging practice (thelog/slogdesign philosophy): a logging abstraction should not let a library terminate the host process, and it should not leak backend internals. The following methods were removed from the interface:Fatal(...any)/Fatalf(string, ...any)Panic(...any)/Panicf(string, ...any)LogOutput() []io.WriterThe level methods (
Info/Infof/InfoContext/InfofContextand theWarn/Error/Debugequivalents),Enabled,With,LogLevel,Flush, andStdLoggerare unchanged. The concrete implementations (Slog,Zap, and the discard logger) still exposeFatal/Panic/LogOutputas methods, so application code that holds a concrete type keeps working.Level.String()now returns"invalid"(instead of an empty string) forInvalidLeveland any unrecognized level. The numeric values of the level constants are unchanged.You hold the interface (
log.Logger) and callFatal/Fatalf/Panic/Panicf. Log at error level and then halt explicitly:You hold a concrete logger (e.g. the value returned by
log.NewZap/log.NewSlog, orlog.DefaultLogger). No change is required;Fatal/Panic/LogOutputremain available on the concrete type.You call
LogOutput()through the interface. Either keep a reference to the concrete type, or track the writers you passed into the constructor yourself.🔀 Pull Requests
Full Changelog: v4.2.7...v4.2.8
This discussion was created from the release v4.2.8.
All reactions