[ 
https://issues.apache.org/jira/browse/CAMEL-23225?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18068276#comment-18068276
 ] 

Guillaume Nodet commented on CAMEL-23225:
-----------------------------------------

_Claude Code on behalf of Guillaume Nodet_

After thorough investigation, we recommend closing this issue as Not A Problem. 
Here is the full analysis:

h3. Background

The issue reported that Spring Boot's {{ThreadPoolTaskExecutor}} (used in 
{{camel-platform-http-starter}}) doesn't propagate OpenTelemetry context across 
threads, causing context leaks.

Two PRs were attempted:
* [apache/camel#22190|https://github.com/apache/camel/pull/22190] — ported 
{{Context.taskWrapping()}} thread pool wrappers from deprecated 
camel-opentelemetry to camel-opentelemetry2. *Reverted* by 
[apache/camel#22254|https://github.com/apache/camel/pull/22254].
* 
[apache/camel-spring-boot#1730|https://github.com/apache/camel-spring-boot/pull/1730]
 — added a Spring Boot {{TaskDecorator}} to propagate OTel context. *Closed* 
after review feedback.

h3. Why no fix is needed

The {{camel-opentelemetry2}} module is *designed* not to depend on ThreadLocal 
context propagation. Per the [design 
doc|https://github.com/apache/camel/blob/main/proposals/tracing.adoc] and 
confirmed by the component author (@squakez) in 
[camel-spring-boot#1730|https://github.com/apache/camel-spring-boot/pull/1730#issuecomment-2781052771]:

* Trace context is propagated exclusively via *Exchange headers* (W3C 
{{traceparent}}), not ThreadLocal.
* Span storage uses Exchange properties ({{SpanStorageManagerExchange}}), not 
ThreadLocal.
* Thread pool wrapping ({{Context.taskWrapping()}}) contradicts this design.

h3. How context actually flows across thread boundaries

We verified that all async patterns work correctly without any ThreadLocal 
propagation:

* *WireTap*: {{exchange.copy()}} deep-copies all headers including 
{{traceparent}} to the new Exchange (verified by {{AsyncWiretapTest}} — 10 
traces, correct hierarchy)
* *RecipientList*: reuses the same Exchange, headers preserved (verified by 
{{AsyncTest}})
* *CXF REST async*: {{inject()}} writes {{traceparent}} to Exchange headers → 
CXF copies to HTTP headers → REST endpoint creates new Exchange from HTTP 
headers → {{extract()}} reads them back (verified by {{AsyncCXFTest}})
* *HTTP inbound*: Platform HTTP Vert.x / Netty HTTP copy ALL HTTP request 
headers (including {{traceparent}}) into Exchange headers before Camel 
processes them

The {{BAGGAGE_CAMEL_FLAG}} mechanism (added in 
[CAMEL-22648|https://issues.apache.org/jira/browse/CAMEL-22648] / [PR 
#20720|https://github.com/apache/camel/pull/20720]) handles a specific edge 
case: when a third-party component (Vert.x, OTel Java agent) sets a span in 
{{Context.current()}} before Camel processes a message via direct in-process 
call (no HTTP boundary). This is intentional and working correctly — it does 
not require thread pool wrapping.

h3. Recommendation

Close this issue as Not A Problem. No changes are needed in either camel-core 
or camel-spring-boot. The existing design handles cross-thread context 
propagation via Exchange headers, and the {{BAGGAGE_CAMEL_FLAG}} handles the 
in-process integration edge case.

> Spring Boot's default ThreadPoolTaskExecutor doesn't propagate OpenTelemetry 
> Context
> ------------------------------------------------------------------------------------
>
>                 Key: CAMEL-23225
>                 URL: https://issues.apache.org/jira/browse/CAMEL-23225
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-opentelemetry
>            Reporter: John Poth
>            Assignee: Guillaume Nodet
>            Priority: Major
>
> When using camel-opentelemetry-starter (and v2), let's propagate the 
> OpenTelemetry context in Spring Boot's default ThreadPoolTaskExecutor (used 
> in camel-platform-http-starter). This causes context leaks



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to