diff --git a/implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpMetricConverter.java b/implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpMetricConverter.java index d666db2dfa..c505f8a6d3 100644 --- a/implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpMetricConverter.java +++ b/implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpMetricConverter.java @@ -126,6 +126,8 @@ private void writeHistogramSupport(HistogramSupport histogramSupport) { double max = isTimeBased ? histogramSnapshot.max(baseTimeUnit) : histogramSnapshot.max(); long count = histogramSnapshot.count(); + addMaxGaugeForTimer(id, tags, max); + // if percentiles configured, use summary if (histogramSnapshot.percentileValues().length != 0) { buildSummaryDataPoint(histogramSupport, tags, startTimeNanos, total, count, isTimeBased, histogramSnapshot); @@ -154,6 +156,20 @@ private static Optional getExponentialHistogramSna return Optional.empty(); } + private void addMaxGaugeForTimer(Meter.Id id, Iterable tags, double max) { + String metricName = id.getName() + ".max"; + Metric.Builder metricBuilder = getOrCreateMetricBuilder(id.withName(metricName), DataCase.GAUGE); + if (!metricBuilder.hasGauge()) { + metricBuilder.setGauge(io.opentelemetry.proto.metrics.v1.Gauge.newBuilder()); + } + + metricBuilder.getGaugeBuilder() + .addDataPoints(NumberDataPoint.newBuilder() + .setTimeUnixNano(TimeUnit.MILLISECONDS.toNanos(clock.wallTime())) + .setAsDouble(max) + .addAllAttributes(tags)); + } + private void writeFunctionTimer(FunctionTimer functionTimer) { Metric.Builder builder = getOrCreateMetricBuilder(functionTimer.getId(), DataCase.HISTOGRAM); HistogramDataPoint.Builder histogramDataPoint = HistogramDataPoint.newBuilder() diff --git a/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OTelCollectorIntegrationTest.java b/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OTelCollectorIntegrationTest.java index 9653f4dce0..a4e8726e42 100644 --- a/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OTelCollectorIntegrationTest.java +++ b/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OTelCollectorIntegrationTest.java @@ -107,11 +107,13 @@ void collectorShouldExportMetrics() throws Exception { // see: https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/20519 matchesPattern("(?s)^.*test_timer_milliseconds_sum\\{.+} 123\\.0\\n.*$"), matchesPattern("(?s)^.*test_timer_milliseconds_bucket\\{.+,le=\"\\+Inf\"} 1\\n.*$"), + matchesPattern("(?s)^.*test_timer_max_milliseconds\\{.+} 123\\.0\n.*$"), containsString("# HELP test_ds \n"), containsString("# TYPE test_ds histogram\n"), matchesPattern("(?s)^.*test_ds_count\\{.+} 1\\n.*$"), matchesPattern("(?s)^.*test_ds_sum\\{.+} 24\\.0\\n.*$"), + matchesPattern("(?s)^.*test_ds_max\\{.+} 24\\.0\\n.*$"), matchesPattern("(?s)^.*test_ds_bucket\\{.+,le=\"\\+Inf\"} 1\\n.*$") ); // @formatter:on diff --git a/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpCumulativeMeterRegistryTest.java b/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpCumulativeMeterRegistryTest.java index 022dbe61d2..9dddb2153f 100644 --- a/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpCumulativeMeterRegistryTest.java +++ b/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpCumulativeMeterRegistryTest.java @@ -26,6 +26,7 @@ import java.lang.management.ManagementFactory; import java.lang.management.OperatingSystemMXBean; import java.time.Duration; +import java.util.List; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -111,7 +112,9 @@ void timer() { timer.record(111, TimeUnit.MILLISECONDS); clock.add(otlpConfig().step()); timer.record(4, TimeUnit.MILLISECONDS); - assertThat(writeToMetric(timer).toString()).isEqualTo( + List metrics = writeToMetrics(timer); + Metric metric = metrics.stream().filter(Metric::hasHistogram).findFirst().orElseThrow(); + assertThat(metric.toString()).isEqualTo( "name: \"web.requests\"\n" + "description: \"timing web requests\"\n" + "unit: \"milliseconds\"\n" + "histogram {\n" + " data_points {\n" + " start_time_unix_nano: 1000000\n" + " time_unix_nano: 60001000000\n" + " count: 4\n" + " sum: 202.0\n" + " }\n" @@ -128,7 +131,9 @@ void timerWithHistogram() { clock.add(otlpConfig().step()); timer.record(4, TimeUnit.MILLISECONDS); - assertThat(writeToMetric(timer).toString()) + List metrics = writeToMetrics(timer); + Metric metric = metrics.stream().filter(Metric::hasHistogram).findFirst().orElseThrow(); + assertThat(metric.toString()) .isEqualTo("name: \"http.client.requests\"\n" + "unit: \"milliseconds\"\n" + "histogram {\n" + " data_points {\n" + " start_time_unix_nano: 1000000\n" + " time_unix_nano: 60001000000\n" + " count: 5\n" + " sum: 60202.0\n" + " bucket_counts: 0\n" + " bucket_counts: 0\n" @@ -198,13 +203,14 @@ void timerWithPercentiles() { timer.record(77, TimeUnit.MILLISECONDS); timer.record(111, TimeUnit.MILLISECONDS); - assertThat(writeToMetric(timer).toString()) - .isEqualTo("name: \"service.requests\"\n" + "unit: \"milliseconds\"\n" + "summary {\n" + " data_points {\n" - + " start_time_unix_nano: 1000000\n" + " time_unix_nano: 1000000\n" + " count: 3\n" - + " sum: 198.0\n" + " quantile_values {\n" + " quantile: 0.5\n" - + " value: 79.167488\n" + " }\n" + " quantile_values {\n" + " quantile: 0.9\n" - + " value: 112.72192\n" + " }\n" + " quantile_values {\n" + " quantile: 0.99\n" - + " value: 112.72192\n" + " }\n" + " }\n" + "}\n"); + List metrics = writeToMetrics(timer); + Metric metric = metrics.stream().filter(Metric::hasSummary).findFirst().orElseThrow(); + assertThat(metric.toString()).isEqualTo("name: \"service.requests\"\n" + "unit: \"milliseconds\"\n" + + "summary {\n" + " data_points {\n" + " start_time_unix_nano: 1000000\n" + + " time_unix_nano: 1000000\n" + " count: 3\n" + " sum: 198.0\n" + " quantile_values {\n" + + " quantile: 0.5\n" + " value: 79.167488\n" + " }\n" + " quantile_values {\n" + + " quantile: 0.9\n" + " value: 112.72192\n" + " }\n" + " quantile_values {\n" + + " quantile: 0.99\n" + " value: 112.72192\n" + " }\n" + " }\n" + "}\n"); } @Test @@ -230,10 +236,11 @@ void distributionSummary() { size.record(2233); clock.add(otlpConfig().step()); size.record(204); - - assertThat(writeToMetric(size).toString()).isEqualTo("name: \"http.response.size\"\n" + "unit: \"bytes\"\n" - + "histogram {\n" + " data_points {\n" + " start_time_unix_nano: 1000000\n" - + " time_unix_nano: 60001000000\n" + " count: 4\n" + " sum: 2552.0\n" + " }\n" + List metrics = writeToMetrics(size); + Metric metric = metrics.stream().filter(Metric::hasHistogram).findFirst().orElseThrow(); + assertThat(metric.toString()).isEqualTo("name: \"http.response.size\"\n" + "unit: \"bytes\"\n" + "histogram {\n" + + " data_points {\n" + " start_time_unix_nano: 1000000\n" + " time_unix_nano: 60001000000\n" + + " count: 4\n" + " sum: 2552.0\n" + " }\n" + " aggregation_temporality: AGGREGATION_TEMPORALITY_CUMULATIVE\n" + "}\n"); } @@ -471,7 +478,7 @@ void distributionSummaryWithHistogram() { + " explicit_bounds: 3.8430716820228234E18\n" + " explicit_bounds: 4.2273788502251054E18\n" + " }\n" + " aggregation_temporality: AGGREGATION_TEMPORALITY_CUMULATIVE\n" + "}\n"; String[] expectedLines = expected.split("\n"); - String actual = writeToMetric(size).toString(); + String actual = writeToMetrics(size).stream().filter(Metric::hasHistogram).findFirst().orElseThrow().toString(); String[] actualLines = actual.split("\n"); assertThat(actualLines).hasSameSizeAs(expectedLines); for (int i = 0; i < actualLines.length; i++) { @@ -505,13 +512,14 @@ void distributionSummaryWithPercentiles() { clock.add(otlpConfig().step()); size.record(204); - assertThat(writeToMetric(size).toString()) - .isEqualTo("name: \"http.response.size\"\n" + "unit: \"bytes\"\n" + "summary {\n" + " data_points {\n" - + " start_time_unix_nano: 1000000\n" + " time_unix_nano: 60001000000\n" + " count: 4\n" - + " sum: 2552.0\n" + " quantile_values {\n" + " quantile: 0.5\n" + " value: 200.0\n" - + " }\n" + " quantile_values {\n" + " quantile: 0.9\n" + " value: 200.0\n" - + " }\n" + " quantile_values {\n" + " quantile: 0.99\n" + " value: 200.0\n" - + " }\n" + " }\n" + "}\n"); + List metrics = writeToMetrics(size); + Metric metric = metrics.stream().filter(Metric::hasSummary).findFirst().orElseThrow(); + assertThat(metric.toString()).isEqualTo("name: \"http.response.size\"\n" + "unit: \"bytes\"\n" + "summary {\n" + + " data_points {\n" + " start_time_unix_nano: 1000000\n" + " time_unix_nano: 60001000000\n" + + " count: 4\n" + " sum: 2552.0\n" + " quantile_values {\n" + " quantile: 0.5\n" + + " value: 200.0\n" + " }\n" + " quantile_values {\n" + " quantile: 0.9\n" + + " value: 200.0\n" + " }\n" + " quantile_values {\n" + " quantile: 0.99\n" + + " value: 200.0\n" + " }\n" + " }\n" + "}\n"); } private double extractValue(String line) { @@ -525,11 +533,12 @@ void longTaskTimer() { LongTaskTimer.Sample task2 = taskTimer.start(); this.clock.add(otlpConfig().step().multipliedBy(3)); - assertThat(writeToMetric(taskTimer).toString()) - .isEqualTo("name: \"checkout.batch\"\n" + "unit: \"milliseconds\"\n" + "histogram {\n" + " data_points {\n" - + " start_time_unix_nano: 1000000\n" + " time_unix_nano: 180001000000\n" + " count: 2\n" - + " sum: 360000.0\n" + " }\n" - + " aggregation_temporality: AGGREGATION_TEMPORALITY_CUMULATIVE\n" + "}\n"); + List metrics = writeToMetrics(taskTimer); + Metric metric = metrics.stream().filter(Metric::hasHistogram).findFirst().orElseThrow(); + assertThat(metric.toString()).isEqualTo("name: \"checkout.batch\"\n" + "unit: \"milliseconds\"\n" + + "histogram {\n" + " data_points {\n" + " start_time_unix_nano: 1000000\n" + + " time_unix_nano: 180001000000\n" + " count: 2\n" + " sum: 360000.0\n" + " }\n" + + " aggregation_temporality: AGGREGATION_TEMPORALITY_CUMULATIVE\n" + "}\n"); task1.stop(); task2.stop(); @@ -537,7 +546,9 @@ void longTaskTimer() { // this is not right that count/sum reset, but it's the same thing we do with // prometheus - assertThat(writeToMetric(taskTimer).toString()) + metrics = writeToMetrics(taskTimer); + metric = metrics.stream().filter(Metric::hasHistogram).findFirst().orElseThrow(); + assertThat(metric.toString()) .isEqualTo("name: \"checkout.batch\"\n" + "unit: \"milliseconds\"\n" + "histogram {\n" + " data_points {\n" + " start_time_unix_nano: 1000000\n" + " time_unix_nano: 240001000000\n" + " sum: 0.0\n" + " }\n" + " aggregation_temporality: AGGREGATION_TEMPORALITY_CUMULATIVE\n" + "}\n"); @@ -568,7 +579,8 @@ void testExponentialHistogramWithTimer() { timer.record(Duration.ofMillis(100)); timer.record(Duration.ofMillis(1000)); - Metric metric = writeToMetric(timer); + List metrics = writeToMetrics(timer); + Metric metric = metrics.stream().filter(Metric::hasExponentialHistogram).findFirst().orElseThrow(); assertThat(metric.getExponentialHistogram().getDataPointsCount()).isPositive(); ExponentialHistogramDataPoint exponentialHistogramDataPoint = metric.getExponentialHistogram().getDataPoints(0); @@ -585,7 +597,8 @@ void testExponentialHistogramWithTimer() { clock.add(exponentialHistogramOtlpConfig().step()); timer.record(Duration.ofMillis(10000)); - metric = writeToMetric(timer); + metrics = writeToMetrics(timer); + metric = metrics.stream().filter(Metric::hasExponentialHistogram).findFirst().orElseThrow(); exponentialHistogramDataPoint = metric.getExponentialHistogram().getDataPoints(0); assertThat(exponentialHistogramDataPoint.getTimeUnixNano() - previousEndTime) .isEqualTo(otlpConfig().step().toNanos()); @@ -611,7 +624,8 @@ void testExponentialHistogramDs() { ds.record(100); ds.record(1000); - Metric metric = writeToMetric(ds); + List metrics = writeToMetrics(ds); + Metric metric = metrics.stream().filter(Metric::hasExponentialHistogram).findFirst().orElseThrow(); assertThat(metric.getExponentialHistogram().getDataPointsCount()).isPositive(); ExponentialHistogramDataPoint exponentialHistogramDataPoint = metric.getExponentialHistogram().getDataPoints(0); @@ -628,7 +642,8 @@ void testExponentialHistogramDs() { clock.add(exponentialHistogramOtlpConfig().step()); ds.record(10000); - metric = writeToMetric(ds); + metrics = writeToMetrics(ds); + metric = metrics.stream().filter(Metric::hasExponentialHistogram).findFirst().orElseThrow(); exponentialHistogramDataPoint = metric.getExponentialHistogram().getDataPoints(0); assertThat(exponentialHistogramDataPoint.getTimeUnixNano() - previousEndTime) .isEqualTo(otlpConfig().step().toNanos()); diff --git a/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpDeltaMeterRegistryTest.java b/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpDeltaMeterRegistryTest.java index ca7de9753b..376ae48a18 100644 --- a/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpDeltaMeterRegistryTest.java +++ b/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpDeltaMeterRegistryTest.java @@ -162,23 +162,23 @@ void timer() { timer.record(77, MILLISECONDS); timer.record(111, MILLISECONDS); - assertHistogram(writeToMetric(timer), 0, TimeUnit.MINUTES.toNanos(1), UNIT_MILLISECONDS, 0, 0, 0); + assertHistogram(writeToMetrics(timer), 0, TimeUnit.MINUTES.toNanos(1), UNIT_MILLISECONDS, 0, 0, 0); stepOverNStep(1); - assertHistogram(writeToMetric(timer), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), + assertHistogram(writeToMetrics(timer), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), UNIT_MILLISECONDS, 3, 198, 111); timer.record(4, MILLISECONDS); - assertHistogram(writeToMetric(timer), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), + assertHistogram(writeToMetrics(timer), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), UNIT_MILLISECONDS, 3, 198, 111); stepOverNStep(1); - assertHistogram(writeToMetric(timer), TimeUnit.MINUTES.toNanos(2), TimeUnit.MINUTES.toNanos(3), + assertHistogram(writeToMetrics(timer), TimeUnit.MINUTES.toNanos(2), TimeUnit.MINUTES.toNanos(3), UNIT_MILLISECONDS, 1, 4, 4); stepOverNStep(2); - assertHistogram(writeToMetric(timer), TimeUnit.MINUTES.toNanos(4), TimeUnit.MINUTES.toNanos(5), + assertHistogram(writeToMetrics(timer), TimeUnit.MINUTES.toNanos(4), TimeUnit.MINUTES.toNanos(5), UNIT_MILLISECONDS, 0, 0, 0); timer.record(1, MILLISECONDS); stepOverNStep(1); - assertHistogram(writeToMetric(timer), TimeUnit.MINUTES.toNanos(5), TimeUnit.MINUTES.toNanos(6), + assertHistogram(writeToMetrics(timer), TimeUnit.MINUTES.toNanos(5), TimeUnit.MINUTES.toNanos(6), UNIT_MILLISECONDS, 1, 1, 1); } @@ -195,46 +195,54 @@ void timerWithHistogram() { timer.record(77, MILLISECONDS); timer.record(111, MILLISECONDS); - HistogramDataPoint histogramDataPoint = writeToMetric(timer).getHistogram().getDataPoints(0); - assertThat(histogramDataPoint.getExplicitBoundsCount()).isEqualTo(4); + assertThat(writeToMetrics(timer)).filteredOn(Metric::hasHistogram).singleElement().satisfies(metric -> { + HistogramDataPoint histogramDataPoint = metric.getHistogram().getDataPoints(0); + assertThat(histogramDataPoint.getExplicitBoundsCount()).isEqualTo(4); + }); stepOverNStep(1); - Metric metric = writeToMetric(timer); - assertHistogram(metric, TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), UNIT_MILLISECONDS, 3, 198, + List metrics = writeToMetrics(timer); + assertHistogram(metrics, TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), UNIT_MILLISECONDS, 3, 198, 111); - histogramDataPoint = metric.getHistogram().getDataPoints(0); - assertThat(histogramDataPoint.getExplicitBoundsCount()).isEqualTo(4); - - assertThat(histogramDataPoint.getExplicitBounds(0)).isEqualTo(10.0); - assertThat(histogramDataPoint.getBucketCounts(0)).isEqualTo(1); - assertThat(histogramDataPoint.getExplicitBounds(1)).isEqualTo(50.0); - assertThat(histogramDataPoint.getBucketCounts(1)).isZero(); - assertThat(histogramDataPoint.getExplicitBounds(2)).isEqualTo(100.0); - assertThat(histogramDataPoint.getBucketCounts(2)).isEqualTo(1); - assertThat(histogramDataPoint.getExplicitBounds(3)).isEqualTo(500.0); - assertThat(histogramDataPoint.getBucketCounts(3)).isEqualTo(1); - + assertThat(metrics).filteredOn(Metric::hasHistogram).singleElement().satisfies(metric -> { + HistogramDataPoint histogramDataPoint = metric.getHistogram().getDataPoints(0); + assertThat(histogramDataPoint.getExplicitBoundsCount()).isEqualTo(4); + + assertThat(histogramDataPoint.getExplicitBounds(0)).isEqualTo(10.0); + assertThat(histogramDataPoint.getBucketCounts(0)).isEqualTo(1); + assertThat(histogramDataPoint.getExplicitBounds(1)).isEqualTo(50.0); + assertThat(histogramDataPoint.getBucketCounts(1)).isZero(); + assertThat(histogramDataPoint.getExplicitBounds(2)).isEqualTo(100.0); + assertThat(histogramDataPoint.getBucketCounts(2)).isEqualTo(1); + assertThat(histogramDataPoint.getExplicitBounds(3)).isEqualTo(500.0); + assertThat(histogramDataPoint.getBucketCounts(3)).isEqualTo(1); + }); timer.record(4, MILLISECONDS); stepOverNStep(1); - metric = writeToMetric(timer); - assertHistogram(metric, TimeUnit.MINUTES.toNanos(2), TimeUnit.MINUTES.toNanos(3), UNIT_MILLISECONDS, 1, 4, 4); + metrics = writeToMetrics(timer); + assertHistogram(metrics, TimeUnit.MINUTES.toNanos(2), TimeUnit.MINUTES.toNanos(3), UNIT_MILLISECONDS, 1, 4, 4); - histogramDataPoint = metric.getHistogram().getDataPoints(0); + assertThat(metrics).filteredOn(Metric::hasHistogram).singleElement().satisfies(metric -> { - assertThat(histogramDataPoint.getBucketCounts(0)).isEqualTo(1); - assertThat(histogramDataPoint.getBucketCounts(1)).isZero(); - assertThat(histogramDataPoint.getBucketCounts(2)).isZero(); - assertThat(histogramDataPoint.getBucketCounts(3)).isZero(); + HistogramDataPoint histogramDataPoint = metric.getHistogram().getDataPoints(0); + assertThat(histogramDataPoint.getBucketCounts(0)).isEqualTo(1); + assertThat(histogramDataPoint.getBucketCounts(1)).isZero(); + assertThat(histogramDataPoint.getBucketCounts(2)).isZero(); + assertThat(histogramDataPoint.getBucketCounts(3)).isZero(); + }); timer.record(4, MILLISECONDS); stepOverNStep(2); - histogramDataPoint = writeToMetric(timer).getHistogram().getDataPoints(0); - assertThat(histogramDataPoint.getBucketCounts(0)).isZero(); - assertThat(histogramDataPoint.getBucketCounts(1)).isZero(); - assertThat(histogramDataPoint.getBucketCounts(2)).isZero(); - assertThat(histogramDataPoint.getBucketCounts(3)).isZero(); + + assertThat(writeToMetrics(timer)).filteredOn(Metric::hasHistogram).singleElement().satisfies(metric -> { + HistogramDataPoint histogramDataPoint = metric.getHistogram().getDataPoints(0); + assertThat(histogramDataPoint.getBucketCounts(0)).isZero(); + assertThat(histogramDataPoint.getBucketCounts(1)).isZero(); + assertThat(histogramDataPoint.getBucketCounts(2)).isZero(); + assertThat(histogramDataPoint.getBucketCounts(3)).isZero(); + }); } @Test @@ -243,12 +251,12 @@ void functionTimer() { .description(METER_DESCRIPTION) .tags(Tags.of(meterTag)) .register(registry); - assertHistogram(writeToMetric(functionTimer), 0, TimeUnit.MINUTES.toNanos(1), UNIT_MILLISECONDS, 0, 0, 0); + assertHistogram(writeToMetrics(functionTimer), 0, TimeUnit.MINUTES.toNanos(1), UNIT_MILLISECONDS, 0, 0, 0); stepOverNStep(1); - assertHistogram(writeToMetric(functionTimer), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), + assertHistogram(writeToMetrics(functionTimer), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), UNIT_MILLISECONDS, 5, 127, 0); stepOverNStep(1); - assertHistogram(writeToMetric(functionTimer), TimeUnit.MINUTES.toNanos(2), TimeUnit.MINUTES.toNanos(3), + assertHistogram(writeToMetrics(functionTimer), TimeUnit.MINUTES.toNanos(2), TimeUnit.MINUTES.toNanos(3), UNIT_MILLISECONDS, 0, 0, 0); } @@ -263,15 +271,15 @@ void distributionSummary() { size.record(15); size.record(2233); - assertHistogram(writeToMetric(size), 0, TimeUnit.MINUTES.toNanos(1), BaseUnits.BYTES, 0, 0, 0); + assertHistogram(writeToMetrics(size), 0, TimeUnit.MINUTES.toNanos(1), BaseUnits.BYTES, 0, 0, 0); stepOverNStep(1); - assertHistogram(writeToMetric(size), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), BaseUnits.BYTES, + assertHistogram(writeToMetrics(size), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), BaseUnits.BYTES, 3, 2348, 2233); size.record(204); - assertHistogram(writeToMetric(size), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), BaseUnits.BYTES, + assertHistogram(writeToMetrics(size), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), BaseUnits.BYTES, 3, 2348, 2233); stepOverNStep(1); - assertHistogram(writeToMetric(size), TimeUnit.MINUTES.toNanos(2), TimeUnit.MINUTES.toNanos(3), BaseUnits.BYTES, + assertHistogram(writeToMetrics(size), TimeUnit.MINUTES.toNanos(2), TimeUnit.MINUTES.toNanos(3), BaseUnits.BYTES, 1, 204, 204); } @@ -284,45 +292,40 @@ void distributionSummaryWithHistogram() { .serviceLevelObjectives(10, 50, 100, 500) .register(registry); - assertHistogram(writeToMetric(ds), 0, TimeUnit.MINUTES.toNanos(1), BaseUnits.BYTES, 0, 0, 0); + assertHistogram(writeToMetrics(ds), 0, TimeUnit.MINUTES.toNanos(1), BaseUnits.BYTES, 0, 0, 0); ds.record(10); ds.record(77); ds.record(111); - assertHistogram(writeToMetric(ds), 0, TimeUnit.MINUTES.toNanos(1), BaseUnits.BYTES, 0, 0, 0); - - HistogramDataPoint histogramDataPoint = writeToMetric(ds).getHistogram().getDataPoints(0); - assertThat(histogramDataPoint.getExplicitBoundsCount()).isEqualTo(4); + assertHistogram(writeToMetrics(ds), 0, TimeUnit.MINUTES.toNanos(1), BaseUnits.BYTES, 0, 0, 0, + histogramDataPoint -> { + assertThat(histogramDataPoint.getExplicitBoundsCount()).isEqualTo(4); + }); stepOverNStep(1); - Metric metric = writeToMetric(ds); - assertHistogram(metric, TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), BaseUnits.BYTES, 3, 198, 111); - - histogramDataPoint = metric.getHistogram().getDataPoints(0); - assertThat(histogramDataPoint.getExplicitBoundsCount()).isEqualTo(4); - - assertThat(histogramDataPoint.getExplicitBounds(0)).isEqualTo(10); - assertThat(histogramDataPoint.getBucketCounts(0)).isEqualTo(1); - assertThat(histogramDataPoint.getExplicitBounds(1)).isEqualTo(50); - assertThat(histogramDataPoint.getBucketCounts(1)).isZero(); - assertThat(histogramDataPoint.getExplicitBounds(2)).isEqualTo(100); - assertThat(histogramDataPoint.getBucketCounts(2)).isEqualTo(1); - assertThat(histogramDataPoint.getExplicitBounds(3)).isEqualTo(500); - assertThat(histogramDataPoint.getBucketCounts(3)).isEqualTo(1); - + assertHistogram(writeToMetrics(ds), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), BaseUnits.BYTES, + 3, 198, 111, histogramDataPoint -> { + assertThat(histogramDataPoint.getExplicitBoundsCount()).isEqualTo(4); + + assertThat(histogramDataPoint.getExplicitBounds(0)).isEqualTo(10); + assertThat(histogramDataPoint.getBucketCounts(0)).isEqualTo(1); + assertThat(histogramDataPoint.getExplicitBounds(1)).isEqualTo(50); + assertThat(histogramDataPoint.getBucketCounts(1)).isZero(); + assertThat(histogramDataPoint.getExplicitBounds(2)).isEqualTo(100); + assertThat(histogramDataPoint.getBucketCounts(2)).isEqualTo(1); + assertThat(histogramDataPoint.getExplicitBounds(3)).isEqualTo(500); + assertThat(histogramDataPoint.getBucketCounts(3)).isEqualTo(1); + }); stepOverNStep(1); ds.record(4); clock.addSeconds(otlpConfig().step().getSeconds() - 5); - metric = writeToMetric(ds); - assertHistogram(writeToMetric(ds), TimeUnit.MINUTES.toNanos(2), TimeUnit.MINUTES.toNanos(3), BaseUnits.BYTES, 1, - 4, 4); - - histogramDataPoint = metric.getHistogram().getDataPoints(0); - - assertThat(histogramDataPoint.getBucketCounts(0)).isEqualTo(1); - assertThat(histogramDataPoint.getBucketCounts(1)).isZero(); - assertThat(histogramDataPoint.getBucketCounts(2)).isZero(); - assertThat(histogramDataPoint.getBucketCounts(3)).isZero(); + assertHistogram(writeToMetrics(ds), TimeUnit.MINUTES.toNanos(2), TimeUnit.MINUTES.toNanos(3), BaseUnits.BYTES, + 1, 4, 4, histogramDataPoint -> { + assertThat(histogramDataPoint.getBucketCounts(0)).isEqualTo(1); + assertThat(histogramDataPoint.getBucketCounts(1)).isZero(); + assertThat(histogramDataPoint.getBucketCounts(2)).isZero(); + assertThat(histogramDataPoint.getBucketCounts(3)).isZero(); + }); } @Test @@ -339,20 +342,26 @@ void distributionSummaryWithPercentiles() { stepOverNStep(1); size.record(204); - Metric metric = writeToMetric(size); - assertThat(metric.getName()).isEqualTo(METER_NAME); - assertThat(metric.getDescription()).isEqualTo(METER_DESCRIPTION); - assertThat(metric.getUnit()).isEqualTo(BaseUnits.BYTES); - List dataPoints = metric.getSummary().getDataPointsList(); - assertThat(dataPoints).hasSize(1); - List quantiles = dataPoints.get(0).getQuantileValuesList(); - assertThat(quantiles).hasSize(3); - assertThat(quantiles.get(0)).satisfies(quantile -> assertThat(quantile.getQuantile()).isEqualTo(0.5)) - .satisfies(quantile -> assertThat(quantile.getValue()).isEqualTo(200)); - assertThat(quantiles.get(1)).satisfies(quantile -> assertThat(quantile.getQuantile()).isEqualTo(0.9)) - .satisfies(quantile -> assertThat(quantile.getValue()).isEqualTo(200)); - assertThat(quantiles.get(2)).satisfies(quantile -> assertThat(quantile.getQuantile()).isEqualTo(0.99)) - .satisfies(quantile -> assertThat(quantile.getValue()).isEqualTo(200)); + List metrics = writeToMetrics(size); + assertThat(metrics).filteredOn(Metric::hasSummary).singleElement().satisfies(metric -> { + assertThat(metric.getName()).isEqualTo(METER_NAME); + assertThat(metric.getDescription()).isEqualTo(METER_DESCRIPTION); + assertThat(metric.getUnit()).isEqualTo(BaseUnits.BYTES); + List dataPoints = metric.getSummary().getDataPointsList(); + assertThat(dataPoints).hasSize(1); + List quantiles = dataPoints.get(0).getQuantileValuesList(); + assertThat(quantiles).hasSize(3); + assertThat(quantiles.get(0)).satisfies(quantile -> assertThat(quantile.getQuantile()).isEqualTo(0.5)) + .satisfies(quantile -> assertThat(quantile.getValue()).isEqualTo(200)); + assertThat(quantiles.get(1)).satisfies(quantile -> assertThat(quantile.getQuantile()).isEqualTo(0.9)) + .satisfies(quantile -> assertThat(quantile.getValue()).isEqualTo(200)); + assertThat(quantiles.get(2)).satisfies(quantile -> assertThat(quantile.getQuantile()).isEqualTo(0.99)) + .satisfies(quantile -> assertThat(quantile.getValue()).isEqualTo(200)); + }); + assertThat(metrics).filteredOn(Metric::hasGauge).singleElement().satisfies(metric -> { + assertThat(metric.getName()).isEqualTo(METER_NAME + ".max"); + assertThat(metric.getGauge().getDataPoints(0).getAsDouble()).isEqualTo(2233.0); + }); } @Test @@ -364,15 +373,15 @@ void longTaskTimer() { LongTaskTimer.Sample task1 = taskTimer.start(); LongTaskTimer.Sample task2 = taskTimer.start(); stepOverNStep(3); - assertHistogram(writeToMetric(taskTimer), TimeUnit.MINUTES.toNanos(3), TimeUnit.MINUTES.toNanos(4), + assertHistogram(writeToMetrics(taskTimer), TimeUnit.MINUTES.toNanos(3), TimeUnit.MINUTES.toNanos(4), UNIT_MILLISECONDS, 2, 360000, 180000); task1.stop(); - assertHistogram(writeToMetric(taskTimer), TimeUnit.MINUTES.toNanos(3), TimeUnit.MINUTES.toNanos(4), + assertHistogram(writeToMetrics(taskTimer), TimeUnit.MINUTES.toNanos(3), TimeUnit.MINUTES.toNanos(4), UNIT_MILLISECONDS, 1, 180000, 180000); task2.stop(); stepOverNStep(1); - assertHistogram(writeToMetric(taskTimer), TimeUnit.MINUTES.toNanos(4), TimeUnit.MINUTES.toNanos(5), + assertHistogram(writeToMetrics(taskTimer), TimeUnit.MINUTES.toNanos(4), TimeUnit.MINUTES.toNanos(5), UNIT_MILLISECONDS, 0, 0, 0); } @@ -451,26 +460,27 @@ void scheduledRolloverTimer() { .register(registry); registry.pollMetersToRollover(); - assertHistogram(writeToMetric(timer), 0, TimeUnit.MINUTES.toNanos(1), UNIT_MILLISECONDS, 0, 0, 0); + assertHistogram(writeToMetrics(timer), 0, TimeUnit.MINUTES.toNanos(1), UNIT_MILLISECONDS, 0, 0, 0); timer.record(Duration.ofMillis(5)); timer.record(Duration.ofMillis(15)); timer.record(Duration.ofMillis(150)); - assertHistogram(writeToMetric(timer), 0, TimeUnit.MINUTES.toNanos(1), UNIT_MILLISECONDS, 0, 0, 0); - assertThat(writeToMetric(timer).getHistogram().getDataPoints(0).getBucketCountsList()).allMatch(e -> e == 0); + assertHistogram(writeToMetrics(timer), 0, TimeUnit.MINUTES.toNanos(1), UNIT_MILLISECONDS, 0, 0, 0, + histogram -> assertThat(histogram.getBucketCountsList()).allMatch(e -> e == 0)); + stepOverNStep(1); // This should roll over the entire Meter to next step. registry.pollMetersToRollover(); - assertHistogram(writeToMetric(timer), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), - UNIT_MILLISECONDS, 3, 170, 150); - assertThat(writeToMetric(timer).getHistogram().getDataPoints(0).getBucketCountsList()).allMatch(e -> e == 1); + assertHistogram(writeToMetrics(timer), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), + UNIT_MILLISECONDS, 3, 170, 150, + histogram -> assertThat(histogram.getBucketCountsList()).allMatch(e -> e == 1)); clock.addSeconds(1); timer.record(Duration.ofMillis(160)); // This belongs to current step. - assertThat(writeToMetric(timer).getHistogram().getDataPoints(0).getBucketCountsList()).allMatch(e -> e == 1); - assertHistogram(writeToMetric(timer), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), - UNIT_MILLISECONDS, 3, 170, 150); + assertHistogram(writeToMetrics(timer), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), + UNIT_MILLISECONDS, 3, 170, 150, + histogram -> assertThat(histogram.getBucketCountsList()).allMatch(e -> e == 1)); } @@ -484,26 +494,26 @@ void scheduledRolloverDistributionSummary() { .register(registry); registry.pollMetersToRollover(); - assertHistogram(writeToMetric(ds), 0, TimeUnit.MINUTES.toNanos(1), BaseUnits.BYTES, 0, 0, 0); + assertHistogram(writeToMetrics(ds), 0, TimeUnit.MINUTES.toNanos(1), BaseUnits.BYTES, 0, 0, 0); ds.record(5); ds.record(15); ds.record(150); - assertHistogram(writeToMetric(ds), 0, TimeUnit.MINUTES.toNanos(1), BaseUnits.BYTES, 0, 0, 0); - assertThat(writeToMetric(ds).getHistogram().getDataPoints(0).getBucketCountsList()).allMatch(e -> e == 0); + assertHistogram(writeToMetrics(ds), 0, TimeUnit.MINUTES.toNanos(1), BaseUnits.BYTES, 0, 0, 0, + histogram -> assertThat(histogram.getBucketCountsList()).allMatch(e -> e == 0)); stepOverNStep(1); registry.pollMetersToRollover(); // This should roll over the entire Meter to next // step. - assertHistogram(writeToMetric(ds), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), BaseUnits.BYTES, 3, - 170, 150); + assertHistogram(writeToMetrics(ds), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), BaseUnits.BYTES, + 3, 170, 150); assertThat(writeToMetric(ds).getHistogram().getDataPoints(0).getBucketCountsList()).allMatch(e -> e == 1); clock.addSeconds(1); ds.record(160); // This belongs to current step. assertThat(writeToMetric(ds).getHistogram().getDataPoints(0).getBucketCountsList()).allMatch(e -> e == 1); - assertHistogram(writeToMetric(ds), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), BaseUnits.BYTES, 3, - 170, 150); + assertHistogram(writeToMetrics(ds), TimeUnit.MINUTES.toNanos(1), TimeUnit.MINUTES.toNanos(2), BaseUnits.BYTES, + 3, 170, 150); } @Test @@ -520,43 +530,52 @@ void testExponentialHistogramWithTimer() { registryWithExponentialHistogram.publish(); timer.record(Duration.ofMillis(10000)); - Metric metric = writeToMetric(timer); - assertThat(metric.getExponentialHistogram().getDataPointsCount()).isPositive(); - ExponentialHistogramDataPoint exponentialHistogramDataPoint = metric.getExponentialHistogram().getDataPoints(0); - assertExponentialHistogram(metric, 2, 1100, 1000.0, 0, 5); - ExponentialHistogramDataPoint.Buckets buckets = exponentialHistogramDataPoint.getPositive(); - assertThat(buckets.getOffset()).isEqualTo(212); - assertThat(buckets.getBucketCountsCount()).isEqualTo(107); - assertThat(buckets.getBucketCountsList().get(0)).isEqualTo(1); - assertThat(buckets.getBucketCountsList().get(106)).isEqualTo(1); - assertThat(buckets.getBucketCountsList()).filteredOn(v -> v == 0).hasSize(105); + List metrics = writeToMetrics(timer); + assertThat(metrics).filteredOn(Metric::hasExponentialHistogram).singleElement().satisfies(metric -> { + assertThat(metric.getExponentialHistogram().getDataPointsCount()).isPositive(); + ExponentialHistogramDataPoint exponentialHistogramDataPoint = metric.getExponentialHistogram() + .getDataPoints(0); + assertExponentialHistogram(metric, 2, 1100, 1000.0, 0, 5); + ExponentialHistogramDataPoint.Buckets buckets = exponentialHistogramDataPoint.getPositive(); + assertThat(buckets.getOffset()).isEqualTo(212); + assertThat(buckets.getBucketCountsCount()).isEqualTo(107); + assertThat(buckets.getBucketCountsList().get(0)).isEqualTo(1); + assertThat(buckets.getBucketCountsList().get(106)).isEqualTo(1); + assertThat(buckets.getBucketCountsList()).filteredOn(v -> v == 0).hasSize(105); + }); clock.add(exponentialHistogramOtlpConfig().step()); - metric = writeToMetric(timer); - exponentialHistogramDataPoint = metric.getExponentialHistogram().getDataPoints(0); - - // Note the difference here, if it cumulative we had gone to a lower scale to - // accommodate 1, 100, 1000, - // 10000 but since the first 3 values are reset after the step. We will still be - // able to record 10000 in the - // same scale. - assertExponentialHistogram(metric, 1, 10000, 10000.0, 0, 5); - buckets = exponentialHistogramDataPoint.getPositive(); - assertThat(buckets.getOffset()).isEqualTo(425); - assertThat(buckets.getBucketCountsCount()).isEqualTo(1); + metrics = writeToMetrics(timer); + assertThat(metrics).filteredOn(Metric::hasExponentialHistogram).singleElement().satisfies(metric -> { + ExponentialHistogramDataPoint exponentialHistogramDataPoint = metric.getExponentialHistogram() + .getDataPoints(0); + // Note the difference here, if it cumulative we had gone to a lower scale to + // accommodate 1, 100, 1000, + // 10000 but since the first 3 values are reset after the step. We will still + // be + // able to record 10000 in the + // same scale. + assertExponentialHistogram(metric, 1, 10000, 10000.0, 0, 5); + ExponentialHistogramDataPoint.Buckets buckets = exponentialHistogramDataPoint.getPositive(); + assertThat(buckets.getOffset()).isEqualTo(425); + assertThat(buckets.getBucketCountsCount()).isEqualTo(1); + }); timer.record(Duration.ofMillis(10001)); clock.add(exponentialHistogramOtlpConfig().step()); - metric = writeToMetric(timer); - exponentialHistogramDataPoint = metric.getExponentialHistogram().getDataPoints(0); - - // Since, the range of recorded values in the last step is low, the histogram - // would have been rescaled to Max - // scale. - assertExponentialHistogram(metric, 1, 10001, 10001.0, 0, 20); - buckets = exponentialHistogramDataPoint.getPositive(); - assertThat(buckets.getOffset()).isEqualTo(13933327); - assertThat(buckets.getBucketCountsCount()).isEqualTo(1); + metrics = writeToMetrics(timer); + assertThat(metrics).filteredOn(Metric::hasExponentialHistogram).singleElement().satisfies(metric -> { + ExponentialHistogramDataPoint exponentialHistogramDataPoint = metric.getExponentialHistogram() + .getDataPoints(0); + + // Since, the range of recorded values in the last step is low, the histogram + // would have been rescaled to Max + // scale. + assertExponentialHistogram(metric, 1, 10001, 10001.0, 0, 20); + ExponentialHistogramDataPoint.Buckets buckets = exponentialHistogramDataPoint.getPositive(); + assertThat(buckets.getOffset()).isEqualTo(13933327); + assertThat(buckets.getBucketCountsCount()).isEqualTo(1); + }); } @Test @@ -573,43 +592,53 @@ void testExponentialHistogramDs() { registryWithExponentialHistogram.publish(); ds.record(10000); - Metric metric = writeToMetric(ds); - assertThat(metric.getExponentialHistogram().getDataPointsCount()).isPositive(); - ExponentialHistogramDataPoint exponentialHistogramDataPoint = metric.getExponentialHistogram().getDataPoints(0); - assertExponentialHistogram(metric, 2, 1100, 1000.0, 0, 5); - ExponentialHistogramDataPoint.Buckets buckets = exponentialHistogramDataPoint.getPositive(); - assertThat(buckets.getOffset()).isEqualTo(212); - assertThat(buckets.getBucketCountsCount()).isEqualTo(107); - assertThat(buckets.getBucketCountsList().get(0)).isEqualTo(1); - assertThat(buckets.getBucketCountsList().get(106)).isEqualTo(1); - assertThat(buckets.getBucketCountsList()).filteredOn(v -> v == 0).hasSize(105); + List metrics = writeToMetrics(ds); + assertThat(metrics).filteredOn(Metric::hasExponentialHistogram).singleElement().satisfies(metric -> { + assertThat(metric.getExponentialHistogram().getDataPointsCount()).isPositive(); + ExponentialHistogramDataPoint exponentialHistogramDataPoint = metric.getExponentialHistogram() + .getDataPoints(0); + assertExponentialHistogram(metric, 2, 1100, 1000.0, 0, 5); + ExponentialHistogramDataPoint.Buckets buckets = exponentialHistogramDataPoint.getPositive(); + assertThat(buckets.getOffset()).isEqualTo(212); + assertThat(buckets.getBucketCountsCount()).isEqualTo(107); + assertThat(buckets.getBucketCountsList().get(0)).isEqualTo(1); + assertThat(buckets.getBucketCountsList().get(106)).isEqualTo(1); + assertThat(buckets.getBucketCountsList()).filteredOn(v -> v == 0).hasSize(105); + }); clock.add(exponentialHistogramOtlpConfig().step()); - metric = writeToMetric(ds); - exponentialHistogramDataPoint = metric.getExponentialHistogram().getDataPoints(0); - - // Mote the difference here, if it cumulative we had gone to a lower scale to - // accommodate 1, 100, 1000, - // 10000 but since the first 3 values are reset after the step. We will still be - // able to record 10000 in the - // same scale. - assertExponentialHistogram(metric, 1, 10000, 10000.0, 0, 5); - buckets = exponentialHistogramDataPoint.getPositive(); - assertThat(buckets.getOffset()).isEqualTo(425); - assertThat(buckets.getBucketCountsCount()).isEqualTo(1); - + metrics = writeToMetrics(ds); + assertThat(metrics).filteredOn(Metric::hasExponentialHistogram).singleElement().satisfies(metric -> { + ExponentialHistogramDataPoint exponentialHistogramDataPoint = metric.getExponentialHistogram() + .getDataPoints(0); + + // Mote the difference here, if it cumulative we had gone to a lower scale to + // accommodate 1, 100, 1000, + // 10000 but since the first 3 values are reset after the step. We will still + // be + // able to record 10000 in the + // same scale. + assertExponentialHistogram(metric, 1, 10000, 10000.0, 0, 5); + ExponentialHistogramDataPoint.Buckets buckets = exponentialHistogramDataPoint.getPositive(); + assertThat(buckets.getOffset()).isEqualTo(425); + assertThat(buckets.getBucketCountsCount()).isEqualTo(1); + }); ds.record(10001); clock.add(exponentialHistogramOtlpConfig().step()); - metric = writeToMetric(ds); - exponentialHistogramDataPoint = metric.getExponentialHistogram().getDataPoints(0); - - // Since, the range of recorded values in the last step is low, the histogram - // would have been rescaled to Max - // scale. - assertExponentialHistogram(metric, 1, 10001, 10001.0, 0, 20); - buckets = exponentialHistogramDataPoint.getPositive(); - assertThat(buckets.getOffset()).isEqualTo(13933327); - assertThat(buckets.getBucketCountsCount()).isEqualTo(1); + metrics = writeToMetrics(ds); + assertThat(metrics).filteredOn(Metric::hasExponentialHistogram).singleElement().satisfies(metric -> { + ExponentialHistogramDataPoint exponentialHistogramDataPoint = metric.getExponentialHistogram() + .getDataPoints(0); + + // Since, the range of recorded values in the last step is low, the histogram + // would have been rescaled to Max + // scale. + assertExponentialHistogram(metric, 1, 10001, 10001.0, 0, 20); + ExponentialHistogramDataPoint.Buckets buckets = exponentialHistogramDataPoint.getPositive(); + assertThat(buckets.getOffset()).isEqualTo(13933327); + assertThat(buckets.getBucketCountsCount()).isEqualTo(1); + }); + } @Issue("#3773") diff --git a/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpMeterRegistryTest.java b/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpMeterRegistryTest.java index 1999c53cdb..eff481354a 100644 --- a/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpMeterRegistryTest.java +++ b/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpMeterRegistryTest.java @@ -31,6 +31,7 @@ import java.time.Duration; import java.util.*; import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; import java.util.stream.IntStream; import static io.micrometer.registry.otlp.HistogramFlavor.BASE2_EXPONENTIAL_BUCKET_HISTOGRAM; @@ -177,14 +178,26 @@ void distributionWithPercentileShouldWriteSummary() { .tags(Tags.of(meterTag)) .publishPercentiles(0.5, 0.9); - assertThat(writeToMetric(timer.register(registry)).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.SUMMARY.getNumber()); - assertThat(writeToMetric(ds.register(registry)).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.SUMMARY.getNumber()); - assertThat(writeToMetric(timer.register(registryWithExponentialHistogram)).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.SUMMARY.getNumber()); - assertThat(writeToMetric(ds.register(registryWithExponentialHistogram)).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.SUMMARY.getNumber()); + assertThat(writeToMetrics(timer.register(registry))).filteredOn(Metric::hasSummary) + .singleElement() + .satisfies(summary -> { + assertThat(summary.getDataCase().getNumber()).isEqualTo(Metric.DataCase.SUMMARY.getNumber()); + }); + assertThat(writeToMetrics(ds.register(registry))).filteredOn(Metric::hasSummary) + .singleElement() + .satisfies(summary -> { + assertThat(summary.getDataCase().getNumber()).isEqualTo(Metric.DataCase.SUMMARY.getNumber()); + }); + assertThat(writeToMetrics(timer.register(registryWithExponentialHistogram))).filteredOn(Metric::hasSummary) + .singleElement() + .satisfies(summary -> { + assertThat(summary.getDataCase().getNumber()).isEqualTo(Metric.DataCase.SUMMARY.getNumber()); + }); + assertThat(writeToMetrics(ds.register(registryWithExponentialHistogram))).filteredOn(Metric::hasSummary) + .singleElement() + .satisfies(summary -> { + assertThat(summary.getDataCase().getNumber()).isEqualTo(Metric.DataCase.SUMMARY.getNumber()); + }); } @Test @@ -199,14 +212,30 @@ void distributionWithPercentileHistogramShouldWriteHistogramOrExponentialHistogr .tags(Tags.of(meterTag)) .publishPercentileHistogram(); - assertThat(writeToMetric(timer.register(registry)).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.HISTOGRAM.getNumber()); - assertThat(writeToMetric(ds.register(registry)).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.HISTOGRAM.getNumber()); - assertThat(writeToMetric(timer.register(registryWithExponentialHistogram)).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber()); - assertThat(writeToMetric(ds.register(registryWithExponentialHistogram)).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber()); + assertThat(writeToMetrics(timer.register(registry))).filteredOn(Metric::hasHistogram) + .singleElement() + .satisfies(metric -> { + assertThat(metric.getDataCase().getNumber()).isEqualTo(Metric.DataCase.HISTOGRAM.getNumber()); + }); + assertThat(writeToMetrics(ds.register(registry))).filteredOn(Metric::hasHistogram) + .singleElement() + .satisfies(metric -> { + assertThat(metric.getDataCase().getNumber()).isEqualTo(Metric.DataCase.HISTOGRAM.getNumber()); + }); + assertThat(writeToMetrics(timer.register(registryWithExponentialHistogram))) + .filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(metric -> { + assertThat(metric.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber()); + }); + assertThat(writeToMetrics(ds.register(registryWithExponentialHistogram))) + .filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(metric -> { + assertThat(metric.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber()); + }); } @Test @@ -224,11 +253,15 @@ void multipleMetricsWithSameMetaDataShouldBeSingleMetric() { Timer.builder("test.timer").description("description").tags(secondTag).register(registry); List metrics = writeAllMeters(); - assertThat(metrics).hasSize(3); + assertThat(metrics).hasSize(4); - assertThat(metrics).filteredOn(Metric::hasGauge).singleElement().satisfies(metric -> { + assertThat(metrics).filteredOn(Metric::hasGauge).hasSize(2).satisfiesExactlyInAnyOrder(metric -> { + assertThat(metric.getDescription()).isEqualTo("description"); + assertThat(metric.getGauge().getDataPointsCount()).isEqualTo(2); + }, metric -> { assertThat(metric.getDescription()).isEqualTo("description"); assertThat(metric.getGauge().getDataPointsCount()).isEqualTo(2); + assertThat(metric.getUnit()).isEqualTo("milliseconds"); }); assertThat(metrics).filteredOn(Metric::hasSum).singleElement().satisfies(metric -> { @@ -263,10 +296,12 @@ void metricsWithDifferentMetadataShouldBeMultipleMetrics() { Timer.builder("test.timer").description(description2).tags(secondTag).register(registry); List metrics = writeAllMeters(); - assertThat(metrics).hasSize(6); + assertThat(metrics).hasSize(8); assertThat(metrics).filteredOn(Metric::hasGauge) - .hasSize(2) + .hasSize(4) .satisfiesExactlyInAnyOrder(metric -> assertThat(metric.getDescription()).isEqualTo(description1), + metric -> assertThat(metric.getDescription()).isEqualTo(description2), + metric -> assertThat(metric.getDescription()).isEqualTo(description1), metric -> assertThat(metric.getDescription()).isEqualTo(description2)); assertThat(metrics).filteredOn(Metric::hasSum) @@ -294,14 +329,24 @@ void distributionWithPercentileAndHistogramShouldWriteHistogramOrExponentialHist .publishPercentiles(0.5, 0.9) .publishPercentileHistogram(); - assertThat(writeToMetric(timer.register(registry)).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.HISTOGRAM.getNumber()); - assertThat(writeToMetric(ds.register(registry)).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.HISTOGRAM.getNumber()); - assertThat(writeToMetric(timer.register(registryWithExponentialHistogram)).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber()); - assertThat(writeToMetric(ds.register(registryWithExponentialHistogram)).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber()); + assertThat(writeToMetrics(timer.register(registry))).filteredOn(Metric::hasHistogram) + .singleElement() + .satisfies(metric -> assertThat(metric.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.HISTOGRAM.getNumber())); + assertThat(writeToMetrics(ds.register(registry))).filteredOn(Metric::hasHistogram) + .singleElement() + .satisfies(metric -> assertThat(metric.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.HISTOGRAM.getNumber())); + assertThat(writeToMetrics(timer.register(registryWithExponentialHistogram))) + .filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(metric -> assertThat(metric.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber())); + assertThat(writeToMetrics(ds.register(registryWithExponentialHistogram))) + .filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(metric -> assertThat(metric.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber())); } @Test @@ -315,14 +360,20 @@ void distributionWithSLOShouldWriteHistogramDataPoint() { .tags(Tags.of(meterTag)) .serviceLevelObjectives(1.0); - assertThat(writeToMetric(timer.register(registry)).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.HISTOGRAM.getNumber()); - assertThat(writeToMetric(ds.register(registry)).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.HISTOGRAM.getNumber()); - assertThat(writeToMetric(timer.register(registryWithExponentialHistogram)).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.HISTOGRAM.getNumber()); - assertThat(writeToMetric(ds.register(registryWithExponentialHistogram)).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.HISTOGRAM.getNumber()); + assertThat(writeToMetrics(ds.register(registry))).filteredOn(Metric::hasHistogram) + .singleElement() + .satisfies(metric -> assertThat(metric.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.HISTOGRAM.getNumber())); + assertThat(writeToMetrics(timer.register(registryWithExponentialHistogram))).filteredOn(Metric::hasHistogram) + .singleElement() + .satisfies(metric -> { + assertThat(metric.getDataCase().getNumber()).isEqualTo(Metric.DataCase.HISTOGRAM.getNumber()); + }); + assertThat(writeToMetrics(ds.register(registryWithExponentialHistogram))).filteredOn(Metric::hasHistogram) + .singleElement() + .satisfies(metric -> { + assertThat(metric.getDataCase().getNumber()).isEqualTo(Metric.DataCase.HISTOGRAM.getNumber()); + }); } @Test @@ -342,16 +393,27 @@ void testZeroCountForExponentialHistogram() { clock.add(exponentialHistogramOtlpConfig().step()); - ExponentialHistogramDataPoint dataPoint = writeToMetric(timerWithZero1ms).getExponentialHistogram() - .getDataPoints(0); - assertThat(dataPoint.getZeroCount()).isEqualTo(1); - assertThat(dataPoint.getCount()).isEqualTo(2); - assertThat(dataPoint.getPositive().getBucketCountsCount()).isEqualTo(1); + assertThat(writeToMetrics(timerWithZero1ms)).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(exponentialHistogram -> { + ExponentialHistogramDataPoint dataPoint = exponentialHistogram.getExponentialHistogram() + .getDataPoints(0); + assertThat(dataPoint.getZeroCount()).isEqualTo(1); + assertThat(dataPoint.getCount()).isEqualTo(2); + assertThat(dataPoint.getPositive().getBucketCountsCount()).isEqualTo(1); + assertThat(exponentialHistogram.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber()); + }); - dataPoint = writeToMetric(timerWithZero1ns).getExponentialHistogram().getDataPoints(0); - assertThat(dataPoint.getZeroCount()).isZero(); - assertThat(dataPoint.getCount()).isEqualTo(2); - assertThat(dataPoint.getPositive().getBucketCountsCount()).isGreaterThan(1); + assertThat(writeToMetrics(timerWithZero1ns)).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(exponentialHistogram -> { + ExponentialHistogramDataPoint dataPoint = exponentialHistogram.getExponentialHistogram() + .getDataPoints(0); + assertThat(dataPoint.getZeroCount()).isZero(); + assertThat(dataPoint.getCount()).isEqualTo(2); + assertThat(dataPoint.getPositive().getBucketCountsCount()).isGreaterThan(1); + }); } @Test @@ -366,20 +428,25 @@ void timerShouldRecordInBaseUnitForExponentialHistogram() { timer.record(Duration.ofSeconds(1)); // 1000 Milliseconds clock.add(exponentialHistogramOtlpConfig().step()); - - Metric metric = writeToMetric(timer); - ExponentialHistogramDataPoint dataPoint = metric.getExponentialHistogram().getDataPoints(0); - - assertThat(dataPoint.getCount()).isEqualTo(3); - assertThat(dataPoint.getSum()).isEqualTo(1001.001); - - ExponentialHistogramDataPoint.Buckets buckets = dataPoint.getPositive(); - assertThat(buckets.getOffset()).isEqualTo(-80); - assertThat(buckets.getBucketCountsCount()).isEqualTo(160); - assertThat(buckets.getBucketCountsList().get(0)).isEqualTo(1); - assertThat(buckets.getBucketCountsList().get(79)).isEqualTo(1); - assertThat(buckets.getBucketCountsList().get(159)).isEqualTo(1); - assertThat(buckets.getBucketCountsList()).filteredOn(v -> v == 0).hasSize(157); + List metrics = writeToMetrics(timer); + assertThat(metrics).hasSize(2); + assertThat(metrics).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(exponentialHistogram -> { + ExponentialHistogramDataPoint dataPoint = exponentialHistogram.getExponentialHistogram() + .getDataPoints(0); + + assertThat(dataPoint.getCount()).isEqualTo(3); + assertThat(dataPoint.getSum()).isEqualTo(1001.001); + + ExponentialHistogramDataPoint.Buckets buckets = dataPoint.getPositive(); + assertThat(buckets.getOffset()).isEqualTo(-80); + assertThat(buckets.getBucketCountsCount()).isEqualTo(160); + assertThat(buckets.getBucketCountsList().get(0)).isEqualTo(1); + assertThat(buckets.getBucketCountsList().get(79)).isEqualTo(1); + assertThat(buckets.getBucketCountsList().get(159)).isEqualTo(1); + assertThat(buckets.getBucketCountsList()).filteredOn(v -> v == 0).hasSize(157); + }); } @Test @@ -425,14 +492,21 @@ public AggregationTemporality aggregationTemporality() { OtlpMeterRegistry meterRegistry = OtlpMeterRegistry.builder(config).clock(clock).build(); Timer timer = Timer.builder("test.timer").publishPercentileHistogram().register(meterRegistry); - assertThat(writeToMetric(timer).getDataCase().getNumber()).isEqualTo(Metric.DataCase.HISTOGRAM.getNumber()); + + assertThat(writeToMetrics(timer)).filteredOn(Metric::hasHistogram) + .singleElement() + .satisfies(metric -> assertThat(metric.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.HISTOGRAM.getNumber())); meterRegistry.clear(); DistributionSummary ds = DistributionSummary.builder("test.ds") .publishPercentileHistogram() .register(meterRegistry); - assertThat(writeToMetric(ds).getDataCase().getNumber()).isEqualTo(Metric.DataCase.HISTOGRAM.getNumber()); + assertThat(writeToMetrics(ds)).filteredOn(Metric::hasHistogram) + .singleElement() + .satisfies(metric -> assertThat(metric.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.HISTOGRAM.getNumber())); } @Test @@ -455,16 +529,26 @@ public HistogramFlavor histogramFlavor() { }; OtlpMeterRegistry meterRegistry = OtlpMeterRegistry.builder(config).clock(clock).build(); Timer timer = Timer.builder("test.timer").publishPercentileHistogram().register(meterRegistry); - assertThat(writeToMetric(timer).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber()); + + assertThat(writeToMetrics(timer)).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(exponentialHistogram -> { + assertThat(exponentialHistogram.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber()); + }); meterRegistry.clear(); DistributionSummary ds = DistributionSummary.builder("test.ds") .publishPercentileHistogram() .register(meterRegistry); - assertThat(writeToMetric(ds).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber()); + + assertThat(writeToMetrics(ds)).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(exponentialHistogram -> { + assertThat(exponentialHistogram.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber()); + }); } @Test @@ -497,11 +581,18 @@ public Map histogramFlavorPerMeter() { Timer expo = Timer.builder("expo").publishPercentileHistogram().register(meterRegistry); Timer expoOther = Timer.builder("expo.other").publishPercentileHistogram().register(meterRegistry); Timer other = Timer.builder("other").publishPercentileHistogram().register(meterRegistry); - assertThat(writeToMetric(expo).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber()); - assertThat(writeToMetric(expoOther).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber()); - assertThat(writeToMetric(other).getDataCase().getNumber()).isEqualTo(Metric.DataCase.HISTOGRAM.getNumber()); + assertThat(writeToMetrics(expo)).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(metric -> assertThat(metric.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber())); + assertThat(writeToMetrics(expoOther)).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(metric -> assertThat(metric.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber())); + assertThat(writeToMetrics(other)).filteredOn(Metric::hasHistogram) + .singleElement() + .satisfies(metric -> assertThat(metric.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.HISTOGRAM.getNumber())); meterRegistry.clear(); @@ -514,11 +605,18 @@ public Map histogramFlavorPerMeter() { DistributionSummary other2 = DistributionSummary.builder("other") .publishPercentileHistogram() .register(meterRegistry); - assertThat(writeToMetric(expo2).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber()); - assertThat(writeToMetric(expoOther2).getDataCase().getNumber()) - .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber()); - assertThat(writeToMetric(other2).getDataCase().getNumber()).isEqualTo(Metric.DataCase.HISTOGRAM.getNumber()); + assertThat(writeToMetrics(expo2)).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(metric -> assertThat(metric.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber())); + assertThat(writeToMetrics(expoOther2)).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(metric -> assertThat(metric.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.EXPONENTIAL_HISTOGRAM.getNumber())); + assertThat(writeToMetrics(other2)).filteredOn(Metric::hasHistogram) + .singleElement() + .satisfies(metric -> assertThat(metric.getDataCase().getNumber()) + .isEqualTo(Metric.DataCase.HISTOGRAM.getNumber())); } @Test @@ -550,8 +648,14 @@ public int maxBucketCount() { clock.add(config.step()); - assertThat(writeToMetric(timer).getExponentialHistogram().getDataPoints(0).getPositive().getBucketCountsList()) - .hasSize(56); + assertThat(writeToMetrics(timer)).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(exponentialHistogram -> { + assertThat(exponentialHistogram.getExponentialHistogram() + .getDataPoints(0) + .getPositive() + .getBucketCountsList()).hasSize(56); + }); meterRegistry.clear(); @@ -562,8 +666,13 @@ public int maxBucketCount() { clock.add(config.step()); - assertThat(writeToMetric(ds).getExponentialHistogram().getDataPoints(0).getPositive().getBucketCountsList()) - .hasSize(56); + assertThat(writeToMetrics(ds)).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(exponentialHistogram -> { + ExponentialHistogramDataPoint dataPoint = exponentialHistogram.getExponentialHistogram() + .getDataPoints(0); + assertThat(dataPoint.getPositive().getBucketCountsList()).hasSize(56); + }); } @Test @@ -608,16 +717,28 @@ public Map maxBucketsPerMeter() { .forEach(t -> IntStream.range(1, 111).forEach(i -> t.record(i, TimeUnit.MILLISECONDS))); clock.add(config.step()); - assertThat(writeToMetric(lowVariation).getExponentialHistogram() - .getDataPoints(0) - .getPositive() - .getBucketCountsList()).hasSize(15); - assertThat(writeToMetric(lowVariationOther).getExponentialHistogram() - .getDataPoints(0) - .getPositive() - .getBucketCountsList()).hasSize(15); - assertThat(writeToMetric(other).getExponentialHistogram().getDataPoints(0).getPositive().getBucketCountsList()) - .hasSize(56); + assertThat(writeToMetrics(lowVariation)).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(exponentialHistogram -> { + ExponentialHistogramDataPoint dataPoint = exponentialHistogram.getExponentialHistogram() + .getDataPoints(0); + assertThat(dataPoint.getPositive().getBucketCountsList()).hasSize(15); + }); + assertThat(writeToMetrics(lowVariationOther)).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(exponentialHistogram -> { + ExponentialHistogramDataPoint dataPoint = exponentialHistogram.getExponentialHistogram() + .getDataPoints(0); + assertThat(dataPoint.getPositive().getBucketCountsList()).hasSize(15); + }); + + assertThat(writeToMetrics(other)).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(exponentialHistogram -> { + ExponentialHistogramDataPoint dataPoint = exponentialHistogram.getExponentialHistogram() + .getDataPoints(0); + assertThat(dataPoint.getPositive().getBucketCountsList()).hasSize(56); + }); meterRegistry.clear(); @@ -634,16 +755,27 @@ public Map maxBucketsPerMeter() { List.of(lowVariation2, lowVariationOther2, other2).forEach(t -> IntStream.range(1, 111).forEach(t::record)); clock.add(config.step()); - assertThat(writeToMetric(lowVariation2).getExponentialHistogram() - .getDataPoints(0) - .getPositive() - .getBucketCountsList()).hasSize(15); - assertThat(writeToMetric(lowVariationOther2).getExponentialHistogram() - .getDataPoints(0) - .getPositive() - .getBucketCountsList()).hasSize(15); - assertThat(writeToMetric(other2).getExponentialHistogram().getDataPoints(0).getPositive().getBucketCountsList()) - .hasSize(56); + assertThat(writeToMetrics(lowVariation2)).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(exponentialHistogram -> { + ExponentialHistogramDataPoint dataPoint = exponentialHistogram.getExponentialHistogram() + .getDataPoints(0); + assertThat(dataPoint.getPositive().getBucketCountsList()).hasSize(15); + }); + assertThat(writeToMetrics(lowVariationOther2)).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(exponentialHistogram -> { + ExponentialHistogramDataPoint dataPoint = exponentialHistogram.getExponentialHistogram() + .getDataPoints(0); + assertThat(dataPoint.getPositive().getBucketCountsList()).hasSize(15); + }); + assertThat(writeToMetrics(other2)).filteredOn(Metric::hasExponentialHistogram) + .singleElement() + .satisfies(exponentialHistogram -> { + ExponentialHistogramDataPoint dataPoint = exponentialHistogram.getExponentialHistogram() + .getDataPoints(0); + assertThat(dataPoint.getPositive().getBucketCountsList()).hasSize(56); + }); } @Test @@ -673,12 +805,16 @@ private Meter.Id createIdWithName(String name) { } protected Metric writeToMetric(Meter meter) { + return writeToMetrics(meter).get(0); + } + + protected List writeToMetrics(Meter meter) { OtlpMetricConverter otlpMetricConverter = new OtlpMetricConverter(clock, otlpConfig().step(), registry.getBaseTimeUnit(), otlpConfig().aggregationTemporality(), registry.config().namingConvention()); otlpMetricConverter.addMeter(meter); - List metrics = otlpMetricConverter.getAllMetrics(); - return metrics.get(0); + return otlpMetricConverter.getAllMetrics(); + } protected List writeAllMeters() { @@ -693,29 +829,39 @@ protected void stepOverNStep(int numStepsToSkip) { clock.addSeconds(otlpConfig().step().getSeconds() * numStepsToSkip); } - protected void assertHistogram(Metric metric, long startTime, long endTime, String unit, long count, double sum, - double max) { - assertThat(metric.getHistogram().getAggregationTemporality()) - .isEqualTo(AggregationTemporality.toOtlpAggregationTemporality(otlpConfig().aggregationTemporality())); + protected void assertHistogram(List metrics, long startTime, long endTime, String unit, long count, + double sum, double max, Consumer consumer) { + assertThat(metrics).filteredOn(Metric::hasHistogram).singleElement().satisfies(metric -> { + assertThat(metric.getHistogram().getAggregationTemporality()) + .isEqualTo(AggregationTemporality.toOtlpAggregationTemporality(otlpConfig().aggregationTemporality())); + HistogramDataPoint histogram = metric.getHistogram().getDataPoints(0); + assertMetricMetadata(metric, Optional.of(unit)); + assertThat(histogram.getStartTimeUnixNano()).isEqualTo(startTime); + assertThat(histogram.getTimeUnixNano()).isEqualTo(endTime); + assertThat(histogram.getCount()).isEqualTo(count); + assertThat(histogram.getSum()).isEqualTo(sum); + assertThat(histogram.getAttributesCount()).isEqualTo(1); + assertThat(histogram.getAttributes(0).getKey()).isEqualTo(meterTag.getKey()); + assertThat(histogram.getAttributes(0).getValue().getStringValue()).isEqualTo(meterTag.getValue()); + + if (histogram.getExplicitBoundsCount() > 0) { + assertThat(histogram.getBucketCountsList().stream().mapToLong(Long::longValue).sum()).isEqualTo(count); + assertThat(histogram.getExplicitBoundsCount() + 1).isEqualTo(histogram.getBucketCountsCount()); + } + + if (otlpConfig().aggregationTemporality() == AggregationTemporality.DELTA) { + assertThat(histogram.getMax()).isEqualTo(max); + } + + if (consumer != null) { + consumer.accept(histogram); + } + }); + } - HistogramDataPoint histogram = metric.getHistogram().getDataPoints(0); - assertMetricMetadata(metric, Optional.of(unit)); - assertThat(histogram.getStartTimeUnixNano()).isEqualTo(startTime); - assertThat(histogram.getTimeUnixNano()).isEqualTo(endTime); - assertThat(histogram.getCount()).isEqualTo(count); - assertThat(histogram.getSum()).isEqualTo(sum); - assertThat(histogram.getAttributesCount()).isEqualTo(1); - assertThat(histogram.getAttributes(0).getKey()).isEqualTo(meterTag.getKey()); - assertThat(histogram.getAttributes(0).getValue().getStringValue()).isEqualTo(meterTag.getValue()); - - if (histogram.getExplicitBoundsCount() > 0) { - assertThat(histogram.getBucketCountsList().stream().mapToLong(Long::longValue).sum()).isEqualTo(count); - assertThat(histogram.getExplicitBoundsCount() + 1).isEqualTo(histogram.getBucketCountsCount()); - } - - if (otlpConfig().aggregationTemporality() == AggregationTemporality.DELTA) { - assertThat(histogram.getMax()).isEqualTo(max); - } + protected void assertHistogram(List metrics, long startTime, long endTime, String unit, long count, + double sum, double max) { + assertHistogram(metrics, startTime, endTime, unit, count, sum, max, null); } protected void assertSum(Metric metric, long startTime, long endTime, double expectedValue) { diff --git a/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpMetricConverterTest.java b/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpMetricConverterTest.java index 39ffa98f94..cd78dfaa3b 100644 --- a/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpMetricConverterTest.java +++ b/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpMetricConverterTest.java @@ -129,7 +129,7 @@ void timerWithSummaryAndHistogramShouldBeMultipleMetrics() { otlpMetricConverter.addMeters(otlpMeterRegistry.getMeters()); List metrics = otlpMetricConverter.getAllMetrics(); - assertThat(metrics).hasSize(2); + assertThat(metrics).hasSize(3); assertThat(metrics).filteredOn(Metric::hasSummary) .singleElement() @@ -154,6 +154,20 @@ void timerWithSummaryAndHistogramShouldBeMultipleMetrics() { assertThat(histogramDataPoint.getExplicitBoundsCount()).isEqualTo(1); assertThat(histogramDataPoint.getBucketCountsCount()).isEqualTo(2); })); + + assertThat(metrics).filteredOn(Metric::hasGauge) + .singleElement() + .satisfies(metric -> assertThat(metric.getGauge().getDataPointsList()).hasSize(3) + .satisfiesExactlyInAnyOrder(gaugeDataPoint -> { + assertThat(gaugeDataPoint.getAttributesCount()).isEqualTo(1); + assertThat(gaugeDataPoint.getAttributes(0).getValue().getStringValue()).isEqualTo("vanilla"); + }, gaugeDataPoint -> { + assertThat(gaugeDataPoint.getAttributesCount()).isEqualTo(1); + assertThat(gaugeDataPoint.getAttributes(0).getValue().getStringValue()).isEqualTo("histogram"); + }, gaugeDataPoint -> { + assertThat(gaugeDataPoint.getAttributesCount()).isEqualTo(1); + assertThat(gaugeDataPoint.getAttributes(0).getValue().getStringValue()).isEqualTo("summary"); + })); } @Test @@ -185,10 +199,16 @@ void addMeterWithDistributionSummary() { mockClock.add(STEP); otlpMetricConverter.addMeter(summary); - assertThat(otlpMetricConverter.getAllMetrics()).singleElement() + List metrics = otlpMetricConverter.getAllMetrics(); + assertThat(metrics).hasSize(2); + assertThat(metrics).filteredOn(Metric::hasSummary) + .singleElement() .satisfies(metric -> assertThat(metric.getSummary().getDataPointsList()).singleElement() .satisfies(dataPoint -> assertThat(dataPoint.getQuantileValuesList()).singleElement() .satisfies(valueAtQuantile -> assertThat(valueAtQuantile.getValue()).isEqualTo(5)))); + assertThat(metrics).filteredOn(Metric::hasGauge) + .singleElement() + .satisfies(metric -> assertThat(metric.getGauge().getDataPointsList()).hasSize(1)); } }