This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch CAMEL-23225-remove-threadlocal-context-fallback
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 7a0636015350f06376259cfabcf405512f00eb18
Author: Guillaume Nodet <[email protected]>
AuthorDate: Wed Mar 25 10:51:39 2026 +0100

    CAMEL-23225: Remove ThreadLocal context fallback from camel-opentelemetry2
    
    - Remove BAGGAGE_CAMEL_FLAG / dirty context detection in create() method,
      always use Context.root() as base for extract()
    - Remove baggage flag logic and baggageScope from OpenTelemetrySpanAdapter
    - Delete OpenTelemetryInstrumentedThreadPoolFactory and
      OpenTelemetryInstrumentedThreadFactoryListener (Context.taskWrapping)
    - Remove corresponding META-INF service files
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
 .../org/apache/camel/thread-factory-listener       |  2 -
 .../services/org/apache/camel/thread-pool-factory  |  2 -
 ...TelemetryInstrumentedThreadFactoryListener.java | 32 ----------
 ...OpenTelemetryInstrumentedThreadPoolFactory.java | 69 ----------------------
 .../opentelemetry2/OpenTelemetrySpanAdapter.java   | 19 +-----
 .../camel/opentelemetry2/OpenTelemetryTracer.java  | 23 ++------
 6 files changed, 6 insertions(+), 141 deletions(-)

diff --git 
a/components/camel-opentelemetry2/src/generated/resources/META-INF/services/org/apache/camel/thread-factory-listener
 
b/components/camel-opentelemetry2/src/generated/resources/META-INF/services/org/apache/camel/thread-factory-listener
deleted file mode 100644
index 8cb98164902d..000000000000
--- 
a/components/camel-opentelemetry2/src/generated/resources/META-INF/services/org/apache/camel/thread-factory-listener
+++ /dev/null
@@ -1,2 +0,0 @@
-# Generated by camel build tools - do NOT edit this file!
-class=org.apache.camel.opentelemetry2.OpenTelemetryInstrumentedThreadFactoryListener
diff --git 
a/components/camel-opentelemetry2/src/generated/resources/META-INF/services/org/apache/camel/thread-pool-factory
 
b/components/camel-opentelemetry2/src/generated/resources/META-INF/services/org/apache/camel/thread-pool-factory
deleted file mode 100644
index 31eb3a73f0bc..000000000000
--- 
a/components/camel-opentelemetry2/src/generated/resources/META-INF/services/org/apache/camel/thread-pool-factory
+++ /dev/null
@@ -1,2 +0,0 @@
-# Generated by camel build tools - do NOT edit this file!
-class=org.apache.camel.opentelemetry2.OpenTelemetryInstrumentedThreadPoolFactory
diff --git 
a/components/camel-opentelemetry2/src/main/java/org/apache/camel/opentelemetry2/OpenTelemetryInstrumentedThreadFactoryListener.java
 
b/components/camel-opentelemetry2/src/main/java/org/apache/camel/opentelemetry2/OpenTelemetryInstrumentedThreadFactoryListener.java
deleted file mode 100644
index f2eaae4bcd06..000000000000
--- 
a/components/camel-opentelemetry2/src/main/java/org/apache/camel/opentelemetry2/OpenTelemetryInstrumentedThreadFactoryListener.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.opentelemetry2;
-
-import java.util.concurrent.ThreadFactory;
-
-import io.opentelemetry.context.Context;
-import org.apache.camel.spi.ExecutorServiceManager;
-import org.apache.camel.spi.annotations.JdkService;
-
-@JdkService(ExecutorServiceManager.ThreadFactoryListener.FACTORY)
-public class OpenTelemetryInstrumentedThreadFactoryListener implements 
ExecutorServiceManager.ThreadFactoryListener {
-
-    @Override
-    public ThreadFactory onNewThreadFactory(Object source, ThreadFactory 
factory) {
-        return runnable -> factory.newThread(Context.current().wrap(runnable));
-    }
-}
diff --git 
a/components/camel-opentelemetry2/src/main/java/org/apache/camel/opentelemetry2/OpenTelemetryInstrumentedThreadPoolFactory.java
 
b/components/camel-opentelemetry2/src/main/java/org/apache/camel/opentelemetry2/OpenTelemetryInstrumentedThreadPoolFactory.java
deleted file mode 100644
index 9c70dbaf1b19..000000000000
--- 
a/components/camel-opentelemetry2/src/main/java/org/apache/camel/opentelemetry2/OpenTelemetryInstrumentedThreadPoolFactory.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.opentelemetry2;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.RejectedExecutionHandler;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-
-import io.opentelemetry.context.Context;
-import org.apache.camel.spi.ThreadPoolFactory;
-import org.apache.camel.spi.ThreadPoolProfile;
-import org.apache.camel.spi.annotations.JdkService;
-import org.apache.camel.support.DefaultThreadPoolFactory;
-
-@JdkService(ThreadPoolFactory.FACTORY)
-public class OpenTelemetryInstrumentedThreadPoolFactory extends 
DefaultThreadPoolFactory {
-
-    @Override
-    public ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
-        return Context.taskWrapping(super.newCachedThreadPool(threadFactory));
-    }
-
-    @Override
-    public ExecutorService newThreadPool(
-            int corePoolSize,
-            int maxPoolSize,
-            long keepAliveTime,
-            TimeUnit timeUnit,
-            int maxQueueSize,
-            boolean allowCoreThreadTimeOut,
-            RejectedExecutionHandler rejectedExecutionHandler,
-            ThreadFactory threadFactory)
-            throws IllegalArgumentException {
-
-        ExecutorService executorService = super.newThreadPool(
-                corePoolSize,
-                maxPoolSize,
-                keepAliveTime,
-                timeUnit,
-                maxQueueSize,
-                allowCoreThreadTimeOut,
-                rejectedExecutionHandler,
-                threadFactory);
-
-        return Context.taskWrapping(executorService);
-    }
-
-    @Override
-    public ScheduledExecutorService newScheduledThreadPool(ThreadPoolProfile 
profile, ThreadFactory threadFactory) {
-        return Context.taskWrapping(super.newScheduledThreadPool(profile, 
threadFactory));
-    }
-
-}
diff --git 
a/components/camel-opentelemetry2/src/main/java/org/apache/camel/opentelemetry2/OpenTelemetrySpanAdapter.java
 
b/components/camel-opentelemetry2/src/main/java/org/apache/camel/opentelemetry2/OpenTelemetrySpanAdapter.java
index b6c7a0720215..bff54e03c098 100644
--- 
a/components/camel-opentelemetry2/src/main/java/org/apache/camel/opentelemetry2/OpenTelemetrySpanAdapter.java
+++ 
b/components/camel-opentelemetry2/src/main/java/org/apache/camel/opentelemetry2/OpenTelemetrySpanAdapter.java
@@ -18,7 +18,6 @@ package org.apache.camel.opentelemetry2;
 
 import java.util.Map;
 
-import io.opentelemetry.api.baggage.Baggage;
 import io.opentelemetry.api.common.Attributes;
 import io.opentelemetry.api.common.AttributesBuilder;
 import io.opentelemetry.api.trace.Span;
@@ -29,18 +28,12 @@ import org.apache.camel.telemetry.TagConstants;
 public class OpenTelemetrySpanAdapter implements 
org.apache.camel.telemetry.Span {
 
     private static final String DEFAULT_EVENT_NAME = "log";
-    static final String BAGGAGE_CAMEL_FLAG = "camelScope";
 
     private final Span otelSpan;
-    private final Baggage baggage;
     private Scope scope;
-    private Scope baggageScope;
 
-    protected OpenTelemetrySpanAdapter(Span otelSpan, Baggage baggage) {
+    protected OpenTelemetrySpanAdapter(Span otelSpan) {
         this.otelSpan = otelSpan;
-        // We store an important flag in the baggage in order to verify if the
-        // root span was generated internally or from a third party dependency.
-        this.baggage = baggage.toBuilder().put(BAGGAGE_CAMEL_FLAG, 
"true").build();
     }
 
     protected Span getSpan() {
@@ -49,7 +42,6 @@ public class OpenTelemetrySpanAdapter implements 
org.apache.camel.telemetry.Span
 
     protected void makeCurrent() {
         this.scope = this.otelSpan.makeCurrent();
-        this.baggageScope = this.baggage.makeCurrent();
     }
 
     protected void end() {
@@ -57,18 +49,11 @@ public class OpenTelemetrySpanAdapter implements 
org.apache.camel.telemetry.Span
     }
 
     protected void close() {
-        if (baggageScope != null) {
-            this.baggageScope.close();
-        }
         if (scope != null) {
             this.scope.close();
         }
     }
 
-    protected Baggage getBaggage() {
-        return this.baggage;
-    }
-
     @Override
     public void log(Map<String, String> fields) {
         this.otelSpan.addEvent(getEventNameFromFields(fields), 
convertToAttributes(fields));
@@ -126,7 +111,7 @@ public class OpenTelemetrySpanAdapter implements 
org.apache.camel.telemetry.Span
 
     @Override
     public String toString() {
-        return "OpenTelemetrySpanAdapter [span=" + otelSpan + ", baggage=" + 
baggage + "]";
+        return "OpenTelemetrySpanAdapter [span=" + otelSpan + "]";
     }
 
 }
diff --git 
a/components/camel-opentelemetry2/src/main/java/org/apache/camel/opentelemetry2/OpenTelemetryTracer.java
 
b/components/camel-opentelemetry2/src/main/java/org/apache/camel/opentelemetry2/OpenTelemetryTracer.java
index 381488b6e300..deb85b11b77b 100644
--- 
a/components/camel-opentelemetry2/src/main/java/org/apache/camel/opentelemetry2/OpenTelemetryTracer.java
+++ 
b/components/camel-opentelemetry2/src/main/java/org/apache/camel/opentelemetry2/OpenTelemetryTracer.java
@@ -17,7 +17,6 @@
 package org.apache.camel.opentelemetry2;
 
 import io.opentelemetry.api.GlobalOpenTelemetry;
-import io.opentelemetry.api.baggage.Baggage;
 import io.opentelemetry.api.trace.SpanBuilder;
 import io.opentelemetry.api.trace.Tracer;
 import io.opentelemetry.context.Context;
@@ -98,24 +97,14 @@ public class OpenTelemetryTracer extends 
org.apache.camel.telemetry.Tracer {
         @Override
         public Span create(String spanName, Span parent, 
SpanContextPropagationExtractor extractor) {
             SpanBuilder builder = tracer.spanBuilder(spanName);
-            Baggage baggage = null;
 
             if (parent != null) {
                 OpenTelemetrySpanAdapter otelParentSpan = 
(OpenTelemetrySpanAdapter) parent;
                 builder = 
builder.setParent(Context.current().with(otelParentSpan.getSpan()));
-                baggage = otelParentSpan.getBaggage();
             } else {
-                Context current = Context.root();
-                // If the current span was generated by Camel, then, this is a 
"dirty" context.
-                // A "dirty" context happens when the Camel thread local is 
reused and
-                // due to the way Camel async works, can't reliably clean its 
context before reusing it.
-                if 
(Baggage.current().getEntryValue(OpenTelemetrySpanAdapter.BAGGAGE_CAMEL_FLAG) 
== null) {
-                    // Not "dirty" context. In this case a Span exists and the 
current span was generated by some third party dependency (ie, vertx)
-                    // therefore we need to consider this span as the root on 
such a trace.
-                    current = Context.current();
-                }
-                // Try to get parent from context propagation (upstream traces)
-                Context ctx = 
contextPropagators.getTextMapPropagator().extract(current, extractor,
+                // Always use Context.root() as the base — context propagation 
is handled
+                // exclusively via Exchange headers (W3C traceparent), not 
ThreadLocal.
+                Context ctx = 
contextPropagators.getTextMapPropagator().extract(Context.root(), extractor,
                         new TextMapGetter<SpanContextPropagationExtractor>() {
                             @Override
                             public Iterable<String> 
keys(SpanContextPropagationExtractor carrier) {
@@ -132,10 +121,9 @@ public class OpenTelemetryTracer extends 
org.apache.camel.telemetry.Tracer {
                         });
 
                 builder = builder.setParent(ctx);
-                baggage = Baggage.fromContext(ctx);
             }
 
-            return new OpenTelemetrySpanAdapter(builder.startSpan(), baggage);
+            return new OpenTelemetrySpanAdapter(builder.startSpan());
         }
 
         @Override
@@ -160,9 +148,6 @@ public class OpenTelemetryTracer extends 
org.apache.camel.telemetry.Tracer {
         public void inject(Span span, SpanContextPropagationInjector injector, 
boolean includeTracing) {
             OpenTelemetrySpanAdapter otelSpan = (OpenTelemetrySpanAdapter) 
span;
             Context ctx = Context.current().with(otelSpan.getSpan());
-            if (otelSpan.getBaggage() != null) {
-                ctx = ctx.with(otelSpan.getBaggage());
-            }
             contextPropagators.getTextMapPropagator().inject(ctx, injector,
                     (carrier, key, value) -> carrier.put(key, value));
             if (includeTracing) {

Reply via email to