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>

Reply via email to