You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ja...@apache.org on 2021/11/24 08:24:08 UTC

[camel-quarkus] branch main updated: JFR Native support

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

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


The following commit(s) were added to refs/heads/main by this push:
     new c82a51c  JFR Native support
c82a51c is described below

commit c82a51c72b37e3d8c6fb1377d7e27ea6f773584f
Author: James Netherton <ja...@gmail.com>
AuthorDate: Thu Nov 18 07:45:29 2021 +0000

    JFR Native support
    
    Fixes #2151
---
 .../ROOT/pages/reference/extensions/jfr.adoc       | 61 +++++++++++++++++----
 .../ROOT/partials/reference/others/jfr.adoc        |  6 +--
 .../core/deployment/CamelContextProcessor.java     |  3 --
 .../quarkus/core/deployment/CamelProcessor.java    |  8 ---
 .../spi/CamelStartupStepRecorderBuildItem.java     | 41 --------------
 .../camel/quarkus/core/CamelContextRecorder.java   |  4 --
 .../quarkus/component/jfr/CamelJfrRecorder.java    | 52 ------------------
 extensions-jvm/pom.xml                             |  1 -
 .../jfr/deployment/pom.xml                         |  0
 .../component/jfr/deployment/JfrProcessor.java     | 17 ++----
 .../jfr/deployment/JfrConfigInterceptorTest.java   |  0
 {extensions-jvm => extensions}/jfr/pom.xml         |  2 +-
 {extensions-jvm => extensions}/jfr/runtime/pom.xml |  1 +
 extensions/jfr/runtime/src/main/doc/usage.adoc     | 33 ++++++++++++
 .../CamelJfrConfigSourceInterceptorFactory.java    |  2 +-
 .../quarkus/component/jfr/CamelJfrRecorder.java    | 62 ++++++++++++++++++++++
 .../component/jfr/RuntimeCamelJfrConfig.java       |  4 +-
 .../main/resources/META-INF/quarkus-extension.yaml |  0
 ....smallrye.config.ConfigSourceInterceptorFactory |  0
 extensions/pom.xml                                 |  1 +
 integration-tests-jvm/pom.xml                      |  1 -
 .../jfr/pom.xml                                    | 27 ++++++++++
 .../quarkus/component/jfr/it/JfrResource.java      |  0
 .../camel/quarkus/component/jfr/it/JfrRoutes.java  |  0
 .../jfr/src/main/resources/application.properties  | 19 +++++++
 .../camel/quarkus/component/jfr/it/JfrIT.java      | 10 ++--
 .../camel/quarkus/component/jfr/it/JfrTest.java    |  0
 .../quarkus/component/jfr/it/JfrTestResource.java  |  6 +++
 integration-tests/pom.xml                          |  1 +
 tooling/scripts/test-categories.yaml               |  1 +
 30 files changed, 217 insertions(+), 146 deletions(-)

diff --git a/docs/modules/ROOT/pages/reference/extensions/jfr.adoc b/docs/modules/ROOT/pages/reference/extensions/jfr.adoc
index 74ac397..d000cf7 100644
--- a/docs/modules/ROOT/pages/reference/extensions/jfr.adoc
+++ b/docs/modules/ROOT/pages/reference/extensions/jfr.adoc
@@ -3,16 +3,16 @@
 = Jfr
 :linkattrs:
 :cq-artifact-id: camel-quarkus-jfr
-:cq-native-supported: false
-:cq-status: Preview
-:cq-status-deprecation: Preview
+:cq-native-supported: true
+:cq-status: Stable
+:cq-status-deprecation: Stable
 :cq-description: Diagnose Camel applications with Java Flight Recorder
 :cq-deprecated: false
 :cq-jvm-since: 1.7.0
-:cq-native-since: n/a
+:cq-native-since: 2.6.0
 
 [.badges]
-[.badge-key]##JVM since##[.badge-supported]##1.7.0## [.badge-key]##Native##[.badge-unsupported]##unsupported##
+[.badge-key]##JVM since##[.badge-supported]##1.7.0## [.badge-key]##Native since##[.badge-supported]##2.6.0##
 
 Diagnose Camel applications with Java Flight Recorder
 
@@ -24,6 +24,10 @@ Please refer to the above link for usage and configuration details.
 
 == Maven coordinates
 
+https://code.quarkus.io/?extension-search=camel-quarkus-jfr[Create a new project with this extension on code.quarkus.io, window="_blank"]
+
+Or add the coordinates to your existing project:
+
 [source,xml]
 ----
 <dependency>
@@ -34,6 +38,43 @@ Please refer to the above link for usage and configuration details.
 
 Check the xref:user-guide/index.adoc[User guide] for more information about writing Camel Quarkus applications.
 
+== Usage
+
+### Starting flight recording
+
+To enable Java Flight Recorder to start a recording and automatically dump the recording to disk after Camel startup is complete, use the following configuration in `application.properties`.
+
+[source,properties]
+----
+quarkus.camel.jfr.startup-recorder-recording=true
+----
+
+Alternatively you can pass some Java options to the runnable application JAR or the native executable to enable flight recording at application startup.
+
+In JVM mode the application runnable JAR can be executed as follows.
+
+[source,shell]
+----
+$ java -XX:+FlightRecorder -XX:StartFlightRecording=filename=recording.jfr -jar quarkus-run.jar
+----
+
+In native mode, the native executable can be executed as follows.
+
+[source,shell]
+----
+$ ./my-application-runner -XX:+FlightRecorder -XX:StartFlightRecording=filename=recording.jfr
+----
+
+### Flight recording in native mode
+
+To build a native image with Java Flight Recorder support, it is mandatory to enable VM inspection via the following configuration property in `application.properties`.
+
+[source,properties]
+----
+quarkus.native.enable-vm-inspection=true
+----
+
+
 == Additional Camel Quarkus configuration
 
 [width="100%",cols="80,5,15",options="header"]
@@ -41,31 +82,31 @@ Check the xref:user-guide/index.adoc[User guide] for more information about writ
 | Configuration property | Type | Default
 
 
-|icon:lock[title=Fixed at build time] [[quarkus.camel.jfr.startup-recorder-dir]]`link:#quarkus.camel.jfr.startup-recorder-dir[quarkus.camel.jfr.startup-recorder-dir]`
+| [[quarkus.camel.jfr.startup-recorder-dir]]`link:#quarkus.camel.jfr.startup-recorder-dir[quarkus.camel.jfr.startup-recorder-dir]`
 
 Directory to store the recording. By default the current directory will be used. Use false to turn off saving the recording to disk.
 | `string`
 | 
 
-|icon:lock[title=Fixed at build time] [[quarkus.camel.jfr.startup-recorder-duration]]`link:#quarkus.camel.jfr.startup-recorder-duration[quarkus.camel.jfr.startup-recorder-duration]`
+| [[quarkus.camel.jfr.startup-recorder-duration]]`link:#quarkus.camel.jfr.startup-recorder-duration[quarkus.camel.jfr.startup-recorder-duration]`
 
 How long time to run the startup recorder. Use 0 (default) to keep the recorder running until the JVM is exited. Use -1 to stop the recorder right after Camel has been started (to only focus on potential Camel startup performance bottlenecks) Use a positive value to keep recording for N seconds. When the recorder is stopped then the recording is auto saved to disk (note: save to disk can be disabled by setting startupRecorderDir to false).
 | `java.lang.Long`
 | 
 
-|icon:lock[title=Fixed at build time] [[quarkus.camel.jfr.startup-recorder-max-depth]]`link:#quarkus.camel.jfr.startup-recorder-max-depth[quarkus.camel.jfr.startup-recorder-max-depth]`
+| [[quarkus.camel.jfr.startup-recorder-max-depth]]`link:#quarkus.camel.jfr.startup-recorder-max-depth[quarkus.camel.jfr.startup-recorder-max-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.
 | `java.lang.Integer`
 | 
 
-|icon:lock[title=Fixed at build time] [[quarkus.camel.jfr.startup-recorder-profile]]`link:#quarkus.camel.jfr.startup-recorder-profile[quarkus.camel.jfr.startup-recorder-profile]`
+| [[quarkus.camel.jfr.startup-recorder-profile]]`link:#quarkus.camel.jfr.startup-recorder-profile[quarkus.camel.jfr.startup-recorder-profile]`
 
 To use a specific Java Flight Recorder profile configuration, such as default or profile. The default is default.
 | `string`
 | 
 
-|icon:lock[title=Fixed at build time] [[quarkus.camel.jfr.startup-recorder-recording]]`link:#quarkus.camel.jfr.startup-recorder-recording[quarkus.camel.jfr.startup-recorder-recording]`
+| [[quarkus.camel.jfr.startup-recorder-recording]]`link:#quarkus.camel.jfr.startup-recorder-recording[quarkus.camel.jfr.startup-recorder-recording]`
 
 To enable Java Flight Recorder to start a recording and automatic dump the recording to disk after startup is complete. This requires that camel-jfr is on the classpath. The default is false.
 | `java.lang.Boolean`
diff --git a/docs/modules/ROOT/partials/reference/others/jfr.adoc b/docs/modules/ROOT/partials/reference/others/jfr.adoc
index b3d4714..c7ba938 100644
--- a/docs/modules/ROOT/partials/reference/others/jfr.adoc
+++ b/docs/modules/ROOT/partials/reference/others/jfr.adoc
@@ -2,11 +2,11 @@
 // This file was generated by camel-quarkus-maven-plugin:update-extension-doc-page
 :cq-artifact-id: camel-quarkus-jfr
 :cq-artifact-id-base: jfr
-:cq-native-supported: false
-:cq-status: Preview
+:cq-native-supported: true
+:cq-status: Stable
 :cq-deprecated: false
 :cq-jvm-since: 1.7.0
-:cq-native-since: n/a
+:cq-native-since: 2.6.0
 :cq-camel-part-name: jfr
 :cq-camel-part-title: Jfr
 :cq-camel-part-description: Diagnose Camel applications with Java Flight Recorder
diff --git a/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelContextProcessor.java b/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelContextProcessor.java
index 814ac56..5d2f023 100644
--- a/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelContextProcessor.java
+++ b/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelContextProcessor.java
@@ -47,7 +47,6 @@ import org.apache.camel.quarkus.core.deployment.spi.CamelRegistryBuildItem;
 import org.apache.camel.quarkus.core.deployment.spi.CamelRoutesBuilderClassBuildItem;
 import org.apache.camel.quarkus.core.deployment.spi.CamelRuntimeBuildItem;
 import org.apache.camel.quarkus.core.deployment.spi.CamelRuntimeTaskBuildItem;
-import org.apache.camel.quarkus.core.deployment.spi.CamelStartupStepRecorderBuildItem;
 import org.apache.camel.quarkus.core.deployment.spi.CamelTypeConverterRegistryBuildItem;
 import org.apache.camel.quarkus.core.deployment.spi.ContainerBeansBuildItem;
 import org.apache.camel.quarkus.core.deployment.spi.RuntimeCamelContextCustomizerBuildItem;
@@ -81,7 +80,6 @@ public class CamelContextProcessor {
             CamelModelToXMLDumperBuildItem modelDumper,
             CamelFactoryFinderResolverBuildItem factoryFinderResolver,
             List<CamelContextCustomizerBuildItem> customizers,
-            CamelStartupStepRecorderBuildItem startupStepRecorder,
             CamelComponentNameResolverBuildItem componentNameResolver,
             CamelConfig config) {
 
@@ -91,7 +89,6 @@ public class CamelContextProcessor {
                 modelJAXBContextFactory.getContextFactory(),
                 modelDumper.getValue(),
                 factoryFinderResolver.getFactoryFinderResolver(),
-                startupStepRecorder.getValue(),
                 componentNameResolver.getComponentNameResolver(),
                 beanContainer.getValue(),
                 CamelSupport.getCamelVersion(),
diff --git a/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelProcessor.java b/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelProcessor.java
index a333305..639e386 100644
--- a/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelProcessor.java
+++ b/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/CamelProcessor.java
@@ -65,7 +65,6 @@ import org.apache.camel.quarkus.core.deployment.spi.CamelServiceDestination;
 import org.apache.camel.quarkus.core.deployment.spi.CamelServiceFilter;
 import org.apache.camel.quarkus.core.deployment.spi.CamelServiceFilterBuildItem;
 import org.apache.camel.quarkus.core.deployment.spi.CamelServicePatternBuildItem;
-import org.apache.camel.quarkus.core.deployment.spi.CamelStartupStepRecorderBuildItem;
 import org.apache.camel.quarkus.core.deployment.spi.CamelTypeConverterLoaderBuildItem;
 import org.apache.camel.quarkus.core.deployment.spi.CamelTypeConverterRegistryBuildItem;
 import org.apache.camel.quarkus.core.deployment.spi.ContainerBeansBuildItem;
@@ -334,13 +333,6 @@ class CamelProcessor {
         return new CamelFactoryFinderResolverBuildItem(recorder.factoryFinderResolver(builder));
     }
 
-    @Overridable
-    @BuildStep
-    @Record(value = ExecutionTime.STATIC_INIT, optional = true)
-    public CamelStartupStepRecorderBuildItem createStartupStepRecorder(CamelRecorder recorder) {
-        return new CamelStartupStepRecorderBuildItem(recorder.newDefaultStartupStepRecorder());
-    }
-
     @BuildStep
     UnremovableBeanBuildItem unremovableRoutesBuilders() {
         return new UnremovableBeanBuildItem(
diff --git a/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelStartupStepRecorderBuildItem.java b/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelStartupStepRecorderBuildItem.java
deleted file mode 100644
index cd4229f..0000000
--- a/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelStartupStepRecorderBuildItem.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.quarkus.core.deployment.spi;
-
-import io.quarkus.builder.item.SimpleBuildItem;
-import io.quarkus.runtime.RuntimeValue;
-import org.apache.camel.spi.StartupStepRecorder;
-
-/**
- * Holds the {@link RuntimeValue} of a {@link StartupStepRecorder} to be configured on the CamelContext.
- *
- * By default this BuildItem is produced holding a {@link org.apache.camel.support.startup.DefaultStartupStepRecorder}.
- *
- * However, this is overridable by other extensions that choose to produce CamelStartupStepRecorderBuildItem with a
- * different {@link StartupStepRecorder} implementation.
- */
-public final class CamelStartupStepRecorderBuildItem extends SimpleBuildItem {
-    private final RuntimeValue<StartupStepRecorder> value;
-
-    public CamelStartupStepRecorderBuildItem(RuntimeValue<StartupStepRecorder> value) {
-        this.value = value;
-    }
-
-    public RuntimeValue<StartupStepRecorder> getValue() {
-        return value;
-    }
-}
diff --git a/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/CamelContextRecorder.java b/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/CamelContextRecorder.java
index 1e03f27..d73891b 100644
--- a/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/CamelContextRecorder.java
+++ b/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/CamelContextRecorder.java
@@ -22,7 +22,6 @@ import io.quarkus.arc.runtime.BeanContainer;
 import io.quarkus.runtime.RuntimeValue;
 import io.quarkus.runtime.annotations.Recorder;
 import org.apache.camel.CamelContext;
-import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.RoutesBuilder;
 import org.apache.camel.builder.LambdaRouteBuilder;
 import org.apache.camel.builder.RouteBuilder;
@@ -33,7 +32,6 @@ import org.apache.camel.spi.FactoryFinderResolver;
 import org.apache.camel.spi.ModelJAXBContextFactory;
 import org.apache.camel.spi.ModelToXMLDumper;
 import org.apache.camel.spi.Registry;
-import org.apache.camel.spi.StartupStepRecorder;
 import org.apache.camel.spi.TypeConverterRegistry;
 
 @Recorder
@@ -44,7 +42,6 @@ public class CamelContextRecorder {
             RuntimeValue<ModelJAXBContextFactory> contextFactory,
             RuntimeValue<ModelToXMLDumper> xmlModelDumper,
             RuntimeValue<FactoryFinderResolver> factoryFinderResolver,
-            RuntimeValue<StartupStepRecorder> startupStepRecorder,
             RuntimeValue<ComponentNameResolver> componentNameResolver,
             BeanContainer beanContainer,
             String version,
@@ -63,7 +60,6 @@ public class CamelContextRecorder {
         context.setTypeConverterRegistry(typeConverterRegistry.getValue());
         context.setLoadTypeConverters(false);
         context.setModelJAXBContextFactory(contextFactory.getValue());
-        context.adapt(ExtendedCamelContext.class).setStartupStepRecorder(startupStepRecorder.getValue());
         context.build();
         context.setComponentNameResolver(componentNameResolver.getValue());
 
diff --git a/extensions-jvm/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/CamelJfrRecorder.java b/extensions-jvm/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/CamelJfrRecorder.java
deleted file mode 100644
index 53cc277..0000000
--- a/extensions-jvm/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/CamelJfrRecorder.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.quarkus.component.jfr;
-
-import io.quarkus.runtime.RuntimeValue;
-import io.quarkus.runtime.annotations.Recorder;
-import org.apache.camel.spi.StartupStepRecorder;
-import org.apache.camel.startup.jfr.FlightRecorderStartupStepRecorder;
-
-@Recorder
-public class CamelJfrRecorder {
-
-    public RuntimeValue<StartupStepRecorder> createStartupStepRecorder(CamelJfrConfig config) {
-        FlightRecorderStartupStepRecorder flightRecorder = new FlightRecorderStartupStepRecorder();
-
-        if (config.startupRecorderRecording.isPresent()) {
-            flightRecorder.setRecording(config.startupRecorderRecording.get());
-        }
-
-        if (config.startupRecorderProfile.isPresent()) {
-            flightRecorder.setRecordingProfile(config.startupRecorderProfile.get());
-        }
-
-        if (config.startupRecorderMaxDepth.isPresent()) {
-            flightRecorder.setMaxDepth(config.startupRecorderMaxDepth.get());
-        }
-
-        if (config.startupRecorderDuration.isPresent()) {
-            flightRecorder.setStartupRecorderDuration(config.startupRecorderDuration.get());
-        }
-
-        if (config.startupRecorderDir.isPresent()) {
-            flightRecorder.setRecordingDir(config.startupRecorderDir.get());
-        }
-
-        return new RuntimeValue<>(flightRecorder);
-    }
-}
diff --git a/extensions-jvm/pom.xml b/extensions-jvm/pom.xml
index f217db0..61f0a1a 100644
--- a/extensions-jvm/pom.xml
+++ b/extensions-jvm/pom.xml
@@ -83,7 +83,6 @@
         <module>jcache</module>
         <module>jclouds</module>
         <module>jcr</module>
-        <module>jfr</module>
         <module>jgroups</module>
         <module>jgroups-raft</module>
         <module>jooq</module>
diff --git a/extensions-jvm/jfr/deployment/pom.xml b/extensions/jfr/deployment/pom.xml
similarity index 100%
rename from extensions-jvm/jfr/deployment/pom.xml
rename to extensions/jfr/deployment/pom.xml
diff --git a/extensions-jvm/jfr/deployment/src/main/java/org/apache/camel/quarkus/component/jfr/deployment/JfrProcessor.java b/extensions/jfr/deployment/src/main/java/org/apache/camel/quarkus/component/jfr/deployment/JfrProcessor.java
similarity index 73%
rename from extensions-jvm/jfr/deployment/src/main/java/org/apache/camel/quarkus/component/jfr/deployment/JfrProcessor.java
rename to extensions/jfr/deployment/src/main/java/org/apache/camel/quarkus/component/jfr/deployment/JfrProcessor.java
index 8956642..58ad85a 100644
--- a/extensions-jvm/jfr/deployment/src/main/java/org/apache/camel/quarkus/component/jfr/deployment/JfrProcessor.java
+++ b/extensions/jfr/deployment/src/main/java/org/apache/camel/quarkus/component/jfr/deployment/JfrProcessor.java
@@ -20,13 +20,12 @@ import io.quarkus.deployment.annotations.BuildStep;
 import io.quarkus.deployment.annotations.ExecutionTime;
 import io.quarkus.deployment.annotations.Record;
 import io.quarkus.deployment.builditem.FeatureBuildItem;
-import io.quarkus.deployment.pkg.steps.NativeBuild;
-import org.apache.camel.quarkus.component.jfr.CamelJfrConfig;
 import org.apache.camel.quarkus.component.jfr.CamelJfrRecorder;
+import org.apache.camel.quarkus.component.jfr.RuntimeCamelJfrConfig;
 import org.apache.camel.quarkus.core.deployment.main.spi.CamelMainEnabled;
 import org.apache.camel.quarkus.core.deployment.spi.CamelServiceDestination;
 import org.apache.camel.quarkus.core.deployment.spi.CamelServicePatternBuildItem;
-import org.apache.camel.quarkus.core.deployment.spi.CamelStartupStepRecorderBuildItem;
+import org.apache.camel.quarkus.core.deployment.spi.RuntimeCamelContextCustomizerBuildItem;
 
 class JfrProcessor {
 
@@ -44,15 +43,9 @@ class JfrProcessor {
                 "META-INF/services/org/apache/camel/startup-step-recorder");
     }
 
+    @Record(value = ExecutionTime.RUNTIME_INIT)
     @BuildStep
-    @Record(value = ExecutionTime.STATIC_INIT, optional = true)
-    CamelStartupStepRecorderBuildItem customizeCamelContext(CamelJfrConfig config, CamelJfrRecorder recorder) {
-        return new CamelStartupStepRecorderBuildItem(recorder.createStartupStepRecorder(config));
-    }
-
-    @BuildStep(onlyIf = NativeBuild.class)
-    void nativeUnsupported() {
-        throw new RuntimeException("The " + FEATURE + " extension is not supported in native mode "
-                + "as JFR APIs are not fully supported on GraalVM");
+    RuntimeCamelContextCustomizerBuildItem customizeCamelContext(RuntimeCamelJfrConfig config, CamelJfrRecorder recorder) {
+        return new RuntimeCamelContextCustomizerBuildItem(recorder.createStartupStepRecorder(config));
     }
 }
diff --git a/extensions-jvm/jfr/deployment/src/test/java/org/apache/camel/quarkus/component/jfr/deployment/JfrConfigInterceptorTest.java b/extensions/jfr/deployment/src/test/java/org/apache/camel/quarkus/component/jfr/deployment/JfrConfigInterceptorTest.java
similarity index 100%
rename from extensions-jvm/jfr/deployment/src/test/java/org/apache/camel/quarkus/component/jfr/deployment/JfrConfigInterceptorTest.java
rename to extensions/jfr/deployment/src/test/java/org/apache/camel/quarkus/component/jfr/deployment/JfrConfigInterceptorTest.java
diff --git a/extensions-jvm/jfr/pom.xml b/extensions/jfr/pom.xml
similarity index 96%
rename from extensions-jvm/jfr/pom.xml
rename to extensions/jfr/pom.xml
index 468facc..2d0ca9c 100644
--- a/extensions-jvm/jfr/pom.xml
+++ b/extensions/jfr/pom.xml
@@ -21,7 +21,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.camel.quarkus</groupId>
-        <artifactId>camel-quarkus-extensions-jvm</artifactId>
+        <artifactId>camel-quarkus-extensions</artifactId>
         <version>2.6.0-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
diff --git a/extensions-jvm/jfr/runtime/pom.xml b/extensions/jfr/runtime/pom.xml
similarity index 98%
rename from extensions-jvm/jfr/runtime/pom.xml
rename to extensions/jfr/runtime/pom.xml
index 5586f29..396c01b 100644
--- a/extensions-jvm/jfr/runtime/pom.xml
+++ b/extensions/jfr/runtime/pom.xml
@@ -32,6 +32,7 @@
 
     <properties>
         <camel.quarkus.jvmSince>1.7.0</camel.quarkus.jvmSince>
+        <camel.quarkus.nativeSince>2.6.0</camel.quarkus.nativeSince>
     </properties>
 
     <dependencyManagement>
diff --git a/extensions/jfr/runtime/src/main/doc/usage.adoc b/extensions/jfr/runtime/src/main/doc/usage.adoc
new file mode 100644
index 0000000..d4e75f8
--- /dev/null
+++ b/extensions/jfr/runtime/src/main/doc/usage.adoc
@@ -0,0 +1,33 @@
+### Starting flight recording
+
+To enable Java Flight Recorder to start a recording and automatically dump the recording to disk after Camel startup is complete, use the following configuration in `application.properties`.
+
+[source,properties]
+----
+quarkus.camel.jfr.startup-recorder-recording=true
+----
+
+Alternatively you can pass some Java options to the runnable application JAR or the native executable to enable flight recording at application startup.
+
+In JVM mode the application runnable JAR can be executed as follows.
+
+[source,shell]
+----
+$ java -XX:+FlightRecorder -XX:StartFlightRecording=filename=recording.jfr -jar quarkus-run.jar
+----
+
+In native mode, the native executable can be executed as follows.
+
+[source,shell]
+----
+$ ./my-application-runner -XX:+FlightRecorder -XX:StartFlightRecording=filename=recording.jfr
+----
+
+### Flight recording in native mode
+
+To build a native image with Java Flight Recorder support, it is mandatory to enable VM inspection via the following configuration property in `application.properties`.
+
+[source,properties]
+----
+quarkus.native.enable-vm-inspection=true
+----
diff --git a/extensions-jvm/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/CamelJfrConfigSourceInterceptorFactory.java b/extensions/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/CamelJfrConfigSourceInterceptorFactory.java
similarity index 96%
rename from extensions-jvm/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/CamelJfrConfigSourceInterceptorFactory.java
rename to extensions/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/CamelJfrConfigSourceInterceptorFactory.java
index 082e6c2..5b56763 100644
--- a/extensions-jvm/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/CamelJfrConfigSourceInterceptorFactory.java
+++ b/extensions/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/CamelJfrConfigSourceInterceptorFactory.java
@@ -25,7 +25,7 @@ import io.smallrye.config.ConfigValue;
 import io.smallrye.config.Priorities;
 
 /**
- * Map {@link CamelJfrConfig} startupRecorder properties to their equivalents in camel main.
+ * Map {@link RuntimeCamelJfrConfig} startupRecorder properties to their equivalents in camel main.
  */
 public class CamelJfrConfigSourceInterceptorFactory implements ConfigSourceInterceptorFactory {
 
diff --git a/extensions/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/CamelJfrRecorder.java b/extensions/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/CamelJfrRecorder.java
new file mode 100644
index 0000000..56b4a9b
--- /dev/null
+++ b/extensions/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/CamelJfrRecorder.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.quarkus.component.jfr;
+
+import io.quarkus.runtime.RuntimeValue;
+import io.quarkus.runtime.annotations.Recorder;
+import org.apache.camel.CamelContext;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.spi.CamelContextCustomizer;
+import org.apache.camel.startup.jfr.FlightRecorderStartupStepRecorder;
+
+@Recorder
+public class CamelJfrRecorder {
+
+    public RuntimeValue<CamelContextCustomizer> createStartupStepRecorder(RuntimeCamelJfrConfig config) {
+        CamelContextCustomizer flightRecorderCustomizer = new CamelContextCustomizer() {
+            @Override
+            public void configure(CamelContext camelContext) {
+                FlightRecorderStartupStepRecorder flightRecorder = new FlightRecorderStartupStepRecorder();
+
+                if (config.startupRecorderRecording.isPresent()) {
+                    flightRecorder.setRecording(config.startupRecorderRecording.get());
+                }
+
+                if (config.startupRecorderProfile.isPresent()) {
+                    flightRecorder.setRecordingProfile(config.startupRecorderProfile.get());
+                }
+
+                if (config.startupRecorderMaxDepth.isPresent()) {
+                    flightRecorder.setMaxDepth(config.startupRecorderMaxDepth.get());
+                }
+
+                if (config.startupRecorderDuration.isPresent()) {
+                    flightRecorder.setStartupRecorderDuration(config.startupRecorderDuration.get());
+                }
+
+                if (config.startupRecorderDir.isPresent()) {
+                    flightRecorder.setRecordingDir(config.startupRecorderDir.get());
+                }
+
+                camelContext.getExtension(ExtendedCamelContext.class).setStartupStepRecorder(flightRecorder);
+                flightRecorder.setEnabled(true);
+                flightRecorder.start();
+            }
+        };
+        return new RuntimeValue<>(flightRecorderCustomizer);
+    }
+}
diff --git a/extensions-jvm/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/CamelJfrConfig.java b/extensions/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/RuntimeCamelJfrConfig.java
similarity index 95%
rename from extensions-jvm/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/CamelJfrConfig.java
rename to extensions/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/RuntimeCamelJfrConfig.java
index 2e27c9e..625b553 100644
--- a/extensions-jvm/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/CamelJfrConfig.java
+++ b/extensions/jfr/runtime/src/main/java/org/apache/camel/quarkus/component/jfr/RuntimeCamelJfrConfig.java
@@ -22,8 +22,8 @@ import io.quarkus.runtime.annotations.ConfigItem;
 import io.quarkus.runtime.annotations.ConfigPhase;
 import io.quarkus.runtime.annotations.ConfigRoot;
 
-@ConfigRoot(name = "camel.jfr", phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)
-public class CamelJfrConfig {
+@ConfigRoot(name = "camel.jfr", phase = ConfigPhase.RUN_TIME)
+public class RuntimeCamelJfrConfig {
 
     /**
      * Directory to store the recording. By default the current directory will be used. Use false to turn off saving the
diff --git a/extensions-jvm/jfr/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/jfr/runtime/src/main/resources/META-INF/quarkus-extension.yaml
similarity index 100%
rename from extensions-jvm/jfr/runtime/src/main/resources/META-INF/quarkus-extension.yaml
rename to extensions/jfr/runtime/src/main/resources/META-INF/quarkus-extension.yaml
diff --git a/extensions-jvm/jfr/runtime/src/main/resources/META-INF/services/io.smallrye.config.ConfigSourceInterceptorFactory b/extensions/jfr/runtime/src/main/resources/META-INF/services/io.smallrye.config.ConfigSourceInterceptorFactory
similarity index 100%
rename from extensions-jvm/jfr/runtime/src/main/resources/META-INF/services/io.smallrye.config.ConfigSourceInterceptorFactory
rename to extensions/jfr/runtime/src/main/resources/META-INF/services/io.smallrye.config.ConfigSourceInterceptorFactory
diff --git a/extensions/pom.xml b/extensions/pom.xml
index af13fe4..7804bcf 100644
--- a/extensions/pom.xml
+++ b/extensions/pom.xml
@@ -132,6 +132,7 @@
         <module>jacksonxml</module>
         <module>jaxb</module>
         <module>jdbc</module>
+        <module>jfr</module>
         <module>jing</module>
         <module>jira</module>
         <module>jms</module>
diff --git a/integration-tests-jvm/pom.xml b/integration-tests-jvm/pom.xml
index 2242cfe..3abd6b8 100644
--- a/integration-tests-jvm/pom.xml
+++ b/integration-tests-jvm/pom.xml
@@ -81,7 +81,6 @@
         <module>jcache</module>
         <module>jclouds</module>
         <module>jcr</module>
-        <module>jfr</module>
         <module>jgroups</module>
         <module>jgroups-raft</module>
         <module>jooq</module>
diff --git a/integration-tests-jvm/jfr/pom.xml b/integration-tests/jfr/pom.xml
similarity index 83%
rename from integration-tests-jvm/jfr/pom.xml
rename to integration-tests/jfr/pom.xml
index 37d195c..882c0aa 100644
--- a/integration-tests-jvm/jfr/pom.xml
+++ b/integration-tests/jfr/pom.xml
@@ -112,5 +112,32 @@
                 </dependency>
             </dependencies>
         </profile>
+        <profile>
+            <id>native</id>
+            <activation>
+                <property>
+                    <name>native</name>
+                </property>
+            </activation>
+            <properties>
+                <quarkus.package.type>native</quarkus.package.type>
+            </properties>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-failsafe-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <goals>
+                                    <goal>integration-test</goal>
+                                    <goal>verify</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
     </profiles>
 </project>
diff --git a/integration-tests-jvm/jfr/src/main/java/org/apache/camel/quarkus/component/jfr/it/JfrResource.java b/integration-tests/jfr/src/main/java/org/apache/camel/quarkus/component/jfr/it/JfrResource.java
similarity index 100%
rename from integration-tests-jvm/jfr/src/main/java/org/apache/camel/quarkus/component/jfr/it/JfrResource.java
rename to integration-tests/jfr/src/main/java/org/apache/camel/quarkus/component/jfr/it/JfrResource.java
diff --git a/integration-tests-jvm/jfr/src/main/java/org/apache/camel/quarkus/component/jfr/it/JfrRoutes.java b/integration-tests/jfr/src/main/java/org/apache/camel/quarkus/component/jfr/it/JfrRoutes.java
similarity index 100%
copy from integration-tests-jvm/jfr/src/main/java/org/apache/camel/quarkus/component/jfr/it/JfrRoutes.java
copy to integration-tests/jfr/src/main/java/org/apache/camel/quarkus/component/jfr/it/JfrRoutes.java
diff --git a/integration-tests/jfr/src/main/resources/application.properties b/integration-tests/jfr/src/main/resources/application.properties
new file mode 100644
index 0000000..715da7f
--- /dev/null
+++ b/integration-tests/jfr/src/main/resources/application.properties
@@ -0,0 +1,19 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+# Must enable VM inspection for JFR in native mode
+quarkus.native.enable-vm-inspection=true
diff --git a/integration-tests-jvm/jfr/src/main/java/org/apache/camel/quarkus/component/jfr/it/JfrRoutes.java b/integration-tests/jfr/src/test/java/org/apache/camel/quarkus/component/jfr/it/JfrIT.java
similarity index 77%
rename from integration-tests-jvm/jfr/src/main/java/org/apache/camel/quarkus/component/jfr/it/JfrRoutes.java
rename to integration-tests/jfr/src/test/java/org/apache/camel/quarkus/component/jfr/it/JfrIT.java
index 5b8aa6d..418aa68 100644
--- a/integration-tests-jvm/jfr/src/main/java/org/apache/camel/quarkus/component/jfr/it/JfrRoutes.java
+++ b/integration-tests/jfr/src/test/java/org/apache/camel/quarkus/component/jfr/it/JfrIT.java
@@ -16,13 +16,9 @@
  */
 package org.apache.camel.quarkus.component.jfr.it;
 
-import org.apache.camel.builder.RouteBuilder;
+import io.quarkus.test.junit.NativeImageTest;
 
-public class JfrRoutes extends RouteBuilder {
+@NativeImageTest
+class JfrIT extends JfrTest {
 
-    @Override
-    public void configure() throws Exception {
-        from("timer:tick?repeatCount=1&delay=-1")
-                .log("Timer tick...");
-    }
 }
diff --git a/integration-tests-jvm/jfr/src/test/java/org/apache/camel/quarkus/component/jfr/it/JfrTest.java b/integration-tests/jfr/src/test/java/org/apache/camel/quarkus/component/jfr/it/JfrTest.java
similarity index 100%
rename from integration-tests-jvm/jfr/src/test/java/org/apache/camel/quarkus/component/jfr/it/JfrTest.java
rename to integration-tests/jfr/src/test/java/org/apache/camel/quarkus/component/jfr/it/JfrTest.java
diff --git a/integration-tests-jvm/jfr/src/test/java/org/apache/camel/quarkus/component/jfr/it/JfrTestResource.java b/integration-tests/jfr/src/test/java/org/apache/camel/quarkus/component/jfr/it/JfrTestResource.java
similarity index 89%
rename from integration-tests-jvm/jfr/src/test/java/org/apache/camel/quarkus/component/jfr/it/JfrTestResource.java
rename to integration-tests/jfr/src/test/java/org/apache/camel/quarkus/component/jfr/it/JfrTestResource.java
index 7f6e601..0a7eeaf 100644
--- a/integration-tests-jvm/jfr/src/test/java/org/apache/camel/quarkus/component/jfr/it/JfrTestResource.java
+++ b/integration-tests/jfr/src/test/java/org/apache/camel/quarkus/component/jfr/it/JfrTestResource.java
@@ -23,6 +23,7 @@ import java.util.Map;
 
 import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
 import org.apache.camel.util.CollectionHelper;
+import org.apache.commons.io.FileUtils;
 
 public class JfrTestResource implements QuarkusTestResourceLifecycleManager {
 
@@ -45,5 +46,10 @@ public class JfrTestResource implements QuarkusTestResourceLifecycleManager {
 
     @Override
     public void stop() {
+        try {
+            FileUtils.deleteDirectory(JFR_RECORDINGS_DIR.toFile());
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
     }
 }
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 1c71420..0c80c69 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -115,6 +115,7 @@
         <module>jackson-protobuf</module>
         <module>jaxb</module>
         <module>jdbc</module>
+        <module>jfr</module>
         <module>jing</module>
         <module>jira</module>
         <module>jms-artemis-client</module>
diff --git a/tooling/scripts/test-categories.yaml b/tooling/scripts/test-categories.yaml
index 0533f29..9811bba 100644
--- a/tooling/scripts/test-categories.yaml
+++ b/tooling/scripts/test-categories.yaml
@@ -38,6 +38,7 @@ group-02:
   - grpc
   - jackson-avro
   - jackson-protobuf
+  - jfr
   - oaipmh
   - pubnub
   - protobuf