From 6d2f870e6bcb4a09d346b9888adf25dd8a09b9f8 Mon Sep 17 00:00:00 2001 From: MRomeh Date: Fri, 13 Dec 2019 11:04:59 +0100 Subject: [PATCH] Issue #509: Added Spring support for custom global tags (#749) --- .../bulkhead/BulkheadRegistry.java | 16 ++ .../bulkhead/BulkheadRegistryTest.java | 8 + .../CircuitBreakerRegistry.java | 17 ++ .../InMemoryCircuitBreakerRegistry.java | 14 ++ .../CircuitBreakerRegistryTest.java | 11 ++ .../io/github/resilience4j/core/Registry.java | 6 + .../core/registry/AbstractRegistry.java | 11 +- .../core/registry/AbstractRegistryTest.java | 15 ++ .../resilience4j/common/CommonProperties.java | 46 +++++ .../BulkheadConfigurationProperties.java | 5 +- ...adPoolBulkheadConfigurationProperties.java | 5 +- ...CircuitBreakerConfigurationProperties.java | 17 +- .../RateLimiterConfigurationProperties.java | 22 ++- .../RetryConfigurationProperties.java | 7 +- .../BulkheadConfigurationPropertiesTest.java | 13 +- ...uitBreakerConfigurationPropertiesTest.java | 7 +- ...ateLimiterConfigurationPropertiesTest.java | 7 +- .../RetryConfigurationPropertiesTest.java | 7 +- .../tagged/AbstractBulkheadMetrics.java | 60 +++--- .../tagged/AbstractCircuitBreakerMetrics.java | 178 ++++++++++-------- .../micrometer/tagged/AbstractMetrics.java | 10 + .../tagged/AbstractRateLimiterMetrics.java | 52 ++--- .../tagged/AbstractRetryMetrics.java | 73 +++---- .../AbstractThreadPoolBulkheadMetrics.java | 113 ++++++----- .../ratelimiter/RateLimiterRegistry.java | 16 ++ .../ratelimiter/RateLimiterRegistryTest.java | 10 + .../resilience4j/retry/RetryRegistry.java | 16 ++ .../resilience4j/retry/RetryRegistryTest.java | 10 + ...cuitBreakerConfigurationOnMissingBean.java | 2 - .../src/test/resources/application.yaml | 16 ++ ...reshScopedCircuitBreakerConfiguration.java | 2 - .../configure/BulkheadConfiguration.java | 9 +- .../ThreadPoolBulkheadConfiguration.java | 17 +- .../CircuitBreakerConfiguration.java | 5 +- .../configure/RateLimiterConfiguration.java | 10 +- .../retry/configure/RetryConfiguration.java | 8 +- 36 files changed, 575 insertions(+), 266 deletions(-) create mode 100644 resilience4j-framework-common/src/main/java/io/github/resilience4j/common/CommonProperties.java diff --git a/resilience4j-bulkhead/src/main/java/io/github/resilience4j/bulkhead/BulkheadRegistry.java b/resilience4j-bulkhead/src/main/java/io/github/resilience4j/bulkhead/BulkheadRegistry.java index 809e019540..e60e7fe29f 100644 --- a/resilience4j-bulkhead/src/main/java/io/github/resilience4j/bulkhead/BulkheadRegistry.java +++ b/resilience4j-bulkhead/src/main/java/io/github/resilience4j/bulkhead/BulkheadRegistry.java @@ -124,6 +124,22 @@ static BulkheadRegistry of(Map configs, return new InMemoryBulkheadRegistry(configs, registryEventConsumer); } + /** + * Creates a BulkheadRegistry with a Map of shared Bulkhead configurations and a Bulkhead + * registry event consumer. + * + * @param configs a Map of shared Bulkhead configurations. + * @param registryEventConsumer a Bulkhead registry event consumer. + * @param tags default tags to add to the registry + * @return a BulkheadRegistry with a Map of shared Bulkhead configurations and a Bulkhead + * registry event consumer. + */ + static BulkheadRegistry of(Map configs, + RegistryEventConsumer registryEventConsumer, + io.vavr.collection.Map tags) { + return new InMemoryBulkheadRegistry(configs, registryEventConsumer, tags); + } + /** * Creates a BulkheadRegistry with a Map of shared Bulkhead configurations and a list of * Bulkhead registry event consumers. diff --git a/resilience4j-bulkhead/src/test/java/io/github/resilience4j/bulkhead/BulkheadRegistryTest.java b/resilience4j-bulkhead/src/test/java/io/github/resilience4j/bulkhead/BulkheadRegistryTest.java index 8911e5cee0..135dd683a6 100644 --- a/resilience4j-bulkhead/src/test/java/io/github/resilience4j/bulkhead/BulkheadRegistryTest.java +++ b/resilience4j-bulkhead/src/test/java/io/github/resilience4j/bulkhead/BulkheadRegistryTest.java @@ -24,6 +24,7 @@ import io.github.resilience4j.core.registry.EntryRemovedEvent; import io.github.resilience4j.core.registry.EntryReplacedEvent; import io.github.resilience4j.core.registry.RegistryEventConsumer; +import io.vavr.Tuple; import org.assertj.core.api.Assertions; import org.junit.Before; import org.junit.Test; @@ -54,6 +55,13 @@ public void setUp() { .build(); } + @Test + public void shouldInitRegistryTags() { + BulkheadRegistry registry = BulkheadRegistry.of(config,io.vavr.collection.HashMap.of("Tag1Key","Tag1Value")); + assertThat(registry.getTags()).isNotEmpty(); + assertThat(registry.getTags()).containsOnly(Tuple.of("Tag1Key","Tag1Value")); + } + @Test public void shouldReturnCustomConfig() { BulkheadRegistry registry = BulkheadRegistry.of(config); diff --git a/resilience4j-circuitbreaker/src/main/java/io/github/resilience4j/circuitbreaker/CircuitBreakerRegistry.java b/resilience4j-circuitbreaker/src/main/java/io/github/resilience4j/circuitbreaker/CircuitBreakerRegistry.java index 37c0d5e6e0..c6839ee8c9 100644 --- a/resilience4j-circuitbreaker/src/main/java/io/github/resilience4j/circuitbreaker/CircuitBreakerRegistry.java +++ b/resilience4j-circuitbreaker/src/main/java/io/github/resilience4j/circuitbreaker/CircuitBreakerRegistry.java @@ -111,6 +111,23 @@ static CircuitBreakerRegistry of(Map configs, return new InMemoryCircuitBreakerRegistry(configs, registryEventConsumer); } + /** + * Creates a CircuitBreakerRegistry with a Map of shared CircuitBreaker configurations and a + * CircuitBreaker registry event consumer. + * + * @param configs a Map of shared CircuitBreaker configurations. + * @param registryEventConsumer a CircuitBreaker registry event consumer. + * @param tags default tags to add to the registry + * @return a CircuitBreakerRegistry with a Map of shared CircuitBreaker configurations and a + * CircuitBreaker registry event consumer. + */ + static CircuitBreakerRegistry of(Map configs, + RegistryEventConsumer registryEventConsumer, + io.vavr.collection.Map tags) { + return new InMemoryCircuitBreakerRegistry(configs, registryEventConsumer, tags); + } + + /** * Creates a CircuitBreakerRegistry with a Map of shared CircuitBreaker configurations and a * list of CircuitBreaker registry event consumers. diff --git a/resilience4j-circuitbreaker/src/main/java/io/github/resilience4j/circuitbreaker/internal/InMemoryCircuitBreakerRegistry.java b/resilience4j-circuitbreaker/src/main/java/io/github/resilience4j/circuitbreaker/internal/InMemoryCircuitBreakerRegistry.java index 9c66dd67ea..6e37fe1976 100644 --- a/resilience4j-circuitbreaker/src/main/java/io/github/resilience4j/circuitbreaker/internal/InMemoryCircuitBreakerRegistry.java +++ b/resilience4j-circuitbreaker/src/main/java/io/github/resilience4j/circuitbreaker/internal/InMemoryCircuitBreakerRegistry.java @@ -68,6 +68,14 @@ public InMemoryCircuitBreakerRegistry(Map configs, this.configurations.putAll(configs); } + public InMemoryCircuitBreakerRegistry(Map configs, + RegistryEventConsumer registryEventConsumer, + io.vavr.collection.Map tags) { + this(configs.getOrDefault(DEFAULT_CONFIG, CircuitBreakerConfig.ofDefaults()), + registryEventConsumer, tags); + this.configurations.putAll(configs); + } + public InMemoryCircuitBreakerRegistry(Map configs, List> registryEventConsumers) { this(configs.getOrDefault(DEFAULT_CONFIG, CircuitBreakerConfig.ofDefaults()), @@ -100,6 +108,12 @@ public InMemoryCircuitBreakerRegistry(CircuitBreakerConfig defaultConfig, super(defaultConfig, registryEventConsumer); } + public InMemoryCircuitBreakerRegistry(CircuitBreakerConfig defaultConfig, + RegistryEventConsumer registryEventConsumer, + io.vavr.collection.Map tags) { + super(defaultConfig, registryEventConsumer, tags); + } + public InMemoryCircuitBreakerRegistry(CircuitBreakerConfig defaultConfig, List> registryEventConsumers) { super(defaultConfig, registryEventConsumers); diff --git a/resilience4j-circuitbreaker/src/test/java/io/github/resilience4j/circuitbreaker/CircuitBreakerRegistryTest.java b/resilience4j-circuitbreaker/src/test/java/io/github/resilience4j/circuitbreaker/CircuitBreakerRegistryTest.java index 0f0133e744..13d71e39d2 100644 --- a/resilience4j-circuitbreaker/src/test/java/io/github/resilience4j/circuitbreaker/CircuitBreakerRegistryTest.java +++ b/resilience4j-circuitbreaker/src/test/java/io/github/resilience4j/circuitbreaker/CircuitBreakerRegistryTest.java @@ -24,6 +24,7 @@ import io.github.resilience4j.core.registry.EntryRemovedEvent; import io.github.resilience4j.core.registry.EntryReplacedEvent; import io.github.resilience4j.core.registry.RegistryEventConsumer; +import io.vavr.Tuple; import org.junit.Test; import java.util.*; @@ -43,6 +44,16 @@ private static Optional> getEventProcessor( return Optional.empty(); } + @Test + public void shouldInitRegistryTags() { + CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.ofDefaults(); + Map circuitBreakerConfigs = Collections + .singletonMap("default", circuitBreakerConfig); + CircuitBreakerRegistry registry = CircuitBreakerRegistry.of(circuitBreakerConfigs,new NoOpCircuitBreakerEventConsumer(),io.vavr.collection.HashMap.of("Tag1Key","Tag1Value")); + assertThat(registry.getTags()).isNotEmpty(); + assertThat(registry.getTags()).containsOnly(Tuple.of("Tag1Key","Tag1Value")); + } + @Test public void shouldReturnTheCorrectName() { CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults(); diff --git a/resilience4j-core/src/main/java/io/github/resilience4j/core/Registry.java b/resilience4j-core/src/main/java/io/github/resilience4j/core/Registry.java index efcd92637a..07e2101a03 100644 --- a/resilience4j-core/src/main/java/io/github/resilience4j/core/Registry.java +++ b/resilience4j-core/src/main/java/io/github/resilience4j/core/Registry.java @@ -22,6 +22,7 @@ import io.github.resilience4j.core.registry.EntryRemovedEvent; import io.github.resilience4j.core.registry.EntryReplacedEvent; import io.github.resilience4j.core.registry.RegistryEvent; +import io.vavr.collection.Map; import java.util.Optional; @@ -75,6 +76,11 @@ public interface Registry { */ C getDefaultConfig(); + /** + * @return global configured registry tags + */ + Map getTags(); + /** * Returns an EventPublisher which can be used to register event consumers. * diff --git a/resilience4j-core/src/main/java/io/github/resilience4j/core/registry/AbstractRegistry.java b/resilience4j-core/src/main/java/io/github/resilience4j/core/registry/AbstractRegistry.java index 36ea009ec7..eb97b5ab6c 100644 --- a/resilience4j-core/src/main/java/io/github/resilience4j/core/registry/AbstractRegistry.java +++ b/resilience4j-core/src/main/java/io/github/resilience4j/core/registry/AbstractRegistry.java @@ -24,7 +24,11 @@ import io.vavr.collection.HashMap; import io.vavr.collection.Map; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.function.Supplier; @@ -132,6 +136,11 @@ public C getDefaultConfig() { return configurations.get(DEFAULT_CONFIG); } + @Override + public Map getTags() { + return registryTags; + } + @Override public EventPublisher getEventPublisher() { return eventProcessor; diff --git a/resilience4j-core/src/test/java/io/github/resilience4j/core/registry/AbstractRegistryTest.java b/resilience4j-core/src/test/java/io/github/resilience4j/core/registry/AbstractRegistryTest.java index e83e53db25..3693510201 100644 --- a/resilience4j-core/src/test/java/io/github/resilience4j/core/registry/AbstractRegistryTest.java +++ b/resilience4j-core/src/test/java/io/github/resilience4j/core/registry/AbstractRegistryTest.java @@ -1,5 +1,7 @@ package io.github.resilience4j.core.registry; +import io.vavr.Tuple; +import io.vavr.collection.Map; import org.junit.Test; import java.util.ArrayList; @@ -13,6 +15,14 @@ public class AbstractRegistryTest { + @Test + public void shouldInitRegistryTags(){ + TestRegistry testRegistry = new TestRegistry(io.vavr.collection.HashMap.of("Tag1","Tag1Value")); + assertThat(testRegistry.getTags()).isNotEmpty(); + assertThat(testRegistry.getTags()).containsOnly(Tuple.of("Tag1","Tag1Value")); + } + + @Test public void shouldContainDefaultAndCustomConfiguration() { TestRegistry testRegistry = new TestRegistry(); @@ -150,6 +160,11 @@ static class TestRegistry extends AbstractRegistry { super("default", registryEventConsumer); this.configurations.put(DEFAULT_CONFIG, "default"); } + + TestRegistry(Map tags) { + super("default", tags); + this.configurations.put(DEFAULT_CONFIG, "default"); + } } } diff --git a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/CommonProperties.java b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/CommonProperties.java new file mode 100644 index 0000000000..e932a13690 --- /dev/null +++ b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/CommonProperties.java @@ -0,0 +1,46 @@ +/* + * Copyright Mahmoud Romeh + * + * 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 + * + * http://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 io.github.resilience4j.common; + +import java.util.HashMap; +import java.util.Map; + +/** + * common properties between different spring resilience4j supported types + */ +public class CommonProperties { + + /** + * The Optional configured global registry tags if any that can be used with the exported + * metrics + */ + Map tags = new HashMap<>(); + + /** + * @return the Optional configured registry global tags if any that can be used with the + * exported metrics + */ + public Map getTags() { + return tags; + } + + /** + * @param tags the optional configured tags values into registry + */ + public void setTags(Map tags) { + this.tags = tags; + } +} diff --git a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/bulkhead/configuration/BulkheadConfigurationProperties.java b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/bulkhead/configuration/BulkheadConfigurationProperties.java index 72e5a25a10..c347ce47a9 100644 --- a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/bulkhead/configuration/BulkheadConfigurationProperties.java +++ b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/bulkhead/configuration/BulkheadConfigurationProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Dan Maas + * Copyright 2019 Dan Maas , Mahmoud Romeh * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package io.github.resilience4j.common.bulkhead.configuration; import io.github.resilience4j.bulkhead.BulkheadConfig; +import io.github.resilience4j.common.CommonProperties; import io.github.resilience4j.common.utils.ConfigUtils; import io.github.resilience4j.core.ConfigurationNotFoundException; import io.github.resilience4j.core.StringUtils; @@ -26,7 +27,7 @@ import java.util.Map; import java.util.Objects; -public class BulkheadConfigurationProperties { +public class BulkheadConfigurationProperties extends CommonProperties { private Map instances = new HashMap<>(); private Map configs = new HashMap<>(); diff --git a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/bulkhead/configuration/ThreadPoolBulkheadConfigurationProperties.java b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/bulkhead/configuration/ThreadPoolBulkheadConfigurationProperties.java index 15ba413f7b..ea64a909f7 100644 --- a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/bulkhead/configuration/ThreadPoolBulkheadConfigurationProperties.java +++ b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/bulkhead/configuration/ThreadPoolBulkheadConfigurationProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Dan Maas + * Copyright 2019 Dan Maas, Mahmoud Romeh * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ import io.github.resilience4j.bulkhead.Bulkhead; import io.github.resilience4j.bulkhead.ThreadPoolBulkheadConfig; +import io.github.resilience4j.common.CommonProperties; import io.github.resilience4j.core.ConfigurationNotFoundException; import io.github.resilience4j.core.StringUtils; import io.github.resilience4j.core.lang.Nullable; @@ -26,7 +27,7 @@ import java.util.Map; import java.util.Objects; -public class ThreadPoolBulkheadConfigurationProperties { +public class ThreadPoolBulkheadConfigurationProperties extends CommonProperties { private Map instances = new HashMap<>(); private Map configs = new HashMap<>(); diff --git a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigurationProperties.java b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigurationProperties.java index ca8514241d..e16bc96e24 100644 --- a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigurationProperties.java +++ b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigurationProperties.java @@ -19,6 +19,7 @@ import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig; import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.Builder; import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.SlidingWindowType; +import io.github.resilience4j.common.CommonProperties; import io.github.resilience4j.common.utils.ConfigUtils; import io.github.resilience4j.core.ClassUtils; import io.github.resilience4j.core.ConfigurationNotFoundException; @@ -36,7 +37,7 @@ import static io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.custom; import static io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.from; -public class CircuitBreakerConfigurationProperties { +public class CircuitBreakerConfigurationProperties extends CommonProperties { private Map instances = new HashMap<>(); private Map configs = new HashMap<>(); @@ -300,7 +301,6 @@ public static class InstanceProperties { */ private Double randomizedWaitFactor; - /** * Returns the failure rate threshold for the circuit breaker as percentage. * @@ -474,7 +474,8 @@ public InstanceProperties setEventConsumerBufferSize(Integer eventConsumerBuffer } /** - * @return the flag that controls if health indicators are allowed to go into a failed (DOWN) status. + * @return the flag that controls if health indicators are allowed to go into a failed + * (DOWN) status. * @see #setAllowHealthIndicatorToFail(Boolean) */ @Nullable @@ -483,13 +484,15 @@ public Boolean getAllowHealthIndicatorToFail() { } /** - * When set to true, it allows the health indicator to go to a failed (DOWN) status. - * By default, health indicators for circuit breakers will never go into an unhealthy state. + * When set to true, it allows the health indicator to go to a failed (DOWN) status. By + * default, health indicators for circuit breakers will never go into an unhealthy state. * - * @param allowHealthIndicatorToFail flag to control if the health indicator is allowed to fail + * @param allowHealthIndicatorToFail flag to control if the health indicator is allowed to + * fail * @return the InstanceProperties */ - public InstanceProperties setAllowHealthIndicatorToFail(Boolean allowHealthIndicatorToFail) { + public InstanceProperties setAllowHealthIndicatorToFail( + Boolean allowHealthIndicatorToFail) { this.allowHealthIndicatorToFail = allowHealthIndicatorToFail; return this; } diff --git a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationProperties.java b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationProperties.java index 0913a8abfd..26c03047ed 100644 --- a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationProperties.java +++ b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Dan Maas + * Copyright 2019 Dan Maas, Mahmoud Romeh * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package io.github.resilience4j.common.ratelimiter.configuration; +import io.github.resilience4j.common.CommonProperties; import io.github.resilience4j.common.utils.ConfigUtils; import io.github.resilience4j.core.ConfigurationNotFoundException; import io.github.resilience4j.core.StringUtils; @@ -27,7 +28,7 @@ import java.util.Objects; import java.util.Optional; -public class RateLimiterConfigurationProperties { +public class RateLimiterConfigurationProperties extends CommonProperties{ private Map instances = new HashMap<>(); private Map configs = new HashMap<>(); @@ -56,7 +57,7 @@ public RateLimiterConfig createRateLimiterConfig( } private RateLimiterConfig buildConfigFromBaseConfig(InstanceProperties baseProperties, - InstanceProperties instanceProperties) { + InstanceProperties instanceProperties) { ConfigUtils.mergePropertiesIfAny(baseProperties, instanceProperties); RateLimiterConfig baseConfig = buildRateLimiterConfig(RateLimiterConfig.custom(), baseProperties); @@ -64,7 +65,7 @@ private RateLimiterConfig buildConfigFromBaseConfig(InstanceProperties basePrope } private RateLimiterConfig buildRateLimiterConfig(RateLimiterConfig.Builder builder, - @Nullable InstanceProperties instanceProperties) { + @Nullable InstanceProperties instanceProperties) { if (instanceProperties == null) { return builder.build(); } @@ -249,7 +250,8 @@ public InstanceProperties setEventConsumerBufferSize(Integer eventConsumerBuffer } /** - * @return the flag that controls if health indicators are allowed to go into a failed (DOWN) status. + * @return the flag that controls if health indicators are allowed to go into a failed + * (DOWN) status. * @see #setAllowHealthIndicatorToFail(Boolean) */ @Nullable @@ -258,13 +260,15 @@ public Boolean getAllowHealthIndicatorToFail() { } /** - * When set to true, it allows the health indicator to go to a failed (DOWN) status. - * By default, health indicators for rate limiters will never go into an unhealthy state. + * When set to true, it allows the health indicator to go to a failed (DOWN) status. By + * default, health indicators for rate limiters will never go into an unhealthy state. * - * @param allowHealthIndicatorToFail flag to control if the health indicator is allowed to fail + * @param allowHealthIndicatorToFail flag to control if the health indicator is allowed to + * fail * @return the InstanceProperties */ - public InstanceProperties setAllowHealthIndicatorToFail(Boolean allowHealthIndicatorToFail) { + public InstanceProperties setAllowHealthIndicatorToFail( + Boolean allowHealthIndicatorToFail) { this.allowHealthIndicatorToFail = allowHealthIndicatorToFail; return this; } diff --git a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/retry/configuration/RetryConfigurationProperties.java b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/retry/configuration/RetryConfigurationProperties.java index e4f4eb7fae..c9b1d20389 100644 --- a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/retry/configuration/RetryConfigurationProperties.java +++ b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/retry/configuration/RetryConfigurationProperties.java @@ -1,6 +1,5 @@ -package io.github.resilience4j.common.retry.configuration; /* - * Copyright 2019 Dan Maas + * Copyright 2019 Dan Maas, Mahmoud Romeh * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package io.github.resilience4j.common.retry.configuration; +import io.github.resilience4j.common.CommonProperties; import io.github.resilience4j.common.utils.ConfigUtils; import io.github.resilience4j.core.ClassUtils; import io.github.resilience4j.core.ConfigurationNotFoundException; @@ -32,7 +33,7 @@ /** * Main spring properties for retry configuration */ -public class RetryConfigurationProperties { +public class RetryConfigurationProperties extends CommonProperties { private final Map instances = new HashMap<>(); private Map configs = new HashMap<>(); diff --git a/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/bulkhead/configuration/BulkheadConfigurationPropertiesTest.java b/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/bulkhead/configuration/BulkheadConfigurationPropertiesTest.java index f5ff3d599b..1e13361341 100644 --- a/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/bulkhead/configuration/BulkheadConfigurationPropertiesTest.java +++ b/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/bulkhead/configuration/BulkheadConfigurationPropertiesTest.java @@ -18,9 +18,13 @@ import io.github.resilience4j.bulkhead.BulkheadConfig; import io.github.resilience4j.bulkhead.ThreadPoolBulkheadConfig; import io.github.resilience4j.core.ConfigurationNotFoundException; +import io.vavr.Tuple; +import io.vavr.Tuple2; import org.junit.Test; import java.time.Duration; +import java.util.HashMap; +import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -42,8 +46,12 @@ public void tesFixedThreadPoolBulkHeadProperties() { ThreadPoolBulkheadConfigurationProperties bulkheadConfigurationProperties = new ThreadPoolBulkheadConfigurationProperties(); bulkheadConfigurationProperties.getBackends().put("backend1", backendProperties1); bulkheadConfigurationProperties.getBackends().put("backend2", backendProperties2); + Map tags=new HashMap<>(); + tags.put("testKey1","testKet2"); + bulkheadConfigurationProperties.setTags(tags); //Then + assertThat(bulkheadConfigurationProperties.getTags()).isNotEmpty(); assertThat(bulkheadConfigurationProperties.getBackends().size()).isEqualTo(2); assertThat(bulkheadConfigurationProperties.getInstances().size()).isEqualTo(2); ThreadPoolBulkheadConfig bulkhead1 = bulkheadConfigurationProperties @@ -132,9 +140,12 @@ public void testBulkHeadProperties() { BulkheadConfigurationProperties bulkheadConfigurationProperties = new BulkheadConfigurationProperties(); bulkheadConfigurationProperties.getInstances().put("backend1", instanceProperties1); bulkheadConfigurationProperties.getInstances().put("backend2", instanceProperties2); - + Map globalTags=new HashMap<>(); + globalTags.put("testKey1","testKet2"); + bulkheadConfigurationProperties.setTags(globalTags); //Then assertThat(bulkheadConfigurationProperties.getInstances().size()).isEqualTo(2); + assertThat(bulkheadConfigurationProperties.getTags()).isNotEmpty(); BulkheadConfig bulkhead1 = bulkheadConfigurationProperties .createBulkheadConfig(instanceProperties1); assertThat(bulkhead1).isNotNull(); diff --git a/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigurationPropertiesTest.java b/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigurationPropertiesTest.java index 3ba0ad4b76..ad51ab0d4e 100644 --- a/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigurationPropertiesTest.java +++ b/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigurationPropertiesTest.java @@ -21,6 +21,8 @@ import org.junit.Test; import java.time.Duration; +import java.util.HashMap; +import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -111,9 +113,12 @@ public void testCircuitBreakerIntervalFunctionProperties() { CircuitBreakerConfigurationProperties circuitBreakerConfigurationProperties = new CircuitBreakerConfigurationProperties(); circuitBreakerConfigurationProperties.getInstances().put("backend1", instanceProperties1); circuitBreakerConfigurationProperties.getInstances().put("backend2", instanceProperties2); - + Map globalTagsForCircuitBreakers=new HashMap<>(); + globalTagsForCircuitBreakers.put("testKey1","testKet2"); + circuitBreakerConfigurationProperties.setTags(globalTagsForCircuitBreakers); //Then assertThat(circuitBreakerConfigurationProperties.getInstances().size()).isEqualTo(2); + assertThat(circuitBreakerConfigurationProperties.getTags()).isNotEmpty(); assertThat(circuitBreakerConfigurationProperties.getBackends().size()).isEqualTo(2); final CircuitBreakerConfig circuitBreakerConfig1 = circuitBreakerConfigurationProperties .createCircuitBreakerConfig(instanceProperties1); diff --git a/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationPropertiesTest.java b/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationPropertiesTest.java index b2ed64a164..76694c1080 100644 --- a/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationPropertiesTest.java +++ b/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationPropertiesTest.java @@ -20,6 +20,8 @@ import org.junit.Test; import java.time.Duration; +import java.util.HashMap; +import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -48,8 +50,11 @@ public void testRateLimiterRegistry() { RateLimiterConfigurationProperties rateLimiterConfigurationProperties = new RateLimiterConfigurationProperties(); rateLimiterConfigurationProperties.getInstances().put("backend1", instanceProperties1); rateLimiterConfigurationProperties.getInstances().put("backend2", instanceProperties2); - + Map globalTagsForRateLimiters=new HashMap<>(); + globalTagsForRateLimiters.put("testKey1","testKet2"); + rateLimiterConfigurationProperties.setTags(globalTagsForRateLimiters); //Then + assertThat(rateLimiterConfigurationProperties.getTags().size()).isEqualTo(1); assertThat(rateLimiterConfigurationProperties.getInstances().size()).isEqualTo(2); assertThat(rateLimiterConfigurationProperties.getLimiters().size()).isEqualTo(2); RateLimiterConfig rateLimiter = rateLimiterConfigurationProperties diff --git a/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/retry/configuration/RetryConfigurationPropertiesTest.java b/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/retry/configuration/RetryConfigurationPropertiesTest.java index 8fd1982c5d..23baa00bf9 100644 --- a/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/retry/configuration/RetryConfigurationPropertiesTest.java +++ b/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/retry/configuration/RetryConfigurationPropertiesTest.java @@ -23,6 +23,8 @@ import org.mockito.junit.MockitoJUnitRunner; import java.time.Duration; +import java.util.HashMap; +import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -52,8 +54,11 @@ public void testRetryProperties() { RetryConfigurationProperties retryConfigurationProperties = new RetryConfigurationProperties(); retryConfigurationProperties.getInstances().put("backend1", instanceProperties1); retryConfigurationProperties.getInstances().put("backend2", instanceProperties2); - + Map globalTagsForRetries=new HashMap<>(); + globalTagsForRetries.put("testKey1","testKet2"); + retryConfigurationProperties.setTags(globalTagsForRetries); //Then + assertThat(retryConfigurationProperties.getTags().size()).isEqualTo(1); assertThat(retryConfigurationProperties.getInstances().size()).isEqualTo(2); assertThat(retryConfigurationProperties.getBackends().size()).isEqualTo(2); final RetryConfig retry1 = retryConfigurationProperties.createRetryConfig("backend1"); diff --git a/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractBulkheadMetrics.java b/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractBulkheadMetrics.java index 575e55f23c..5ca5845b15 100644 --- a/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractBulkheadMetrics.java +++ b/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractBulkheadMetrics.java @@ -25,7 +25,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.stream.Collectors; import static java.util.Objects.requireNonNull; @@ -38,26 +37,29 @@ protected AbstractBulkheadMetrics(MetricNames names) { } protected void addMetrics(MeterRegistry meterRegistry, Bulkhead bulkhead) { + List customTags = mapToTagsList(bulkhead.getTags().toJavaMap()); + addMetrics(meterRegistry, bulkhead, customTags); + } + + private void addMetrics(MeterRegistry meterRegistry, Bulkhead bulkhead, List customTags) { Set idSet = new HashSet<>(); - List customTags = bulkhead.getTags() - .toJavaMap() - .entrySet() - .stream().map(tagsEntry -> Tag.of(tagsEntry.getKey(), tagsEntry.getValue())) - .collect(Collectors.toList()); - idSet.add(Gauge.builder(names.getAvailableConcurrentCallsMetricName(), bulkhead, bh -> bh.getMetrics().getAvailableConcurrentCalls()) - .description("The number of available permissions") - .tag(TagNames.NAME, bulkhead.getName()) - .tags(customTags) - .register(meterRegistry).getId()); - idSet.add(Gauge.builder(names.getMaxAllowedConcurrentCallsMetricName(), bulkhead, bh -> bh.getMetrics().getMaxAllowedConcurrentCalls()) - .description("The maximum number of available permissions") - .tag(TagNames.NAME, bulkhead.getName()) - .tags(customTags) - .register(meterRegistry).getId()); + + idSet.add(Gauge.builder(names.getAvailableConcurrentCallsMetricName(), bulkhead, + bh -> bh.getMetrics().getAvailableConcurrentCalls()) + .description("The number of available permissions") + .tag(TagNames.NAME, bulkhead.getName()) + .tags(customTags) + .register(meterRegistry).getId()); + idSet.add(Gauge.builder(names.getMaxAllowedConcurrentCallsMetricName(), bulkhead, + bh -> bh.getMetrics().getMaxAllowedConcurrentCalls()) + .description("The maximum number of available permissions") + .tag(TagNames.NAME, bulkhead.getName()) + .tags(customTags) + .register(meterRegistry).getId()); meterIdMap.put(bulkhead.getName(), idSet); - } + } /** * Defines possible configuration for metric names. @@ -77,8 +79,8 @@ private MetricNames() { } /** - * Returns a builder for creating custom metric names. - * Note that names have default values, so only desired metrics can be renamed. + * Returns a builder for creating custom metric names. Note that names have default values, + * so only desired metrics can be renamed. * * @return The builder. */ @@ -96,8 +98,8 @@ public static MetricNames ofDefaults() { } /** - * Returns the metric name for bulkhead concurrent calls, - * defaults to {@value DEFAULT_BULKHEAD_AVAILABLE_CONCURRENT_CALLS_METRIC_NAME}. + * Returns the metric name for bulkhead concurrent calls, defaults to {@value + * DEFAULT_BULKHEAD_AVAILABLE_CONCURRENT_CALLS_METRIC_NAME}. * * @return The available concurrent calls metric name. */ @@ -106,8 +108,8 @@ public String getAvailableConcurrentCallsMetricName() { } /** - * Returns the metric name for bulkhead max available concurrent calls, - * defaults to {@value DEFAULT_BULKHEAD_MAX_ALLOWED_CONCURRENT_CALLS_METRIC_NAME}. + * Returns the metric name for bulkhead max available concurrent calls, defaults to {@value + * DEFAULT_BULKHEAD_MAX_ALLOWED_CONCURRENT_CALLS_METRIC_NAME}. * * @return The max allowed concurrent calls metric name. */ @@ -123,9 +125,11 @@ public static class Builder { private final MetricNames metricNames = new MetricNames(); /** - * Overrides the default metric name {@value TaggedBulkheadMetrics.MetricNames#DEFAULT_BULKHEAD_AVAILABLE_CONCURRENT_CALLS_METRIC_NAME} with a given one. + * Overrides the default metric name {@value TaggedBulkheadMetrics.MetricNames#DEFAULT_BULKHEAD_AVAILABLE_CONCURRENT_CALLS_METRIC_NAME} + * with a given one. * - * @param availableConcurrentCallsMetricName The available concurrent calls metric name. + * @param availableConcurrentCallsMetricName The available concurrent calls metric + * name. * @return The builder. */ public Builder availableConcurrentCallsMetricName( @@ -136,9 +140,11 @@ public Builder availableConcurrentCallsMetricName( } /** - * Overrides the default metric name {@value TaggedBulkheadMetrics.MetricNames#DEFAULT_BULKHEAD_MAX_ALLOWED_CONCURRENT_CALLS_METRIC_NAME} with a given one. + * Overrides the default metric name {@value TaggedBulkheadMetrics.MetricNames#DEFAULT_BULKHEAD_MAX_ALLOWED_CONCURRENT_CALLS_METRIC_NAME} + * with a given one. * - * @param maxAllowedConcurrentCallsMetricName The max allowed concurrent calls metric name. + * @param maxAllowedConcurrentCallsMetricName The max allowed concurrent calls metric + * name. * @return The builder. */ public Builder maxAllowedConcurrentCallsMetricName( diff --git a/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractCircuitBreakerMetrics.java b/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractCircuitBreakerMetrics.java index 6ab6baeda4..77fa23558d 100644 --- a/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractCircuitBreakerMetrics.java +++ b/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractCircuitBreakerMetrics.java @@ -22,7 +22,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.stream.Collectors; import static java.util.Objects.requireNonNull; @@ -41,85 +40,94 @@ protected AbstractCircuitBreakerMetrics(MetricNames names) { } protected void addMetrics(MeterRegistry meterRegistry, CircuitBreaker circuitBreaker) { - Set idSet = new HashSet<>(); - List customTags = circuitBreaker.getTags() - .toJavaMap() - .entrySet() - .stream().map(tagsEntry -> Tag.of(tagsEntry.getKey(), tagsEntry.getValue())) - .collect(Collectors.toList()); + List customTags = mapToTagsList(circuitBreaker.getTags() + .toJavaMap()); + registerMetrics(meterRegistry, circuitBreaker, customTags); + } + private void registerMetrics(MeterRegistry meterRegistry, CircuitBreaker circuitBreaker, + List customTags) { + Set idSet = new HashSet<>(); final CircuitBreaker.State[] states = CircuitBreaker.State.values(); for (CircuitBreaker.State state : states) { - idSet.add(Gauge.builder(names.getStateMetricName(), circuitBreaker, cb -> cb.getState() == state ? 1 : 0) - .description("The states of the circuit breaker") - .tag(TagNames.NAME, circuitBreaker.getName()) - .tag(KIND_STATE, state.name().toLowerCase()) - .tags(customTags) - .register(meterRegistry).getId()); - } - idSet.add(Gauge.builder(names.getBufferedCallsMetricName(), circuitBreaker, cb -> cb.getMetrics().getNumberOfFailedCalls()) - .description("The number of buffered failed calls stored in the ring buffer") - .tag(TagNames.NAME, circuitBreaker.getName()) - .tag(TagNames.KIND, KIND_FAILED) - .tags(customTags) - .register(meterRegistry).getId()); - idSet.add(Gauge.builder(names.getBufferedCallsMetricName(), circuitBreaker, cb -> cb.getMetrics().getNumberOfSuccessfulCalls()) - .description("The number of buffered successful calls stored in the ring buffer") - .tag(TagNames.NAME, circuitBreaker.getName()) - .tag(TagNames.KIND, KIND_SUCCESSFUL) - .tags(customTags) - .register(meterRegistry).getId()); - idSet.add(Gauge.builder(names.getSlowCallsMetricName(), circuitBreaker, cb -> cb.getMetrics().getNumberOfSlowSuccessfulCalls()) - .description("The number of slow successful which were slower than a certain threshold") - .tag(TagNames.NAME, circuitBreaker.getName()) - .tag(TagNames.KIND, KIND_SUCCESSFUL) - .tags(customTags) - .register(meterRegistry).getId()); - idSet.add(Gauge.builder(names.getSlowCallsMetricName(), circuitBreaker, cb -> cb.getMetrics().getNumberOfSlowFailedCalls()) - .description("The number of slow failed calls which were slower than a certain threshold") - .tag(TagNames.NAME, circuitBreaker.getName()) - .tag(TagNames.KIND, KIND_FAILED) - .tags(customTags) - .register(meterRegistry).getId()); - idSet.add(Gauge.builder(names.getFailureRateMetricName(), circuitBreaker, cb -> cb.getMetrics().getFailureRate()) - .description("The failure rate of the circuit breaker") - .tag(TagNames.NAME, circuitBreaker.getName()) - .tags(customTags) - .register(meterRegistry).getId()); - - idSet.add(Gauge.builder(names.getSlowCallRateMetricName(), circuitBreaker, cb -> cb.getMetrics().getSlowCallRate()) - .description("The slow call of the circuit breaker") + idSet.add(Gauge.builder(names.getStateMetricName(), circuitBreaker, + cb -> cb.getState() == state ? 1 : 0) + .description("The states of the circuit breaker") .tag(TagNames.NAME, circuitBreaker.getName()) + .tag(KIND_STATE, state.name().toLowerCase()) .tags(customTags) .register(meterRegistry).getId()); + } + idSet.add(Gauge.builder(names.getBufferedCallsMetricName(), circuitBreaker, + cb -> cb.getMetrics().getNumberOfFailedCalls()) + .description("The number of buffered failed calls stored in the ring buffer") + .tag(TagNames.NAME, circuitBreaker.getName()) + .tag(TagNames.KIND, KIND_FAILED) + .tags(customTags) + .register(meterRegistry).getId()); + idSet.add(Gauge.builder(names.getBufferedCallsMetricName(), circuitBreaker, + cb -> cb.getMetrics().getNumberOfSuccessfulCalls()) + .description("The number of buffered successful calls stored in the ring buffer") + .tag(TagNames.NAME, circuitBreaker.getName()) + .tag(TagNames.KIND, KIND_SUCCESSFUL) + .tags(customTags) + .register(meterRegistry).getId()); + idSet.add(Gauge.builder(names.getSlowCallsMetricName(), circuitBreaker, + cb -> cb.getMetrics().getNumberOfSlowSuccessfulCalls()) + .description("The number of slow successful which were slower than a certain threshold") + .tag(TagNames.NAME, circuitBreaker.getName()) + .tag(TagNames.KIND, KIND_SUCCESSFUL) + .tags(customTags) + .register(meterRegistry).getId()); + idSet.add(Gauge.builder(names.getSlowCallsMetricName(), circuitBreaker, + cb -> cb.getMetrics().getNumberOfSlowFailedCalls()) + .description( + "The number of slow failed calls which were slower than a certain threshold") + .tag(TagNames.NAME, circuitBreaker.getName()) + .tag(TagNames.KIND, KIND_FAILED) + .tags(customTags) + .register(meterRegistry).getId()); + idSet.add(Gauge.builder(names.getFailureRateMetricName(), circuitBreaker, + cb -> cb.getMetrics().getFailureRate()) + .description("The failure rate of the circuit breaker") + .tag(TagNames.NAME, circuitBreaker.getName()) + .tags(customTags) + .register(meterRegistry).getId()); + + idSet.add(Gauge.builder(names.getSlowCallRateMetricName(), circuitBreaker, + cb -> cb.getMetrics().getSlowCallRate()) + .description("The slow call of the circuit breaker") + .tag(TagNames.NAME, circuitBreaker.getName()) + .tags(customTags) + .register(meterRegistry).getId()); Timer successfulCalls = Timer.builder(names.getCallsMetricName()) - .description("Total number of successful calls") - .tag(TagNames.NAME, circuitBreaker.getName()) - .tag(TagNames.KIND, KIND_SUCCESSFUL) - .tags(customTags) - .register(meterRegistry); + .description("Total number of successful calls") + .tag(TagNames.NAME, circuitBreaker.getName()) + .tag(TagNames.KIND, KIND_SUCCESSFUL) + .tags(customTags) + .register(meterRegistry); Timer failedCalls = Timer.builder(names.getCallsMetricName()) - .description("Total number of failed calls") - .tag(TagNames.NAME, circuitBreaker.getName()) - .tag(TagNames.KIND, KIND_FAILED) - .tags(customTags) - .register(meterRegistry); + .description("Total number of failed calls") + .tag(TagNames.NAME, circuitBreaker.getName()) + .tag(TagNames.KIND, KIND_FAILED) + .tags(customTags) + .register(meterRegistry); Timer ignoredFailedCalls = Timer.builder(names.getCallsMetricName()) - .description("Total number of calls which failed but the exception was ignored") - .tag(TagNames.NAME, circuitBreaker.getName()) - .tag(TagNames.KIND, KIND_IGNORED) - .tags(customTags) - .register(meterRegistry); + .description("Total number of calls which failed but the exception was ignored") + .tag(TagNames.NAME, circuitBreaker.getName()) + .tag(TagNames.KIND, KIND_IGNORED) + .tags(customTags) + .register(meterRegistry); Counter notPermittedCalls = Counter.builder(names.getCallsMetricName()) - .description("Total number of not permitted calls") - .tag(TagNames.NAME, circuitBreaker.getName()) - .tag(TagNames.KIND, KIND_NOT_PERMITTED) - .tags(customTags) - .register(meterRegistry); + .description("Total number of not permitted calls") + .tag(TagNames.NAME, circuitBreaker.getName()) + .tag(TagNames.KIND, KIND_NOT_PERMITTED) + .tags(customTags) + .register(meterRegistry); idSet.add(successfulCalls.getId()); idSet.add(failedCalls.getId()); @@ -155,12 +163,13 @@ public static class MetricNames { private String slowCallsMetricName = DEFAULT_CIRCUIT_BREAKER_SLOW_CALLS; private String failureRateMetricName = DEFAULT_CIRCUIT_BREAKER_FAILURE_RATE; private String slowCallRateMetricName = DEFAULT_CIRCUIT_BREAKER_SLOW_CALL_RATE; + private MetricNames() { } /** - * Returns a builder for creating custom metric names. - * Note that names have default values, so only desired metrics can be renamed. + * Returns a builder for creating custom metric names. Note that names have default values, + * so only desired metrics can be renamed. * * @return The builder. */ @@ -178,7 +187,8 @@ public static MetricNames ofDefaults() { } /** - * Returns the metric name for circuit breaker calls, defaults to {@value DEFAULT_CIRCUIT_BREAKER_CALLS}. + * Returns the metric name for circuit breaker calls, defaults to {@value + * DEFAULT_CIRCUIT_BREAKER_CALLS}. * * @return The circuit breaker calls metric name. */ @@ -187,7 +197,8 @@ public String getCallsMetricName() { } /** - * Returns the metric name for currently buffered calls, defaults to {@value DEFAULT_CIRCUIT_BREAKER_BUFFERED_CALLS}. + * Returns the metric name for currently buffered calls, defaults to {@value + * DEFAULT_CIRCUIT_BREAKER_BUFFERED_CALLS}. * * @return The buffered calls metric name. */ @@ -196,7 +207,8 @@ public String getBufferedCallsMetricName() { } /** - * Returns the metric name for currently slow calls, defaults to {@value DEFAULT_CIRCUIT_BREAKER_SLOW_CALLS}. + * Returns the metric name for currently slow calls, defaults to {@value + * DEFAULT_CIRCUIT_BREAKER_SLOW_CALLS}. * * @return The slow calls metric name. */ @@ -214,7 +226,8 @@ public String getStateMetricName() { } /** - * Returns the metric name for failure rate, defaults to {@value DEFAULT_CIRCUIT_BREAKER_FAILURE_RATE}. + * Returns the metric name for failure rate, defaults to {@value + * DEFAULT_CIRCUIT_BREAKER_FAILURE_RATE}. * * @return The failure rate metric name. */ @@ -223,7 +236,8 @@ public String getFailureRateMetricName() { } /** - * Returns the metric name for slow call rate, defaults to {@value DEFAULT_CIRCUIT_BREAKER_SLOW_CALL_RATE}. + * Returns the metric name for slow call rate, defaults to {@value + * DEFAULT_CIRCUIT_BREAKER_SLOW_CALL_RATE}. * * @return The failure rate metric name. */ @@ -239,7 +253,8 @@ public static class Builder { private final MetricNames metricNames = new MetricNames(); /** - * Overrides the default metric name {@value MetricNames#DEFAULT_CIRCUIT_BREAKER_CALLS} with a given one. + * Overrides the default metric name {@value MetricNames#DEFAULT_CIRCUIT_BREAKER_CALLS} + * with a given one. * * @param callsMetricName The calls metric name. * @return The builder. @@ -250,7 +265,8 @@ public Builder callsMetricName(String callsMetricName) { } /** - * Overrides the default metric name {@value MetricNames#DEFAULT_CIRCUIT_BREAKER_STATE} with a given one. + * Overrides the default metric name {@value MetricNames#DEFAULT_CIRCUIT_BREAKER_STATE} + * with a given one. * * @param stateMetricName The state metric name. * @return The builder. @@ -261,7 +277,8 @@ public Builder stateMetricName(String stateMetricName) { } /** - * Overrides the default metric name {@value MetricNames#DEFAULT_CIRCUIT_BREAKER_BUFFERED_CALLS} with a given one. + * Overrides the default metric name {@value MetricNames#DEFAULT_CIRCUIT_BREAKER_BUFFERED_CALLS} + * with a given one. * * @param bufferedCallsMetricName The bufferd calls metric name. * @return The builder. @@ -272,7 +289,8 @@ public Builder bufferedCallsMetricName(String bufferedCallsMetricName) { } /** - * Overrides the default metric name {@value MetricNames#DEFAULT_CIRCUIT_BREAKER_SLOW_CALLS} with a given one. + * Overrides the default metric name {@value MetricNames#DEFAULT_CIRCUIT_BREAKER_SLOW_CALLS} + * with a given one. * * @param slowCallsMetricName The slow calls metric name. * @return The builder. @@ -283,7 +301,8 @@ public Builder slowCallsMetricName(String slowCallsMetricName) { } /** - * Overrides the default metric name {@value MetricNames#DEFAULT_CIRCUIT_BREAKER_FAILURE_RATE} with a given one. + * Overrides the default metric name {@value MetricNames#DEFAULT_CIRCUIT_BREAKER_FAILURE_RATE} + * with a given one. * * @param failureRateMetricName The failure rate metric name. * @return The builder. @@ -294,7 +313,8 @@ public Builder failureRateMetricName(String failureRateMetricName) { } /** - * Overrides the default metric name {@value MetricNames#DEFAULT_CIRCUIT_BREAKER_SLOW_CALL_RATE} with a given one. + * Overrides the default metric name {@value MetricNames#DEFAULT_CIRCUIT_BREAKER_SLOW_CALL_RATE} + * with a given one. * * @param slowCallRateMetricName The slow call rate metric name. * @return The builder. diff --git a/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractMetrics.java b/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractMetrics.java index a846f91822..15391ea6ca 100644 --- a/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractMetrics.java +++ b/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractMetrics.java @@ -17,10 +17,14 @@ import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; +import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.stream.Collectors; abstract class AbstractMetrics { @@ -37,4 +41,10 @@ void removeMetrics(MeterRegistry registry, String name) { } meterIdMap.remove(name); } + + List mapToTagsList(Map tagsMap) { + return tagsMap.entrySet() + .stream().map(tagsEntry -> Tag.of(tagsEntry.getKey(), tagsEntry.getValue())) + .collect(Collectors.toList()); + } } diff --git a/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractRateLimiterMetrics.java b/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractRateLimiterMetrics.java index 92af009cea..b9828ebdd7 100644 --- a/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractRateLimiterMetrics.java +++ b/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractRateLimiterMetrics.java @@ -25,7 +25,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.stream.Collectors; import static java.util.Objects.requireNonNull; @@ -38,23 +37,26 @@ protected AbstractRateLimiterMetrics(MetricNames names) { } protected void addMetrics(MeterRegistry meterRegistry, RateLimiter rateLimiter) { - Set idSet = new HashSet<>(); - List customTags = rateLimiter.getTags() - .toJavaMap() - .entrySet() - .stream().map(tagsEntry -> Tag.of(tagsEntry.getKey(), tagsEntry.getValue())) - .collect(Collectors.toList()); - idSet.add(Gauge.builder(names.getAvailablePermissionsMetricName(), rateLimiter, rl -> rl.getMetrics().getAvailablePermissions()) - .description("The number of available permissions") - .tag(TagNames.NAME, rateLimiter.getName()) - .tags(customTags) - .register(meterRegistry).getId()); - idSet.add(Gauge.builder(names.getWaitingThreadsMetricName(), rateLimiter, rl -> rl.getMetrics().getNumberOfWaitingThreads()) - .description("The number of waiting threads") - .tag(TagNames.NAME, rateLimiter.getName()) - .tags(customTags) - .register(meterRegistry).getId()); + List customTags = mapToTagsList(rateLimiter.getTags() + .toJavaMap()); + registerMetrics(meterRegistry, rateLimiter, customTags); + } + private void registerMetrics(MeterRegistry meterRegistry, RateLimiter rateLimiter, + List customTags) { + Set idSet = new HashSet<>(); + idSet.add(Gauge.builder(names.getAvailablePermissionsMetricName(), rateLimiter, + rl -> rl.getMetrics().getAvailablePermissions()) + .description("The number of available permissions") + .tag(TagNames.NAME, rateLimiter.getName()) + .tags(customTags) + .register(meterRegistry).getId()); + idSet.add(Gauge.builder(names.getWaitingThreadsMetricName(), rateLimiter, + rl -> rl.getMetrics().getNumberOfWaitingThreads()) + .description("The number of waiting threads") + .tag(TagNames.NAME, rateLimiter.getName()) + .tags(customTags) + .register(meterRegistry).getId()); meterIdMap.put(rateLimiter.getName(), idSet); } @@ -70,8 +72,8 @@ public static class MetricNames { private String waitingThreadsMetricName = DEFAULT_WAITING_THREADS_METRIC_NAME; /** - * Returns a builder for creating custom metric names. - * Note that names have default values, so only desired metrics can be renamed. + * Returns a builder for creating custom metric names. Note that names have default values, + * so only desired metrics can be renamed. * * @return The builder. */ @@ -89,7 +91,8 @@ public static MetricNames ofDefaults() { } /** - * Returns the metric name for available permissions, defaults to {@value DEFAULT_AVAILABLE_PERMISSIONS_METRIC_NAME}. + * Returns the metric name for available permissions, defaults to {@value + * DEFAULT_AVAILABLE_PERMISSIONS_METRIC_NAME}. * * @return The available permissions metric name. */ @@ -98,7 +101,8 @@ public String getAvailablePermissionsMetricName() { } /** - * Returns the metric name for waiting threads, defaults to {@value DEFAULT_WAITING_THREADS_METRIC_NAME}. + * Returns the metric name for waiting threads, defaults to {@value + * DEFAULT_WAITING_THREADS_METRIC_NAME}. * * @return The waiting threads metric name. */ @@ -114,7 +118,8 @@ public static class Builder { private final MetricNames metricNames = new MetricNames(); /** - * Overrides the default metric name {@value MetricNames#DEFAULT_AVAILABLE_PERMISSIONS_METRIC_NAME} with a given one. + * Overrides the default metric name {@value MetricNames#DEFAULT_AVAILABLE_PERMISSIONS_METRIC_NAME} + * with a given one. * * @param availablePermissionsMetricName The available permissions metric name. * @return The builder. @@ -126,7 +131,8 @@ public Builder availablePermissionsMetricName(String availablePermissionsMetricN } /** - * Overrides the default metric name {@value MetricNames#DEFAULT_WAITING_THREADS_METRIC_NAME} with a given one. + * Overrides the default metric name {@value MetricNames#DEFAULT_WAITING_THREADS_METRIC_NAME} + * with a given one. * * @param waitingThreadsMetricName The waiting threads metric name. * @return The builder. diff --git a/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractRetryMetrics.java b/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractRetryMetrics.java index 25428e8f22..41908ef740 100644 --- a/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractRetryMetrics.java +++ b/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractRetryMetrics.java @@ -25,7 +25,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.stream.Collectors; import static java.util.Objects.requireNonNull; @@ -38,47 +37,52 @@ protected AbstractRetryMetrics(MetricNames names) { } protected void addMetrics(MeterRegistry meterRegistry, Retry retry) { - Set idSet = new HashSet<>(); - List customTags = retry.getTags() - .toJavaMap() - .entrySet() - .stream().map(tagsEntry -> Tag.of(tagsEntry.getKey(), tagsEntry.getValue())) - .collect(Collectors.toList()); - idSet.add(Gauge.builder(names.getCallsMetricName(), retry, rt -> rt.getMetrics().getNumberOfSuccessfulCallsWithoutRetryAttempt()) - .description("The number of successful calls without a retry attempt") - .tag(TagNames.NAME, retry.getName()) - .tag(TagNames.KIND, "successful_without_retry") - .tags(customTags) - .register(meterRegistry).getId()); - idSet.add(Gauge.builder(names.getCallsMetricName(), retry, rt -> rt.getMetrics().getNumberOfSuccessfulCallsWithRetryAttempt()) - .description("The number of successful calls after a retry attempt") - .tag(TagNames.NAME, retry.getName()) - .tag(TagNames.KIND, "successful_with_retry") - .tags(customTags) - .register(meterRegistry).getId()); - idSet.add(Gauge.builder(names.getCallsMetricName(), retry, rt -> rt.getMetrics().getNumberOfFailedCallsWithoutRetryAttempt()) - .description("The number of failed calls without a retry attempt") - .tag(TagNames.NAME, retry.getName()) - .tag(TagNames.KIND, "failed_without_retry") - .tags(customTags) - .register(meterRegistry).getId()); - idSet.add(Gauge.builder(names.getCallsMetricName(), retry, rt -> rt.getMetrics().getNumberOfFailedCallsWithRetryAttempt()) - .description("The number of failed calls after a retry attempt") - .tag(TagNames.NAME, retry.getName()) - .tag(TagNames.KIND, "failed_with_retry") - .tags(customTags) - .register(meterRegistry).getId()); + List customTags = mapToTagsList(retry.getTags() + .toJavaMap()); + registerMetrics(meterRegistry, retry, customTags); + } + private void registerMetrics(MeterRegistry meterRegistry, Retry retry, List customTags) { + Set idSet = new HashSet<>(); + idSet.add(Gauge.builder(names.getCallsMetricName(), retry, + rt -> rt.getMetrics().getNumberOfSuccessfulCallsWithoutRetryAttempt()) + .description("The number of successful calls without a retry attempt") + .tag(TagNames.NAME, retry.getName()) + .tag(TagNames.KIND, "successful_without_retry") + .tags(customTags) + .register(meterRegistry).getId()); + idSet.add(Gauge.builder(names.getCallsMetricName(), retry, + rt -> rt.getMetrics().getNumberOfSuccessfulCallsWithRetryAttempt()) + .description("The number of successful calls after a retry attempt") + .tag(TagNames.NAME, retry.getName()) + .tag(TagNames.KIND, "successful_with_retry") + .tags(customTags) + .register(meterRegistry).getId()); + idSet.add(Gauge.builder(names.getCallsMetricName(), retry, + rt -> rt.getMetrics().getNumberOfFailedCallsWithoutRetryAttempt()) + .description("The number of failed calls without a retry attempt") + .tag(TagNames.NAME, retry.getName()) + .tag(TagNames.KIND, "failed_without_retry") + .tags(customTags) + .register(meterRegistry).getId()); + idSet.add(Gauge.builder(names.getCallsMetricName(), retry, + rt -> rt.getMetrics().getNumberOfFailedCallsWithRetryAttempt()) + .description("The number of failed calls after a retry attempt") + .tag(TagNames.NAME, retry.getName()) + .tag(TagNames.KIND, "failed_with_retry") + .tags(customTags) + .register(meterRegistry).getId()); meterIdMap.put(retry.getName(), idSet); } + public static class MetricNames { public static final String DEFAULT_RETRY_CALLS = "resilience4j.retry.calls"; /** - * Returns a builder for creating custom metric names. - * Note that names have default values, so only desired metrics can be renamed. + * Returns a builder for creating custom metric names. Note that names have default values, + * so only desired metrics can be renamed. * * @return The builder. */ @@ -117,7 +121,8 @@ public static class Builder { private final MetricNames metricNames = new MetricNames(); /** - * Overrides the default metric name {@value MetricNames#DEFAULT_RETRY_CALLS} with a given one. + * Overrides the default metric name {@value MetricNames#DEFAULT_RETRY_CALLS} with a + * given one. * * @param callsMetricName The metric name for retry calls. * @return The builder. diff --git a/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractThreadPoolBulkheadMetrics.java b/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractThreadPoolBulkheadMetrics.java index 98a8d007e2..a853dabbf8 100644 --- a/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractThreadPoolBulkheadMetrics.java +++ b/resilience4j-micrometer/src/main/java/io/github/resilience4j/micrometer/tagged/AbstractThreadPoolBulkheadMetrics.java @@ -25,7 +25,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.stream.Collectors; import static java.util.Objects.requireNonNull; @@ -38,40 +37,46 @@ protected AbstractThreadPoolBulkheadMetrics(MetricNames names) { } protected void addMetrics(MeterRegistry meterRegistry, ThreadPoolBulkhead bulkhead) { + List customTags = mapToTagsList(bulkhead.getTags().toJavaMap()); + addMetrics(meterRegistry, bulkhead, customTags); + } + + private void addMetrics(MeterRegistry meterRegistry, ThreadPoolBulkhead bulkhead, + List customTags) { Set idSet = new HashSet<>(); - List customTags = bulkhead.getTags() - .toJavaMap() - .entrySet() - .stream().map(tagsEntry -> Tag.of(tagsEntry.getKey(), tagsEntry.getValue())) - .collect(Collectors.toList()); - idSet.add(Gauge.builder(names.getQueueDepthMetricName(), bulkhead, bh -> bh.getMetrics().getQueueDepth()) - .description("The queue depth") - .tag(TagNames.NAME, bulkhead.getName()) - .tags(customTags) - .register(meterRegistry).getId()); - idSet.add(Gauge.builder(names.getThreadPoolSizeMetricName(), bulkhead, bh -> bh.getMetrics().getThreadPoolSize()) - .description("The thread pool size") - .tag(TagNames.NAME, bulkhead.getName()) - .tags(customTags) - .register(meterRegistry).getId()); - - idSet.add(Gauge.builder(names.getQueueCapacityMetricName(), bulkhead, bh -> bh.getMetrics().getQueueCapacity()) - .description("The queue capacity") - .tag(TagNames.NAME, bulkhead.getName()) - .tags(customTags) - .register(meterRegistry).getId()); - - idSet.add(Gauge.builder(names.getMaxThreadPoolSizeMetricName(), bulkhead, bh -> bh.getMetrics().getMaximumThreadPoolSize()) - .description("The maximum thread pool size") - .tag(TagNames.NAME, bulkhead.getName()) - .tags(customTags) - .register(meterRegistry).getId()); - - idSet.add(Gauge.builder(names.getCoreThreadPoolSizeMetricName(), bulkhead, bh -> bh.getMetrics().getCoreThreadPoolSize()) - .description("The core thread pool size") - .tag(TagNames.NAME, bulkhead.getName()) - .tags(customTags) - .register(meterRegistry).getId()); + idSet.add(Gauge.builder(names.getQueueDepthMetricName(), bulkhead, + bh -> bh.getMetrics().getQueueDepth()) + .description("The queue depth") + .tag(TagNames.NAME, bulkhead.getName()) + .tags(customTags) + .register(meterRegistry).getId()); + idSet.add(Gauge.builder(names.getThreadPoolSizeMetricName(), bulkhead, + bh -> bh.getMetrics().getThreadPoolSize()) + .description("The thread pool size") + .tag(TagNames.NAME, bulkhead.getName()) + .tags(customTags) + .register(meterRegistry).getId()); + + idSet.add(Gauge.builder(names.getQueueCapacityMetricName(), bulkhead, + bh -> bh.getMetrics().getQueueCapacity()) + .description("The queue capacity") + .tag(TagNames.NAME, bulkhead.getName()) + .tags(customTags) + .register(meterRegistry).getId()); + + idSet.add(Gauge.builder(names.getMaxThreadPoolSizeMetricName(), bulkhead, + bh -> bh.getMetrics().getMaximumThreadPoolSize()) + .description("The maximum thread pool size") + .tag(TagNames.NAME, bulkhead.getName()) + .tags(customTags) + .register(meterRegistry).getId()); + + idSet.add(Gauge.builder(names.getCoreThreadPoolSizeMetricName(), bulkhead, + bh -> bh.getMetrics().getCoreThreadPoolSize()) + .description("The core thread pool size") + .tag(TagNames.NAME, bulkhead.getName()) + .tags(customTags) + .register(meterRegistry).getId()); meterIdMap.put(bulkhead.getName(), idSet); } @@ -95,12 +100,13 @@ public static class MetricNames { private String maxThreadPoolSizeMetricName = DEFAULT_MAX_THREAD_POOL_SIZE_METRIC_NAME; private String coreThreadPoolSizeMetricName = DEFAULT_CORE_THREAD_POOL_SIZE_METRIC_NAME; private String queueCapacityMetricName = DEFAULT_BULKHEAD_QUEUE_CAPACITY_METRIC_NAME; + private MetricNames() { } /** - * Returns a builder for creating custom metric names. - * Note that names have default values, so only desired metrics can be renamed. + * Returns a builder for creating custom metric names. Note that names have default values, + * so only desired metrics can be renamed. * * @return The builder. */ @@ -118,8 +124,8 @@ public static MetricNames ofDefaults() { } /** - * Returns the metric name for queue depth, - * defaults to {@value DEFAULT_BULKHEAD_QUEUE_DEPTH_METRIC_NAME}. + * Returns the metric name for queue depth, defaults to {@value + * DEFAULT_BULKHEAD_QUEUE_DEPTH_METRIC_NAME}. * * @return The queue depth metric name. */ @@ -128,8 +134,8 @@ public String getQueueDepthMetricName() { } /** - * Returns the metric name for thread pool size, - * defaults to {@value DEFAULT_THREAD_POOL_SIZE_METRIC_NAME}. + * Returns the metric name for thread pool size, defaults to {@value + * DEFAULT_THREAD_POOL_SIZE_METRIC_NAME}. * * @return The thread pool size metric name. */ @@ -138,8 +144,8 @@ public String getThreadPoolSizeMetricName() { } /** - * Returns the metric name for max thread pool size, - * defaults to {@value DEFAULT_MAX_THREAD_POOL_SIZE_METRIC_NAME}. + * Returns the metric name for max thread pool size, defaults to {@value + * DEFAULT_MAX_THREAD_POOL_SIZE_METRIC_NAME}. * * @return The max thread pool size metric name. */ @@ -148,8 +154,8 @@ public String getMaxThreadPoolSizeMetricName() { } /** - * Returns the metric name for core thread pool size, - * defaults to {@value DEFAULT_CORE_THREAD_POOL_SIZE_METRIC_NAME}. + * Returns the metric name for core thread pool size, defaults to {@value + * DEFAULT_CORE_THREAD_POOL_SIZE_METRIC_NAME}. * * @return The core thread pool size metric name. */ @@ -158,8 +164,8 @@ public String getCoreThreadPoolSizeMetricName() { } /** - * Returns the metric name for queue capacity, - * defaults to {@value DEFAULT_BULKHEAD_QUEUE_CAPACITY_METRIC_NAME}. + * Returns the metric name for queue capacity, defaults to {@value + * DEFAULT_BULKHEAD_QUEUE_CAPACITY_METRIC_NAME}. * * @return The queue capacity metric name. */ @@ -175,7 +181,8 @@ public static class Builder { private final MetricNames metricNames = new MetricNames(); /** - * Overrides the default metric name {@value MetricNames#DEFAULT_BULKHEAD_QUEUE_DEPTH_METRIC_NAME} with a given one. + * Overrides the default metric name {@value MetricNames#DEFAULT_BULKHEAD_QUEUE_DEPTH_METRIC_NAME} + * with a given one. * * @param queueDepthMetricName The queue depth metric name. * @return The builder. @@ -186,7 +193,8 @@ public Builder queueDepthMetricName(String queueDepthMetricName) { } /** - * Overrides the default metric name {@value MetricNames#DEFAULT_THREAD_POOL_SIZE_METRIC_NAME} with a given one. + * Overrides the default metric name {@value MetricNames#DEFAULT_THREAD_POOL_SIZE_METRIC_NAME} + * with a given one. * * @param threadPoolSizeMetricName The thread pool size metric name. * @return The builder. @@ -197,7 +205,8 @@ public Builder threadPoolSizeMetricName(String threadPoolSizeMetricName) { } /** - * Overrides the default metric name {@value MetricNames#DEFAULT_MAX_THREAD_POOL_SIZE_METRIC_NAME} with a given one. + * Overrides the default metric name {@value MetricNames#DEFAULT_MAX_THREAD_POOL_SIZE_METRIC_NAME} + * with a given one. * * @param maxThreadPoolSizeMetricName The max thread pool size metric name. * @return The builder. @@ -209,7 +218,8 @@ public Builder maxThreadPoolSizeMetricName(String maxThreadPoolSizeMetricName) { } /** - * Overrides the default metric name {@value MetricNames#DEFAULT_CORE_THREAD_POOL_SIZE_METRIC_NAME} with a given one. + * Overrides the default metric name {@value MetricNames#DEFAULT_CORE_THREAD_POOL_SIZE_METRIC_NAME} + * with a given one. * * @param coreThreadPoolSizeMetricName The core thread pool size metric name. * @return The builder. @@ -221,7 +231,8 @@ public Builder coreThreadPoolSizeMetricName(String coreThreadPoolSizeMetricName) } /** - * Overrides the default metric name {@value MetricNames#DEFAULT_BULKHEAD_QUEUE_CAPACITY_METRIC_NAME} with a given one. + * Overrides the default metric name {@value MetricNames#DEFAULT_BULKHEAD_QUEUE_CAPACITY_METRIC_NAME} + * with a given one. * * @param queueCapacityMetricName The queue capacity metric name. * @return The builder. diff --git a/resilience4j-ratelimiter/src/main/java/io/github/resilience4j/ratelimiter/RateLimiterRegistry.java b/resilience4j-ratelimiter/src/main/java/io/github/resilience4j/ratelimiter/RateLimiterRegistry.java index 2a801146f4..6d6bec8681 100644 --- a/resilience4j-ratelimiter/src/main/java/io/github/resilience4j/ratelimiter/RateLimiterRegistry.java +++ b/resilience4j-ratelimiter/src/main/java/io/github/resilience4j/ratelimiter/RateLimiterRegistry.java @@ -118,6 +118,22 @@ static RateLimiterRegistry of(Map configs, return new InMemoryRateLimiterRegistry(configs, registryEventConsumer); } + /** + * Creates a RateLimiterRegistry with a Map of shared RateLimiter configurations and a + * RateLimiter registry event consumer. + * + * @param configs a Map of shared RateLimiter configurations. + * @param registryEventConsumer a RateLimiter registry event consumer. + * @param tags default tags to add to the registry + * @return a RateLimiterRegistry with a Map of shared RateLimiter configurations and a + * RateLimiter registry event consumer. + */ + static RateLimiterRegistry of(Map configs, + RegistryEventConsumer registryEventConsumer, + io.vavr.collection.Map tags) { + return new InMemoryRateLimiterRegistry(configs, registryEventConsumer, tags); + } + /** * Creates a RateLimiterRegistry with a Map of shared RateLimiter configurations and a list of * RateLimiter registry event consumers. diff --git a/resilience4j-ratelimiter/src/test/java/io/github/resilience4j/ratelimiter/RateLimiterRegistryTest.java b/resilience4j-ratelimiter/src/test/java/io/github/resilience4j/ratelimiter/RateLimiterRegistryTest.java index eebc104dc1..6c21a625d4 100644 --- a/resilience4j-ratelimiter/src/test/java/io/github/resilience4j/ratelimiter/RateLimiterRegistryTest.java +++ b/resilience4j-ratelimiter/src/test/java/io/github/resilience4j/ratelimiter/RateLimiterRegistryTest.java @@ -7,6 +7,7 @@ import io.github.resilience4j.core.registry.EntryRemovedEvent; import io.github.resilience4j.core.registry.EntryReplacedEvent; import io.github.resilience4j.core.registry.RegistryEventConsumer; +import io.vavr.Tuple; import org.junit.Test; import java.time.Duration; @@ -27,6 +28,15 @@ private static Optional> getEventProcessor( return Optional.empty(); } + @Test + public void shouldInitRegistryTags() { + Map configs = new HashMap<>(); + configs.put("custom", RateLimiterConfig.ofDefaults()); + RateLimiterRegistry registry = RateLimiterRegistry.of(configs,io.vavr.collection.HashMap.of("Tag1Key","Tag1Value")); + assertThat(registry.getTags()).isNotEmpty(); + assertThat(registry.getTags()).containsOnly(Tuple.of("Tag1Key","Tag1Value")); + } + @Test public void testCreateWithConfigurationMap() { Map configs = new HashMap<>(); diff --git a/resilience4j-retry/src/main/java/io/github/resilience4j/retry/RetryRegistry.java b/resilience4j-retry/src/main/java/io/github/resilience4j/retry/RetryRegistry.java index e3bc2ec08f..dbef80ed3d 100644 --- a/resilience4j-retry/src/main/java/io/github/resilience4j/retry/RetryRegistry.java +++ b/resilience4j-retry/src/main/java/io/github/resilience4j/retry/RetryRegistry.java @@ -117,6 +117,22 @@ static RetryRegistry of(Map configs, return new InMemoryRetryRegistry(configs, registryEventConsumer); } + /** + * Creates a RetryRegistry with a Map of shared Retry configurations and a Retry registry event + * consumer. + * + * @param configs a Map of shared Retry configurations. + * @param registryEventConsumer a Retry registry event consumer. + * @param tags default tags to add to the registry + * @return a RetryRegistry with a Map of shared Retry configurations and a Retry registry event + * consumer. + */ + static RetryRegistry of(Map configs, + RegistryEventConsumer registryEventConsumer, + io.vavr.collection.Map tags) { + return new InMemoryRetryRegistry(configs, registryEventConsumer, tags); + } + /** * Creates a RetryRegistry with a Map of shared Retry configurations and a list of Retry * registry event consumers. diff --git a/resilience4j-retry/src/test/java/io/github/resilience4j/retry/RetryRegistryTest.java b/resilience4j-retry/src/test/java/io/github/resilience4j/retry/RetryRegistryTest.java index 90233883df..461357c666 100644 --- a/resilience4j-retry/src/test/java/io/github/resilience4j/retry/RetryRegistryTest.java +++ b/resilience4j-retry/src/test/java/io/github/resilience4j/retry/RetryRegistryTest.java @@ -22,6 +22,7 @@ import io.github.resilience4j.core.registry.EntryRemovedEvent; import io.github.resilience4j.core.registry.EntryReplacedEvent; import io.github.resilience4j.core.registry.RegistryEventConsumer; +import io.vavr.Tuple; import org.junit.Before; import org.junit.Test; @@ -53,6 +54,15 @@ public void testCreateWithNullConfig() { .isInstanceOf(NullPointerException.class).hasMessage("Config must not be null"); } + @Test + public void shouldInitRegistryTags() { + RetryConfig retryConfig = RetryConfig.ofDefaults(); + Map retryConfigs = Collections.singletonMap("default", retryConfig); + RetryRegistry registry = RetryRegistry.of(retryConfigs,new NoOpRetryEventConsumer(),io.vavr.collection.HashMap.of("Tag1Key","Tag1Value")); + assertThat(registry.getTags()).isNotEmpty(); + assertThat(registry.getTags()).containsOnly(Tuple.of("Tag1Key","Tag1Value")); + } + @Test public void shouldReturnTheCorrectName() { Retry retry = retryRegistry.retry("testName"); diff --git a/resilience4j-spring-boot-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractCircuitBreakerConfigurationOnMissingBean.java b/resilience4j-spring-boot-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractCircuitBreakerConfigurationOnMissingBean.java index 19c2c7771c..536ca5a31f 100644 --- a/resilience4j-spring-boot-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractCircuitBreakerConfigurationOnMissingBean.java +++ b/resilience4j-spring-boot-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractCircuitBreakerConfigurationOnMissingBean.java @@ -55,11 +55,9 @@ public CircuitBreakerRegistry circuitBreakerRegistry( CircuitBreakerRegistry circuitBreakerRegistry = circuitBreakerConfiguration.createCircuitBreakerRegistry(circuitBreakerProperties, circuitBreakerRegistryEventConsumer); - // Register the event consumers circuitBreakerConfiguration .registerEventConsumer(circuitBreakerRegistry, eventConsumerRegistry); - // Initialize backends that were initially configured. circuitBreakerConfiguration.initCircuitBreakerRegistry(circuitBreakerRegistry); diff --git a/resilience4j-spring-boot2/src/test/resources/application.yaml b/resilience4j-spring-boot2/src/test/resources/application.yaml index 178a917df8..2ee567f1ec 100644 --- a/resilience4j-spring-boot2/src/test/resources/application.yaml +++ b/resilience4j-spring-boot2/src/test/resources/application.yaml @@ -1,5 +1,8 @@ resilience4j.retry: retryAspectOrder: 399 + tags: + tag1: tag1Value + tag2: tag2Value configs: default: maxRetryAttempts: 3 @@ -28,6 +31,9 @@ resilience4j.retry: resilience4j.circuitbreaker: circuitBreakerAspectOrder: 400 + tags: + tag1: tag1Value + tag2: tag2Value configs: default: slidingWindowSize: 100 @@ -82,6 +88,9 @@ resilience4j.circuitbreaker: resilience4j.ratelimiter: + tags: + tag1: tag1Value + tag2: tag2Value rateLimiterAspectOrder: 401 configs: default: @@ -102,6 +111,9 @@ resilience4j.ratelimiter: baseConfig: default resilience4j.bulkhead: + tags: + tag1: tag1Value + tag2: tag2Value configs: default: maxWaitDuration: 10 @@ -116,6 +128,9 @@ resilience4j.bulkhead: maxConcurrentCalls: 3 resilience4j.thread-pool-bulkhead": + tags: + tag1: tag1Value + tag2: tag2Value configs: default: maxThreadPoolSize: 4 @@ -124,6 +139,7 @@ resilience4j.thread-pool-bulkhead": keepAliveDuration: 1s backends: backendB: + tags: baseConfig: default backendC: maxThreadPoolSize: 1 diff --git a/resilience4j-spring-cloud-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractRefreshScopedCircuitBreakerConfiguration.java b/resilience4j-spring-cloud-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractRefreshScopedCircuitBreakerConfiguration.java index 48b01d6655..8660cded14 100644 --- a/resilience4j-spring-cloud-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractRefreshScopedCircuitBreakerConfiguration.java +++ b/resilience4j-spring-cloud-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractRefreshScopedCircuitBreakerConfiguration.java @@ -38,11 +38,9 @@ public CircuitBreakerRegistry circuitBreakerRegistry( CircuitBreakerRegistry circuitBreakerRegistry = circuitBreakerConfiguration.createCircuitBreakerRegistry(circuitBreakerProperties, circuitBreakerRegistryEventConsumer); - // Register the event consumers circuitBreakerConfiguration .registerEventConsumer(circuitBreakerRegistry, eventConsumerRegistry); - // Initialize backends that were initially configured. circuitBreakerConfiguration.initCircuitBreakerRegistry(circuitBreakerRegistry); diff --git a/resilience4j-spring/src/main/java/io/github/resilience4j/bulkhead/configure/BulkheadConfiguration.java b/resilience4j-spring/src/main/java/io/github/resilience4j/bulkhead/configure/BulkheadConfiguration.java index 6842069708..58c5b626aa 100644 --- a/resilience4j-spring/src/main/java/io/github/resilience4j/bulkhead/configure/BulkheadConfiguration.java +++ b/resilience4j-spring/src/main/java/io/github/resilience4j/bulkhead/configure/BulkheadConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 lespinsideg + * Copyright 2019 lespinsideg, Mahmoud Romeh * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -60,8 +60,8 @@ public BulkheadRegistry bulkheadRegistry( bulkheadRegistryEventConsumer); registerEventConsumer(bulkheadRegistry, bulkheadEventConsumerRegistry, bulkheadConfigurationProperties); - bulkheadConfigurationProperties.getInstances().forEach( - (name, properties) -> bulkheadRegistry + bulkheadConfigurationProperties.getInstances().forEach((name, properties) -> + bulkheadRegistry .bulkhead(name, bulkheadConfigurationProperties.createBulkheadConfig(properties))); return bulkheadRegistry; } @@ -87,7 +87,8 @@ private BulkheadRegistry createBulkheadRegistry( .entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> bulkheadConfigurationProperties.createBulkheadConfig(entry.getValue()))); - return BulkheadRegistry.of(configs, bulkheadRegistryEventConsumer); + return BulkheadRegistry.of(configs, bulkheadRegistryEventConsumer, + io.vavr.collection.HashMap.ofAll(bulkheadConfigurationProperties.getTags())); } /** diff --git a/resilience4j-spring/src/main/java/io/github/resilience4j/bulkhead/configure/threadpool/ThreadPoolBulkheadConfiguration.java b/resilience4j-spring/src/main/java/io/github/resilience4j/bulkhead/configure/threadpool/ThreadPoolBulkheadConfiguration.java index e7067e228c..6cd0a16a8b 100644 --- a/resilience4j-spring/src/main/java/io/github/resilience4j/bulkhead/configure/threadpool/ThreadPoolBulkheadConfiguration.java +++ b/resilience4j-spring/src/main/java/io/github/resilience4j/bulkhead/configure/threadpool/ThreadPoolBulkheadConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 lespinsideg + * Copyright 2019 lespinsideg , Mahmoud Romeh * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -69,19 +69,22 @@ public RegistryEventConsumer threadPoolBulkheadRegistryEvent /** * Initializes a bulkhead registry. * - * @param bulkheadConfigurationProperties The bulkhead configuration properties. + * @param threadPoolBulkheadConfigurationProperties The bulkhead configuration properties. * @return a ThreadPoolBulkheadRegistry */ private ThreadPoolBulkheadRegistry createBulkheadRegistry( - ThreadPoolBulkheadConfigurationProperties bulkheadConfigurationProperties, + ThreadPoolBulkheadConfigurationProperties threadPoolBulkheadConfigurationProperties, RegistryEventConsumer threadPoolBulkheadRegistryEventConsumer) { - Map configs = bulkheadConfigurationProperties.getConfigs() + Map configs = threadPoolBulkheadConfigurationProperties + .getConfigs() .entrySet() .stream() - .collect(Collectors.toMap(Map.Entry::getKey, entry -> bulkheadConfigurationProperties - .createThreadPoolBulkheadConfig(entry.getValue()))); + .collect(Collectors.toMap(Map.Entry::getKey, + entry -> threadPoolBulkheadConfigurationProperties + .createThreadPoolBulkheadConfig(entry.getValue()))); - return ThreadPoolBulkheadRegistry.of(configs, threadPoolBulkheadRegistryEventConsumer); + return ThreadPoolBulkheadRegistry.of(configs, threadPoolBulkheadRegistryEventConsumer, + io.vavr.collection.HashMap.ofAll(threadPoolBulkheadConfigurationProperties.getTags())); } /** diff --git a/resilience4j-spring/src/main/java/io/github/resilience4j/circuitbreaker/configure/CircuitBreakerConfiguration.java b/resilience4j-spring/src/main/java/io/github/resilience4j/circuitbreaker/configure/CircuitBreakerConfiguration.java index bf435c92f8..fc8226ee10 100644 --- a/resilience4j-spring/src/main/java/io/github/resilience4j/circuitbreaker/configure/CircuitBreakerConfiguration.java +++ b/resilience4j-spring/src/main/java/io/github/resilience4j/circuitbreaker/configure/CircuitBreakerConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Robert Winkler + * Copyright 2017 Robert Winkler,Mahmoud Romeh * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -120,7 +120,8 @@ public CircuitBreakerRegistry createCircuitBreakerRegistry( .entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> circuitBreakerProperties.createCircuitBreakerConfig(entry.getValue()))); - return CircuitBreakerRegistry.of(configs, circuitBreakerRegistryEventConsumer); + return CircuitBreakerRegistry.of(configs, circuitBreakerRegistryEventConsumer, + io.vavr.collection.HashMap.ofAll(circuitBreakerProperties.getTags())); } /** diff --git a/resilience4j-spring/src/main/java/io/github/resilience4j/ratelimiter/configure/RateLimiterConfiguration.java b/resilience4j-spring/src/main/java/io/github/resilience4j/ratelimiter/configure/RateLimiterConfiguration.java index 4121a076a6..fee851d50b 100644 --- a/resilience4j-spring/src/main/java/io/github/resilience4j/ratelimiter/configure/RateLimiterConfiguration.java +++ b/resilience4j-spring/src/main/java/io/github/resilience4j/ratelimiter/configure/RateLimiterConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Bohdan Storozhuk + * Copyright 2017 Bohdan Storozhuk, Mahmoud Romeh * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -57,8 +57,9 @@ public RateLimiterRegistry rateLimiterRegistry( registerEventConsumer(rateLimiterRegistry, rateLimiterEventsConsumerRegistry, rateLimiterProperties); rateLimiterProperties.getInstances().forEach( - (name, properties) -> rateLimiterRegistry - .rateLimiter(name, rateLimiterProperties.createRateLimiterConfig(properties)) + (name, properties) -> + rateLimiterRegistry + .rateLimiter(name, rateLimiterProperties.createRateLimiterConfig(properties)) ); return rateLimiterRegistry; } @@ -85,7 +86,8 @@ private RateLimiterRegistry createRateLimiterRegistry( entry -> rateLimiterConfigurationProperties .createRateLimiterConfig(entry.getValue()))); - return RateLimiterRegistry.of(configs, rateLimiterRegistryEventConsumer); + return RateLimiterRegistry.of(configs, rateLimiterRegistryEventConsumer, + io.vavr.collection.HashMap.ofAll(rateLimiterConfigurationProperties.getTags())); } /** diff --git a/resilience4j-spring/src/main/java/io/github/resilience4j/retry/configure/RetryConfiguration.java b/resilience4j-spring/src/main/java/io/github/resilience4j/retry/configure/RetryConfiguration.java index 6c5d940832..e98f0c510c 100644 --- a/resilience4j-spring/src/main/java/io/github/resilience4j/retry/configure/RetryConfiguration.java +++ b/resilience4j-spring/src/main/java/io/github/resilience4j/retry/configure/RetryConfiguration.java @@ -59,8 +59,9 @@ public RetryRegistry retryRegistry(RetryConfigurationProperties retryConfigurati retryRegistryEventConsumer); registerEventConsumer(retryRegistry, retryEventConsumerRegistry, retryConfigurationProperties); - retryConfigurationProperties.getInstances().forEach((name, properties) -> retryRegistry - .retry(name, retryConfigurationProperties.createRetryConfig(name))); + retryConfigurationProperties.getInstances() + .forEach((name, properties) -> + retryRegistry.retry(name, retryConfigurationProperties.createRetryConfig(name))); return retryRegistry; } @@ -85,7 +86,8 @@ private RetryRegistry createRetryRegistry( .entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> retryConfigurationProperties.createRetryConfig(entry.getValue()))); - return RetryRegistry.of(configs, retryRegistryEventConsumer); + return RetryRegistry.of(configs, retryRegistryEventConsumer, + io.vavr.collection.HashMap.ofAll(retryConfigurationProperties.getTags())); } /**