Skip to content

CAMEL-23225: Propagate OTel context in Spring Boot task executors#1730

Closed
gnodet wants to merge 1 commit intomainfrom
CAMEL-23225-otel-context-propagation-task-decorator
Closed

CAMEL-23225: Propagate OTel context in Spring Boot task executors#1730
gnodet wants to merge 1 commit intomainfrom
CAMEL-23225-otel-context-propagation-task-decorator

Conversation

@gnodet
Copy link
Copy Markdown
Contributor

@gnodet gnodet commented Mar 25, 2026

JIRA: CAMEL-23225

Summary

  • Register an OTel context-propagating TaskDecorator bean in camel-opentelemetry2-starter auto-configuration
  • Spring's ThreadPoolTaskExecutor (used by camel-platform-http-starter) captures the current OTel context on the submitting thread and restores it on the worker thread
  • Prevents OpenTelemetry context leaks in async/multi-threaded scenarios
  • @ConditionalOnMissingBean allows users to provide their own TaskDecorator if needed

Follow-up to apache/camel#22190 based on review feedback from @johnpoth.

Test plan

  • OtelContextPropagatingTaskDecoratorTest verifies the TaskDecorator bean is auto-configured
  • Verifies OTel context is propagated from submitting thread to worker thread

Claude Code on behalf of Guillaume Nodet

🤖 Generated with Claude Code

Register an OTel context-propagating TaskDecorator bean in the
camel-opentelemetry2-starter auto-configuration. This ensures
Spring's ThreadPoolTaskExecutor (used by camel-platform-http-starter)
propagates OpenTelemetry context to worker threads, preventing
context leaks in async processing scenarios.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@squakez squakez left a comment

Choose a reason for hiding this comment

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

Why is this change needed? see apache/camel#22190

This PR is wrapping the context around a thread. The context propagation for otel2 has nothing to deal with what it happened with otel1 component. IMO, we should discard this one.

@gnodet
Copy link
Copy Markdown
Contributor Author

gnodet commented Mar 25, 2026

@squakez Thanks for the feedback. After reading the design doc more carefully, I agree the core camel PR #22190 was wrong — wrapping all Camel-internal thread pools with Context.taskWrapping() contradicts the Exchange-based storage design. That one has been reverted in apache/camel#22254.

For this Spring Boot starter PR, the question is more nuanced. The create() method in OpenTelemetrySpanLifecycleManager does fall back to Context.current() when there's no Camel parent span and no traceparent header — this is the case where an OTel Java agent instruments the HTTP server and sets context via ThreadLocal, but Spring Boot's ThreadPoolTaskExecutor hands off to a different thread before Camel's create() runs, losing that ThreadLocal context.

If camel-opentelemetry2 should rely exclusively on W3C traceparent header-based propagation (as the design doc implies), then this TaskDecorator is unnecessary — the agent/upstream system should pass headers. But if the ThreadLocal fallback in create() is intentional and should work, then the Spring Boot starter is the right place to ensure Spring's thread pool preserves it (not the core component).

So the real question is: should we remove the Context.current() fallback from create() and rely only on header extraction? Or is the fallback intentional for cases like Java agent instrumentation?

Happy to close this PR if the answer is header-only.

Claude Code on behalf of Guillaume Nodet

@squakez
Copy link
Copy Markdown
Contributor

squakez commented Mar 25, 2026

Threading logic belongs to Camel core, so, any problem with that, should be treated there. Likely camel-opentelemetry has some relation with that logic. However, camel-opentelemetry2 is designed not to have any relation with such, exactly with the scope of decoupling from those kind of potential problems we're suffering in camel-opentelemetry bound to thread context coupling. The storage of traces is, by design, propagated via exchanges headers. So, nothing is required, at least, according to this design.

Also, that unit test has nothing to deal with Camel. It never starts a Camel application or a context, not sure what it was supposed to test of Camel framework.

@gnodet gnodet closed this Mar 25, 2026
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.

2 participants