From 888acb94fc27fba8b2d2eb7a07d36b4d9d3e7da4 Mon Sep 17 00:00:00 2001 From: Leo Li <269739606@qq.com> Date: Fri, 6 Aug 2021 17:18:25 +0800 Subject: [PATCH] Add expiry and bufferLength configuration properties See gh-27584 --- .../metrics/MetricsProperties.java | 25 +++++++ .../metrics/PropertiesMeterFilter.java | 3 + .../metrics/PropertiesMeterFilterTests.java | 66 +++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsProperties.java index c4c0b2c2f4e..f3ac7fb53f1 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MetricsProperties.java @@ -16,6 +16,7 @@ package org.springframework.boot.actuate.autoconfigure.metrics; +import java.time.Duration; import java.util.LinkedHashMap; import java.util.Map; @@ -29,6 +30,7 @@ import org.springframework.boot.context.properties.NestedConfigurationProperty; * @author Jon Schneider * @author Alexander Abramov * @author Tadaya Tsuyukubo + * @author Leo Li * @since 2.0.0 */ @ConfigurationProperties("management.metrics") @@ -296,6 +298,21 @@ public class MetricsProperties { */ private final Map maximumExpectedValue = new LinkedHashMap<>(); + /** + * Specific statistic's expiry for meter IDs starting-with the specified name. + * Values should be a Duration value, the key `all` can also be used to configure + * all meters. + */ + private final Map expiry = new LinkedHashMap<>(); + + /** + * Specific statistic's bufferLength for meter IDs starting-with the specified + * name. Samples are accumulated to statistics in ring buffers, and bufferLength + * is the number to keep in the ring buffer, the key `all` can also be used to + * configure all meters. + */ + private final Map bufferLength = new LinkedHashMap<>(); + public Map getPercentilesHistogram() { return this.percentilesHistogram; } @@ -316,6 +333,14 @@ public class MetricsProperties { return this.maximumExpectedValue; } + public Map getExpiry() { + return this.expiry; + } + + public Map getBufferLength() { + return this.bufferLength; + } + } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/PropertiesMeterFilter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/PropertiesMeterFilter.java index 7689480c7ea..528352404dc 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/PropertiesMeterFilter.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/PropertiesMeterFilter.java @@ -42,6 +42,7 @@ import org.springframework.util.StringUtils; * @author Stephane Nicoll * @author Artsiom Yudovin * @author Alexander Abramov + * @author Leo Li * @since 2.0.0 */ public class PropertiesMeterFilter implements MeterFilter { @@ -83,6 +84,8 @@ public class PropertiesMeterFilter implements MeterFilter { return DistributionStatisticConfig.builder() .percentilesHistogram(lookupWithFallbackToAll(distribution.getPercentilesHistogram(), id, null)) .percentiles(lookupWithFallbackToAll(distribution.getPercentiles(), id, null)) + .expiry(lookupWithFallbackToAll(distribution.getExpiry(), id, null)) + .bufferLength(lookupWithFallbackToAll(distribution.getBufferLength(), id, null)) .serviceLevelObjectives( convertServiceLevelObjectives(id.getType(), lookup(distribution.getSlo(), id, null))) .minimumExpectedValue( diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/PropertiesMeterFilterTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/PropertiesMeterFilterTests.java index 7d6611df10a..0e375e29ebf 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/PropertiesMeterFilterTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/PropertiesMeterFilterTests.java @@ -41,6 +41,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException * @author Phillip Webb * @author Jon Schneider * @author Artsiom Yudovin + * @author Leo Li */ class PropertiesMeterFilterTests { @@ -275,6 +276,71 @@ class PropertiesMeterFilterTests { .getMaximumExpectedValueAsDouble()).isEqualTo(Duration.ofMillis(10000).toNanos()); } + @Test + void configureWhenHasExpiryShouldSetExpiryToValue() { + PropertiesMeterFilter filter = new PropertiesMeterFilter( + createProperties("distribution.expiry[spring.boot]=5ms")); + assertThat(filter.configure(createMeterId("spring.boot"), DistributionStatisticConfig.DEFAULT).getExpiry()) + .isEqualTo(Duration.ofMillis(5)); + } + + @Test + void configureWhenHasHigherExpiryShouldSetExpiryToValue() { + PropertiesMeterFilter filter = new PropertiesMeterFilter(createProperties("distribution.expiry.spring=5ms")); + assertThat(filter.configure(createMeterId("spring.boot"), DistributionStatisticConfig.DEFAULT).getExpiry()) + .isEqualTo(Duration.ofMillis(5)); + } + + @Test + void configureWhenHasHigherExpiryAndLowerShouldSetExpiryToHigher() { + PropertiesMeterFilter filter = new PropertiesMeterFilter( + createProperties("distribution.expiry.spring=5ms", "distribution.expiry[spring.boot]=10ms")); + assertThat(filter.configure(createMeterId("spring.boot"), DistributionStatisticConfig.DEFAULT).getExpiry()) + .isEqualTo(Duration.ofMillis(10)); + } + + @Test + void configureWhenAllExpirySetShouldSetExpiryToValue() { + PropertiesMeterFilter filter = new PropertiesMeterFilter(createProperties("distribution.expiry.all=5ms")); + assertThat(filter.configure(createMeterId("spring.boot"), DistributionStatisticConfig.DEFAULT).getExpiry()) + .isEqualTo(Duration.ofMillis(5)); + } + + @Test + void configureWhenHasBufferLengthShouldSetBufferLengthToValue() { + PropertiesMeterFilter filter = new PropertiesMeterFilter( + createProperties("distribution.bufferLength[spring.boot]=3")); + assertThat( + filter.configure(createMeterId("spring.boot"), DistributionStatisticConfig.DEFAULT).getBufferLength()) + .isEqualTo(3); + } + + @Test + void configureWhenHasHigherBufferLengthShouldSetBufferLengthToValue() { + PropertiesMeterFilter filter = new PropertiesMeterFilter( + createProperties("distribution.bufferLength.spring=3")); + assertThat( + filter.configure(createMeterId("spring.boot"), DistributionStatisticConfig.DEFAULT).getBufferLength()) + .isEqualTo(3); + } + + @Test + void configureWhenHasHigherBufferLengthAndLowerShouldSetBufferLengthToHigher() { + PropertiesMeterFilter filter = new PropertiesMeterFilter( + createProperties("distribution.bufferLength.spring=2", "distribution.bufferLength[spring.boot]=3")); + assertThat( + filter.configure(createMeterId("spring.boot"), DistributionStatisticConfig.DEFAULT).getBufferLength()) + .isEqualTo(3); + } + + @Test + void configureWhenAllBufferLengthSetShouldSetBufferLengthToValue() { + PropertiesMeterFilter filter = new PropertiesMeterFilter(createProperties("distribution.bufferLength.all=3")); + assertThat( + filter.configure(createMeterId("spring.boot"), DistributionStatisticConfig.DEFAULT).getBufferLength()) + .isEqualTo(3); + } + private Id createMeterId(String name) { Meter.Type meterType = Type.TIMER; return createMeterId(name, meterType);