From 0ff1b25f52c2641e48e8008c362931e7deb6f823 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Fri, 12 Oct 2018 11:37:09 +0200 Subject: [PATCH] Polish "Improve Micrometer histogram properties support" Closes gh-14139 --- .../autoconfigure/metrics/MeterValue.java | 104 ++++++++++++++++++ .../metrics/MetricsProperties.java | 22 ++-- .../metrics/PropertiesMeterFilter.java | 8 +- .../ServiceLevelAgreementBoundary.java | 55 ++------- .../metrics/MeterValueTests.java | 91 +++++++++++++++ .../metrics/PropertiesMeterFilterTests.java | 58 +--------- .../ServiceLevelAgreementBoundaryTests.java | 45 -------- .../appendix-application-properties.adoc | 6 +- 8 files changed, 225 insertions(+), 164 deletions(-) create mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterValue.java create mode 100644 spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterValueTests.java diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterValue.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterValue.java new file mode 100644 index 0000000000..829a5aa647 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterValue.java @@ -0,0 +1,104 @@ +/* + * Copyright 2012-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 org.springframework.boot.actuate.autoconfigure.metrics; + +import java.time.Duration; +import java.util.concurrent.TimeUnit; + +import io.micrometer.core.instrument.Meter.Type; + +import org.springframework.boot.convert.DurationStyle; + +/** + * A meter value that is used when configuring micrometer. Can be a String representation + * of either a {@link Long} (applicable to timers and distribution summaries) or a + * {@link Duration} (applicable to only timers). + * + * @author Phillip Webb + */ +final class MeterValue { + + private final Object value; + + MeterValue(long value) { + this.value = value; + } + + MeterValue(Duration value) { + this.value = value; + } + + /** + * Return the underlying value of the SLA in form suitable to apply to the given meter + * type. + * @param meterType the meter type + * @return the value or {@code null} if the value cannot be applied + */ + public Long getValue(Type meterType) { + if (meterType == Type.DISTRIBUTION_SUMMARY) { + return getDistributionSummaryValue(); + } + if (meterType == Type.TIMER) { + return getTimerValue(); + } + return null; + } + + private Long getDistributionSummaryValue() { + if (this.value instanceof Long) { + return (Long) this.value; + } + return null; + } + + private Long getTimerValue() { + if (this.value instanceof Long) { + return TimeUnit.MILLISECONDS.toNanos((long) this.value); + } + if (this.value instanceof Duration) { + return ((Duration) this.value).toNanos(); + } + return null; + } + + /** + * Return a new {@link MeterValue} instance for the given String value. The value may + * contain a simple number, or a {@link DurationStyle duration style string}. + * @param value the source value + * @return a {@link MeterValue} instance + */ + public static MeterValue valueOf(String value) { + if (isNumber(value)) { + return new MeterValue(Long.parseLong(value)); + } + return new MeterValue(DurationStyle.detectAndParse(value)); + } + + /** + * Return a new {@link MeterValue} instance for the given long value. + * @param value the source value + * @return a {@link MeterValue} instance + */ + public static MeterValue valueOf(long value) { + return new MeterValue(value); + } + + private static boolean isNumber(String value) { + return value.chars().allMatch(Character::isDigit); + } + +} 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 dcd309a0ad..009103f920 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 @@ -200,20 +200,18 @@ public class MetricsProperties { private final Map sla = new LinkedHashMap<>(); /** - * The minimum value that this distribution summary is expected to observe. - * Controls the number of buckets shipped by percentilesHistogram. Can be - * specified as a long or as a Duration value (for timer meters, defaulting to ms - * if no unit specified). + * Minimum value that meter IDs starting-with the specified name are expected to + * observe. The longest match wins. 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 minimumExpectedValue = new LinkedHashMap<>(); + private final Map minimumExpectedValue = new LinkedHashMap<>(); /** - * The maximum value that this distribution summary is expected to observe. - * Controls the number of buckets shipped by percentilesHistogram. Can be - * specified as a long or as a Duration value (for timer meters, defaulting to ms - * if no unit specified). + * Maximum value that meter IDs starting-with the specified name are expected to + * observe. The longest match wins. 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 maximumExpectedValue = new LinkedHashMap<>(); + private final Map maximumExpectedValue = new LinkedHashMap<>(); public Map getPercentilesHistogram() { return this.percentilesHistogram; @@ -227,11 +225,11 @@ public class MetricsProperties { return this.sla; } - public Map getMinimumExpectedValue() { + public Map getMinimumExpectedValue() { return this.minimumExpectedValue; } - public Map getMaximumExpectedValue() { + public Map getMaximumExpectedValue() { return this.maximumExpectedValue; } 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 d29a57b1c7..86487b3dfb 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 @@ -88,9 +88,9 @@ public class PropertiesMeterFilter implements MeterFilter { .percentiles( lookupWithFallbackToAll(distribution.getPercentiles(), id, null)) .sla(convertSla(id.getType(), lookup(distribution.getSla(), id, null))) - .minimumExpectedValue(convertSla(id.getType(), + .minimumExpectedValue(convertMeterValue(id.getType(), lookup(distribution.getMinimumExpectedValue(), id, null))) - .maximumExpectedValue(convertSla(id.getType(), + .maximumExpectedValue(convertMeterValue(id.getType(), lookup(distribution.getMaximumExpectedValue(), id, null))) .build().merge(config); } @@ -105,8 +105,8 @@ public class PropertiesMeterFilter implements MeterFilter { return (converted.length != 0) ? converted : null; } - private Long convertSla(Meter.Type meterType, ServiceLevelAgreementBoundary sla) { - return (sla != null) ? sla.getValue(meterType) : null; + private Long convertMeterValue(Meter.Type meterType, String value) { + return (value != null) ? MeterValue.valueOf(value).getValue(meterType) : null; } private T lookup(Map values, Id id, T defaultValue) { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ServiceLevelAgreementBoundary.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ServiceLevelAgreementBoundary.java index 707f1116f8..aae8f20f0d 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ServiceLevelAgreementBoundary.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/ServiceLevelAgreementBoundary.java @@ -17,12 +17,8 @@ package org.springframework.boot.actuate.autoconfigure.metrics; import java.time.Duration; -import java.util.concurrent.TimeUnit; import io.micrometer.core.instrument.Meter; -import io.micrometer.core.instrument.Meter.Type; - -import org.springframework.boot.convert.DurationStyle; /** * A service level agreement boundary for use when configuring micrometer. Can be @@ -34,13 +30,9 @@ import org.springframework.boot.convert.DurationStyle; */ public final class ServiceLevelAgreementBoundary { - private final Object value; - - ServiceLevelAgreementBoundary(long value) { - this.value = value; - } + private final MeterValue value; - ServiceLevelAgreementBoundary(Duration value) { + ServiceLevelAgreementBoundary(MeterValue value) { this.value = value; } @@ -51,37 +43,7 @@ public final class ServiceLevelAgreementBoundary { * @return the value or {@code null} if the value cannot be applied */ public Long getValue(Meter.Type meterType) { - if (meterType == Type.DISTRIBUTION_SUMMARY) { - return getDistributionSummaryValue(); - } - if (meterType == Type.TIMER) { - return getTimerValue(); - } - return null; - } - - private Long getDistributionSummaryValue() { - if (this.value instanceof Long) { - return (Long) this.value; - } - return null; - } - - private Long getTimerValue() { - if (this.value instanceof Long) { - return TimeUnit.MILLISECONDS.toNanos((long) this.value); - } - if (this.value instanceof Duration) { - return ((Duration) this.value).toNanos(); - } - return null; - } - - public static ServiceLevelAgreementBoundary valueOf(String value) { - if (isNumber(value)) { - return new ServiceLevelAgreementBoundary(Long.parseLong(value)); - } - return new ServiceLevelAgreementBoundary(DurationStyle.detectAndParse(value)); + return this.value.getValue(meterType); } /** @@ -91,18 +53,17 @@ public final class ServiceLevelAgreementBoundary { * @return a {@link ServiceLevelAgreementBoundary} instance */ public static ServiceLevelAgreementBoundary valueOf(long value) { - return new ServiceLevelAgreementBoundary(value); + return new ServiceLevelAgreementBoundary(MeterValue.valueOf(value)); } /** - * Return a new {@link ServiceLevelAgreementBoundary} instance for the given String - * value. The value may contain a simple number, or a {@link DurationStyle duration - * style string}. + * Return a new {@link ServiceLevelAgreementBoundary} instance for the given long + * value. * @param value the source value * @return a {@link ServiceLevelAgreementBoundary} instance */ - private static boolean isNumber(String value) { - return value.chars().allMatch(Character::isDigit); + public static ServiceLevelAgreementBoundary valueOf(String value) { + return new ServiceLevelAgreementBoundary(MeterValue.valueOf(value)); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterValueTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterValueTests.java new file mode 100644 index 0000000000..b86f350799 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/MeterValueTests.java @@ -0,0 +1,91 @@ +/* + * Copyright 2012-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * 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 org.springframework.boot.actuate.autoconfigure.metrics; + +import io.micrometer.core.instrument.Meter.Type; +import org.junit.Test; + +import org.springframework.boot.context.properties.bind.Bindable; +import org.springframework.boot.context.properties.bind.Binder; +import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.mock.env.MockEnvironment; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link MeterValue}. + * + * @author Phillip Webb + */ +public class MeterValueTests { + + @Test + public void getValueForDistributionSummaryWhenFromLongShouldReturnLongValue() { + MeterValue meterValue = MeterValue.valueOf(123L); + assertThat(meterValue.getValue(Type.DISTRIBUTION_SUMMARY)).isEqualTo(123); + } + + @Test + public void getValueForDistributionSummaryWhenFromNumberStringShouldReturnLongValue() { + MeterValue meterValue = MeterValue.valueOf("123"); + assertThat(meterValue.getValue(Type.DISTRIBUTION_SUMMARY)).isEqualTo(123); + } + + @Test + public void getValueForDistributionSummaryWhenFromDurationStringShouldReturnNull() { + MeterValue meterValue = MeterValue.valueOf("123ms"); + assertThat(meterValue.getValue(Type.DISTRIBUTION_SUMMARY)).isNull(); + } + + @Test + public void getValueForTimerWhenFromLongShouldReturnMsToNanosValue() { + MeterValue meterValue = MeterValue.valueOf(123L); + assertThat(meterValue.getValue(Type.TIMER)).isEqualTo(123000000); + } + + @Test + public void getValueForTimerWhenFromNumberStringShouldMsToNanosValue() { + MeterValue meterValue = MeterValue.valueOf("123"); + assertThat(meterValue.getValue(Type.TIMER)).isEqualTo(123000000); + } + + @Test + public void getValueForTimerWhenFromDurationStringShouldReturnDurationNanos() { + MeterValue meterValue = MeterValue.valueOf("123ms"); + assertThat(meterValue.getValue(Type.TIMER)).isEqualTo(123000000); + } + + @Test + public void getValueForOthersShouldReturnNull() { + MeterValue meterValue = MeterValue.valueOf("123"); + assertThat(meterValue.getValue(Type.COUNTER)).isNull(); + assertThat(meterValue.getValue(Type.GAUGE)).isNull(); + assertThat(meterValue.getValue(Type.LONG_TASK_TIMER)).isNull(); + assertThat(meterValue.getValue(Type.OTHER)).isNull(); + } + + @Test + public void valueOfShouldWorkInBinder() { + MockEnvironment environment = new MockEnvironment(); + TestPropertyValues.of("duration=10ms", "long=20").applyTo(environment); + assertThat(Binder.get(environment).bind("duration", Bindable.of(MeterValue.class)) + .get().getValue(Type.TIMER)).isEqualTo(10000000); + assertThat(Binder.get(environment).bind("long", Bindable.of(MeterValue.class)) + .get().getValue(Type.TIMER)).isEqualTo(20000000); + } + +} 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 5fd2d2f3f5..d3240f4485 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 @@ -255,7 +255,7 @@ public class PropertiesMeterFilterTests { @Test public void configureWhenHasMinimumExpectedValueShouldSetMinimumExpectedToValue() { PropertiesMeterFilter filter = new PropertiesMeterFilter( - createProperties("distribution.minimum-expected-value.[spring.boot]=10")); + createProperties("distribution.minimum-expected-value.spring.boot=10")); assertThat(filter.configure(createMeterId("spring.boot"), DistributionStatisticConfig.DEFAULT).getMinimumExpectedValue()) .isEqualTo(Duration.ofMillis(10).toNanos()); @@ -274,40 +274,16 @@ public class PropertiesMeterFilterTests { public void configureWhenHasHigherMinimumExpectedValueAndLowerShouldSetMinimumExpectedValueToHigher() { PropertiesMeterFilter filter = new PropertiesMeterFilter( createProperties("distribution.minimum-expected-value.spring=10", - "distribution.minimum-expected-value.[spring.boot]=50")); + "distribution.minimum-expected-value.spring.boot=50")); assertThat(filter.configure(createMeterId("spring.boot"), DistributionStatisticConfig.DEFAULT).getMinimumExpectedValue()) .isEqualTo(Duration.ofMillis(50).toNanos()); } - @Test - public void configureWhenAllMinimumExpectedValueSetShouldSetMinimumExpectedValueToValue() { - PropertiesMeterFilter filter = new PropertiesMeterFilter( - createProperties("distribution.minimum-expected-value.all=10")); - assertThat(filter.configure(createMeterId("spring.boot"), - DistributionStatisticConfig.DEFAULT).getMinimumExpectedValue()) - .isEqualTo(Duration.ofMillis(10).toNanos()); - } - - @Test - public void configureWhenMinimumExpectedValueDurationShouldOnlyApplyToTimer() { - PropertiesMeterFilter filter = new PropertiesMeterFilter( - createProperties("distribution.minimum-expected-value.all=10ms")); - 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) - .getMinimumExpectedValue()).isEqualTo(Duration.ofMillis(10).toNanos()); - assertThat(filter.configure(summary, DistributionStatisticConfig.DEFAULT) - .getMinimumExpectedValue()).isEqualTo(1L); - assertThat(filter.configure(counter, DistributionStatisticConfig.DEFAULT) - .getMinimumExpectedValue()).isEqualTo(1L); - } - @Test public void configureWhenHasMaximumExpectedValueShouldSetMaximumExpectedToValue() { - PropertiesMeterFilter filter = new PropertiesMeterFilter(createProperties( - "distribution.maximum-expected-value.[spring.boot]=5000")); + PropertiesMeterFilter filter = new PropertiesMeterFilter( + createProperties("distribution.maximum-expected-value.spring.boot=5000")); assertThat(filter.configure(createMeterId("spring.boot"), DistributionStatisticConfig.DEFAULT).getMaximumExpectedValue()) .isEqualTo(Duration.ofMillis(5000).toNanos()); @@ -326,36 +302,12 @@ public class PropertiesMeterFilterTests { public void configureWhenHasHigherMaximumExpectedValueAndLowerShouldSetMaximumExpectedValueToHigher() { PropertiesMeterFilter filter = new PropertiesMeterFilter( createProperties("distribution.maximum-expected-value.spring=5000", - "distribution.maximum-expected-value.[spring.boot]=10000")); + "distribution.maximum-expected-value.spring.boot=10000")); assertThat(filter.configure(createMeterId("spring.boot"), DistributionStatisticConfig.DEFAULT).getMaximumExpectedValue()) .isEqualTo(Duration.ofMillis(10000).toNanos()); } - @Test - public void configureWhenAllMaximumExpectedValueSetShouldSetMaximumExpectedValueToValue() { - PropertiesMeterFilter filter = new PropertiesMeterFilter( - createProperties("distribution.maximum-expected-value.all=5000")); - assertThat(filter.configure(createMeterId("spring.boot"), - DistributionStatisticConfig.DEFAULT).getMaximumExpectedValue()) - .isEqualTo(Duration.ofMillis(5000).toNanos()); - } - - @Test - public void configureWhenMaximumExpectedValueDurationShouldOnlyApplyToTimer() { - PropertiesMeterFilter filter = new PropertiesMeterFilter( - createProperties("distribution.maximum-expected-value.all=15s")); - 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) - .getMaximumExpectedValue()).isEqualTo(Duration.ofMillis(15000).toNanos()); - assertThat(filter.configure(summary, DistributionStatisticConfig.DEFAULT) - .getMaximumExpectedValue()).isEqualTo(Long.MAX_VALUE); - assertThat(filter.configure(counter, DistributionStatisticConfig.DEFAULT) - .getMaximumExpectedValue()).isEqualTo(Long.MAX_VALUE); - } - private Id createMeterId(String name) { Meter.Type meterType = Type.TIMER; return createMeterId(name, meterType); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/ServiceLevelAgreementBoundaryTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/ServiceLevelAgreementBoundaryTests.java index 99875e6467..a0df3aa3ff 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/ServiceLevelAgreementBoundaryTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/ServiceLevelAgreementBoundaryTests.java @@ -19,11 +19,6 @@ package org.springframework.boot.actuate.autoconfigure.metrics; import io.micrometer.core.instrument.Meter.Type; import org.junit.Test; -import org.springframework.boot.context.properties.bind.Bindable; -import org.springframework.boot.context.properties.bind.Binder; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.mock.env.MockEnvironment; - import static org.assertj.core.api.Assertions.assertThat; /** @@ -33,25 +28,6 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class ServiceLevelAgreementBoundaryTests { - @Test - public void getValueForDistributionSummaryWhenFromLongShouldReturnLongValue() { - ServiceLevelAgreementBoundary sla = ServiceLevelAgreementBoundary.valueOf(123L); - assertThat(sla.getValue(Type.DISTRIBUTION_SUMMARY)).isEqualTo(123); - } - - @Test - public void getValueForDistributionSummaryWhenFromNumberStringShouldReturnLongValue() { - ServiceLevelAgreementBoundary sla = ServiceLevelAgreementBoundary.valueOf("123"); - assertThat(sla.getValue(Type.DISTRIBUTION_SUMMARY)).isEqualTo(123); - } - - @Test - public void getValueForDistributionSummaryWhenFromDurationStringShouldReturnNull() { - ServiceLevelAgreementBoundary sla = ServiceLevelAgreementBoundary - .valueOf("123ms"); - assertThat(sla.getValue(Type.DISTRIBUTION_SUMMARY)).isNull(); - } - @Test public void getValueForTimerWhenFromLongShouldReturnMsToNanosValue() { ServiceLevelAgreementBoundary sla = ServiceLevelAgreementBoundary.valueOf(123L); @@ -71,25 +47,4 @@ public class ServiceLevelAgreementBoundaryTests { assertThat(sla.getValue(Type.TIMER)).isEqualTo(123000000); } - @Test - public void getValueForOthersShouldReturnNull() { - ServiceLevelAgreementBoundary sla = ServiceLevelAgreementBoundary.valueOf("123"); - assertThat(sla.getValue(Type.COUNTER)).isNull(); - assertThat(sla.getValue(Type.GAUGE)).isNull(); - assertThat(sla.getValue(Type.LONG_TASK_TIMER)).isNull(); - assertThat(sla.getValue(Type.OTHER)).isNull(); - } - - @Test - public void valueOfShouldWorkInBinder() { - MockEnvironment environment = new MockEnvironment(); - TestPropertyValues.of("duration=10ms", "long=20").applyTo(environment); - assertThat(Binder.get(environment) - .bind("duration", Bindable.of(ServiceLevelAgreementBoundary.class)).get() - .getValue(Type.TIMER)).isEqualTo(10000000); - assertThat(Binder.get(environment) - .bind("long", Bindable.of(ServiceLevelAgreementBoundary.class)).get() - .getValue(Type.TIMER)).isEqualTo(20000000); - } - } 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 ef142175b6..1ece72a682 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 @@ -1379,10 +1379,10 @@ content into your application. Rather, pick only the properties that you need. management.info.git.mode=simple # Mode to use to expose git information. # METRICS - management.metrics.distribution.percentiles-histogram.*= # Whether meter IDs starting with the specified name should publish percentile histograms. - management.metrics.distribution.minimum-expected-value.*= # Minimum limit on the histogram buckets for IDs starting with the specified name. The longest match wins, the key `all` can also be used to configure all meters. - management.metrics.distribution.maximum-expected-value.*= # Maximum limit on the histogram buckets for IDs starting with the specified name. The longest match wins, the key `all` can also be used to configure all meters. + management.metrics.distribution.maximum-expected-value.*= # Maximum value that meter IDs starting-with the specified name are expected to observe. + management.metrics.distribution.minimum-expected-value.*= # Minimum value that meter IDs starting-with the specified name are expected to observe. 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.percentiles-histogram.*= # Whether meter IDs starting with the specified name should publish percentile histograms. 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.