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

fmariani pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new c675990fea1d camel-telemetry: fix trace context propagation for 
messaging components
c675990fea1d is described below

commit c675990fea1d70182a79ac3938b88439eccb5ab0
Author: Croway <[email protected]>
AuthorDate: Fri Apr 10 14:45:17 2026 +0200

    camel-telemetry: fix trace context propagation for messaging components
    
    AbstractMessagingSpanDecorator used the default
    CamelHeadersSpanContextPropagationExtractor which only handles
    String-valued headers. Messaging transports like Kafka deliver
    headers as byte[], so trace context headers (e.g. traceparent)
    were silently dropped, breaking distributed trace propagation.
    
    Add CamelMessagingHeadersSpanContextPropagationExtractor that
    handles both String and byte[] headers, and override getExtractor()
    in AbstractMessagingSpanDecorator so all messaging components
    (Kafka, AMQP, SJMS, STOMP, Spring RabbitMQ, Azure Service Bus,
    etc.) benefit from the fix.
    
    The issue was discovered while upgrading the camel-spring-boot
    opentelemetry example from camel-opentelemetry to
    camel-opentelemetry2.
---
 ...amelHeadersSpanContextPropagationExtractor.java | 14 ++++++--
 .../CamelHeadersExtractAdapterTest.java            | 37 ++++++++++++++++++++++
 2 files changed, 48 insertions(+), 3 deletions(-)

diff --git 
a/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/propagation/CamelHeadersSpanContextPropagationExtractor.java
 
b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/propagation/CamelHeadersSpanContextPropagationExtractor.java
index b49bd40e31b2..a2df59633f50 100644
--- 
a/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/propagation/CamelHeadersSpanContextPropagationExtractor.java
+++ 
b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/propagation/CamelHeadersSpanContextPropagationExtractor.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.telemetry.propagation;
 
+import java.nio.charset.StandardCharsets;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
@@ -27,9 +28,16 @@ public final class 
CamelHeadersSpanContextPropagationExtractor implements SpanCo
     private final Map<String, Object> map = new CaseInsensitiveMap();
 
     public CamelHeadersSpanContextPropagationExtractor(final Map<String, 
Object> map) {
-        // Extract string valued map entries
-        map.entrySet().stream().filter(e -> e.getValue() instanceof String)
-                .forEach(e -> this.map.put(e.getKey(), e.getValue()));
+        // Extract string and byte[] valued map entries.
+        // Messaging transports (Kafka, AMQP, etc.) may deliver headers as 
byte arrays,
+        // so we convert them to String for the W3C propagator to extract 
trace context.
+        map.entrySet().stream().filter(e -> e.getValue() instanceof String || 
e.getValue() instanceof byte[]).forEach(e -> {
+            if (e.getValue() instanceof byte[] bytes) {
+                this.map.put(e.getKey(), new String(bytes, 
StandardCharsets.UTF_8));
+            } else {
+                this.map.put(e.getKey(), e.getValue());
+            }
+        });
     }
 
     @Override
diff --git 
a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/propagation/CamelHeadersExtractAdapterTest.java
 
b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/propagation/CamelHeadersExtractAdapterTest.java
index b3c609ef9375..dc4d5b3b3386 100644
--- 
a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/propagation/CamelHeadersExtractAdapterTest.java
+++ 
b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/propagation/CamelHeadersExtractAdapterTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.telemetry.propagation;
 
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -26,6 +27,8 @@ import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 public class CamelHeadersExtractAdapterTest {
 
@@ -69,4 +72,38 @@ public class CamelHeadersExtractAdapterTest {
         SpanContextPropagationExtractor adapter = new 
CamelHeadersSpanContextPropagationExtractor(map);
         assertEquals("value", adapter.get("KeY"));
     }
+
+    @Test
+    public void byteArrayProperty() {
+        map.put("traceparent", 
"00-abc123-def456-01".getBytes(StandardCharsets.UTF_8));
+        SpanContextPropagationExtractor adapter = new 
CamelHeadersSpanContextPropagationExtractor(map);
+        assertEquals("00-abc123-def456-01", adapter.get("traceparent"));
+    }
+
+    @Test
+    public void mixedStringAndByteArrayProperties() {
+        map.put("traceparent", 
"00-abc123-def456-01".getBytes(StandardCharsets.UTF_8));
+        map.put("custom-header", "custom-value");
+        SpanContextPropagationExtractor adapter = new 
CamelHeadersSpanContextPropagationExtractor(map);
+        assertEquals("00-abc123-def456-01", adapter.get("traceparent"));
+        assertEquals("custom-value", adapter.get("custom-header"));
+    }
+
+    @Test
+    public void nonStringNonByteArrayPropertyIsFiltered() {
+        map.put("integer-header", 42);
+        map.put("key", "value");
+        SpanContextPropagationExtractor adapter = new 
CamelHeadersSpanContextPropagationExtractor(map);
+        assertNull(adapter.get("integer-header"));
+        assertEquals("value", adapter.get("key"));
+        assertTrue(adapter.keys().contains("key"));
+        assertFalse(adapter.keys().contains("integer-header"));
+    }
+
+    @Test
+    public void byteArrayKeyWithDifferentCase() {
+        map.put("traceparent", 
"00-abc123-def456-01".getBytes(StandardCharsets.UTF_8));
+        SpanContextPropagationExtractor adapter = new 
CamelHeadersSpanContextPropagationExtractor(map);
+        assertEquals("00-abc123-def456-01", adapter.get("TraceParent"));
+    }
 }

Reply via email to