From a7d9136629c424d2d6824de99c86c0c5d39dc674 Mon Sep 17 00:00:00 2001 From: Chris Pennello Date: Fri, 5 Aug 2022 16:02:09 -0700 Subject: [PATCH 1/3] Upgrades felix to 7.0.5. This update avoids an issue in at least JDK 18 in which `java.net.URLStreamHandler.equals` was inaccessible due to module java.base not "opens java.net". See below for more detail. [ERROR] Tests run: 2, Failures: 0, Errors: 2, Skipped: 0, Time elapsed: 0.129 s <<< FAILURE! - in com.zaxxer.hikari.osgi.OSGiBundleTest [ERROR] com.zaxxer.hikari.osgi.OSGiBundleTest.checkBundle Time elapsed: 0.09 s <<< ERROR! java.lang.ExceptionInInitializerError Caused by: java.lang.RuntimeException: Unable to make protected boolean java.net.URLStreamHandler.equals(java.net.URL,java.net.URL) accessible: module java.base does not "opens java.net" to unnamed module @484b61fc Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected boolean java.net.URLStreamHandler.equals(java.net.URL,java.net.URL) accessible: module java.base does not "opens java.net" to unnamed module @484b61fc --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 61994449..90166323 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ 0.40.3 5.1.1 - 6.0.1 + 7.0.5 5.4.24.Final 3.29.2-GA 0.11.4.1 From 07e40c20ab8f38c86ee9c744e4a8b6623482212d Mon Sep 17 00:00:00 2001 From: Chris Pennello Date: Fri, 5 Aug 2022 17:04:30 -0700 Subject: [PATCH 2/3] Fixes TestMetrics filter bug. Previously, this matches implementation was ignoring the `name` passed in and instead comparing the *literal* `"testMetricWait.pool.Wait"` to the dynamically-created `MetricRegistry.name("testMetricWait", "pool", "Wait")`. This commit updates the matches implementation to instead compare the `name` passed in. This brings it in line with the other implementations in the same file. --- src/test/java/com/zaxxer/hikari/pool/TestMetrics.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/zaxxer/hikari/pool/TestMetrics.java b/src/test/java/com/zaxxer/hikari/pool/TestMetrics.java index 2e05dca9..84ad628f 100644 --- a/src/test/java/com/zaxxer/hikari/pool/TestMetrics.java +++ b/src/test/java/com/zaxxer/hikari/pool/TestMetrics.java @@ -71,7 +71,7 @@ public class TestMetrics @Override public boolean matches(String name, Metric metric) { - return "testMetricWait.pool.Wait".equals(MetricRegistry.name("testMetricWait", "pool", "Wait")); + return name.equals(MetricRegistry.name("testMetricWait", "pool", "Wait")); } }).values().iterator().next(); From 3f377c0bda615f9abb2efacd2d67766997f3d2f8 Mon Sep 17 00:00:00 2001 From: Chris Pennello Date: Mon, 8 Aug 2022 09:17:19 -0700 Subject: [PATCH 3/3] Adds support for Dropwizard 5 metrics. But not health checks yet, though. --- CHANGES | 5 + pom.xml | 9 + .../java/com/zaxxer/hikari/HikariConfig.java | 4 +- .../dropwizard/CodaHaleMetricsTracker.java | 24 +- .../dropwizard/Dropwizard5MetricsTracker.java | 118 +++++++ .../Dropwizard5MetricsTrackerFactory.java | 27 ++ .../metrics/dropwizard/DropwizardCommon.java | 33 ++ .../com/zaxxer/hikari/pool/HikariPool.java | 4 + src/main/java/module-info.java | 1 + .../Dropwizard5MetricsTrackerTest.java | 43 +++ .../hikari/pool/CodahaleMetricsTest.java | 242 +++++++++++++++ .../hikari/pool/Dropwizard5MetricsTest.java | 174 +++++++++++ .../com/zaxxer/hikari/pool/TestMetrics.java | 293 +----------------- .../zaxxer/hikari/pool/TestMetricsBase.java | 147 +++++++++ 14 files changed, 821 insertions(+), 303 deletions(-) create mode 100644 src/main/java/com/zaxxer/hikari/metrics/dropwizard/Dropwizard5MetricsTracker.java create mode 100644 src/main/java/com/zaxxer/hikari/metrics/dropwizard/Dropwizard5MetricsTrackerFactory.java create mode 100644 src/main/java/com/zaxxer/hikari/metrics/dropwizard/DropwizardCommon.java create mode 100644 src/test/java/com/zaxxer/hikari/metrics/dropwizard/Dropwizard5MetricsTrackerTest.java create mode 100644 src/test/java/com/zaxxer/hikari/pool/CodahaleMetricsTest.java create mode 100644 src/test/java/com/zaxxer/hikari/pool/Dropwizard5MetricsTest.java create mode 100644 src/test/java/com/zaxxer/hikari/pool/TestMetricsBase.java diff --git a/CHANGES b/CHANGES index 3a5d0c6d..d715e38f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,10 @@ HikariCP Changes +Changes in 5.0.2 + + * Dropwizard 5 metrics are now supported via the setMetricRegistry() + method in HikariConfig and in HikariDataSource. + Changes in 5.0.0 * rewrote connection elide/add code to fix an unconfirmed but occassionally reported diff --git a/pom.xml b/pom.xml index 90166323..e6e7d4bb 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,7 @@ 0.11.4.1 2.5.3 3.2.5 + 5.0.0-rc17 1.5.10 0.9.0 3.7.7 @@ -174,6 +175,13 @@ provided true + + io.dropwizard.metrics5 + metrics-core + ${metrics5.version} + provided + true + io.prometheus simpleclient @@ -462,6 +470,7 @@ javax.sql.rowset.spi, com.codahale.metrics;resolution:=optional, com.codahale.metrics.health;resolution:=optional, + io.dropwizard.metrics5;resolution:=optional, io.micrometer.core.instrument;resolution:=optional, org.slf4j;version="[1.6,2)", org.hibernate;resolution:=optional, diff --git a/src/main/java/com/zaxxer/hikari/HikariConfig.java b/src/main/java/com/zaxxer/hikari/HikariConfig.java index 92c20577..b2f82518 100644 --- a/src/main/java/com/zaxxer/hikari/HikariConfig.java +++ b/src/main/java/com/zaxxer/hikari/HikariConfig.java @@ -671,8 +671,10 @@ public class HikariConfig implements HikariConfigMXBean metricRegistry = getObjectOrPerformJndiLookup(metricRegistry); if (!safeIsAssignableFrom(metricRegistry, "com.codahale.metrics.MetricRegistry") + && !(safeIsAssignableFrom(metricRegistry, "io.dropwizard.metrics5.MetricRegistry")) && !(safeIsAssignableFrom(metricRegistry, "io.micrometer.core.instrument.MeterRegistry"))) { - throw new IllegalArgumentException("Class must be instance of com.codahale.metrics.MetricRegistry or io.micrometer.core.instrument.MeterRegistry"); + throw new IllegalArgumentException("Class must be instance of com.codahale.metrics.MetricRegistry, " + + "io.dropwizard.metrics5.MetricRegistry, or io.micrometer.core.instrument.MeterRegistry"); } } diff --git a/src/main/java/com/zaxxer/hikari/metrics/dropwizard/CodaHaleMetricsTracker.java b/src/main/java/com/zaxxer/hikari/metrics/dropwizard/CodaHaleMetricsTracker.java index 633ff52d..3126edc5 100644 --- a/src/main/java/com/zaxxer/hikari/metrics/dropwizard/CodaHaleMetricsTracker.java +++ b/src/main/java/com/zaxxer/hikari/metrics/dropwizard/CodaHaleMetricsTracker.java @@ -26,6 +26,18 @@ import com.codahale.metrics.Timer; import com.zaxxer.hikari.metrics.IMetricsTracker; import com.zaxxer.hikari.metrics.PoolStats; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_CATEGORY; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_ACTIVE_CONNECTIONS; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_CONNECT; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_IDLE_CONNECTIONS; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_MAX_CONNECTIONS; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_MIN_CONNECTIONS; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_PENDING_CONNECTIONS; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_TIMEOUT_RATE; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_TOTAL_CONNECTIONS; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_USAGE; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_WAIT; + public final class CodaHaleMetricsTracker implements IMetricsTracker { private final String poolName; @@ -35,18 +47,6 @@ public final class CodaHaleMetricsTracker implements IMetricsTracker private final Meter connectionTimeoutMeter; private final MetricRegistry registry; - private static final String METRIC_CATEGORY = "pool"; - private static final String METRIC_NAME_WAIT = "Wait"; - private static final String METRIC_NAME_USAGE = "Usage"; - private static final String METRIC_NAME_CONNECT = "ConnectionCreation"; - private static final String METRIC_NAME_TIMEOUT_RATE = "ConnectionTimeoutRate"; - private static final String METRIC_NAME_TOTAL_CONNECTIONS = "TotalConnections"; - private static final String METRIC_NAME_IDLE_CONNECTIONS = "IdleConnections"; - private static final String METRIC_NAME_ACTIVE_CONNECTIONS = "ActiveConnections"; - private static final String METRIC_NAME_PENDING_CONNECTIONS = "PendingConnections"; - private static final String METRIC_NAME_MAX_CONNECTIONS = "MaxConnections"; - private static final String METRIC_NAME_MIN_CONNECTIONS = "MinConnections"; - CodaHaleMetricsTracker(final String poolName, final PoolStats poolStats, final MetricRegistry registry) { this.poolName = poolName; diff --git a/src/main/java/com/zaxxer/hikari/metrics/dropwizard/Dropwizard5MetricsTracker.java b/src/main/java/com/zaxxer/hikari/metrics/dropwizard/Dropwizard5MetricsTracker.java new file mode 100644 index 00000000..ac5576d9 --- /dev/null +++ b/src/main/java/com/zaxxer/hikari/metrics/dropwizard/Dropwizard5MetricsTracker.java @@ -0,0 +1,118 @@ +package com.zaxxer.hikari.metrics.dropwizard; + +import java.util.concurrent.TimeUnit; + +import com.zaxxer.hikari.metrics.IMetricsTracker; +import com.zaxxer.hikari.metrics.PoolStats; +import io.dropwizard.metrics5.Gauge; +import io.dropwizard.metrics5.Histogram; +import io.dropwizard.metrics5.Meter; +import io.dropwizard.metrics5.MetricRegistry; +import io.dropwizard.metrics5.Timer; + +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_CATEGORY; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_ACTIVE_CONNECTIONS; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_CONNECT; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_IDLE_CONNECTIONS; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_MAX_CONNECTIONS; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_MIN_CONNECTIONS; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_PENDING_CONNECTIONS; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_TIMEOUT_RATE; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_TOTAL_CONNECTIONS; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_USAGE; +import static com.zaxxer.hikari.metrics.dropwizard.DropwizardCommon.METRIC_NAME_WAIT; + +public class Dropwizard5MetricsTracker implements IMetricsTracker +{ + private final String poolName; + private final Timer connectionObtainTimer; + private final Histogram connectionUsage; + private final Histogram connectionCreation; + private final Meter connectionTimeoutMeter; + private final MetricRegistry registry; + + Dropwizard5MetricsTracker(final String poolName, final PoolStats poolStats, final MetricRegistry registry) + { + this.poolName = poolName; + this.registry = registry; + this.connectionObtainTimer = registry.timer(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_WAIT)); + this.connectionUsage = registry.histogram(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_USAGE)); + this.connectionCreation = registry.histogram(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_CONNECT)); + this.connectionTimeoutMeter = registry.meter(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_TIMEOUT_RATE)); + + registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_TOTAL_CONNECTIONS), + (Gauge) poolStats::getTotalConnections); + + registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_IDLE_CONNECTIONS), + (Gauge) poolStats::getIdleConnections); + + registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_ACTIVE_CONNECTIONS), + (Gauge) poolStats::getActiveConnections); + + registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_PENDING_CONNECTIONS), + (Gauge) poolStats::getPendingThreads); + + registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_MAX_CONNECTIONS), + (Gauge) poolStats::getMaxConnections); + + registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_MIN_CONNECTIONS), + (Gauge) poolStats::getMinConnections); + } + + /** {@inheritDoc} */ + @Override + public void close() + { + registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_WAIT)); + registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_USAGE)); + registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_CONNECT)); + registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_TIMEOUT_RATE)); + registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_TOTAL_CONNECTIONS)); + registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_IDLE_CONNECTIONS)); + registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_ACTIVE_CONNECTIONS)); + registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_PENDING_CONNECTIONS)); + registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_MAX_CONNECTIONS)); + registry.remove(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_MIN_CONNECTIONS)); + } + + /** {@inheritDoc} */ + @Override + public void recordConnectionAcquiredNanos(final long elapsedAcquiredNanos) + { + connectionObtainTimer.update(elapsedAcquiredNanos, TimeUnit.NANOSECONDS); + } + + /** {@inheritDoc} */ + @Override + public void recordConnectionUsageMillis(final long elapsedBorrowedMillis) + { + connectionUsage.update(elapsedBorrowedMillis); + } + + @Override + public void recordConnectionTimeout() + { + connectionTimeoutMeter.mark(); + } + + @Override + public void recordConnectionCreatedMillis(final long connectionCreatedMillis) + { + connectionCreation.update(connectionCreatedMillis); + } + + public Timer getConnectionAcquisitionTimer() + { + return connectionObtainTimer; + } + + public Histogram getConnectionDurationHistogram() + { + return connectionUsage; + } + + public Histogram getConnectionCreationHistogram() + { + return connectionCreation; + } +} diff --git a/src/main/java/com/zaxxer/hikari/metrics/dropwizard/Dropwizard5MetricsTrackerFactory.java b/src/main/java/com/zaxxer/hikari/metrics/dropwizard/Dropwizard5MetricsTrackerFactory.java new file mode 100644 index 00000000..b1c22184 --- /dev/null +++ b/src/main/java/com/zaxxer/hikari/metrics/dropwizard/Dropwizard5MetricsTrackerFactory.java @@ -0,0 +1,27 @@ +package com.zaxxer.hikari.metrics.dropwizard; + +import com.zaxxer.hikari.metrics.IMetricsTracker; +import com.zaxxer.hikari.metrics.MetricsTrackerFactory; +import com.zaxxer.hikari.metrics.PoolStats; +import io.dropwizard.metrics5.MetricRegistry; + +public class Dropwizard5MetricsTrackerFactory implements MetricsTrackerFactory +{ + private final MetricRegistry registry; + + public Dropwizard5MetricsTrackerFactory(final MetricRegistry registry) + { + this.registry = registry; + } + + public MetricRegistry getRegistry() + { + return registry; + } + + @Override + public IMetricsTracker create(final String poolName, final PoolStats poolStats) + { + return new Dropwizard5MetricsTracker(poolName, poolStats, registry); + } +} diff --git a/src/main/java/com/zaxxer/hikari/metrics/dropwizard/DropwizardCommon.java b/src/main/java/com/zaxxer/hikari/metrics/dropwizard/DropwizardCommon.java new file mode 100644 index 00000000..e1a0254c --- /dev/null +++ b/src/main/java/com/zaxxer/hikari/metrics/dropwizard/DropwizardCommon.java @@ -0,0 +1,33 @@ +/* + * Licensed 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 com.zaxxer.hikari.metrics.dropwizard; + +final class DropwizardCommon { + private DropwizardCommon() + { + } + + static final String METRIC_CATEGORY = "pool"; + static final String METRIC_NAME_WAIT = "Wait"; + static final String METRIC_NAME_USAGE = "Usage"; + static final String METRIC_NAME_CONNECT = "ConnectionCreation"; + static final String METRIC_NAME_TIMEOUT_RATE = "ConnectionTimeoutRate"; + static final String METRIC_NAME_TOTAL_CONNECTIONS = "TotalConnections"; + static final String METRIC_NAME_IDLE_CONNECTIONS = "IdleConnections"; + static final String METRIC_NAME_ACTIVE_CONNECTIONS = "ActiveConnections"; + static final String METRIC_NAME_PENDING_CONNECTIONS = "PendingConnections"; + static final String METRIC_NAME_MAX_CONNECTIONS = "MaxConnections"; + static final String METRIC_NAME_MIN_CONNECTIONS = "MinConnections"; +} diff --git a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java index 07712055..d98cf897 100644 --- a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java +++ b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java @@ -24,6 +24,7 @@ import com.zaxxer.hikari.metrics.MetricsTrackerFactory; import com.zaxxer.hikari.metrics.PoolStats; import com.zaxxer.hikari.metrics.dropwizard.CodahaleHealthChecker; import com.zaxxer.hikari.metrics.dropwizard.CodahaleMetricsTrackerFactory; +import com.zaxxer.hikari.metrics.dropwizard.Dropwizard5MetricsTrackerFactory; import com.zaxxer.hikari.metrics.micrometer.MicrometerMetricsTrackerFactory; import com.zaxxer.hikari.util.ConcurrentBag; import com.zaxxer.hikari.util.ConcurrentBag.IBagStateListener; @@ -279,6 +280,9 @@ public final class HikariPool extends PoolBase implements HikariPoolMXBean, IBag if (metricRegistry != null && safeIsAssignableFrom(metricRegistry, "com.codahale.metrics.MetricRegistry")) { setMetricsTrackerFactory(new CodahaleMetricsTrackerFactory((MetricRegistry) metricRegistry)); } + else if (metricRegistry != null && safeIsAssignableFrom(metricRegistry, "io.dropwizard.metrics5.MetricRegistry")) { + setMetricsTrackerFactory(new Dropwizard5MetricsTrackerFactory((io.dropwizard.metrics5.MetricRegistry) metricRegistry)); + } else if (metricRegistry != null && safeIsAssignableFrom(metricRegistry, "io.micrometer.core.instrument.MeterRegistry")) { setMetricsTrackerFactory(new MicrometerMetricsTrackerFactory((MeterRegistry) metricRegistry)); } diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index dd7142a6..703e1e0d 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -8,6 +8,7 @@ module com.zaxxer.hikari requires static simpleclient; requires static metrics.core; requires static metrics.healthchecks; + requires static io.dropwizard.metrics5; requires static micrometer.core; requires static org.javassist; diff --git a/src/test/java/com/zaxxer/hikari/metrics/dropwizard/Dropwizard5MetricsTrackerTest.java b/src/test/java/com/zaxxer/hikari/metrics/dropwizard/Dropwizard5MetricsTrackerTest.java new file mode 100644 index 00000000..21567cab --- /dev/null +++ b/src/test/java/com/zaxxer/hikari/metrics/dropwizard/Dropwizard5MetricsTrackerTest.java @@ -0,0 +1,43 @@ +package com.zaxxer.hikari.metrics.dropwizard; + +import com.zaxxer.hikari.mocks.StubPoolStats; +import io.dropwizard.metrics5.MetricRegistry; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import static org.mockito.Mockito.verify; + +@RunWith(MockitoJUnitRunner.class) +public class Dropwizard5MetricsTrackerTest +{ + @Mock + public MetricRegistry mockMetricRegistry; + + private Dropwizard5MetricsTracker testee; + + @Before + public void setup() + { + testee = new Dropwizard5MetricsTracker("mypool", new StubPoolStats(0), mockMetricRegistry); + } + + @Test + public void close() + { + testee.close(); + + verify(mockMetricRegistry).remove(MetricRegistry.name("mypool.pool.Wait")); + verify(mockMetricRegistry).remove(MetricRegistry.name("mypool.pool.Usage")); + verify(mockMetricRegistry).remove(MetricRegistry.name("mypool.pool.ConnectionCreation")); + verify(mockMetricRegistry).remove(MetricRegistry.name("mypool.pool.ConnectionTimeoutRate")); + verify(mockMetricRegistry).remove(MetricRegistry.name("mypool.pool.TotalConnections")); + verify(mockMetricRegistry).remove(MetricRegistry.name("mypool.pool.IdleConnections")); + verify(mockMetricRegistry).remove(MetricRegistry.name("mypool.pool.ActiveConnections")); + verify(mockMetricRegistry).remove(MetricRegistry.name("mypool.pool.PendingConnections")); + verify(mockMetricRegistry).remove(MetricRegistry.name("mypool.pool.MaxConnections")); + verify(mockMetricRegistry).remove(MetricRegistry.name("mypool.pool.MinConnections")); + } +} diff --git a/src/test/java/com/zaxxer/hikari/pool/CodahaleMetricsTest.java b/src/test/java/com/zaxxer/hikari/pool/CodahaleMetricsTest.java new file mode 100644 index 00000000..681e0db3 --- /dev/null +++ b/src/test/java/com/zaxxer/hikari/pool/CodahaleMetricsTest.java @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2013, 2014 Brett Wooldridge + * + * Licensed 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 com.zaxxer.hikari.pool; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.SortedMap; +import java.util.concurrent.TimeUnit; + +import com.codahale.metrics.Histogram; +import com.codahale.metrics.Metric; +import com.codahale.metrics.MetricFilter; +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.Timer; +import com.codahale.metrics.health.HealthCheck; +import com.codahale.metrics.health.HealthCheckRegistry; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import com.zaxxer.hikari.metrics.MetricsTrackerFactory; +import com.zaxxer.hikari.metrics.dropwizard.CodahaleMetricsTrackerFactory; +import com.zaxxer.hikari.util.UtilityElf; +import org.junit.Test; + +import static com.zaxxer.hikari.pool.TestElf.newHikariConfig; +import static com.zaxxer.hikari.pool.TestElf.newHikariDataSource; +import static com.zaxxer.hikari.util.UtilityElf.quietlySleep; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeFalse; + +/** + * Test HikariCP/CodaHale metrics integration. + * + * @author Brett Wooldridge + */ +public class CodahaleMetricsTest extends TestMetricsBase +{ + @Override + protected MetricsTrackerFactory metricsTrackerFactory(final MetricRegistry metricRegistry) + { + return new CodahaleMetricsTrackerFactory(metricRegistry); + } + + @Override + protected MetricRegistry metricRegistry() + { + return new MetricRegistry(); + } + + @Test + public void testHealthChecks() throws Exception + { + MetricRegistry metricRegistry = metricRegistry(); + HealthCheckRegistry healthRegistry = new HealthCheckRegistry(); + + HikariConfig config = newHikariConfig(); + config.setMaximumPoolSize(10); + config.setMetricRegistry(metricRegistry); + config.setHealthCheckRegistry(healthRegistry); + config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + config.addHealthCheckProperty("connectivityCheckTimeoutMs", "1000"); + config.addHealthCheckProperty("expected99thPercentileMs", "100"); + + try (HikariDataSource ds = new HikariDataSource(config)) { + quietlySleep(TimeUnit.SECONDS.toMillis(2)); + + try (Connection connection = ds.getConnection()) { + // close immediately + } + + try (Connection connection = ds.getConnection()) { + // close immediately + } + + SortedMap healthChecks = healthRegistry.runHealthChecks(); + + HealthCheck.Result connectivityResult = healthChecks.get("testHealthChecks.pool.ConnectivityCheck"); + assertTrue(connectivityResult.isHealthy()); + + HealthCheck.Result slaResult = healthChecks.get("testHealthChecks.pool.Connection99Percent"); + assertTrue(slaResult.isHealthy()); + } + } + + @Test + public void testSetters1() throws Exception + { + try (HikariDataSource ds = newHikariDataSource()) { + ds.setMaximumPoolSize(1); + ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + + MetricRegistry metricRegistry = metricRegistry(); + HealthCheckRegistry healthRegistry = new HealthCheckRegistry(); + + try { + try (Connection connection = ds.getConnection()) { + // close immediately + } + + // After the pool as started, we can only set them once... + ds.setMetricRegistry(metricRegistry); + ds.setHealthCheckRegistry(healthRegistry); + + // and never again... + ds.setMetricRegistry(metricRegistry); + fail("Should not have been allowed to set registry after pool started"); + } + catch (IllegalStateException ise) { + // pass + try { + ds.setHealthCheckRegistry(healthRegistry); + fail("Should not have been allowed to set registry after pool started"); + } + catch (IllegalStateException ise2) { + // pass + } + } + } + } + + @Test + public void testSetters2() throws Exception + { + try (HikariDataSource ds = newHikariDataSource()) { + ds.setMaximumPoolSize(1); + ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + + MetricRegistry metricRegistry = metricRegistry(); + HealthCheckRegistry healthRegistry = new HealthCheckRegistry(); + + ds.setMetricRegistry(metricRegistry); + ds.setHealthCheckRegistry(healthRegistry); + + // before the pool is started, we can set it any number of times... + ds.setMetricRegistry(metricRegistry); + ds.setHealthCheckRegistry(healthRegistry); + + try (Connection connection = ds.getConnection()) { + + // after the pool is started, we cannot set it any more + ds.setMetricRegistry(metricRegistry); + fail("Should not have been allowed to set registry after pool started"); + } + catch (IllegalStateException ise) { + // pass + } + } + } + + @Test + public void testMetricWait() throws SQLException + { + MetricRegistry metricRegistry = new MetricRegistry(); + + HikariConfig config = newHikariConfig(); + config.setMinimumIdle(1); + config.setMaximumPoolSize(1); + config.setMetricRegistry(metricRegistry); + config.setInitializationFailTimeout(Long.MAX_VALUE); + config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + + try (HikariDataSource ds = new HikariDataSource(config)) { + ds.getConnection().close(); + + Timer timer = metricRegistry.getTimers(new MetricFilter() { + /** {@inheritDoc} */ + @Override + public boolean matches(String name, Metric metric) + { + return name.equals(MetricRegistry.name("testMetricWait", "pool", "Wait")); + } + }).values().iterator().next(); + + assertEquals(1, timer.getCount()); + assertTrue(timer.getMeanRate() > 0.0); + } + } + + @Test + public void testMetricUsage() throws SQLException + { + assumeFalse(System.getProperty("os.name").contains("Windows")); + MetricRegistry metricRegistry = new MetricRegistry(); + + HikariConfig config = newHikariConfig(); + config.setMinimumIdle(1); + config.setMaximumPoolSize(1); + config.setMetricRegistry(metricRegistry); + config.setInitializationFailTimeout(0); + config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + + try (HikariDataSource ds = new HikariDataSource(config)) { + try (Connection connection = ds.getConnection()) { + UtilityElf.quietlySleep(250L); + } + + Histogram histo = metricRegistry.getHistograms(new MetricFilter() { + /** {@inheritDoc} */ + @Override + public boolean matches(String name, Metric metric) + { + return name.equals(MetricRegistry.name("testMetricUsage", "pool", "Usage")); + } + }).values().iterator().next(); + + assertEquals(1, histo.getCount()); + double seventyFifth = histo.getSnapshot().get75thPercentile(); + assertTrue("Seventy-fith percentile less than 250ms: " + seventyFifth, seventyFifth >= 250.0); + } + } + + @Test + public void testMetricRegistrySubclassIsAllowed() + { + try (HikariDataSource ds = newHikariDataSource()) { + ds.setMaximumPoolSize(1); + ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + + ds.setMetricRegistry(new MetricRegistry() { + @Override + public Timer timer(String name) { + return super.timer(name); + } + }); + } + } +} diff --git a/src/test/java/com/zaxxer/hikari/pool/Dropwizard5MetricsTest.java b/src/test/java/com/zaxxer/hikari/pool/Dropwizard5MetricsTest.java new file mode 100644 index 00000000..1d2ff79f --- /dev/null +++ b/src/test/java/com/zaxxer/hikari/pool/Dropwizard5MetricsTest.java @@ -0,0 +1,174 @@ +package com.zaxxer.hikari.pool; + +import java.sql.Connection; +import java.sql.SQLException; + +import com.codahale.metrics.health.HealthCheckRegistry; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import com.zaxxer.hikari.metrics.MetricsTrackerFactory; +import com.zaxxer.hikari.metrics.dropwizard.Dropwizard5MetricsTrackerFactory; +import com.zaxxer.hikari.util.UtilityElf; +import io.dropwizard.metrics5.Histogram; +import io.dropwizard.metrics5.Metric; +import io.dropwizard.metrics5.MetricFilter; +import io.dropwizard.metrics5.MetricName; +import io.dropwizard.metrics5.MetricRegistry; +import io.dropwizard.metrics5.Timer; +import org.junit.Test; + +import static com.zaxxer.hikari.pool.TestElf.newHikariConfig; +import static com.zaxxer.hikari.pool.TestElf.newHikariDataSource; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeFalse; + +/** + * Test HikariCP/Dropwizard 5 metrics integration. + */ +public class Dropwizard5MetricsTest extends TestMetricsBase +{ + @Override + protected MetricsTrackerFactory metricsTrackerFactory(final MetricRegistry metricRegistry) + { + return new Dropwizard5MetricsTrackerFactory(metricRegistry); + } + + @Override + protected MetricRegistry metricRegistry() + { + return new MetricRegistry(); + } + + @Test + public void testSetters1() throws Exception + { + try (HikariDataSource ds = newHikariDataSource()) { + ds.setMaximumPoolSize(1); + ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + + MetricRegistry metricRegistry = metricRegistry(); + + try { + try (Connection connection = ds.getConnection()) { + // close immediately + } + + // After the pool as started, we can only set it once... + ds.setMetricRegistry(metricRegistry); + + // and never again... + ds.setMetricRegistry(metricRegistry); + fail("Should not have been allowed to set registry after pool started"); + } + catch (IllegalStateException ise) { + // pass + } + } + } + + @Test + public void testSetters2() throws Exception + { + try (HikariDataSource ds = newHikariDataSource()) { + ds.setMaximumPoolSize(1); + ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + + MetricRegistry metricRegistry = metricRegistry(); + + ds.setMetricRegistry(metricRegistry); + + // before the pool is started, we can set it any number of times... + ds.setMetricRegistry(metricRegistry); + + try (Connection connection = ds.getConnection()) { + + // after the pool is started, we cannot set it any more + ds.setMetricRegistry(metricRegistry); + fail("Should not have been allowed to set registry after pool started"); + } + catch (IllegalStateException ise) { + // pass + } + } + } + + @Test + public void testMetricWait() throws SQLException + { + MetricRegistry metricRegistry = new MetricRegistry(); + + HikariConfig config = newHikariConfig(); + config.setMinimumIdle(1); + config.setMaximumPoolSize(1); + config.setMetricRegistry(metricRegistry); + config.setInitializationFailTimeout(Long.MAX_VALUE); + config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + + try (HikariDataSource ds = new HikariDataSource(config)) { + ds.getConnection().close(); + + Timer timer = metricRegistry.getTimers(new MetricFilter() { + /** {@inheritDoc} */ + @Override + public boolean matches(MetricName name, Metric metric) + { + return name.equals(MetricRegistry.name("testMetricWait", "pool", "Wait")); + } + }).values().iterator().next(); + + assertEquals(1, timer.getCount()); + assertTrue(timer.getMeanRate() > 0.0); + } + } + + @Test + public void testMetricUsage() throws SQLException + { + assumeFalse(System.getProperty("os.name").contains("Windows")); + MetricRegistry metricRegistry = new MetricRegistry(); + + HikariConfig config = newHikariConfig(); + config.setMinimumIdle(1); + config.setMaximumPoolSize(1); + config.setMetricRegistry(metricRegistry); + config.setInitializationFailTimeout(0); + config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + + try (HikariDataSource ds = new HikariDataSource(config)) { + try (Connection connection = ds.getConnection()) { + UtilityElf.quietlySleep(250L); + } + + Histogram histo = metricRegistry.getHistograms(new MetricFilter() { + /** {@inheritDoc} */ + @Override + public boolean matches(MetricName name, Metric metric) + { + return name.equals(MetricRegistry.name("testMetricUsage", "pool", "Usage")); + } + }).values().iterator().next(); + + assertEquals(1, histo.getCount()); + double seventyFifth = histo.getSnapshot().get75thPercentile(); + assertTrue("Seventy-fith percentile less than 250ms: " + seventyFifth, seventyFifth >= 250.0); + } + } + + @Test + public void testMetricRegistrySubclassIsAllowed() + { + try (HikariDataSource ds = newHikariDataSource()) { + ds.setMaximumPoolSize(1); + ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + + ds.setMetricRegistry(new MetricRegistry() { + @Override + public Timer timer(String name) { + return super.timer(name); + } + }); + } + } +} diff --git a/src/test/java/com/zaxxer/hikari/pool/TestMetrics.java b/src/test/java/com/zaxxer/hikari/pool/TestMetrics.java index 84ad628f..b1e37ca8 100644 --- a/src/test/java/com/zaxxer/hikari/pool/TestMetrics.java +++ b/src/test/java/com/zaxxer/hikari/pool/TestMetrics.java @@ -16,289 +16,18 @@ package com.zaxxer.hikari.pool; -import static com.zaxxer.hikari.pool.TestElf.newHikariConfig; -import static com.zaxxer.hikari.pool.TestElf.newHikariDataSource; -import static com.zaxxer.hikari.util.UtilityElf.quietlySleep; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.junit.Assume.assumeFalse; - -import java.sql.Connection; -import java.sql.SQLException; -import java.util.SortedMap; -import java.util.concurrent.TimeUnit; - +import com.zaxxer.hikari.HikariDataSource; import org.junit.Test; -import com.codahale.metrics.Histogram; -import com.codahale.metrics.Metric; -import com.codahale.metrics.MetricFilter; -import com.codahale.metrics.MetricRegistry; -import com.codahale.metrics.Timer; -import com.codahale.metrics.health.HealthCheck.Result; -import com.codahale.metrics.health.HealthCheckRegistry; -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; -import com.zaxxer.hikari.metrics.MetricsTrackerFactory; -import com.zaxxer.hikari.metrics.dropwizard.CodahaleMetricsTrackerFactory; -import com.zaxxer.hikari.util.UtilityElf; +import static com.zaxxer.hikari.pool.TestElf.newHikariDataSource; /** - * Test HikariCP/CodaHale metrics integration. + * Test HikariCP metrics integration. * * @author Brett Wooldridge */ public class TestMetrics { - @Test - public void testMetricWait() throws SQLException - { - MetricRegistry metricRegistry = new MetricRegistry(); - - HikariConfig config = newHikariConfig(); - config.setMinimumIdle(1); - config.setMaximumPoolSize(1); - config.setMetricRegistry(metricRegistry); - config.setInitializationFailTimeout(Long.MAX_VALUE); - config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); - - try (HikariDataSource ds = new HikariDataSource(config)) { - ds.getConnection().close(); - - Timer timer = metricRegistry.getTimers(new MetricFilter() { - /** {@inheritDoc} */ - @Override - public boolean matches(String name, Metric metric) - { - return name.equals(MetricRegistry.name("testMetricWait", "pool", "Wait")); - } - }).values().iterator().next(); - - assertEquals(1, timer.getCount()); - assertTrue(timer.getMeanRate() > 0.0); - } - } - - @Test - public void testMetricUsage() throws SQLException - { - assumeFalse(System.getProperty("os.name").contains("Windows")); - MetricRegistry metricRegistry = new MetricRegistry(); - - HikariConfig config = newHikariConfig(); - config.setMinimumIdle(1); - config.setMaximumPoolSize(1); - config.setMetricRegistry(metricRegistry); - config.setInitializationFailTimeout(0); - config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); - - try (HikariDataSource ds = new HikariDataSource(config)) { - try (Connection connection = ds.getConnection()) { - UtilityElf.quietlySleep(250L); - } - - Histogram histo = metricRegistry.getHistograms(new MetricFilter() { - /** {@inheritDoc} */ - @Override - public boolean matches(String name, Metric metric) - { - return name.equals(MetricRegistry.name("testMetricUsage", "pool", "Usage")); - } - }).values().iterator().next(); - - assertEquals(1, histo.getCount()); - double seventyFifth = histo.getSnapshot().get75thPercentile(); - assertTrue("Seventy-fith percentile less than 250ms: " + seventyFifth, seventyFifth >= 250.0); - } - } - - @Test - public void testHealthChecks() throws Exception - { - MetricRegistry metricRegistry = new MetricRegistry(); - HealthCheckRegistry healthRegistry = new HealthCheckRegistry(); - - HikariConfig config = newHikariConfig(); - config.setMaximumPoolSize(10); - config.setMetricRegistry(metricRegistry); - config.setHealthCheckRegistry(healthRegistry); - config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); - config.addHealthCheckProperty("connectivityCheckTimeoutMs", "1000"); - config.addHealthCheckProperty("expected99thPercentileMs", "100"); - - try (HikariDataSource ds = new HikariDataSource(config)) { - quietlySleep(TimeUnit.SECONDS.toMillis(2)); - - try (Connection connection = ds.getConnection()) { - // close immediately - } - - try (Connection connection = ds.getConnection()) { - // close immediately - } - - SortedMap healthChecks = healthRegistry.runHealthChecks(); - - Result connectivityResult = healthChecks.get("testHealthChecks.pool.ConnectivityCheck"); - assertTrue(connectivityResult.isHealthy()); - - Result slaResult = healthChecks.get("testHealthChecks.pool.Connection99Percent"); - assertTrue(slaResult.isHealthy()); - } - } - - @Test - public void testSetters1() throws Exception - { - try (HikariDataSource ds = newHikariDataSource()) { - ds.setMaximumPoolSize(1); - ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); - - MetricRegistry metricRegistry = new MetricRegistry(); - HealthCheckRegistry healthRegistry = new HealthCheckRegistry(); - - try { - try (Connection connection = ds.getConnection()) { - // close immediately - } - - // After the pool as started, we can only set them once... - ds.setMetricRegistry(metricRegistry); - ds.setHealthCheckRegistry(healthRegistry); - - // and never again... - ds.setMetricRegistry(metricRegistry); - fail("Should not have been allowed to set registry after pool started"); - } - catch (IllegalStateException ise) { - // pass - try { - ds.setHealthCheckRegistry(healthRegistry); - fail("Should not have been allowed to set registry after pool started"); - } - catch (IllegalStateException ise2) { - // pass - } - } - } - } - - @Test - public void testSetters2() throws Exception - { - try (HikariDataSource ds = newHikariDataSource()) { - ds.setMaximumPoolSize(1); - ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); - - MetricRegistry metricRegistry = new MetricRegistry(); - HealthCheckRegistry healthRegistry = new HealthCheckRegistry(); - - ds.setMetricRegistry(metricRegistry); - ds.setHealthCheckRegistry(healthRegistry); - - // before the pool is started, we can set it any number of times... - ds.setMetricRegistry(metricRegistry); - ds.setHealthCheckRegistry(healthRegistry); - - try (Connection connection = ds.getConnection()) { - - // after the pool is started, we cannot set it any more - ds.setMetricRegistry(metricRegistry); - fail("Should not have been allowed to set registry after pool started"); - } - catch (IllegalStateException ise) { - // pass - } - } - } - - @Test - public void testSetters3() throws Exception - { - try (HikariDataSource ds = newHikariDataSource()) { - ds.setMaximumPoolSize(1); - ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); - - MetricRegistry metricRegistry = new MetricRegistry(); - MetricsTrackerFactory metricsTrackerFactory = new CodahaleMetricsTrackerFactory(metricRegistry); - - try (Connection connection = ds.getConnection()) { - - // After the pool as started, we can only set them once... - ds.setMetricsTrackerFactory(metricsTrackerFactory); - - // and never again... - ds.setMetricsTrackerFactory(metricsTrackerFactory); - fail("Should not have been allowed to set metricsTrackerFactory after pool started"); - } - catch (IllegalStateException ise) { - // pass - try { - // and never again... (even when calling another method) - ds.setMetricRegistry(metricRegistry); - fail("Should not have been allowed to set registry after pool started"); - } - catch (IllegalStateException ise2) { - // pass - } - } - } - } - - @Test - public void testSetters4() throws Exception - { - try (HikariDataSource ds = newHikariDataSource()) { - ds.setMaximumPoolSize(1); - ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); - - MetricRegistry metricRegistry = new MetricRegistry(); - - // before the pool is started, we can set it any number of times using either setter - ds.setMetricRegistry(metricRegistry); - ds.setMetricRegistry(metricRegistry); - ds.setMetricRegistry(metricRegistry); - - try (Connection connection = ds.getConnection()) { - - // after the pool is started, we cannot set it any more - ds.setMetricRegistry(metricRegistry); - fail("Should not have been allowed to set registry after pool started"); - } - catch (IllegalStateException ise) { - // pass - } - } - } - - @Test - public void testSetters5() throws Exception - { - try (HikariDataSource ds = newHikariDataSource()) { - ds.setMaximumPoolSize(1); - ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); - - MetricRegistry metricRegistry = new MetricRegistry(); - MetricsTrackerFactory metricsTrackerFactory = new CodahaleMetricsTrackerFactory(metricRegistry); - - // before the pool is started, we can set it any number of times using either setter - ds.setMetricsTrackerFactory(metricsTrackerFactory); - ds.setMetricsTrackerFactory(metricsTrackerFactory); - ds.setMetricsTrackerFactory(metricsTrackerFactory); - - try (Connection connection = ds.getConnection()) { - - // after the pool is started, we cannot set it any more - ds.setMetricsTrackerFactory(metricsTrackerFactory); - fail("Should not have been allowed to set registry factory after pool started"); - } - catch (IllegalStateException ise) { - // pass - } - } - } - @Test(expected = IllegalArgumentException.class) public void testFakeMetricRegistryThrowsIllegalArgumentException() { @@ -313,20 +42,4 @@ public class TestMetrics } private static class FakeMetricRegistry {} - - @Test - public void testMetricRegistrySubclassIsAllowed() - { - try (HikariDataSource ds = newHikariDataSource()) { - ds.setMaximumPoolSize(1); - ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); - - ds.setMetricRegistry(new MetricRegistry() { - @Override - public Timer timer(String name) { - return super.timer(name); - } - }); - } - } } diff --git a/src/test/java/com/zaxxer/hikari/pool/TestMetricsBase.java b/src/test/java/com/zaxxer/hikari/pool/TestMetricsBase.java new file mode 100644 index 00000000..bc2adc22 --- /dev/null +++ b/src/test/java/com/zaxxer/hikari/pool/TestMetricsBase.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2013, 2014 Brett Wooldridge + * + * Licensed 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 com.zaxxer.hikari.pool; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.SortedMap; +import java.util.concurrent.TimeUnit; + +import com.codahale.metrics.Histogram; +import com.codahale.metrics.Metric; +import com.codahale.metrics.MetricFilter; +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.Timer; +import com.codahale.metrics.health.HealthCheck.Result; +import com.codahale.metrics.health.HealthCheckRegistry; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import com.zaxxer.hikari.metrics.MetricsTrackerFactory; +import com.zaxxer.hikari.metrics.dropwizard.CodahaleMetricsTrackerFactory; +import com.zaxxer.hikari.util.UtilityElf; +import org.junit.Test; + +import static com.zaxxer.hikari.pool.TestElf.newHikariConfig; +import static com.zaxxer.hikari.pool.TestElf.newHikariDataSource; +import static com.zaxxer.hikari.util.UtilityElf.quietlySleep; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeFalse; + +/** + * Test HikariCP/CodaHale/Dropwizard 5 metrics integration. + * + *

+ * This base test class contains tests common to Codahale metrics testing (pre-5) and Dropwizard 5 metrics testing. + * That's the idea behind the registry type parameterization and abstract methods. + * Include health checks when implemented for Dropwizard 5. + * There's still a bit of duplication between the extending classes. + * + * @author Brett Wooldridge + */ +abstract class TestMetricsBase +{ + protected abstract MetricsTrackerFactory metricsTrackerFactory(M metricRegistry); + protected abstract M metricRegistry(); + + @Test + public void testSetters3() throws Exception + { + try (HikariDataSource ds = newHikariDataSource()) { + ds.setMaximumPoolSize(1); + ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + + M metricRegistry = metricRegistry(); + MetricsTrackerFactory metricsTrackerFactory = metricsTrackerFactory(metricRegistry); + + try (Connection connection = ds.getConnection()) { + + // After the pool as started, we can only set them once... + ds.setMetricsTrackerFactory(metricsTrackerFactory); + + // and never again... + ds.setMetricsTrackerFactory(metricsTrackerFactory); + fail("Should not have been allowed to set metricsTrackerFactory after pool started"); + } + catch (IllegalStateException ise) { + // pass + try { + // and never again... (even when calling another method) + ds.setMetricRegistry(metricRegistry); + fail("Should not have been allowed to set registry after pool started"); + } + catch (IllegalStateException ise2) { + // pass + } + } + } + } + + @Test + public void testSetters4() throws Exception + { + try (HikariDataSource ds = newHikariDataSource()) { + ds.setMaximumPoolSize(1); + ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + + M metricRegistry = metricRegistry(); + + // before the pool is started, we can set it any number of times using either setter + ds.setMetricRegistry(metricRegistry); + ds.setMetricRegistry(metricRegistry); + ds.setMetricRegistry(metricRegistry); + + try (Connection connection = ds.getConnection()) { + + // after the pool is started, we cannot set it any more + ds.setMetricRegistry(metricRegistry); + fail("Should not have been allowed to set registry after pool started"); + } + catch (IllegalStateException ise) { + // pass + } + } + } + + @Test + public void testSetters5() throws Exception + { + try (HikariDataSource ds = newHikariDataSource()) { + ds.setMaximumPoolSize(1); + ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + + M metricRegistry = metricRegistry(); + MetricsTrackerFactory metricsTrackerFactory = metricsTrackerFactory(metricRegistry); + + // before the pool is started, we can set it any number of times using either setter + ds.setMetricsTrackerFactory(metricsTrackerFactory); + ds.setMetricsTrackerFactory(metricsTrackerFactory); + ds.setMetricsTrackerFactory(metricsTrackerFactory); + + try (Connection connection = ds.getConnection()) { + + // after the pool is started, we cannot set it any more + ds.setMetricsTrackerFactory(metricsTrackerFactory); + fail("Should not have been allowed to set registry factory after pool started"); + } + catch (IllegalStateException ise) { + // pass + } + } + } +}