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