Skip to content

Fix MultiplexInstrument tracer fan-out - #235

Draft
aryansk wants to merge 1 commit into
apple:mainfrom
aryansk:codex/issue-232-multiplex-tracer
Draft

Fix MultiplexInstrument tracer fan-out#235
aryansk wants to merge 1 commit into
apple:mainfrom
aryansk:codex/issue-232-multiplex-tracer

Conversation

@aryansk

@aryansk aryansk commented Aug 6, 2026

Copy link
Copy Markdown

Fixes #232

MultiplexInstrument now forwards span creation and span lifecycle operations to every configured tracer, including context propagation, attributes, events, errors, links, status, flush, and end. This adds direct and global instrumentation coverage for multiple tracers.

Validation:
swift test
git diff --check

**Motivation:**\nA MultiplexInstrument forwards context propagation to all instruments, but InstrumentationSystem selected only the first tracer for span creation.\n\n**Modifications:**\nAdd a package-scoped type-erased MultiplexTracer and MultiplexSpan, forward tracer and span operations to every underlying tracer, and cover both direct and global tracing paths with tests.\n\n**Result:**\nMultiple tracing backends configured through MultiplexInstrument now receive the same span lifecycle operations.

@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
extension InstrumentationSystem {
private static var multiplexTracer: MultiplexTracer? {

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.

Is this really necessary? A multiplex tracer or instrument should really just behave as any other tracer/instrument and should not need any special handling. It should be full on possible to implement the multiplex instrument/tracer outside of this module and the instrument/tracer properties behave correct.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for raising this. The reason I put the forwarding type here is that InstrumentationSystem.tracer currently selects only the first tracer when bootstrapped with MultiplexInstrument; without an adapter at this boundary, global tracing calls do not fan out to the other configured tracers. I agree that a multiplex tracer could be implemented outside this module, so I don’t want to assume this is the preferred API boundary. Would you prefer keeping the global accessor behavior unchanged and moving fan-out to an external integration, or should this PR keep the global accessor behavior and add the smallest supported adapter? I’m happy to narrow the patch to the project’s preferred direction.

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.

Let me clarify. There can only be a single bootstrapped instrument or tracer. The fact that the current implementation checks if that bootstrapped instrument/tracer is a multiplex instrument is in my opinion wrong. Multiplex instruments/tracers are just as a regular instrument/tracer and they must not get any special treatment inside the core library here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Understood. I agree that the core tracing accessor should treat a bootstrapped multiplex value like any other tracer and should not inspect MultiplexInstrument specially. The current patch does not meet that boundary: it adds the special-case in InstrumentationSystem+Tracing.swift.

I will not push a speculative API rewrite. MultiplexInstrument lives in the Instrumentation target while Tracer and Span live in Tracing, so making the multiplex value a regular Tracer requires choosing the supported ownership/API boundary for that wrapper. Please confirm whether you want the multiplex tracer abstraction moved into the Instrumentation target or exposed as a separate tracing bootstrap value; once that boundary is confirmed, I can remove the special-case and update the tests accordingly.

}

package var context: ServiceContext {
self.spans[0].context

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this needs to be discussed. Returning just the first context is at least confusing and needs documenting. But I would discuss what should be the expected context for a MultiplexSpan.

@aryansk

aryansk commented Aug 10, 2026

Copy link
Copy Markdown
Author

Agreed — returning the first context is an ambiguous contract, and MultiplexSpan needs an explicit decision before I change the implementation. I will hold this PR at the design boundary until maintainers decide whether the expected result is the first context, a documented merged/selected context, or another supported value; then I can update the implementation and regression tests to match.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MultiplexInstrument does not fan out to all tracers

3 participants