-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Describe the bug
A single recorded time (sample) affects a Timer
's max()
for a longer time than percentiles produced by the Timer
. With default DistributionStatisticConfig
the effective expiry is one minute for the percentiles and three minutes for max. The issue is related to how TimeWindowMax
and AbstractTimeWindowHistogram
interpret the value of DistributionStatisticConfig.expiry.
Both use ring buffers of same size to implement the decay, but while the former only moves by one buffer position in intervals equal to expiry
, the latter is implemented to do a full rotation of the buffer in the same time.
Environment
- Micrometer version: 1.9.x
- OS: Linux
- Java version: 17.0.3
To Reproduce
@Test
void demonstratesDifferentExpiryForMaxAndPercentiles() throws InterruptedException {
MeterRegistry meterRegistry = new SimpleMeterRegistry();
Timer timer = Timer.builder("test").publishPercentiles(new double[]{0.5}).register(meterRegistry);
Duration checkInterval = Duration.ofSeconds(30);
timer.record(Duration.ofMillis(200));
Duration testDuration = Duration.ZERO;
var max = timer.max(MILLISECONDS);
var snapshot = timer.takeSnapshot();
while (max != 0) {
System.out.printf("%ss: %s max %.0f%n", testDuration.toSeconds(), snapshot.percentileValues()[0], max);
Thread.sleep(checkInterval.toMillis());
testDuration = testDuration.plus(checkInterval);
max = timer.max(MILLISECONDS);
snapshot = timer.takeSnapshot();
}
System.out.printf("%ss: %s max %.0f%n", testDuration.toSeconds(), snapshot.percentileValues()[0], max);
}
Prints:
0s: (1.92937984E8 at 50.0%) max 200
30s: (1.92937984E8 at 50.0%) max 200
60s: (0.0 at 50.0%) max 200
90s: (0.0 at 50.0%) max 200
120s: (0.0 at 50.0%) max 200
150s: (0.0 at 50.0%) max 200
180s: (0.0 at 50.0%) max 0
Expected behaviour
A single sample ceases to affect percentiles and timer max at the same point in time.
Related issues
In #2751 there is a complaint about max not expiring in expected time, but response was that the TimeWindowMax
uses expiry
(and bufferLength
) from DistributionStatisticConfig
right.