From ba912bc382d680e1298a4e8452a048effb29d373 Mon Sep 17 00:00:00 2001 From: Ago Allikmaa Date: Mon, 20 Jun 2022 12:21:54 +0100 Subject: [PATCH] Implement C3P0 connection pool metrics (#6174) * C3P0 connection pool metrics * Use PooledDataSource instead of specific implementation * Add C3P0 readme * RuntimeException in case of underlying SQLException * Use ISE instead of RuntimeException --- .../c3p0-0.9/javaagent/build.gradle.kts | 22 ++++ ...ctPoolBackedDataSourceInstrumentation.java | 49 +++++++ .../c3p0/C3p0InstrumentationModule.java | 25 ++++ .../instrumentation/c3p0/C3p0Singletons.java | 21 +++ .../c3p0/C3p0InstrumentationTest.java | 29 +++++ instrumentation/c3p0-0.9/library/README.md | 47 +++++++ .../c3p0-0.9/library/build.gradle.kts | 10 ++ .../instrumentation/c3p0/C3p0Telemetry.java | 32 +++++ .../c3p0/ConnectionPoolMetrics.java | 122 ++++++++++++++++++ .../c3p0/C3p0InstrumentationTest.java | 40 ++++++ .../c3p0-0.9/testing/build.gradle.kts | 11 ++ .../c3p0/AbstractC3p0InstrumentationTest.java | 96 ++++++++++++++ settings.gradle.kts | 3 + .../db/DbConnectionPoolMetricsAssertions.java | 10 +- 14 files changed, 516 insertions(+), 1 deletion(-) create mode 100644 instrumentation/c3p0-0.9/javaagent/build.gradle.kts create mode 100644 instrumentation/c3p0-0.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/c3p0/AbstractPoolBackedDataSourceInstrumentation.java create mode 100644 instrumentation/c3p0-0.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/c3p0/C3p0InstrumentationModule.java create mode 100644 instrumentation/c3p0-0.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/c3p0/C3p0Singletons.java create mode 100644 instrumentation/c3p0-0.9/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/c3p0/C3p0InstrumentationTest.java create mode 100644 instrumentation/c3p0-0.9/library/README.md create mode 100644 instrumentation/c3p0-0.9/library/build.gradle.kts create mode 100644 instrumentation/c3p0-0.9/library/src/main/java/io/opentelemetry/instrumentation/c3p0/C3p0Telemetry.java create mode 100644 instrumentation/c3p0-0.9/library/src/main/java/io/opentelemetry/instrumentation/c3p0/ConnectionPoolMetrics.java create mode 100644 instrumentation/c3p0-0.9/library/src/test/java/io/opentelemetry/instrumentation/c3p0/C3p0InstrumentationTest.java create mode 100644 instrumentation/c3p0-0.9/testing/build.gradle.kts create mode 100644 instrumentation/c3p0-0.9/testing/src/main/java/io/opentelemetry/instrumentation/c3p0/AbstractC3p0InstrumentationTest.java diff --git a/instrumentation/c3p0-0.9/javaagent/build.gradle.kts b/instrumentation/c3p0-0.9/javaagent/build.gradle.kts new file mode 100644 index 000000000000..fd401d78af1b --- /dev/null +++ b/instrumentation/c3p0-0.9/javaagent/build.gradle.kts @@ -0,0 +1,22 @@ +plugins { + id("otel.javaagent-instrumentation") +} + +muzzle { + pass { + group.set("com.mchange") + module.set("c3p0") + versions.set("[0.9.2,)") + assertInverse.set(true) + // these versions have missing dependencies in maven central + skip("0.9.2-pre2-RELEASE", "0.9.2-pre3") + } +} + +dependencies { + library("com.mchange:c3p0:0.9.2") + + implementation(project(":instrumentation:c3p0-0.9:library")) + + testImplementation(project(":instrumentation:c3p0-0.9:testing")) +} diff --git a/instrumentation/c3p0-0.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/c3p0/AbstractPoolBackedDataSourceInstrumentation.java b/instrumentation/c3p0-0.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/c3p0/AbstractPoolBackedDataSourceInstrumentation.java new file mode 100644 index 000000000000..60bf2e6feaa4 --- /dev/null +++ b/instrumentation/c3p0-0.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/c3p0/AbstractPoolBackedDataSourceInstrumentation.java @@ -0,0 +1,49 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.c3p0; + +import static io.opentelemetry.javaagent.instrumentation.c3p0.C3p0Singletons.telemetry; +import static net.bytebuddy.matcher.ElementMatchers.named; + +import com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +final class AbstractPoolBackedDataSourceInstrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher typeMatcher() { + return named("com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + named("resetPoolManager"), this.getClass().getName() + "$ResetPoolManagerAdvice"); + transformer.applyAdviceToMethod(named("close"), this.getClass().getName() + "$CloseAdvice"); + } + + @SuppressWarnings("unused") + public static class ResetPoolManagerAdvice { + + @Advice.OnMethodExit(suppress = Throwable.class) + public static void onExit(@Advice.This AbstractPoolBackedDataSource dataSource) { + telemetry().registerMetrics(dataSource); + } + } + + @SuppressWarnings("unused") + public static class CloseAdvice { + + @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) + public static void onExit(@Advice.This AbstractPoolBackedDataSource dataSource) { + telemetry().unregisterMetrics(dataSource); + } + } +} diff --git a/instrumentation/c3p0-0.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/c3p0/C3p0InstrumentationModule.java b/instrumentation/c3p0-0.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/c3p0/C3p0InstrumentationModule.java new file mode 100644 index 000000000000..33c869ae26e1 --- /dev/null +++ b/instrumentation/c3p0-0.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/c3p0/C3p0InstrumentationModule.java @@ -0,0 +1,25 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.c3p0; + +import com.google.auto.service.AutoService; +import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import java.util.Collections; +import java.util.List; + +@AutoService(InstrumentationModule.class) +public class C3p0InstrumentationModule extends InstrumentationModule { + + public C3p0InstrumentationModule() { + super("c3p0", "c3p0-0.9"); + } + + @Override + public List typeInstrumentations() { + return Collections.singletonList(new AbstractPoolBackedDataSourceInstrumentation()); + } +} diff --git a/instrumentation/c3p0-0.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/c3p0/C3p0Singletons.java b/instrumentation/c3p0-0.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/c3p0/C3p0Singletons.java new file mode 100644 index 000000000000..5d7a606715a4 --- /dev/null +++ b/instrumentation/c3p0-0.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/c3p0/C3p0Singletons.java @@ -0,0 +1,21 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.c3p0; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.instrumentation.c3p0.C3p0Telemetry; + +public final class C3p0Singletons { + + private static final C3p0Telemetry c3p0Telemetry = + C3p0Telemetry.create(GlobalOpenTelemetry.get()); + + public static C3p0Telemetry telemetry() { + return c3p0Telemetry; + } + + private C3p0Singletons() {} +} diff --git a/instrumentation/c3p0-0.9/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/c3p0/C3p0InstrumentationTest.java b/instrumentation/c3p0-0.9/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/c3p0/C3p0InstrumentationTest.java new file mode 100644 index 000000000000..7278cc80f3ac --- /dev/null +++ b/instrumentation/c3p0-0.9/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/c3p0/C3p0InstrumentationTest.java @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.c3p0; + +import com.mchange.v2.c3p0.PooledDataSource; +import io.opentelemetry.instrumentation.c3p0.AbstractC3p0InstrumentationTest; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class C3p0InstrumentationTest extends AbstractC3p0InstrumentationTest { + + @RegisterExtension + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + @Override + protected InstrumentationExtension testing() { + return testing; + } + + @Override + protected void configure(PooledDataSource dataSource) {} + + @Override + protected void shutdown(PooledDataSource dataSource) {} +} diff --git a/instrumentation/c3p0-0.9/library/README.md b/instrumentation/c3p0-0.9/library/README.md new file mode 100644 index 000000000000..5fcf8bfe91d5 --- /dev/null +++ b/instrumentation/c3p0-0.9/library/README.md @@ -0,0 +1,47 @@ +# Manual Instrumentation for C3P0 + +Provides OpenTelemetry instrumentation for [C3P0](https://www.mchange.com/projects/c3p0/). + +## Quickstart + +### Add these dependencies to your project: + +Replace `OPENTELEMETRY_VERSION` with the latest stable +[release](https://mvnrepository.com/artifact/io.opentelemetry). `Minimum version: 1.15.0` + +For Maven, add to your `pom.xml` dependencies: + +```xml + + + + io.opentelemetry.instrumentation + opentelemetry-c3p0-0.9 + OPENTELEMETRY_VERSION + + +``` + +For Gradle, add to your dependencies: + +```groovy +implementation("io.opentelemetry.instrumentation:opentelemetry-c3p0-0.9:OPENTELEMETRY_VERSION") +``` + +### Usage + +The instrumentation library allows registering `PooledDataSource` instances for +collecting OpenTelemetry-based metrics. + +```java +C3p0Telemetry c3p0Telemetry; + +void configure(OpenTelemetry openTelemetry, PooledDataSource dataSource) { + c3p0Telemetry = C3p0Telemetry.create(openTelemetry); + c3p0Telemetry.registerMetrics(dataSource); +} + +void destroy(PooledDataSource dataSource) { + c3p0Telemetry.unregisterMetrics(dataSource); +} +``` diff --git a/instrumentation/c3p0-0.9/library/build.gradle.kts b/instrumentation/c3p0-0.9/library/build.gradle.kts new file mode 100644 index 000000000000..d6970bff8f9e --- /dev/null +++ b/instrumentation/c3p0-0.9/library/build.gradle.kts @@ -0,0 +1,10 @@ +plugins { + id("otel.library-instrumentation") + id("otel.nullaway-conventions") +} + +dependencies { + library("com.mchange:c3p0:0.9.2") + + testImplementation(project(":instrumentation:c3p0-0.9:testing")) +} diff --git a/instrumentation/c3p0-0.9/library/src/main/java/io/opentelemetry/instrumentation/c3p0/C3p0Telemetry.java b/instrumentation/c3p0-0.9/library/src/main/java/io/opentelemetry/instrumentation/c3p0/C3p0Telemetry.java new file mode 100644 index 000000000000..f4ac3d21f2ba --- /dev/null +++ b/instrumentation/c3p0-0.9/library/src/main/java/io/opentelemetry/instrumentation/c3p0/C3p0Telemetry.java @@ -0,0 +1,32 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.c3p0; + +import com.mchange.v2.c3p0.PooledDataSource; +import io.opentelemetry.api.OpenTelemetry; + +public final class C3p0Telemetry { + /** Returns a new {@link C3p0Telemetry} configured with the given {@link OpenTelemetry}. */ + public static C3p0Telemetry create(OpenTelemetry openTelemetry) { + return new C3p0Telemetry(openTelemetry); + } + + private final OpenTelemetry openTelemetry; + + private C3p0Telemetry(OpenTelemetry openTelemetry) { + this.openTelemetry = openTelemetry; + } + + /** Start collecting metrics for given connection pool. */ + public void registerMetrics(PooledDataSource dataSource) { + ConnectionPoolMetrics.registerMetrics(openTelemetry, dataSource); + } + + /** Stop collecting metrics for given connection pool. */ + public void unregisterMetrics(PooledDataSource dataSource) { + ConnectionPoolMetrics.unregisterMetrics(dataSource); + } +} diff --git a/instrumentation/c3p0-0.9/library/src/main/java/io/opentelemetry/instrumentation/c3p0/ConnectionPoolMetrics.java b/instrumentation/c3p0-0.9/library/src/main/java/io/opentelemetry/instrumentation/c3p0/ConnectionPoolMetrics.java new file mode 100644 index 000000000000..6255771f98e6 --- /dev/null +++ b/instrumentation/c3p0-0.9/library/src/main/java/io/opentelemetry/instrumentation/c3p0/ConnectionPoolMetrics.java @@ -0,0 +1,122 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.c3p0; + +import com.mchange.v2.c3p0.PooledDataSource; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.metrics.ObservableLongUpDownCounter; +import io.opentelemetry.instrumentation.api.metrics.db.DbConnectionPoolMetrics; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.LongSupplier; +import javax.annotation.Nullable; + +final class ConnectionPoolMetrics { + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.c3p0-0.9"; + + // a weak map does not make sense here because each Meter holds a reference to the dataSource + // PooledDataSource implements equals() & hashCode() in IdentityTokenResolvable, + // that's why we wrap it with IdentityDataSourceKey that uses identity comparison instead + private static final Map> + dataSourceMetrics = new ConcurrentHashMap<>(); + + public static void registerMetrics(OpenTelemetry openTelemetry, PooledDataSource dataSource) { + dataSourceMetrics.compute( + new IdentityDataSourceKey(dataSource), + (key, existingCounters) -> + ConnectionPoolMetrics.createMeters(openTelemetry, key, existingCounters)); + } + + private static List createMeters( + OpenTelemetry openTelemetry, + IdentityDataSourceKey key, + List existingCounters) { + // remove old counters from the registry in case they were already there + removeMetersFromRegistry(existingCounters); + + PooledDataSource dataSource = key.dataSource; + + DbConnectionPoolMetrics metrics = + DbConnectionPoolMetrics.create( + openTelemetry, INSTRUMENTATION_NAME, dataSource.getDataSourceName()); + + return Arrays.asList( + metrics.usedConnections(wrapThrowingSupplier(dataSource::getNumBusyConnectionsDefaultUser)), + metrics.idleConnections(wrapThrowingSupplier(dataSource::getNumIdleConnectionsDefaultUser)), + metrics.pendingRequestsForConnection( + wrapThrowingSupplier(dataSource::getNumThreadsAwaitingCheckoutDefaultUser))); + } + + public static void unregisterMetrics(PooledDataSource dataSource) { + List meters = + dataSourceMetrics.remove(new IdentityDataSourceKey(dataSource)); + removeMetersFromRegistry(meters); + } + + private static void removeMetersFromRegistry( + @Nullable List observableInstruments) { + if (observableInstruments != null) { + for (ObservableLongUpDownCounter observable : observableInstruments) { + observable.close(); + } + } + } + + /** + * A wrapper over {@link PooledDataSource} that implements identity comparison in its {@link + * #equals(Object)} and {@link #hashCode()} methods. + */ + static final class IdentityDataSourceKey { + final PooledDataSource dataSource; + + IdentityDataSourceKey(PooledDataSource dataSource) { + this.dataSource = dataSource; + } + + @Override + @SuppressWarnings("ReferenceEquality") + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + IdentityDataSourceKey that = (IdentityDataSourceKey) o; + return dataSource == that.dataSource; + } + + @Override + public int hashCode() { + return System.identityHashCode(dataSource); + } + + @Override + public String toString() { + return dataSource.toString(); + } + } + + static LongSupplier wrapThrowingSupplier(DataSourceIntSupplier supplier) { + return () -> { + try { + return supplier.getAsInt(); + } catch (SQLException e) { + throw new IllegalStateException("Failed to get C3P0 datasource metric", e); + } + }; + } + + @FunctionalInterface + interface DataSourceIntSupplier { + int getAsInt() throws SQLException; + } + + private ConnectionPoolMetrics() {} +} diff --git a/instrumentation/c3p0-0.9/library/src/test/java/io/opentelemetry/instrumentation/c3p0/C3p0InstrumentationTest.java b/instrumentation/c3p0-0.9/library/src/test/java/io/opentelemetry/instrumentation/c3p0/C3p0InstrumentationTest.java new file mode 100644 index 000000000000..29bd5d8a9782 --- /dev/null +++ b/instrumentation/c3p0-0.9/library/src/test/java/io/opentelemetry/instrumentation/c3p0/C3p0InstrumentationTest.java @@ -0,0 +1,40 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.c3p0; + +import com.mchange.v2.c3p0.PooledDataSource; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class C3p0InstrumentationTest extends AbstractC3p0InstrumentationTest { + + @RegisterExtension + static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); + + private static C3p0Telemetry telemetry; + + @Override + protected InstrumentationExtension testing() { + return testing; + } + + @BeforeAll + static void setup() { + telemetry = C3p0Telemetry.create(testing.getOpenTelemetry()); + } + + @Override + protected void configure(PooledDataSource dataSource) { + telemetry.registerMetrics(dataSource); + } + + @Override + protected void shutdown(PooledDataSource dataSource) { + telemetry.unregisterMetrics(dataSource); + } +} diff --git a/instrumentation/c3p0-0.9/testing/build.gradle.kts b/instrumentation/c3p0-0.9/testing/build.gradle.kts new file mode 100644 index 000000000000..28f6dbd967f2 --- /dev/null +++ b/instrumentation/c3p0-0.9/testing/build.gradle.kts @@ -0,0 +1,11 @@ +plugins { + id("otel.java-conventions") +} + +dependencies { + api(project(":testing-common")) + api("org.mockito:mockito-core") + api("org.mockito:mockito-junit-jupiter") + + compileOnly("com.mchange:c3p0:0.9.2") +} diff --git a/instrumentation/c3p0-0.9/testing/src/main/java/io/opentelemetry/instrumentation/c3p0/AbstractC3p0InstrumentationTest.java b/instrumentation/c3p0-0.9/testing/src/main/java/io/opentelemetry/instrumentation/c3p0/AbstractC3p0InstrumentationTest.java new file mode 100644 index 000000000000..bdee186cae54 --- /dev/null +++ b/instrumentation/c3p0-0.9/testing/src/main/java/io/opentelemetry/instrumentation/c3p0/AbstractC3p0InstrumentationTest.java @@ -0,0 +1,96 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.c3p0; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.mchange.v2.c3p0.ComboPooledDataSource; +import com.mchange.v2.c3p0.PooledDataSource; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.db.DbConnectionPoolMetricsAssertions; +import io.opentelemetry.instrumentation.testing.junit.db.MockDriver; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public abstract class AbstractC3p0InstrumentationTest { + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.c3p0-0.9"; + + protected abstract InstrumentationExtension testing(); + + protected abstract void configure(PooledDataSource dataSource) throws Exception; + + protected abstract void shutdown(PooledDataSource dataSource) throws Exception; + + @BeforeAll + static void setUpMocks() throws SQLException { + MockDriver.register(); + } + + @Test + void shouldReportMetrics() throws Exception { + // given + ComboPooledDataSource c3p0DataSource = new ComboPooledDataSource(); + c3p0DataSource.setDriverClass(MockDriver.class.getName()); + c3p0DataSource.setJdbcUrl("jdbc:mock:testDatabase"); + + // when + Connection connection = c3p0DataSource.getConnection(); + configure(c3p0DataSource); + TimeUnit.MILLISECONDS.sleep(100); + connection.close(); + + // then + assertDataSourceMetrics(c3p0DataSource); + + // when + shutdown(c3p0DataSource); + c3p0DataSource.close(); + + // wait interval of the test metrics exporter + Thread.sleep(100); + testing().clearData(); + Thread.sleep(100); + + // then + Set metricNames = + new HashSet<>( + Arrays.asList("db.client.connections.usage", "db.client.connections.pending_requests")); + assertThat(testing().metrics()) + .filteredOn( + metricData -> + metricData.getInstrumentationScopeInfo().getName().equals(INSTRUMENTATION_NAME) + && metricNames.contains(metricData.getName())) + .isEmpty(); + } + + private void assertDataSourceMetrics(PooledDataSource dataSource) { + String dataSourceName = dataSource.getDataSourceName(); + + assertThat(dataSourceName) + .as("c3p0 generates a unique pool name if it's not explicitly provided") + .isNotEmpty(); + + DbConnectionPoolMetricsAssertions.create( + testing(), INSTRUMENTATION_NAME, dataSource.getDataSourceName()) + .disableMinIdleConnections() + .disableMaxIdleConnections() + .disableMaxConnections() + .disableConnectionTimeouts() + .disableCreateTime() + .disableWaitTime() + .disableUseTime() + .assertConnectionPoolEmitsMetrics(); + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 3b1c0b8ca990..372306a2a48c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -187,6 +187,9 @@ include(":instrumentation:internal:internal-reflection:javaagent") include(":instrumentation:internal:internal-reflection:javaagent-integration-tests") include(":instrumentation:internal:internal-url-class-loader:javaagent") include(":instrumentation:internal:internal-url-class-loader:javaagent-integration-tests") +include(":instrumentation:c3p0-0.9:javaagent") +include(":instrumentation:c3p0-0.9:library") +include(":instrumentation:c3p0-0.9:testing") include(":instrumentation:couchbase:couchbase-2.0:javaagent") include(":instrumentation:couchbase:couchbase-2.6:javaagent") include(":instrumentation:couchbase:couchbase-2-common:javaagent") diff --git a/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/db/DbConnectionPoolMetricsAssertions.java b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/db/DbConnectionPoolMetricsAssertions.java index 6fea21a336ee..f16b197b3c70 100644 --- a/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/db/DbConnectionPoolMetricsAssertions.java +++ b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/db/DbConnectionPoolMetricsAssertions.java @@ -32,6 +32,7 @@ public static DbConnectionPoolMetricsAssertions create( private boolean testMinIdleConnections = true; private boolean testMaxIdleConnections = true; + private boolean testMaxConnections = true; private boolean testPendingRequests = true; private boolean testConnectionTimeouts = true; private boolean testCreateTime = true; @@ -55,6 +56,11 @@ public DbConnectionPoolMetricsAssertions disableMaxIdleConnections() { return this; } + public DbConnectionPoolMetricsAssertions disableMaxConnections() { + testMaxConnections = false; + return this; + } + public DbConnectionPoolMetricsAssertions disablePendingRequests() { testPendingRequests = false; return this; @@ -88,7 +94,9 @@ public void assertConnectionPoolEmitsMetrics() { if (testMaxIdleConnections) { verifyMaxIdleConnections(); } - verifyMaxConnections(); + if (testMaxConnections) { + verifyMaxConnections(); + } if (testPendingRequests) { verifyPendingRequests(); }