diff --git a/instrumentation/micrometer/micrometer-1.5/README.md b/instrumentation/micrometer/micrometer-1.5/README.md
index 1bb868a05f81..e6fe4c15f060 100644
--- a/instrumentation/micrometer/micrometer-1.5/README.md
+++ b/instrumentation/micrometer/micrometer-1.5/README.md
@@ -1,6 +1,7 @@
# Settings for the Micrometer bridge instrumentation
-| System property | Type | Default | Description |
-|---|---|---|---|
-| `otel.instrumentation.micrometer.base-time-unit` | String | `ms` | Set the base time unit for the OpenTelemetry `MeterRegistry` implementation. Valid values
`ns`, `nanoseconds`, `us`, `microseconds`, `ms`, `microseconds`, `s`, `seconds`, `min`, `minutes`, `h`, `hours`, `d`, `days`Valid values
`ns`, `nanoseconds`, `us`, `microseconds`, `ms`, `microseconds`, `s`, `seconds`, `min`, `minutes`, `h`, `hours`, `d`, `days`
Note that this setting does not concern the {@link LongTaskTimer}, as it is not bridged to + * an OpenTelemetry histogram. + * + *
This is disabled by default, set this to {@code true} to enable gauge-based Micrometer + * histograms. + */ + @CanIgnoreReturnValue + public OpenTelemetryMeterRegistryBuilder setMicrometerHistogramGaugesEnabled( + boolean histogramGaugesEnabled) { + this.histogramGaugesEnabled = histogramGaugesEnabled; + return this; + } + /** * Returns a new {@link OpenTelemetryMeterRegistry} with the settings of this {@link * OpenTelemetryMeterRegistryBuilder}. @@ -63,11 +88,16 @@ public MeterRegistry build() { TimeUnit baseTimeUnit = prometheusMode ? TimeUnit.SECONDS : this.baseTimeUnit; NamingConvention namingConvention = prometheusMode ? PrometheusModeNamingConvention.INSTANCE : NamingConvention.identity; + DistributionStatisticConfigModifier modifier = + histogramGaugesEnabled + ? DistributionStatisticConfigModifier.IDENTITY + : DistributionStatisticConfigModifier.DISABLE_HISTOGRAM_GAUGES; return new OpenTelemetryMeterRegistry( clock, baseTimeUnit, namingConvention, + modifier, openTelemetry.getMeterProvider().get(INSTRUMENTATION_NAME)); } } diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryTimer.java b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryTimer.java index 86df5008a8f9..a81531e52d40 100644 --- a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryTimer.java +++ b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryTimer.java @@ -43,10 +43,17 @@ final class OpenTelemetryTimer extends AbstractTimer implements RemovableMeter { NamingConvention namingConvention, Clock clock, DistributionStatisticConfig distributionStatisticConfig, + DistributionStatisticConfigModifier modifier, PauseDetector pauseDetector, TimeUnit baseTimeUnit, Meter otelMeter) { - super(id, clock, distributionStatisticConfig, pauseDetector, TimeUnit.MILLISECONDS, false); + super( + id, + clock, + modifier.modify(distributionStatisticConfig), + pauseDetector, + baseTimeUnit, + false); if (isUsingMicrometerHistograms()) { measurements = new MicrometerHistogramMeasurements(); diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/DistributionSummaryHistogramGaugesTest.java b/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/DistributionSummaryHistogramGaugesTest.java new file mode 100644 index 000000000000..853aa3ffb85a --- /dev/null +++ b/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/DistributionSummaryHistogramGaugesTest.java @@ -0,0 +1,32 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.micrometer.v1_5; + +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; +import org.junit.jupiter.api.extension.RegisterExtension; + +class DistributionSummaryHistogramGaugesTest + extends AbstractDistributionSummaryHistogramGaugesTest { + + @RegisterExtension + static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); + + @RegisterExtension + static final MicrometerTestingExtension micrometerExtension = + new MicrometerTestingExtension(testing) { + @Override + OpenTelemetryMeterRegistryBuilder configureOtelRegistry( + OpenTelemetryMeterRegistryBuilder registry) { + return registry.setMicrometerHistogramGaugesEnabled(true); + } + }; + + @Override + protected InstrumentationExtension testing() { + return testing; + } +} diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/NamingConventionTest.java b/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/NamingConventionTest.java index 0487167ad9d1..2de72631d7cc 100644 --- a/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/NamingConventionTest.java +++ b/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/NamingConventionTest.java @@ -10,7 +10,7 @@ import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; import org.junit.jupiter.api.extension.RegisterExtension; -public class NamingConventionTest extends AbstractNamingConventionTest { +class NamingConventionTest extends AbstractNamingConventionTest { @RegisterExtension static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/TimerHistogramGaugesTest.java b/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/TimerHistogramGaugesTest.java new file mode 100644 index 000000000000..95176d3a3cb3 --- /dev/null +++ b/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/TimerHistogramGaugesTest.java @@ -0,0 +1,31 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.micrometer.v1_5; + +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; +import org.junit.jupiter.api.extension.RegisterExtension; + +class TimerHistogramGaugesTest extends AbstractTimerHistogramGaugesTest { + + @RegisterExtension + static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); + + @RegisterExtension + static final MicrometerTestingExtension micrometerExtension = + new MicrometerTestingExtension(testing) { + @Override + OpenTelemetryMeterRegistryBuilder configureOtelRegistry( + OpenTelemetryMeterRegistryBuilder registry) { + return registry.setMicrometerHistogramGaugesEnabled(true); + } + }; + + @Override + protected InstrumentationExtension testing() { + return testing; + } +} diff --git a/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractDistributionSummaryHistogramGaugesTest.java b/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractDistributionSummaryHistogramGaugesTest.java new file mode 100644 index 000000000000..dbaa2ddbb39a --- /dev/null +++ b/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractDistributionSummaryHistogramGaugesTest.java @@ -0,0 +1,191 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.micrometer.v1_5; + +import static io.opentelemetry.instrumentation.micrometer.v1_5.AbstractCounterTest.INSTRUMENTATION_NAME; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry; + +import io.micrometer.core.instrument.DistributionSummary; +import io.micrometer.core.instrument.Metrics; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public abstract class AbstractDistributionSummaryHistogramGaugesTest { + + protected abstract InstrumentationExtension testing(); + + @BeforeEach + void cleanupMeters() { + Metrics.globalRegistry.forEachMeter(Metrics.globalRegistry::remove); + } + + @Test + void testMicrometerHistogram() { + // given + DistributionSummary summary = + DistributionSummary.builder("testSummary") + .description("This is a test distribution summary") + .baseUnit("things") + .tags("tag", "value") + .serviceLevelObjectives(1, 10, 100, 1000) + .distributionStatisticBufferLength(10) + .register(Metrics.globalRegistry); + + // when + summary.record(0.5); + summary.record(5); + summary.record(50); + summary.record(500); + + // then + testing() + .waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "testSummary", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDescription("This is a test distribution summary") + .hasUnit("things") + .hasHistogramSatisfying( + histogram -> + histogram.hasPointsSatisfying( + points -> + points + .hasSum(555.5) + .hasCount(4) + .hasAttributes(attributeEntry("tag", "value")))))); + testing() + .waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "testSummary.max", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDescription("This is a test distribution summary") + .hasDoubleGaugeSatisfying( + gauge -> + gauge.hasPointsSatisfying( + point -> + point + .hasValue(500) + .hasAttributes(attributeEntry("tag", "value")))))); + testing() + .waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "testSummary.histogram", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDoubleGaugeSatisfying( + gauge -> + gauge.hasPointsSatisfying( + point -> + point + .hasValue(1) + .hasAttributes( + attributeEntry("le", "1"), + attributeEntry("tag", "value")), + point -> + point + .hasValue(2) + .hasAttributes( + attributeEntry("le", "10"), + attributeEntry("tag", "value")), + point -> + point + .hasValue(3) + .hasAttributes( + attributeEntry("le", "100"), + attributeEntry("tag", "value")), + point -> + point + .hasValue(4) + .hasAttributes( + attributeEntry("le", "1000"), + attributeEntry("tag", "value")))))); + } + + @Test + void testMicrometerPercentiles() { + // given + DistributionSummary summary = + DistributionSummary.builder("testSummary") + .description("This is a test distribution summary") + .baseUnit("things") + .tags("tag", "value") + .publishPercentiles(0.5, 0.95, 0.99) + .register(Metrics.globalRegistry); + + // when + summary.record(50); + summary.record(100); + + // then + testing() + .waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "testSummary", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDescription("This is a test distribution summary") + .hasUnit("things") + .hasHistogramSatisfying( + histogram -> + histogram.hasPointsSatisfying( + point -> + point + .hasSum(150) + .hasCount(2) + .hasAttributes(attributeEntry("tag", "value")))))); + testing() + .waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "testSummary.max", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDescription("This is a test distribution summary") + .hasDoubleGaugeSatisfying( + gauge -> + gauge.hasPointsSatisfying( + point -> + point + .hasValue(100) + .hasAttributes(attributeEntry("tag", "value")))))); + testing() + .waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "testSummary.percentile", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDoubleGaugeSatisfying( + gauge -> + gauge.hasPointsSatisfying( + point -> + point.hasAttributes( + attributeEntry("phi", "0.5"), + attributeEntry("tag", "value")), + point -> + point.hasAttributes( + attributeEntry("phi", "0.95"), + attributeEntry("tag", "value")), + point -> + point.hasAttributes( + attributeEntry("phi", "0.99"), + attributeEntry("tag", "value")))))); + } +} diff --git a/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractDistributionSummaryTest.java b/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractDistributionSummaryTest.java index bf64e0d632ee..67589bf55bec 100644 --- a/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractDistributionSummaryTest.java +++ b/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractDistributionSummaryTest.java @@ -12,11 +12,18 @@ import io.micrometer.core.instrument.DistributionSummary; import io.micrometer.core.instrument.Metrics; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.sdk.metrics.internal.aggregator.ExplicitBucketHistogramUtils; +import org.assertj.core.api.AbstractIterableAssert; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public abstract class AbstractDistributionSummaryTest { + static final double[] DEFAULT_BUCKETS = + ExplicitBucketHistogramUtils.DEFAULT_HISTOGRAM_BUCKET_BOUNDARIES.stream() + .mapToDouble(d -> d) + .toArray(); + protected abstract InstrumentationExtension testing(); @BeforeEach @@ -57,7 +64,8 @@ void testMicrometerDistributionSummary() { point .hasSum(7) .hasCount(3) - .hasAttributes(attributeEntry("tag", "value")))))); + .hasAttributes(attributeEntry("tag", "value")) + .hasBucketBoundaries(DEFAULT_BUCKETS))))); testing() .waitAndAssertMetrics( INSTRUMENTATION_NAME, @@ -75,6 +83,11 @@ void testMicrometerDistributionSummary() { .hasValue(4) .hasAttributes(attributeEntry("tag", "value")))))); + // micrometer gauge histogram is not emitted + testing() + .waitAndAssertMetrics( + INSTRUMENTATION_NAME, "testSummary.histogram", AbstractIterableAssert::isEmpty); + // when Metrics.globalRegistry.remove(summary); @@ -98,169 +111,4 @@ void testMicrometerDistributionSummary() { .hasCount(3) .hasAttributes(attributeEntry("tag", "value")))))); } - - @Test - void testMicrometerHistogram() { - // given - DistributionSummary summary = - DistributionSummary.builder("testSummary") - .description("This is a test distribution summary") - .baseUnit("things") - .tags("tag", "value") - .serviceLevelObjectives(1, 10, 100, 1000) - .distributionStatisticBufferLength(10) - .register(Metrics.globalRegistry); - - // when - summary.record(0.5); - summary.record(5); - summary.record(50); - summary.record(500); - - // then - testing() - .waitAndAssertMetrics( - INSTRUMENTATION_NAME, - "testSummary", - metrics -> - metrics.anySatisfy( - metric -> - assertThat(metric) - .hasDescription("This is a test distribution summary") - .hasUnit("things") - .hasHistogramSatisfying( - histogram -> - histogram.hasPointsSatisfying( - points -> - points - .hasSum(555.5) - .hasCount(4) - .hasAttributes(attributeEntry("tag", "value")))))); - testing() - .waitAndAssertMetrics( - INSTRUMENTATION_NAME, - "testSummary.max", - metrics -> - metrics.anySatisfy( - metric -> - assertThat(metric) - .hasDescription("This is a test distribution summary") - .hasDoubleGaugeSatisfying( - gauge -> - gauge.hasPointsSatisfying( - point -> - point - .hasValue(500) - .hasAttributes(attributeEntry("tag", "value")))))); - testing() - .waitAndAssertMetrics( - INSTRUMENTATION_NAME, - "testSummary.histogram", - metrics -> - metrics.anySatisfy( - metric -> - assertThat(metric) - .hasDoubleGaugeSatisfying( - gauge -> - gauge.hasPointsSatisfying( - point -> - point - .hasValue(1) - .hasAttributes( - attributeEntry("le", "1"), - attributeEntry("tag", "value")), - point -> - point - .hasValue(2) - .hasAttributes( - attributeEntry("le", "10"), - attributeEntry("tag", "value")), - point -> - point - .hasValue(3) - .hasAttributes( - attributeEntry("le", "100"), - attributeEntry("tag", "value")), - point -> - point - .hasValue(4) - .hasAttributes( - attributeEntry("le", "1000"), - attributeEntry("tag", "value")))))); - } - - @Test - void testMicrometerPercentiles() { - // given - DistributionSummary summary = - DistributionSummary.builder("testSummary") - .description("This is a test distribution summary") - .baseUnit("things") - .tags("tag", "value") - .publishPercentiles(0.5, 0.95, 0.99) - .register(Metrics.globalRegistry); - - // when - summary.record(50); - summary.record(100); - - // then - testing() - .waitAndAssertMetrics( - INSTRUMENTATION_NAME, - "testSummary", - metrics -> - metrics.anySatisfy( - metric -> - assertThat(metric) - .hasDescription("This is a test distribution summary") - .hasUnit("things") - .hasHistogramSatisfying( - histogram -> - histogram.hasPointsSatisfying( - point -> - point - .hasSum(150) - .hasCount(2) - .hasAttributes(attributeEntry("tag", "value")))))); - testing() - .waitAndAssertMetrics( - INSTRUMENTATION_NAME, - "testSummary.max", - metrics -> - metrics.anySatisfy( - metric -> - assertThat(metric) - .hasDescription("This is a test distribution summary") - .hasDoubleGaugeSatisfying( - gauge -> - gauge.hasPointsSatisfying( - point -> - point - .hasValue(100) - .hasAttributes(attributeEntry("tag", "value")))))); - testing() - .waitAndAssertMetrics( - INSTRUMENTATION_NAME, - "testSummary.percentile", - metrics -> - metrics.anySatisfy( - metric -> - assertThat(metric) - .hasDoubleGaugeSatisfying( - gauge -> - gauge.hasPointsSatisfying( - point -> - point.hasAttributes( - attributeEntry("phi", "0.5"), - attributeEntry("tag", "value")), - point -> - point.hasAttributes( - attributeEntry("phi", "0.95"), - attributeEntry("tag", "value")), - point -> - point.hasAttributes( - attributeEntry("phi", "0.99"), - attributeEntry("tag", "value")))))); - } } diff --git a/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractTimerHistogramGaugesTest.java b/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractTimerHistogramGaugesTest.java new file mode 100644 index 000000000000..7f8ceaf4a173 --- /dev/null +++ b/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractTimerHistogramGaugesTest.java @@ -0,0 +1,190 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.micrometer.v1_5; + +import static io.opentelemetry.instrumentation.micrometer.v1_5.AbstractCounterTest.INSTRUMENTATION_NAME; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry; + +import io.micrometer.core.instrument.Metrics; +import io.micrometer.core.instrument.Timer; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import java.time.Duration; +import java.util.concurrent.TimeUnit; +import org.junit.jupiter.api.Test; + +@SuppressWarnings("PreferJavaTimeOverload") +public abstract class AbstractTimerHistogramGaugesTest { + + protected abstract InstrumentationExtension testing(); + + @Test + void testMicrometerHistogram() { + // given + Timer timer = + Timer.builder("testTimer") + .description("This is a test timer") + .tags("tag", "value") + .serviceLevelObjectives( + Duration.ofSeconds(1), + Duration.ofSeconds(10), + Duration.ofSeconds(100), + Duration.ofSeconds(1000)) + .distributionStatisticBufferLength(10) + .register(Metrics.globalRegistry); + + // when + timer.record(500, TimeUnit.MILLISECONDS); + timer.record(5, TimeUnit.SECONDS); + timer.record(50, TimeUnit.SECONDS); + timer.record(500, TimeUnit.SECONDS); + + // then + testing() + .waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "testTimer", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDescription("This is a test timer") + .hasUnit("ms") + .hasHistogramSatisfying( + histogram -> + histogram.hasPointsSatisfying( + point -> + point + .hasSum(555500) + .hasCount(4) + .hasAttributes(attributeEntry("tag", "value")))))); + testing() + .waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "testTimer.max", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDescription("This is a test timer") + .hasDoubleGaugeSatisfying( + gauge -> + gauge.hasPointsSatisfying( + point -> + point + .hasValue(500000) + .hasAttributes(attributeEntry("tag", "value")))))); + testing() + .waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "testTimer.histogram", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDoubleGaugeSatisfying( + gauge -> + gauge.hasPointsSatisfying( + point -> + point + .hasValue(1) + .hasAttributes( + attributeEntry("le", "1000"), + attributeEntry("tag", "value")), + point -> + point + .hasValue(2) + .hasAttributes( + attributeEntry("le", "10000"), + attributeEntry("tag", "value")), + point -> + point + .hasValue(3) + .hasAttributes( + attributeEntry("le", "100000"), + attributeEntry("tag", "value")), + point -> + point + .hasValue(4) + .hasAttributes( + attributeEntry("le", "1000000"), + attributeEntry("tag", "value")))))); + } + + @Test + void testMicrometerPercentiles() { + // given + Timer timer = + Timer.builder("testTimer") + .description("This is a test timer") + .tags("tag", "value") + .publishPercentiles(0.5, 0.95, 0.99) + .register(Metrics.globalRegistry); + + // when + timer.record(50, TimeUnit.MILLISECONDS); + timer.record(100, TimeUnit.MILLISECONDS); + + // then + testing() + .waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "testTimer", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDescription("This is a test timer") + .hasUnit("ms") + .hasHistogramSatisfying( + histogram -> + histogram.hasPointsSatisfying( + point -> + point + .hasSum(150) + .hasCount(2) + .hasAttributes(attributeEntry("tag", "value")))))); + testing() + .waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "testTimer.max", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDescription("This is a test timer") + .hasDoubleGaugeSatisfying( + gauge -> + gauge.hasPointsSatisfying( + point -> + point + .hasValue(100) + .hasAttributes(attributeEntry("tag", "value")))))); + testing() + .waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "testTimer.percentile", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDoubleGaugeSatisfying( + gauge -> + gauge.hasPointsSatisfying( + point -> + point.hasAttributes( + attributeEntry("phi", "0.5"), + attributeEntry("tag", "value")), + point -> + point.hasAttributes( + attributeEntry("phi", "0.95"), + attributeEntry("tag", "value")), + point -> + point.hasAttributes( + attributeEntry("phi", "0.99"), + attributeEntry("tag", "value")))))); + } +} diff --git a/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractTimerTest.java b/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractTimerTest.java index 84d4b07f142b..b21eb73b4597 100644 --- a/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractTimerTest.java +++ b/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractTimerTest.java @@ -13,7 +13,7 @@ import io.micrometer.core.instrument.Timer; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; -import java.time.Duration; +import io.opentelemetry.sdk.metrics.internal.aggregator.ExplicitBucketHistogramUtils; import java.util.concurrent.TimeUnit; import org.assertj.core.api.AbstractIterableAssert; import org.junit.jupiter.api.Test; @@ -21,6 +21,11 @@ @SuppressWarnings("PreferJavaTimeOverload") public abstract class AbstractTimerTest { + static final double[] DEFAULT_BUCKETS = + ExplicitBucketHistogramUtils.DEFAULT_HISTOGRAM_BUCKET_BOUNDARIES.stream() + .mapToDouble(d -> d) + .toArray(); + protected abstract InstrumentationExtension testing(); @Test @@ -53,7 +58,8 @@ void testTimer() { point .hasSum(42_000) .hasCount(1) - .hasAttributes(attributeEntry("tag", "value")))))); + .hasAttributes(attributeEntry("tag", "value")) + .hasBucketBoundaries(DEFAULT_BUCKETS))))); testing() .waitAndAssertMetrics( INSTRUMENTATION_NAME, @@ -71,6 +77,11 @@ void testTimer() { .hasValue(42_000) .hasAttributes(attributeEntry("tag", "value")))))); + // micrometer gauge histogram is not emitted + testing() + .waitAndAssertMetrics( + INSTRUMENTATION_NAME, "testTimer.histogram", AbstractIterableAssert::isEmpty); + // when Metrics.globalRegistry.remove(timer); testing().clearData(); @@ -123,171 +134,4 @@ void testNanoPrecision() { .hasValue(1.234) .hasAttributes(Attributes.empty()))))); } - - @Test - void testMicrometerHistogram() { - // given - Timer timer = - Timer.builder("testTimer") - .description("This is a test timer") - .tags("tag", "value") - .serviceLevelObjectives( - Duration.ofSeconds(1), - Duration.ofSeconds(10), - Duration.ofSeconds(100), - Duration.ofSeconds(1000)) - .distributionStatisticBufferLength(10) - .register(Metrics.globalRegistry); - - // when - timer.record(500, TimeUnit.MILLISECONDS); - timer.record(5, TimeUnit.SECONDS); - timer.record(50, TimeUnit.SECONDS); - timer.record(500, TimeUnit.SECONDS); - - // then - testing() - .waitAndAssertMetrics( - INSTRUMENTATION_NAME, - "testTimer", - metrics -> - metrics.anySatisfy( - metric -> - assertThat(metric) - .hasDescription("This is a test timer") - .hasUnit("ms") - .hasHistogramSatisfying( - histogram -> - histogram.hasPointsSatisfying( - point -> - point - .hasSum(555500) - .hasCount(4) - .hasAttributes(attributeEntry("tag", "value")))))); - testing() - .waitAndAssertMetrics( - INSTRUMENTATION_NAME, - "testTimer.max", - metrics -> - metrics.anySatisfy( - metric -> - assertThat(metric) - .hasDescription("This is a test timer") - .hasDoubleGaugeSatisfying( - gauge -> - gauge.hasPointsSatisfying( - point -> - point - .hasValue(500000) - .hasAttributes(attributeEntry("tag", "value")))))); - testing() - .waitAndAssertMetrics( - INSTRUMENTATION_NAME, - "testTimer.histogram", - metrics -> - metrics.anySatisfy( - metric -> - assertThat(metric) - .hasDoubleGaugeSatisfying( - gauge -> - gauge.hasPointsSatisfying( - point -> - point - .hasValue(1) - .hasAttributes( - attributeEntry("le", "1000"), - attributeEntry("tag", "value")), - point -> - point - .hasValue(2) - .hasAttributes( - attributeEntry("le", "10000"), - attributeEntry("tag", "value")), - point -> - point - .hasValue(3) - .hasAttributes( - attributeEntry("le", "100000"), - attributeEntry("tag", "value")), - point -> - point - .hasValue(4) - .hasAttributes( - attributeEntry("le", "1000000"), - attributeEntry("tag", "value")))))); - } - - @Test - void testMicrometerPercentiles() { - // given - Timer timer = - Timer.builder("testTimer") - .description("This is a test timer") - .tags("tag", "value") - .publishPercentiles(0.5, 0.95, 0.99) - .register(Metrics.globalRegistry); - - // when - timer.record(50, TimeUnit.MILLISECONDS); - timer.record(100, TimeUnit.MILLISECONDS); - - // then - testing() - .waitAndAssertMetrics( - INSTRUMENTATION_NAME, - "testTimer", - metrics -> - metrics.anySatisfy( - metric -> - assertThat(metric) - .hasDescription("This is a test timer") - .hasUnit("ms") - .hasHistogramSatisfying( - histogram -> - histogram.hasPointsSatisfying( - point -> - point - .hasSum(150) - .hasCount(2) - .hasAttributes(attributeEntry("tag", "value")))))); - testing() - .waitAndAssertMetrics( - INSTRUMENTATION_NAME, - "testTimer.max", - metrics -> - metrics.anySatisfy( - metric -> - assertThat(metric) - .hasDescription("This is a test timer") - .hasDoubleGaugeSatisfying( - gauge -> - gauge.hasPointsSatisfying( - point -> - point - .hasValue(100) - .hasAttributes(attributeEntry("tag", "value")))))); - testing() - .waitAndAssertMetrics( - INSTRUMENTATION_NAME, - "testTimer.percentile", - metrics -> - metrics.anySatisfy( - metric -> - assertThat(metric) - .hasDoubleGaugeSatisfying( - gauge -> - gauge.hasPointsSatisfying( - point -> - point.hasAttributes( - attributeEntry("phi", "0.5"), - attributeEntry("tag", "value")), - point -> - point.hasAttributes( - attributeEntry("phi", "0.95"), - attributeEntry("tag", "value")), - point -> - point.hasAttributes( - attributeEntry("phi", "0.99"), - attributeEntry("tag", "value")))))); - } }