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 2023/11/17 13:39:39 UTC

(camel) branch standby created (now baca9f8cf05)

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

davsclaus pushed a change to branch standby
in repository https://gitbox.apache.org/repos/asf/camel.git


      at baca9f8cf05 CAMEL-20067: camel-core - Add debuggingStandby option

This branch includes the following new commits:

     new ef8c4cf44d5 CAMEL-20067: camel-core - Add debuggingStandby option
     new baca9f8cf05 CAMEL-20067: camel-core - Add debuggingStandby option

The 2 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/02: CAMEL-20067: camel-core - Add debuggingStandby option

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit ef8c4cf44d5188a5c64751ffdb041629c9993901
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Nov 17 14:11:06 2023 +0100

    CAMEL-20067: camel-core - Add debuggingStandby option
---
 .../main/camel-main-configuration-metadata.json    |   1 +
 .../component/debug/CamelDebuggerFactory.java      |   5 +-
 .../java/org/apache/camel/spi/BacklogDebugger.java |  16 +++
 .../impl/debugger/DefaultBacklogDebugger.java      |  11 ++
 .../apache/camel/impl/console/DebugDevConsole.java |   6 +-
 .../DebuggerConfigurationPropertiesConfigurer.java |   6 +
 .../camel-main-configuration-metadata.json         |   1 +
 core/camel-main/src/main/docs/main.adoc            |   3 +-
 .../org/apache/camel/main/BaseMainSupport.java     |   6 +-
 .../main/DebuggerConfigurationProperties.java      |  23 ++++
 .../mbean/ManagedBacklogDebuggerMBean.java         |   3 +
 .../management/mbean/ManagedBacklogDebugger.java   |   5 +
 .../management/BacklogDebuggerStandbyTest.java     | 126 +++++++++++++++++++++
 .../camel/management/BacklogDebuggerTest.java      |   3 +
 14 files changed, 211 insertions(+), 4 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
index 8e56959bc3c..b5d6c587081 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
@@ -153,6 +153,7 @@
     { "name": "camel.debug.includeExchangeProperties", "description": "Whether to include the exchange properties in the traced message", "sourceType": "org.apache.camel.main.DebuggerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true },
     { "name": "camel.debug.loggingLevel", "description": "The debugger logging level to use when logging activity.", "sourceType": "org.apache.camel.main.DebuggerConfigurationProperties", "type": "object", "javaType": "org.apache.camel.LoggingLevel", "defaultValue": "INFO", "enum": [ "ERROR", "WARN", "INFO", "DEBUG", "TRACE", "OFF" ] },
     { "name": "camel.debug.singleStepIncludeStartEnd", "description": "In single step mode, then when the exchange is created and completed, then simulate a breakpoint at start and end, that allows to suspend and watch the incoming\/complete exchange at the route (you can see message body as response, failed exception etc).", "sourceType": "org.apache.camel.main.DebuggerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
+    { "name": "camel.debug.standby", "description": "To set the debugger in standby mode, where the debugger will be installed by not automatic enabled. The debugger can then later be enabled explicit from Java, JMX or tooling.", "sourceType": "org.apache.camel.main.DebuggerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.debug.waitForAttach", "description": "Whether the debugger should suspend on startup, and wait for a remote debugger to attach. This is what the IDEA and VSCode tooling is using.", "sourceType": "org.apache.camel.main.DebuggerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.faulttolerance.bulkheadEnabled", "description": "Whether bulkhead is enabled or not on the circuit breaker. Default is false.", "sourceType": "org.apache.camel.main.FaultToleranceConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean", "defaultValue": false },
     { "name": "camel.faulttolerance.bulkheadExecutorService", "description": "References to a custom thread pool to use when bulkhead is enabled.", "sourceType": "org.apache.camel.main.FaultToleranceConfigurationProperties", "type": "string", "javaType": "java.lang.String" },
diff --git a/components/camel-debug/src/main/java/org/apache/camel/component/debug/CamelDebuggerFactory.java b/components/camel-debug/src/main/java/org/apache/camel/component/debug/CamelDebuggerFactory.java
index 6dd9e4bae11..f2842d56b60 100644
--- a/components/camel-debug/src/main/java/org/apache/camel/component/debug/CamelDebuggerFactory.java
+++ b/components/camel-debug/src/main/java/org/apache/camel/component/debug/CamelDebuggerFactory.java
@@ -37,7 +37,10 @@ public class CamelDebuggerFactory implements DebuggerFactory {
             camelContext.addLifecycleStrategy(new LifecycleStrategySupport() {
                 @Override
                 public void onContextStarted(CamelContext context) {
-                    backlog.enableDebugger();
+                    // only enable debugger if not in standby mode
+                    if (!backlog.isStandby()) {
+                        backlog.enableDebugger();
+                    }
                 }
 
                 @Override
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/BacklogDebugger.java b/core/camel-api/src/main/java/org/apache/camel/spi/BacklogDebugger.java
index 284f33844fa..b8582c98f12 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/BacklogDebugger.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/BacklogDebugger.java
@@ -95,6 +95,22 @@ public interface BacklogDebugger extends StatefulService {
      */
     boolean isEnabled();
 
+    /**
+     * Whether the debugger is standby.
+     * <p>
+     * If a debugger is in standby then the tracer is activated during startup and are ready to be enabled manually via
+     * JMX or calling the enableDebugger method.
+     */
+    boolean isStandby();
+
+    /**
+     * Whether the debugger is standby.
+     * <p>
+     * If a debugger is in standby then the tracer is activated during startup and are ready to be enabled manually via
+     * JMX or calling the enableDebugger method.
+     */
+    void setStandby(boolean standby);
+
     /**
      * Does the node have a breakpoint
      */
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogDebugger.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogDebugger.java
index e37fccaecc5..dacb5bbee3a 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogDebugger.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogDebugger.java
@@ -65,6 +65,7 @@ public final class DefaultBacklogDebugger extends ServiceSupport implements Back
     private LoggingLevel loggingLevel = LoggingLevel.INFO;
     private final CamelLogger logger = new CamelLogger(LOG, loggingLevel);
     private final AtomicBoolean enabled = new AtomicBoolean();
+    private final AtomicBoolean standby = new AtomicBoolean();
     private final AtomicLong debugCounter = new AtomicLong();
     private final Debugger debugger;
     private final ConcurrentMap<String, NodeBreakpoint> breakpoints = new ConcurrentHashMap<>();
@@ -199,6 +200,16 @@ public final class DefaultBacklogDebugger extends ServiceSupport implements Back
         return enabled.get();
     }
 
+    @Override
+    public boolean isStandby() {
+        return standby.get();
+    }
+
+    @Override
+    public void setStandby(boolean standby) {
+        this.standby.set(standby);
+    }
+
     @Override
     public boolean hasBreakpoint(String nodeId) {
         return breakpoints.containsKey(nodeId);
diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/DebugDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/DebugDevConsole.java
index 6f6540ce673..161a458ce81 100644
--- a/core/camel-console/src/main/java/org/apache/camel/impl/console/DebugDevConsole.java
+++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/DebugDevConsole.java
@@ -107,7 +107,11 @@ public class DebugDevConsole extends AbstractDevConsole {
             return;
         }
 
-        if ("attach".equalsIgnoreCase(command)) {
+        if ("enable".equalsIgnoreCase(command)) {
+            backlog.enableDebugger();
+        } else if ("disable".equalsIgnoreCase(command)) {
+            backlog.disableDebugger();
+        } else if ("attach".equalsIgnoreCase(command)) {
             backlog.attach();
         } else if ("detach".equalsIgnoreCase(command)) {
             backlog.detach();
diff --git a/core/camel-main/src/generated/java/org/apache/camel/main/DebuggerConfigurationPropertiesConfigurer.java b/core/camel-main/src/generated/java/org/apache/camel/main/DebuggerConfigurationPropertiesConfigurer.java
index 811756e0a99..c9b2f6c3d92 100644
--- a/core/camel-main/src/generated/java/org/apache/camel/main/DebuggerConfigurationPropertiesConfigurer.java
+++ b/core/camel-main/src/generated/java/org/apache/camel/main/DebuggerConfigurationPropertiesConfigurer.java
@@ -41,6 +41,8 @@ public class DebuggerConfigurationPropertiesConfigurer extends org.apache.camel.
         case "LoggingLevel": target.setLoggingLevel(property(camelContext, org.apache.camel.LoggingLevel.class, value)); return true;
         case "singlestepincludestartend":
         case "SingleStepIncludeStartEnd": target.setSingleStepIncludeStartEnd(property(camelContext, boolean.class, value)); return true;
+        case "standby":
+        case "Standby": target.setStandby(property(camelContext, boolean.class, value)); return true;
         case "waitforattach":
         case "WaitForAttach": target.setWaitForAttach(property(camelContext, boolean.class, value)); return true;
         default: return false;
@@ -70,6 +72,8 @@ public class DebuggerConfigurationPropertiesConfigurer extends org.apache.camel.
         case "LoggingLevel": return org.apache.camel.LoggingLevel.class;
         case "singlestepincludestartend":
         case "SingleStepIncludeStartEnd": return boolean.class;
+        case "standby":
+        case "Standby": return boolean.class;
         case "waitforattach":
         case "WaitForAttach": return boolean.class;
         default: return null;
@@ -100,6 +104,8 @@ public class DebuggerConfigurationPropertiesConfigurer extends org.apache.camel.
         case "LoggingLevel": return target.getLoggingLevel();
         case "singlestepincludestartend":
         case "SingleStepIncludeStartEnd": return target.isSingleStepIncludeStartEnd();
+        case "standby":
+        case "Standby": return target.isStandby();
         case "waitforattach":
         case "WaitForAttach": return target.isWaitForAttach();
         default: return null;
diff --git a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
index 8e56959bc3c..b5d6c587081 100644
--- a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
+++ b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
@@ -153,6 +153,7 @@
     { "name": "camel.debug.includeExchangeProperties", "description": "Whether to include the exchange properties in the traced message", "sourceType": "org.apache.camel.main.DebuggerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true },
     { "name": "camel.debug.loggingLevel", "description": "The debugger logging level to use when logging activity.", "sourceType": "org.apache.camel.main.DebuggerConfigurationProperties", "type": "object", "javaType": "org.apache.camel.LoggingLevel", "defaultValue": "INFO", "enum": [ "ERROR", "WARN", "INFO", "DEBUG", "TRACE", "OFF" ] },
     { "name": "camel.debug.singleStepIncludeStartEnd", "description": "In single step mode, then when the exchange is created and completed, then simulate a breakpoint at start and end, that allows to suspend and watch the incoming\/complete exchange at the route (you can see message body as response, failed exception etc).", "sourceType": "org.apache.camel.main.DebuggerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
+    { "name": "camel.debug.standby", "description": "To set the debugger in standby mode, where the debugger will be installed by not automatic enabled. The debugger can then later be enabled explicit from Java, JMX or tooling.", "sourceType": "org.apache.camel.main.DebuggerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.debug.waitForAttach", "description": "Whether the debugger should suspend on startup, and wait for a remote debugger to attach. This is what the IDEA and VSCode tooling is using.", "sourceType": "org.apache.camel.main.DebuggerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.faulttolerance.bulkheadEnabled", "description": "Whether bulkhead is enabled or not on the circuit breaker. Default is false.", "sourceType": "org.apache.camel.main.FaultToleranceConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean", "defaultValue": false },
     { "name": "camel.faulttolerance.bulkheadExecutorService", "description": "References to a custom thread pool to use when bulkhead is enabled.", "sourceType": "org.apache.camel.main.FaultToleranceConfigurationProperties", "type": "string", "javaType": "java.lang.String" },
diff --git a/core/camel-main/src/main/docs/main.adoc b/core/camel-main/src/main/docs/main.adoc
index 6fc77d2bfd6..beac1024996 100644
--- a/core/camel-main/src/main/docs/main.adoc
+++ b/core/camel-main/src/main/docs/main.adoc
@@ -174,7 +174,7 @@ The camel.server supports 11 options, which are listed below.
 
 
 === Camel Debugger configurations
-The camel.debug supports 11 options, which are listed below.
+The camel.debug supports 12 options, which are listed below.
 
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
@@ -189,6 +189,7 @@ The camel.debug supports 11 options, which are listed below.
 | *camel.debug.includeExchange{zwsp}Properties* | Whether to include the exchange properties in the traced message | true | boolean
 | *camel.debug.loggingLevel* | The debugger logging level to use when logging activity. | INFO | LoggingLevel
 | *camel.debug.singleStepInclude{zwsp}StartEnd* | In single step mode, then when the exchange is created and completed, then simulate a breakpoint at start and end, that allows to suspend and watch the incoming/complete exchange at the route (you can see message body as response, failed exception etc). | false | boolean
+| *camel.debug.standby* | To set the debugger in standby mode, where the debugger will be installed by not automatic enabled. The debugger can then later be enabled explicit from Java, JMX or tooling. | false | boolean
 | *camel.debug.waitForAttach* | Whether the debugger should suspend on startup, and wait for a remote debugger to attach. This is what the IDEA and VSCode tooling is using. | false | boolean
 |===
 
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
index 660fa08e5f6..3c9fe680d11 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
@@ -1572,6 +1572,7 @@ public abstract class BaseMainSupport extends BaseService {
         camelContext.setDebugging(true);
 
         BacklogDebugger debugger = DefaultBacklogDebugger.createDebugger(camelContext);
+        debugger.setStandby(config.isStandby());
         debugger.setInitialBreakpoints(config.getBreakpoints());
         debugger.setSingleStepIncludeStartEnd(config.isSingleStepIncludeStartEnd());
         debugger.setBodyMaxChars(config.getBodyMaxChars());
@@ -1587,7 +1588,10 @@ public abstract class BaseMainSupport extends BaseService {
         camelContext.addLifecycleStrategy(new LifecycleStrategySupport() {
             @Override
             public void onContextStarted(CamelContext context) {
-                debugger.enableDebugger();
+                // only enable debugger if not in standby mode
+                if (!debugger.isStandby()) {
+                    debugger.enableDebugger();
+                }
             }
 
             @Override
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DebuggerConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/DebuggerConfigurationProperties.java
index de1113897e8..db62f28227b 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/DebuggerConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/DebuggerConfigurationProperties.java
@@ -31,6 +31,8 @@ public class DebuggerConfigurationProperties implements BootstrapCloseable {
 
     @Metadata
     private boolean enabled;
+    @Metadata
+    private boolean standby;
     @Metadata(label = "advanced")
     private boolean waitForAttach;
     @Metadata(defaultValue = "INFO")
@@ -76,6 +78,18 @@ public class DebuggerConfigurationProperties implements BootstrapCloseable {
         this.enabled = enabled;
     }
 
+    public boolean isStandby() {
+        return standby;
+    }
+
+    /**
+     * To set the debugger in standby mode, where the debugger will be installed by not automatic enabled. The debugger
+     * can then later be enabled explicit from Java, JMX or tooling.
+     */
+    public void setStandby(boolean standby) {
+        this.standby = standby;
+    }
+
     public boolean isWaitForAttach() {
         return waitForAttach;
     }
@@ -202,6 +216,15 @@ public class DebuggerConfigurationProperties implements BootstrapCloseable {
         return (DebuggerConfigurationProperties) this;
     }
 
+    /**
+     * To set the debugger in standby mode, where the debugger will be installed by not automatic enabled. The debugger
+     * can then later be enabled explicit from Java, JMX or tooling.
+     */
+    public DebuggerConfigurationProperties withStandby(boolean standby) {
+        this.standby = standby;
+        return (DebuggerConfigurationProperties) this;
+    }
+
     /**
      * Whether the debugger should suspend on startup, and wait for a remote debugger to attach. This is what the IDEA
      * and VSCode tooling is using.
diff --git a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedBacklogDebuggerMBean.java b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedBacklogDebuggerMBean.java
index 1f77619f5d0..3a1dc32a26c 100644
--- a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedBacklogDebuggerMBean.java
+++ b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedBacklogDebuggerMBean.java
@@ -38,6 +38,9 @@ public interface ManagedBacklogDebuggerMBean {
     @ManagedAttribute(description = "Is debugger enabled")
     boolean isEnabled();
 
+    @ManagedAttribute(description = "Is debugger standby")
+    boolean isStandby();
+
     @ManagedOperation(description = "Enable the debugger")
     void enableDebugger();
 
diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedBacklogDebugger.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedBacklogDebugger.java
index a3a86690544..a89d53da607 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedBacklogDebugger.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedBacklogDebugger.java
@@ -88,6 +88,11 @@ public class ManagedBacklogDebugger implements ManagedBacklogDebuggerMBean {
         return backlogDebugger.isEnabled();
     }
 
+    @Override
+    public boolean isStandby() {
+        return backlogDebugger.isStandby();
+    }
+
     @Override
     public void enableDebugger() {
         backlogDebugger.enableDebugger();
diff --git a/core/camel-management/src/test/java/org/apache/camel/management/BacklogDebuggerStandbyTest.java b/core/camel-management/src/test/java/org/apache/camel/management/BacklogDebuggerStandbyTest.java
new file mode 100644
index 00000000000..a978657b658
--- /dev/null
+++ b/core/camel-management/src/test/java/org/apache/camel/management/BacklogDebuggerStandbyTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.management;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.debugger.DefaultBacklogDebugger;
+import org.apache.camel.spi.BacklogDebugger;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+
+import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@DisabledOnOs(OS.AIX)
+public class BacklogDebuggerStandbyTest extends ManagementTestSupport {
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testBacklogDebuggerStandby() throws Exception {
+        MBeanServer mbeanServer = getMBeanServer();
+        ObjectName on = new ObjectName(
+                "org.apache.camel:context=" + context.getManagementName() + ",type=tracer,name=BacklogDebugger");
+        assertNotNull(on);
+        mbeanServer.isRegistered(on);
+
+        Boolean enabled = (Boolean) mbeanServer.getAttribute(on, "Enabled");
+        assertEquals(Boolean.FALSE, enabled, "Should not be enabled");
+
+        Boolean standby = (Boolean) mbeanServer.getAttribute(on, "Standby");
+        assertEquals(Boolean.TRUE, standby, "Should be standby");
+
+        // enable debugger
+        mbeanServer.invoke(on, "enableDebugger", null, null);
+
+        enabled = (Boolean) mbeanServer.getAttribute(on, "Enabled");
+        assertEquals(Boolean.TRUE, enabled, "Should be enabled");
+
+        // add breakpoint at bar
+        mbeanServer.invoke(on, "addBreakpoint", new Object[] { "bar" }, new String[] { "java.lang.String" });
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(0);
+        mock.setSleepForEmptyTest(100);
+
+        template.sendBody("seda:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+
+        // wait for breakpoint at bar
+        await().atMost(1, TimeUnit.SECONDS).untilAsserted(() -> {
+            Set<String> suspended = (Set<String>) mbeanServer.invoke(on, "suspendedBreakpointNodeIds", null, null);
+            assertNotNull(suspended);
+            assertEquals(1, suspended.size());
+            assertEquals("bar", suspended.iterator().next());
+        });
+
+        // the message should be ours
+        String xml = (String) mbeanServer.invoke(on, "dumpTracedMessagesAsXml", new Object[] { "bar", false },
+                new String[] { "java.lang.String", "boolean" });
+        assertNotNull(xml);
+        log.info(xml);
+
+        assertTrue(xml.contains("Hello World"), "Should contain our body");
+        assertTrue(xml.contains("<toNode>bar</toNode>"), "Should contain bar node");
+
+        resetMocks();
+        mock.expectedMessageCount(1);
+
+        // resume breakpoint
+        mbeanServer.invoke(on, "resumeBreakpoint", new Object[] { "bar" }, new String[] { "java.lang.String" });
+
+        assertMockEndpointsSatisfied();
+
+        // and no suspended anymore
+        Set<String> nodes = (Set<String>) mbeanServer.invoke(on, "suspendedBreakpointNodeIds", null, null);
+        assertNotNull(nodes);
+        assertEquals(0, nodes.size());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // set debugger in standby mode
+                BacklogDebugger bd = DefaultBacklogDebugger.createDebugger(context);
+                bd.setStandby(true);
+                context.addService(bd);
+                context.setDebugging(true);
+
+                from("seda:start?concurrentConsumers=2")
+                        .setProperty("myProperty", constant("myValue")).id("setProp")
+                        .to("log:foo").id("foo")
+                        .to("log:bar").id("bar")
+                        .transform().constant("Bye World").id("transform")
+                        .to("log:cheese?showExchangeId=true").id("cheese")
+                        .to("mock:result").id("result");
+            }
+        };
+    }
+
+}
diff --git a/core/camel-management/src/test/java/org/apache/camel/management/BacklogDebuggerTest.java b/core/camel-management/src/test/java/org/apache/camel/management/BacklogDebuggerTest.java
index cbd75bbc775..3d81881d01d 100644
--- a/core/camel-management/src/test/java/org/apache/camel/management/BacklogDebuggerTest.java
+++ b/core/camel-management/src/test/java/org/apache/camel/management/BacklogDebuggerTest.java
@@ -53,6 +53,9 @@ public class BacklogDebuggerTest extends ManagementTestSupport {
         Boolean enabled = (Boolean) mbeanServer.getAttribute(on, "Enabled");
         assertEquals(Boolean.FALSE, enabled, "Should not be enabled");
 
+        Boolean standby = (Boolean) mbeanServer.getAttribute(on, "Standby");
+        assertEquals(Boolean.FALSE, standby, "Should not be standby");
+
         // enable debugger
         mbeanServer.invoke(on, "enableDebugger", null, null);
 


(camel) 02/02: CAMEL-20067: camel-core - Add debuggingStandby option

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit baca9f8cf05541525504c92cbe216527cf4f81db
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Nov 17 14:32:14 2023 +0100

    CAMEL-20067: camel-core - Add debuggingStandby option
---
 .../src/main/java/org/apache/camel/CamelContext.java        | 12 ++++++++++++
 .../apache/camel/impl/debugger/DefaultBacklogDebugger.java  |  4 +++-
 .../org/apache/camel/impl/engine/AbstractCamelContext.java  | 13 ++++++++++++-
 .../java/org/apache/camel/impl/engine/DefaultChannel.java   |  2 +-
 .../java/org/apache/camel/impl/console/DebugDevConsole.java |  2 ++
 .../java/org/apache/camel/impl/CamelContextConfigurer.java  |  6 ++++++
 .../main/java/org/apache/camel/main/BaseMainSupport.java    |  5 +++--
 .../apache/camel/main/DefaultConfigurationConfigurer.java   |  5 +++++
 8 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
index 041bb697acf..cbf1548e1dd 100644
--- a/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
+++ b/core/camel-api/src/main/java/org/apache/camel/CamelContext.java
@@ -1180,6 +1180,18 @@ public interface CamelContext extends CamelContextLifecycle, RuntimeConfiguratio
      */
     boolean isBacklogTracingStandby();
 
+    /**
+     * Whether to set backlog debugger on standby. If on standby then the backlog debugger is installed and made
+     * available. Then the backlog debugger can be enabled later at runtime via JMX or via Java API.
+     */
+    void setDebugStandby(boolean debugStandby);
+
+    /**
+     * Whether to set backlog debugger on standby. If on standby then the backlog debugger is installed and made
+     * available. Then the backlog debugger can be enabled later at runtime via JMX or via Java API.
+     */
+    boolean isDebugStandby();
+
     /**
      * Whether backlog tracing should trace inner details from route templates (or kamelets). Turning this off can
      * reduce the verbosity of tracing when using many route templates, and allow to focus on tracing your own Camel
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogDebugger.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogDebugger.java
index dacb5bbee3a..8ccc3a2cc01 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogDebugger.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogDebugger.java
@@ -139,7 +139,9 @@ public final class DefaultBacklogDebugger extends ServiceSupport implements Back
         // must enable message history for debugger to capture more details
         context.setMessageHistory(true);
 
-        return new DefaultBacklogDebugger(context, resolveSuspendMode());
+        DefaultBacklogDebugger answer = new DefaultBacklogDebugger(context, resolveSuspendMode());
+        answer.setStandby(context.isDebugStandby());
+        return answer;
     }
 
     /**
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
index 2d2726ea1d2..e4e0b4f63b6 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java
@@ -237,6 +237,7 @@ public abstract class AbstractCamelContext extends BaseService
     private String tracingLoggingFormat;
     private Boolean modeline = Boolean.FALSE;
     private Boolean debug = Boolean.FALSE;
+    private Boolean debugStandby = Boolean.FALSE;
     private String debugBreakpoints;
     private Boolean messageHistory = Boolean.FALSE;
     private Boolean logMask = Boolean.FALSE;
@@ -1738,6 +1739,16 @@ public abstract class AbstractCamelContext extends BaseService
         return debug;
     }
 
+    @Override
+    public void setDebugStandby(boolean debugStandby) {
+        this.debugStandby = debugStandby;
+    }
+
+    @Override
+    public boolean isDebugStandby() {
+        return debugStandby != null && debugStandby;
+    }
+
     public void setDebuggingBreakpoints(String debugBreakpoints) {
         this.debugBreakpoints = debugBreakpoints;
     }
@@ -2254,7 +2265,7 @@ public abstract class AbstractCamelContext extends BaseService
                 }
             }
         }
-        if (!debuggerDetected && isDebugging()) {
+        if (!debuggerDetected && (isDebugging() || isDebugStandby())) {
             // debugging enabled but camel-debug was not auto-detected from classpath
             // so install default debugger
             BacklogDebugger backlog = DefaultBacklogDebugger.createDebugger(this);
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultChannel.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultChannel.java
index 84fb4e61f2a..07539ebedc0 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultChannel.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultChannel.java
@@ -174,7 +174,7 @@ public class DefaultChannel extends CamelInternalProcessor implements Channel {
 
         // then wrap the output with the tracer and debugger (debugger first,
         // as we do not want regular tracer to trace the debugger)
-        if (route.isDebugging()) {
+        if (camelContext.isDebugStandby() || route.isDebugging()) {
             final Debugger customDebugger = camelContext.getDebugger();
             if (customDebugger != null) {
                 // use custom debugger
diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/DebugDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/DebugDevConsole.java
index 161a458ce81..72100c0295a 100644
--- a/core/camel-console/src/main/java/org/apache/camel/impl/console/DebugDevConsole.java
+++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/DebugDevConsole.java
@@ -67,6 +67,7 @@ public class DebugDevConsole extends AbstractDevConsole {
         if (backlog != null) {
             sb.append("Settings:");
             sb.append(String.format("\n    Enabled: %s", backlog.isEnabled()));
+            sb.append(String.format("\n    Standby: %s", backlog.isStandby()));
             sb.append(String.format("\n    Suspended Mode: %s", backlog.isSuspendMode()));
             sb.append(String.format("\n    Fallback Timeout: %ss", backlog.getFallbackTimeout())); // is in seconds
             sb.append(String.format("\n    Logging Level: %s", backlog.getLoggingLevel()));
@@ -151,6 +152,7 @@ public class DebugDevConsole extends AbstractDevConsole {
         BacklogDebugger backlog = getCamelContext().hasService(BacklogDebugger.class);
         if (backlog != null) {
             root.put("enabled", backlog.isEnabled());
+            root.put("standby", backlog.isStandby());
             root.put("suspendedMode", backlog.isSuspendMode());
             root.put("fallbackTimeout", backlog.getFallbackTimeout());
             root.put("loggingLevel", backlog.getLoggingLevel());
diff --git a/core/camel-core-engine/src/generated/java/org/apache/camel/impl/CamelContextConfigurer.java b/core/camel-core-engine/src/generated/java/org/apache/camel/impl/CamelContextConfigurer.java
index 43067b7d8e7..36058f48b6b 100644
--- a/core/camel-core-engine/src/generated/java/org/apache/camel/impl/CamelContextConfigurer.java
+++ b/core/camel-core-engine/src/generated/java/org/apache/camel/impl/CamelContextConfigurer.java
@@ -39,6 +39,8 @@ public class CamelContextConfigurer extends org.apache.camel.support.component.P
         case "CaseInsensitiveHeaders": target.setCaseInsensitiveHeaders(property(camelContext, java.lang.Boolean.class, value)); return true;
         case "classresolver":
         case "ClassResolver": target.setClassResolver(property(camelContext, org.apache.camel.spi.ClassResolver.class, value)); return true;
+        case "debugstandby":
+        case "DebugStandby": target.setDebugStandby(property(camelContext, boolean.class, value)); return true;
         case "debugger":
         case "Debugger": target.setDebugger(property(camelContext, org.apache.camel.spi.Debugger.class, value)); return true;
         case "debugging":
@@ -158,6 +160,8 @@ public class CamelContextConfigurer extends org.apache.camel.support.component.P
         case "CaseInsensitiveHeaders": return java.lang.Boolean.class;
         case "classresolver":
         case "ClassResolver": return org.apache.camel.spi.ClassResolver.class;
+        case "debugstandby":
+        case "DebugStandby": return boolean.class;
         case "debugger":
         case "Debugger": return org.apache.camel.spi.Debugger.class;
         case "debugging":
@@ -278,6 +282,8 @@ public class CamelContextConfigurer extends org.apache.camel.support.component.P
         case "CaseInsensitiveHeaders": return target.isCaseInsensitiveHeaders();
         case "classresolver":
         case "ClassResolver": return target.getClassResolver();
+        case "debugstandby":
+        case "DebugStandby": return target.isDebugStandby();
         case "debugger":
         case "Debugger": return target.getDebugger();
         case "debugging":
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
index 3c9fe680d11..e04d05609b9 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
@@ -1561,7 +1561,7 @@ public abstract class BaseMainSupport extends BaseService {
         setPropertiesOnTarget(camelContext, config, properties, "camel.debug.",
                 failIfNotSet, true, autoConfiguredProperties);
 
-        if (!config.isEnabled()) {
+        if (!config.isEnabled() && !config.isStandby()) {
             return;
         }
 
@@ -1569,7 +1569,8 @@ public abstract class BaseMainSupport extends BaseService {
         camelContext.setSourceLocationEnabled(true);
 
         // enable debugger on camel
-        camelContext.setDebugging(true);
+        camelContext.setDebugging(config.isEnabled());
+        camelContext.setDebugStandby(config.isStandby());
 
         BacklogDebugger debugger = DefaultBacklogDebugger.createDebugger(camelContext);
         debugger.setStandby(config.isStandby());
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
index 3d958a06a0c..7b6f4bcedff 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
@@ -43,6 +43,7 @@ import org.apache.camel.model.Model;
 import org.apache.camel.model.ModelCamelContext;
 import org.apache.camel.model.ModelLifecycleStrategy;
 import org.apache.camel.spi.AsyncProcessorAwaitManager;
+import org.apache.camel.spi.BacklogDebugger;
 import org.apache.camel.spi.BeanIntrospection;
 import org.apache.camel.spi.ClassResolver;
 import org.apache.camel.spi.CliConnectorFactory;
@@ -395,6 +396,10 @@ public final class DefaultConfigurationConfigurer {
         if (bt != null) {
             camelContext.getCamelContextExtension().addContextPlugin(BacklogTracer.class, bt);
         }
+        BacklogDebugger bd = getSingleBeanOfType(registry, BacklogDebugger.class);
+        if (bd != null) {
+            camelContext.getCamelContextExtension().addContextPlugin(BacklogDebugger.class, bd);
+        }
         InflightRepository ir = getSingleBeanOfType(registry, InflightRepository.class);
         if (ir != null) {
             camelContext.setInflightRepository(ir);