From 421ff5b03eb43ce45f51e07dd8033c85548fca0c Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Wed, 27 Dec 2023 17:28:17 +0100 Subject: [PATCH] For long task timers fixes the percentiles above interpolatable line without this change for the provided test one of the histogram buckets gets removed and an ArrayIndexOutOfBoundsException is thrown with this change the exception is not thrown anymore fixes gh-3877 --- .../internal/DefaultLongTaskTimer.java | 2 +- .../core/tck/DefaultLongTaskTimerTest.java | 42 +++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/internal/DefaultLongTaskTimer.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/internal/DefaultLongTaskTimer.java index ad8591d573..4f1ae810d6 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/internal/DefaultLongTaskTimer.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/internal/DefaultLongTaskTimer.java @@ -141,7 +141,7 @@ public HistogramSnapshot takeSnapshot() { CountAtBucket[] countAtBucketsArr = new CountAtBucket[0]; List percentilesAboveInterpolatableLine = percentilesRequested.stream() - .filter(p -> p * (activeTasks.size() + 1) > activeTasks.size()) + .filter(p -> p * (activeTasks.size() + 1) >= activeTasks.size()) .collect(Collectors.toList()); percentilesRequested.removeAll(percentilesAboveInterpolatableLine); diff --git a/micrometer-test/src/main/java/io/micrometer/core/tck/DefaultLongTaskTimerTest.java b/micrometer-test/src/main/java/io/micrometer/core/tck/DefaultLongTaskTimerTest.java index d92e6830ba..c53ce03e05 100644 --- a/micrometer-test/src/main/java/io/micrometer/core/tck/DefaultLongTaskTimerTest.java +++ b/micrometer-test/src/main/java/io/micrometer/core/tck/DefaultLongTaskTimerTest.java @@ -24,8 +24,12 @@ import io.micrometer.core.instrument.internal.DefaultLongTaskTimer; import io.micrometer.core.instrument.simple.SimpleConfig; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; + +import java.io.PrintStream; + +import org.junit.jupiter.api.*; import java.time.Duration; import java.util.Arrays; @@ -33,10 +37,22 @@ import java.util.concurrent.TimeUnit; import static io.micrometer.core.instrument.MockClock.clock; -import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.*; public class DefaultLongTaskTimerTest { + final ByteArrayOutputStream myErr = new ByteArrayOutputStream(); + + @BeforeEach + void setup() { + System.setErr(new PrintStream(myErr)); + } + + @AfterAll + static void cleanup() { + System.setErr(System.err); + } + @Test @DisplayName("supports sending histograms of active task duration") void histogram() { @@ -97,4 +113,24 @@ protected LongTaskTimer newLongTaskTimer(Meter.Id id, } } + @Test + void histogramToStringNotThrowingException() throws InterruptedException { + SimpleMeterRegistry simpleMeterRegistry = new SimpleMeterRegistry(); + + LongTaskTimer timer = LongTaskTimer.builder("jobrunr.jobs") + .publishPercentiles(0.25, 0.5, 0.75, 0.8, 0.9, 0.95) + .publishPercentileHistogram() + .register(simpleMeterRegistry); + LongTaskTimer.Sample start = timer.start(); + Thread.sleep(10); + + assertThatNoException().isThrownBy(() -> { + simpleMeterRegistry.getMetersAsString(); + start.stop(); + simpleMeterRegistry.getMetersAsString(); + String standardOutput = myErr.toString(); + assertThat(standardOutput).doesNotContain("ArrayIndexOutOfBoundsException"); + }); + } + }