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 1e88905c65 Expand micrometer test coverage #4582 1e88905c65 is described below commit 1e88905c6574b8994c802c048fceafee768ff1d6 Author: JiriOndrusek <ondrusek.j...@gmail.com> AuthorDate: Thu Jun 1 14:39:46 2023 +0200 Expand micrometer test coverage #4582 --- .../pages/reference/extensions/micrometer.adoc | 43 +++------ .../runtime/src/main/doc/limitations.adoc | 8 ++ .../micrometer/runtime/src/main/doc/usage.adoc | 44 ++------- integration-tests/micrometer/pom.xml | 5 +- .../{TestMetric.java => MicrometerProducers.java} | 43 +++++---- .../micrometer/it/MicrometerResource.java | 91 ++++++++++++++++-- .../component/micrometer/it/TestMetric.java | 20 ---- .../src/main/resources/application.properties | 2 + .../micrometer/it/AbstractMicrometerTest.java | 62 ++++++++++++ .../component/micrometer/it/MicrometerTest.java | 107 +++++++++++++++------ .../it/NoInstrumentedThreadPoolMicrometerTest.java | 38 ++++++++ .../it/NoInstrumentedThreadPoolProfile.java | 29 ++++++ pom.xml | 1 + poms/bom-test/pom.xml | 5 + 14 files changed, 354 insertions(+), 144 deletions(-) diff --git a/docs/modules/ROOT/pages/reference/extensions/micrometer.adoc b/docs/modules/ROOT/pages/reference/extensions/micrometer.adoc index a66cb0aa76..830a2c9648 100644 --- a/docs/modules/ROOT/pages/reference/extensions/micrometer.adoc +++ b/docs/modules/ROOT/pages/reference/extensions/micrometer.adoc @@ -48,41 +48,30 @@ endif::[] == Usage This extension leverages https://quarkus.io/guides/micrometer[Quarkus Micrometer]. Quarkus supports a variety of Micrometer metric registry implementations. -Your application should declare one of the following dependencies, depending on the monitoring solution you want to work with. +Your application should declare the following dependency or one of the dependencies listed in the https://quarkiverse.github.io/quarkiverse-docs/quarkus-micrometer-registry/dev/index.html[quarkiverse documentation], depending on the monitoring solution you want to work with. -[cols="50,.^50] -|=== -|Monitoring System | Dependency - -| Azure - -| `io.micrometer:micrometer-registry-azure-monitor` - -| Datadog - -| `io.micrometer:micrometer-registry-datadog` - -| JMX (JVM mode only) - -| `io.micrometer:micrometer-registry-jmx` - -| Prometheus - -| `io.micrometer:micrometer-registry-prometheus` +[source,xml] +---- +<dependency> + <groupId>io.micrometer</groupId> + <artifactId>micrometer-registry-prometheus</artifactId> +</dependency> +---- -| SignalFx -| `io.micrometer:micrometer-registry-signalfx` +[id="extensions-micrometer-camel-quarkus-limitations"] +== Camel Quarkus limitations -| Stackdriver +[id="extensions-micrometer-limitations-exposing-micrometer-statisctics-in-jmx"] +=== Exposing Micrometer statisctics in JMX -| `io.micrometer:micrometer-registry-stackdriver` +The `Exposing Micrometer statisctics in JMX` action is not available in native mode as JMX is not supported on GraalVM. -| StatsD +[id="extensions-micrometer-limitations-decrement-header-for-counter-is-ignored-by-prometheus"] +=== Decrement header for Counter is ignored by Prometheus -| `io.micrometer:micrometer-registry-statsd` +Prometheus backend ignores negative values during increment of Counter metrics. -|=== [id="extensions-micrometer-additional-camel-quarkus-configuration"] diff --git a/extensions/micrometer/runtime/src/main/doc/limitations.adoc b/extensions/micrometer/runtime/src/main/doc/limitations.adoc new file mode 100644 index 0000000000..0b019beb5b --- /dev/null +++ b/extensions/micrometer/runtime/src/main/doc/limitations.adoc @@ -0,0 +1,8 @@ +=== Exposing Micrometer statisctics in JMX + +The `Exposing Micrometer statisctics in JMX` action is not available in native mode as JMX is not supported on GraalVM. + +=== Decrement header for Counter is ignored by Prometheus + +Prometheus backend ignores negative values during increment of Counter metrics. + diff --git a/extensions/micrometer/runtime/src/main/doc/usage.adoc b/extensions/micrometer/runtime/src/main/doc/usage.adoc index 9b35670216..7170250acd 100644 --- a/extensions/micrometer/runtime/src/main/doc/usage.adoc +++ b/extensions/micrometer/runtime/src/main/doc/usage.adoc @@ -1,37 +1,11 @@ This extension leverages https://quarkus.io/guides/micrometer[Quarkus Micrometer]. Quarkus supports a variety of Micrometer metric registry implementations. -Your application should declare one of the following dependencies, depending on the monitoring solution you want to work with. - -[cols="50,.^50] -|=== -|Monitoring System | Dependency - -| Azure - -| `io.micrometer:micrometer-registry-azure-monitor` - -| Datadog - -| `io.micrometer:micrometer-registry-datadog` - -| JMX (JVM mode only) - -| `io.micrometer:micrometer-registry-jmx` - -| Prometheus - -| `io.micrometer:micrometer-registry-prometheus` - -| SignalFx - -| `io.micrometer:micrometer-registry-signalfx` - -| Stackdriver - -| `io.micrometer:micrometer-registry-stackdriver` - -| StatsD - -| `io.micrometer:micrometer-registry-statsd` - -|=== +Your application should declare the following dependency or one of the dependencies listed in the https://quarkiverse.github.io/quarkiverse-docs/quarkus-micrometer-registry/dev/index.html[quarkiverse documentation], depending on the monitoring solution you want to work with. + +[source,xml] +---- +<dependency> + <groupId>io.micrometer</groupId> + <artifactId>micrometer-registry-prometheus</artifactId> +</dependency> +---- diff --git a/integration-tests/micrometer/pom.xml b/integration-tests/micrometer/pom.xml index 9650a41867..fb156d5de7 100644 --- a/integration-tests/micrometer/pom.xml +++ b/integration-tests/micrometer/pom.xml @@ -63,7 +63,10 @@ <groupId>io.quarkus</groupId> <artifactId>quarkus-resteasy-jsonb</artifactId> </dependency> - + <dependency> + <groupId>io.quarkiverse.micrometer.registry</groupId> + <artifactId>quarkus-micrometer-registry-jmx</artifactId> + </dependency> <!-- test dependencies --> <dependency> <groupId>io.quarkus</groupId> diff --git a/integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/TestMetric.java b/integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerProducers.java similarity index 60% copy from integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/TestMetric.java copy to integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerProducers.java index 749da892ec..f677005b44 100644 --- a/integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/TestMetric.java +++ b/integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerProducers.java @@ -16,33 +16,35 @@ */ package org.apache.camel.quarkus.component.micrometer.it; -import io.micrometer.core.annotation.Counted; -import io.micrometer.core.annotation.Timed; +import java.util.Arrays; + +import io.micrometer.core.instrument.Clock; import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; import io.micrometer.core.instrument.config.MeterFilter; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; -import jakarta.inject.Named; +import io.micrometer.core.instrument.util.HierarchicalNameMapper; +import io.micrometer.jmx.JmxMeterRegistry; +import io.micrometer.prometheus.PrometheusMeterRegistry; +import io.quarkus.micrometer.runtime.MeterFilterConstraint; import jakarta.inject.Singleton; +import jakarta.ws.rs.Produces; +import org.apache.camel.component.micrometer.CamelJmxConfig; -@ApplicationScoped -@Named("testMetric") -public class TestMetric { +public class MicrometerProducers { - @Counted(value = "TestMetric.counted1") - @Timed(value = "TestMetric.timed1") - public void call1() { - try { - //wait 1 second - Thread.sleep(1000); - } catch (InterruptedException e) { - //do nothing - } + @Produces + @Singleton + public MeterRegistry registry(Clock clock) { + return new JmxMeterRegistry(CamelJmxConfig.DEFAULT, Clock.SYSTEM, HierarchicalNameMapper.DEFAULT); } - @Counted(value = "TestMetric_wrong.counted2") - public void call2() { - //do nothing + @Produces + @Singleton + @MeterFilterConstraint(applyTo = PrometheusMeterRegistry.class) + public MeterFilter configurePrometheusRegistries() { + return MeterFilter.commonTags(Arrays.asList( + Tag.of("customTag", "prometheus"))); } @Produces @@ -61,4 +63,5 @@ public class TestMetric { } }; } + } diff --git a/integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerResource.java b/integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerResource.java index d77c7bf321..969ad98f8b 100644 --- a/integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerResource.java +++ b/integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerResource.java @@ -17,12 +17,17 @@ package org.apache.camel.quarkus.component.micrometer.it; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; +import java.util.NoSuchElementException; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.Tags; import io.micrometer.core.instrument.search.Search; +import io.micrometer.prometheus.PrometheusMeterRegistry; import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; @@ -31,7 +36,14 @@ 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.CamelContext; import org.apache.camel.ProducerTemplate; +import org.apache.camel.component.micrometer.MicrometerConstants; +import org.apache.camel.component.micrometer.eventnotifier.MicrometerEventNotifierService; +import org.apache.camel.component.micrometer.spi.InstrumentedThreadPoolFactory; +import org.apache.camel.impl.engine.DefaultExecutorServiceManager; +import org.apache.camel.spi.ThreadPoolFactory; +import org.apache.camel.support.DefaultThreadPoolFactory; @Path("/micrometer") public class MicrometerResource { @@ -43,7 +55,17 @@ public class MicrometerResource { MeterRegistry meterRegistry; @Inject - TestMetric counter; + PrometheusMeterRegistry prometheusMeterRegistry; + + @Inject + CamelContext camelContext; + + private LinkedList<Integer> list = new LinkedList<>(); + + public MicrometerResource(MeterRegistry meterRegistry) { + this.meterRegistry = meterRegistry; + meterRegistry.gaugeCollectionSize("example.list.size", Tags.empty(), list); + } @Path("/metric/{type}/{name}") @Produces(MediaType.APPLICATION_JSON) @@ -51,7 +73,6 @@ public class MicrometerResource { public Response getMetricValue(@PathParam("type") String type, @PathParam("name") String name, @QueryParam("tags") String tagValues) { List<Tag> tags = new ArrayList<>(); - if (tagValues.length() > 0) { String[] tagElements = tagValues.split(","); for (String element : tagElements) { @@ -59,12 +80,11 @@ public class MicrometerResource { tags.add(Tag.of(tagParts[0], tagParts[1])); } } - - Search search = meterRegistry.find(name).tags(tags); + //search only in prometheus registry (not in jmx one), counter test covers among others the unexpected behavior of prometheus + Search search = prometheusMeterRegistry.find(name).tags(tags); if (search == null) { return Response.status(404).build(); } - try { Response.ResponseBuilder response = Response.ok(); if (type.equals("counter")) { @@ -78,7 +98,6 @@ public class MicrometerResource { } else { throw new IllegalArgumentException("Unknown metric type: " + type); } - return response.build(); } catch (NullPointerException e) { //metric does not exist @@ -86,10 +105,25 @@ public class MicrometerResource { } } - @Path("/counter") + /** + * If inc is > 0, MicrometerConstants.HEADER_COUNTER_INCREMENT is used + * If inc is < 0, MicrometerConstants.HEADER_COUNTER_DECREMENT is used (with positive value) + * If inc == 0, no header is added. + */ + @Path("/counter/{inc}") @GET - public Response counter() { - producerTemplate.sendBody("direct:counter", null); + public Response counter(@PathParam("inc") int increment) { + if (increment > 0) { + producerTemplate.sendBodyAndHeader("direct:counter", null, MicrometerConstants.HEADER_COUNTER_INCREMENT, increment); + } else if (increment < 0) { + producerTemplate.sendBodyAndHeader("direct:counter", null, MicrometerConstants.HEADER_COUNTER_DECREMENT, + 0 - increment); + List l = meterRegistry.getMeters().stream().filter(m -> m.getId().getName().contains("executor")) + .collect(Collectors.toList());//forEach(System.out::println); + System.out.println(l); + } else { + producerTemplate.sendBody("direct:counter", null); + } return Response.ok().build(); } @@ -114,10 +148,49 @@ public class MicrometerResource { return Response.ok().build(); } + @Path("/setInstrumentedThreadPoolFactory") + @GET + public Response setInstrumentedThreadPoolFactory() { + ThreadPoolFactory threadPoolFactory = new DefaultThreadPoolFactory(); + InstrumentedThreadPoolFactory instrumentedThreadPoolFactory = new InstrumentedThreadPoolFactory(meterRegistry, + threadPoolFactory); + + DefaultExecutorServiceManager executorServiceManager = new DefaultExecutorServiceManager(camelContext); + executorServiceManager.setThreadPoolFactory(instrumentedThreadPoolFactory); + camelContext.setExecutorServiceManager(executorServiceManager); + + return Response.ok().build(); + } + + @Path("/statistics") + @GET + public Response statistics() { + MicrometerEventNotifierService service = camelContext.hasService(MicrometerEventNotifierService.class); + String json = service.dumpStatisticsAsJson(); + return Response.ok().entity(json).build(); + } + @Path("/annotations/call/{number}") @GET public Response annotationsCall(@PathParam("number") int number) { producerTemplate.requestBodyAndHeader("direct:annotatedBean", (Object) null, "number", number); return Response.ok().build(); } + + @Path("/gauge/{number}") + @GET + public Response gauge(@PathParam("number") int number) { + if (number == 2 || number % 2 == 0) { + // add even numbers to the list + list.add(number); + } else { + // remove items from the list for odd numbers + try { + number = list.removeFirst(); + } catch (NoSuchElementException nse) { + number = 0; + } + } + return Response.ok().build(); + } } diff --git a/integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/TestMetric.java b/integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/TestMetric.java index 749da892ec..1b1f35777f 100644 --- a/integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/TestMetric.java +++ b/integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/TestMetric.java @@ -18,12 +18,8 @@ package org.apache.camel.quarkus.component.micrometer.it; import io.micrometer.core.annotation.Counted; import io.micrometer.core.annotation.Timed; -import io.micrometer.core.instrument.Meter; -import io.micrometer.core.instrument.config.MeterFilter; import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; import jakarta.inject.Named; -import jakarta.inject.Singleton; @ApplicationScoped @Named("testMetric") @@ -45,20 +41,4 @@ public class TestMetric { //do nothing } - @Produces - @Singleton - public MeterFilter renameApplicationMeters() { - final String targetMetric = "TestMetric_wrong.counted2"; - - return new MeterFilter() { - @Override - public Meter.Id map(Meter.Id id) { - if (id.getName().equals(targetMetric)) { - // rename the metric - return id.withName("TestMetric.counted2"); - } - return id; - } - }; - } } diff --git a/integration-tests/micrometer/src/main/resources/application.properties b/integration-tests/micrometer/src/main/resources/application.properties index 88616a5c2a..38a64cd146 100644 --- a/integration-tests/micrometer/src/main/resources/application.properties +++ b/integration-tests/micrometer/src/main/resources/application.properties @@ -18,3 +18,5 @@ camel.context.name = quarkus-camel-micrometer quarkus.camel.metrics.enable-message-history = true + +quarkus.camel.metrics.enable-instrumented-thread-pool-factory = true \ No newline at end of file diff --git a/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/AbstractMicrometerTest.java b/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/AbstractMicrometerTest.java new file mode 100644 index 0000000000..84606884e0 --- /dev/null +++ b/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/AbstractMicrometerTest.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.micrometer.it; + +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +import io.restassured.response.ResponseBodyExtractionOptions; + +@QuarkusTest +abstract class AbstractMicrometerTest { + + <T> T getMetricValue(Class<T> as, String type, String name) { + return getMetricValue(as, type, name, null); + } + + <T> T getMetricValue(Class<T> as, String type, String name, String tags) { + return getMetricValue(as, type, name, tags, 200); + } + + <T> T getMetricValue(Class<T> as, String type, String name, String tags, int statusCode) { + ResponseBodyExtractionOptions resp = RestAssured.given() + .queryParam("tags", tags) + .when() + .get("/micrometer/metric/" + type + "/" + name) + .then() + .statusCode(statusCode) + .extract() + .body(); + + if (as.equals(String.class)) { + return (T) resp.asString(); + } + + return resp.as(as); + } + + /** + * Debug available metrics + */ + String dumpMetrics() { + return RestAssured.get("/q/metrics") + .then() + .statusCode(200) + .extract() + .body() + .asString(); + } +} diff --git a/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerTest.java b/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerTest.java index 8501ca7e06..36b4b832bf 100644 --- a/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerTest.java +++ b/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerTest.java @@ -16,23 +16,47 @@ */ package org.apache.camel.quarkus.component.micrometer.it; +import java.lang.management.ManagementFactory; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.management.Attribute; +import javax.management.MBeanServer; +import javax.management.ObjectInstance; +import javax.management.ObjectName; + +import io.quarkus.test.junit.DisabledOnIntegrationTest; import io.quarkus.test.junit.QuarkusTest; import io.restassured.RestAssured; -import io.restassured.response.ResponseBodyExtractionOptions; +import io.restassured.path.json.JsonPath; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @QuarkusTest -class MicrometerTest { +class MicrometerTest extends AbstractMicrometerTest { @Test - public void testMicrometerMetricsCounter() { - RestAssured.get("/micrometer/counter") + public void testMicrometerMetricsCounter() throws Exception { + RestAssured.get("/micrometer/counter/0") .then() .statusCode(200); - assertEquals(1, getMetricValue(Integer.class, "counter", "camel-quarkus-counter")); + assertEquals(1, getMetricValue(Integer.class, "counter", "camel-quarkus-counter", "customTag=prometheus")); + + RestAssured.get("/micrometer/counter/5") + .then() + .statusCode(200); + assertEquals(6, getMetricValue(Integer.class, "counter", "camel-quarkus-counter")); + + //prometheus metrics ignores decrements + RestAssured.get("/micrometer/counter/-3") + .then() + .statusCode(200); + assertEquals(6, getMetricValue(Integer.class, "counter", "camel-quarkus-counter")); } @Test @@ -108,40 +132,59 @@ class MicrometerTest { assertEquals(1, getMetricValue(Double.class, "counter", "TestMetric.counted2", "")); } - private <T> T getMetricValue(Class<T> as, String type, String name) { - return getMetricValue(as, type, name, null); + @Test + public void testInstrumentedThreadPoolFactory() { + assertNotNull(getMetricValue(Double.class, "timer", "executor")); } - private <T> T getMetricValue(Class<T> as, String type, String name, String tags) { - return getMetricValue(as, type, name, tags, 200); + @Test + public void testGauge() { + RestAssured.get("/micrometer/gauge/1").then().statusCode(200); + RestAssured.get("/micrometer/gauge/2").then().statusCode(200); + RestAssured.get("/micrometer/gauge/4").then().statusCode(200); + assertEquals(2.0, getMetricValue(Double.class, "gauge", "example.list.size")); + RestAssured.get("/micrometer/gauge/6").then().statusCode(200); + RestAssured.get("/micrometer/gauge/5").then().statusCode(200); + RestAssured.get("/micrometer/gauge/7").then().statusCode(200); + assertEquals(1.0, getMetricValue(Double.class, "gauge", "example.list.size")); } - private <T> T getMetricValue(Class<T> as, String type, String name, String tags, int statusCode) { - ResponseBodyExtractionOptions resp = RestAssured.given() - .queryParam("tags", tags) - .when() - .get("/micrometer/metric/" + type + "/" + name) + @Test + public void testDumpAsJson() { + JsonPath jsonPath = RestAssured.get("/micrometer/statistics") .then() - .statusCode(statusCode) - .extract() - .body(); + .statusCode(200) + .extract().jsonPath(); + + //extract required values + Map result = jsonPath.getList("gauges").stream() + .map(o -> (Map) o) + .filter(o -> ((Map) o.get("id")).get("name").toString().contains(".routes.")) + //filter only values with tag: customTag=prometheus + .filter(o -> ((List) ((Map) o.get("id")).get("tags")).stream() + .anyMatch(item -> ((Map) item).containsKey("customTag"))) + .collect(Collectors.toMap(o -> ((Map) o.get("id")).get("name"), o -> o.get("value").toString())); + + assertEquals(result.size(), 2); + assertTrue(result.containsKey("camel.routes.running")); + assertEquals(result.get("camel.routes.running"), "5.0"); + assertTrue(result.containsKey("camel.routes.added")); + assertEquals(result.get("camel.routes.added"), "5.0"); + } + + @Test + @DisabledOnIntegrationTest // JMX is not supported in native mode + public void testJMX() throws Exception { + MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); - if (as.equals(String.class)) { - return (T) resp.asString(); - } + ObjectName objectName = new ObjectName("org.apache.camel.micrometer:name=jvmClassesLoaded"); + Set<ObjectInstance> mbeans = mBeanServer.queryMBeans(objectName, null); - return resp.as(as); - } + assertEquals(1, mbeans.size()); - /** - * Debug available metrics - */ - private String dumpMetrics() { - return RestAssured.get("/metrics") - .then() - .statusCode(200) - .extract() - .body() - .asString(); + ObjectInstance oi = mbeans.iterator().next(); + Double classes = (Double) ((Attribute) mBeanServer.getAttributes(oi.getObjectName(), new String[] { "Value" }).get(0)) + .getValue(); + assertTrue(classes > 1); } } diff --git a/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/NoInstrumentedThreadPoolMicrometerTest.java b/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/NoInstrumentedThreadPoolMicrometerTest.java new file mode 100644 index 0000000000..071ad5e803 --- /dev/null +++ b/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/NoInstrumentedThreadPoolMicrometerTest.java @@ -0,0 +1,38 @@ +/* + * 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.micrometer.it; + +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Test class runs only in JVM mode, because profile changes some application.properties which is not allowed in native. + * (native Exception: "java.lang.IllegalStateException: Build time property cannot be changed at runtime:") + * Test verify that instrumented thread pool metric is not present, if the feature is turned off. + */ +@QuarkusTest +@TestProfile(NoInstrumentedThreadPoolProfile.class) +class NoInstrumentedThreadPoolMicrometerTest extends AbstractMicrometerTest { + + @Test + public void testInstrumentedThreadPoolFactory() { + assertEquals("Metric does not exist", getMetricValue(String.class, "timer", "executor", null, 500)); + } +} diff --git a/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/NoInstrumentedThreadPoolProfile.java b/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/NoInstrumentedThreadPoolProfile.java new file mode 100644 index 0000000000..38cc2d8d30 --- /dev/null +++ b/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/NoInstrumentedThreadPoolProfile.java @@ -0,0 +1,29 @@ +/* + * 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.micrometer.it; + +import java.util.Map; + +import io.quarkus.test.junit.QuarkusTestProfile; + +public class NoInstrumentedThreadPoolProfile implements QuarkusTestProfile { + + @Override + public Map<String, String> getConfigOverrides() { + return Map.of("quarkus.camel.metrics.enable-instrumented-thread-pool-factory", "false"); + } +} diff --git a/pom.xml b/pom.xml index 16718ba3c0..44061c8eb6 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,7 @@ <quarkiverse-jackson-jq.version>2.0.1</quarkiverse-jackson-jq.version><!-- https://repo1.maven.org/maven2/io/quarkiverse/jackson-jq/quarkus-jackson-jq-parent/ --> <quarkiverse-jgit.version>3.0.0</quarkiverse-jgit.version><!-- https://repo1.maven.org/maven2/io/quarkiverse/jgit/quarkus-jgit-parent/ --> <quarkiverse-jsch.version>3.0.1</quarkiverse-jsch.version><!-- https://repo1.maven.org/maven2/io/quarkiverse/jsch/quarkus-jsch-parent/ --> + <quarkiverse-micrometer.version>0.2.0</quarkiverse-micrometer.version><!-- https://repo1.maven.org/maven2/io/quarkiverse/micrometer/registry/quarkiverse-micrometer-registry-parent/ --> <quarkiverse-minio.version>3.1.0.Final</quarkiverse-minio.version><!-- https://repo1.maven.org/maven2/io/quarkiverse/minio/quarkus-minio-parent/ --> <quarkiverse-mybatis.version>2.0.0</quarkiverse-mybatis.version><!-- https://repo1.maven.org/maven2/io/quarkiverse/mybatis/quarkus-mybatis-parent/ --> <quarkiverse-pooled-jms.version>2.0.1</quarkiverse-pooled-jms.version><!-- https://repo1.maven.org/maven2/io/quarkiverse/messaginghub/quarkus-pooled-jms-parent/ --> diff --git a/poms/bom-test/pom.xml b/poms/bom-test/pom.xml index ace0ec0356..99c5cb73a4 100644 --- a/poms/bom-test/pom.xml +++ b/poms/bom-test/pom.xml @@ -72,6 +72,11 @@ <scope>import</scope> </dependency> + <dependency> + <groupId>io.quarkiverse.micrometer.registry</groupId> + <artifactId>quarkus-micrometer-registry-jmx</artifactId> + <version>${quarkiverse-micrometer.version}</version> + </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-integration-test-support-custom-dataformat</artifactId>