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

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

commit 2dc16e182384438498781f94ea2580a32ca05ca0
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Jan 19 19:49:19 2021 +0100

    CAMEL-16056: Added StartupStep to diagnose startup exeuction times for 
various steps.
---
 .../main/java/org/apache/camel/StartupStep.java    |  7 ---
 .../org/apache/camel/spi/StartupStepRecorder.java  |  8 +--
 .../camel/impl/engine/AbstractCamelContext.java    |  8 ++-
 .../org/apache/camel/impl/DefaultCamelContext.java |  8 +++
 .../MainConfigurationPropertiesConfigurer.java     | 12 ++++
 .../camel-main-configuration-metadata.json         |  2 +
 core/camel-main/src/main/docs/main.adoc            |  2 +
 .../camel/main/DefaultConfigurationConfigurer.java | 17 ++++++
 .../camel/main/DefaultConfigurationProperties.java | 54 ++++++++++++++++++
 .../support/{ => startup}/DefaultStartupStep.java  |  6 +-
 .../{ => startup}/DefaultStartupStepRecorder.java  | 37 ++-----------
 .../startup/LoggingStartupStepRecorder.java        | 62 +++++++++++++++++++++
 .../jfr/FlightRecorderStartupStep.java}            | 64 ++++++++++++----------
 .../jfr/FlightRecorderStartupStepRecorder.java     | 40 ++++++++++++++
 14 files changed, 247 insertions(+), 80 deletions(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/StartupStep.java 
b/core/camel-api/src/main/java/org/apache/camel/StartupStep.java
index 18f23cd..58d7114 100644
--- a/core/camel-api/src/main/java/org/apache/camel/StartupStep.java
+++ b/core/camel-api/src/main/java/org/apache/camel/StartupStep.java
@@ -62,11 +62,4 @@ public interface StartupStep {
      */
     long getBeginTime();
 
-    /**
-     * Add metadata.
-     *
-     * @param key   the key
-     * @param value the value
-     */
-    void addTag(String key, String value);
 }
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/spi/StartupStepRecorder.java 
b/core/camel-api/src/main/java/org/apache/camel/spi/StartupStepRecorder.java
index 60df638..91296d6 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/StartupStepRecorder.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/StartupStepRecorder.java
@@ -36,14 +36,14 @@ public interface StartupStepRecorder extends StaticService {
     void setEnabled(boolean enabled);
 
     /**
-     * Whether to automatic disable this recorder after Camel has been started.
-     * This is done by default to remove any overhead after the startup 
process is done.
+     * Whether to automatic disable this recorder after Camel has been 
started. This is done by default to remove any
+     * overhead after the startup process is done.
      */
     boolean isDisableAfterStarted();
 
     /**
-     * Whether to automatic disable this recorder after Camel has been started.
-     * This is done by default to remove any overhead after the startup 
process is done.
+     * Whether to automatic disable this recorder after Camel has been 
started. This is done by default to remove any
+     * overhead after the startup process is done.
      */
     void setDisableAfterStarted(boolean disableAfterStarted);
 
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 b4ccabd..8640bd7 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
@@ -154,7 +154,6 @@ import org.apache.camel.spi.Validator;
 import org.apache.camel.spi.ValidatorRegistry;
 import org.apache.camel.spi.XMLRoutesDefinitionLoader;
 import org.apache.camel.support.CamelContextHelper;
-import org.apache.camel.support.DefaultStartupStepRecorder;
 import org.apache.camel.support.EndpointHelper;
 import org.apache.camel.support.EventHelper;
 import org.apache.camel.support.LRUCacheFactory;
@@ -165,6 +164,7 @@ import org.apache.camel.support.ResolverHelper;
 import org.apache.camel.support.jsse.SSLContextParameters;
 import org.apache.camel.support.service.BaseService;
 import org.apache.camel.support.service.ServiceHelper;
+import org.apache.camel.support.startup.DefaultStartupStepRecorder;
 import org.apache.camel.util.IOHelper;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.StopWatch;
@@ -2527,6 +2527,9 @@ public abstract class AbstractCamelContext extends 
BaseService
     @Override
     public void doBuild() throws Exception {
         bootDate = System.currentTimeMillis();
+        if (!(startupStepRecorder instanceof DefaultStartupStepRecorder)) {
+            LOG.info("Using startup recorder: {}", startupStepRecorder);
+        }
         startupStepRecorder.start();
         StartupStep step = startupStepRecorder.beginStep(CamelContext.class, 
null, "Building context");
 
@@ -3249,6 +3252,8 @@ public abstract class AbstractCamelContext extends 
BaseService
                 // start the route service
                 routeServices.put(routeService.getId(), routeService);
                 if (shouldStartRoutes()) {
+                    StartupStep step
+                            = startupStepRecorder.beginStep(Route.class, 
routeService.getId(), "Starting route services");
                     // this method will log the routes being started
                     internalRouteStartupManager.safelyStartRouteServices(true, 
true, true, false, addingRoutes, routeService);
                     // start route services if it was configured to auto 
startup
@@ -3259,6 +3264,7 @@ public abstract class AbstractCamelContext extends 
BaseService
                         // starting a route (not adding new routes)
                         routeService.start();
                     }
+                    startupStepRecorder.endStep(step);
                 }
             }
         } finally {
diff --git 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index 43e4941..71ff083 100644
--- 
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ 
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -24,10 +24,12 @@ import java.util.function.Function;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Expression;
+import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.FailedToStartRouteException;
 import org.apache.camel.Predicate;
 import org.apache.camel.Processor;
 import org.apache.camel.Route;
+import org.apache.camel.StartupStep;
 import org.apache.camel.ValueHolder;
 import org.apache.camel.builder.AdviceWith;
 import org.apache.camel.builder.AdviceWithRouteBuilder;
@@ -60,6 +62,7 @@ import org.apache.camel.spi.ExecutorServiceManager;
 import org.apache.camel.spi.ModelReifierFactory;
 import org.apache.camel.spi.PropertiesComponent;
 import org.apache.camel.spi.Registry;
+import org.apache.camel.spi.StartupStepRecorder;
 import org.apache.camel.spi.Transformer;
 import org.apache.camel.spi.Validator;
 import org.apache.camel.support.CamelContextHelper;
@@ -600,7 +603,12 @@ public class DefaultCamelContext extends 
SimpleCamelContext implements ModelCame
                     routeDefinition.markPrepared();
                 }
 
+                StartupStepRecorder recorder
+                        = 
getCamelContextReference().adapt(ExtendedCamelContext.class).getStartupStepRecorder();
+                StartupStep step = recorder.beginStep(Route.class, 
routeDefinition.getRouteId(), "Creating route");
                 Route route = model.getModelReifierFactory().createRoute(this, 
routeDefinition);
+                recorder.endStep(step);
+
                 RouteService routeService = new RouteService(route);
                 startRouteService(routeService, true);
 
diff --git 
a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
 
b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
index 28ced68..0ec603e 100644
--- 
a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
+++ 
b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
@@ -143,6 +143,10 @@ public class MainConfigurationPropertiesConfigurer extends 
org.apache.camel.supp
         case "ShutdownSuppressLoggingOnTimeout": 
target.setShutdownSuppressLoggingOnTimeout(property(camelContext, 
boolean.class, value)); return true;
         case "shutdowntimeout":
         case "ShutdownTimeout": 
target.setShutdownTimeout(property(camelContext, int.class, value)); return 
true;
+        case "startuprecorder":
+        case "StartupRecorder": 
target.setStartupRecorder(property(camelContext, java.lang.String.class, 
value)); return true;
+        case "startuprecordermaxdepth":
+        case "StartupRecorderMaxDepth": 
target.setStartupRecorderMaxDepth(property(camelContext, int.class, value)); 
return true;
         case "streamcachinganyspoolrules":
         case "StreamCachingAnySpoolRules": 
target.setStreamCachingAnySpoolRules(property(camelContext, boolean.class, 
value)); return true;
         case "streamcachingbuffersize":
@@ -310,6 +314,10 @@ public class MainConfigurationPropertiesConfigurer extends 
org.apache.camel.supp
         case "ShutdownSuppressLoggingOnTimeout": return boolean.class;
         case "shutdowntimeout":
         case "ShutdownTimeout": return int.class;
+        case "startuprecorder":
+        case "StartupRecorder": return java.lang.String.class;
+        case "startuprecordermaxdepth":
+        case "StartupRecorderMaxDepth": return int.class;
         case "streamcachinganyspoolrules":
         case "StreamCachingAnySpoolRules": return boolean.class;
         case "streamcachingbuffersize":
@@ -478,6 +486,10 @@ public class MainConfigurationPropertiesConfigurer extends 
org.apache.camel.supp
         case "ShutdownSuppressLoggingOnTimeout": return 
target.isShutdownSuppressLoggingOnTimeout();
         case "shutdowntimeout":
         case "ShutdownTimeout": return target.getShutdownTimeout();
+        case "startuprecorder":
+        case "StartupRecorder": return target.getStartupRecorder();
+        case "startuprecordermaxdepth":
+        case "StartupRecorderMaxDepth": return 
target.getStartupRecorderMaxDepth();
         case "streamcachinganyspoolrules":
         case "StreamCachingAnySpoolRules": return 
target.isStreamCachingAnySpoolRules();
         case "streamcachingbuffersize":
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 7a249fd..9429f05 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
@@ -71,6 +71,8 @@
     { "name": "camel.main.shutdownRoutesInReverseOrder", "description": "Sets 
whether routes should be shutdown in reverse or the same order as they were 
started.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", 
"javaType": "boolean", "defaultValue": true },
     { "name": "camel.main.shutdownSuppressLoggingOnTimeout", "description": 
"Whether Camel should try to suppress logging during shutdown and timeout was 
triggered, meaning forced shutdown is happening. And during forced shutdown we 
want to avoid logging errors\/warnings et all in the logs as a side-effect of 
the forced timeout. Notice the suppress is a best effort as there may still be 
some logs coming from 3rd party libraries and whatnot, which Camel cannot 
control. This option is defa [...]
     { "name": "camel.main.shutdownTimeout", "description": "Timeout in seconds 
to graceful shutdown Camel.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", 
"javaType": "int", "defaultValue": 45 },
+    { "name": "camel.main.startupRecorder", "description": "To use startup 
recorder for capturing execution time during starting Camel. The recorder can 
be one of: false, logging, java-flight-recorder The default is false.", 
"sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": 
"string", "javaType": "java.lang.String" },
+    { "name": "camel.main.startupRecorderMaxDepth", "description": "To filter 
our sub steps at a maximum depth. Use -1 for no maximum. Use 0 for no sub 
steps. Use 1 for max 1 sub step, and so forth. The default is -1.", 
"sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": 
"integer", "javaType": "int", "defaultValue": -1 },
     { "name": "camel.main.streamCachingAnySpoolRules", "description": "Sets 
whether if just any of the org.apache.camel.spi.StreamCachingStrategy.SpoolRule 
rules returns true then shouldSpoolCache(long) returns true, to allow spooling 
to disk. If this option is false, then all the 
org.apache.camel.spi.StreamCachingStrategy.SpoolRule must return true. The 
default value is false which means that all the rules must return true.", 
"sourceType": "org.apache.camel.main.DefaultConfigurationProp [...]
     { "name": "camel.main.streamCachingBufferSize", "description": "Sets the 
stream caching buffer size to use when allocating in-memory buffers used for 
in-memory stream caches. The default size is 4096.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", 
"javaType": "int" },
     { "name": "camel.main.streamCachingEnabled", "description": "Sets whether 
stream caching is enabled or not. Default is false.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", 
"javaType": "boolean" },
diff --git a/core/camel-main/src/main/docs/main.adoc 
b/core/camel-main/src/main/docs/main.adoc
index 32177f1..7c60056 100644
--- a/core/camel-main/src/main/docs/main.adoc
+++ b/core/camel-main/src/main/docs/main.adoc
@@ -83,6 +83,8 @@ The following table lists all the options:
 | *camel.main.shutdownRoutesIn{zwsp}ReverseOrder* | Sets whether routes should 
be shutdown in reverse or the same order as they were started. | true | boolean
 | *camel.main.shutdownSuppress{zwsp}LoggingOnTimeout* | Whether Camel should 
try to suppress logging during shutdown and timeout was triggered, meaning 
forced shutdown is happening. And during forced shutdown we want to avoid 
logging errors/warnings et all in the logs as a side-effect of the forced 
timeout. Notice the suppress is a best effort as there may still be some logs 
coming from 3rd party libraries and whatnot, which Camel cannot control. This 
option is default false. |  | boolean
 | *camel.main.shutdownTimeout* | Timeout in seconds to graceful shutdown 
Camel. | 45 | int
+| *camel.main.startupRecorder* | To use startup recorder for capturing 
execution time during starting Camel. The recorder can be one of: false, 
logging, java-flight-recorder The default is false. |  | String
+| *camel.main.startupRecorderMax{zwsp}Depth* | To filter our sub steps at a 
maximum depth. Use -1 for no maximum. Use 0 for no sub steps. Use 1 for max 1 
sub step, and so forth. The default is -1. | -1 | int
 | *camel.main.streamCachingAny{zwsp}SpoolRules* | Sets whether if just any of 
the org.apache.camel.spi.StreamCachingStrategy.SpoolRule rules returns true 
then shouldSpoolCache(long) returns true, to allow spooling to disk. If this 
option is false, then all the 
org.apache.camel.spi.StreamCachingStrategy.SpoolRule must return true. The 
default value is false which means that all the rules must return true. |  | 
boolean
 | *camel.main.streamCachingBuffer{zwsp}Size* | Sets the stream caching buffer 
size to use when allocating in-memory buffers used for in-memory stream caches. 
The default size is 4096. |  | int
 | *camel.main.streamCaching{zwsp}Enabled* | Sets whether stream caching is 
enabled or not. Default is false. |  | boolean
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 51c200f..e8a2757 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
@@ -59,6 +59,7 @@ import org.apache.camel.spi.RouteController;
 import org.apache.camel.spi.RoutePolicyFactory;
 import org.apache.camel.spi.RuntimeEndpointRegistry;
 import org.apache.camel.spi.ShutdownStrategy;
+import org.apache.camel.spi.StartupStepRecorder;
 import org.apache.camel.spi.StreamCachingStrategy;
 import org.apache.camel.spi.SupervisingRouteController;
 import org.apache.camel.spi.ThreadPoolFactory;
@@ -66,6 +67,8 @@ import org.apache.camel.spi.ThreadPoolProfile;
 import org.apache.camel.spi.UnitOfWorkFactory;
 import org.apache.camel.spi.UuidGenerator;
 import org.apache.camel.support.jsse.GlobalSSLContextParametersSupplier;
+import org.apache.camel.support.startup.LoggingStartupStepRecorder;
+import org.apache.camel.support.startup.jfr.FlightRecorderStartupStepRecorder;
 import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -89,6 +92,16 @@ public final class DefaultConfigurationConfigurer {
      */
     public static void configure(CamelContext camelContext, 
DefaultConfigurationProperties config) throws Exception {
         ExtendedCamelContext ecc = 
camelContext.adapt(ExtendedCamelContext.class);
+
+        if (config.getStartupRecorder() != null && 
!"false".equals(config.getStartupRecorder())) {
+            if ("logging".equals(config.getStartupRecorder())) {
+                ecc.setStartupStepRecorder(new LoggingStartupStepRecorder());
+            } else if 
("java-flight-recorder".equals(config.getStartupRecorder())) {
+                ecc.setStartupStepRecorder(new 
FlightRecorderStartupStepRecorder());
+            }
+        }
+        
ecc.getStartupStepRecorder().setMaxDepth(config.getStartupRecorderMaxDepth());
+
         ecc.setLightweight(config.isLightweight());
         
ecc.getBeanPostProcessor().setEnabled(config.isBeanPostProcessorEnabled());
         
ecc.getBeanIntrospection().setExtendedStatistics(config.isBeanIntrospectionExtendedStatistics());
@@ -239,6 +252,10 @@ public final class DefaultConfigurationConfigurer {
         final ManagementStrategy managementStrategy = 
camelContext.getManagementStrategy();
         final ExtendedCamelContext ecc = 
camelContext.adapt(ExtendedCamelContext.class);
 
+        StartupStepRecorder ssr = getSingleBeanOfType(registry, 
StartupStepRecorder.class);
+        if (ssr != null) {
+            ecc.setStartupStepRecorder(ssr);
+        }
         PropertiesComponent pc = getSingleBeanOfType(registry, 
PropertiesComponent.class);
         if (pc != null) {
             ecc.setPropertiesComponent(pc);
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java
 
b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java
index 44de80a..8b71105 100644
--- 
a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java
+++ 
b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java
@@ -100,6 +100,8 @@ public abstract class DefaultConfigurationProperties<T> {
     private long routeControllerBackOffMaxAttempts;
     private double routeControllerBackOffMultiplier;
     private boolean routeControllerUnhealthyOnExhausted;
+    private String startupRecorder;
+    private int startupRecorderMaxDepth = -1;
 
     // getter and setters
     // --------------------------------------------------------------
@@ -1096,6 +1098,35 @@ public abstract class DefaultConfigurationProperties<T> {
         this.routeControllerUnhealthyOnExhausted = 
routeControllerUnhealthyOnExhausted;
     }
 
+    public String getStartupRecorder() {
+        return startupRecorder;
+    }
+
+    /**
+     * To use startup recorder for capturing execution time during starting 
Camel. The recorder can be one of: false,
+     * logging, java-flight-recorder
+     *
+     * The default is false.
+     */
+    public void setStartupRecorder(String startupRecorder) {
+        this.startupRecorder = startupRecorder;
+    }
+
+    public int getStartupRecorderMaxDepth() {
+        return startupRecorderMaxDepth;
+    }
+
+    /**
+     * To filter our sub steps at a maximum depth.
+     *
+     * Use -1 for no maximum. Use 0 for no sub steps. Use 1 for max 1 sub 
step, and so forth.
+     *
+     * The default is -1.
+     */
+    public void setStartupRecorderMaxDepth(int startupRecorderMaxDepth) {
+        this.startupRecorderMaxDepth = startupRecorderMaxDepth;
+    }
+
     // fluent builders
     // --------------------------------------------------------------
 
@@ -1847,4 +1878,27 @@ public abstract class DefaultConfigurationProperties<T> {
         return (T) this;
     }
 
+    /**
+     * To use startup recorder for capturing execution time during starting 
Camel. The recorder can be one of: false,
+     * logging, java-flight-recorder
+     *
+     * The default is false.
+     */
+    public T withStartupRecorder(String startupRecorder) {
+        this.startupRecorder = startupRecorder;
+        return (T) this;
+    }
+
+    /**
+     * To filter our sub steps at a maximum depth.
+     *
+     * Use -1 for no maximum. Use 0 for no sub steps. Use 1 for max 1 sub 
step, and so forth.
+     *
+     * The default is -1.
+     */
+    public T withStartupRecorderMaxDepth(int startupRecorderMaxDepth) {
+        this.startupRecorderMaxDepth = startupRecorderMaxDepth;
+        return (T) this;
+    }
+
 }
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/DefaultStartupStep.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/startup/DefaultStartupStep.java
similarity index 95%
copy from 
core/camel-support/src/main/java/org/apache/camel/support/DefaultStartupStep.java
copy to 
core/camel-support/src/main/java/org/apache/camel/support/startup/DefaultStartupStep.java
index c8e9e46..d604743 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/DefaultStartupStep.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/startup/DefaultStartupStep.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.support;
+package org.apache.camel.support.startup;
 
 import org.apache.camel.StartupStep;
 
@@ -78,8 +78,4 @@ public class DefaultStartupStep implements StartupStep {
         // noop
     }
 
-    @Override
-    public void addTag(String key, String value) {
-
-    }
 }
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/DefaultStartupStepRecorder.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/startup/DefaultStartupStepRecorder.java
similarity index 77%
rename from 
core/camel-support/src/main/java/org/apache/camel/support/DefaultStartupStepRecorder.java
rename to 
core/camel-support/src/main/java/org/apache/camel/support/startup/DefaultStartupStepRecorder.java
index e07e1ce..0fab31e 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/DefaultStartupStepRecorder.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/startup/DefaultStartupStepRecorder.java
@@ -14,28 +14,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.support;
+package org.apache.camel.support.startup;
 
 import java.util.ArrayDeque;
-import java.util.Arrays;
 import java.util.Deque;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.camel.StartupStep;
 import org.apache.camel.spi.StartupStepRecorder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
- * Default {@link StartupStepRecorder} that outputs to log.
+ * Default {@link StartupStepRecorder} that is always disabled.
  */
 public class DefaultStartupStepRecorder implements StartupStepRecorder {
 
-    private static final Logger LOG = 
LoggerFactory.getLogger(StartupStepRecorder.class);
-
-    // TODO: jfr implementation
-    // TODO: spring-boot implementation
-
     private final AtomicInteger stepCounter = new AtomicInteger();
     private final Deque<Integer> currentSteps = new ArrayDeque<>();
 
@@ -80,13 +72,10 @@ public class DefaultStartupStepRecorder implements 
StartupStepRecorder {
             return 0;
         }
 
-        @Override
-        public void addTag(String key, String value) {
-            // noop
-        }
     };
 
     public DefaultStartupStepRecorder() {
+        currentSteps.offerFirst(0);
     }
 
     private boolean enabled;
@@ -165,25 +154,7 @@ public class DefaultStartupStepRecorder implements 
StartupStepRecorder {
     }
 
     protected void onEndStep(StartupStep step) {
-        if (LOG.isInfoEnabled()) {
-            long delta = System.currentTimeMillis() - step.getBeginTime();
-            String pad = padString(step.getLevel());
-            String out = String.format("%s", pad + step.getType());
-            String out2 = String.format("%6s ms", delta);
-            String out3 = String.format("%s(%s)", step.getDescription(), 
step.getName());
-            LOG.info("{} : {} - {}", out2, out, out3);
-        }
-    }
-
-    public static String padString(int level) {
-        if (level == 0) {
-            return "";
-        } else {
-            byte[] arr = new byte[level * 2];
-            byte space = ' ';
-            Arrays.fill(arr, space);
-            return new String(arr);
-        }
+        // noop
     }
 
 }
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/startup/LoggingStartupStepRecorder.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/startup/LoggingStartupStepRecorder.java
new file mode 100644
index 0000000..3c73db0
--- /dev/null
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/startup/LoggingStartupStepRecorder.java
@@ -0,0 +1,62 @@
+/*
+ * 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.support.startup;
+
+import java.util.Arrays;
+
+import org.apache.camel.StartupStep;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Logging {@link org.apache.camel.spi.StartupStepRecorder} that outputs to 
log.
+ */
+public class LoggingStartupStepRecorder extends DefaultStartupStepRecorder {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(LoggingStartupStepRecorder.class);
+
+    public LoggingStartupStepRecorder() {
+        setEnabled(true);
+    }
+
+    protected void onEndStep(StartupStep step) {
+        if (LOG.isInfoEnabled()) {
+            long delta = System.currentTimeMillis() - step.getBeginTime();
+            String pad = padString(step.getLevel());
+            String out = String.format("%s", pad + step.getType());
+            String out2 = String.format("%6s ms", delta);
+            String out3 = String.format("%s(%s)", step.getDescription(), 
step.getName());
+            LOG.info("{} : {} - {}", out2, out, out3);
+        }
+    }
+
+    public static String padString(int level) {
+        if (level == 0) {
+            return "";
+        } else {
+            byte[] arr = new byte[level * 2];
+            byte space = ' ';
+            Arrays.fill(arr, space);
+            return new String(arr);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "logging";
+    }
+}
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/DefaultStartupStep.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/startup/jfr/FlightRecorderStartupStep.java
similarity index 60%
rename from 
core/camel-support/src/main/java/org/apache/camel/support/DefaultStartupStep.java
rename to 
core/camel-support/src/main/java/org/apache/camel/support/startup/jfr/FlightRecorderStartupStep.java
index c8e9e46..f07b712 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/DefaultStartupStep.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/startup/jfr/FlightRecorderStartupStep.java
@@ -14,33 +14,40 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.support;
+package org.apache.camel.support.startup.jfr;
 
+import jdk.jfr.Category;
+import jdk.jfr.Description;
+import jdk.jfr.Event;
+import jdk.jfr.Label;
+import jdk.jfr.Name;
+import jdk.jfr.StackTrace;
 import org.apache.camel.StartupStep;
 
-public class DefaultStartupStep implements StartupStep {
+@Name(FlightRecorderStartupStep.NAME)
+@Category("Camel Application")
+@Label("Startup Step")
+@Description("Camel Application Startup")
+@StackTrace(false)
+public class FlightRecorderStartupStep extends Event implements StartupStep {
 
-    private final String type;
-    private final String name;
-    private final String description;
-    private final int id;
-    private final int parentId;
-    private final int level;
-    private final long time;
+    public static final String NAME = "org.apache.camel.spi.CamelEvent";
 
-    public DefaultStartupStep(String type, String name, String description, 
int id, int parentId, int level, long time) {
-        this.type = type;
+    @Label("Event Name")
+    public final String name;
+    @Label("Event Id")
+    public final int id;
+    @Label("Event Parent Id")
+    public final int parentId;
+    @Label("Event Type")
+    public String type;
+    @Label("Event Description")
+    public String description;
+
+    public FlightRecorderStartupStep(String name, int id, int parentId) {
         this.name = name;
-        this.description = description;
         this.id = id;
         this.parentId = parentId;
-        this.level = level;
-        this.time = time;
-    }
-
-    @Override
-    public String getType() {
-        return type;
     }
 
     @Override
@@ -49,11 +56,6 @@ public class DefaultStartupStep implements StartupStep {
     }
 
     @Override
-    public String getDescription() {
-        return description;
-    }
-
-    @Override
     public int getId() {
         return id;
     }
@@ -65,21 +67,23 @@ public class DefaultStartupStep implements StartupStep {
 
     @Override
     public int getLevel() {
-        return level;
+        // not used by jfr
+        return 0;
     }
 
     @Override
     public long getBeginTime() {
-        return time;
+        // not used by jfr
+        return 0;
     }
 
     @Override
-    public void end() {
-        // noop
+    public String getType() {
+        return type;
     }
 
     @Override
-    public void addTag(String key, String value) {
-
+    public String getDescription() {
+        return description;
     }
 }
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/startup/jfr/FlightRecorderStartupStepRecorder.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/startup/jfr/FlightRecorderStartupStepRecorder.java
new file mode 100644
index 0000000..7c216ac
--- /dev/null
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/startup/jfr/FlightRecorderStartupStepRecorder.java
@@ -0,0 +1,40 @@
+/*
+ * 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.support.startup.jfr;
+
+import org.apache.camel.StartupStep;
+import org.apache.camel.support.startup.DefaultStartupStepRecorder;
+
+/**
+ * To capture startup steps to be emitted to Java Flight Recorder.
+ */
+public class FlightRecorderStartupStepRecorder extends 
DefaultStartupStepRecorder {
+
+    public FlightRecorderStartupStepRecorder() {
+        setEnabled(true);
+    }
+
+    @Override
+    public StartupStep createStartupStep(String type, String name, String 
description, int id, int parentId, int level) {
+        return new FlightRecorderStartupStep(name, id, parentId);
+    }
+
+    @Override
+    public String toString() {
+        return "java-flight-recorder";
+    }
+}

Reply via email to