diff --git a/instrumentation/micrometer/micrometer-1.5/README.md b/instrumentation/micrometer/micrometer-1.5/README.md
new file mode 100644
index 000000000000..2181acafa118
--- /dev/null
+++ b/instrumentation/micrometer/micrometer-1.5/README.md
@@ -0,0 +1,5 @@
+# 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` |
\ No newline at end of file
diff --git a/instrumentation/micrometer/micrometer-1.5/javaagent/build.gradle.kts b/instrumentation/micrometer/micrometer-1.5/javaagent/build.gradle.kts
index d23987d1dfe8..7898ca334ade 100644
--- a/instrumentation/micrometer/micrometer-1.5/javaagent/build.gradle.kts
+++ b/instrumentation/micrometer/micrometer-1.5/javaagent/build.gradle.kts
@@ -18,3 +18,24 @@ dependencies {
testImplementation(project(":instrumentation:micrometer:micrometer-1.5:testing"))
}
+
+tasks {
+ val testBaseTimeUnit by registering(Test::class) {
+ filter {
+ includeTestsMatching("*TimerSecondsTest")
+ includeTestsMatching("*LongTimerSecondsTest")
+ isFailOnNoMatchingTests = false
+ }
+ include("**/*TimerSecondsTest.*", "**/*LongTaskTimerSecondsTest.*")
+ jvmArgs("-Dotel.instrumentation.micrometer.base-time-unit=seconds")
+ }
+
+ test {
+ dependsOn(testBaseTimeUnit)
+ filter {
+ excludeTestsMatching("*TimerSecondsTest")
+ excludeTestsMatching("*LongTimerSecondsTest")
+ isFailOnNoMatchingTests = false
+ }
+ }
+}
diff --git a/instrumentation/micrometer/micrometer-1.5/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/micrometer/v1_5/LongTaskTimerSecondsTest.java b/instrumentation/micrometer/micrometer-1.5/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/micrometer/v1_5/LongTaskTimerSecondsTest.java
new file mode 100644
index 000000000000..d3d6db88acc9
--- /dev/null
+++ b/instrumentation/micrometer/micrometer-1.5/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/micrometer/v1_5/LongTaskTimerSecondsTest.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.micrometer.v1_5;
+
+import io.opentelemetry.instrumentation.micrometer.v1_5.AbstractLongTaskTimerSecondsTest;
+import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class LongTaskTimerSecondsTest extends AbstractLongTaskTimerSecondsTest {
+
+ @RegisterExtension
+ static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
+
+ @Override
+ protected InstrumentationExtension testing() {
+ return testing;
+ }
+}
diff --git a/instrumentation/micrometer/micrometer-1.5/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/micrometer/v1_5/TimerSecondsTest.java b/instrumentation/micrometer/micrometer-1.5/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/micrometer/v1_5/TimerSecondsTest.java
new file mode 100644
index 000000000000..3782935de591
--- /dev/null
+++ b/instrumentation/micrometer/micrometer-1.5/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/micrometer/v1_5/TimerSecondsTest.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.micrometer.v1_5;
+
+import io.opentelemetry.instrumentation.micrometer.v1_5.AbstractTimerSecondsTest;
+import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class TimerSecondsTest extends AbstractTimerSecondsTest {
+
+ @RegisterExtension
+ static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
+
+ @Override
+ protected InstrumentationExtension testing() {
+ return testing;
+ }
+}
diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryLongTaskTimer.java b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryLongTaskTimer.java
index 7ead9a6d2470..e1a1e596afd4 100644
--- a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryLongTaskTimer.java
+++ b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryLongTaskTimer.java
@@ -8,12 +8,14 @@
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.description;
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.statisticInstrumentName;
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.tagsAsAttributes;
+import static io.opentelemetry.instrumentation.micrometer.v1_5.TimeUnitHelper.getUnitString;
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.Measurement;
import io.micrometer.core.instrument.Statistic;
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
import io.micrometer.core.instrument.internal.DefaultLongTaskTimer;
+import io.micrometer.core.instrument.util.TimeUtils;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.DoubleHistogram;
import io.opentelemetry.api.metrics.LongUpDownCounter;
@@ -23,8 +25,7 @@
final class OpenTelemetryLongTaskTimer extends DefaultLongTaskTimer implements RemovableMeter {
- private static final double NANOS_PER_MS = TimeUnit.MILLISECONDS.toNanos(1);
-
+ private final TimeUnit baseTimeUnit;
private final DistributionStatisticConfig distributionStatisticConfig;
// TODO: use bound instruments when they're available
private final DoubleHistogram otelHistogram;
@@ -36,16 +37,19 @@ final class OpenTelemetryLongTaskTimer extends DefaultLongTaskTimer implements R
OpenTelemetryLongTaskTimer(
Id id,
Clock clock,
+ TimeUnit baseTimeUnit,
DistributionStatisticConfig distributionStatisticConfig,
Meter otelMeter) {
- super(id, clock, TimeUnit.MILLISECONDS, distributionStatisticConfig, false);
+ super(id, clock, baseTimeUnit, distributionStatisticConfig, false);
+
+ this.baseTimeUnit = baseTimeUnit;
this.distributionStatisticConfig = distributionStatisticConfig;
this.otelHistogram =
otelMeter
.histogramBuilder(id.getName())
.setDescription(description(id))
- .setUnit("ms")
+ .setUnit(getUnitString(baseTimeUnit))
.build();
this.otelActiveTasksCounter =
otelMeter
@@ -101,7 +105,7 @@ public long stop() {
long durationNanos = original.stop();
if (!removed) {
otelActiveTasksCounter.add(-1, attributes);
- double time = durationNanos / NANOS_PER_MS;
+ double time = TimeUtils.nanosToUnit(durationNanos, baseTimeUnit);
otelHistogram.record(time, attributes);
}
return durationNanos;
diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeterRegistry.java b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeterRegistry.java
index 725a64d31eb1..a7781b2db866 100644
--- a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeterRegistry.java
+++ b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeterRegistry.java
@@ -49,11 +49,14 @@ public static OpenTelemetryMeterRegistryBuilder builder(OpenTelemetry openTeleme
return new OpenTelemetryMeterRegistryBuilder(openTelemetry);
}
+ private final TimeUnit baseTimeUnit;
private final io.opentelemetry.api.metrics.Meter otelMeter;
private final AsyncInstrumentRegistry asyncInstrumentRegistry;
- OpenTelemetryMeterRegistry(Clock clock, io.opentelemetry.api.metrics.Meter otelMeter) {
+ OpenTelemetryMeterRegistry(
+ Clock clock, TimeUnit baseTimeUnit, io.opentelemetry.api.metrics.Meter otelMeter) {
super(clock);
+ this.baseTimeUnit = baseTimeUnit;
this.otelMeter = otelMeter;
this.asyncInstrumentRegistry = AsyncInstrumentRegistry.getOrCreate(otelMeter);
this.config().onMeterRemoved(OpenTelemetryMeterRegistry::onMeterRemoved);
@@ -73,7 +76,8 @@ protected Counter newCounter(Meter.Id id) {
protected LongTaskTimer newLongTaskTimer(
Meter.Id id, DistributionStatisticConfig distributionStatisticConfig) {
OpenTelemetryLongTaskTimer timer =
- new OpenTelemetryLongTaskTimer(id, clock, distributionStatisticConfig, otelMeter);
+ new OpenTelemetryLongTaskTimer(
+ id, clock, getBaseTimeUnit(), distributionStatisticConfig, otelMeter);
if (timer.isUsingMicrometerHistograms()) {
HistogramGauges.registerWithCommonFormat(timer, this);
}
@@ -91,6 +95,7 @@ protected Timer newTimer(
clock,
distributionStatisticConfig,
pauseDetector,
+ getBaseTimeUnit(),
otelMeter,
asyncInstrumentRegistry);
if (timer.isUsingMicrometerHistograms()) {
@@ -135,7 +140,7 @@ protected FunctionCounter newFunctionCounter(
@Override
protected TimeUnit getBaseTimeUnit() {
- return TimeUnit.MILLISECONDS;
+ return baseTimeUnit;
}
@Override
diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeterRegistryBuilder.java b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeterRegistryBuilder.java
index 53cbc6380c8d..157549d9f695 100644
--- a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeterRegistryBuilder.java
+++ b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeterRegistryBuilder.java
@@ -8,6 +8,8 @@
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.MeterRegistry;
import io.opentelemetry.api.OpenTelemetry;
+import io.opentelemetry.instrumentation.api.config.Config;
+import java.util.concurrent.TimeUnit;
/** A builder of {@link OpenTelemetryMeterRegistry}. */
public final class OpenTelemetryMeterRegistryBuilder {
@@ -16,6 +18,9 @@ public final class OpenTelemetryMeterRegistryBuilder {
private final OpenTelemetry openTelemetry;
private Clock clock = Clock.SYSTEM;
+ private TimeUnit baseTimeUnit =
+ TimeUnitHelper.parseConfigValue(
+ Config.get().getString("otel.instrumentation.micrometer.base-time-unit"));
OpenTelemetryMeterRegistryBuilder(OpenTelemetry openTelemetry) {
this.openTelemetry = openTelemetry;
@@ -27,12 +32,18 @@ public OpenTelemetryMeterRegistryBuilder setClock(Clock clock) {
return this;
}
+ /** Sets the base time unit. */
+ public OpenTelemetryMeterRegistryBuilder setBaseTimeUnit(TimeUnit baseTimeUnit) {
+ this.baseTimeUnit = baseTimeUnit;
+ return this;
+ }
+
/**
* Returns a new {@link OpenTelemetryMeterRegistry} with the settings of this {@link
* OpenTelemetryMeterRegistryBuilder}.
*/
public MeterRegistry build() {
return new OpenTelemetryMeterRegistry(
- clock, openTelemetry.getMeterProvider().get(INSTRUMENTATION_NAME));
+ clock, baseTimeUnit, 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 ae01bdb24a7b..e046a2839e4c 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
@@ -8,6 +8,7 @@
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.description;
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.statisticInstrumentName;
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.tagsAsAttributes;
+import static io.opentelemetry.instrumentation.micrometer.v1_5.TimeUnitHelper.getUnitString;
import io.micrometer.core.instrument.AbstractTimer;
import io.micrometer.core.instrument.Clock;
@@ -29,10 +30,9 @@
final class OpenTelemetryTimer extends AbstractTimer implements RemovableMeter {
- private static final double NANOS_PER_MS = TimeUnit.MILLISECONDS.toNanos(1);
-
private final Measurements measurements;
private final TimeWindowMax max;
+ private final TimeUnit baseTimeUnit;
// TODO: use bound instruments when they're available
private final DoubleHistogram otelHistogram;
private final Attributes attributes;
@@ -45,6 +45,7 @@ final class OpenTelemetryTimer extends AbstractTimer implements RemovableMeter {
Clock clock,
DistributionStatisticConfig distributionStatisticConfig,
PauseDetector pauseDetector,
+ TimeUnit baseTimeUnit,
Meter otelMeter,
AsyncInstrumentRegistry asyncInstrumentRegistry) {
super(id, clock, distributionStatisticConfig, pauseDetector, TimeUnit.MILLISECONDS, false);
@@ -56,12 +57,13 @@ final class OpenTelemetryTimer extends AbstractTimer implements RemovableMeter {
}
max = new TimeWindowMax(clock, distributionStatisticConfig);
+ this.baseTimeUnit = baseTimeUnit;
this.attributes = tagsAsAttributes(id);
this.otelHistogram =
otelMeter
.histogramBuilder(id.getName())
.setDescription(description(id))
- .setUnit("ms")
+ .setUnit(getUnitString(baseTimeUnit))
.build();
this.maxHandle =
asyncInstrumentRegistry.buildGauge(
@@ -81,7 +83,7 @@ boolean isUsingMicrometerHistograms() {
protected void recordNonNegative(long amount, TimeUnit unit) {
if (amount >= 0 && !removed) {
long nanos = unit.toNanos(amount);
- double time = nanos / NANOS_PER_MS;
+ double time = TimeUtils.nanosToUnit(nanos, baseTimeUnit);
otelHistogram.record(time, attributes);
measurements.record(nanos);
max.record(nanos, TimeUnit.NANOSECONDS);
diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/TimeUnitHelper.java b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/TimeUnitHelper.java
new file mode 100644
index 000000000000..29af910c8827
--- /dev/null
+++ b/instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/TimeUnitHelper.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.micrometer.v1_5;
+
+import java.util.Locale;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class TimeUnitHelper {
+
+ private static final Logger logger = LoggerFactory.getLogger(OpenTelemetryMeterRegistry.class);
+
+ static TimeUnit parseConfigValue(@Nullable String value) {
+ if (value == null) {
+ return TimeUnit.MILLISECONDS;
+ }
+ // short names are UCUM names
+ // long names are just TimeUnit values lowercased
+ switch (value.toLowerCase(Locale.ROOT)) {
+ case "ns":
+ case "nanoseconds":
+ return TimeUnit.NANOSECONDS;
+ case "us":
+ case "microseconds":
+ return TimeUnit.MICROSECONDS;
+ case "ms":
+ case "milliseconds":
+ return TimeUnit.MILLISECONDS;
+ case "s":
+ case "seconds":
+ return TimeUnit.SECONDS;
+ case "min":
+ case "minutes":
+ return TimeUnit.MINUTES;
+ case "h":
+ case "hours":
+ return TimeUnit.HOURS;
+ case "d":
+ case "days":
+ return TimeUnit.DAYS;
+ default:
+ logger.warn(
+ "Invalid base time unit: '{}'; using microseconds as the base time unit instead",
+ value);
+ return TimeUnit.MILLISECONDS;
+ }
+ }
+
+ static String getUnitString(TimeUnit unit) {
+ switch (unit) {
+ case NANOSECONDS:
+ return "ns";
+ case MICROSECONDS:
+ return "us";
+ case MILLISECONDS:
+ return "ms";
+ case SECONDS:
+ return "s";
+ case MINUTES:
+ return "min";
+ case HOURS:
+ return "h";
+ case DAYS:
+ return "d";
+ }
+ throw new IllegalStateException("Should not ever happen");
+ }
+
+ private TimeUnitHelper() {}
+}
diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/LongTaskTimerSecondsTest.java b/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/LongTaskTimerSecondsTest.java
new file mode 100644
index 000000000000..b340b652a830
--- /dev/null
+++ b/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/LongTaskTimerSecondsTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.micrometer.v1_5;
+
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Metrics;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
+import java.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class LongTaskTimerSecondsTest extends AbstractLongTaskTimerSecondsTest {
+
+ @RegisterExtension
+ static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
+
+ static MeterRegistry otelMeterRegistry;
+
+ @BeforeAll
+ public static void setUpRegistry() {
+ otelMeterRegistry =
+ OpenTelemetryMeterRegistry.builder(testing.getOpenTelemetry())
+ .setBaseTimeUnit(TimeUnit.SECONDS)
+ .build();
+ Metrics.addRegistry(otelMeterRegistry);
+ }
+
+ @AfterAll
+ public static void tearDownRegistry() {
+ Metrics.removeRegistry(otelMeterRegistry);
+ }
+
+ @Override
+ protected InstrumentationExtension testing() {
+ return testing;
+ }
+}
diff --git a/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/TimerSecondsTest.java b/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/TimerSecondsTest.java
new file mode 100644
index 000000000000..cd800b3d2bc0
--- /dev/null
+++ b/instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/TimerSecondsTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.micrometer.v1_5;
+
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Metrics;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
+import java.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class TimerSecondsTest extends AbstractTimerSecondsTest {
+
+ @RegisterExtension
+ static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
+
+ static MeterRegistry otelMeterRegistry;
+
+ @BeforeAll
+ public static void setUpRegistry() {
+ otelMeterRegistry =
+ OpenTelemetryMeterRegistry.builder(testing.getOpenTelemetry())
+ .setBaseTimeUnit(TimeUnit.SECONDS)
+ .build();
+ Metrics.addRegistry(otelMeterRegistry);
+ }
+
+ @AfterAll
+ public static void tearDownRegistry() {
+ Metrics.removeRegistry(otelMeterRegistry);
+ }
+
+ @Override
+ protected InstrumentationExtension testing() {
+ return testing;
+ }
+}
diff --git a/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractLongTaskTimerSecondsTest.java b/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractLongTaskTimerSecondsTest.java
new file mode 100644
index 000000000000..658de0ab2e89
--- /dev/null
+++ b/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractLongTaskTimerSecondsTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.micrometer.v1_5;
+
+import static io.opentelemetry.sdk.testing.assertj.MetricAssertions.assertThat;
+import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
+
+import io.micrometer.core.instrument.LongTaskTimer;
+import io.micrometer.core.instrument.Metrics;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import java.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public abstract class AbstractLongTaskTimerSecondsTest {
+
+ static final String INSTRUMENTATION_NAME = "io.opentelemetry.micrometer-1.5";
+
+ protected abstract InstrumentationExtension testing();
+
+ @BeforeEach
+ void cleanupMeters() {
+ Metrics.globalRegistry.forEachMeter(Metrics.globalRegistry::remove);
+ }
+
+ @Test
+ void testLongTaskTimerWithBaseUnitSeconds() throws InterruptedException {
+ // given
+ LongTaskTimer timer =
+ LongTaskTimer.builder("testLongTaskTimerSeconds")
+ .description("This is a test long task timer")
+ .tags("tag", "value")
+ .register(Metrics.globalRegistry);
+
+ // when
+ LongTaskTimer.Sample sample = timer.start();
+
+ // then
+ testing()
+ .waitAndAssertMetrics(
+ INSTRUMENTATION_NAME,
+ "testLongTaskTimerSeconds.active",
+ metrics ->
+ metrics.anySatisfy(
+ metric ->
+ assertThat(metric)
+ .hasDescription("This is a test long task timer")
+ .hasUnit("tasks")
+ .hasLongSum()
+ .isNotMonotonic()
+ .points()
+ .satisfiesExactly(
+ point ->
+ assertThat(point)
+ .hasValue(1)
+ .attributes()
+ .containsOnly(attributeEntry("tag", "value")))));
+
+ // when
+ TimeUnit.MILLISECONDS.sleep(100);
+ sample.stop();
+
+ // then
+ testing()
+ .waitAndAssertMetrics(
+ INSTRUMENTATION_NAME,
+ "testLongTaskTimerSeconds",
+ metrics ->
+ metrics.anySatisfy(
+ metric ->
+ assertThat(metric)
+ .hasDescription("This is a test long task timer")
+ .hasUnit("s")
+ .hasDoubleHistogram()
+ .points()
+ .satisfiesExactly(
+ point ->
+ assertThat(point)
+ .hasSumGreaterThan(0.1)
+ .hasCount(1)
+ .attributes()
+ .containsOnly(attributeEntry("tag", "value")))));
+ testing()
+ .waitAndAssertMetrics(
+ INSTRUMENTATION_NAME,
+ "testLongTaskTimerSeconds.active",
+ metrics ->
+ metrics.anySatisfy(
+ metric ->
+ assertThat(metric)
+ .hasLongSum()
+ .points()
+ .satisfiesExactly(
+ point ->
+ assertThat(point)
+ .hasValue(0)
+ .attributes()
+ .containsOnly(attributeEntry("tag", "value")))));
+ testing().clearData();
+
+ // when timer is removed from the registry
+ Metrics.globalRegistry.remove(timer);
+ sample = timer.start();
+
+ // then no tasks are active after starting a new sample
+ testing()
+ .waitAndAssertMetrics(
+ INSTRUMENTATION_NAME,
+ "testLongTaskTimerSeconds.active",
+ metrics ->
+ metrics.anySatisfy(
+ metric ->
+ assertThat(metric)
+ .hasLongSum()
+ .points()
+ .satisfiesExactly(
+ point ->
+ assertThat(point)
+ .hasValue(0)
+ .attributes()
+ .containsOnly(attributeEntry("tag", "value")))));
+
+ // when
+ TimeUnit.MILLISECONDS.sleep(100);
+ sample.stop();
+
+ // then sample of a removed timer does not record any data
+ testing()
+ .waitAndAssertMetrics(
+ INSTRUMENTATION_NAME,
+ "testLongTaskTimerSeconds",
+ metrics ->
+ metrics.allSatisfy(
+ metric ->
+ assertThat(metric)
+ .hasDoubleHistogram()
+ .points()
+ .noneSatisfy(
+ point -> assertThat(point).hasSumGreaterThan(0.2).hasCount(2))));
+ }
+}
diff --git a/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractTimerSecondsTest.java b/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractTimerSecondsTest.java
new file mode 100644
index 000000000000..86110bedaa3b
--- /dev/null
+++ b/instrumentation/micrometer/micrometer-1.5/testing/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/AbstractTimerSecondsTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.micrometer.v1_5;
+
+import static io.opentelemetry.sdk.testing.assertj.MetricAssertions.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.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+@SuppressWarnings("PreferJavaTimeOverload")
+public abstract class AbstractTimerSecondsTest {
+
+ static final String INSTRUMENTATION_NAME = "io.opentelemetry.micrometer-1.5";
+
+ protected abstract InstrumentationExtension testing();
+
+ @BeforeEach
+ void cleanupMeters() {
+ Metrics.globalRegistry.forEachMeter(Metrics.globalRegistry::remove);
+ }
+
+ @Test
+ void testTimerWithBaseUnitSeconds() {
+ // given
+ Timer timer =
+ Timer.builder("testTimerSeconds")
+ .description("This is a test timer")
+ .tags("tag", "value")
+ .register(Metrics.globalRegistry);
+
+ // when
+ timer.record(1, TimeUnit.SECONDS);
+ timer.record(10, TimeUnit.SECONDS);
+ timer.record(12_345, TimeUnit.MILLISECONDS);
+
+ // then
+ testing()
+ .waitAndAssertMetrics(
+ INSTRUMENTATION_NAME,
+ "testTimerSeconds",
+ metrics ->
+ metrics.anySatisfy(
+ metric ->
+ assertThat(metric)
+ .hasDescription("This is a test timer")
+ .hasUnit("s")
+ .hasDoubleHistogram()
+ .points()
+ .satisfiesExactly(
+ point ->
+ assertThat(point)
+ .hasSum(23.345)
+ .hasCount(3)
+ .attributes()
+ .containsOnly(attributeEntry("tag", "value")))));
+ testing().clearData();
+
+ // when
+ Metrics.globalRegistry.remove(timer);
+ timer.record(12, TimeUnit.SECONDS);
+
+ // then
+ testing()
+ .waitAndAssertMetrics(
+ INSTRUMENTATION_NAME,
+ "testTimerSeconds",
+ metrics ->
+ metrics.allSatisfy(
+ metric ->
+ assertThat(metric)
+ .hasDoubleHistogram()
+ .points()
+ .noneSatisfy(point -> assertThat(point).hasSum(35.345).hasCount(4))));
+ }
+}