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 2eeabbdf4d3e..3bcbd3d0f03e 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 @@ -192,10 +192,9 @@ public static class Distribution { /** * Specific SLA boundaries for meter IDs starting-with the specified name. The - * longest match wins, the key `all` can also be used to configure all meters. - * Counters will be published for each specified boundary. Values can be specified - * as a long or as a Duration value (for timer meters, defaulting to ms if no unit - * specified). + * longest match wins. Counters will be published for each specified boundary. + * Values can be specified as a long or as a Duration value (for timer meters, + * defaulting to ms if no unit specified). */ private final Map sla = new LinkedHashMap<>(); 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 eacbe66e893f..55f5c80c5fd0 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 @@ -19,6 +19,7 @@ import java.util.Arrays; import java.util.Map; import java.util.Objects; +import java.util.function.Supplier; import java.util.stream.Collectors; import io.micrometer.core.instrument.Meter; @@ -39,6 +40,7 @@ * @author Jon Schneider * @author Phillip Webb * @author Stephane Nicoll + * @author Artsiom Yudovin * @since 2.0.0 */ public class PropertiesMeterFilter implements MeterFilter { @@ -66,7 +68,7 @@ private static MeterFilter createMapFilter(Map tags) { @Override public MeterFilterReply accept(Meter.Id id) { - boolean enabled = lookup(this.properties.getEnable(), id, true); + boolean enabled = lookupWithFallbackToAll(this.properties.getEnable(), id, true); return enabled ? MeterFilterReply.NEUTRAL : MeterFilterReply.DENY; } @@ -80,9 +82,10 @@ public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) { Distribution distribution = this.properties.getDistribution(); return DistributionStatisticConfig.builder() - .percentilesHistogram( - lookup(distribution.getPercentilesHistogram(), id, null)) - .percentiles(lookup(distribution.getPercentiles(), id, null)) + .percentilesHistogram(lookupWithFallbackToAll( + distribution.getPercentilesHistogram(), id, null)) + .percentiles( + lookupWithFallbackToAll(distribution.getPercentiles(), id, null)) .sla(convertSla(id.getType(), lookup(distribution.getSla(), id, null))) .build().merge(config); } @@ -101,6 +104,18 @@ private T lookup(Map values, Id id, T defaultValue) { if (values.isEmpty()) { return defaultValue; } + return this.baseLookup(values, id, () -> defaultValue); + } + + private T lookupWithFallbackToAll(Map values, Id id, T defaultValue) { + if (values.isEmpty()) { + return defaultValue; + } + return this.baseLookup(values, id, + () -> values.getOrDefault("all", defaultValue)); + } + + private T baseLookup(Map values, Id id, Supplier defaultValue) { String name = id.getName(); while (StringUtils.hasLength(name)) { T result = values.get(name); @@ -110,7 +125,8 @@ private T lookup(Map values, Id id, T defaultValue) { int lastDot = name.lastIndexOf('.'); name = (lastDot != -1) ? name.substring(0, lastDot) : ""; } - return values.getOrDefault("all", defaultValue); + + return defaultValue.get(); } } 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 d13ef843daf4..0f035848f87b 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 @@ -42,6 +42,7 @@ * * @author Phillip Webb * @author Jon Schneider + * @author Artsiom Yudovin */ public class PropertiesMeterFilterTests { @@ -254,42 +255,11 @@ public void configureWhenHasHigherSlaAndLowerShouldSetSlaToHigher() { } @Test - public void configureWhenAllSlaSetShouldSetSlaToValue() { + public void acceptWhenHasNoMatchingEnabledPropertyShouldReturnNeutral() { PropertiesMeterFilter filter = new PropertiesMeterFilter( - createProperties("distribution.sla.all=1,2,3")); - assertThat(filter.configure(createMeterId("spring.boot"), - DistributionStatisticConfig.DEFAULT).getSlaBoundaries()) - .containsExactly(1000000, 2000000, 3000000); - } - - @Test - public void configureWhenSlaDurationShouldOnlyApplyToTimer() { - PropertiesMeterFilter filter = new PropertiesMeterFilter( - createProperties("distribution.sla.all=1ms,2ms,3ms")); - Meter.Id timer = createMeterId("spring.boot", Meter.Type.TIMER); - Meter.Id summary = createMeterId("spring.boot", Meter.Type.DISTRIBUTION_SUMMARY); - Meter.Id counter = createMeterId("spring.boot", Meter.Type.COUNTER); - assertThat(filter.configure(timer, DistributionStatisticConfig.DEFAULT) - .getSlaBoundaries()).containsExactly(1000000, 2000000, 3000000); - assertThat(filter.configure(summary, DistributionStatisticConfig.DEFAULT) - .getSlaBoundaries()).isNullOrEmpty(); - assertThat(filter.configure(counter, DistributionStatisticConfig.DEFAULT) - .getSlaBoundaries()).isNullOrEmpty(); - } - - @Test - public void configureWhenSlaLongShouldOnlyApplyToTimerAndDistributionSummary() { - PropertiesMeterFilter filter = new PropertiesMeterFilter( - createProperties("distribution.sla.all=1,2,3")); - Meter.Id timer = createMeterId("spring.boot", Meter.Type.TIMER); - Meter.Id summary = createMeterId("spring.boot", Meter.Type.DISTRIBUTION_SUMMARY); - Meter.Id counter = createMeterId("spring.boot", Meter.Type.COUNTER); - assertThat(filter.configure(timer, DistributionStatisticConfig.DEFAULT) - .getSlaBoundaries()).containsExactly(1000000, 2000000, 3000000); - assertThat(filter.configure(summary, DistributionStatisticConfig.DEFAULT) - .getSlaBoundaries()).containsExactly(1, 2, 3); - assertThat(filter.configure(counter, DistributionStatisticConfig.DEFAULT) - .getSlaBoundaries()).isNullOrEmpty(); + createProperties("enable.something.else=false")); + assertThat(filter.accept(createMeterId("spring.boot"))) + .isEqualTo(MeterFilterReply.NEUTRAL); } private Id createMeterId(String name) { diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 7699e6afc42b..cb4c75ce6d4c 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -1381,7 +1381,7 @@ content into your application. Rather, pick only the properties that you need. # METRICS management.metrics.distribution.percentiles-histogram.*= # Whether meter IDs starting with the specified name should publish percentile histograms. management.metrics.distribution.percentiles.*= # Specific computed non-aggregable percentiles to ship to the backend for meter IDs starting-with the specified name. - management.metrics.distribution.sla.*= # Specific SLA boundaries for meter IDs starting-with the specified name. The longest match wins, the key `all` can also be used to configure all meters. + management.metrics.distribution.sla.*= # Specific SLA boundaries for meter IDs starting-with the specified name. The longest match wins. management.metrics.enable.*= # Whether meter IDs starting-with the specified name should be enabled. The longest match wins, the key `all` can also be used to configure all meters. management.metrics.export.atlas.batch-size=10000 # Number of measurements per request to use for this backend. If more measurements are found, then multiple requests will be made. management.metrics.export.atlas.config-refresh-frequency=10s # Frequency for refreshing config settings from the LWC service.