Chapter 6. Observability 6.1. Health & liveness checks Health & liveness checks are supported via the MicroProfile Health extension. They can be configured via the Camel Health API or via Quarkus MicroProfile Health . All configured checks are available on the standard MicroProfile Health endpoint URLs: http://localhost:8080/q/health http://localhost:8080/q/health/live http://localhost:8080/q/health/ready 6.1.1. Health endpoint Camel provides some out of the box liveness and readiness checks. To see this working, interrogate the /q/health/live and /q/health/ready endpoints on port 9000 : USD curl -s localhost:9000/q/health/live USD curl -s localhost:9000/q/health/ready The JSON output will contain a checks for verifying whether the CamelContext and each individual route is in the 'Started' state. This example project contains a custom liveness check class CustomLivenessCheck and custom readiness check class CustomReadinessCheck which leverage the Camel health API. You'll see these listed in the health JSON as 'custom-liveness-check' and 'custom-readiness-check'. On every 5th invocation of these checks, the health status of custom-liveness-check will be reported as DOWN. You can also directly leverage MicroProfile Health APIs to create checks. Class CamelUptimeHealthCheck demonstrates how to register a readiness check. 6.2. Metrics We provide MicroProfile Metrics for exposing metrics. Some basic Camel metrics are provided for you out of the box, and these can be supplemented by configuring additional metrics in your routes. Metrics are available on the standard Quarkus metrics endpoint: http://localhost:8080/q/metrics 6.3. Monitoring a Camel application With monitoring of your applications, you can collect information about how your application behaves, such as metrics, health checks and distributed tracing. Note This section uses the Observability example listed in the Red Hat build of Quarkus examples , adding observability with micrometer . Tip Check the Camel Quarkus User guide for prerequisites and other general information. 6.3.1. Creating a project Start in the Development mode Run the maven compile command: USD mvn clean compile quarkus:dev This compiles the project, starts the application and lets the Quarkus tooling watch for changes in your workspace. Any modifications in your project automatically take effect in the running application. Tip Refer to the Development mode section of Camel Quarkus User guide for more details. 6.3.2. Enabling metrics To enable observability features in Camel Quarkus, you must add additional dependencies to the project's pom.xml file. The most important ones are camel-quarkus-opentelemetry and quarkus-micrometer-registry-prometheus . Add the dependencies to your project pom.xml : <dependencies> ... <dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-opentelemetry</artifactId> </dependency> <dependency> <groupId>io.quarkiverse.micrometer.registry</groupId> <artifactId>quarkus-micrometer-registry-prometheus</artifactId> </dependency> ... </dependencies> With these dependencies you benefit from both Camel Micrometer and Quarkus Micrometer . 6.3.3. Creating meters You can create meters for custom metrics in multiple ways: Section 6.3.3.1, "Using Camel micrometer component" Section 6.3.3.2, "Using CDI dependency injection" Section 6.3.3.3, "Using Micrometer annotations" 6.3.3.1. Using Camel micrometer component With this method you use Routes.java . .to("micrometer:counter:org.acme.observability.greeting-provider?tags=type=events,purpose=example") Which will count each call to the platform-http:/greeting-provider endpoint. 6.3.3.2. Using CDI dependency injection With this method you use CDI dependency injection of the MeterRegistry : @Inject MeterRegistry registry; Then using it directly in a Camel Processor method to publish metrics: void countGreeting(Exchange exchange) { registry.counter("org.acme.observability.greeting", "type", "events", "purpose", "example").increment(); } from("platform-http:/greeting") .removeHeaders("*") .process(this::countGreeting) This counts each call to the platform-http:/greeting endpoint. 6.3.3.3. Using Micrometer annotations With this method you use Micrometer annotations , by defining a bean TimerCounter.java as follows: @ApplicationScoped @Named("timerCounter") public class TimerCounter { @Counted(value = "org.acme.observability.timer-counter", extraTags = { "purpose", "example" }) public void count() { } } It can then be invoked from Camel via the bean EIP (see TimerRoute.java ): .bean("timerCounter", "count") It will increment the counter metric each time the Camel timer is fired. 6.3.3.4. Browsing metrics Metrics are exposed on an HTTP endpoint at /q/metrics on port 9000 . Note Note we are using a different port (9000) for the management endpoint then our application (8080) is listening on. This is configured in application.properties via quarkus.management.enabled = true . See the Quarkus management interface guide for more information. To view all Camel metrics do: USD curl -s localhost:9000/q/metrics To view only our previously created metrics, use: USD curl -s localhost:9000/q/metrics | grep -i 'purpose="example"' and you should see 3 lines of different metrics (with the same value, as they are all triggered by the timer). Note Maybe you've noticed the Prometheus output format. If you would rather use the JSON format, please follow the Quarkus Micrometer management interface configuration guide . 6.3.4. Tracing To be able to diagnose problems in Camel Quarkus applications, you can start tracing messages. We will use OpenTelemetry standard suited for cloud environments. All you need is to add the dependencies camel-quarkus-opentelemetry and quarkus-micrometer-registry-prometheus to your project pom.xml : <dependencies> ... <dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-opentelemetry</artifactId> </dependency> <dependency> <groupId>io.quarkiverse.micrometer.registry</groupId> <artifactId>quarkus-micrometer-registry-prometheus</artifactId> </dependency> ... </dependencies> Then configure the OpenTelemetry exporter in application.properties : # We are using a property placeholder to be able to test this example in convenient way in a cloud environment quarkus.otel.exporter.otlp.traces.endpoint = http://USD{TELEMETRY_COLLECTOR_COLLECTOR_SERVICE_HOST:localhost}:4317 Note For information about other OpenTelemetry exporters, refer to the Camel Quarkus OpenTelemetry extension documentation . To view tracing events, start a tracing server. A simple way of doing this is with Docker Compose: USD docker-compose up -d With the server running, browse to http://localhost:16686 . Then choose 'camel-quarkus-observability' from the 'Service' drop down and click the 'Find Traces' button. The platform-http consumer route introduces a random delay to simulate latency, hence the overall time of each trace should be different. When viewing a trace, you should see a hierarchy of 6 spans showing the progression of the message exchange through each endpoint. 6.3.5. Packaging and running the application Once you are done with developing you can package and run the application. Tip For more details about the JVM mode and Native mode, see the "Package and run" section of the Camel Quarkus User guide 6.3.5.1. JVM mode USD mvn clean package USD java -jar target/quarkus-app/quarkus-run.jar ... [io.quarkus] (main) camel-quarkus-examples-... started in 1.163s. Listening on: http://0.0.0.0:8080 6.3.5.2. Native mode Important Native mode requires having GraalVM and other tools installed. Please check the Prerequisites section of Camel Quarkus User guide . To prepare a native executable using GraalVM, run the following command: USD mvn clean package -Pnative USD ./target/*-runner ... [io.quarkus] (main) camel-quarkus-examples-... started in 0.013s. Listening on: http://0.0.0.0:8080 ...

Commands:
curl -s localhost:9000/q/health/live
curl -s localhost:9000/q/health/ready
mvn clean compile quarkus:dev
<dependencies> <dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-opentelemetry</artifactId> </dependency> <dependency> <groupId>io.quarkiverse.micrometer.registry</groupId> <artifactId>quarkus-micrometer-registry-prometheus</artifactId> </dependency> </dependencies>
.to("micrometer:counter:org.acme.observability.greeting-provider?tags=type=events,purpose=example")
@Inject MeterRegistry registry;
void countGreeting(Exchange exchange) { registry.counter("org.acme.observability.greeting", "type", "events", "purpose", "example").increment(); }
from("platform-http:/greeting") .removeHeaders("*") .process(this::countGreeting)
@ApplicationScoped @Named("timerCounter") public class TimerCounter { @Counted(value = "org.acme.observability.timer-counter", extraTags = { "purpose", "example" }) public void count() { } }
.bean("timerCounter", "count")
curl -s localhost:9000/q/metrics
curl -s localhost:9000/q/metrics | grep -i 'purpose="example"'
<dependencies> <dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-opentelemetry</artifactId> </dependency> <dependency> <groupId>io.quarkiverse.micrometer.registry</groupId> <artifactId>quarkus-micrometer-registry-prometheus</artifactId> </dependency> </dependencies>
We are using a property placeholder to be able to test this example in convenient way in a cloud environment quarkus.otel.exporter.otlp.traces.endpoint = http://USD{TELEMETRY_COLLECTOR_COLLECTOR_SERVICE_HOST:localhost}:4317
docker-compose up -d
mvn clean package java -jar target/quarkus-app/quarkus-run.jar [io.quarkus] (main) camel-quarkus-examples-... started in 1.163s. Listening on: http://0.0.0.0:8080
mvn clean package -Pnative ./target/*-runner [io.quarkus] (main) camel-quarkus-examples-... started in 0.013s. Listening on: http://0.0.0.0:8080