Skip to content

Commit

Permalink
Support to extend Micrometer tags in TimeLimiter (ReactiveX#838)
Browse files Browse the repository at this point in the history
  • Loading branch information
dlsrb6342 committed Feb 4, 2020
1 parent 2222e3e commit 22258f6
Show file tree
Hide file tree
Showing 13 changed files with 337 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.github.resilience4j.common.timelimiter.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;
Expand All @@ -27,7 +28,7 @@
import java.util.Map;
import java.util.Objects;

public class TimeLimiterConfigurationProperties {
public class TimeLimiterConfigurationProperties extends CommonProperties {

private final Map<String, InstanceProperties> instances = new HashMap<>();
private final Map<String, InstanceProperties> configs = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,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;
Expand All @@ -27,8 +29,12 @@ public void testTimeLimiterProperties() {
TimeLimiterConfigurationProperties timeLimiterConfigurationProperties = new TimeLimiterConfigurationProperties();
timeLimiterConfigurationProperties.getInstances().put("backend1", instanceProperties1);
timeLimiterConfigurationProperties.getInstances().put("backend2", instanceProperties2);
Map<String,String> tags = new HashMap<>();
tags.put("testKey1","testKet2");
timeLimiterConfigurationProperties.setTags(tags);

// Then
assertThat(timeLimiterConfigurationProperties.getTags()).isNotEmpty();
assertThat(timeLimiterConfigurationProperties.getInstances().size()).isEqualTo(2);
final TimeLimiterConfig timeLimiter1 = timeLimiterConfigurationProperties.createTimeLimiterConfig("backend1");
final TimeLimiterConfig timeLimiter2 = timeLimiterConfigurationProperties.createTimeLimiterConfig("backend2");
Expand Down Expand Up @@ -71,7 +77,12 @@ public void testCreateTimeLimiterPropertiesWithSharedConfigs() {
timeLimiterConfigurationProperties.getInstances().put("backendWithDefaultConfig", backendWithDefaultConfig);
timeLimiterConfigurationProperties.getInstances().put("backendWithSharedConfig", backendWithSharedConfig);

Map<String,String> globalTags = new HashMap<>();
globalTags.put("testKey1","testKet2");
timeLimiterConfigurationProperties.setTags(globalTags);

//Then
assertThat(timeLimiterConfigurationProperties.getTags()).isNotEmpty();
// Should get default config and overwrite max attempt and wait time
TimeLimiterConfig timeLimiter1 = timeLimiterConfigurationProperties.createTimeLimiterConfig("backendWithDefaultConfig");
assertThat(timeLimiter1).isNotNull();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;

import java.util.Arrays;
import java.util.HashSet;
Expand All @@ -40,23 +41,31 @@ protected AbstractTimeLimiterMetrics(MetricNames names) {
}

protected void addMetrics(MeterRegistry meterRegistry, TimeLimiter timeLimiter) {
List<Tag> customTags = mapToTagsList(timeLimiter.getTags().toJavaMap());
registerMetrics(meterRegistry, timeLimiter, customTags);
}

protected void registerMetrics(MeterRegistry meterRegistry, TimeLimiter timeLimiter, List<Tag> customTags) {
// Remove previous meters before register
removeMetrics(meterRegistry, timeLimiter.getName());

Counter successes = Counter.builder(names.getCallsMetricName())
.description("The number of successful calls")
.tag(TagNames.NAME, timeLimiter.getName())
.tag(TagNames.KIND, KIND_SUCCESSFUL)
.tags(customTags)
.register(meterRegistry);
Counter failures = Counter.builder(names.getCallsMetricName())
.description("The number of failed calls")
.tag(TagNames.NAME, timeLimiter.getName())
.tag(TagNames.KIND, KIND_FAILED)
.tags(customTags)
.register(meterRegistry);
Counter timeouts = Counter.builder(names.getCallsMetricName())
.description("The number of timed out calls")
.tag(TagNames.NAME, timeLimiter.getName())
.tag(TagNames.KIND, KIND_TIMEOUT)
.tags(customTags)
.register(meterRegistry);

timeLimiter.getEventPublisher()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.search.RequiredSearch;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -73,6 +74,18 @@ public void shouldAddMetricsForANewlyCreatedTimeLimiter() {
assertThat(successful).map(Counter::count).contains(1d);
}

@Test
public void shouldAddCustomTags() {
TimeLimiter timeLimiterF = timeLimiterRegistry.timeLimiter("backendF", io.vavr.collection.HashMap.of("key1", "value1"));
timeLimiterF.onSuccess();
assertThat(taggedTimeLimiterMetricsPublisher.meterIdMap).containsKeys("backendA", "backendF");
assertThat(taggedTimeLimiterMetricsPublisher.meterIdMap.get("backendF")).hasSize(3);

assertThat(meterRegistry.getMeters()).hasSize(6);
RequiredSearch match = meterRegistry.get(DEFAULT_TIME_LIMITER_CALLS).tags("key1", "value1");
assertThat(match).isNotNull();
}

@Test
public void shouldRemovedMetricsForRemovedRetry() {
assertThat(meterRegistry.getMeters()).hasSize(3);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public InMemoryRetryRegistry(Map<String, RetryConfig> configs,
List<RegistryEventConsumer<Retry>> registryEventConsumers,
io.vavr.collection.Map<String, String> tags) {
this(configs.getOrDefault(DEFAULT_CONFIG, RetryConfig.ofDefaults()),
registryEventConsumers);
registryEventConsumers, tags);
this.configurations.putAll(configs);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public class TimeLimiterAutoConfigurationTest {
public void testTimeLimiterAutoConfigurationTest() throws Exception {
assertThat(timeLimiterRegistry).isNotNull();
assertThat(timeLimiterProperties).isNotNull();
assertThat(timeLimiterRegistry.getTags()).isNotEmpty();

TimeLimiterEventsEndpointResponse timeLimiterEventsBefore =
timeLimiterEvents("/actuator/timelimiterevents");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ resilience4j.bulkhead:
maxWaitDuration: 100
maxConcurrentCalls: 10

resilience4j.thread-pool-bulkhead":
resilience4j.thread-pool-bulkhead:
tags:
tag1: tag1Value
tag2: tag2Value
Expand All @@ -164,6 +164,9 @@ resilience4j.thread-pool-bulkhead":
- io.github.resilience4j.TestThreadLocalContextPropagator

resilience4j.timelimiter:
tags:
tag1: tag1Value
tag2: tag2Value
time-limiter-aspect-order: 398
configs:
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import io.github.resilience4j.utils.AspectJOnClasspathCondition;
import io.github.resilience4j.utils.ReactorOnClasspathCondition;
import io.github.resilience4j.utils.RxJava2OnClasspathCondition;
import io.vavr.collection.HashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
Expand Down Expand Up @@ -108,7 +109,8 @@ private static TimeLimiterRegistry createTimeLimiterRegistry(TimeLimiterConfigur
.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
entry -> timeLimiterConfigurationProperties.createTimeLimiterConfig(entry.getValue())));

return TimeLimiterRegistry.of(configs, timeLimiterRegistryEventConsumer);
return TimeLimiterRegistry.of(configs, timeLimiterRegistryEventConsumer,
HashMap.ofAll(timeLimiterConfigurationProperties.getTags()));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,23 @@ static TimeLimiter of(String name, TimeLimiterConfig timeLimiterConfig) {
return new TimeLimiterImpl(name, timeLimiterConfig);
}

/**
* Creates a TimeLimiter with a custom TimeLimiter configuration.
* <p>
* The {@code tags} passed will be appended to the tags already configured for the registry.
* When tags (keys) of the two collide the tags passed with this method will override the tags
* of the registry.
*
* @param name the name of the TimeLimiter
* @param timeLimiterConfig a custom TimeLimiter configuration
* @param tags tags added to the Retry
* @return a TimeLimiter with a custom TimeLimiter configuration.
*/
static TimeLimiter of(String name, TimeLimiterConfig timeLimiterConfig,
io.vavr.collection.Map<String, String> tags) {
return new TimeLimiterImpl(name, timeLimiterConfig, tags);
}

/**
* Creates a TimeLimiter decorator with a timeout Duration.
*
Expand Down Expand Up @@ -104,6 +121,13 @@ static <T, F extends CompletionStage<T>> Supplier<CompletionStage<T>> decorateCo

String getName();

/**
* Returns an unmodifiable map with tags assigned to this TimeLimiter.
*
* @return the tags assigned to this TimeLimiter in an unmodifiable map
*/
io.vavr.collection.Map<String, String> getTags();

/**
* Get the TimeLimiterConfig of this TimeLimiter decorator.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,20 @@ static TimeLimiterRegistry of(Map<String, TimeLimiterConfig> configs) {
return new InMemoryTimeLimiterRegistry(configs);
}

/**
* Creates a TimeLimiterRegistry with a Map of shared TimeLimiter configurations.
* <p>
* Tags added to the registry will be added to every instance created by this registry.
*
* @param configs a Map of shared TimeLimiter configurations
* @param tags default tags to add to the registry
* @return a TimeLimiterRegistry with a Map of shared TimeLimiter configurations.
*/
static TimeLimiterRegistry of(Map<String, TimeLimiterConfig> configs,
io.vavr.collection.Map<String, String> tags) {
return new InMemoryTimeLimiterRegistry(configs, tags);
}

/**
* Creates a TimeLimiterRegistry with a Map of shared TimeLimiter configurations and a
* TimeLimiter registry event consumer.
Expand All @@ -104,6 +118,22 @@ static TimeLimiterRegistry of(Map<String, TimeLimiterConfig> configs,
return new InMemoryTimeLimiterRegistry(configs, registryEventConsumer);
}

/**
* Creates a TimeLimiterRegistry with a Map of shared TimeLimiter configurations and a
* TimeLimiter registry event consumer.
*
* @param configs a Map of shared TimeLimiter configurations.
* @param registryEventConsumer a TimeLimiter registry event consumer.
* @param tags default tags to add to the registry
* @return a TimeLimiterRegistry with a Map of shared TimeLimiter configurations and a
* TimeLimiter registry event consumer.
*/
static TimeLimiterRegistry of(Map<String, TimeLimiterConfig> configs,
RegistryEventConsumer<TimeLimiter> registryEventConsumer,
io.vavr.collection.Map<String, String> tags) {
return new InMemoryTimeLimiterRegistry(configs, registryEventConsumer, tags);
}

/**
* Creates a TimeLimiterRegistry with a Map of shared TimeLimiter configurations and a list of
* TimeLimiter registry event consumers.
Expand Down Expand Up @@ -134,6 +164,20 @@ static TimeLimiterRegistry of(Map<String, TimeLimiterConfig> configs,
*/
TimeLimiter timeLimiter(String name);

/**
* Returns a managed {@link TimeLimiter} or creates a new one with the default TimeLimiter
* configuration.
* <p>
* The {@code tags} passed will be appended to the tags already configured for the registry.
* When tags (keys) of the two collide the tags passed with this method will override the tags
* of the registry.
*
* @param name the name of the TimeLimiter
* @param tags tags added to the TimeLimiter
* @return The {@link TimeLimiter}
*/
TimeLimiter timeLimiter(String name, io.vavr.collection.Map<String, String> tags);

/**
* Returns a managed {@link TimeLimiter} or creates a new one with a custom TimeLimiter
* configuration.
Expand All @@ -144,6 +188,22 @@ static TimeLimiterRegistry of(Map<String, TimeLimiterConfig> configs,
*/
TimeLimiter timeLimiter(String name, TimeLimiterConfig timeLimiterConfig);

/**
* Returns a managed {@link TimeLimiter} or creates a new one with a custom TimeLimiter
* configuration.
* <p>
* The {@code tags} passed will be appended to the tags already configured for the registry.
* When tags (keys) of the two collide the tags passed with this method will override the tags
* of the registry.
*
* @param name the name of the TimeLimiter
* @param timeLimiterConfig a custom TimeLimiter configuration
* @param tags tags added to the TimeLimiter
* @return The {@link TimeLimiter}
*/
TimeLimiter timeLimiter(String name, TimeLimiterConfig timeLimiterConfig,
io.vavr.collection.Map<String, String> tags);

/**
* Returns a managed {@link TimeLimiterConfig} or creates a new one with a custom
* TimeLimiterConfig configuration.
Expand All @@ -154,6 +214,23 @@ static TimeLimiterRegistry of(Map<String, TimeLimiterConfig> configs,
*/
TimeLimiter timeLimiter(String name, Supplier<TimeLimiterConfig> timeLimiterConfigSupplier);

/**
* Returns a managed {@link TimeLimiter} or creates a new one with a custom TimeLimiter
* configuration.
* <p>
* The {@code tags} passed will be appended to the tags already configured for the registry.
* When tags (keys) of the two collide the tags passed with this method will override the tags
* of the registry.
*
* @param name the name of the TimeLimiter
* @param timeLimiterConfigSupplier a supplier of a custom TimeLimiter configuration
* @param tags tags added to the TimeLimiter
* @return The {@link TimeLimiter}
*/
TimeLimiter timeLimiter(String name,
Supplier<TimeLimiterConfig> timeLimiterConfigSupplier,
io.vavr.collection.Map<String, String> tags);

/**
* Returns a managed {@link TimeLimiter} or creates a new one.
* The configuration must have been added upfront via {@link #addConfiguration(String, Object)}.
Expand All @@ -164,4 +241,20 @@ static TimeLimiterRegistry of(Map<String, TimeLimiterConfig> configs,
*/
TimeLimiter timeLimiter(String name, String configName);

/**
* Returns a managed {@link TimeLimiter} or creates a new one.
* The configuration must have been added upfront via {@link #addConfiguration(String, Object)}.
* <p>
* The {@code tags} passed will be appended to the tags already configured for the registry.
* When tags (keys) of the two collide the tags passed with this method will override the tags
* of the registry.
*
* @param name the name of the TimeLimiter
* @param configName the name of the shared configuration
* @param tags tags added to the TimeLimiter
* @return The {@link TimeLimiter}
*/
TimeLimiter timeLimiter(String name, String configName,
io.vavr.collection.Map<String, String> tags);

}
Loading

0 comments on commit 22258f6

Please sign in to comment.