Files
logz/docs/adr/ADR-001-slog-stdlib-backend.md
Rene Nochebuena 3667b92fab 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/
2026-03-18 13:31:39 -06:00

1.8 KiB

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.