Start rework of metrics handling.

pull/192/head
Brett Wooldridge 11 years ago
parent 0f67b83697
commit 0aa14d1d9b

@ -35,6 +35,8 @@ import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.codahale.metrics.MetricRegistry;
import com.zaxxer.hikari.metrics.CodaHaleShim;
import com.zaxxer.hikari.proxy.JavassistProxyFactory;
import com.zaxxer.hikari.util.PoolUtilities;
import com.zaxxer.hikari.util.PropertyBeanSetter;
@ -69,7 +71,6 @@ public class HikariConfig implements HikariConfigMBean
private String dataSourceJndiName;
private String driverClassName;
private String jdbcUrl;
private String metricsTrackerClassName;
private String password;
private String poolName;
private String transactionIsolationName;
@ -79,15 +80,16 @@ public class HikariConfig implements HikariConfigMBean
private boolean isInitializationFailFast;
private boolean isJdbc4connectionTest;
private boolean isIsolateInternalQueries;
private boolean isRecordMetrics;
private boolean isRegisterMbeans;
private DataSource dataSource;
private Properties dataSourceProperties;
private IConnectionCustomizer customizer;
private ThreadFactory threadFactory;
private MetricRegistry metricRegistry;
static {
JavassistProxyFactory.initialize();
CodaHaleShim.initialize();
}
/**
@ -105,8 +107,6 @@ public class HikariConfig implements HikariConfigMBean
minIdle = -1;
maxPoolSize = 10;
maxLifetime = MAX_LIFETIME;
isRecordMetrics = false;
metricsTrackerClassName = "com.zaxxer.hikari.metrics.CodaHaleMetricsTracker";
customizer = new IConnectionCustomizer() {
@Override
public void customize(Connection connection) throws SQLException
@ -433,29 +433,34 @@ public class HikariConfig implements HikariConfigMBean
this.isJdbc4connectionTest = useIsValid;
}
public boolean isReadOnly()
/**
* Get the Codahale MetricRegistry, could be null.
*
* @return the codahale MetricRegistry instance
*/
public MetricRegistry getMetricRegistry()
{
return isReadOnly;
return metricRegistry;
}
public void setReadOnly(boolean readOnly)
/**
* Set a Codahale MetricRegistry to use for HikariCP.
*
* @param metricRegistry the Codahale MetricRegistry to set
*/
public void setMetricRegistry(MetricRegistry metricRegistry)
{
this.isReadOnly = readOnly;
this.metricRegistry = metricRegistry;
}
public boolean isRecordMetrics()
public boolean isReadOnly()
{
return isRecordMetrics;
return isReadOnly;
}
/**
* Currently not supported.
* @param recordMetrics <code>true</code> if metrics should be recorded
*/
@Deprecated
public void setRecordMetrics(boolean recordMetrics)
public void setReadOnly(boolean readOnly)
{
this.isRecordMetrics = recordMetrics;
this.isReadOnly = readOnly;
}
public boolean isRegisterMbeans()
@ -513,28 +518,6 @@ public class HikariConfig implements HikariConfigMBean
this.maxPoolSize = maxPoolSize;
}
/**
* Get the name of the class that implements the IMetricsTracker interface to
* be used for metrics tracking.
*
* @return the name of the class that implements the IMetricsTracker interface
*/
public String getMetricsTrackerClassName()
{
return metricsTrackerClassName;
}
/**
* Set the name of the class that implements the IMetricsTracker interface to
* be used for metrics tracking.
*
* @param className the name of the class that implements the IMetricsTracker interface
*/
public void setMetricsTrackerClassName(String className)
{
this.metricsTrackerClassName = className;
}
/** {@inheritDoc} */
@Override
public int getMinimumIdle()

@ -25,15 +25,13 @@ import com.zaxxer.hikari.util.PoolUtilities;
public final class CodaHaleMetricsTracker extends MetricsTracker
{
private MetricRegistry registry;
private final Timer connectionObtainTimer;
private final Histogram connectionUsage;
public CodaHaleMetricsTracker(final HikariPool pool)
public CodaHaleMetricsTracker(final HikariPool pool, final MetricRegistry registry)
{
super(pool);
registry = new MetricRegistry();
connectionObtainTimer = registry.timer(MetricRegistry.name(pool.getConfiguration().getPoolName(), "-connection", "Wait"));
connectionUsage = registry.histogram(MetricRegistry.name(pool.getConfiguration().getPoolName(), "-connection", "Usage"));
}

@ -0,0 +1,92 @@
/*
* Copyright (C) 2013 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.metrics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.LoaderClassPath;
import javassist.Modifier;
/**
*
* @author Brett Wooldridge
*/
public class CodaHaleShim
{
private static final Logger LOGGER = LoggerFactory.getLogger(CodaHaleShim.class);
static
{
CodaHaleShim codaHaleShim = new CodaHaleShim();
codaHaleShim.loadOrShimCodahale();
}
private CodaHaleShim()
{
// empty
}
/**
* Simply invoking this method causes the initialization of this class. All work
* by this class is performed in static initialization.
*/
public static void initialize()
{
// no-op
}
/**
*
*/
private void loadOrShimCodahale()
{
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
try {
CodaHaleShim.class.getClassLoader().loadClass("com.codahale.metrics.MetricRegistry");
}
catch (ClassNotFoundException e) {
// OK, it is not present, we have to generate a shim
ClassPool classPool = new ClassPool();
classPool.appendClassPath(new LoaderClassPath(this.getClass().getClassLoader()));
try {
CtClass targetCt = classPool.makeClass("com.codahale.metrics.MetricRegistry");
targetCt.setModifiers(Modifier.PUBLIC | Modifier.FINAL);
CtConstructor constructorCt = new CtConstructor(null, targetCt);
constructorCt.setModifiers(Modifier.PUBLIC);
constructorCt.setBody("{ throw new RuntimeException(\"HikariCP Codahale shim says: Codahale metrics library is required but was not found in the classpath\"); }");
targetCt.addConstructor(constructorCt);
targetCt.toClass(classPool.getClassLoader(), getClass().getProtectionDomain());
}
catch (CannotCompileException cce) {
LOGGER.error("Cannot generate CodaHale metrics shim", cce);
throw new RuntimeException(cce);
}
}
finally {
Thread.currentThread().setContextClassLoader(contextClassLoader);
}
}
}

@ -1,37 +0,0 @@
/*
* Copyright (C) 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.metrics;
import com.zaxxer.hikari.pool.HikariPool;
import com.zaxxer.hikari.util.PoolUtilities;
/**
*
* @author Brett Wooldridge
*/
public final class MetricsFactory
{
private MetricsFactory()
{
// private contructor
}
public static final IMetricsTracker createMetricsTracker(String metricsClassName, HikariPool pool)
{
return PoolUtilities.createInstance(metricsClassName, IMetricsTracker.class, pool);
}
}

@ -48,9 +48,9 @@ import org.slf4j.LoggerFactory;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.IConnectionCustomizer;
import com.zaxxer.hikari.metrics.CodaHaleMetricsTracker;
import com.zaxxer.hikari.metrics.IMetricsTracker;
import com.zaxxer.hikari.metrics.IMetricsTracker.MetricsContext;
import com.zaxxer.hikari.metrics.MetricsFactory;
import com.zaxxer.hikari.metrics.MetricsTracker;
import com.zaxxer.hikari.proxy.IHikariConnectionProxy;
import com.zaxxer.hikari.proxy.ProxyFactory;
@ -140,8 +140,8 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
this.leakDetectionThreshold = configuration.getLeakDetectionThreshold();
this.isIsolateInternalQueries = configuration.isIsolateInternalQueries();
this.isRecordMetrics = configuration.isRecordMetrics();
this.metricsTracker = MetricsFactory.createMetricsTracker((isRecordMetrics ? configuration.getMetricsTrackerClassName() : "com.zaxxer.hikari.metrics.MetricsTracker"), this);
this.isRecordMetrics = configuration.getMetricRegistry() != null;
this.metricsTracker = (isRecordMetrics ? new CodaHaleMetricsTracker(this, configuration.getMetricRegistry()) : new MetricsTracker(this));
this.dataSource = PoolUtilities.initializeDataSource(configuration.getDataSourceClassName(), configuration.getDataSource(), configuration.getDataSourceProperties(), configuration.getJdbcUrl(), username, password);

@ -41,7 +41,6 @@ import com.zaxxer.hikari.util.PoolUtilities;
*/
public class TestConnections
{
@SuppressWarnings("deprecation")
@Test
public void testCreate() throws SQLException
{
@ -51,7 +50,6 @@ public class TestConnections
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setConnectionInitSql("SELECT 1");
config.setRecordMetrics(true);
config.setReadOnly(true);
config.setLeakDetectionThreshold(TimeUnit.SECONDS.toMillis(60));
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");

@ -35,6 +35,8 @@ import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.codahale.metrics.MetricRegistry;
import com.zaxxer.hikari.metrics.CodaHaleShim;
import com.zaxxer.hikari.proxy.JavassistProxyFactory;
import com.zaxxer.hikari.util.PoolUtilities;
import com.zaxxer.hikari.util.PropertyBeanSetter;
@ -69,7 +71,6 @@ public class HikariConfig implements HikariConfigMBean
private String dataSourceJndiName;
private String driverClassName;
private String jdbcUrl;
private String metricsTrackerClassName;
private String password;
private String poolName;
private String transactionIsolationName;
@ -79,15 +80,16 @@ public class HikariConfig implements HikariConfigMBean
private boolean isInitializationFailFast;
private boolean isJdbc4connectionTest;
private boolean isIsolateInternalQueries;
private boolean isRecordMetrics;
private boolean isRegisterMbeans;
private DataSource dataSource;
private Properties dataSourceProperties;
private IConnectionCustomizer customizer;
private ThreadFactory threadFactory;
private MetricRegistry metricRegistry;
static {
JavassistProxyFactory.initialize();
CodaHaleShim.initialize();
}
/**
@ -105,8 +107,6 @@ public class HikariConfig implements HikariConfigMBean
minIdle = -1;
maxPoolSize = 10;
maxLifetime = MAX_LIFETIME;
isRecordMetrics = false;
metricsTrackerClassName = "com.zaxxer.hikari.metrics.CodaHaleMetricsTracker";
customizer = new IConnectionCustomizer() {
@Override
public void customize(Connection connection) throws SQLException
@ -433,29 +433,34 @@ public class HikariConfig implements HikariConfigMBean
this.isJdbc4connectionTest = useIsValid;
}
public boolean isReadOnly()
/**
* Get the Codahale MetricRegistry, could be null.
*
* @return the codahale MetricRegistry instance
*/
public MetricRegistry getMetricRegistry()
{
return isReadOnly;
return metricRegistry;
}
public void setReadOnly(boolean readOnly)
/**
* Set a Codahale MetricRegistry to use for HikariCP.
*
* @param metricRegistry the Codahale MetricRegistry to set
*/
public void setMetricRegistry(MetricRegistry metricRegistry)
{
this.isReadOnly = readOnly;
this.metricRegistry = metricRegistry;
}
public boolean isRecordMetrics()
public boolean isReadOnly()
{
return isRecordMetrics;
return isReadOnly;
}
/**
* Currently not supported.
* @param recordMetrics <code>true</code> if metrics should be recorded
*/
@Deprecated
public void setRecordMetrics(boolean recordMetrics)
public void setReadOnly(boolean readOnly)
{
this.isRecordMetrics = recordMetrics;
this.isReadOnly = readOnly;
}
public boolean isRegisterMbeans()
@ -513,28 +518,6 @@ public class HikariConfig implements HikariConfigMBean
this.maxPoolSize = maxPoolSize;
}
/**
* Get the name of the class that implements the IMetricsTracker interface to
* be used for metrics tracking.
*
* @return the name of the class that implements the IMetricsTracker interface
*/
public String getMetricsTrackerClassName()
{
return metricsTrackerClassName;
}
/**
* Set the name of the class that implements the IMetricsTracker interface to
* be used for metrics tracking.
*
* @param className the name of the class that implements the IMetricsTracker interface
*/
public void setMetricsTrackerClassName(String className)
{
this.metricsTrackerClassName = className;
}
/** {@inheritDoc} */
@Override
public int getMinimumIdle()

@ -25,15 +25,13 @@ import com.zaxxer.hikari.util.PoolUtilities;
public final class CodaHaleMetricsTracker extends MetricsTracker
{
private MetricRegistry registry;
private final Timer connectionObtainTimer;
private final Histogram connectionUsage;
public CodaHaleMetricsTracker(final HikariPool pool)
public CodaHaleMetricsTracker(final HikariPool pool, final MetricRegistry registry)
{
super(pool);
registry = new MetricRegistry();
connectionObtainTimer = registry.timer(MetricRegistry.name(pool.getConfiguration().getPoolName(), "-connection", "Wait"));
connectionUsage = registry.histogram(MetricRegistry.name(pool.getConfiguration().getPoolName(), "-connection", "Usage"));
}

@ -0,0 +1,92 @@
/*
* Copyright (C) 2013 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.metrics;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.LoaderClassPath;
import javassist.Modifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Brett Wooldridge
*/
public class CodaHaleShim
{
private static final Logger LOGGER = LoggerFactory.getLogger(CodaHaleShim.class);
static
{
CodaHaleShim codaHaleShim = new CodaHaleShim();
codaHaleShim.loadOrShimCodahale();
}
private CodaHaleShim()
{
// empty
}
/**
* Simply invoking this method causes the initialization of this class. All work
* by this class is performed in static initialization.
*/
public static void initialize()
{
// no-op
}
/**
*
*/
private void loadOrShimCodahale()
{
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
try {
CodaHaleShim.class.getClassLoader().loadClass("com.codahale.metrics.MetricRegistry");
}
catch (ClassNotFoundException e) {
// OK, it is not present, we have to generate a shim
ClassPool classPool = new ClassPool();
classPool.appendClassPath(new LoaderClassPath(this.getClass().getClassLoader()));
try {
CtClass targetCt = classPool.makeClass("com.codahale.metrics.MetricRegistry");
targetCt.setModifiers(Modifier.PUBLIC | Modifier.FINAL);
CtConstructor constructorCt = new CtConstructor(null, targetCt);
constructorCt.setModifiers(Modifier.PUBLIC);
constructorCt.setBody("{ throw new RuntimeException(\"HikariCP Codahale shim says: Codahale metrics library is required but was not found in the classpath\"); }");
targetCt.addConstructor(constructorCt);
targetCt.toClass(classPool.getClassLoader(), getClass().getProtectionDomain());
}
catch (CannotCompileException cce) {
LOGGER.error("Cannot generate CodaHale metrics shim", cce);
throw new RuntimeException(cce);
}
}
finally {
Thread.currentThread().setContextClassLoader(contextClassLoader);
}
}
}

@ -1,37 +0,0 @@
/*
* Copyright (C) 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.metrics;
import com.zaxxer.hikari.pool.HikariPool;
import com.zaxxer.hikari.util.PoolUtilities;
/**
*
* @author Brett Wooldridge
*/
public final class MetricsFactory
{
private MetricsFactory()
{
// private contructor
}
public static final IMetricsTracker createMetricsTracker(String metricsClassName, HikariPool pool)
{
return PoolUtilities.createInstance(metricsClassName, IMetricsTracker.class, pool);
}
}

@ -47,9 +47,9 @@ import org.slf4j.LoggerFactory;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.IConnectionCustomizer;
import com.zaxxer.hikari.metrics.CodaHaleMetricsTracker;
import com.zaxxer.hikari.metrics.IMetricsTracker;
import com.zaxxer.hikari.metrics.IMetricsTracker.MetricsContext;
import com.zaxxer.hikari.metrics.MetricsFactory;
import com.zaxxer.hikari.metrics.MetricsTracker;
import com.zaxxer.hikari.proxy.IHikariConnectionProxy;
import com.zaxxer.hikari.proxy.ProxyFactory;
@ -139,8 +139,8 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener
this.leakDetectionThreshold = configuration.getLeakDetectionThreshold();
this.isIsolateInternalQueries = configuration.isIsolateInternalQueries();
this.isRecordMetrics = configuration.isRecordMetrics();
this.metricsTracker = MetricsFactory.createMetricsTracker((isRecordMetrics ? configuration.getMetricsTrackerClassName() : "com.zaxxer.hikari.metrics.MetricsTracker"), this);
this.isRecordMetrics = configuration.getMetricRegistry() != null;
this.metricsTracker = (isRecordMetrics ? new CodaHaleMetricsTracker(this, configuration.getMetricRegistry()) : new MetricsTracker(this));
this.dataSource = PoolUtilities.initializeDataSource(configuration.getDataSourceClassName(), configuration.getDataSource(), configuration.getDataSourceProperties(), configuration.getJdbcUrl(), username, password);

@ -41,7 +41,6 @@ import com.zaxxer.hikari.util.PoolUtilities;
*/
public class TestConnections
{
@SuppressWarnings("deprecation")
@Test
public void testCreate() throws SQLException
{
@ -51,7 +50,6 @@ public class TestConnections
config.setInitializationFailFast(true);
config.setConnectionTestQuery("VALUES 1");
config.setConnectionInitSql("SELECT 1");
config.setRecordMetrics(true);
config.setReadOnly(true);
config.setLeakDetectionThreshold(TimeUnit.SECONDS.toMillis(60));
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");

Loading…
Cancel
Save