You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2026/07/11 20:45:38 UTC
(camel) branch feature/CAMEL-24003-activity-span-enrichment created (now 684b49dcda6f)
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a change to branch feature/CAMEL-24003-activity-span-enrichment
in repository https://gitbox.apache.org/repos/asf/camel.git
at 684b49dcda6f CAMEL-24003: Enrich activity data with span decorator attributes from camel-telemetry
This branch includes the following new commits:
new 684b49dcda6f CAMEL-24003: Enrich activity data with span decorator attributes from camel-telemetry
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(camel) 01/01: CAMEL-24003: Enrich activity data with span decorator attributes from camel-telemetry
Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch feature/CAMEL-24003-activity-span-enrichment
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 684b49dcda6ff3a27711c309288448ef89850b40
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sat Jul 11 22:45:24 2026 +0200
CAMEL-24003: Enrich activity data with span decorator attributes from camel-telemetry
Co-Authored-By: Claude Opus 4.6 <no...@anthropic.com>
Signed-off-by: Claus Ibsen <cl...@gmail.com>
---
.../org/apache/camel/telemetry/RecordingSpan.java | 78 ++++++++++++++++++++++
.../java/org/apache/camel/telemetry/Tracer.java | 26 +++++++-
.../src/main/java/org/apache/camel/Exchange.java | 8 +++
.../java/org/apache/camel/ExchangePropertyKey.java | 5 +-
.../java/org/apache/camel/spi/BacklogTracer.java | 9 +++
5 files changed, 124 insertions(+), 2 deletions(-)
diff --git a/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/RecordingSpan.java b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/RecordingSpan.java
new file mode 100644
index 000000000000..28f40223d963
--- /dev/null
+++ b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/RecordingSpan.java
@@ -0,0 +1,78 @@
+/*
+ * 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.telemetry;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * A {@link Span} wrapper that records all {@code setTag} and {@code setComponent} calls into a {@link Map} while
+ * delegating every operation to the underlying span. This is used to capture span decorator attributes for the
+ * BacklogTracer activity enrichment without running decorator logic twice.
+ * <p>
+ * The recording is only activated when the BacklogTracer activity feature is enabled, so in production there is no
+ * wrapping overhead.
+ */
+class RecordingSpan implements Span {
+
+ private final Span delegate;
+ private final Map<String, String> tags = new LinkedHashMap<>();
+
+ RecordingSpan(Span delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public void setTag(String key, String value) {
+ delegate.setTag(key, value);
+ if (value != null) {
+ tags.put(key, value);
+ }
+ }
+
+ @Override
+ public void setComponent(String component) {
+ delegate.setComponent(component);
+ if (component != null) {
+ tags.put("component", component);
+ }
+ }
+
+ @Override
+ public void setError(boolean isError) {
+ delegate.setError(isError);
+ }
+
+ @Override
+ public void log(Map<String, String> fields) {
+ delegate.log(fields);
+ }
+
+ /**
+ * Returns the real span that this wrapper delegates to.
+ */
+ Span getDelegate() {
+ return delegate;
+ }
+
+ /**
+ * Returns the recorded tags as an unmodifiable snapshot.
+ */
+ Map<String, String> getRecordedTags() {
+ return Map.copyOf(tags);
+ }
+}
diff --git a/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/Tracer.java b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/Tracer.java
index 40d148fd5c88..91806d3fd62c 100644
--- a/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/Tracer.java
+++ b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/Tracer.java
@@ -24,11 +24,13 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePropertyKey;
import org.apache.camel.NamedNode;
import org.apache.camel.Route;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.StaticService;
import org.apache.camel.api.management.ManagedAttribute;
+import org.apache.camel.spi.BacklogTracer;
import org.apache.camel.spi.CamelEvent;
import org.apache.camel.spi.CamelLogger;
import org.apache.camel.spi.CamelTracingService;
@@ -68,6 +70,7 @@ public abstract class Tracer extends ServiceSupport implements CamelTracingServi
private final TracingEventNotifier eventNotifier = new TracingEventNotifier();
private final SpanStorageManager spanStorageManager = new SpanStorageManagerExchange();
private final SpanDecoratorManager spanDecoratorManager = new SpanDecoratorManagerImpl();
+ private boolean activityEnabled;
/*
* It has to be provided by the specific implementation
@@ -209,6 +212,13 @@ public abstract class Tracer extends ServiceSupport implements CamelTracingServi
InterceptStrategy interceptStrategy = new TraceProcessorsInterceptStrategy(this);
camelContext.getCamelContextExtension().addInterceptStrategy(interceptStrategy);
+ // check if BacklogTracer activity is enabled so we can enrich activity data with span attributes
+ BacklogTracer backlogTracer
+ = camelContext.getCamelContextExtension().getContextPlugin(BacklogTracer.class);
+ if (backlogTracer != null) {
+ activityEnabled = backlogTracer.isActivityEnabled();
+ }
+
initTracer();
ServiceHelper.startService(eventNotifier);
}
@@ -349,7 +359,21 @@ public abstract class Tracer extends ServiceSupport implements CamelTracingServi
Span span = spanLifecycleManager.create(spanName, spanKind, parentSpan,
spanDecorator.getExtractor(exchange));
span.setTag(TagConstants.OP, op.toString());
- spanDecorator.beforeTracingEvent(span, exchange, endpoint);
+
+ if (activityEnabled && op == Op.EVENT_SENT) {
+ // wrap with recording span to capture decorator attributes for activity enrichment
+ RecordingSpan recording = new RecordingSpan(span);
+ spanDecorator.beforeTracingEvent(recording, exchange, endpoint);
+ // store recorded tags on exchange for BacklogTracer activity to pick up
+ Map<String, String> tags = recording.getRecordedTags();
+ if (!tags.isEmpty()) {
+ exchange.setProperty(ExchangePropertyKey.ACTIVITY_SPAN_TAGS, tags);
+ }
+ // continue with the real span for activation/storage
+ } else {
+ spanDecorator.beforeTracingEvent(span, exchange, endpoint);
+ }
+
spanLifecycleManager.activate(span);
spanStorageManager.push(exchange, span);
spanLifecycleManager.inject(span, spanDecorator.getInjector(exchange), this.traceHeadersInclusion);
diff --git a/core/camel-api/src/main/java/org/apache/camel/Exchange.java b/core/camel-api/src/main/java/org/apache/camel/Exchange.java
index 27607438f0a8..ac8ec7044d75 100644
--- a/core/camel-api/src/main/java/org/apache/camel/Exchange.java
+++ b/core/camel-api/src/main/java/org/apache/camel/Exchange.java
@@ -327,6 +327,14 @@ public interface Exchange extends VariableAware {
String OTEL_ACTIVE_SPAN = "OpenTracing.activeSpan";
@Deprecated(since = "4.19.0")
String OTEL_CLOSE_CLIENT_SCOPE = "OpenTracing.closeClientScope";
+ /**
+ * Exchange property set by tracing implementations (e.g., camel-telemetry) containing span decorator attributes as a
+ * {@code Map<String, String>}. Used by the BacklogTracer activity feature to enrich endpoint send entries with
+ * component-specific details (e.g., Kafka topic, SQL query, HTTP method).
+ *
+ * @since 4.22
+ */
+ String ACTIVITY_SPAN_TAGS = "CamelActivitySpanTags";
/**
* Returns the {@link ExchangePattern} (MEP) of this exchange.
diff --git a/core/camel-api/src/main/java/org/apache/camel/ExchangePropertyKey.java b/core/camel-api/src/main/java/org/apache/camel/ExchangePropertyKey.java
index 8b4dd6415e0c..c3d9ed220f05 100644
--- a/core/camel-api/src/main/java/org/apache/camel/ExchangePropertyKey.java
+++ b/core/camel-api/src/main/java/org/apache/camel/ExchangePropertyKey.java
@@ -100,7 +100,8 @@ public enum ExchangePropertyKey {
@Deprecated(since = "4.19.0")
OTEL_ACTIVE_SPAN(Exchange.OTEL_ACTIVE_SPAN),
@Deprecated(since = "4.19.0")
- OTEL_CLOSE_CLIENT_SCOPE(Exchange.OTEL_CLOSE_CLIENT_SCOPE);
+ OTEL_CLOSE_CLIENT_SCOPE(Exchange.OTEL_CLOSE_CLIENT_SCOPE),
+ ACTIVITY_SPAN_TAGS(Exchange.ACTIVITY_SPAN_TAGS);
private final String name;
@@ -246,6 +247,8 @@ public enum ExchangePropertyKey {
// Deprecated since 4.19.0
case Exchange.OTEL_CLOSE_CLIENT_SCOPE:
return OTEL_CLOSE_CLIENT_SCOPE;
+ case Exchange.ACTIVITY_SPAN_TAGS:
+ return ACTIVITY_SPAN_TAGS;
default:
return null;
}
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/BacklogTracer.java b/core/camel-api/src/main/java/org/apache/camel/spi/BacklogTracer.java
index d56acdc2dde5..2596cd53ee3d 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/BacklogTracer.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/BacklogTracer.java
@@ -43,6 +43,15 @@ import org.jspecify.annotations.Nullable;
*/
public interface BacklogTracer {
+ /**
+ * Whether the activity tracking feature is enabled.
+ *
+ * @since 4.22
+ */
+ default boolean isActivityEnabled() {
+ return false;
+ }
+
/**
* Is the tracer enabled.
*/