'Quarkus prometheus percentiles still zeroed after long metrics update time

I have a service bean MonitoringRegistryServiceImpl implementation in the Quarkus which I used to register timers and update them (code bellow). They were registered only once (into map timerMap) and then reused when recording / updating their values.

The problem I had that if I called http://localhost:8080/q/metrics to see the current state of percentile metrics I saw only zero values.

This happens only after long time period (e.g.3 hours without update of metrics). So far so good, that is something I would expect as there is distributionStatisticExpiry(Duration.ofMinutes(5)) for the percentiles. Let's call it "natural decay of values" :)

However, if I would updated the metrics and then called the http://localhost:8080/q/metrics again the zero values on percentiles were still there yet related counters and max values were updated correctly.

Maybe my understanding of percentiles is not complete, please advice.

Note: I use quarkus-micrometer-registry-prometheus artifact.

@JBossLog
@ApplicationScoped
public class MonitoringRegistryServiceImpl implements MonitoringRegistryService {

    private static final double[] PERCENTILES = { 0.5, 0.75, 0.95, 0.99 };
    private Map<String, Timer> timerMap = new ConcurrentHashMap<>();
    
    @Inject
    MeterRegistry registry;

    @Override
    public <T> void updateTimer(String timerName, String[] tags,
            Duration duration) {
        String key = timerName + "_" + String.join(".", tags);
        Timer timer = timerMap.get(key);

        if (timer != null) {
            log.debug("Key found:" + key);
            timer.record(duration);
        } else {
            log.debug("Key not found:" + key);
            Timer newTimer = Timer.builder(timerName).tags(newTags).publishPercentiles(PERCENTILES)
                    .distributionStatisticExpiry(Duration.ofMinutes(5))
                    .register(registry);
            timerMap.put(key, newTimer);
            newTimer.record(duration);
        }
    }

}


Solution 1:[1]

The solution was quite simple, rather than using the Timer.builder()..register() just use registry.timer(). There was also no need for the timerMap above. After this change, the timers metrics were not zeroed.

Timer timer = registry.timer(timerName, tags);
if (duration != null) {
    timer.record(duration);
} else {
    log.error("Time duration was equal to null for a metric with a timerName:" + timerName);
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Suraj Rao