From 83b2a6939bae4707c5e0e4ac018e5f6069dc259c Mon Sep 17 00:00:00 2001 From: Brett Wooldridge Date: Wed, 1 Oct 2014 13:13:00 +0900 Subject: [PATCH] Expose metrics through the HikariDataSource. --- .../com/zaxxer/hikari/HikariDataSource.java | 13 ++++++ .../metrics/CodaHaleMetricsTracker.java | 26 ++++++++--- .../hikari/metrics/IMetricsTracker.java | 32 +++++++++++++- .../zaxxer/hikari/metrics/MetricsFactory.java | 5 ++- .../zaxxer/hikari/metrics/MetricsTracker.java | 43 ++++++++++++++++--- .../com/zaxxer/hikari/pool/HikariPool.java | 22 +++++++++- .../com/zaxxer/hikari/HikariDataSource.java | 13 ++++++ .../metrics/CodaHaleMetricsTracker.java | 20 +++++++-- .../hikari/metrics/IMetricsTracker.java | 32 +++++++++++++- .../zaxxer/hikari/metrics/MetricsFactory.java | 5 ++- .../zaxxer/hikari/metrics/MetricsTracker.java | 43 ++++++++++++++++--- .../com/zaxxer/hikari/pool/HikariPool.java | 24 ++++++++++- 12 files changed, 248 insertions(+), 30 deletions(-) diff --git a/hikaricp-java6/src/main/java/com/zaxxer/hikari/HikariDataSource.java b/hikaricp-java6/src/main/java/com/zaxxer/hikari/HikariDataSource.java index 0e6b50ef..5f676d1a 100644 --- a/hikaricp-java6/src/main/java/com/zaxxer/hikari/HikariDataSource.java +++ b/hikaricp-java6/src/main/java/com/zaxxer/hikari/HikariDataSource.java @@ -29,6 +29,7 @@ import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.zaxxer.hikari.metrics.IMetricsTracker; import com.zaxxer.hikari.pool.HikariPool; import com.zaxxer.hikari.proxy.IHikariConnectionProxy; import com.zaxxer.hikari.util.DriverDataSource; @@ -215,6 +216,18 @@ public class HikariDataSource extends HikariConfig implements DataSource, Closea } } + /** + * Get the metrics tracker associated with this DataSource. If metrics collection is + * disabled, the resulting object will provide no meaning data or return null from + * some APIs. + * + * @return the metrics tracker for this DataSource + */ + public IMetricsTracker getMetricsTracker() + { + return (pool != null ? pool.getMetricsTracker() : null); + } + /** * close() and shutdown() are synonymous. */ diff --git a/hikaricp-java6/src/main/java/com/zaxxer/hikari/metrics/CodaHaleMetricsTracker.java b/hikaricp-java6/src/main/java/com/zaxxer/hikari/metrics/CodaHaleMetricsTracker.java index aca55fb1..64b2a227 100644 --- a/hikaricp-java6/src/main/java/com/zaxxer/hikari/metrics/CodaHaleMetricsTracker.java +++ b/hikaricp-java6/src/main/java/com/zaxxer/hikari/metrics/CodaHaleMetricsTracker.java @@ -24,31 +24,45 @@ import com.zaxxer.hikari.pool.HikariPool; public final class CodaHaleMetricsTracker extends MetricsTracker { private MetricRegistry registry; - private Timer connectionObtainTimer; - private Histogram connectionUsage; + private final Timer connectionObtainTimer; + private final Histogram connectionUsage; - public CodaHaleMetricsTracker(String poolName) + public CodaHaleMetricsTracker(final HikariPool pool) { + super(pool); + registry = new MetricRegistry(); - connectionObtainTimer = registry.timer(MetricRegistry.name(HikariPool.class, "connection", "wait")); - connectionUsage = registry.histogram(MetricRegistry.name(HikariPool.class, "connection", "usage")); + connectionObtainTimer = registry.timer(MetricRegistry.name(HikariPool.class, pool.getConfiguration().getPoolName() + "-connection", "wait")); + connectionUsage = registry.histogram(MetricRegistry.name(HikariPool.class, pool.getConfiguration().getPoolName() + "-connection", "usage")); } + /** {@inheritDoc} */ @Override public Context recordConnectionRequest(long requestTime) { return new Context(connectionObtainTimer); } + /** {@inheritDoc} */ @Override public void recordConnectionUsage(long usageMilleseconds) { connectionUsage.update(usageMilleseconds); } + public Timer getConnectionAcquisitionTimer() + { + return connectionObtainTimer; + } + + public Histogram getConnectionDurationHistogram() + { + return connectionUsage; + } + public static final class Context extends MetricsContext { - Timer.Context innerContext; + final Timer.Context innerContext; Context(Timer timer) { diff --git a/hikaricp-java6/src/main/java/com/zaxxer/hikari/metrics/IMetricsTracker.java b/hikaricp-java6/src/main/java/com/zaxxer/hikari/metrics/IMetricsTracker.java index 9a44fc6b..e7aae992 100644 --- a/hikaricp-java6/src/main/java/com/zaxxer/hikari/metrics/IMetricsTracker.java +++ b/hikaricp-java6/src/main/java/com/zaxxer/hikari/metrics/IMetricsTracker.java @@ -30,7 +30,7 @@ public interface IMetricsTracker * @param startTime the timestamp of the start time as returned by System.currentTimeMillis() * @return an instance of MetricsContext */ - public MetricsContext recordConnectionRequest(long startTime); + MetricsContext recordConnectionRequest(long startTime); /** * This method is called when a Connection is closed, with the total time in milliseconds @@ -38,7 +38,35 @@ public interface IMetricsTracker * * @param usageMilleseconds the Connection usage time in milliseconds */ - public void recordConnectionUsage(long usageMilleseconds); + void recordConnectionUsage(long usageMilleseconds); + + /** + * Get the current number of idle connections. + * + * @return the number of idle connections in the pool + */ + int getIdleConnections(); + + /** + * Get the current number of active (in-use) connections. + * + * @return the number of active connections in the pool + */ + int getActiveConnections(); + + /** + * Get the current total number of connections. + * + * @return the total number of connections in the pool + */ + int getTotalConnections(); + + /** + * Get the current number of threads awaiting a connection. + * + * @return the number of awaiting threads + */ + int getThreadsAwaitingConnection(); /** * A base instance of a MetricsContext. Classes extending this class should exhibit the diff --git a/hikaricp-java6/src/main/java/com/zaxxer/hikari/metrics/MetricsFactory.java b/hikaricp-java6/src/main/java/com/zaxxer/hikari/metrics/MetricsFactory.java index c68bbb93..5dd30615 100644 --- a/hikaricp-java6/src/main/java/com/zaxxer/hikari/metrics/MetricsFactory.java +++ b/hikaricp-java6/src/main/java/com/zaxxer/hikari/metrics/MetricsFactory.java @@ -16,6 +16,7 @@ package com.zaxxer.hikari.metrics; +import com.zaxxer.hikari.pool.HikariPool; import com.zaxxer.hikari.util.PoolUtilities; /** @@ -29,8 +30,8 @@ public final class MetricsFactory // private contructor } - public static final IMetricsTracker createMetricsTracker(String metricsClassName, String poolName) + public static final IMetricsTracker createMetricsTracker(String metricsClassName, HikariPool pool) { - return PoolUtilities.createInstance(metricsClassName, IMetricsTracker.class, poolName); + return PoolUtilities.createInstance(metricsClassName, IMetricsTracker.class, pool); } } diff --git a/hikaricp-java6/src/main/java/com/zaxxer/hikari/metrics/MetricsTracker.java b/hikaricp-java6/src/main/java/com/zaxxer/hikari/metrics/MetricsTracker.java index cc536b2f..6c268990 100644 --- a/hikaricp-java6/src/main/java/com/zaxxer/hikari/metrics/MetricsTracker.java +++ b/hikaricp-java6/src/main/java/com/zaxxer/hikari/metrics/MetricsTracker.java @@ -16,8 +16,10 @@ package com.zaxxer.hikari.metrics; +import com.zaxxer.hikari.pool.HikariPool; + /** - * This class does absolutely nothing. + * This class only supports realtime, not historical metrics. * * @author Brett Wooldridge */ @@ -25,20 +27,51 @@ public class MetricsTracker implements IMetricsTracker { public static final MetricsContext NO_CONTEXT = new MetricsContext(); - public MetricsTracker() - { - } + protected final HikariPool pool; - public MetricsTracker(String poolName) + public MetricsTracker(final HikariPool pool) { + this.pool = pool; } + /** {@inheritDoc} */ + @Override public MetricsContext recordConnectionRequest(long requestTime) { return NO_CONTEXT; } + /** {@inheritDoc} */ + @Override public void recordConnectionUsage(long usageMilleseconds) { } + + /** {@inheritDoc} */ + @Override + public int getIdleConnections() + { + return pool.getIdleConnections(); + } + + /** {@inheritDoc} */ + @Override + public int getActiveConnections() + { + return pool.getActiveConnections(); + } + + /** {@inheritDoc} */ + @Override + public int getTotalConnections() + { + return pool.getTotalConnections(); + } + + /** {@inheritDoc} */ + @Override + public int getThreadsAwaitingConnection() + { + return pool.getThreadsAwaitingConnection(); + } } diff --git a/hikaricp-java6/src/main/java/com/zaxxer/hikari/pool/HikariPool.java b/hikaricp-java6/src/main/java/com/zaxxer/hikari/pool/HikariPool.java index 7a50dde6..1a63abe5 100644 --- a/hikaricp-java6/src/main/java/com/zaxxer/hikari/pool/HikariPool.java +++ b/hikaricp-java6/src/main/java/com/zaxxer/hikari/pool/HikariPool.java @@ -134,7 +134,7 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener this.transactionIsolation = PoolUtilities.getTransactionIsolation(configuration.getTransactionIsolation()); this.isRecordMetrics = configuration.isRecordMetrics(); this.metricsTracker = MetricsFactory.createMetricsTracker((isRecordMetrics ? configuration.getMetricsTrackerClassName() - : "com.zaxxer.hikari.metrics.MetricsTracker"), configuration.getPoolName()); + : "com.zaxxer.hikari.metrics.MetricsTracker"), this); this.dataSource = initializeDataSource(); @@ -275,6 +275,26 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener return dataSource; } + /** + * Get the pool configuration object. + * + * @return the {@link HikariConfig} for this pool + */ + public HikariConfig getConfiguration() + { + return configuration; + } + + /** + * Get the metrics tracker for this pool. + * + * @return the metrics tracker + */ + public IMetricsTracker getMetricsTracker() + { + return metricsTracker; + } + @Override public String toString() { diff --git a/hikaricp/src/main/java/com/zaxxer/hikari/HikariDataSource.java b/hikaricp/src/main/java/com/zaxxer/hikari/HikariDataSource.java index 0e6b50ef..5f676d1a 100644 --- a/hikaricp/src/main/java/com/zaxxer/hikari/HikariDataSource.java +++ b/hikaricp/src/main/java/com/zaxxer/hikari/HikariDataSource.java @@ -29,6 +29,7 @@ import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.zaxxer.hikari.metrics.IMetricsTracker; import com.zaxxer.hikari.pool.HikariPool; import com.zaxxer.hikari.proxy.IHikariConnectionProxy; import com.zaxxer.hikari.util.DriverDataSource; @@ -215,6 +216,18 @@ public class HikariDataSource extends HikariConfig implements DataSource, Closea } } + /** + * Get the metrics tracker associated with this DataSource. If metrics collection is + * disabled, the resulting object will provide no meaning data or return null from + * some APIs. + * + * @return the metrics tracker for this DataSource + */ + public IMetricsTracker getMetricsTracker() + { + return (pool != null ? pool.getMetricsTracker() : null); + } + /** * close() and shutdown() are synonymous. */ diff --git a/hikaricp/src/main/java/com/zaxxer/hikari/metrics/CodaHaleMetricsTracker.java b/hikaricp/src/main/java/com/zaxxer/hikari/metrics/CodaHaleMetricsTracker.java index 9c653488..64b2a227 100644 --- a/hikaricp/src/main/java/com/zaxxer/hikari/metrics/CodaHaleMetricsTracker.java +++ b/hikaricp/src/main/java/com/zaxxer/hikari/metrics/CodaHaleMetricsTracker.java @@ -27,25 +27,39 @@ public final class CodaHaleMetricsTracker extends MetricsTracker private final Timer connectionObtainTimer; private final Histogram connectionUsage; - public CodaHaleMetricsTracker(String poolName) + public CodaHaleMetricsTracker(final HikariPool pool) { + super(pool); + registry = new MetricRegistry(); - connectionObtainTimer = registry.timer(MetricRegistry.name(HikariPool.class, poolName + "-connection", "wait")); - connectionUsage = registry.histogram(MetricRegistry.name(HikariPool.class, poolName + "-connection", "usage")); + connectionObtainTimer = registry.timer(MetricRegistry.name(HikariPool.class, pool.getConfiguration().getPoolName() + "-connection", "wait")); + connectionUsage = registry.histogram(MetricRegistry.name(HikariPool.class, pool.getConfiguration().getPoolName() + "-connection", "usage")); } + /** {@inheritDoc} */ @Override public Context recordConnectionRequest(long requestTime) { return new Context(connectionObtainTimer); } + /** {@inheritDoc} */ @Override public void recordConnectionUsage(long usageMilleseconds) { connectionUsage.update(usageMilleseconds); } + public Timer getConnectionAcquisitionTimer() + { + return connectionObtainTimer; + } + + public Histogram getConnectionDurationHistogram() + { + return connectionUsage; + } + public static final class Context extends MetricsContext { final Timer.Context innerContext; diff --git a/hikaricp/src/main/java/com/zaxxer/hikari/metrics/IMetricsTracker.java b/hikaricp/src/main/java/com/zaxxer/hikari/metrics/IMetricsTracker.java index 9a44fc6b..e7aae992 100644 --- a/hikaricp/src/main/java/com/zaxxer/hikari/metrics/IMetricsTracker.java +++ b/hikaricp/src/main/java/com/zaxxer/hikari/metrics/IMetricsTracker.java @@ -30,7 +30,7 @@ public interface IMetricsTracker * @param startTime the timestamp of the start time as returned by System.currentTimeMillis() * @return an instance of MetricsContext */ - public MetricsContext recordConnectionRequest(long startTime); + MetricsContext recordConnectionRequest(long startTime); /** * This method is called when a Connection is closed, with the total time in milliseconds @@ -38,7 +38,35 @@ public interface IMetricsTracker * * @param usageMilleseconds the Connection usage time in milliseconds */ - public void recordConnectionUsage(long usageMilleseconds); + void recordConnectionUsage(long usageMilleseconds); + + /** + * Get the current number of idle connections. + * + * @return the number of idle connections in the pool + */ + int getIdleConnections(); + + /** + * Get the current number of active (in-use) connections. + * + * @return the number of active connections in the pool + */ + int getActiveConnections(); + + /** + * Get the current total number of connections. + * + * @return the total number of connections in the pool + */ + int getTotalConnections(); + + /** + * Get the current number of threads awaiting a connection. + * + * @return the number of awaiting threads + */ + int getThreadsAwaitingConnection(); /** * A base instance of a MetricsContext. Classes extending this class should exhibit the diff --git a/hikaricp/src/main/java/com/zaxxer/hikari/metrics/MetricsFactory.java b/hikaricp/src/main/java/com/zaxxer/hikari/metrics/MetricsFactory.java index c68bbb93..5dd30615 100644 --- a/hikaricp/src/main/java/com/zaxxer/hikari/metrics/MetricsFactory.java +++ b/hikaricp/src/main/java/com/zaxxer/hikari/metrics/MetricsFactory.java @@ -16,6 +16,7 @@ package com.zaxxer.hikari.metrics; +import com.zaxxer.hikari.pool.HikariPool; import com.zaxxer.hikari.util.PoolUtilities; /** @@ -29,8 +30,8 @@ public final class MetricsFactory // private contructor } - public static final IMetricsTracker createMetricsTracker(String metricsClassName, String poolName) + public static final IMetricsTracker createMetricsTracker(String metricsClassName, HikariPool pool) { - return PoolUtilities.createInstance(metricsClassName, IMetricsTracker.class, poolName); + return PoolUtilities.createInstance(metricsClassName, IMetricsTracker.class, pool); } } diff --git a/hikaricp/src/main/java/com/zaxxer/hikari/metrics/MetricsTracker.java b/hikaricp/src/main/java/com/zaxxer/hikari/metrics/MetricsTracker.java index cc536b2f..6c268990 100644 --- a/hikaricp/src/main/java/com/zaxxer/hikari/metrics/MetricsTracker.java +++ b/hikaricp/src/main/java/com/zaxxer/hikari/metrics/MetricsTracker.java @@ -16,8 +16,10 @@ package com.zaxxer.hikari.metrics; +import com.zaxxer.hikari.pool.HikariPool; + /** - * This class does absolutely nothing. + * This class only supports realtime, not historical metrics. * * @author Brett Wooldridge */ @@ -25,20 +27,51 @@ public class MetricsTracker implements IMetricsTracker { public static final MetricsContext NO_CONTEXT = new MetricsContext(); - public MetricsTracker() - { - } + protected final HikariPool pool; - public MetricsTracker(String poolName) + public MetricsTracker(final HikariPool pool) { + this.pool = pool; } + /** {@inheritDoc} */ + @Override public MetricsContext recordConnectionRequest(long requestTime) { return NO_CONTEXT; } + /** {@inheritDoc} */ + @Override public void recordConnectionUsage(long usageMilleseconds) { } + + /** {@inheritDoc} */ + @Override + public int getIdleConnections() + { + return pool.getIdleConnections(); + } + + /** {@inheritDoc} */ + @Override + public int getActiveConnections() + { + return pool.getActiveConnections(); + } + + /** {@inheritDoc} */ + @Override + public int getTotalConnections() + { + return pool.getTotalConnections(); + } + + /** {@inheritDoc} */ + @Override + public int getThreadsAwaitingConnection() + { + return pool.getThreadsAwaitingConnection(); + } } diff --git a/hikaricp/src/main/java/com/zaxxer/hikari/pool/HikariPool.java b/hikaricp/src/main/java/com/zaxxer/hikari/pool/HikariPool.java index 6123b2dc..821d9db6 100644 --- a/hikaricp/src/main/java/com/zaxxer/hikari/pool/HikariPool.java +++ b/hikaricp/src/main/java/com/zaxxer/hikari/pool/HikariPool.java @@ -133,7 +133,7 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener this.transactionIsolation = PoolUtilities.getTransactionIsolation(configuration.getTransactionIsolation()); this.isRecordMetrics = configuration.isRecordMetrics(); this.metricsTracker = MetricsFactory.createMetricsTracker((isRecordMetrics ? configuration.getMetricsTrackerClassName() - : "com.zaxxer.hikari.metrics.MetricsTracker"), configuration.getPoolName()); + : "com.zaxxer.hikari.metrics.MetricsTracker"), this); this.dataSource = initializeDataSource(); @@ -143,7 +143,7 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener addConnectionExecutor = createThreadPoolExecutor(configuration.getMaximumPoolSize(), "HikariCP connection filler", configuration.getThreadFactory()); closeConnectionExecutor = createThreadPoolExecutor(configuration.getMaximumPoolSize(), "HikariCP connection closer", configuration.getThreadFactory()); - + fillPool(); long delayPeriod = Long.getLong("com.zaxxer.hikari.housekeeping.periodMs", TimeUnit.SECONDS.toMillis(30L)); @@ -272,6 +272,26 @@ public final class HikariPool implements HikariPoolMBean, IBagStateListener return dataSource; } + /** + * Get the pool configuration object. + * + * @return the {@link HikariConfig} for this pool + */ + public HikariConfig getConfiguration() + { + return configuration; + } + + /** + * Get the metrics tracker for this pool. + * + * @return the metrics tracker + */ + public IMetricsTracker getMetricsTracker() + { + return metricsTracker; + } + @Override public String toString() {