samber slog extensions
Inspect go.mod, every github.com/samber/slog-* import, local handler wrappers, and the full record path from logger to sink. These extensions are separate modules with independent major versions and lifecycle APIs; verify each selected module rather than applying one shared version assumption.
Select the module by responsibility
| Module | Responsibility | Representative surface |
|---|---|---|
github.com/samber/slog-multi |
Handler composition | Fanout, Router, FirstMatch, Failover, Pool, Pipe |
github.com/samber/slog-sampling |
Record admission | uniform, threshold, absolute, or custom sampling options |
github.com/samber/slog-formatter |
Attribute transformation | formatter middleware and key/type/group formatters |
github.com/samber/slog-gin, slog-echo, slog-fiber, slog-chi, slog-http |
HTTP logging | framework middleware, filters, request attributes |
github.com/samber/slog-datadog, slog-sentry, slog-loki, and other selected adapters |
Remote, queue, storage, or logger bridge | backend-specific option and handler constructors |
Major-version suffixes and constructor names vary by module. Read the exact go.mod requirement and package docs before writing an import or shutdown call.
Preserve slog.Handler behavior
Trace Enabled, Handle, WithAttrs, and WithGroup through every wrapper. Preformatted attributes and group state must survive composition. Confirm whether handlers copy slog.Record before mutation and whether callbacks can run concurrently.
Composition choices have different delivery semantics:
Fanoutsends a record to every handler and defines how their errors combine;Routercan send to all matching routes, whileFirstMatchmakes route order significant;Failovertries alternatives after a handler error;Pooldistributes records rather than replicating them;Pipewraps a sink with ordered middleware.
Define the unmatched-route behavior and what one sink failure means for other destinations. Audit or compliance delivery should not accidentally inherit sampling, pool, or best-effort semantics.
Order transformations from the real policy
Handler order is observable. Early sampling avoids later work, but a sampling matcher may first need safe normalized attributes. Redaction must happen before any sink, buffer, hash, metric label, or fallback path that could expose the original value. Routing may belong before or after formatting depending on which representation predicates inspect.
With slog-sampling, verify the option type, matcher, interval state, and accepted/dropped hooks. Decide which record classes may be lost and whether state is global or grouped by level, message, source, or attributes.
With slog-formatter, verify whether a formatter replaces, groups, flattens, or expands an attribute. Preserve slog.LogValuer resolution and avoid transforming the same sensitive field differently across sinks unless that is explicit policy.
HTTP and backend modules
HTTP middleware configuration differs across frameworks even when fields look similar. Confirm status-to-level mapping, filters, request/response body capture, request IDs, trace fields, panic behavior, and where custom attributes enter the context. Body and header capture requires an explicit size and redaction policy.
Backend handlers may buffer, batch, retry, spawn workers, or own clients. Keep the concrete handler, client, writer, or buffer needed for Stop, Close, or Flush; slog.Handler itself has no shutdown method. Use a bounded application shutdown context and avoid logging a delivery failure back through the same failed pipeline.
Performance and cardinality
Benchmark the assembled pipeline with representative disabled levels, groups, context attributes, formatting, routing, and sink behavior. Fanout, remote handlers, and formatter chains can change both caller latency and allocations. Backend-specific indexed labels need a cardinality review separate from ordinary structured fields.
Verification
Use a recording handler or controlled fake backend to assert level filtering, groups, attributes, redaction, route selection, fanout/failover behavior, and sampling boundaries. Test WithAttrs and WithGroup on derived loggers, concurrent logging where touched, backend failures, and bounded flush on shutdown.
Compile and test every changed extension module path; similar APIs in another slog-* repository are not evidence that the pinned module has the same contract.