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

commit 84f7ab58b7efb2ac5c003596d075cfa82bb68a0e
Author: James Netherton <jamesnether...@gmail.com>
AuthorDate: Mon Feb 3 13:22:18 2025 +0000

    Test observability-services otel tracing and JMX metrics
    
    Fixes #6968
---
 .../deployment/ObservabilityServicesProcessor.java |  10 +-
 .../ObservabilityServicesConfigSourceFactory.java  |  54 ++++++++
 ...ObservabilityServicesRuntimeConfigBuilder.java} |  17 +--
 integration-tests/observability-services/pom.xml   |  25 ++++
 .../it/health/ObservabilityServicesResource.java   |  91 +++++++++++++
 ...ilder.java => ObservabilityServicesRoutes.java} |  23 +---
 .../it/health/SpanExporterProducer.java            |  21 +--
 .../it/health/SpanExporterResource.java            |  72 ++++++++++
 .../src/main/resources/application.properties      |  11 +-
 .../it/ObservabilityServicesDefaultTest.java       |  70 ----------
 .../it/ObservabilityServicesIT.java                |   2 +-
 .../it/ObservabilityServicesTest.java              | 149 +++++++++++++++++++++
 12 files changed, 431 insertions(+), 114 deletions(-)

diff --git 
a/extensions/observability-services/deployment/src/main/java/org/apache/camel/quarkus/component/observabilityservices/deployment/ObservabilityServicesProcessor.java
 
b/extensions/observability-services/deployment/src/main/java/org/apache/camel/quarkus/component/observabilityservices/deployment/ObservabilityServicesProcessor.java
index b599823fd1..63be81aa25 100644
--- 
a/extensions/observability-services/deployment/src/main/java/org/apache/camel/quarkus/component/observabilityservices/deployment/ObservabilityServicesProcessor.java
+++ 
b/extensions/observability-services/deployment/src/main/java/org/apache/camel/quarkus/component/observabilityservices/deployment/ObservabilityServicesProcessor.java
@@ -18,13 +18,21 @@ package 
org.apache.camel.quarkus.component.observabilityservices.deployment;
 
 import io.quarkus.deployment.annotations.BuildStep;
 import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.deployment.builditem.RunTimeConfigBuilderBuildItem;
+import io.quarkus.opentelemetry.deployment.tracing.TracerEnabled;
+import 
org.apache.camel.quarkus.component.observabilityservices.ObservabilityServicesRuntimeConfigBuilder;
 
 class ObservabilityServicesProcessor {
-
     private static final String FEATURE = "camel-observability-services";
 
     @BuildStep
     FeatureBuildItem feature() {
         return new FeatureBuildItem(FEATURE);
     }
+
+    // TODO: Remove this https://github.com/apache/camel-quarkus/issues/6967
+    @BuildStep(onlyIf = TracerEnabled.class)
+    RunTimeConfigBuilderBuildItem observabilityServicesRuntimeConfiguration() {
+        return new 
RunTimeConfigBuilderBuildItem(ObservabilityServicesRuntimeConfigBuilder.class);
+    }
 }
diff --git 
a/extensions/observability-services/runtime/src/main/java/org.apache.camel.quarkus.component.observabilityservices/ObservabilityServicesConfigSourceFactory.java
 
b/extensions/observability-services/runtime/src/main/java/org.apache.camel.quarkus.component.observabilityservices/ObservabilityServicesConfigSourceFactory.java
new file mode 100644
index 0000000000..2d2d7714db
--- /dev/null
+++ 
b/extensions/observability-services/runtime/src/main/java/org.apache.camel.quarkus.component.observabilityservices/ObservabilityServicesConfigSourceFactory.java
@@ -0,0 +1,54 @@
+/*
+ * 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.observabilityservices;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import io.smallrye.config.ConfigSourceContext;
+import io.smallrye.config.ConfigSourceFactory;
+import io.smallrye.config.ConfigValue;
+import io.smallrye.config.PropertiesConfigSource;
+import org.apache.camel.util.ObjectHelper;
+import org.eclipse.microprofile.config.spi.ConfigSource;
+
+/**
+ * TODO: Remove this https://github.com/apache/camel-quarkus/issues/6967
+ */
+public class ObservabilityServicesConfigSourceFactory implements 
ConfigSourceFactory {
+    @Override
+    public Iterable<ConfigSource> getConfigSources(ConfigSourceContext 
context) {
+        ConfigValue sdkDisabled = 
context.getValue("quarkus.otel.sdk.disabled");
+
+        if (sdkDisabled != null && sdkDisabled.getValue().equals("false")) {
+            Map<String, String> properties = new HashMap<>(1);
+            ConfigValue otelSuppressedUris = 
context.getValue("quarkus.otel.traces.suppress-application-uris");
+            String suppressedEndpoints = "/observe/*";
+
+            if (otelSuppressedUris != null && 
ObjectHelper.isNotEmpty(otelSuppressedUris.getValue())) {
+                suppressedEndpoints += "," + otelSuppressedUris.getValue();
+            }
+
+            properties.put("quarkus.otel.traces.suppress-application-uris", 
suppressedEndpoints);
+            return Set.of(new PropertiesConfigSource(properties, 
"camel-quarkus-observability-services", 300));
+        }
+
+        return Collections.emptySet();
+    }
+}
diff --git 
a/extensions/observability-services/deployment/src/main/java/org/apache/camel/quarkus/component/observabilityservices/deployment/ObservabilityServicesProcessor.java
 
b/extensions/observability-services/runtime/src/main/java/org.apache.camel.quarkus.component.observabilityservices/ObservabilityServicesRuntimeConfigBuilder.java
similarity index 70%
copy from 
extensions/observability-services/deployment/src/main/java/org/apache/camel/quarkus/component/observabilityservices/deployment/ObservabilityServicesProcessor.java
copy to 
extensions/observability-services/runtime/src/main/java/org.apache.camel.quarkus.component.observabilityservices/ObservabilityServicesRuntimeConfigBuilder.java
index b599823fd1..3a382cc37e 100644
--- 
a/extensions/observability-services/deployment/src/main/java/org/apache/camel/quarkus/component/observabilityservices/deployment/ObservabilityServicesProcessor.java
+++ 
b/extensions/observability-services/runtime/src/main/java/org.apache.camel.quarkus.component.observabilityservices/ObservabilityServicesRuntimeConfigBuilder.java
@@ -14,17 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.observabilityservices.deployment;
+package org.apache.camel.quarkus.component.observabilityservices;
 
-import io.quarkus.deployment.annotations.BuildStep;
-import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.runtime.configuration.ConfigBuilder;
+import io.smallrye.config.SmallRyeConfigBuilder;
 
-class ObservabilityServicesProcessor {
-
-    private static final String FEATURE = "camel-observability-services";
-
-    @BuildStep
-    FeatureBuildItem feature() {
-        return new FeatureBuildItem(FEATURE);
+public class ObservabilityServicesRuntimeConfigBuilder implements 
ConfigBuilder {
+    @Override
+    public SmallRyeConfigBuilder configBuilder(SmallRyeConfigBuilder builder) {
+        return builder.withSources(new 
ObservabilityServicesConfigSourceFactory());
     }
 }
diff --git a/integration-tests/observability-services/pom.xml 
b/integration-tests/observability-services/pom.xml
index ea73469981..97c287347a 100644
--- a/integration-tests/observability-services/pom.xml
+++ b/integration-tests/observability-services/pom.xml
@@ -43,10 +43,22 @@
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-observability-services</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-seda</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.opentelemetry</groupId>
+            <artifactId>opentelemetry-sdk-testing</artifactId>
+        </dependency>
         <dependency>
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-resteasy</artifactId>
         </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-jsonb</artifactId>
+        </dependency>
 
         <!-- test dependencies -->
         <dependency>
@@ -142,6 +154,19 @@
                         </exclusion>
                     </exclusions>
                 </dependency>
+                <dependency>
+                    <groupId>org.apache.camel.quarkus</groupId>
+                    <artifactId>camel-quarkus-seda-deployment</artifactId>
+                    <version>${project.version}</version>
+                    <type>pom</type>
+                    <scope>test</scope>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>*</groupId>
+                            <artifactId>*</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
             </dependencies>
         </profile>
     </profiles>
diff --git 
a/integration-tests/observability-services/src/main/java/org/apache/camel/quarkus/component/observabilityservices/it/health/ObservabilityServicesResource.java
 
b/integration-tests/observability-services/src/main/java/org/apache/camel/quarkus/component/observabilityservices/it/health/ObservabilityServicesResource.java
new file mode 100644
index 0000000000..12ecd0501a
--- /dev/null
+++ 
b/integration-tests/observability-services/src/main/java/org/apache/camel/quarkus/component/observabilityservices/it/health/ObservabilityServicesResource.java
@@ -0,0 +1,91 @@
+/*
+ * 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.observabilityservices.it.health;
+
+import java.lang.management.ManagementFactory;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+
+import io.micrometer.prometheus.PrometheusMeterRegistry;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.apache.camel.FluentProducerTemplate;
+
+@Path("/observability-services")
+public class ObservabilityServicesResource {
+    @Inject
+    FluentProducerTemplate fluentProducerTemplate;
+
+    @Inject
+    PrometheusMeterRegistry prometheusMeterRegistry;
+
+    @GET
+    @Path("/registry")
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response prometheusMeterRegistry() {
+        if (prometheusMeterRegistry != null) {
+            return 
Response.ok().entity(prometheusMeterRegistry.getClass().getName()).build();
+        }
+        return Response.status(Response.Status.NOT_FOUND).build();
+    }
+
+    @POST
+    @Path("/trace")
+    @Produces(MediaType.TEXT_PLAIN)
+    public String trace(String message) {
+        return fluentProducerTemplate.to("direct:start")
+                .withBody(message)
+                .request(String.class);
+    }
+
+    @GET
+    @Path("/jmx/attribute")
+    @Produces(MediaType.TEXT_PLAIN)
+    public String getMBeanAttribute(@QueryParam("name") String name, 
@QueryParam("attribute") String attribute)
+            throws Exception {
+        ObjectInstance mbean = getMBean(name);
+        if (mbean != null) {
+            return 
String.valueOf(getMBeanServer().getAttribute(mbean.getObjectName(), attribute));
+        }
+        return null;
+    }
+
+    private ObjectInstance getMBean(String name) throws 
MalformedObjectNameException {
+        ObjectName objectName = new ObjectName(name);
+        Set<ObjectInstance> mbeans = getMBeanServer().queryMBeans(objectName, 
null);
+        Iterator<ObjectInstance> iterator = mbeans.iterator();
+        if (iterator.hasNext()) {
+            return iterator.next();
+        }
+        return null;
+    }
+
+    private MBeanServer getMBeanServer() {
+        return ManagementFactory.getPlatformMBeanServer();
+    }
+}
diff --git 
a/integration-tests/observability-services/src/main/java/org/apache/camel/quarkus/component/observabilityservices/it/health/ObservabilityServicesHealthRouteBuilder.java
 
b/integration-tests/observability-services/src/main/java/org/apache/camel/quarkus/component/observabilityservices/it/health/ObservabilityServicesRoutes.java
similarity index 51%
rename from 
integration-tests/observability-services/src/main/java/org/apache/camel/quarkus/component/observabilityservices/it/health/ObservabilityServicesHealthRouteBuilder.java
rename to 
integration-tests/observability-services/src/main/java/org/apache/camel/quarkus/component/observabilityservices/it/health/ObservabilityServicesRoutes.java
index 0156316ab3..8f011b99d5 100644
--- 
a/integration-tests/observability-services/src/main/java/org/apache/camel/quarkus/component/observabilityservices/it/health/ObservabilityServicesHealthRouteBuilder.java
+++ 
b/integration-tests/observability-services/src/main/java/org/apache/camel/quarkus/component/observabilityservices/it/health/ObservabilityServicesRoutes.java
@@ -17,24 +17,15 @@
 package org.apache.camel.quarkus.component.observabilityservices.it.health;
 
 import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.spi.SupervisingRouteController;
 
-public class ObservabilityServicesHealthRouteBuilder extends RouteBuilder {
+public class ObservabilityServicesRoutes extends RouteBuilder {
     @Override
-    public void configure() {
-        from("direct:start").routeId("healthyRoute")
-                .setBody(constant("Hello Camel Quarkus"));
+    public void configure() throws Exception {
+        from("direct:start")
+                .to("seda:next");
 
-        from("direct:disabled").routeId("disabledHealthRoute")
-                .log("This route will not show up in health checks as it is 
disabled in application.properties");
-
-        if (getContext().getRouteController() instanceof 
SupervisingRouteController) {
-            from("direct:supervising").routeId("supervisingRoute")
-                    .to("log:end");
-
-            // Force a failure for SupervisingRouteController to try and 
recover (duplicate consumer on the same endpoint)
-            from("direct:supervising?timeout=100").routeId("brokenRoute")
-                    .to("log:end");
-        }
+        from("seda:next")
+                .transform().simple("modified ${body}")
+                .log("${body}");
     }
 }
diff --git 
a/extensions/observability-services/deployment/src/main/java/org/apache/camel/quarkus/component/observabilityservices/deployment/ObservabilityServicesProcessor.java
 
b/integration-tests/observability-services/src/main/java/org/apache/camel/quarkus/component/observabilityservices/it/health/SpanExporterProducer.java
similarity index 68%
copy from 
extensions/observability-services/deployment/src/main/java/org/apache/camel/quarkus/component/observabilityservices/deployment/ObservabilityServicesProcessor.java
copy to 
integration-tests/observability-services/src/main/java/org/apache/camel/quarkus/component/observabilityservices/it/health/SpanExporterProducer.java
index b599823fd1..23d5c7c7a3 100644
--- 
a/extensions/observability-services/deployment/src/main/java/org/apache/camel/quarkus/component/observabilityservices/deployment/ObservabilityServicesProcessor.java
+++ 
b/integration-tests/observability-services/src/main/java/org/apache/camel/quarkus/component/observabilityservices/it/health/SpanExporterProducer.java
@@ -14,17 +14,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.observabilityservices.deployment;
+package org.apache.camel.quarkus.component.observabilityservices.it.health;
 
-import io.quarkus.deployment.annotations.BuildStep;
-import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.inject.Produces;
+import jakarta.inject.Singleton;
 
-class ObservabilityServicesProcessor {
-
-    private static final String FEATURE = "camel-observability-services";
-
-    @BuildStep
-    FeatureBuildItem feature() {
-        return new FeatureBuildItem(FEATURE);
+@ApplicationScoped
+public class SpanExporterProducer {
+    @Produces
+    @Singleton
+    public InMemorySpanExporter createInMemoryExporter() {
+        return InMemorySpanExporter.create();
     }
 }
diff --git 
a/integration-tests/observability-services/src/main/java/org/apache/camel/quarkus/component/observabilityservices/it/health/SpanExporterResource.java
 
b/integration-tests/observability-services/src/main/java/org/apache/camel/quarkus/component/observabilityservices/it/health/SpanExporterResource.java
new file mode 100644
index 0000000000..c57f3d7a6e
--- /dev/null
+++ 
b/integration-tests/observability-services/src/main/java/org/apache/camel/quarkus/component/observabilityservices/it/health/SpanExporterResource.java
@@ -0,0 +1,72 @@
+/*
+ * 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.observabilityservices.it.health;
+
+import java.util.Map;
+
+import io.opentelemetry.api.common.AttributeKey;
+import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter;
+import io.opentelemetry.sdk.trace.data.SpanData;
+import jakarta.inject.Inject;
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonArrayBuilder;
+import jakarta.json.JsonObjectBuilder;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+
+@Path("/spans")
+public class SpanExporterResource {
+    @Inject
+    InMemorySpanExporter exporter;
+
+    @GET
+    @Path("/export")
+    @Produces(MediaType.APPLICATION_JSON)
+    public JsonArray exportSpans() {
+        JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
+
+        for (SpanData span : exporter.getFinishedSpanItems()) {
+            if (span.getName().contains("exporter")) {
+                // Ignore any trace events on this resource
+                continue;
+            }
+
+            Map<AttributeKey<?>, Object> attributes = 
span.getAttributes().asMap();
+            JsonObjectBuilder objectBuilder = Json.createObjectBuilder();
+            objectBuilder.add("spanId", span.getSpanId());
+            objectBuilder.add("traceId", span.getTraceId());
+            objectBuilder.add("parentId", span.getParentSpanId());
+            objectBuilder.add("kind", span.getKind().name());
+
+            attributes.forEach((k, v) -> objectBuilder.add(String.valueOf(k), 
v.toString()));
+
+            arrayBuilder.add(objectBuilder.build());
+        }
+
+        return arrayBuilder.build();
+    }
+
+    @POST
+    @Path("/reset")
+    public void resetSpanExporter() {
+        exporter.reset();
+    }
+}
diff --git 
a/integration-tests/observability-services/src/main/resources/application.properties
 
b/integration-tests/observability-services/src/main/resources/application.properties
index 526e9a9a8d..75eac8f864 100644
--- 
a/integration-tests/observability-services/src/main/resources/application.properties
+++ 
b/integration-tests/observability-services/src/main/resources/application.properties
@@ -15,10 +15,9 @@
 ## limitations under the License.
 ## ---------------------------------------------------------------------------
 
-#
-# Camel
-#
-camel.context.name = quarkus-camel-example
+camel.context.name=observability-services-context
 
-# Prevent unwanted routes appearing in the health check output
-camel.health.exclude-pattern = disabledHealthRoute
+quarkus.otel.sdk.disabled=false
+quarkus.otel.bsp.export.timeout=1s
+quarkus.otel.bsp.schedule.delay=50
+quarkus.otel.traces.suppress-application-uris=/spans/*,/observability-services/registry
diff --git 
a/integration-tests/observability-services/src/test/java/org/apache/camel/quarkus/component/observabilityservices/it/ObservabilityServicesDefaultTest.java
 
b/integration-tests/observability-services/src/test/java/org/apache/camel/quarkus/component/observabilityservices/it/ObservabilityServicesDefaultTest.java
deleted file mode 100644
index cd1589aefc..0000000000
--- 
a/integration-tests/observability-services/src/test/java/org/apache/camel/quarkus/component/observabilityservices/it/ObservabilityServicesDefaultTest.java
+++ /dev/null
@@ -1,70 +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.observabilityservices.it;
-
-import io.quarkus.test.junit.QuarkusTest;
-import io.restassured.RestAssured;
-import io.restassured.http.ContentType;
-import org.apache.http.HttpStatus;
-import org.junit.jupiter.api.Test;
-
-import static org.hamcrest.Matchers.contains;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-
-@QuarkusTest
-class ObservabilityServicesDefaultTest {
-
-    @Test
-    public void testHealthUpStatus() {
-        RestAssured.when().get("/observe/health").then()
-                .contentType(ContentType.JSON)
-                .header("Content-Type", containsString("charset=UTF-8"))
-                .body("status", is("UP"),
-                        "checks.status.findAll().unique()", contains("UP"),
-                        "checks.find { it.name == 'camel-routes' }", 
notNullValue(),
-                        "checks.find { it.name == 'camel-consumers' }", 
notNullValue(),
-                        "checks.find { it.name == 'context' }", notNullValue(),
-                        "checks.find { it.name == 'context' 
}.data.'context.name'", notNullValue());
-    }
-
-    @Test
-    public void testLivenessUpStatus() {
-        RestAssured.when().get("/observe/health/live").then()
-                .contentType(ContentType.JSON)
-                .header("Content-Type", containsString("charset=UTF-8"))
-                .body("status", is("UP"),
-                        "checks.status.findAll().unique()", contains("UP"));
-    }
-
-    @Test
-    public void testReadinessUpStatus() {
-        RestAssured.when().get("/observe/health/ready").then()
-                .contentType(ContentType.JSON)
-                .header("Content-Type", containsString("charset=UTF-8"))
-                .body("status", is("UP"),
-                        "checks.status.findAll().unique()", contains("UP"));
-    }
-
-    @Test
-    public void testMetricsStatus() {
-        RestAssured.when().get("/observe/metrics").then()
-                .header("Content-Type", 
containsString("application/openmetrics-text"))
-                .statusCode(HttpStatus.SC_OK);
-    }
-}
diff --git 
a/integration-tests/observability-services/src/test/java/org/apache/camel/quarkus/component/observabilityservices/it/ObservabilityServicesIT.java
 
b/integration-tests/observability-services/src/test/java/org/apache/camel/quarkus/component/observabilityservices/it/ObservabilityServicesIT.java
index c1a786b925..043b40ec5d 100644
--- 
a/integration-tests/observability-services/src/test/java/org/apache/camel/quarkus/component/observabilityservices/it/ObservabilityServicesIT.java
+++ 
b/integration-tests/observability-services/src/test/java/org/apache/camel/quarkus/component/observabilityservices/it/ObservabilityServicesIT.java
@@ -19,6 +19,6 @@ package 
org.apache.camel.quarkus.component.observabilityservices.it;
 import io.quarkus.test.junit.QuarkusIntegrationTest;
 
 @QuarkusIntegrationTest
-class ObservabilityServicesIT extends ObservabilityServicesDefaultTest {
+class ObservabilityServicesIT extends ObservabilityServicesTest {
 
 }
diff --git 
a/integration-tests/observability-services/src/test/java/org/apache/camel/quarkus/component/observabilityservices/it/ObservabilityServicesTest.java
 
b/integration-tests/observability-services/src/test/java/org/apache/camel/quarkus/component/observabilityservices/it/ObservabilityServicesTest.java
new file mode 100644
index 0000000000..7c7cf5b495
--- /dev/null
+++ 
b/integration-tests/observability-services/src/test/java/org/apache/camel/quarkus/component/observabilityservices/it/ObservabilityServicesTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.observabilityservices.it;
+
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import io.micrometer.prometheus.PrometheusMeterRegistry;
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import io.restassured.http.ContentType;
+import org.apache.http.HttpStatus;
+import org.junit.jupiter.api.Test;
+
+import static org.awaitility.Awaitility.await;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@QuarkusTest
+class ObservabilityServicesTest {
+
+    @Test
+    void testHealthUpStatus() {
+        RestAssured.when().get("/observe/health").then()
+                .contentType(ContentType.JSON)
+                .header("Content-Type", containsString("charset=UTF-8"))
+                .body("status", is("UP"),
+                        "checks.status.findAll().unique()", contains("UP"),
+                        "checks.find { it.name == 'camel-routes' }", 
notNullValue(),
+                        "checks.find { it.name == 'camel-consumers' }", 
notNullValue(),
+                        "checks.find { it.name == 'context' }", notNullValue(),
+                        "checks.find { it.name == 'context' 
}.data.'context.name'", notNullValue());
+    }
+
+    @Test
+    void testLivenessUpStatus() {
+        RestAssured.when().get("/observe/health/live").then()
+                .contentType(ContentType.JSON)
+                .header("Content-Type", containsString("charset=UTF-8"))
+                .body("status", is("UP"),
+                        "checks.status.findAll().unique()", contains("UP"));
+    }
+
+    @Test
+    void testReadinessUpStatus() {
+        RestAssured.when().get("/observe/health/ready").then()
+                .contentType(ContentType.JSON)
+                .header("Content-Type", containsString("charset=UTF-8"))
+                .body("status", is("UP"),
+                        "checks.status.findAll().unique()", contains("UP"));
+    }
+
+    @Test
+    void testMetricsStatus() {
+        RestAssured.when().get("/observe/metrics").then()
+                .header("Content-Type", 
containsString("application/openmetrics-text"))
+                .statusCode(HttpStatus.SC_OK);
+    }
+
+    @Test
+    void metricsRegistry() {
+        RestAssured.get("/observability-services/registry")
+                .then()
+                .statusCode(200)
+                .body(is(PrometheusMeterRegistry.class.getName()));
+    }
+
+    @Test
+    void traceRoute() {
+        try {
+            String message = UUID.randomUUID().toString();
+            RestAssured.given()
+                    .body(message)
+                    .post("/observability-services/trace")
+                    .then()
+                    .statusCode(200)
+                    .body(is("modified " + message));
+
+            await().atMost(30, TimeUnit.SECONDS).pollDelay(50, 
TimeUnit.MILLISECONDS).until(() -> getSpans().size() == 5);
+            List<Map<String, String>> spans = getSpans();
+            assertEquals(spans.get(0).get("parentId"), 
spans.get(1).get("spanId"));
+            assertEquals(spans.get(0).get("camel.uri"), "seda://next");
+            assertEquals(spans.get(0).get("kind"), "INTERNAL");
+
+            assertEquals(spans.get(1).get("parentId"), 
spans.get(2).get("spanId"));
+            assertEquals(spans.get(1).get("camel.uri"), "seda://next");
+            assertEquals(spans.get(1).get("kind"), "CLIENT");
+
+            assertEquals(spans.get(2).get("parentId"), 
spans.get(3).get("spanId"));
+            assertEquals(spans.get(2).get("camel.uri"), "direct://start");
+            assertEquals(spans.get(2).get("kind"), "INTERNAL");
+
+            assertEquals(spans.get(3).get("parentId"), 
spans.get(4).get("spanId"));
+            assertEquals(spans.get(3).get("camel.uri"), "direct://start");
+            assertEquals(spans.get(3).get("kind"), "CLIENT");
+
+            assertEquals(spans.get(4).get("parentId"), "0000000000000000");
+            assertEquals(spans.get(4).get("code.function"), "trace");
+            assertEquals(spans.get(4).get("url.path"), 
"/observability-services/trace");
+        } finally {
+            RestAssured.given()
+                    .post("/spans/reset")
+                    .then()
+                    .statusCode(204);
+        }
+    }
+
+    @Test
+    void resolveMBeanAttribute() {
+        String name = "org.apache.camel:type=context,*";
+        RestAssured.given()
+                .queryParam("name", name)
+                .queryParam("attribute", "CamelId")
+                .get("/observability-services/jmx/attribute")
+                .then()
+                .statusCode(200)
+                .body(is("observability-services-context"));
+    }
+
+    static List<Map<String, String>> getSpans() {
+        return RestAssured.given()
+                .get("/spans/export")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .jsonPath()
+                .get();
+    }
+}

Reply via email to