This is an automated email from the ASF dual-hosted git repository.
fmariani pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-spring-boot-examples.git
The following commit(s) were added to refs/heads/main by this push:
new 2879bbe Adds observability-services example
2879bbe is described below
commit 2879bbe0f07a3fb960fa678c3de8709e6e8e384f
Author: Marco Carletti <[email protected]>
AuthorDate: Wed Sep 10 17:06:33 2025 +0200
Adds observability-services example
---
README.adoc | 4 +-
observability-services/README.adoc | 95 ++++++++++++++
observability-services/docker-compose.yml | 38 ++++++
observability-services/otel-collector.yml | 31 +++++
observability-services/pom.xml | 145 +++++++++++++++++++++
observability-services/prometheus.yml | 8 ++
.../CamelObservabilityApplication.java | 30 +++++
.../example/observability/RandomNumberRoute.java | 48 +++++++
.../src/main/resources/application.properties | 24 ++++
pom.xml | 1 +
10 files changed, 423 insertions(+), 1 deletion(-)
diff --git a/README.adoc b/README.adoc
index a5f80a2..e4e3d44 100644
--- a/README.adoc
+++ b/README.adoc
@@ -27,7 +27,7 @@ readme's instructions.
=== Examples
// examples: START
-Number of Examples: 66 (0 deprecated)
+Number of Examples: 67 (0 deprecated)
[width="100%",cols="4,2,4",options="header"]
|===
@@ -168,6 +168,8 @@ Number of Examples: 66 (0 deprecated)
| link:salesforce/README.adoc[Salesforce] (salesforce) | SaaS | How to work
with Salesforce contacts using REST endpoints and Streaming API
| link:twitter-salesforce/README.adoc[Twitter Salesforce] (twitter-salesforce)
| SaaS | Twitter mentions is created as contacts in Salesforce
+
+| link:observability-services/README.adoc[Observability Services] | Management
and Monitoring | An example showing how to use Camel with Observability Services
|===
// examples: END
diff --git a/observability-services/README.adoc
b/observability-services/README.adoc
new file mode 100644
index 0000000..7bade71
--- /dev/null
+++ b/observability-services/README.adoc
@@ -0,0 +1,95 @@
+== Spring Boot Example with Camel Observability Services
+
+=== Introduction
+
+This example illustrates how to use
https://projects.spring.io/spring-boot/[Spring Boot] with
http://camel.apache.org[Camel] to demonstrate observability capabilities. It
implements a REST service that generates random numbers with variable response
times, showcasing distributed tracing, metrics collection, and monitoring
through OpenTelemetry.
+
+The project uses `camel-observability-services-starter` component for
automatic instrumentation, `camel-platform-http-starter` for REST endpoints,
and integrates with OpenTelemetry Java agent for comprehensive observability.
+
+For additional information there is
https://camel.apache.org/blog/2025/03/camel-observability[blog post]
+
+=== Observability Stack
+
+To run the complete observability stack with Jaeger and Prometheus:
+
+[source,bash]
+----
+docker-compose up
+----
+
+This will start:
+
+ - OpenTelemetry Collector (ports 4317/4318) - collects traces and metrics
+ - Jaeger UI (http://localhost:16686) - distributed tracing visualization
+ - Prometheus (http://localhost:9090) - metrics collection and storage
+
+The application, using agent, sends telemetry data to the OpenTelemetry
Collector, which exports traces to Jaeger and metrics to Prometheus.
+
+=== Run
+
+You can run this example using:
+
+[source,bash]
+----
+mvn spring-boot:run
+----
+
+After the Spring Boot application is started, you can execute the following
HTTP requests:
+
+[source,bash]
+----
+curl http://localhost:8080/api/random
+----
+
+The command will call the random number generator endpoint. Each call will:
+- Generate a random number between 1-1000
+- Simulate a random delay between 100-2000ms
+- Return the number as response body
+- Create traces and metrics for observability
+
+You should see output similar to:
+
+----
+INFO 101511 --- [ task-1] generate-random-number
: Generated random number: 742 with delay: 1250ms
+----
+
+=== Exposed Observability endpoints
+
+The `camel-observability-services-starter` will configure the application and
overrides the actuator setup so the health and metrics (in prometheus format)
endpoints will be
+
+```
+http://localhost:9876/observe/health
+
+http://localhost:9876/observe/metrics
+```
+
+even if in this example the metrics will be distributed using OpenTelemetry
agent and not scraping the `/observe/metrics` endpoint
+
+=== Testing Observability
+
+1. **Generate some traffic:**
+[source,bash]
+----
+for i in {1..10}; do curl http://localhost:8080/api/random; echo; sleep 1; done
+----
+
+2. **View traces in Jaeger:**
+ - Open http://localhost:16686
+ - Select service and search for traces
+
+3. **View metrics in Prometheus:**
+ - Open http://localhost:9090
+ - Query metrics like `camel_route_exchange_completed_total`
+
+
+The Spring Boot application can be stopped pressing `[CTRL] + [C]` in the
shell.
+
+=== Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+https://camel.apache.org/community/support/[let us know].
+
+We also love contributors, so
+https://camel.apache.org/community/contributing/[get involved] :-)
+
+The Camel riders!
\ No newline at end of file
diff --git a/observability-services/docker-compose.yml
b/observability-services/docker-compose.yml
new file mode 100644
index 0000000..b0f6946
--- /dev/null
+++ b/observability-services/docker-compose.yml
@@ -0,0 +1,38 @@
+version: "3.9"
+
+services:
+
+ otel-collector:
+ image: otel/opentelemetry-collector:latest
+ command:
+ - --config=/etc/otelcol-cont/otel-collector.yml
+ volumes:
+ - ./otel-collector.yml:/etc/otelcol-cont/otel-collector.yml
+ ports:
+ - "4318:4318" # OTLP http receiver
+ - "4317:4317" # OTLP grpc receiver
+ depends_on:
+ - jaeger-all-in-one
+ - prometheus
+
+ jaeger-all-in-one:
+ image: quay.io/jaegertracing/all-in-one:latest
+ restart: always
+ ports:
+ - "16686:16686"
+
+ prometheus:
+ image: prom/prometheus:latest
+ container_name: prometheus
+ restart: always
+ ports:
+ - "9090:9090"
+ volumes:
+ - ./prometheus.yml:/etc/prometheus/prometheus.yml
+ command:
+ - '--config.file=/etc/prometheus/prometheus.yml'
+ - '--storage.tsdb.path=/prometheus'
+ - '--web.console.libraries=/etc/prometheus/console_libraries'
+ - '--web.console.templates=/etc/prometheus/consoles'
+ - '--storage.tsdb.retention.time=200h'
+ - '--web.enable-lifecycle'
\ No newline at end of file
diff --git a/observability-services/otel-collector.yml
b/observability-services/otel-collector.yml
new file mode 100644
index 0000000..050a8f4
--- /dev/null
+++ b/observability-services/otel-collector.yml
@@ -0,0 +1,31 @@
+receivers:
+ otlp:
+ protocols:
+ grpc:
+ endpoint: 0.0.0.0:4317
+ http:
+ endpoint: 0.0.0.0:4318
+
+processors:
+ batch:
+
+exporters:
+ debug:
+ verbosity: detailed
+ otlp/jaeger:
+ endpoint: jaeger-all-in-one:4317
+ tls:
+ insecure: true
+ prometheus:
+ endpoint: "0.0.0.0:8889"
+
+service:
+ pipelines:
+ traces:
+ receivers: [otlp]
+ processors: [batch]
+ exporters: [debug,otlp/jaeger]
+ metrics:
+ receivers: [otlp]
+ processors: [batch]
+ exporters: [debug,prometheus]
\ No newline at end of file
diff --git a/observability-services/pom.xml b/observability-services/pom.xml
new file mode 100644
index 0000000..d4880e6
--- /dev/null
+++ b/observability-services/pom.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.camel.springboot.example</groupId>
+ <artifactId>examples</artifactId>
+ <version>4.15.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>camel-example-spring-boot-observability-services</artifactId>
+ <name>Camel SB Examples :: Observability Services</name>
+ <description>This example shows how to work with Apache Camel
observability services using Spring Boot</description>
+
+ <properties>
+ <category>Management and Monitoring</category>
+ <opentelemetry-agent.version>2.19.0</opentelemetry-agent.version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <!-- Camel BOM -->
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-spring-boot-bom</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <!-- Spring Boot BOM -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>${spring-boot-version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <!-- spring-boot -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-actuator</artifactId>
+ </dependency>
+
+ <!-- Camel -->
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-spring-boot-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-observability-services-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-platform-http-starter</artifactId>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-javaagent</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+
<groupId>io.opentelemetry.javaagent</groupId>
+
<artifactId>opentelemetry-javaagent</artifactId>
+
<version>${opentelemetry-agent.version}</version>
+ <overWrite>true</overWrite>
+
<outputDirectory>${project.build.directory}/javaagents</outputDirectory>
+ <destFileName>javaagent.jar</destFileName>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>${spring-boot-version}</version>
+ <configuration>
+ <agents>
+
<agent>${project.build.directory}/javaagents/javaagent.jar</agent>
+ </agents>
+ <environmentVariables>
+ <OTEL_LOGS_EXPORTER>none</OTEL_LOGS_EXPORTER>
+
<OTEL_SERVICE_NAME>camel-observability-services</OTEL_SERVICE_NAME>
+ <OTEL_JMX_TARGET_SYSTEM>camel</OTEL_JMX_TARGET_SYSTEM>
+ </environmentVariables>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
diff --git a/observability-services/prometheus.yml
b/observability-services/prometheus.yml
new file mode 100644
index 0000000..8104ede
--- /dev/null
+++ b/observability-services/prometheus.yml
@@ -0,0 +1,8 @@
+global:
+ scrape_interval: 15s
+ evaluation_interval: 15s
+
+scrape_configs:
+ - job_name: 'otel-collector'
+ static_configs:
+ - targets: ['otel-collector:8889']
\ No newline at end of file
diff --git
a/observability-services/src/main/java/org/apache/camel/example/observability/CamelObservabilityApplication.java
b/observability-services/src/main/java/org/apache/camel/example/observability/CamelObservabilityApplication.java
new file mode 100644
index 0000000..36aa0eb
--- /dev/null
+++
b/observability-services/src/main/java/org/apache/camel/example/observability/CamelObservabilityApplication.java
@@ -0,0 +1,30 @@
+/*
+ * 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.example.observability;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+//CHECKSTYLE:OFF
+@SpringBootApplication
+public class CamelObservabilityApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(CamelObservabilityApplication.class, args);
+ }
+}
+// CHECKSTYLE:ON
\ No newline at end of file
diff --git
a/observability-services/src/main/java/org/apache/camel/example/observability/RandomNumberRoute.java
b/observability-services/src/main/java/org/apache/camel/example/observability/RandomNumberRoute.java
new file mode 100644
index 0000000..44d635c
--- /dev/null
+++
b/observability-services/src/main/java/org/apache/camel/example/observability/RandomNumberRoute.java
@@ -0,0 +1,48 @@
+/*
+ * 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.example.observability;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.springframework.stereotype.Component;
+
+import java.util.Random;
+
+@Component
+public class RandomNumberRoute extends RouteBuilder {
+
+ @Override
+ public void configure() throws Exception {
+
+ rest("/api")
+ .get("/random")
+ .routeId("get-random")
+ .produces("text/plain")
+ .to("direct:generateRandomNumber");
+
+ from("direct:generateRandomNumber")
+ .routeId("generate-random-number")
+ .process(exchange -> {
+ Random random = new Random();
+ int randomNumber = random.nextInt(1000) + 1;
+ int delay = random.nextInt(1900) + 100;
+ exchange.setVariable("delay", delay);
+ exchange.getIn().setBody(String.valueOf(randomNumber));
+ })
+ .delay(simple("${variable.delay}"))
+ .log("Generated random number: ${body} with delay:
${variable.delay}ms");
+ }
+}
\ No newline at end of file
diff --git a/observability-services/src/main/resources/application.properties
b/observability-services/src/main/resources/application.properties
new file mode 100644
index 0000000..970b10d
--- /dev/null
+++ b/observability-services/src/main/resources/application.properties
@@ -0,0 +1,24 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+# Camel configuration
+camel.main.run-controller=true
+camel.main.name=camel-observability-services
+
+# Logging configuration
+logging.level.root=INFO
+logging.level.org.apache.camel=INFO
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 8efdd1a..48e6488 100644
--- a/pom.xml
+++ b/pom.xml
@@ -84,6 +84,7 @@
<module>routes-configuration</module>
<module>salesforce</module>
<module>saga</module>
+ <module>observability-services</module>
<module>soap-cxf</module>
<module>supervising-route-controller</module>
<module>twitter-salesforce</module>