Skip to content

Commit

Permalink
Fix prometheus metrics to support multiple hikaricp pools (#890)
Browse files Browse the repository at this point in the history
  • Loading branch information
cenkakin authored and brettwooldridge committed May 20, 2017
1 parent 4f4aacd commit fa79e4e
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 116 deletions.
Expand Up @@ -17,93 +17,76 @@
package com.zaxxer.hikari.metrics.prometheus; package com.zaxxer.hikari.metrics.prometheus;


import com.zaxxer.hikari.metrics.IMetricsTracker; import com.zaxxer.hikari.metrics.IMetricsTracker;

import io.prometheus.client.Collector; import io.prometheus.client.Collector;
import io.prometheus.client.CollectorRegistry; import io.prometheus.client.CollectorRegistry;
import io.prometheus.client.Counter; import io.prometheus.client.Counter;
import io.prometheus.client.Summary; import io.prometheus.client.Summary;
import java.util.concurrent.TimeUnit;


class PrometheusMetricsTracker implements IMetricsTracker class PrometheusMetricsTracker implements IMetricsTracker
{ {
private final Counter.Child connectionTimeoutCounter; private static final Counter CONNECTION_TIMEOUT_COUNTER = Counter.build()
private final Summary.Child elapsedAcquiredSummary; .name("hikaricp_connection_timeout_total")
private final Summary.Child elapsedBorrowedSummary; .labelNames("pool")
private final Summary.Child elapsedCreationSummary; .help("Connection timeout total count")

.register();
private final Counter ctCounter; private static final Summary ELAPSED_ACQUIRED_SUMMARY = Summary.build()
private final Summary eaSummary; .name("hikaricp_connection_acquired_nanos")
private final Summary ebSummary; .labelNames("pool")
private final Summary ecSummary; .help("Connection acquired time (ns)")

.register();
private static final Summary ELAPSED_BORROWED_SUMMARY = Summary.build()
.name("hikaricp_connection_usage_millis")
.labelNames("pool")
.help("Connection usage (ms)")
.register();
private static final Summary ELAPSED_CREATION_SUMMARY = Summary.build()
.name("hikaricp_connection_creation_millis")
.labelNames("pool")
.help("Connection creation (ms)")
.register();

private final Counter.Child connectionTimeoutCounterChild;
private final Summary.Child elapsedAcquiredSummaryChild;
private final Summary.Child elapsedBorrowedSummaryChild;
private final Summary.Child elapsedCreationSummaryChild;
private final Collector collector; private final Collector collector;
private final CollectorRegistry registry;


PrometheusMetricsTracker(String poolName, Collector collector, CollectorRegistry registry) PrometheusMetricsTracker(String poolName, Collector collector) {
{
this.collector = collector; this.collector = collector;
this.registry = registry; this.connectionTimeoutCounterChild = CONNECTION_TIMEOUT_COUNTER.labels(poolName);

this.elapsedAcquiredSummaryChild = ELAPSED_ACQUIRED_SUMMARY.labels(poolName);
ctCounter = Counter.build() this.elapsedBorrowedSummaryChild = ELAPSED_BORROWED_SUMMARY.labels(poolName);
.name("hikaricp_connection_timeout_count") this.elapsedCreationSummaryChild = ELAPSED_CREATION_SUMMARY.labels(poolName);
.labelNames("pool")
.help("Connection timeout count")
.register(registry);

this.connectionTimeoutCounter = ctCounter.labels(poolName);

eaSummary = Summary.build()
.name("hikaricp_connection_acquired_nanos")
.labelNames("pool")
.help("Connection acquired time (ns)")
.register(registry);
this.elapsedAcquiredSummary = eaSummary.labels(poolName);

ebSummary = Summary.build()
.name("hikaricp_connection_usage_millis")
.labelNames("pool")
.help("Connection usage (ms)")
.register(registry);
this.elapsedBorrowedSummary = ebSummary.labels(poolName);

ecSummary = Summary.build()
.name("hikaricp_connection_creation_millis")
.labelNames("pool")
.help("Connection creation (ms)")
.register(registry);
this.elapsedCreationSummary = ecSummary.labels(poolName);
} }


@Override @Override
public void close() public void close()
{ {
registry.unregister(ctCounter); CollectorRegistry.defaultRegistry.unregister(collector);
registry.unregister(eaSummary);
registry.unregister(ebSummary);
registry.unregister(ecSummary);
registry.unregister(collector);
} }


@Override @Override
public void recordConnectionAcquiredNanos(long elapsedAcquiredNanos) public void recordConnectionAcquiredNanos(long elapsedAcquiredNanos)
{ {
elapsedAcquiredSummary.observe(elapsedAcquiredNanos); elapsedAcquiredSummaryChild.observe(elapsedAcquiredNanos);
} }


@Override @Override
public void recordConnectionUsageMillis(long elapsedBorrowedMillis) public void recordConnectionUsageMillis(long elapsedBorrowedMillis)
{ {
elapsedBorrowedSummary.observe(elapsedBorrowedMillis); elapsedBorrowedSummaryChild.observe(elapsedBorrowedMillis);
} }


@Override @Override
public void recordConnectionCreatedMillis(long connectionCreatedMillis) public void recordConnectionCreatedMillis(long connectionCreatedMillis)
{ {
elapsedCreationSummary.observe(connectionCreatedMillis); elapsedCreationSummaryChild.observe(connectionCreatedMillis);
} }


@Override @Override
public void recordConnectionTimeout() public void recordConnectionTimeout()
{ {
connectionTimeoutCounter.inc(); connectionTimeoutCounterChild.inc();
} }
} }
Expand Up @@ -19,9 +19,7 @@
import com.zaxxer.hikari.metrics.IMetricsTracker; import com.zaxxer.hikari.metrics.IMetricsTracker;
import com.zaxxer.hikari.metrics.MetricsTrackerFactory; import com.zaxxer.hikari.metrics.MetricsTrackerFactory;
import com.zaxxer.hikari.metrics.PoolStats; import com.zaxxer.hikari.metrics.PoolStats;

import io.prometheus.client.Collector; import io.prometheus.client.Collector;
import io.prometheus.client.CollectorRegistry;


/** /**
* <pre>{@code * <pre>{@code
Expand All @@ -31,20 +29,9 @@
*/ */
public class PrometheusMetricsTrackerFactory implements MetricsTrackerFactory public class PrometheusMetricsTrackerFactory implements MetricsTrackerFactory
{ {

private final CollectorRegistry registry;

public PrometheusMetricsTrackerFactory() {
this(CollectorRegistry.defaultRegistry);
}

public PrometheusMetricsTrackerFactory(CollectorRegistry registry) {
this.registry = registry;
}

@Override @Override
public IMetricsTracker create(String poolName, PoolStats poolStats) { public IMetricsTracker create(String poolName, PoolStats poolStats) {
Collector collector = new HikariCPCollector(poolName, poolStats).register(registry); Collector collector = new HikariCPCollector(poolName, poolStats).register();
return new PrometheusMetricsTracker(poolName, collector, registry); return new PrometheusMetricsTracker(poolName, collector);
} }
} }
Expand Up @@ -19,16 +19,17 @@
import static com.zaxxer.hikari.pool.TestElf.newHikariConfig; import static com.zaxxer.hikari.pool.TestElf.newHikariConfig;
import static com.zaxxer.hikari.util.UtilityElf.quietlySleep; import static com.zaxxer.hikari.util.UtilityElf.quietlySleep;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;


import java.sql.Connection;

import org.junit.Test;

import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.mocks.StubConnection; import com.zaxxer.hikari.mocks.StubConnection;
import io.prometheus.client.CollectorRegistry;
import org.junit.Test;


import java.sql.Connection; import io.prometheus.client.CollectorRegistry;


public class HikariCPCollectorTest { public class HikariCPCollectorTest {
@Test @Test
Expand Down Expand Up @@ -116,32 +117,10 @@ public void connectionClosed() throws Exception {
} }
} }


@Test private double getValue(String name, String poolName) {
public void checkRegistry() {
HikariConfig config = newHikariConfig();
config.setMinimumIdle(0);
CollectorRegistry customRegistry = new CollectorRegistry();
config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory(customRegistry));
config.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource");

StubConnection.slowCreate = true;
try (HikariDataSource ds = new HikariDataSource(config)) {
assertThat(getValue("hikaricp_active_connections", "checkRegistry", customRegistry), is(0.0));
assertThat(getValue("hikaricp_active_connections", "checkRegistry"), is(nullValue()));
}
finally {
StubConnection.slowCreate = false;
}
}

private Double getValue(String name, String poolName) {
return this.getValue(name, poolName, CollectorRegistry.defaultRegistry);
}

private Double getValue(String name, String poolName, CollectorRegistry registry) {
String[] labelNames = {"pool"}; String[] labelNames = {"pool"};
String[] labelValues = {poolName}; String[] labelValues = {poolName};
return registry.getSampleValue(name, labelNames, labelValues); return CollectorRegistry.defaultRegistry.getSampleValue(name, labelNames, labelValues);
} }


} }
Expand Up @@ -19,17 +19,18 @@
import static com.zaxxer.hikari.pool.TestElf.newHikariConfig; import static com.zaxxer.hikari.pool.TestElf.newHikariConfig;
import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;


import java.sql.Connection;
import java.sql.SQLTransientConnectionException;

import org.junit.Test;

import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import io.prometheus.client.CollectorRegistry;
import org.junit.Test;


import java.sql.Connection; import io.prometheus.client.CollectorRegistry;
import java.sql.SQLTransientConnectionException;


public class PrometheusMetricsTrackerTest { public class PrometheusMetricsTrackerTest {


Expand All @@ -46,15 +47,15 @@ public void recordConnectionTimeout() throws Exception {


try (HikariDataSource hikariDataSource = new HikariDataSource(config)) { try (HikariDataSource hikariDataSource = new HikariDataSource(config)) {
try (Connection connection1 = hikariDataSource.getConnection(); try (Connection connection1 = hikariDataSource.getConnection();
Connection connection2 = hikariDataSource.getConnection()) { Connection connection2 = hikariDataSource.getConnection()) {
try (Connection connection3 = hikariDataSource.getConnection()) { try (Connection connection3 = hikariDataSource.getConnection()) {
} }
catch (SQLTransientConnectionException ignored) { catch (SQLTransientConnectionException ignored) {
} }
} }


assertThat(CollectorRegistry.defaultRegistry.getSampleValue( assertThat(CollectorRegistry.defaultRegistry.getSampleValue(
"hikaricp_connection_timeout_count", "hikaricp_connection_timeout_total",
labelNames, labelNames,
labelValues), is(1.0)); labelValues), is(1.0));
assertThat(CollectorRegistry.defaultRegistry.getSampleValue( assertThat(CollectorRegistry.defaultRegistry.getSampleValue(
Expand All @@ -77,26 +78,37 @@ public void recordConnectionTimeout() throws Exception {
} }


@Test @Test
public void testThatTheProperRegistryIsUsed() throws Exception { public void testMultiplePoolName() throws Exception {
String[] labelNames = {"pool"};

HikariConfig config = newHikariConfig(); HikariConfig config = newHikariConfig();
CollectorRegistry customRegistry = new CollectorRegistry(); config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory());
config.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory(customRegistry)); config.setPoolName("first");
config.setJdbcUrl("jdbc:h2:mem:"); config.setJdbcUrl("jdbc:h2:mem:");
config.setMaximumPoolSize(2); config.setMaximumPoolSize(2);
config.setConnectionTimeout(250); config.setConnectionTimeout(250);
String[] labelValues1 = {config.getPoolName()};


String[] labelNames = {"pool"}; try (HikariDataSource ignored = new HikariDataSource(config)) {
String[] labelValues = {config.getPoolName()}; assertThat(CollectorRegistry.defaultRegistry.getSampleValue(

"hikaricp_connection_timeout_total",
try (HikariDataSource hikariDataSource = new HikariDataSource(config)) {
assertThat(customRegistry.getSampleValue(
"hikaricp_connection_timeout_count",
labelNames, labelNames,
labelValues), is(0.0)); labelValues1), is(0.0));
}

HikariConfig config2 = newHikariConfig();
config2.setMetricsTrackerFactory(new PrometheusMetricsTrackerFactory());
config2.setPoolName("second");
config2.setJdbcUrl("jdbc:h2:mem:");
config2.setMaximumPoolSize(4);
config2.setConnectionTimeout(250);
String[] labelValues2 = {config2.getPoolName()};

try (HikariDataSource ignored = new HikariDataSource(config2)) {
assertThat(CollectorRegistry.defaultRegistry.getSampleValue( assertThat(CollectorRegistry.defaultRegistry.getSampleValue(
"hikaricp_connection_usage_millis_sum", "hikaricp_connection_timeout_total",
labelNames, labelNames,
labelValues), is(nullValue())); labelValues2), is(0.0));
} }
} }
} }

0 comments on commit fa79e4e

Please sign in to comment.