Skip to content

Commit

Permalink
Allow configuration of Prometheus buckets (ReactiveX#696)
Browse files Browse the repository at this point in the history
* Allow for configuring of Prometheus Histogram buckets

* Created new MetricOptions class to allow for custom Histogram buckets
  • Loading branch information
kdombeck authored and RobWin committed Oct 21, 2019
1 parent 78ebabb commit a0a5600
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@ public abstract class AbstractCircuitBreakerMetrics extends Collector {
protected final CollectorRegistry collectorRegistry = new CollectorRegistry(true);
protected final Histogram callsHistogram;

protected AbstractCircuitBreakerMetrics(MetricNames names) {
protected AbstractCircuitBreakerMetrics(MetricNames names, MetricOptions options) {
this.names = requireNonNull(names);
requireNonNull(options);
callsHistogram = Histogram.build(names.getCallsMetricName(), "Total number of calls by kind")
.labelNames("name", "kind")
.buckets(options.getBuckets())
.create().register(collectorRegistry);
}

Expand Down Expand Up @@ -212,4 +214,48 @@ public MetricNames build() {
}
}
}

/** Defines possible configuration for metric options. */
public static class MetricOptions {

public static final double[] DEFAULT_BUCKETS = new double[]{.005, .01, .025, .05, .075, .1, .25, .5, .75, 1, 2.5, 5, 7.5, 10};

/**
* Returns a builder for creating custom metric options.
* Note that all options have default values.
*/
public static Builder custom() {
return new Builder();
}

/** Returns default metric options. */
public static MetricOptions ofDefaults() {
return new MetricOptions();
}

private double[] buckets = DEFAULT_BUCKETS;

private MetricOptions() {}

/** Returns the Histogram buckets, defaults to {@link MetricOptions#DEFAULT_BUCKETS}. */
public double[] getBuckets() {
return buckets;
}

/** Helps building custom instance of {@link MetricOptions}. */
public static class Builder {
private final MetricOptions metricOptions = new MetricOptions();

/** Overrides the default Histogram buckets {@link MetricOptions#DEFAULT_BUCKETS} with a given one. */
public Builder buckets(double[] buckets) {
metricOptions.buckets = requireNonNull(buckets);
return this;
}

/** Builds {@link MetricOptions} instance. */
public MetricOptions build() {
return metricOptions;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@
/** Collects circuit breaker exposed {@link Metrics}. */
public class CircuitBreakerMetricsCollector extends AbstractCircuitBreakerMetrics {

/**
* Creates a new collector with custom metric names and
* using given {@code supplier} as source of circuit breakers.
*
* @param names the custom metric names
* @param options the custom metric options
* @param circuitBreakerRegistry the source of circuit breakers
*/
public static CircuitBreakerMetricsCollector ofCircuitBreakerRegistry(MetricNames names, MetricOptions options, CircuitBreakerRegistry circuitBreakerRegistry) {
return new CircuitBreakerMetricsCollector(names, options, circuitBreakerRegistry);
}

/**
* Creates a new collector with custom metric names and
* using given {@code supplier} as source of circuit breakers.
Expand All @@ -36,7 +48,7 @@ public class CircuitBreakerMetricsCollector extends AbstractCircuitBreakerMetric
* @param circuitBreakerRegistry the source of circuit breakers
*/
public static CircuitBreakerMetricsCollector ofCircuitBreakerRegistry(MetricNames names, CircuitBreakerRegistry circuitBreakerRegistry) {
return new CircuitBreakerMetricsCollector(names, circuitBreakerRegistry);
return new CircuitBreakerMetricsCollector(names, MetricOptions.ofDefaults(), circuitBreakerRegistry);
}

/**
Expand All @@ -45,13 +57,13 @@ public static CircuitBreakerMetricsCollector ofCircuitBreakerRegistry(MetricName
* @param circuitBreakerRegistry the source of circuit breakers
*/
public static CircuitBreakerMetricsCollector ofCircuitBreakerRegistry(CircuitBreakerRegistry circuitBreakerRegistry) {
return new CircuitBreakerMetricsCollector(MetricNames.ofDefaults(), circuitBreakerRegistry);
return new CircuitBreakerMetricsCollector(MetricNames.ofDefaults(), MetricOptions.ofDefaults(), circuitBreakerRegistry);
}

private final CircuitBreakerRegistry circuitBreakerRegistry;

private CircuitBreakerMetricsCollector(MetricNames names, CircuitBreakerRegistry circuitBreakerRegistry) {
super(names);
private CircuitBreakerMetricsCollector(MetricNames names, MetricOptions options, CircuitBreakerRegistry circuitBreakerRegistry) {
super(names, options);
this.circuitBreakerRegistry = requireNonNull(circuitBreakerRegistry);

for (CircuitBreaker circuitBreaker : this.circuitBreakerRegistry.getAllCircuitBreakers()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ public CircuitBreakerMetricsPublisher() {
}

public CircuitBreakerMetricsPublisher(MetricNames names) {
super(names);
this(names, MetricOptions.ofDefaults());
}

public CircuitBreakerMetricsPublisher(MetricNames names, MetricOptions options) {
super(names, options);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.time.Duration;
import java.util.concurrent.TimeUnit;

import static io.github.resilience4j.prometheus.AbstractCircuitBreakerMetrics.*;
import static io.github.resilience4j.prometheus.AbstractCircuitBreakerMetrics.MetricNames.*;
import static org.assertj.core.api.Assertions.assertThat;

Expand Down Expand Up @@ -232,4 +233,28 @@ public void customMetricNamesOverrideDefaultOnes() {
new String[]{"backendA", "closed"}
)).isNotNull();
}

@Test
public void customMetricNameBucketsOverrideDefaultOnes() {
CollectorRegistry registry = new CollectorRegistry();

CircuitBreakerMetricsCollector.ofCircuitBreakerRegistry(
MetricNames.ofDefaults(),
MetricOptions.custom().buckets(new double[]{.005, .01}).build(),
circuitBreakerRegistry).register(registry);

circuitBreaker.onSuccess(2000, TimeUnit.NANOSECONDS);

assertThat(registry.getSampleValue(
DEFAULT_CIRCUIT_BREAKER_CALLS + "_bucket",
new String[]{"name", "kind", "le"},
new String[]{circuitBreaker.getName(), "successful", "0.01"}
)).isEqualTo(1d);

assertThat(registry.getSampleValue(
DEFAULT_CIRCUIT_BREAKER_CALLS + "_bucket",
new String[]{"name", "kind", "le"},
new String[]{circuitBreaker.getName(), "successful", "0.025"}
)).isNull();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.time.Duration;
import java.util.concurrent.TimeUnit;

import static io.github.resilience4j.prometheus.AbstractCircuitBreakerMetrics.*;
import static io.github.resilience4j.prometheus.AbstractCircuitBreakerMetrics.MetricNames.*;
import static org.assertj.core.api.Assertions.assertThat;

Expand Down Expand Up @@ -236,4 +237,31 @@ public void customMetricNamesOverrideDefaultOnes() {
new String[]{"backendA", "closed"}
)).isNotNull();
}

@Test
public void customMetricNameBucketsOverrideDefaultOnes() {
CollectorRegistry registry = new CollectorRegistry();

CircuitBreakerMetricsPublisher circuitBreakerMetricsPublisher = new CircuitBreakerMetricsPublisher(
MetricNames.ofDefaults(),
MetricOptions.custom().buckets(new double[]{.005, .01}).build());

circuitBreakerMetricsPublisher.register(registry);
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.of(CircuitBreakerConfig.ofDefaults(), circuitBreakerMetricsPublisher);
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("backendA");

circuitBreaker.onSuccess(2000, TimeUnit.NANOSECONDS);

assertThat(registry.getSampleValue(
DEFAULT_CIRCUIT_BREAKER_CALLS + "_bucket",
new String[]{"name", "kind", "le"},
new String[]{circuitBreaker.getName(), "successful", "0.01"}
)).isEqualTo(1d);

assertThat(registry.getSampleValue(
DEFAULT_CIRCUIT_BREAKER_CALLS + "_bucket",
new String[]{"name", "kind", "le"},
new String[]{circuitBreaker.getName(), "successful", "0.025"}
)).isNull();
}
}

0 comments on commit a0a5600

Please sign in to comment.