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

davsclaus pushed a commit to branch feat/camel-tui
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 02bfc17a8f33384ca8cd28178435aee5eaf41ecb
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon May 18 11:22:21 2026 +0200

    CAMEL-XXXX: rest-openapi mock mode now emits BacklogTracer trace events
    
    When missingOperation=mock and no route exists for an operation, the mock
    response was returned directly bypassing the normal route pipeline entirely,
    so no BacklogTracer trace events were recorded. The TUI inspect/trace tab
    therefore showed no activity for mocked operations.
    
    Fix by:
    - Adding shouldTrace(NamedNode, Exchange), traceBeforeNode(NamedNode, 
Exchange),
      traceAfterNode(NamedNode, Exchange), 
traceEvent(BacklogTracerEventMessage), and
      incrementTraceCounter() to the org.apache.camel.spi.BacklogTracer SPI 
interface
      (all already implemented in the concrete BacklogTracer class).
    - Implementing traceBeforeNode/traceAfterNode in the concrete BacklogTracer,
      building a DefaultBacklogTracerEventMessage with the exchange state.
    - Adding a MockOperationNode (minimal NamedNode) to 
DefaultRestOpenapiProcessorStrategy
      representing the mock operation, and calling 
traceBeforeNode/traceAfterNode around
      loadMockData() with a try/finally to guarantee the after event always 
fires.
    
    Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
---
 .../DefaultRestOpenapiProcessorStrategy.java       | 77 +++++++++++++++++++++-
 .../java/org/apache/camel/spi/BacklogTracer.java   | 40 +++++++++++
 .../apache/camel/impl/debugger/BacklogTracer.java  | 56 +++++++++++++++-
 3 files changed, 171 insertions(+), 2 deletions(-)

diff --git 
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
 
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
index 086e6d84fdc4..696f9e654394 100644
--- 
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
+++ 
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
@@ -36,10 +36,12 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
 import org.apache.camel.Endpoint;
 import org.apache.camel.Exchange;
+import org.apache.camel.NamedNode;
 import org.apache.camel.NonManagedService;
 import org.apache.camel.Route;
 import org.apache.camel.component.platform.http.PlatformHttpComponent;
 import org.apache.camel.component.platform.http.spi.PlatformHttpConsumerAware;
+import org.apache.camel.spi.BacklogTracer;
 import org.apache.camel.spi.PackageScanResourceResolver;
 import org.apache.camel.spi.ProducerCache;
 import org.apache.camel.spi.Resource;
@@ -208,7 +210,19 @@ public class DefaultRestOpenapiProcessorStrategy extends 
ServiceSupport
                         exchange.setRouteStop(true);
                     } else if ("mock".equalsIgnoreCase(missingOperation)) {
                         // no route then try to load mock data as the answer
-                        loadMockData(operation, verb, path, exchange);
+                        BacklogTracer backlogTracer
+                                = 
camelContext.getCamelContextExtension().getContextPlugin(BacklogTracer.class);
+                        NamedNode mockNode = new MockOperationNode(verb, path, 
operation.getOperationId());
+                        if (backlogTracer != null && 
backlogTracer.isEnabled()) {
+                            backlogTracer.traceBeforeNode(mockNode, exchange);
+                        }
+                        try {
+                            loadMockData(operation, verb, path, exchange);
+                        } finally {
+                            if (backlogTracer != null && 
backlogTracer.isEnabled()) {
+                                backlogTracer.traceAfterNode(mockNode, 
exchange);
+                            }
+                        }
                     }
                     if (requestError == null) {
                         var responseError = 
binding.doClientResponseValidation(exchange);
@@ -441,4 +455,65 @@ public class DefaultRestOpenapiProcessorStrategy extends 
ServiceSupport
         }
     }
 
+    /**
+     * Minimal {@link NamedNode} to represent a mocked OpenAPI operation for 
tracing purposes.
+     */
+    private static final class MockOperationNode implements NamedNode {
+
+        private final String id;
+        private final String label;
+
+        private MockOperationNode(String verb, String path, String 
operationId) {
+            this.id = operationId != null ? operationId : verb + ":" + path;
+            this.label = "mock:" + verb + ":" + path;
+        }
+
+        @Override
+        public String getId() {
+            return id;
+        }
+
+        @Override
+        public String getNodePrefixId() {
+            return null;
+        }
+
+        @Override
+        public String getShortName() {
+            return "mock";
+        }
+
+        @Override
+        public String getLabel() {
+            return label;
+        }
+
+        @Override
+        public String getDescriptionText() {
+            return null;
+        }
+
+        @Override
+        public NamedNode getParent() {
+            return null;
+        }
+
+        @Override
+        public int getLineNumber() {
+            return -1;
+        }
+
+        @Override
+        public void setLineNumber(int lineNumber) {
+        }
+
+        @Override
+        public String getLocation() {
+            return null;
+        }
+
+        @Override
+        public void setLocation(String location) {
+        }
+    }
 }
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 7667775c5f2f..4c514e2a9318 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
@@ -19,6 +19,8 @@ package org.apache.camel.spi;
 import java.util.Collection;
 import java.util.List;
 
+import org.apache.camel.Exchange;
+import org.apache.camel.NamedNode;
 import org.jspecify.annotations.Nullable;
 
 /**
@@ -181,6 +183,13 @@ public interface BacklogTracer {
      */
     long getTraceCounter();
 
+    /**
+     * Increments and returns the trace counter.
+     *
+     * @since 4.21
+     */
+    long incrementTraceCounter();
+
     /**
      * Number of traced messages in the backlog
      */
@@ -191,6 +200,37 @@ public interface BacklogTracer {
      */
     void resetTraceCounter();
 
+    /**
+     * Whether the tracer should trace the given node and exchange (taking 
into account patterns and filters).
+     *
+     * @since 4.21
+     */
+    boolean shouldTrace(NamedNode node, Exchange exchange);
+
+    /**
+     * Trace a "before node" event for components that process exchanges 
inline and bypass the normal route pipeline
+     * (e.g. mock mode in rest-openapi consumer). The concrete implementation 
builds and stores the trace event.
+     *
+     * @since 4.21
+     */
+    void traceBeforeNode(NamedNode node, Exchange exchange);
+
+    /**
+     * Trace an "after node" event for components that process exchanges 
inline and bypass the normal route pipeline
+     * (e.g. mock mode in rest-openapi consumer). The concrete implementation 
builds and stores the trace event.
+     *
+     * @since 4.21
+     */
+    void traceAfterNode(NamedNode node, Exchange exchange);
+
+    /**
+     * Records a trace event. Used by components that handle processing inline 
(e.g. mock mode in rest-openapi consumer)
+     * and therefore bypass the normal route pipeline where tracing is applied 
automatically.
+     *
+     * @since 4.21
+     */
+    void traceEvent(BacklogTracerEventMessage event);
+
     /**
      * Get all tracing data (without removing)
      */
diff --git 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/BacklogTracer.java
 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/BacklogTracer.java
index 3f75319df11e..0bad0466d434 100644
--- 
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/BacklogTracer.java
+++ 
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/BacklogTracer.java
@@ -27,11 +27,14 @@ import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePropertyKey;
 import org.apache.camel.NamedNode;
 import org.apache.camel.Predicate;
 import org.apache.camel.spi.BacklogTracerEventMessage;
 import org.apache.camel.spi.Language;
 import org.apache.camel.support.CamelContextHelper;
+import org.apache.camel.support.LoggerHelper;
+import org.apache.camel.support.MessageHelper;
 import org.apache.camel.support.PatternHelper;
 import org.apache.camel.support.service.ServiceSupport;
 import org.apache.camel.util.StringHelper;
@@ -98,6 +101,7 @@ public class BacklogTracer extends ServiceSupport implements 
org.apache.camel.sp
      * @param  exchange   the exchange
      * @return            <tt>true</tt> to trace, <tt>false</tt> to skip 
tracing
      */
+    @Override
     public boolean shouldTrace(NamedNode definition, Exchange exchange) {
         // special in standby mode we allow using tracer to capture latest 
tracing data for
         // enriched message history
@@ -138,7 +142,56 @@ public class BacklogTracer extends ServiceSupport 
implements org.apache.camel.sp
         return false;
     }
 
-    public void traceEvent(DefaultBacklogTracerEventMessage event) {
+    @Override
+    public void traceBeforeNode(NamedNode node, Exchange exchange) {
+        if (!shouldTrace(node, exchange)) {
+            return;
+        }
+        long timestamp = System.currentTimeMillis();
+        String toNode = node.getId();
+        String toNodeParentId = node.getParentId();
+        String toNodeShortName = node.getShortName();
+        String toNodeLabel = StringHelper.limitLength(node.getLabel(), 50);
+        String exchangeId = exchange.getExchangeId();
+        String correlationExchangeId = 
exchange.getProperty(ExchangePropertyKey.CORRELATION_ID, String.class);
+        int level = node.getLevel();
+        String fromRouteId = exchange.getFromRouteId();
+        String source = LoggerHelper.getLineNumberLoggerName(node);
+        JsonObject data = MessageHelper.dumpAsJSonObject(exchange.getIn(), 
isIncludeExchangeProperties(),
+                isIncludeExchangeVariables(), true, true, 
isBodyIncludeStreams(), isBodyIncludeFiles(), getBodyMaxChars());
+        DefaultBacklogTracerEventMessage event = new 
DefaultBacklogTracerEventMessage(
+                camelContext, false, false, incrementTraceCounter(), 
timestamp, source, fromRouteId, null, toNode,
+                toNodeParentId, null, null, toNodeShortName, toNodeLabel, 
level,
+                exchangeId, correlationExchangeId, false, false, data);
+        traceEvent(event);
+    }
+
+    @Override
+    public void traceAfterNode(NamedNode node, Exchange exchange) {
+        if (!shouldTrace(node, exchange)) {
+            return;
+        }
+        long timestamp = System.currentTimeMillis();
+        String toNode = node.getId();
+        String toNodeParentId = node.getParentId();
+        String toNodeShortName = node.getShortName();
+        String toNodeLabel = StringHelper.limitLength(node.getLabel(), 50);
+        String exchangeId = exchange.getExchangeId();
+        String correlationExchangeId = 
exchange.getProperty(ExchangePropertyKey.CORRELATION_ID, String.class);
+        int level = node.getLevel();
+        String fromRouteId = exchange.getFromRouteId();
+        String source = LoggerHelper.getLineNumberLoggerName(node);
+        JsonObject data = MessageHelper.dumpAsJSonObject(exchange.getIn(), 
isIncludeExchangeProperties(),
+                isIncludeExchangeVariables(), true, true, 
isBodyIncludeStreams(), isBodyIncludeFiles(), getBodyMaxChars());
+        DefaultBacklogTracerEventMessage event = new 
DefaultBacklogTracerEventMessage(
+                camelContext, false, true, incrementTraceCounter(), timestamp, 
source, fromRouteId, null, toNode,
+                toNodeParentId, null, null, toNodeShortName, toNodeLabel, 
level,
+                exchangeId, correlationExchangeId, false, false, data);
+        traceEvent(event);
+    }
+
+    @Override
+    public void traceEvent(BacklogTracerEventMessage event) {
         // special in standby mode we allow using tracer to capture latest 
tracing data for
         // enriched message history
         boolean history = (enabled || standby) && 
camelContext.isMessageHistory();
@@ -495,6 +548,7 @@ public class BacklogTracer extends ServiceSupport 
implements org.apache.camel.sp
         provisionalHistoryQueue.clear();
     }
 
+    @Override
     public long incrementTraceCounter() {
         return traceCounter.incrementAndGet();
     }

Reply via email to