Skip to content

Deprecating the logger-in-context accessors (InjectLogger and Logger) #69

@danielorbach

Description

@danielorbach

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

  • component.InjectLogger and component.Logger are deprecated with migration guidance.
  • The guidance names the replacement: slog.Default() plus loggers derived with slog.Logger.With and passed explicitly.
  • The package documentation no longer presents the logger-in-context accessors as the recommended way to obtain a logger.
  • Removal is tracked for a future v2.

Follow-up

  • Downstream migration of existing component.Logger(ctx) call sites (e.g. the atmosphere codebase) ahead of v2 removal.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions