-
Release v0.9.0 Stable
released this
2026-03-18 13:33:16 -06:00 | 0 commits to main since this releasev0.9.0
code.nochebuena.dev/go/logzOverview
logzprovides a stableLoggerinterface backed by the stdliblog/slogpackage, with no external logging library dependencies. It owns the request correlation ID context key and an extra-fields context key, supplying helpers to attach and retrieve them so any downstream handler can enrich log records from the context without manual field threading. When an error passed toLogger.Errorimplements theErrorCode()orErrorContext()duck-type interfaces, the structured fields are automatically appended to the log record — withoutlogzimportingxerrors.What's Included
Loggerinterface —Debug,Info,Warn,Error(msg, err, args...),With,WithContextOptionsstruct —Level slog.Level,JSON bool,StaticArgs []anyNew(opts Options) Logger— constructs aLoggerwriting toos.Stdout; zero value ofOptionsis valid (INFO level, text output)WithRequestID(ctx, id string) context.Context— stores a correlation ID in the context; owned by this packageGetRequestID(ctx context.Context) string— retrieves the correlation ID; returns""if absent or ctx is nilWithField(ctx, key string, value any) context.Context— adds a single key-value logging field to the contextWithFields(ctx context.Context, fields map[string]any) context.Context— merges multiple key-value fields into the context; does not overwrite existing fields- Automatic
error_codeand context-field enrichment inLogger.Errorvia duck-typederrorWithCode/errorWithContextprivate interfaces
Installation
require code.nochebuena.dev/go/logz v0.9.0Design Highlights
- Wraps
log/slogexclusively — no external logging library is required or vendored (seedocs/adr/ADR-001-slog-stdlib-backend.md). logzowns the context keysctxRequestIDKey{}andctxExtraFieldsKey{}as unexported struct types, preventing collisions with any other package's context keys (seedocs/adr/ADR-002-requestid-context-ownership.md).Newreturns theLoggerinterface, not the concrete*slogLogger, andWithalso returnsLogger— the concrete type is never exported, making the interface the only public surface and allowing safe local re-declaration in libraries (seedocs/adr/ADR-003-exported-logger-interface.md).Errortreatserras a first-class parameter (not a variadic arg), enabling the automatic duck-typed enrichment path;xerrors.Errsatisfies this without any import between the two packages.
Known Limitations & Edge Cases
- All log output is always written to
os.Stdout. There is no configurableio.Writer— routing to files, syslog, or other sinks must be handled by the process supervisor or a shell redirect. - There is no log sampling or rate limiting. A high-frequency error loop will produce one log record per call with no throttling.
WithFieldandWithFieldscreate a new map and a new context value on every call. In hot paths (e.g. per-request middleware), repeated calls accumulate allocations; batch them with a singleWithFieldscall where possible.WithContext(nil)is handled safely (returns the same logger), butWithRequestIDandWithFielddo not accept nil contexts and will panic.StaticArgsinOptionsare attached at logger construction time only; there is no way to inject static args into an existing logger without creating a new one viaWith.Logger.Withreturns aLoggerinterface — if the caller needsWithContextafterWith, that is supported, but the full method set ofslogLoggeris not accessible afterWith.
v0.9.0 → v1.0.0 Roadmap
- Evaluate whether a configurable
io.Writer(passed viaOptions) is required for production use cases such as test log capture or file-based audit trails. - Decide whether log sampling belongs in this package or should be left to
slog.Handlerwrappers, and document the recommended pattern. - Validate the duck-typed
xerrorsenrichment path under concurrent production load to confirm no race conditions on theErrorContext()map read path. - Confirm that the
Loggerinterface method set is final before 1.0; any addition is a breaking change for all callers that re-declare the interface locally. - Achieve production validation of the
WithFieldsmerge semantics under concurrent middleware chains.
v0.9.0 rationale: The API is stable and intentional — designed through multiple architecture reviews and tested end-to-end via the todo-api POC (SQLite, RBAC, middleware stack, HTTP handlers). The module is not yet battle-tested in production for all edge cases, and the pre-1.0 designation preserves the option for minor API refinements based on real-world use.
Downloads