Skip to content

Commit

Permalink
Migrate tests to micrometer metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
vkn committed Dec 11, 2024
1 parent 304406f commit dc0689b
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 74 deletions.
7 changes: 6 additions & 1 deletion extensions/mongodb-client/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,12 @@
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-metrics-deployment</artifactId>
<artifactId>quarkus-micrometer-deployment</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-micrometer-registry-prometheus-deployment</artifactId>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -134,7 +135,7 @@ AdditionalIndexedClassesBuildItem includeMongoCommandMetricListener(
boolean withMicrometer = metricsCapability.map(cap -> cap.metricsSupported(MetricsFactory.MICROMETER))
.orElse(false);
if (withMicrometer) {
return new AdditionalIndexedClassesBuildItem(MongoClientRecorder.getMicrometerCommandListenerClassName());
return new AdditionalIndexedClassesBuildItem(MicrometerCommandListener.class.getName());
}
return new AdditionalIndexedClassesBuildItem();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
};
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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"),
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package io.quarkus.mongodb.deployment;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.Optional;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

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();

@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<MetricsCapabilityBuildItem> capability = capability(metricsEnabled, micrometerSupported);

AdditionalIndexedClassesBuildItem result = buildStep.includeMongoCommandMetricListener(config, capability);

if (expectedResult) {
assertThat(result.getClassesToIndex())
.containsExactly("io.quarkus.mongodb.metrics.MicrometerCommandListener");
} else {
assertThat(result.getClassesToIndex()).isEmpty();
}
}

private static Optional<MetricsCapabilityBuildItem> 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;
}

}
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
package io.quarkus.mongodb.runtime;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;

import jakarta.enterprise.inject.Default;
import jakarta.enterprise.inject.literal.NamedLiteral;
import jakarta.enterprise.util.AnnotationLiteral;

import com.mongodb.ConnectionString;
import com.mongodb.client.MongoClient;
import com.mongodb.event.ConnectionPoolListener;

import io.quarkus.arc.Arc;
import io.quarkus.mongodb.metrics.MicrometerCommandListener;
import io.quarkus.mongodb.metrics.MicrometerConnectionPoolListener;
import io.quarkus.mongodb.metrics.MongoMetricsConnectionPoolListener;
import io.quarkus.mongodb.reactive.ReactiveMongoClient;
import io.quarkus.mongodb.runtime.dns.MongoDnsClientProvider;
import io.quarkus.runtime.RuntimeValue;
import io.quarkus.runtime.annotations.Recorder;
import io.vertx.core.Vertx;
import jakarta.enterprise.inject.Default;
import jakarta.enterprise.inject.literal.NamedLiteral;
import jakarta.enterprise.util.AnnotationLiteral;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;

@Recorder
public class MongoClientRecorder {
Expand Down Expand Up @@ -100,10 +97,6 @@ public ConnectionPoolListener get() {
};
}

public static String getMicrometerCommandListenerClassName() {
return MicrometerCommandListener.class.getName();
}

public Supplier<ConnectionPoolListener> createMPMetricsConnectionPoolListener() {
return new Supplier<ConnectionPoolListener>() {
@Override
Expand Down

0 comments on commit dc0689b

Please sign in to comment.