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

Bjorn Beskow commented on CAMEL-23349:
--------------------------------------

The solution provided by the [https://github.com/apache/camel/pull/22705] PR 
may be sufficient in those cases where spans are created automatically for each 
processor (using traceProcessors=true), or when no additional OTEL-aware 
libraries (such as SLF4j or Logback Appenders or additional instrumentation) 
needs access to the baggage using the OTEL apis (i.e. Baggage.current()). It 
provides a very Camel-idiomatic and hence Tracing Technology-agnostic api for 
managing baggage, and makes perfect sense if no OTEL-specific apis are used.

Baggage is however an OTEL-specific concept. As such, I still think it also 
makes sense with a solution that is fully aligned with the semantics of the 
OTEL apis. If using OTEL api's, a baggage entry set using the Baggage setter 
API should be accessible using the Baggage getter api (not just under specific 
circumstances such as in a subsequent span).

Hence I still think it would be reasonable with an (OTEL-specific) solution. 
Having thought more about it, I would like to suggest a BaggageAdapter that 
adapts the OTEL Baggage settings api to the specifics of the Camel Exchange 
lifecycle.

Using the standard OTEL api, baggage is added like this:

// Create baggage and attach it to the current context
Baggage baggage = Baggage.builder()
  .put("tenant.id", "1234")
  .build();

// Make it current (attaches to context)
try (Scope scope = baggage.storeInContext(Context.current()).makeCurrent()) {
  // All code inside this block has access to the baggage
  doSomethingThatPropagatesBaggage();
}

It is the last part that clashes with the specifics of the Camel Exchange 
lifecycle, and would need to be adapted.

An mimimal adapter could look like this:

.process(exchange -> {
  BaggageAdapter.builder(exchange)
    .put("tenant.id", "1234")
    .build();
    // All code inside the current span of this exchange has access to the 
baggage
    ...
}

Such an OTEL-specific BaggageAdapter could exist in tandem with the 
Camel-centric header-based solution.

It would only be usable for Camel users that also depend on and have committed 
to use the OTEL apis and SDKs in other places (such as OTEL log appenders), and 
hence the adapter being OTEL-specific is not an issue.

[~squakez] let me know what you think!

> 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)

Reply via email to