Skip to content

Commit baf8b76

Browse files
jaydelucaCopilot
andauthored
Reduce flakyness of testExemplarsClassicHistogram (#1842)
I've been encountering issues with `io.prometheus.metrics.core.metrics.HistogramTest.testExemplarsClassicHistogram` when running tests locally, lot's of these: ``` [ERROR] Tests run: 28, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.279 s <<< FAILURE! -- in io.prometheus.metrics.core.metrics.HistogramTest [ERROR] io.prometheus.metrics.core.metrics.HistogramTest.testExemplarsClassicHistogram -- Time elapsed: 0.055 s <<< ERROR! java.lang.NullPointerException: Cannot invoke "io.prometheus.metrics.model.snapshots.Exemplar.getValue()" because "actual" is null at io.prometheus.metrics.core.metrics.TestUtil.assertExemplarEquals(TestUtil.java:13) at io.prometheus.metrics.core.metrics.HistogramTest.testExemplarsClassicHistogram(HistogramTest.java:1054) ``` attempting to make it a little more reliable with awaitility. Alternatively we could refactor the ExemplarSampler to take a clock as an argument so we could mock it, but I figured we could start here before we change the production code --------- Signed-off-by: Jay DeLuca <jaydeluca4@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent ba308cf commit baf8b76

File tree

1 file changed

+44
-5
lines changed
  • prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics

1 file changed

+44
-5
lines changed

prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/HistogramTest.java

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package io.prometheus.metrics.core.metrics;
22

33
import static io.prometheus.metrics.core.metrics.TestUtil.assertExemplarEquals;
4+
import static java.util.concurrent.TimeUnit.SECONDS;
45
import static org.assertj.core.api.Assertions.assertThat;
56
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
67
import static org.assertj.core.data.Offset.offset;
8+
import static org.awaitility.Awaitility.await;
79

810
import io.prometheus.metrics.config.EscapingScheme;
911
import io.prometheus.metrics.config.MetricsProperties;
@@ -1020,10 +1022,18 @@ public void markCurrentSpanAsExemplar() {}
10201022
assertThat(getExemplar(snapshot, Double.POSITIVE_INFINITY, "path", "/hello")).isNull();
10211023
assertThat(getExemplar(snapshot, Double.POSITIVE_INFINITY, "path", "/world")).isNull();
10221024

1023-
Thread.sleep(sampleIntervalMillis + 1);
1025+
waitForSampleInterval(sampleIntervalMillis);
10241026
histogram.labelValues("/hello").observe(4.5);
10251027
histogram.labelValues("/world").observe(4.5);
10261028

1029+
await()
1030+
.atMost(2, SECONDS)
1031+
.until(
1032+
() -> {
1033+
HistogramSnapshot s = histogram.collect();
1034+
return getExemplar(s, Double.POSITIVE_INFINITY, "path", "/hello") != null
1035+
&& getExemplar(s, Double.POSITIVE_INFINITY, "path", "/world") != null;
1036+
});
10271037
snapshot = histogram.collect();
10281038
assertExemplarEquals(ex1a, getExemplar(snapshot, 1.0, "path", "/hello"));
10291039
assertExemplarEquals(ex1b, getExemplar(snapshot, 1.0, "path", "/world"));
@@ -1036,16 +1046,28 @@ public void markCurrentSpanAsExemplar() {}
10361046
assertExemplarEquals(ex2a, getExemplar(snapshot, Double.POSITIVE_INFINITY, "path", "/hello"));
10371047
assertExemplarEquals(ex2b, getExemplar(snapshot, Double.POSITIVE_INFINITY, "path", "/world"));
10381048

1039-
Thread.sleep(sampleIntervalMillis + 1);
1049+
waitForSampleInterval(sampleIntervalMillis);
10401050
histogram.labelValues("/hello").observe(1.5);
10411051
histogram.labelValues("/world").observe(1.5);
1042-
Thread.sleep(sampleIntervalMillis + 1);
1052+
waitForSampleInterval(sampleIntervalMillis);
10431053
histogram.labelValues("/hello").observe(2.5);
10441054
histogram.labelValues("/world").observe(2.5);
1045-
Thread.sleep(sampleIntervalMillis + 1);
1055+
waitForSampleInterval(sampleIntervalMillis);
10461056
histogram.labelValues("/hello").observe(3.5);
10471057
histogram.labelValues("/world").observe(3.5);
10481058

1059+
await()
1060+
.atMost(2, SECONDS)
1061+
.until(
1062+
() -> {
1063+
HistogramSnapshot s = histogram.collect();
1064+
return getExemplar(s, 2.0, "path", "/hello") != null
1065+
&& getExemplar(s, 2.0, "path", "/world") != null
1066+
&& getExemplar(s, 3.0, "path", "/hello") != null
1067+
&& getExemplar(s, 3.0, "path", "/world") != null
1068+
&& getExemplar(s, 4.0, "path", "/hello") != null
1069+
&& getExemplar(s, 4.0, "path", "/world") != null;
1070+
});
10491071
snapshot = histogram.collect();
10501072
assertExemplarEquals(ex1a, getExemplar(snapshot, 1.0, "path", "/hello"));
10511073
assertExemplarEquals(ex1b, getExemplar(snapshot, 1.0, "path", "/world"));
@@ -1072,15 +1094,32 @@ public void markCurrentSpanAsExemplar() {}
10721094
"span_id",
10731095
"spanId-11"))
10741096
.build();
1075-
Thread.sleep(sampleIntervalMillis + 1);
1097+
waitForSampleInterval(sampleIntervalMillis);
10761098
histogram
10771099
.labelValues("/hello")
10781100
.observeWithExemplar(3.4, Labels.of("key1", "value1", "key2", "value2"));
1101+
await()
1102+
.atMost(2, SECONDS)
1103+
.until(
1104+
() -> {
1105+
Exemplar actual = getExemplar(histogram.collect(), 4.0, "path", "/hello");
1106+
return actual != null && Math.abs(actual.getValue() - 3.4) < 0.00001;
1107+
});
10791108
snapshot = histogram.collect();
10801109
// custom exemplars have preference, so the automatic exemplar is replaced
10811110
assertExemplarEquals(custom, getExemplar(snapshot, 4.0, "path", "/hello"));
10821111
}
10831112

1113+
/** Waits for the exemplar sampler's rate limit window so the next observation is accepted. */
1114+
private static void waitForSampleInterval(long sampleIntervalMillis) {
1115+
try {
1116+
Thread.sleep(2 * sampleIntervalMillis);
1117+
} catch (InterruptedException e) {
1118+
Thread.currentThread().interrupt();
1119+
throw new AssertionError("Interrupted while waiting for sample interval", e);
1120+
}
1121+
}
1122+
10841123
private Exemplar getExemplar(HistogramSnapshot snapshot, double le, String... labels) {
10851124
HistogramSnapshot.HistogramDataPointSnapshot data =
10861125
snapshot.getDataPoints().stream()

0 commit comments

Comments
 (0)