Allowing anonymous subclasses of MetricRegistry. Also changing checks for metrics libraries from classname contains to assignableFrom the metrics class (#1089)

pull/1091/head
NersesAM 7 years ago committed by Brett Wooldridge
parent 3eb0bc72b8
commit 91bd7dfb33

@ -42,6 +42,7 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadLocalRandom;
import static com.zaxxer.hikari.util.UtilityElf.getNullIfEmpty;
import static com.zaxxer.hikari.util.UtilityElf.safeIsAssignableFrom;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
@ -758,8 +759,8 @@ public class HikariConfig implements HikariConfigMXBean
if (metricRegistry != null) {
metricRegistry = getObjectOrPerformJndiLookup(metricRegistry);
if (!(metricRegistry.getClass().getName().contains("MetricRegistry"))
&& !(metricRegistry.getClass().getName().contains("MeterRegistry"))) {
if (!safeIsAssignableFrom(metricRegistry, "com.codahale.metrics.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");
}
}

@ -57,6 +57,7 @@ import static com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry.STATE_IN_
import static com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry.STATE_NOT_IN_USE;
import static com.zaxxer.hikari.util.UtilityElf.createThreadPoolExecutor;
import static com.zaxxer.hikari.util.UtilityElf.quietlySleep;
import static com.zaxxer.hikari.util.UtilityElf.safeIsAssignableFrom;
import static java.util.Collections.unmodifiableCollection;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
@ -272,10 +273,10 @@ public final class HikariPool extends PoolBase implements HikariPoolMXBean, IBag
*/
public void setMetricRegistry(Object metricRegistry)
{
if (metricRegistry != null && metricRegistry.getClass().getName().contains("MetricRegistry")) {
if (metricRegistry != null && safeIsAssignableFrom(metricRegistry, "com.codahale.metrics.MetricRegistry")) {
setMetricsTrackerFactory(new CodahaleMetricsTrackerFactory((MetricRegistry) metricRegistry));
}
else if (metricRegistry != null && metricRegistry.getClass().getName().contains("MeterRegistry")) {
else if (metricRegistry != null && safeIsAssignableFrom(metricRegistry, "io.micrometer.core.instrument.MeterRegistry")) {
setMetricsTrackerFactory(new MicrometerMetricsTrackerFactory((MeterRegistry) metricRegistry));
}
else {

@ -65,6 +65,21 @@ public final class UtilityElf
}
}
/**
* Checks whether an object is an instance of given type without throwing exception when the class is not loaded.
* @param obj the object to check
* @param className String class
* @return true if object is assignable from the type, false otherwise or when the class cannot be loaded
*/
public static boolean safeIsAssignableFrom(Object obj, String className) {
try {
Class<?> clazz = Class.forName(className);
return clazz.isAssignableFrom(obj.getClass());
} catch (ClassNotFoundException ignored) {
return false;
}
}
/**
* Create and instance of the specified class using the constructor matching the specified
* arguments.

@ -298,4 +298,35 @@ public class TestMetrics
}
}
}
@Test(expected = IllegalArgumentException.class)
public void testFakeMetricRegistryThrowsIllegalArgumentException()
{
try (HikariDataSource ds = newHikariDataSource()) {
ds.setMaximumPoolSize(1);
ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");
FakeMetricRegistry metricRegistry = new FakeMetricRegistry();
ds.setMetricRegistry(metricRegistry);
}
}
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);
}
});
}
}
}

Loading…
Cancel
Save