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

Bjorn Beskow edited comment on CAMEL-23283 at 4/9/26 2:51 PM:
--------------------------------------------------------------

Hi Pasquale,

Thanks for looking into it! I have tried to clarify the problem description, 
and have attached a sample project with integration tests that shows what I 
think is problematic:

*Test Routes*

The project defines 3 routes triggered from different components (rest, jms and 
cxf-rs) but
with identical structure: initial logging followed by a second logging inside 
an inlined
"transformer" processor that forms a nested span:

 

{{from("jms:queue:test")}}
{{  .log("Received message from jms queue")}}
{{  .process(exchange -> Observation}}
{{    .createNotStarted("jms-transformer", observationRegistry)}}
{{      .observe(() -> log.info("Transformed message from jms queue")));}}

 

*Expected behavior*

Expected behavior, as asserted by the integration tests for each route, is that 
traceId and spanId
are available in the MDC context (and hence present in both produced log 
lines), and that the
exported spans have the correct structure, i.e. two spans should be exported: 
one for the route
and a nested span for the transformation. These two spans should have the same 
(parent) traceId.

*Actual behavior*

The `rest` component route is configured to use the `servlet` component, and 
works as expected
(since the Spring Boot servlet in this situation correctly creates the trace, 
and root span).

The `cxf-rs` component defaults to use the `platform-http` component. In this 
case, a trace and
span is indeed created but not correctly associated. This effect is twofold:
 - The traceId and spanId are not set in the MDC for the route span, but they 
are set in the
"transformer" child span
 - The child span for the "transformer" processor is not nested, instead it 
gets a new traceId

The `jms` component behaves the same: traceId and spanId are not set in the MDC 
for the route span
and the child span for the "transformer" processor is not properly nested.

*Suggested fix*

The pull request in [https://github.com/apache/camel/pull/22410] corrects the 
observed behaviour.

 

Thanks for looking into it!


was (Author: beskow):
Hi Pasquale,

Thanks for looking into it! I have tried to clarify the problem description, 
and have attached a sample project with integration tests that shows what I 
think is problematic:

*Test Routes*

The project defines 3 routes triggered from different components (rest, jms and 
cxf-rs) but
with identical structure: initial logging followed by a second logging inside 
an inlined
"transformer" processor that forms a nested span:

 

{{from("jms:queue:test")}}
{{    .log("Received message from jms queue")}}
{{  .process(exchange -> Observation}}
{{    .createNotStarted("jms-transformer", observationRegistry)}}
{{      .observe(() -> log.info("Transformed message from jms queue")));}}

 

*Expected behavior*

Expected behavior, as asserted by the integration tests for each route, is that 
traceId and spanId
are available in the MDC context (and hence present in both produced log 
lines), and that the
exported spans have the correct structure, i.e. two spans should be exported: 
one for the route
and a nested span for the transformation. These two spans should have the same 
(parent) traceId.

*Actual behavior*

The `rest` component route is configured to use the `servlet` component, and 
works as expected
(since the Spring Boot servlet in this situation correctly creates the trace, 
and root span).

The `cxf-rs` component defaults to use the `platform-http` component. In this 
case, a trace and
span is indeed created but not correctly associated. This effect is twofold:
 - The traceId and spanId are not set in the MDC for the route span, but they 
are set in the
"transformer" child span
 - The child span for the "transformer" processor is not nested, instead it 
gets a new traceId

The `jms` component behaves the same: traceId and spanId are not set in the MDC 
for the route span
and the child span for the "transformer" processor is not properly nested.

*Suggested fix*

The pull request in [https://github.com/apache/camel/pull/22410] corrects the 
observed behaviour.

 

Thanks for looking into it!

> OpenTelemetry/Micrometer traces are not correctly structured for 
> JMS-initiated routes
> -------------------------------------------------------------------------------------
>
>                 Key: CAMEL-23283
>                 URL: https://issues.apache.org/jira/browse/CAMEL-23283
>             Project: Camel
>          Issue Type: Task
>          Components: camel-tracing
>    Affects Versions: 4.15.0, 4.16.0, 4.17.0, 4.18.0, 4.18.1
>            Reporter: Bjorn Beskow
>            Priority: Minor
>         Attachments: jms-micrometer-observability.zip
>
>
> When using camel-micrometer-observability, traces and spans are not correctly 
> structured if a traceId and root span is not already present (as a result of 
> OTEL context propagation from the caller, or by a Spring Boot framework 
> component in front of the camel component).
> The effect is twofold:
>  * traceId and spanId is not put in the MDC context, and hence not present in 
> any logs created.
>  * Nested spans created programmatically using the Micrometer Observation API 
> are not properly nested (they get their own, unique traceId's).
> The attached sample project pinpoints the problem: For an exchange with a 
> "traceparent" propagated from the caller, everything works as expected. For 
> an exchange without a propagated existing trace, the tests show that the MDC 
> is not properly populated and any nested spans have the wrong structure.
> This seems to be caused by missing scope management: 
> MicrometerObservabilitySpanAdapter::activate() only calls span.start() but 
> doesn't put the
> span into the tracer's thread-local scope. This means tracer.currentSpan() 
> returns null during route execution, hence the span is invisible to e.g. 
> programmatic child span creation that relies on tracer.currentSpan() to find 
> a parent span (for example via the ObservationRegistry). It also becomes 
> invisible for the MDC context.



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

Reply via email to