feat(logz): initial stable release v0.9.0

Structured logger backed by log/slog with request-context enrichment, extra-field context helpers, and duck-typed automatic error enrichment.

What's included:
- `Logger` interface with Debug / Info / Warn / Error / With / WithContext; `New(Options)` constructor writing to os.Stdout
- `WithRequestID` / `GetRequestID` and `WithField` / `WithFields` context helpers — package owns both context keys
- Automatic error_code and context-field enrichment in Logger.Error via duck-typed errorWithCode / errorWithContext interfaces (no xerrors import)

Tested-via: todo-api POC integration
Reviewed-against: docs/adr/
This commit is contained in:
2026-03-18 13:31:39 -06:00
commit 3667b92fab
15 changed files with 1020 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
# ADR-001: log/slog as the Logging Backend
**Status:** Accepted
**Date:** 2026-03-18
## Context
Structured logging is a cross-cutting concern required by nearly every module in
the ecosystem. External logging libraries (zerolog, zap, logrus) add transitive
dependencies, pin dependency versions, and require every module that accepts a
logger to either import the concrete library or define an adapter interface. Go 1.21
shipped `log/slog` as a stdlib structured logging API, providing JSON and text
handlers, level filtering, and attribute chaining with no external dependencies.
## Decision
`logz` wraps `log/slog` exclusively. The concrete type `slogLogger` holds a
`*slog.Logger`. `New(opts Options) Logger` constructs either a JSON handler
(`slog.NewJSONHandler`) or a text handler (`slog.NewTextHandler`) backed by
`os.Stdout`, controlled by `Options.JSON`.
`Options` exposes:
- `Level slog.Level` — minimum log level (zero value = `slog.LevelInfo`).
- `JSON bool` — JSON vs text output.
- `StaticArgs []any` — key-value pairs attached to every record via `slog.Logger.With`.
The `slog` dependency is internal to the `logz` package. Consumers depend only on
the `logz.Logger` interface and are not required to import `log/slog` at all.
## Consequences
- Zero external dependencies: `logz` stays at Tier 1 (stdlib only).
- The `slog` structured attribute system (`slog.String`, `slog.Int`, etc.) is
available internally but is not exposed through the `Logger` interface — callers
pass plain `key, value` pairs, which `slog` handles via its `any` variadic.
- Output always goes to `os.Stdout`. Log routing (to files, remote sinks) is the
responsibility of the process supervisor or log collector, not this package.
- If a future Go version modifies the `slog` API, only `logz` needs to be updated —
all consumers remain unaffected.