HomeGuidesChangelog
GuidesGitHubLog In

Micrometer

Getting started with resilience4j-micrometer

Resilience4j provides a module for Micrometer which supports most popular monitoring systems like InfluxDB or Prometheus.
The module expects that micrometer-core is already provided at runtime. Spring Reactor is not a transitive dependency.

repositories {
    jCenter()
}

dependencies {
    compile "io.github.resilience4j:resilience4j-micrometer:${resilience4jVersion}"
}

CircuitBreaker Metrics

The following code snippet shows how to bind CircuitBreaker metrics to a MeterRegistry. It binds all CircuitBreaker instances at once and registers event consumers to dynamically bind newly created instances.

MeterRegistry meterRegistry = new SimpleMeterRegistry();
CircuitBreakerRegistry circuitBreakerRegistry =
  CircuitBreakerRegistry.ofDefaults();
CircuitBreaker foo = circuitBreakerRegistry
  .circuitBreaker("backendA");
CircuitBreaker boo = circuitBreakerRegistry
  .circuitBreaker("backendB");

TaggedCircuitBreakerMetrics
  .ofCircuitBreakerRegistry(circuitBreakerRegistry)
  .bindTo(meterRegistry)

The following metrics are exported:

Metric name

Type

Tags

Description

resilience4j
.circuitbreaker
.calls

Timer

One of the following:

  • kind="failed"
  • kind="successful"
  • kind="ignored"

name="backendA"

Total number of successful, failed or ignored calls

resilience4j
.circuitbreaker
.max.buffered.calls

Gauge

name="backendA"

The maximum number of buffered calls which can be stored in the current ring buffer

resilience4j
.circuitbreaker
.state

Gauge
0 - Not active
1 - Active

One of the following:

  • state="closed"
  • state="open"
  • state="half_open"
  • state="forced_open"
  • state="disabled"

name="backendA"

The states of the circuit breaker

resilience4j
.circuitbreaker
.failure.rate

Gauge

name="backendA"

The failure rate of the circuit breaker

resilience4j
.circuitbreaker
.buffered.calls

Gauge

One of the following:

  • kind="failed"
  • kind="successful"

name="backendA"

The number of buffered successful and failed calls stored in the ring buffer

resilience4
.circuitbreaker
.not.permitted.calls

Counter

kind="not_permitted"

name="backendA"

Total number of calls which have not been permitted.

resilience4j
.circuitbreaker
.slow.call.rate

Gauge

name="backendA"

The slow call of the circuit breaker

Retry Metrics

The following code snippet shows how to bind Retry metrics to a MeterRegistry. It binds all Retry instances at once and registers event consumers to dynamically bind newly created instances

MeterRegistry meterRegistry = new SimpleMeterRegistry();
RetryRegistry retryRegistry = RetryRegistry.ofDefaults();
Retry retry = retryRegistry.retry("backendA");

// Register all retries at once
TaggedRetryMetrics
  .ofRetryRegistry(retryRegistry)
  .bindTo(meterRegistry);

The following metrics are exported:

Metric name

Type

Tags

Description

resilience4j
.retry
.calls

Gauge

One of the following:

  • kind="successful.without.retry"
  • kind="successful.with.retry"
  • kind="failed.with.retry"
  • kind="failed.without.retry"

name="backendA"

The number of calls by kind

Bulkhead Metrics

The following code snippet shows how to bind Bulkhead metrics to a MeterRegistry. It binds all Bulkhead instances at once and registers event consumers to dynamically bind newly created instances

MeterRegistry meterRegistry = new SimpleMeterRegistry();
BulkheadRegistry bulkheadRegistry = BulkheadRegistry.ofDefaults();
Bulkhead bulkhead = bulkheadRegistry.bulkhead("backendA");

// Register all retries at once
TaggedBulkheadMetrics
  .ofBulkheadRegistry(bulkheadRegistry)
  .bindTo(meterRegistry);

The following metrics are exported:

Metric name

Type

Tags

Description

resilience4j
.bulkhead
.available
.concurrent.calls

Gauge

name="backendA"

The number of available permissions

resilience4j
.bulkhead
.max.allowed
.concurrent.calls

Gauge

name="backendA"

The maximum number of available permissions

RateLimiter Metrics

The following code snippet shows how to bind RateLimiter metrics to a MeterRegistry. It binds all RateLimiter instances at once and registers event consumers to dynamically bind newly created instances

MeterRegistry meterRegistry = new SimpleMeterRegistry();
RateLimiterRegistry rateLimiterRegistry = RateLimiterRegistry.ofDefaults();
RateLimiter rateLimiter = rateLimiterRegistry
  .rateLimiter("backendA");

// Register rate limiters at once
TaggedRateLimiterMetrics
  .ofRateLimiterRegistry(rateLimiterRegistry)
  .bindTo(meterRegistry);

The following metrics are exported:

Metric name

Type

Tags

Description

resilience4j.ratelimiter
.available.permissions

Gauge

name="backendA"

The number of available permissions

resilience4j.ratelimiter
.waiting.threads

Gauge

name="backendA"

The number of waiting threads

TimeLimiter

The following code snippet shows how to bind TimeLimiter metrics to a MeterRegistry. It binds all TimeLimiter instances at once and registers event consumers to dynamically bind newly created instances

MeterRegistry meterRegistry = new SimpleMeterRegistry();
TimeLimiterRegistry timeLimiterRegistry = TimeLimiterRegistry.ofDefaults();
TimeLimiter timeLimiter = timeLimiterRegistry
  .timeLimiter("backendA");

// Register time limiters at once
TaggedTimeLimiterMetrics
  .ofTimeLimiterRegistry(timeLimiterRegistry)
  .bindTo(meterRegistry);

The following metrics are exported:

Metric name

Type

Tags

Description

resilience4j.timelimiter.calls

Counter

name="backendA"
kind="successful"

Total number of calls which were successful

resilience4j.timelimiter.calls

Counter

name="backendA"
kind="failed"

Total number of calls which failed

resilience4j.timelimiter.calls

Counter

name="backendA"
kind="timeout"

Total number of calls where a timeout occured

Prometheus

When you want to publish to Prometheus, you have to add the following dependency:

dependencies {
    compile "io.micrometer:micrometer-registry-prometheus"
}

The following metrics are exported per CircuitBreaker:

# HELP resilience4j_circuitbreaker_buffered_calls The number of buffered failed calls stored in the ring buffer
# TYPE resilience4j_circuitbreaker_buffered_calls gauge
resilience4j_circuitbreaker_buffered_calls{kind="failed",name="backendA",} 0.0
resilience4j_circuitbreaker_buffered_calls{kind="successful",name="backendA",} 0.0

# HELP resilience4j_circuitbreaker_calls_total Total number of not permitted calls
# TYPE resilience4j_circuitbreaker_calls_total counter
resilience4j_circuitbreaker_calls_total{kind="not_permitted",name="backendA",} 0.0

# HELP resilience4j_circuitbreaker_state The states of the circuit breaker
# TYPE resilience4j_circuitbreaker_state gauge
resilience4j_circuitbreaker_state{name="backendA",state="half_open",} 0.0
resilience4j_circuitbreaker_state{name="backendA",state="forced_open",} 0.0
resilience4j_circuitbreaker_state{name="backendA",state="disabled",} 0.0
resilience4j_circuitbreaker_state{name="backendA",state="closed",} 1.0
resilience4j_circuitbreaker_state{name="backendA",state="open",} 0.0
resilience4j_circuitbreaker_state{name="backendA",} 0.0

# HELP resilience4j_circuitbreaker_failure_rate The failure rate of the circuit breaker
# TYPE resilience4j_circuitbreaker_failure_rate gauge
resilience4j_circuitbreaker_failure_rate{name="backendA",} 20.0

# HELP resilience4j_circuitbreaker_max_buffered_calls The maximum number of buffered calls which can be stored in the ring buffer
# TYPE resilience4j_circuitbreaker_max_buffered_calls gauge
resilience4j_circuitbreaker_max_buffered_calls{name="backendA",} 5.0

# HELP resilience4j_circuitbreaker_calls_seconds_max Total duration of calls
# TYPE resilience4j_circuitbreaker_calls_seconds_max gauge
resilience4j_circuitbreaker_calls_seconds_max{kind="successful",name="backendA",} 0.0
resilience4j_circuitbreaker_calls_seconds_max{kind="failed",name="backendA",} 0.0
resilience4j_circuitbreaker_calls_seconds_max{kind="ignored",name="backendA",} 0.0

resilience4j_circuitbreaker_calls_seconds_sum{kind="ignored",name="backendA",} 0.0

# HELP resilience4j_circuitbreaker_calls_seconds Total number of successful calls
# TYPE resilience4j_circuitbreaker_calls_seconds histogram
resilience4j_circuitbreaker_calls_seconds_count{kind="successful",name="backendA",} 0.0
resilience4j_circuitbreaker_calls_seconds_sum{kind="successful",name="backendA",} 0.0

# HELP resilience4j_circuitbreaker_calls_seconds Total number of failed calls
# TYPE resilience4j_circuitbreaker_calls_seconds histogram
resilience4j_circuitbreaker_calls_seconds_count{kind="failed",name="backendA",} 0.0
resilience4j_circuitbreaker_calls_seconds_sum{kind="failed",name="backendA",} 0.0

The following metrics are exported per Bulkhead:

# HELP resilience4j_bulkhead_available_concurrent_calls The number of available permissions
# TYPE resilience4j_bulkhead_available_concurrent_calls gauge
resilience4j_bulkhead_available_concurrent_calls{name="backendA",} 10.0

# HELP resilience4j_bulkhead_max_allowed_concurrent_calls The maximum number available permissions
# TYPE resilience4j_bulkhead_max_allowed_concurrent_calls gauge
resilience4j_bulkhead_max_allowed_concurrent_calls{name="backendA",} 10.0

The following metrics are exported per Retry:

# HELP resilience4j_retry_calls The number of successful calls without a retry attempt
# TYPE resilience4j_retry_calls gauge
resilience4j_retry_calls{kind="failed_with_retry",name="backendA",} 0.0
resilience4j_retry_calls{kind="failed_without_retry",name="backendA",} 0.0
resilience4j_retry_calls{kind="successful_without_retry",name="backendA",} 0.0
resilience4j_retry_calls{kind="successful_with_retry",name="backendA",} 0.0

The following metrics are exported per RateLimiter:

# HELP resilience4j_ratelimiter_waiting_threads The number of waiting threads
# TYPE resilience4j_ratelimiter_waiting_threads gauge
resilience4j_ratelimiter_waiting_threads{name="backendA",} 0.0

# HELP resilience4j_ratelimiter_available_permissions The number of available permissions
# TYPE resilience4j_ratelimiter_available_permissions gauge
resilience4j_ratelimiter_available_permissions{name="backendA",} 50.0