component.InjectLogger and component.Logger store and retrieve a *slog.Logger inside a context.Context. This is precisely the logger-in-context pattern that log/slog itself built, debated, and then removed before its 1.21 release: the experimental package's NewContext/FromContext/Ctx were cut because, in the words of the package author, putting a logger in a context "creates a hidden dependency — when you call a function that takes a context, you don't know whether the context is for logging, cancellation, or both" (golang/go#58243), and the Go blog records that the feature was removed "as being too controversial." Carrying these accessors forward institutionalizes, in this framework's public API, an approach the standard library deliberately declined.
Every call site that reaches for component.Logger(ctx) depends on a logger smuggled through context rather than one passed explicitly or obtained from slog.Default(). The dependency is invisible at the call boundary, harder to test and reason about, and diverges from the slog conventions the wider ecosystem now follows. The cost compounds with adoption: the pattern is already pervasive downstream (on the order of 1,500 call sites in the atmosphere codebase alone), so every release that keeps it blessed makes the eventual migration larger and normalizes the anti-pattern for new code.
#14 establishes the slog-aligned replacement. Component identity reaches logs through a composable handler that extracts it from context — the one context role slog does sanction, a handler reading request-scoped values — and per-call attributes are added the slog way, by deriving a logger with slog.Logger.With and passing it down explicitly. With that alternative in place, the logger-in-context accessors are redundant: there is a blessed path for everything they were used for.
This module is at v1.0.0, so the import-compatibility rule applies: removing or changing the signature of an exported function is a breaking change reserved for a future v2. Deprecation notices, by contrast, are source-compatible and can land in v1 — they steer new code and let downstream migrate at its own pace ahead of removal. The downstream migration is substantial and cannot be assumed to complete on this repository's schedule.
This issue concerns only the logger-in-context accessors, component.InjectLogger and component.Logger. The deprecation of the ad-hoc L.* string-formatting methods and the introduction of the slog handler belong to #14 and are not revisited here.
Definition of Done
By the time this Issue is complete, component.InjectLogger and component.Logger will carry deprecation notices that direct callers to slog.Default() and to passing a *slog.Logger explicitly, with the actual removal scheduled for the next major version.
Acceptance Criteria
Follow-up
- Downstream migration of existing
component.Logger(ctx) call sites (e.g. the atmosphere codebase) ahead of v2 removal.
component.InjectLoggerandcomponent.Loggerstore and retrieve a*slog.Loggerinside acontext.Context. This is precisely the logger-in-context pattern thatlog/slogitself built, debated, and then removed before its 1.21 release: the experimental package'sNewContext/FromContext/Ctxwere cut because, in the words of the package author, putting a logger in a context "creates a hidden dependency — when you call a function that takes a context, you don't know whether the context is for logging, cancellation, or both" (golang/go#58243), and the Go blog records that the feature was removed "as being too controversial." Carrying these accessors forward institutionalizes, in this framework's public API, an approach the standard library deliberately declined.Every call site that reaches for
component.Logger(ctx)depends on a logger smuggled through context rather than one passed explicitly or obtained fromslog.Default(). The dependency is invisible at the call boundary, harder to test and reason about, and diverges from the slog conventions the wider ecosystem now follows. The cost compounds with adoption: the pattern is already pervasive downstream (on the order of 1,500 call sites in the atmosphere codebase alone), so every release that keeps it blessed makes the eventual migration larger and normalizes the anti-pattern for new code.#14 establishes the slog-aligned replacement. Component identity reaches logs through a composable handler that extracts it from context — the one context role slog does sanction, a handler reading request-scoped values — and per-call attributes are added the slog way, by deriving a logger with
slog.Logger.Withand passing it down explicitly. With that alternative in place, the logger-in-context accessors are redundant: there is a blessed path for everything they were used for.This module is at v1.0.0, so the import-compatibility rule applies: removing or changing the signature of an exported function is a breaking change reserved for a future v2. Deprecation notices, by contrast, are source-compatible and can land in v1 — they steer new code and let downstream migrate at its own pace ahead of removal. The downstream migration is substantial and cannot be assumed to complete on this repository's schedule.
This issue concerns only the logger-in-context accessors,
component.InjectLoggerandcomponent.Logger. The deprecation of the ad-hocL.*string-formatting methods and the introduction of the slog handler belong to #14 and are not revisited here.Definition of Done
By the time this Issue is complete,
component.InjectLoggerandcomponent.Loggerwill carry deprecation notices that direct callers toslog.Default()and to passing a*slog.Loggerexplicitly, with the actual removal scheduled for the next major version.Acceptance Criteria
component.InjectLoggerandcomponent.Loggerare deprecated with migration guidance.slog.Default()plus loggers derived withslog.Logger.Withand passed explicitly.Follow-up
component.Logger(ctx)call sites (e.g. the atmosphere codebase) ahead of v2 removal.