Merge branch '2.1.x'
This commit is contained in:
@@ -28,7 +28,10 @@ import io.github.resilience4j.micrometer.tagged.TaggedCircuitBreakerMetrics;
|
||||
import io.github.resilience4j.micrometer.tagged.TaggedCircuitBreakerMetricsPublisher;
|
||||
import io.github.resilience4j.micrometer.tagged.TaggedThreadPoolBulkheadMetrics;
|
||||
import io.github.resilience4j.timelimiter.TimeLimiterRegistry;
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Tag;
|
||||
import io.micrometer.core.instrument.config.MeterFilter;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -36,6 +39,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
|
||||
import org.springframework.cloud.client.circuitbreaker.Customizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -47,6 +51,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
* @author Andrii Bohutskyi
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(Resilience4JConfigurationProperties.class)
|
||||
@ConditionalOnProperty(name = { "spring.cloud.circuitbreaker.resilience4j.enabled",
|
||||
"spring.cloud.circuitbreaker.resilience4j.blocking.enabled" }, matchIfMissing = true)
|
||||
public class Resilience4JAutoConfiguration {
|
||||
@@ -84,6 +89,31 @@ public class Resilience4JAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnBean({ MeterRegistry.class })
|
||||
public static class MicrometerResilience4JGroupCustomizerConfiguration {
|
||||
|
||||
private static final String RESILIENCE4J_METER_PREFIX = "resilience4j";
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "spring.cloud.circuitbreaker.resilience4j.enableGroupMeterFilter",
|
||||
havingValue = "true", matchIfMissing = true)
|
||||
MeterFilter resilience4JMeterFilter(Resilience4JConfigurationProperties properties) {
|
||||
return new MeterFilter() {
|
||||
@Override
|
||||
public Meter.Id map(Meter.Id id) {
|
||||
if (id.getName().startsWith(RESILIENCE4J_METER_PREFIX)
|
||||
&& id.getTag(Resilience4JCircuitBreaker.CIRCUIT_BREAKER_GROUP_TAG) == null) {
|
||||
return id.withTag(Tag.of(Resilience4JCircuitBreaker.CIRCUIT_BREAKER_GROUP_TAG,
|
||||
properties.getDefaultGroupTag()));
|
||||
}
|
||||
return id;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnBean({ MeterRegistry.class })
|
||||
@ConditionalOnClass(name = { "io.github.resilience4j.micrometer.tagged.TaggedCircuitBreakerMetrics",
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.circuitbreaker.resilience4j;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.circuitbreaker.resilience4j")
|
||||
public class Resilience4JConfigurationProperties {
|
||||
|
||||
private boolean enableGroupMeterFilter = true;
|
||||
|
||||
private String defaultGroupTag = "none";
|
||||
|
||||
public boolean isEnableGroupMeterFilter() {
|
||||
return enableGroupMeterFilter;
|
||||
}
|
||||
|
||||
public void setEnableGroupMeterFilter(boolean enableGroupMeterFilter) {
|
||||
this.enableGroupMeterFilter = enableGroupMeterFilter;
|
||||
}
|
||||
|
||||
public String getDefaultGroupTag() {
|
||||
return defaultGroupTag;
|
||||
}
|
||||
|
||||
public void setDefaultGroupTag(String defaultGroupTag) {
|
||||
this.defaultGroupTag = defaultGroupTag;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.circuitbreaker.resilience4j;
|
||||
|
||||
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
|
||||
import io.github.resilience4j.timelimiter.TimeLimiterRegistry;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class Resilience4JAutoConfigurationTests {
|
||||
|
||||
static Resilience4JCircuitBreakerFactory circuitBreakerFactory = spy(new Resilience4JCircuitBreakerFactory(
|
||||
CircuitBreakerRegistry.ofDefaults(), TimeLimiterRegistry.ofDefaults(), null));
|
||||
|
||||
@Test
|
||||
public void meterFilterEnabled() {
|
||||
try (ConfigurableApplicationContext context = new SpringApplicationBuilder().web(WebApplicationType.NONE)
|
||||
.sources(Resilience4JAutoConfigurationTests.TestApp.class).run()) {
|
||||
assertThat(context.getBean("resilience4JMeterFilter")).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void meterFilterDisabled() {
|
||||
try (ConfigurableApplicationContext context = new SpringApplicationBuilder().web(WebApplicationType.NONE)
|
||||
.sources(Resilience4JAutoConfigurationTests.TestApp.class)
|
||||
.properties("spring.cloud.circuitbreaker.resilience4j.enableGroupMeterFilter=false").run()) {
|
||||
assertThat(context.containsBean("resilience4JMeterFilter")).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@SpringBootConfiguration
|
||||
@EnableAutoConfiguration
|
||||
protected static class TestApp {
|
||||
|
||||
@Bean
|
||||
Resilience4JCircuitBreakerFactory circuitBreakerFactory() {
|
||||
return circuitBreakerFactory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.springframework.cloud.circuitbreaker.resilience4j;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -87,6 +89,9 @@ public class Resilience4JBulkheadIntegrationTest {
|
||||
@Autowired
|
||||
Application.DemoControllerService service;
|
||||
|
||||
@Autowired
|
||||
private TestRestTemplate rest;
|
||||
|
||||
@Test
|
||||
public void testSlow() {
|
||||
assertThat(service.slow()).isEqualTo("fallback");
|
||||
@@ -132,6 +137,17 @@ public class Resilience4JBulkheadIntegrationTest {
|
||||
verify(Application.slowThreadPoolRejectedConsumer, times(1)).consumeEvent(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResilience4JMetricsAvailable() {
|
||||
assertThat(service.normal()).isEqualTo("normal");
|
||||
assertThat(((List) rest.getForObject("/actuator/metrics", Map.class).get("names"))
|
||||
.contains("resilience4j.bulkhead.max.thread.pool.size")).isTrue();
|
||||
|
||||
assertThat(((List) rest
|
||||
.getForObject("/actuator/metrics/resilience4j.bulkhead.max.thread.pool.size?tag=group:none", Map.class)
|
||||
.get("availableTags"))).hasSize(1);
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableAutoConfiguration
|
||||
@RestController
|
||||
|
||||
Reference in New Issue
Block a user