Experimental max. active connections metric.

maxactive
Brett Wooldridge 7 years ago
parent 8e3ecb7ec8
commit 6d785fd2e3

@ -16,25 +16,34 @@
package com.zaxxer.hikari.metrics; package com.zaxxer.hikari.metrics;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicLong;
import static com.zaxxer.hikari.util.ClockSource.currentTime; import static com.zaxxer.hikari.util.ClockSource.currentTime;
import static com.zaxxer.hikari.util.ClockSource.plusMillis; import static com.zaxxer.hikari.util.ClockSource.plusMillis;
import java.util.concurrent.atomic.AtomicLong;
/** /**
* *
* @author Brett Wooldridge * @author Brett Wooldridge
*/ */
@SuppressWarnings("unused")
public abstract class PoolStats public abstract class PoolStats
{ {
private static final AtomicIntegerFieldUpdater<PoolStats> fieldUpdater;
private final AtomicLong reloadAt; private final AtomicLong reloadAt;
private final long timeoutMs; private final long timeoutMs;
private volatile int peakActiveConnections;
protected volatile int totalConnections; protected volatile int totalConnections;
protected volatile int idleConnections; protected volatile int idleConnections;
protected volatile int activeConnections; protected volatile int activeConnections;
protected volatile int pendingThreads; protected volatile int pendingThreads;
static {
fieldUpdater = AtomicIntegerFieldUpdater.newUpdater(PoolStats.class, "peakActiveConnections");
}
public PoolStats(final long timeoutMs) public PoolStats(final long timeoutMs)
{ {
this.timeoutMs = timeoutMs; this.timeoutMs = timeoutMs;
@ -77,6 +86,16 @@ public abstract class PoolStats
return pendingThreads; return pendingThreads;
} }
public int getPeakActiveConnections()
{
return fieldUpdater.getAndSet(this, 0);
}
public void setPeakActiveConnections(final int peak)
{
fieldUpdater.lazySet(this, peak);
}
protected abstract void update(); protected abstract void update();
private boolean shouldLoad() private boolean shouldLoad()

@ -291,7 +291,8 @@ public final class HikariPool extends PoolBase implements HikariPoolMXBean, IBag
public void setMetricsTrackerFactory(MetricsTrackerFactory metricsTrackerFactory) public void setMetricsTrackerFactory(MetricsTrackerFactory metricsTrackerFactory)
{ {
if (metricsTrackerFactory != null) { if (metricsTrackerFactory != null) {
this.metricsTracker = new MetricsTrackerDelegate(metricsTrackerFactory.create(config.getPoolName(), getPoolStats())); final PoolStats poolStats = getPoolStats();
this.metricsTracker = new MetricsTrackerDelegate(metricsTrackerFactory.create(config.getPoolName(), poolStats), poolStats);
} }
else { else {
this.metricsTracker = new NopMetricsTrackerDelegate(); this.metricsTracker = new NopMetricsTrackerDelegate();

@ -30,6 +30,7 @@ import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import javax.management.MBeanServer; import javax.management.MBeanServer;
@ -38,6 +39,7 @@ import javax.naming.InitialContext;
import javax.naming.NamingException; import javax.naming.NamingException;
import javax.sql.DataSource; import javax.sql.DataSource;
import com.zaxxer.hikari.metrics.PoolStats;
import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException; import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -693,16 +695,29 @@ abstract class PoolBase
*/ */
static class MetricsTrackerDelegate implements IMetricsTrackerDelegate static class MetricsTrackerDelegate implements IMetricsTrackerDelegate
{ {
private static final AtomicIntegerFieldUpdater<MetricsTrackerDelegate> activeUpdater;
private static final AtomicIntegerFieldUpdater<MetricsTrackerDelegate> maxActiveUpdater;
final IMetricsTracker tracker; final IMetricsTracker tracker;
final PoolStats poolStats;
volatile int activeCount;
volatile int maxActiveCount;
static {
activeUpdater = AtomicIntegerFieldUpdater.newUpdater(MetricsTrackerDelegate.class, "activeCount");
maxActiveUpdater = AtomicIntegerFieldUpdater.newUpdater(MetricsTrackerDelegate.class, "maxActiveCount");
}
MetricsTrackerDelegate(IMetricsTracker tracker) MetricsTrackerDelegate(IMetricsTracker tracker, PoolStats poolStats)
{ {
this.tracker = tracker; this.tracker = tracker;
this.poolStats = poolStats;
} }
@Override @Override
public void recordConnectionUsage(final PoolEntry poolEntry) public void recordConnectionUsage(final PoolEntry poolEntry)
{ {
activeUpdater.decrementAndGet(this);
tracker.recordConnectionUsageMillis(poolEntry.getMillisSinceBorrowed()); tracker.recordConnectionUsageMillis(poolEntry.getMillisSinceBorrowed());
} }
@ -723,6 +738,15 @@ abstract class PoolBase
{ {
final long now = currentTime(); final long now = currentTime();
poolEntry.lastBorrowed = now; poolEntry.lastBorrowed = now;
final int active = activeUpdater.incrementAndGet(this);
final int maxActive = maxActiveUpdater.get(this);
if (active > maxActive) {
if (maxActive < maxActiveUpdater.getAndUpdate(this, (current) -> (active > current) ? active : current)) {
poolStats.setPeakActiveConnections(active);
}
}
tracker.recordConnectionAcquiredNanos(elapsedNanos(startTime, now)); tracker.recordConnectionAcquiredNanos(elapsedNanos(startTime, now));
} }

Loading…
Cancel
Save