Alpha-level support for micrometer metrics

pull/970/head
Brett Wooldridge 8 years ago
parent 186455d8f2
commit 051f78c276

@ -14,6 +14,7 @@
<jndi.version>0.11.4.1</jndi.version>
<maven.release.version>2.5.3</maven.release.version>
<metrics.version>3.2.2</metrics.version>
<micrometer.version>0.10.0.RELEASE</micrometer.version>
<simpleclient.version>0.0.22</simpleclient.version>
<mockito.version>2.8.9</mockito.version>
<pax.exam.version>4.11.0</pax.exam.version>
@ -125,6 +126,18 @@
<version>${javassist.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<version>${micrometer.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.1.4.jre7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
@ -321,6 +334,7 @@
javax.sql.rowset.spi,
com.codahale.metrics;resolution:=optional,
com.codahale.metrics.health;resolution:=optional,
io.micrometer.core.instrument;resolution:=optional,
org.slf4j;version="[1.6,2)",
org.hibernate;resolution:=optional,
org.hibernate.cfg;resolution:=optional,

@ -37,6 +37,7 @@ import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import io.micrometer.core.instrument.MeterRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -550,8 +551,8 @@ public class HikariConfig implements HikariConfigMXBean
if (metricRegistry != null) {
metricRegistry = getObjectOrPerformJndiLookup(metricRegistry);
if (!(metricRegistry instanceof MetricRegistry)) {
throw new IllegalArgumentException("Class must be an instance of com.codahale.metrics.MetricRegistry");
if (!(metricRegistry instanceof MetricRegistry) && !(metricRegistry instanceof MeterRegistry)) {
throw new IllegalArgumentException("Class must be instance of com.codahale.metrics.MetricRegistry or io.micrometer.core.instrument.MeterRegistry");
}
}

@ -0,0 +1,115 @@
package com.zaxxer.hikari.metrics.micrometer;
import com.zaxxer.hikari.metrics.IMetricsTracker;
import com.zaxxer.hikari.metrics.PoolStats;
import io.micrometer.core.instrument.DistributionSummary;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.stats.quantile.WindowSketchQuantiles;
import java.util.concurrent.TimeUnit;
import static io.micrometer.core.instrument.stats.hist.CumulativeHistogram.buckets;
import static io.micrometer.core.instrument.stats.hist.CumulativeHistogram.linear;
public class MicrometerMetricsTracker implements IMetricsTracker
{
private static final String METRIC_CATEGORY = "pool";
private static final String METRIC_NAME_WAIT = "Wait";
private static final String METRIC_NAME_USAGE = "Usage";
private static final String METRIC_NAME_CONNECT = "ConnectionCreation";
private static final String METRIC_NAME_TIMEOUT_RATE = "ConnectionTimeoutRate";
private static final String METRIC_NAME_TOTAL_CONNECTIONS = "TotalConnections";
private static final String METRIC_NAME_IDLE_CONNECTIONS = "IdleConnections";
private static final String METRIC_NAME_ACTIVE_CONNECTIONS = "ActiveConnections";
private static final String METRIC_NAME_PENDING_CONNECTIONS = "PendingConnections";
private final Timer connectionObtainTimer;
private final DistributionSummary connectionTimeoutMeter;
private final DistributionSummary connectionUsage;
private final DistributionSummary connectionCreation;
@SuppressWarnings({"FieldCanBeLocal", "unused"})
private final Gauge totalConnectionGauge;
@SuppressWarnings({"FieldCanBeLocal", "unused"})
private final Gauge idleConnectionGauge;
@SuppressWarnings({"FieldCanBeLocal", "unused"})
private final Gauge activeConnectionGauge;
@SuppressWarnings({"FieldCanBeLocal", "unused"})
private final Gauge pendingConnectionGauge;
MicrometerMetricsTracker(final String poolName, final PoolStats poolStats, final MeterRegistry meterRegistry)
{
this.connectionObtainTimer = meterRegistry
.timerBuilder(METRIC_NAME_WAIT)
.tags(METRIC_CATEGORY, poolName)
.create();
this.connectionCreation = meterRegistry
.summaryBuilder(METRIC_NAME_CONNECT)
.tags(METRIC_CATEGORY, poolName)
.quantiles(WindowSketchQuantiles.quantiles(0.5, 0.95).create())
.histogram(buckets(linear(0, 10, 20), TimeUnit.MILLISECONDS))
.create();
this.connectionUsage = meterRegistry
.summaryBuilder(METRIC_NAME_USAGE)
.tags(poolName, METRIC_CATEGORY)
.quantiles(WindowSketchQuantiles.quantiles(0.5, 0.95).create())
.histogram(buckets(linear(0, 10, 20), TimeUnit.MILLISECONDS))
.create();
this.connectionTimeoutMeter = meterRegistry
.summaryBuilder(METRIC_NAME_TIMEOUT_RATE)
.tags(METRIC_CATEGORY, poolName)
.quantiles(WindowSketchQuantiles.quantiles(0.5, 0.95).create())
.histogram(buckets(linear(0, 10, 20), TimeUnit.MILLISECONDS))
.create();
this.totalConnectionGauge = meterRegistry
.gaugeBuilder(METRIC_NAME_TOTAL_CONNECTIONS, Integer.class, (i) -> poolStats.getTotalConnections())
.tags(METRIC_CATEGORY, poolName)
.create();
this.idleConnectionGauge = meterRegistry
.gaugeBuilder(METRIC_NAME_IDLE_CONNECTIONS, Integer.class, (i) -> poolStats.getIdleConnections())
.tags(METRIC_CATEGORY, poolName)
.create();
this.activeConnectionGauge = meterRegistry
.gaugeBuilder(METRIC_NAME_ACTIVE_CONNECTIONS, Integer.class, (i) -> poolStats.getActiveConnections())
.tags(METRIC_CATEGORY, poolName)
.create();
this.pendingConnectionGauge = meterRegistry
.gaugeBuilder(METRIC_NAME_PENDING_CONNECTIONS, Integer.class, (i) -> poolStats.getPendingThreads())
.tags(METRIC_CATEGORY, poolName)
.create();
}
/** {@inheritDoc} */
@Override
public void recordConnectionAcquiredNanos(final long elapsedAcquiredNanos)
{
connectionObtainTimer.record(elapsedAcquiredNanos, TimeUnit.NANOSECONDS);
}
/** {@inheritDoc} */
@Override
public void recordConnectionUsageMillis(final long elapsedBorrowedMillis)
{
connectionUsage.record(elapsedBorrowedMillis);
}
@Override
public void recordConnectionTimeout()
{
connectionTimeoutMeter.count();
}
@Override
public void recordConnectionCreatedMillis(long connectionCreatedMillis)
{
connectionCreation.record(connectionCreatedMillis);
}
}

@ -0,0 +1,22 @@
package com.zaxxer.hikari.metrics.micrometer;
import com.zaxxer.hikari.metrics.IMetricsTracker;
import com.zaxxer.hikari.metrics.MetricsTrackerFactory;
import com.zaxxer.hikari.metrics.PoolStats;
import io.micrometer.core.instrument.MeterRegistry;
public class MicrometerMetricsTrackerFactory implements MetricsTrackerFactory {
private final MeterRegistry registry;
public MicrometerMetricsTrackerFactory(MeterRegistry registry)
{
this.registry = registry;
}
@Override
public IMetricsTracker create(String poolName, PoolStats poolStats)
{
return new MicrometerMetricsTracker(poolName, poolStats, registry);
}
}

@ -45,6 +45,8 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.ThreadPoolExecutor;
import com.zaxxer.hikari.metrics.micrometer.MicrometerMetricsTrackerFactory;
import io.micrometer.core.instrument.MeterRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -270,9 +272,12 @@ public final class HikariPool extends PoolBase implements HikariPoolMXBean, IBag
public void setMetricRegistry(Object metricRegistry)
{
if (metricRegistry != null) {
if (metricRegistry instanceof MetricRegistry) {
setMetricsTrackerFactory(new CodahaleMetricsTrackerFactory((MetricRegistry) metricRegistry));
}
else if (metricRegistry instanceof MeterRegistry) {
setMetricsTrackerFactory(new MicrometerMetricsTrackerFactory((MeterRegistry) metricRegistry));
}
else {
setMetricsTrackerFactory(null);
}

@ -0,0 +1,39 @@
package com.zaxxer.hikari.metrics.micrometer;
import com.zaxxer.hikari.metrics.PoolStats;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class MicrometerMetricsTrackerTest {
private MeterRegistry mockMeterRegistry = new SimpleMeterRegistry();
private MicrometerMetricsTracker testee;
@Before
public void setup(){
testee = new MicrometerMetricsTracker("mypool", new PoolStats(1000L) {
@Override
protected void update() {
// nothing
}
}, mockMeterRegistry);
}
@Test
public void close() throws Exception {
Assert.assertNotNull(mockMeterRegistry.find("Wait"));
Assert.assertNotNull(mockMeterRegistry.find("Usage"));
Assert.assertNotNull(mockMeterRegistry.find("ConnectionCreation"));
Assert.assertNotNull(mockMeterRegistry.find("ConnectionTimeoutRate"));
Assert.assertNotNull(mockMeterRegistry.find("TotalConnections"));
Assert.assertNotNull(mockMeterRegistry.find("IdleConnections"));
Assert.assertNotNull(mockMeterRegistry.find("ActiveConnections"));
Assert.assertNotNull(mockMeterRegistry.find("PendingConnections"));
testee.close();
}
}
Loading…
Cancel
Save