Merge pull request #27584 from polarbear567

* pr/27584:
  Polish "Add expiry and bufferLength configuration properties"
  Add expiry and bufferLength configuration properties

Closes gh-27584
This commit is contained in:
Stephane Nicoll 2021-08-16 10:07:15 +02:00
commit 0d67a1af5c
4 changed files with 97 additions and 2 deletions

View File

@ -16,6 +16,7 @@
package org.springframework.boot.actuate.autoconfigure.metrics;
import java.time.Duration;
import java.util.LinkedHashMap;
import java.util.Map;
@ -296,6 +297,21 @@ public class MetricsProperties {
*/
private final Map<String, String> maximumExpectedValue = new LinkedHashMap<>();
/**
* Maximum amount of time that samples for meter IDs starting with the specified
* name are accumulated to decaying distribution statistics before they are reset
* and rotated. The longest match wins, the key `all` can also be used to
* configure all meters.
*/
private final Map<String, Duration> expiry = new LinkedHashMap<>();
/**
* Number of histograms for meter IDs starting with the specified name to keep in
* the ring buffer. The longest match wins, the key `all` can also be used to
* configure all meters.
*/
private final Map<String, Integer> bufferLength = new LinkedHashMap<>();
public Map<String, Boolean> getPercentilesHistogram() {
return this.percentilesHistogram;
}
@ -316,6 +332,14 @@ public class MetricsProperties {
return this.maximumExpectedValue;
}
public Map<String, Duration> getExpiry() {
return this.expiry;
}
public Map<String, Integer> getBufferLength() {
return this.bufferLength;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 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.
@ -89,7 +89,8 @@ public class PropertiesMeterFilter implements MeterFilter {
convertMeterValue(id.getType(), lookup(distribution.getMinimumExpectedValue(), id, null)))
.maximumExpectedValue(
convertMeterValue(id.getType(), lookup(distribution.getMaximumExpectedValue(), id, null)))
.build().merge(config);
.expiry(lookupWithFallbackToAll(distribution.getExpiry(), id, null))
.bufferLength(lookupWithFallbackToAll(distribution.getBufferLength(), id, null)).build().merge(config);
}
private double[] convertServiceLevelObjectives(Meter.Type meterType, ServiceLevelObjectiveBoundary[] slo) {

View File

@ -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.buffer-length.spring.boot=3"));
assertThat(
filter.configure(createMeterId("spring.boot"), DistributionStatisticConfig.DEFAULT).getBufferLength())
.isEqualTo(3);
}
@Test
void configureWhenHasHigherBufferLengthShouldSetBufferLengthToValue() {
PropertiesMeterFilter filter = new PropertiesMeterFilter(
createProperties("distribution.buffer-length.spring=3"));
assertThat(
filter.configure(createMeterId("spring.boot"), DistributionStatisticConfig.DEFAULT).getBufferLength())
.isEqualTo(3);
}
@Test
void configureWhenHasHigherBufferLengthAndLowerShouldSetBufferLengthToHigher() {
PropertiesMeterFilter filter = new PropertiesMeterFilter(
createProperties("distribution.buffer-length.spring=2", "distribution.buffer-length.spring.boot=3"));
assertThat(
filter.configure(createMeterId("spring.boot"), DistributionStatisticConfig.DEFAULT).getBufferLength())
.isEqualTo(3);
}
@Test
void configureWhenAllBufferLengthSetShouldSetBufferLengthToValue() {
PropertiesMeterFilter filter = new PropertiesMeterFilter(createProperties("distribution.buffer-length.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);

View File

@ -1153,6 +1153,10 @@ The following properties allow per-meter customization:
| configprop:management.metrics.distribution.percentiles[]
| Publish percentile values computed in your application
| configprop:management.metrics.distribution.expiry[], configprop:management.metrics.distribution.buffer-length[]
| Give greater weight to recent samples by accumulating them in ring buffers which rotate after a configurable expiry, with a
configurable buffer length.
| configprop:management.metrics.distribution.slo[]
| Publish a cumulative histogram with buckets defined by your service-level objectives.
|===