diff --git a/extensions/mongodb-client/deployment/pom.xml b/extensions/mongodb-client/deployment/pom.xml
index 8bd99d1840900..36b104c57bf4b 100644
--- a/extensions/mongodb-client/deployment/pom.xml
+++ b/extensions/mongodb-client/deployment/pom.xml
@@ -63,7 +63,12 @@
io.quarkus
- quarkus-smallrye-metrics-deployment
+ quarkus-micrometer-deployment
+ true
+
+
+ io.quarkus
+ quarkus-micrometer-registry-prometheus-deployment
test
@@ -86,6 +91,11 @@
awaitility
test
+
+ org.mockito
+ mockito-core
+ test
+
org.assertj
assertj-core
diff --git a/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoClientProcessor.java b/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoClientProcessor.java
index 6413be3720314..68003f57ea613 100644
--- a/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoClientProcessor.java
+++ b/extensions/mongodb-client/deployment/src/main/java/io/quarkus/mongodb/deployment/MongoClientProcessor.java
@@ -64,6 +64,7 @@
import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
import io.quarkus.deployment.metrics.MetricsCapabilityBuildItem;
import io.quarkus.mongodb.MongoClientName;
+import io.quarkus.mongodb.metrics.MicrometerCommandListener;
import io.quarkus.mongodb.reactive.ReactiveMongoClient;
import io.quarkus.mongodb.runtime.MongoClientBeanUtil;
import io.quarkus.mongodb.runtime.MongoClientCustomizer;
@@ -124,6 +125,21 @@ AdditionalIndexedClassesBuildItem includeMongoCommandListener(MongoClientBuildTi
return new AdditionalIndexedClassesBuildItem();
}
+ @BuildStep
+ void includeMongoCommandMetricListener(
+ BuildProducer additionalIndexedClasses,
+ MongoClientBuildTimeConfig buildTimeConfig,
+ Optional metricsCapability) {
+ if (!buildTimeConfig.metricsEnabled) {
+ return;
+ }
+ boolean withMicrometer = metricsCapability.map(cap -> cap.metricsSupported(MetricsFactory.MICROMETER))
+ .orElse(false);
+ if (withMicrometer) {
+ additionalIndexedClasses.produce(new AdditionalIndexedClassesBuildItem(MicrometerCommandListener.class.getName()));
+ }
+ }
+
@BuildStep
public void registerDnsProvider(BuildProducer nativeProducer) {
nativeProducer.produce(new NativeImageResourceBuildItem("META-INF/services/" + DnsClientProvider.class.getName()));
diff --git a/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/MongoLazyTest.java b/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/MongoLazyTest.java
index c8c1d01716668..10c1cae82bf3a 100644
--- a/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/MongoLazyTest.java
+++ b/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/MongoLazyTest.java
@@ -4,58 +4,47 @@
import jakarta.inject.Inject;
-import org.eclipse.microprofile.metrics.Metric;
-import org.eclipse.microprofile.metrics.MetricID;
-import org.eclipse.microprofile.metrics.MetricRegistry;
-import org.eclipse.microprofile.metrics.Tag;
-import org.eclipse.microprofile.metrics.annotation.RegistryType;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import com.mongodb.client.MongoClient;
+import io.micrometer.core.instrument.Meter;
+import io.micrometer.core.instrument.MeterRegistry;
import io.quarkus.arc.Arc;
-import io.quarkus.mongodb.metrics.ConnectionPoolGauge;
import io.quarkus.mongodb.reactive.ReactiveMongoClient;
import io.quarkus.test.QuarkusUnitTest;
/** Variation of {@link io.quarkus.mongodb.MongoMetricsTest} to verify lazy client initialization. */
-public class MongoLazyTest extends MongoTestBase {
+class MongoLazyTest extends MongoTestBase {
@Inject
- @RegistryType(type = MetricRegistry.Type.VENDOR)
- MetricRegistry registry;
+ MeterRegistry meterRegistry;
@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
- .withApplicationRoot((jar) -> jar.addClasses(MongoTestBase.class))
+ .withApplicationRoot(jar -> jar.addClasses(MongoTestBase.class))
.withConfigurationResource("application-metrics-mongo.properties");
@Test
void testLazyClientCreation() {
// Clients are created lazily, this metric should not be present yet
- assertThat(getGaugeValueOrNull("mongodb.connection-pool.size", getTags())).isNull();
- assertThat(getGaugeValueOrNull("mongodb.connection-pool.checked-out-count", getTags())).isNull();
+ assertThat(getMetric("mongodb.driver.pool.size")).isNull();
+ assertThat(getMetric("mongodb.driver.pool.checkedout")).isNull();
+ assertThat(getMetric("mongodb.driver.commands")).isNull();
// doing this here instead of in another method in order to avoid messing with the initialization stats
assertThat(Arc.container().instance(MongoClient.class).get()).isNull();
assertThat(Arc.container().instance(ReactiveMongoClient.class).get()).isNull();
}
- private Long getGaugeValueOrNull(String metricName, Tag[] tags) {
- MetricID metricID = new MetricID(metricName, tags);
- Metric metric = registry.getMetrics().get(metricID);
-
- if (metric == null) {
- return null;
- }
- return ((ConnectionPoolGauge) metric).getValue();
+ private Double getMetric(String name) {
+ Meter metric = meterRegistry.getMeters()
+ .stream()
+ .filter(mtr -> mtr.getId().getName().contains(name))
+ .findFirst()
+ .orElse(null);
+ return metric == null ? null : metric.measure().iterator().next().getValue();
}
- private Tag[] getTags() {
- return new Tag[] {
- new Tag("host", "127.0.0.1"),
- new Tag("port", "27018"),
- };
- }
}
diff --git a/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/MongoMetricsTest.java b/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/MongoMetricsTest.java
index dab2253817afe..cc54cb1b61d8a 100644
--- a/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/MongoMetricsTest.java
+++ b/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/MongoMetricsTest.java
@@ -1,38 +1,32 @@
package io.quarkus.mongodb;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertEquals;
import jakarta.inject.Inject;
-import org.eclipse.microprofile.metrics.Metric;
-import org.eclipse.microprofile.metrics.MetricID;
-import org.eclipse.microprofile.metrics.MetricRegistry;
-import org.eclipse.microprofile.metrics.Tag;
-import org.eclipse.microprofile.metrics.annotation.RegistryType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import com.mongodb.client.MongoClient;
+import io.micrometer.core.instrument.Meter;
+import io.micrometer.core.instrument.MeterRegistry;
import io.quarkus.arc.Arc;
-import io.quarkus.mongodb.metrics.ConnectionPoolGauge;
import io.quarkus.mongodb.reactive.ReactiveMongoClient;
import io.quarkus.test.QuarkusUnitTest;
-public class MongoMetricsTest extends MongoTestBase {
+class MongoMetricsTest extends MongoTestBase {
@Inject
MongoClient client;
@Inject
- @RegistryType(type = MetricRegistry.Type.VENDOR)
- MetricRegistry registry;
+ MeterRegistry meterRegistry;
@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
- .withApplicationRoot((jar) -> jar.addClasses(MongoTestBase.class))
+ .withApplicationRoot(jar -> jar.addClasses(MongoTestBase.class))
.withConfigurationResource("application-metrics-mongo.properties");
@AfterEach
@@ -45,38 +39,32 @@ void cleanup() {
@Test
void testMetricsInitialization() {
// Clients are created lazily, this metric should not be present yet
- assertThat(getGaugeValueOrNull("mongodb.connection-pool.size", getTags())).isNull();
- assertThat(getGaugeValueOrNull("mongodb.connection-pool.checked-out-count", getTags())).isNull();
+ assertThat(getMetric("mongodb.driver.pool.size")).isNull();
+ assertThat(getMetric("mongodb.driver.pool.checkedout")).isNull();
// Just need to execute something so that a connection is opened
String name = client.listDatabaseNames().first();
- assertEquals(1L, getGaugeValueOrNull("mongodb.connection-pool.size", getTags()));
- assertEquals(0L, getGaugeValueOrNull("mongodb.connection-pool.checked-out-count", getTags()));
+ assertThat(getMetric("mongodb.driver.pool.size")).isOne();
+ assertThat(getMetric("mongodb.driver.commands")).isOne();
+ assertThat(getMetric("mongodb.driver.pool.checkedout")).isZero();
client.close();
- assertEquals(0L, getGaugeValueOrNull("mongodb.connection-pool.size", getTags()));
- assertEquals(0L, getGaugeValueOrNull("mongodb.connection-pool.checked-out-count", getTags()));
+ assertThat(getMetric("mongodb.driver.pool.size")).isNull();
+ assertThat(getMetric("mongodb.driver.pool.checkedout")).isNull();
// doing this here instead of in another method in order to avoid messing with the initialization stats
assertThat(Arc.container().instance(MongoClient.class).get()).isNotNull();
assertThat(Arc.container().instance(ReactiveMongoClient.class).get()).isNull();
}
- private Long getGaugeValueOrNull(String metricName, Tag[] tags) {
- MetricID metricID = new MetricID(metricName, tags);
- Metric metric = registry.getMetrics().get(metricID);
-
- if (metric == null) {
- return null;
- }
- return ((ConnectionPoolGauge) metric).getValue();
+ private Double getMetric(String metricName) {
+ Meter metric = meterRegistry.getMeters()
+ .stream()
+ .filter(mtr -> mtr.getId().getName().contains(metricName))
+ .findFirst()
+ .orElse(null);
+ return metric == null ? null : metric.measure().iterator().next().getValue();
}
- private Tag[] getTags() {
- return new Tag[] {
- new Tag("host", "127.0.0.1"),
- new Tag("port", "27018"),
- };
- }
}
diff --git a/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/deployment/MongoClientProcessorTest.java b/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/deployment/MongoClientProcessorTest.java
new file mode 100644
index 0000000000000..ad437dc2dc882
--- /dev/null
+++ b/extensions/mongodb-client/deployment/src/test/java/io/quarkus/mongodb/deployment/MongoClientProcessorTest.java
@@ -0,0 +1,59 @@
+package io.quarkus.mongodb.deployment;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+import java.util.Optional;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.mockito.ArgumentCaptor;
+
+import io.quarkus.deployment.annotations.BuildProducer;
+import io.quarkus.deployment.builditem.AdditionalIndexedClassesBuildItem;
+import io.quarkus.deployment.metrics.MetricsCapabilityBuildItem;
+import io.quarkus.runtime.metrics.MetricsFactory;
+
+class MongoClientProcessorTest {
+ private final MongoClientProcessor buildStep = new MongoClientProcessor();
+
+ @SuppressWarnings("unchecked")
+ @ParameterizedTest
+ @CsvSource({
+ "true, true, true", // Metrics enabled and Micrometer supported
+ "true, false, false", // Metrics enabled but Micrometer not supported
+ "false, true, false", // Metrics disabled and Micrometer supported
+ "false, false, false" // Metrics disabled and Micrometer not supported
+ })
+ void testIncludeMongoCommandMetricListener(boolean metricsEnabled, boolean micrometerSupported, boolean expectedResult) {
+ MongoClientBuildTimeConfig config = config(metricsEnabled);
+ Optional capability = capability(metricsEnabled, micrometerSupported);
+
+ BuildProducer buildProducer = mock(BuildProducer.class);
+ buildStep.includeMongoCommandMetricListener(buildProducer, config, capability);
+
+ if (expectedResult) {
+ var captor = ArgumentCaptor.forClass(AdditionalIndexedClassesBuildItem.class);
+ verify(buildProducer, times(1)).produce(captor.capture());
+ assertThat(captor.getAllValues().get(0).getClassesToIndex())
+ .containsExactly("io.quarkus.mongodb.metrics.MicrometerCommandListener");
+ } else {
+ verify(buildProducer, never()).produce(any(AdditionalIndexedClassesBuildItem.class));
+ }
+ }
+
+ private static Optional capability(boolean metricsEnabled, boolean micrometerSupported) {
+ MetricsCapabilityBuildItem capability = metricsEnabled
+ ? new MetricsCapabilityBuildItem(factory -> MetricsFactory.MICROMETER.equals(factory) && micrometerSupported)
+ : null;
+ return Optional.ofNullable(capability);
+ }
+
+ private static MongoClientBuildTimeConfig config(boolean metricsEnabled) {
+ MongoClientBuildTimeConfig buildTimeConfig = new MongoClientBuildTimeConfig();
+ buildTimeConfig.metricsEnabled = metricsEnabled;
+ return buildTimeConfig;
+ }
+
+}
diff --git a/extensions/mongodb-client/runtime/src/main/java/io/quarkus/mongodb/metrics/MicrometerCommandListener.java b/extensions/mongodb-client/runtime/src/main/java/io/quarkus/mongodb/metrics/MicrometerCommandListener.java
new file mode 100644
index 0000000000000..4ee642491a9c7
--- /dev/null
+++ b/extensions/mongodb-client/runtime/src/main/java/io/quarkus/mongodb/metrics/MicrometerCommandListener.java
@@ -0,0 +1,14 @@
+package io.quarkus.mongodb.metrics;
+
+import jakarta.inject.Inject;
+
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.binder.mongodb.MongoMetricsCommandListener;
+
+public class MicrometerCommandListener extends MongoMetricsCommandListener {
+ @Inject
+ public MicrometerCommandListener(MeterRegistry registry) {
+ super(registry);
+ }
+
+}
diff --git a/integration-tests/mongodb-panache/src/test/java/io/quarkus/it/mongodb/panache/MongodbPanacheResourceTest.java b/integration-tests/mongodb-panache/src/test/java/io/quarkus/it/mongodb/panache/MongodbPanacheResourceTest.java
index d07a9733a4744..976dcc1e75243 100644
--- a/integration-tests/mongodb-panache/src/test/java/io/quarkus/it/mongodb/panache/MongodbPanacheResourceTest.java
+++ b/integration-tests/mongodb-panache/src/test/java/io/quarkus/it/mongodb/panache/MongodbPanacheResourceTest.java
@@ -357,6 +357,7 @@ private void callPersonEndpoint(String endpoint) {
.when().get("/q/metrics")
.then()
.statusCode(200)
+ .body(CoreMatchers.containsString("mongodb_driver_commands_seconds_max"))
.body(CoreMatchers.containsString("mongodb_driver_pool_checkedout"))
.body(CoreMatchers.containsString("mongodb_driver_pool_size"))
.body(CoreMatchers.containsString("mongodb_driver_pool_waitqueuesize"));