Merge branch 'wholesail-dropwizard5-metrics' into dev
commit
f6efe91bd1
@ -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<Integer>) poolStats::getTotalConnections);
|
||||||
|
|
||||||
|
registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_IDLE_CONNECTIONS),
|
||||||
|
(Gauge<Integer>) poolStats::getIdleConnections);
|
||||||
|
|
||||||
|
registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_ACTIVE_CONNECTIONS),
|
||||||
|
(Gauge<Integer>) poolStats::getActiveConnections);
|
||||||
|
|
||||||
|
registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_PENDING_CONNECTIONS),
|
||||||
|
(Gauge<Integer>) poolStats::getPendingThreads);
|
||||||
|
|
||||||
|
registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_MAX_CONNECTIONS),
|
||||||
|
(Gauge<Integer>) poolStats::getMaxConnections);
|
||||||
|
|
||||||
|
registry.register(MetricRegistry.name(poolName, METRIC_CATEGORY, METRIC_NAME_MIN_CONNECTIONS),
|
||||||
|
(Gauge<Integer>) 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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";
|
||||||
|
}
|
@ -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"));
|
||||||
|
}
|
||||||
|
}
|
@ -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<MetricRegistry>
|
||||||
|
{
|
||||||
|
@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<String, HealthCheck.Result> 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<MetricRegistry>
|
||||||
|
{
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 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<M>
|
||||||
|
{
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue