[
https://issues.apache.org/jira/browse/CAMEL-23349?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18078688#comment-18078688
]
Bjorn Beskow commented on CAMEL-23349:
--------------------------------------
Thanks, now we are getting close!
With [https://github.com/apache/camel/pull/22781], it is now possible to use
the OpenTelemetry api (as suggested by your BaggageInjectionInternalTest, but
with a slight modification to make the scope handling thread safe by storing it
on the exchange, and more robust by closing it in onCompletion):
{code:language=java}
from("direct:start")
.process(exchange -> {
Scope scope = Baggage.current().toBuilder().put("tenant.id",
"1234").build().makeCurrent();
exchange.setProperty("BaggageScope", scope);
})
.onCompletion()
.process(exchange -> {
Scope baggageScope = exchange.getProperty("BaggageScope",
Scope.class);
if (baggageScope != null) {
baggageScope.close();
exchange.removeProperty("BaggageScope");
}
})
.end()
.routeId("start")
.log("A message")
.process(exchange -> {
assertEquals("1234", Baggage.current().getEntryValue("tenant.id"));
})
.to("log:info");
{code}
It worked consistently regardless of traceProcessor being true or false.
The explicit scope handling/closing is a little verbose, but straight-forward
and robust (and very similar to how to do it in other frameworks, e.g. Spring
Integration).
Unfortunately, with [https://github.com/apache/camel/pull/22916] it stopped
working again :(. More specifically, the
{{TraceProcessorsOtelInterceptStrategy}} overwrites the baggage created in the
processor with what was originally stored in the {\{OpenTelemetrySpanAdapter}}:
{code:language=java}
Span activeSpan = spanStorage.peek(exchange);
if (activeSpan != null) {
OpenTelemetrySpanAdapter otelSpan = (OpenTelemetrySpanAdapter)
activeSpan;
try (Scope scope = otelSpan.getSpan().makeCurrent();
Scope baggageScope = otelSpan.getBaggage().makeCurrent()) { //
<----- here{code}
> Camel OpenTelemetry2 programmatic baggage management
> ----------------------------------------------------
>
> Key: CAMEL-23349
> URL: https://issues.apache.org/jira/browse/CAMEL-23349
> Project: Camel
> Issue Type: Improvement
> Components: camel-opentelemetry
> Affects Versions: 4.18.1, 4.19.0
> Reporter: Bjorn Beskow
> Assignee: Pasquale Congiusti
> Priority: Major
> Fix For: 4.20.0
>
>
> With Camel OpenTelemetry2 and OpenTelemetry spring boot starter, most aspects
> of Span Customization such as adding attributes, events and creating nested
> spans can be done using the OpenTelemetry apis. Programmatically adding OTEL
> baggage is however an exception. The typical use case for OTEL baggage is to
> allow for small pieces of contextual data that need to travel with a request
> across distributed service boundaries, independent of any single span. In our
> business context, it is in the form of a "business correlation id" that is
> captured from a header or from the message payload as the very first
> processor of a boundary component, and should be available to all downstream
> components.
> The OTEL api itself cannot easily be used to add baggage items to a Camel
> route, due to `Scope` handling: Baggage must be added to a baggage scope, and
> is visible and propagated during the lifetime of the scope. The OTEL api
> looks like this:
> // Create baggage with an entry
> Baggage baggage = Baggage.current().builder()
> .put("user-id", "12345")
> .build();
> // Attach baggage to current context
> Context contextWithBaggage = Context.current().with(baggage);
> // Make it current (scoped)
> try (var scope = contextWithBaggage.makeCurrent())
> { // Your code here - baggage is now active }
> Doing this in a processor, the scope instance must be kept open as long as
> needed, typically until the end of the exchange. In theory, the following
> simple albeit brittle solution should work:
>
> Baggage baggage = Baggage.current().toBuilder()
> .put("user-id", "12345")
> .build();
> Context ctxWithBaggage = Context.current().with(baggage);
> Scope scope = ctxWithBaggage.makeCurrent();
> exchange.getExchangeExtension().addOnCompletion(new SynchronizationAdapter() {
> @Override public void onDone(Exchange exchange)
> { scope.close(); }
> });
> In practice however, this doesn't work. A (final) baggageScope is already
> (automatically) created at the start of a Camel route execution, stored on
> the exchange as part of a wrapped instance of
> org.apache.camel.opentelemetry2.OpenTelemetrySpanAdapter and properly closed
> at the end of the route. It is this baggageScope that is passed to the OTEL
> propagator, not the scope created programmatically as in the example above.
> Hence the programmatically added baggage entry will not be propagated.
> To my understanding, the simplest way to programmatically add baggage items
> would be to allow for mutating the baggage scope stored in the
> org.apache.camel.opentelemetry2.OpenTelemetrySpanAdapter. The required pieces
> are already present, but would need to be exposed in a public API (currently,
> both context, baggage and baggage scope are protected).
--
This message was sent by Atlassian Jira
(v8.20.10#820010)