Ultimate JDBC Connection Pool
—
Pluggable metrics system supporting popular metrics frameworks including Dropwizard Metrics and Prometheus for comprehensive pool monitoring.
Core metrics tracking infrastructure that provides the foundation for all metrics integrations.
/**
* Base class for metrics tracking implementations. This class only supports realtime, not historical metrics.
*/
public abstract class MetricsTracker implements AutoCloseable {
/**
* Default constructor
*/
public MetricsTracker();
/**
* Record the time it took to acquire a connection from the pool
* @param elapsedAcquiredNanos time in nanoseconds to acquire the connection
*/
public void recordConnectionAcquiredNanos(long elapsedAcquiredNanos);
/**
* Record the time that a connection was used (from checkout to checkin)
* @param elapsedBorrowedMillis time in milliseconds the connection was borrowed
*/
public void recordConnectionUsageMillis(long elapsedBorrowedMillis);
/**
* Record a connection timeout event
*/
public void recordConnectionTimeout();
/**
* Close and cleanup the metrics tracker
*/
@Override
public void close();
}
/**
* Factory interface for creating MetricsTracker instances
*/
public interface MetricsTrackerFactory {
/**
* Create an instance of a MetricsTracker
* @param poolName the name of the pool
* @param poolStats a PoolStats instance to use
* @return a MetricsTracker implementation instance
*/
MetricsTracker create(String poolName, PoolStats poolStats);
}Usage Examples:
// Custom metrics tracker implementation
public class CustomMetricsTracker extends MetricsTracker {
private final String poolName;
private final AtomicLong connectionAcquisitions = new AtomicLong();
private final AtomicLong connectionTimeouts = new AtomicLong();
public CustomMetricsTracker(String poolName) {
this.poolName = poolName;
}
@Override
public void recordConnectionAcquiredNanos(long elapsedAcquiredNanos) {
connectionAcquisitions.incrementAndGet();
// Convert to milliseconds and record
long millis = elapsedAcquiredNanos / 1_000_000;
MyMetricsSystem.recordTimer("hikari.connection.acquire", millis, poolName);
}
@Override
public void recordConnectionUsageMillis(long elapsedBorrowedMillis) {
MyMetricsSystem.recordTimer("hikari.connection.usage", elapsedBorrowedMillis, poolName);
}
@Override
public void recordConnectionTimeout() {
connectionTimeouts.incrementAndGet();
MyMetricsSystem.incrementCounter("hikari.connection.timeout", poolName);
}
}
// Custom factory
public class CustomMetricsTrackerFactory implements MetricsTrackerFactory {
@Override
public MetricsTracker create(String poolName, PoolStats poolStats) {
return new CustomMetricsTracker(poolName);
}
}Abstract base class providing pool statistics for metrics systems.
/**
* Abstract base class providing pool statistics with caching support
*/
public abstract class PoolStats {
/**
* Constructor with timeout for statistics caching
* @param timeoutMs timeout in milliseconds for statistics refresh
*/
protected PoolStats(long timeoutMs);
/**
* Get the total number of connections in the pool
* @return total connections
*/
public int getTotalConnections();
/**
* Get the number of idle connections in the pool
* @return idle connections
*/
public int getIdleConnections();
/**
* Get the number of active connections in the pool
* @return active connections
*/
public int getActiveConnections();
/**
* Get the number of threads waiting for connections
* @return pending threads
*/
public int getPendingThreads();
/**
* Update the statistics - implemented by subclasses
*/
protected abstract void update();
}Configure metrics tracking through HikariConfig.
// In HikariConfig class
/**
* Set a MetricsTrackerFactory to be used for tracking pool metrics
* @param metricsTrackerFactory the MetricsTrackerFactory implementation
*/
public void setMetricsTrackerFactory(MetricsTrackerFactory metricsTrackerFactory);
public MetricsTrackerFactory getMetricsTrackerFactory();
/**
* Set a Codahale MetricRegistry to use for HikariCP
* @param metricRegistry the Codahale MetricRegistry to set
*/
public void setMetricRegistry(Object metricRegistry);
public Object getMetricRegistry();
/**
* Set a Codahale HealthCheckRegistry to use for HikariCP
* @param healthCheckRegistry the Codahale HealthCheckRegistry to set
*/
public void setHealthCheckRegistry(Object healthCheckRegistry);
public Object getHealthCheckRegistry();Usage Examples:
// Configure custom metrics factory
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb");
config.setMetricsTrackerFactory(new CustomMetricsTrackerFactory());
// Configure Codahale Metrics (alternative approach)
MetricRegistry metricRegistry = new MetricRegistry();
config.setMetricRegistry(metricRegistry);
HikariDataSource dataSource = new HikariDataSource(config);Pre-built integration with Dropwizard (Codahale) Metrics library.
/**
* Dropwizard Metrics implementation of MetricsTracker
*/
public final class CodaHaleMetricsTracker extends MetricsTracker {
/**
* Constructor with Dropwizard MetricRegistry
* @param poolName the name of the pool
* @param poolStats pool statistics instance
* @param registry the Dropwizard MetricRegistry
*/
public CodaHaleMetricsTracker(String poolName, PoolStats poolStats, MetricRegistry registry);
/**
* Get the Timer used for connection acquisition metrics
* @return Timer for connection acquisition
*/
public Timer getConnectionAcquisitionTimer();
/**
* Get the Histogram used for connection duration metrics
* @return Histogram for connection duration
*/
public Histogram getConnectionDurationHistogram();
}
/**
* Factory for creating Dropwizard metrics trackers
*/
public final class CodahaleMetricsTrackerFactory implements MetricsTrackerFactory {
/**
* Constructor with MetricRegistry
* @param registry the Dropwizard MetricRegistry
*/
public CodahaleMetricsTrackerFactory(MetricRegistry registry);
/**
* Get the MetricRegistry used by this factory
* @return the MetricRegistry
*/
public MetricRegistry getRegistry();
@Override
public MetricsTracker create(String poolName, PoolStats poolStats);
}Usage Examples:
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.ConsoleReporter;
import com.zaxxer.hikari.metrics.dropwizard.CodahaleMetricsTrackerFactory;
// Setup Dropwizard Metrics
MetricRegistry metricRegistry = new MetricRegistry();
// Optional: Setup console reporter
ConsoleReporter reporter = ConsoleReporter.forRegistry(metricRegistry)
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build();
reporter.start(1, TimeUnit.MINUTES);
// Configure HikariCP with Dropwizard Metrics
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb");
config.setMetricsTrackerFactory(new CodahaleMetricsTrackerFactory(metricRegistry));
HikariDataSource dataSource = new HikariDataSource(config);
// Access specific metrics
CodaHaleMetricsTracker tracker = (CodaHaleMetricsTracker)
dataSource.getMetricsTrackerFactory().create("test", null);
Timer acquisitionTimer = tracker.getConnectionAcquisitionTimer();
Histogram usageHistogram = tracker.getConnectionDurationHistogram();Health check integration for monitoring pool health.
/**
* Dropwizard HealthCheck implementation for HikariCP
*/
public final class CodahaleHealthChecker extends HealthCheck {
// Implementation details are internal to the health check framework
}Usage Examples:
import com.codahale.metrics.health.HealthCheckRegistry;
import com.zaxxer.hikari.metrics.dropwizard.CodahaleHealthChecker;
// Setup health check registry
HealthCheckRegistry healthCheckRegistry = new HealthCheckRegistry();
// Configure HikariCP with health checks
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb");
config.setHealthCheckRegistry(healthCheckRegistry);
// Add health check properties
config.addHealthCheckProperty("connectivityCheckTimeoutMs", "5000");
config.addHealthCheckProperty("expected99thPercentileMs", "100");
HikariDataSource dataSource = new HikariDataSource(config);
// Run health checks
Map<String, HealthCheck.Result> results = healthCheckRegistry.runHealthChecks();
for (Map.Entry<String, HealthCheck.Result> entry : results.entrySet()) {
System.out.println(entry.getKey() + ": " +
(entry.getValue().isHealthy() ? "HEALTHY" : "UNHEALTHY"));
}Pre-built integration with Prometheus metrics collection.
/**
* Factory for creating Prometheus metrics trackers
*/
public class PrometheusMetricsTrackerFactory implements MetricsTrackerFactory {
/**
* Create a Prometheus metrics tracker and register collectors
* @param poolName the name of the pool
* @param poolStats pool statistics instance
* @return PrometheusMetricsTracker instance
*/
@Override
public MetricsTracker create(String poolName, PoolStats poolStats);
}Usage Examples:
import com.zaxxer.hikari.metrics.prometheus.PrometheusMetricsTrackerFactory;
import io.prometheus.client.CollectorRegistry;
import io.prometheus.client.exporter.HTTPServer;
// Configure HikariCP with Prometheus
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb");
config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory());
HikariDataSource dataSource = new HikariDataSource(config);
// Start Prometheus HTTP server for metrics scraping
HTTPServer server = new HTTPServer(8080);
// Metrics will be available at http://localhost:8080/metrics
// Example metrics exposed:
// - hikaricp_connection_timeout_count{pool="mypool"}
// - hikaricp_connection_acquired_nanos{pool="mypool",quantile="0.5"}
// - hikaricp_connection_usage_millis{pool="mypool",quantile="0.95"}HikariCP-specific Prometheus collector for pool statistics.
/**
* Prometheus collector for HikariCP pool statistics
*/
public class HikariCPCollector extends Collector {
// Collector implementation registers automatically when MetricsTrackerFactory is used
}Usage Examples:
// The HikariCPCollector is automatically registered when using PrometheusMetricsTrackerFactory
// It exposes the following metrics:
// Pool connection statistics
// - hikaricp_active_connections{pool="poolName"} - Active connections
// - hikaricp_idle_connections{pool="poolName"} - Idle connections
// - hikaricp_pending_threads{pool="poolName"} - Threads waiting for connections
// - hikaricp_connections{pool="poolName"} - Total connections
// Connection timing metrics (from PrometheusMetricsTracker)
// - hikaricp_connection_acquired_nanos{pool="poolName"} - Connection acquisition time
// - hikaricp_connection_usage_millis{pool="poolName"} - Connection usage time
// - hikaricp_connection_timeout_count{pool="poolName"} - Connection timeout count
// Example Prometheus query for monitoring
// Rate of connection acquisitions:
// rate(hikaricp_connection_acquired_nanos_count[5m])
// 95th percentile connection acquisition time:
// hikaricp_connection_acquired_nanos{quantile="0.95"}
// Pool utilization percentage:
// (hikaricp_active_connections / hikaricp_connections) * 100Create custom integrations for other metrics systems.
Usage Examples:
// Example: Micrometer integration
public class MicrometerMetricsTracker extends MetricsTracker {
private final MeterRegistry meterRegistry;
private final Timer acquisitionTimer;
private final Timer usageTimer;
private final Counter timeoutCounter;
private final String poolName;
public MicrometerMetricsTracker(String poolName, MeterRegistry meterRegistry) {
this.poolName = poolName;
this.meterRegistry = meterRegistry;
this.acquisitionTimer = Timer.builder("hikari.connection.acquire")
.tag("pool", poolName)
.description("Connection acquisition time")
.register(meterRegistry);
this.usageTimer = Timer.builder("hikari.connection.usage")
.tag("pool", poolName)
.description("Connection usage time")
.register(meterRegistry);
this.timeoutCounter = Counter.builder("hikari.connection.timeout")
.tag("pool", poolName)
.description("Connection timeout count")
.register(meterRegistry);
}
@Override
public void recordConnectionAcquiredNanos(long elapsedAcquiredNanos) {
acquisitionTimer.record(elapsedAcquiredNanos, TimeUnit.NANOSECONDS);
}
@Override
public void recordConnectionUsageMillis(long elapsedBorrowedMillis) {
usageTimer.record(elapsedBorrowedMillis, TimeUnit.MILLISECONDS);
}
@Override
public void recordConnectionTimeout() {
timeoutCounter.increment();
}
@Override
public void close() {
// Cleanup if needed
meterRegistry.remove(acquisitionTimer);
meterRegistry.remove(usageTimer);
meterRegistry.remove(timeoutCounter);
}
}
public class MicrometerMetricsTrackerFactory implements MetricsTrackerFactory {
private final MeterRegistry meterRegistry;
public MicrometerMetricsTrackerFactory(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
@Override
public MetricsTracker create(String poolName, PoolStats poolStats) {
// Register pool statistics gauges
Gauge.builder("hikari.connections.active")
.tag("pool", poolName)
.register(meterRegistry, poolStats, PoolStats::getActiveConnections);
Gauge.builder("hikari.connections.idle")
.tag("pool", poolName)
.register(meterRegistry, poolStats, PoolStats::getIdleConnections);
Gauge.builder("hikari.connections.total")
.tag("pool", poolName)
.register(meterRegistry, poolStats, PoolStats::getTotalConnections);
Gauge.builder("hikari.connections.pending")
.tag("pool", poolName)
.register(meterRegistry, poolStats, PoolStats::getPendingThreads);
return new MicrometerMetricsTracker(poolName, meterRegistry);
}
}
// Usage
MeterRegistry meterRegistry = new SimpleMeterRegistry();
HikariConfig config = new HikariConfig();
config.setMetricsTrackerFactory(new MicrometerMetricsTrackerFactory(meterRegistry));Install with Tessl CLI
npx tessl i tessl/maven-com-zaxxer--hikari-cp-java7