Skip to content

Timer max expiry inconsistent with percentiles expiry #3298

@gdabski

Description

@gdabski

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions