Skip to content

Commit f8d0e5a

Browse files
dlsrb6342RobWin
authored andcommitted
Issue ReactiveX#571: Spring Boot HealthIndicators use the registries now
1 parent ab93819 commit f8d0e5a

File tree

30 files changed

+488
-329
lines changed

30 files changed

+488
-329
lines changed

resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationProperties.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,17 @@
2525
import java.time.Duration;
2626
import java.util.HashMap;
2727
import java.util.Map;
28+
import java.util.Optional;
2829

2930
public class RateLimiterConfigurationProperties {
3031

3132
private Map<String, InstanceProperties> instances = new HashMap<>();
3233
private Map<String, InstanceProperties> configs = new HashMap<>();
3334

35+
public Optional<InstanceProperties> findRateLimiterProperties(String name) {
36+
return Optional.ofNullable(instances.get(name));
37+
}
38+
3439
public RateLimiterConfig createRateLimiterConfig(@Nullable InstanceProperties instanceProperties) {
3540
if (instanceProperties == null) {
3641
return RateLimiterConfig.ofDefaults();

resilience4j-spring-boot-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractCircuitBreakerConfigurationOnMissingBean.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package io.github.resilience4j.circuitbreaker.autoconfigure;
1717

18-
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
1918
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
2019
import io.github.resilience4j.circuitbreaker.configure.*;
2120
import io.github.resilience4j.circuitbreaker.event.CircuitBreakerEvent;
@@ -54,18 +53,12 @@ public CircuitBreakerRegistry circuitBreakerRegistry(EventConsumerRegistry<Circu
5453
// Register the event consumers
5554
circuitBreakerConfiguration.registerEventConsumer(circuitBreakerRegistry, eventConsumerRegistry);
5655

57-
// Register a consumer to hook up any health indicators for circuit breakers after creation. This will catch ones that get
58-
// created beyond initially configured backends.
59-
circuitBreakerRegistry.getEventPublisher().onEntryAdded(event -> createHealthIndicatorForCircuitBreaker(event.getAddedEntry(), circuitBreakerProperties));
60-
6156
// Initialize backends that were initially configured.
6257
circuitBreakerConfiguration.initCircuitBreakerRegistry(circuitBreakerRegistry);
6358

6459
return circuitBreakerRegistry;
6560
}
6661

67-
protected abstract void createHealthIndicatorForCircuitBreaker(CircuitBreaker circuitBreaker, CircuitBreakerConfigurationProperties circuitBreakerProperties);
68-
6962
@Bean
7063
@ConditionalOnMissingBean
7164
@Conditional(value = {AspectJOnClasspathCondition.class})
Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,19 @@
1818

1919
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
2020
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
21+
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
22+
import io.github.resilience4j.circuitbreaker.configure.CircuitBreakerConfigurationProperties;
2123
import org.springframework.boot.actuate.health.Health;
24+
import org.springframework.boot.actuate.health.HealthAggregator;
2225
import org.springframework.boot.actuate.health.HealthIndicator;
2326

24-
import java.util.Optional;
27+
import java.util.Map;
28+
import java.util.stream.Collectors;
2529

2630
/**
2731
* A Spring Boot health indicators which adds the state of a CircuitBreaker and it's metrics to the health endpoints
2832
*/
29-
public class CircuitBreakerHealthIndicator implements HealthIndicator {
33+
public class CircuitBreakersHealthIndicator implements HealthIndicator {
3034

3135
private static final String FAILURE_RATE = "failureRate";
3236
private static final String SLOW_CALL_RATE = "slowCallRate";
@@ -37,20 +41,35 @@ public class CircuitBreakerHealthIndicator implements HealthIndicator {
3741
private static final String SLOW_CALLS = "slowCalls";
3842
private static final String NOT_PERMITTED = "notPermittedCalls";
3943
private static final String STATE = "state";
40-
private final CircuitBreaker circuitBreaker;
4144

42-
public CircuitBreakerHealthIndicator(CircuitBreaker circuitBreaker) {
43-
this.circuitBreaker = circuitBreaker;
45+
private final CircuitBreakerRegistry circuitBreakerRegistry;
46+
private final CircuitBreakerConfigurationProperties circuitBreakerProperties;
47+
private final HealthAggregator healthAggregator;
48+
49+
public CircuitBreakersHealthIndicator(CircuitBreakerRegistry circuitBreakerRegistry,
50+
CircuitBreakerConfigurationProperties circuitBreakerProperties,
51+
HealthAggregator healthAggregator) {
52+
this.circuitBreakerRegistry = circuitBreakerRegistry;
53+
this.circuitBreakerProperties = circuitBreakerProperties;
54+
this.healthAggregator = healthAggregator;
4455
}
4556

4657
@Override
4758
public Health health() {
48-
return Optional.of(circuitBreaker)
49-
.map(this::mapBackendMonitorState)
50-
.orElse(Health.up().build());
59+
Map<String, Health> healths = circuitBreakerRegistry.getAllCircuitBreakers().toJavaStream()
60+
.filter(this::isRegisterHealthIndicator)
61+
.collect(Collectors.toMap(CircuitBreaker::getName, CircuitBreakersHealthIndicator::mapBackendMonitorState));
62+
63+
return healthAggregator.aggregate(healths);
64+
}
65+
66+
private boolean isRegisterHealthIndicator(CircuitBreaker circuitBreaker) {
67+
return circuitBreakerProperties.findCircuitBreakerProperties(circuitBreaker.getName())
68+
.map(io.github.resilience4j.common.circuitbreaker.configuration.CircuitBreakerConfigurationProperties.InstanceProperties::getRegisterHealthIndicator)
69+
.orElse(true);
5170
}
5271

53-
private Health mapBackendMonitorState(CircuitBreaker circuitBreaker) {
72+
private static Health mapBackendMonitorState(CircuitBreaker circuitBreaker) {
5473
switch (circuitBreaker.getState()) {
5574
case CLOSED:
5675
return addDetails(Health.up(), circuitBreaker).build();
@@ -63,7 +82,7 @@ private Health mapBackendMonitorState(CircuitBreaker circuitBreaker) {
6382
}
6483
}
6584

66-
private Health.Builder addDetails(Health.Builder builder, CircuitBreaker circuitBreaker) {
85+
private static Health.Builder addDetails(Health.Builder builder, CircuitBreaker circuitBreaker) {
6786
CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics();
6887
CircuitBreakerConfig config = circuitBreaker.getCircuitBreakerConfig();
6988
builder.withDetail(FAILURE_RATE, metrics.getFailureRate() + "%")
Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,57 @@
1616
package io.github.resilience4j.ratelimiter.monitoring.health;
1717

1818
import io.github.resilience4j.ratelimiter.RateLimiter;
19+
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;
20+
import io.github.resilience4j.ratelimiter.configure.RateLimiterConfigurationProperties;
1921
import io.github.resilience4j.ratelimiter.internal.AtomicRateLimiter;
2022
import org.springframework.boot.actuate.health.Health;
23+
import org.springframework.boot.actuate.health.HealthAggregator;
2124
import org.springframework.boot.actuate.health.HealthIndicator;
2225
import org.springframework.boot.actuate.health.Status;
2326

24-
public class RateLimiterHealthIndicator implements HealthIndicator {
27+
import java.util.Map;
28+
import java.util.stream.Collectors;
2529

26-
private final RateLimiter rateLimiter;
27-
private final long timeoutInNanos;
30+
public class RateLimitersHealthIndicator implements HealthIndicator {
2831

29-
public RateLimiterHealthIndicator(RateLimiter rateLimiter) {
30-
this.rateLimiter = rateLimiter;
31-
this.timeoutInNanos = rateLimiter.getRateLimiterConfig().getTimeoutDuration().toNanos();
32+
private final RateLimiterRegistry rateLimiterRegistry;
33+
private final RateLimiterConfigurationProperties rateLimiterProperties;
34+
private final HealthAggregator healthAggregator;
35+
36+
public RateLimitersHealthIndicator(RateLimiterRegistry rateLimiterRegistry,
37+
RateLimiterConfigurationProperties rateLimiterProperties,
38+
HealthAggregator healthAggregator) {
39+
this.rateLimiterRegistry = rateLimiterRegistry;
40+
this.rateLimiterProperties = rateLimiterProperties;
41+
this.healthAggregator = healthAggregator;
3242
}
3343

3444
@Override
3545
public Health health() {
46+
Map<String, Health> healths = rateLimiterRegistry.getAllRateLimiters().toJavaStream()
47+
.filter(this::isRegisterHealthIndicator)
48+
.collect(Collectors.toMap(RateLimiter::getName, this::mapRateLimiterHealth));
49+
50+
return healthAggregator.aggregate(healths);
51+
}
52+
53+
private boolean isRegisterHealthIndicator(RateLimiter rateLimiter) {
54+
return rateLimiterProperties.findRateLimiterProperties(rateLimiter.getName())
55+
.map(io.github.resilience4j.common.ratelimiter.configuration.RateLimiterConfigurationProperties.InstanceProperties::getRegisterHealthIndicator)
56+
.orElse(true);
57+
}
58+
59+
private Health mapRateLimiterHealth(RateLimiter rateLimiter) {
3660
RateLimiter.Metrics metrics = rateLimiter.getMetrics();
3761
int availablePermissions = metrics.getAvailablePermissions();
3862
int numberOfWaitingThreads = metrics.getNumberOfWaitingThreads();
63+
long timeoutInNanos = rateLimiter.getRateLimiterConfig().getTimeoutDuration().toNanos();
64+
3965
if (availablePermissions > 0 || numberOfWaitingThreads == 0) {
4066
return rateLimiterHealth(Status.UP, availablePermissions, numberOfWaitingThreads);
4167
}
4268
if (rateLimiter instanceof AtomicRateLimiter) {
43-
AtomicRateLimiter atomicRateLimiter = (AtomicRateLimiter) this.rateLimiter;
69+
AtomicRateLimiter atomicRateLimiter = (AtomicRateLimiter) rateLimiter;
4470
AtomicRateLimiter.AtomicRateLimiterMetrics detailedMetrics = atomicRateLimiter.getDetailedMetrics();
4571
if (detailedMetrics.getNanosToWait() > timeoutInNanos) {
4672
return rateLimiterHealth(Status.DOWN, availablePermissions, numberOfWaitingThreads);
@@ -49,10 +75,10 @@ public Health health() {
4975
return rateLimiterHealth(Status.UNKNOWN, availablePermissions, numberOfWaitingThreads);
5076
}
5177

52-
private Health rateLimiterHealth(Status status, int availablePermissions, int numberOfWaitingThreads) {
78+
private static Health rateLimiterHealth(Status status, int availablePermissions, int numberOfWaitingThreads) {
5379
return Health.status(status)
5480
.withDetail("availablePermissions", availablePermissions)
5581
.withDetail("numberOfWaitingThreads", numberOfWaitingThreads)
5682
.build();
5783
}
58-
}
84+
}

resilience4j-spring-boot-common/src/test/java/io/github/resilience4j/SpringBootCommonTest.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import io.github.resilience4j.bulkhead.ThreadPoolBulkheadRegistry;
2020
import io.github.resilience4j.bulkhead.autoconfigure.AbstractBulkheadConfigurationOnMissingBean;
2121
import io.github.resilience4j.bulkhead.configure.BulkheadConfigurationProperties;
22-
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
2322
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
2423
import io.github.resilience4j.circuitbreaker.autoconfigure.AbstractCircuitBreakerConfigurationOnMissingBean;
2524
import io.github.resilience4j.circuitbreaker.configure.CircuitBreakerConfigurationProperties;
@@ -93,10 +92,6 @@ public CircuitBreakerConfig(CircuitBreakerConfigurationProperties circuitBreaker
9392
super(circuitBreakerProperties);
9493
}
9594

96-
@Override
97-
protected void createHealthIndicatorForCircuitBreaker(CircuitBreaker circuitBreaker, CircuitBreakerConfigurationProperties circuitBreakerProperties) {
98-
99-
}
10095
}
10196

10297
class RetryConfigurationOnMissingBean extends AbstractRetryConfigurationOnMissingBean {

resilience4j-spring-boot-common/src/test/java/io/github/resilience4j/circuitbreaker/monitoring/health/CircuitBreakerHealthIndicatorTest.java

Lines changed: 0 additions & 98 deletions
This file was deleted.

0 commit comments

Comments
 (0)