Skip to content

[SLG-0006]: task-local logger implementation#459

Open
kukushechkin wants to merge 22 commits into
apple:mainfrom
kukushechkin:SLG-0006-task-local-logger-implementation
Open

[SLG-0006]: task-local logger implementation#459
kukushechkin wants to merge 22 commits into
apple:mainfrom
kukushechkin:SLG-0006-task-local-logger-implementation

Conversation

@kukushechkin

Copy link
Copy Markdown
Contributor

This proposal adds task-local logger storage so that metadata can accumulate across async
call stacks without threading a Logger through every function signature.

Motivation:

Metadata propagation requires threading a logger through every layer. Every function on
the path from request ingress to the bottom of the call stack has to accept, mutate, and
forward a Logger. Libraries must choose between polluting their public API with a logger: parameter and
losing all the caller's context. There is no third option today.

Modifications:

  • New API surface for reading and modifying the @TaskLocal Logger instance added.
  • Best practices on how to correctly propagate logger into libraries updated with Logger.current API.

Result:

Users can now automatically propagate accumulated metadata into libraries without explicitly passing loggers through the API boundaries.

@kukushechkin kukushechkin added the 🆕 semver/minor Adds new public API. label May 18, 2026
@kukushechkin kukushechkin force-pushed the SLG-0006-task-local-logger-implementation branch from c5471e9 to 16bce4e Compare May 18, 2026 12:01
@kukushechkin kukushechkin changed the title [SLG-0006]: task local logger implementation [SLG-0006]: task-local logger implementation May 18, 2026
@kukushechkin kukushechkin marked this pull request as draft May 18, 2026 12:04
@kukushechkin kukushechkin force-pushed the SLG-0006-task-local-logger-implementation branch from 16bce4e to 80e5dfd Compare May 18, 2026 12:14
@kukushechkin kukushechkin force-pushed the SLG-0006-task-local-logger-implementation branch from 80e5dfd to 0ed85c1 Compare May 19, 2026 13:58
Comment thread Sources/Logging/Docs.docc/Proposals/SLG-0006-task-local-logger.md Outdated
Comment thread Sources/Logging/Docs.docc/Proposals/SLG-0006-task-local-logger.md Outdated
Comment thread Sources/Logging/Docs.docc/Proposals/SLG-0006-task-local-logger.md Outdated
Comment thread Sources/Logging/Docs.docc/Proposals/SLG-0006-task-local-logger.md
Comment thread Sources/Logging/Docs.docc/Proposals/SLG-0006-task-local-logger.md Outdated
Comment thread Sources/Logging/Logger+With.swift Outdated
Comment thread Sources/Logging/Logger.swift Outdated
Comment thread Sources/Logging/Logger.swift Outdated
Comment thread Sources/Logging/Logger+With.swift Outdated
@kukushechkin kukushechkin marked this pull request as ready for review June 11, 2026 15:12
}
```

#### Alternative: Accept logger through initializer when appropriate

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did this become recommended?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't be recommended. The thinking was if you want a specific logger for the lifetime of an object, caching the logger might be a preferred way — the task-local one can be different over time.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn’t recommend that because caching the logger for the lifetime of an object means the metadata is not inherited down the call stack. I would consider storing the logger actually a bad practice now with task local propagation

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, let's keep it just "Alternative", not a recommended approach.

Comment thread Sources/Logging/Docs.docc/BestPractices/003-AcceptingLoggers.md

#### Recommended: Read ``Logger/current`` from the task-local

When a `logger:` parameter would clutter an otherwise logger-unrelated API, read the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend not saying “clutter” but instead say that if an API doesn’t want to make Logging part of its public API I.e. to hide the dependency

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reworded as just whenever there is no logger in the API for whatever reasons.

@main
struct MyServer {
static func main() async throws {
let logger = Logger(label: "my-server")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example is missing the bootstrap. I am wondering if we want a bootstrap method that also binds the take local

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it will be the same technically, but confusing semantically — LoggingSystem.bootstrap(logger) { } vs withLogger(logger) {}. Can you call bootstrap only once? What is the difference with just withLogger?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am mostly thinking of how we recommend application developers to structure their application Main method. Now we recommend calling bootstrap and then withLogger right afterwards maybe providing a 2-1 solution will make it easier

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Realistically, an application get completely get rid of bootstrap if it itself uses task-local or explicit loggers AND no dependencies create loggers (== do not rely on the global factory bootstrap). This is needed if application has to deal with loggers construction. Changed the paragraph in the corresponding section.

Comment thread Sources/Logging/Docs.docc/BestPractices/003-AcceptingLoggers.md Outdated
Comment thread Sources/Logging/Logger+With.swift Outdated
Comment thread Sources/Logging/Logger.swift
Comment thread Sources/Logging/Logger+With.swift
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🆕 semver/minor Adds new public API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants