Fix a metrics API bridging issue
MODIFY
instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/build.gradle.kts
instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/build.gradle.kts
@@ -3,7 +3,7 @@ plugins {
}
dependencies {
- compileOnly(project(":opentelemetry-api-shaded-for-instrumenting", configuration = "shadow"))
+ compileOnly(project(":opentelemetry-api-shaded-for-instrumenting", configuration = "v1_10"))
implementation(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.0:javaagent"))
implementation(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.4:javaagent"))
}

MODIFY
instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationObservableDoubleCounter.java
instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationObservableDoubleCounter.java
@@ -9,6 +9,16 @@ import application.io.opentelemetry.api.metrics.ObservableDoubleCounter;
public final class ApplicationObservableDoubleCounter implements ObservableDoubleCounter {
+ private final io.opentelemetry.api.metrics.ObservableDoubleCounter agentCounter;
+
public ApplicationObservableDoubleCounter(
- io.opentelemetry.api.metrics.ObservableDoubleCounter agentCounter) {}
+ io.opentelemetry.api.metrics.ObservableDoubleCounter agentCounter) {
+ this.agentCounter = agentCounter;
+ }
+
+ // not adding @Override because this method was introduced in 1.12
+ @SuppressWarnings("unused")
+ public void close() {
+ agentCounter.close();
+ }
}

MODIFY
instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationObservableDoubleGauge.java
instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationObservableDoubleGauge.java
@@ -9,6 +9,16 @@ import application.io.opentelemetry.api.metrics.ObservableDoubleGauge;
public final class ApplicationObservableDoubleGauge implements ObservableDoubleGauge {
+ private final io.opentelemetry.api.metrics.ObservableDoubleGauge agentGauge;
+
public ApplicationObservableDoubleGauge(
- io.opentelemetry.api.metrics.ObservableDoubleGauge agentGauge) {}
+ io.opentelemetry.api.metrics.ObservableDoubleGauge agentGauge) {
+ this.agentGauge = agentGauge;
+ }
+
+ // not adding @Override because this method was introduced in 1.12
+ @SuppressWarnings("unused")
+ public void close() {
+ agentGauge.close();
+ }
}

MODIFY
instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationObservableDoubleUpDownCounter.java
instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationObservableDoubleUpDownCounter.java
@@ -10,6 +10,16 @@ import application.io.opentelemetry.api.metrics.ObservableDoubleUpDownCounter;
public final class ApplicationObservableDoubleUpDownCounter
implements ObservableDoubleUpDownCounter {
+ private final io.opentelemetry.api.metrics.ObservableDoubleUpDownCounter agentUpDownCounter;
+
public ApplicationObservableDoubleUpDownCounter(
- io.opentelemetry.api.metrics.ObservableDoubleUpDownCounter agentUpDownCounter) {}
+ io.opentelemetry.api.metrics.ObservableDoubleUpDownCounter agentUpDownCounter) {
+ this.agentUpDownCounter = agentUpDownCounter;
+ }
+
+ // not adding @Override because this method was introduced in 1.12
+ @SuppressWarnings("unused")
+ public void close() {
+ agentUpDownCounter.close();
+ }
}

MODIFY
instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationObservableLongCounter.java
instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationObservableLongCounter.java
@@ -9,6 +9,16 @@ import application.io.opentelemetry.api.metrics.ObservableLongCounter;
public final class ApplicationObservableLongCounter implements ObservableLongCounter {
+ private final io.opentelemetry.api.metrics.ObservableLongCounter agentCounter;
+
public ApplicationObservableLongCounter(
- io.opentelemetry.api.metrics.ObservableLongCounter agentCounter) {}
+ io.opentelemetry.api.metrics.ObservableLongCounter agentCounter) {
+ this.agentCounter = agentCounter;
+ }
+
+ // not adding @Override because this method was introduced in 1.12
+ @SuppressWarnings("unused")
+ public void close() {
+ agentCounter.close();
+ }
}

MODIFY
instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationObservableLongGauge.java
instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationObservableLongGauge.java
@@ -9,6 +9,16 @@ import application.io.opentelemetry.api.metrics.ObservableLongGauge;
public final class ApplicationObservableLongGauge implements ObservableLongGauge {
+ private final io.opentelemetry.api.metrics.ObservableLongGauge agentGauge;
+
public ApplicationObservableLongGauge(
- io.opentelemetry.api.metrics.ObservableLongGauge agentGauge) {}
+ io.opentelemetry.api.metrics.ObservableLongGauge agentGauge) {
+ this.agentGauge = agentGauge;
+ }
+
+ // not adding @Override because this method was introduced in 1.12
+ @SuppressWarnings("unused")
+ public void close() {
+ agentGauge.close();
+ }
}

MODIFY
instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationObservableLongUpDownCounter.java
instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationObservableLongUpDownCounter.java
@@ -9,6 +9,16 @@ import application.io.opentelemetry.api.metrics.ObservableLongUpDownCounter;
public final class ApplicationObservableLongUpDownCounter implements ObservableLongUpDownCounter {
+ private final io.opentelemetry.api.metrics.ObservableLongUpDownCounter agentUpDownCounter;
+
public ApplicationObservableLongUpDownCounter(
- io.opentelemetry.api.metrics.ObservableLongUpDownCounter agentUpDownCounter) {}
+ io.opentelemetry.api.metrics.ObservableLongUpDownCounter agentUpDownCounter) {
+ this.agentUpDownCounter = agentUpDownCounter;
+ }
+
+ // not adding @Override because this method was introduced in 1.12
+ @SuppressWarnings("unused")
+ public void close() {
+ agentUpDownCounter.close();
+ }
}

MODIFY
instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/MeterTest.java
instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/MeterTest.java
@@ -17,8 +17,15 @@ import io.opentelemetry.api.metrics.LongCounter;
import io.opentelemetry.api.metrics.LongHistogram;
import io.opentelemetry.api.metrics.LongUpDownCounter;
import io.opentelemetry.api.metrics.Meter;
+import io.opentelemetry.api.metrics.ObservableDoubleCounter;
+import io.opentelemetry.api.metrics.ObservableDoubleGauge;
+import io.opentelemetry.api.metrics.ObservableDoubleUpDownCounter;
+import io.opentelemetry.api.metrics.ObservableLongCounter;
+import io.opentelemetry.api.metrics.ObservableLongGauge;
+import io.opentelemetry.api.metrics.ObservableLongUpDownCounter;
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
+import org.assertj.core.api.AbstractIterableAssert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
@@ -76,12 +83,14 @@ class MeterTest {
}
@Test
- void longUpDownCounter() {
- LongUpDownCounter instrument =
- meter.upDownCounterBuilder("test").setDescription("d").setUnit("u").build();
-
- instrument.add(5, Attributes.of(AttributeKey.stringKey("q"), "r"));
- instrument.add(6, Attributes.of(AttributeKey.stringKey("q"), "r"));
+ void observableLongCounter() throws InterruptedException {
+ ObservableLongCounter observableCounter =
+ meter
+ .counterBuilder("test")
+ .setDescription("d")
+ .setUnit("u")
+ .buildWithCallback(
+ result -> result.record(11, Attributes.of(AttributeKey.stringKey("q"), "r")));
testing.waitAndAssertMetrics(
instrumentationName,
@@ -97,13 +106,22 @@ class MeterTest {
instrumentationName, "1.2.3", /* schemaUrl= */ null))
.hasLongSumSatisfying(
sum ->
- sum.isNotMonotonic()
+ sum.isMonotonic()
.hasPointsSatisfying(
point ->
point
.hasValue(11)
.hasAttributesSatisfying(
equalTo(AttributeKey.stringKey("q"), "r"))))));
+
+ observableCounter.close();
+
+ // sleep exporter interval
+ Thread.sleep(100);
+ testing.clearData();
+ Thread.sleep(100);
+
+ testing.waitAndAssertMetrics(instrumentationName, "test", AbstractIterableAssert::isEmpty);
}
@Test
@@ -137,6 +155,122 @@ class MeterTest {
equalTo(AttributeKey.stringKey("q"), "r"))))));
}
+ @Test
+ void observableDoubleCounter() throws InterruptedException {
+ ObservableDoubleCounter observableCounter =
+ meter
+ .counterBuilder("test")
+ .ofDoubles()
+ .setDescription("d")
+ .setUnit("u")
+ .buildWithCallback(
+ result -> result.record(12.1, Attributes.of(AttributeKey.stringKey("q"), "r")));
+
+ testing.waitAndAssertMetrics(
+ instrumentationName,
+ "test",
+ metrics ->
+ metrics.anySatisfy(
+ metric ->
+ assertThat(metric)
+ .hasDescription("d")
+ .hasUnit("u")
+ .hasInstrumentationScope(
+ InstrumentationScopeInfo.create(
+ instrumentationName, "1.2.3", /* schemaUrl= */ null))
+ .hasDoubleSumSatisfying(
+ sum ->
+ sum.isMonotonic()
+ .hasPointsSatisfying(
+ point ->
+ point
+ .hasValue(12.1)
+ .hasAttributesSatisfying(
+ equalTo(AttributeKey.stringKey("q"), "r"))))));
+
+ observableCounter.close();
+
+ // sleep exporter interval
+ Thread.sleep(100);
+ testing.clearData();
+ Thread.sleep(100);
+
+ testing.waitAndAssertMetrics(instrumentationName, "test", AbstractIterableAssert::isEmpty);
+ }
+
+ @Test
+ void longUpDownCounter() {
+ LongUpDownCounter instrument =
+ meter.upDownCounterBuilder("test").setDescription("d").setUnit("u").build();
+
+ instrument.add(5, Attributes.of(AttributeKey.stringKey("q"), "r"));
+ instrument.add(6, Attributes.of(AttributeKey.stringKey("q"), "r"));
+
+ testing.waitAndAssertMetrics(
+ instrumentationName,
+ "test",
+ metrics ->
+ metrics.anySatisfy(
+ metric ->
+ assertThat(metric)
+ .hasDescription("d")
+ .hasUnit("u")
+ .hasInstrumentationScope(
+ InstrumentationScopeInfo.create(
+ instrumentationName, "1.2.3", /* schemaUrl= */ null))
+ .hasLongSumSatisfying(
+ sum ->
+ sum.isNotMonotonic()
+ .hasPointsSatisfying(
+ point ->
+ point
+ .hasValue(11)
+ .hasAttributesSatisfying(
+ equalTo(AttributeKey.stringKey("q"), "r"))))));
+ }
+
+ @Test
+ void observableLongUpDownCounter() throws InterruptedException {
+ ObservableLongUpDownCounter observableCounter =
+ meter
+ .upDownCounterBuilder("test")
+ .setDescription("d")
+ .setUnit("u")
+ .buildWithCallback(
+ result -> result.record(11, Attributes.of(AttributeKey.stringKey("q"), "r")));
+
+ testing.waitAndAssertMetrics(
+ instrumentationName,
+ "test",
+ metrics ->
+ metrics.anySatisfy(
+ metric ->
+ assertThat(metric)
+ .hasDescription("d")
+ .hasUnit("u")
+ .hasInstrumentationScope(
+ InstrumentationScopeInfo.create(
+ instrumentationName, "1.2.3", /* schemaUrl= */ null))
+ .hasLongSumSatisfying(
+ sum ->
+ sum.isNotMonotonic()
+ .hasPointsSatisfying(
+ point ->
+ point
+ .hasValue(11)
+ .hasAttributesSatisfying(
+ equalTo(AttributeKey.stringKey("q"), "r"))))));
+
+ observableCounter.close();
+
+ // sleep exporter interval
+ Thread.sleep(100);
+ testing.clearData();
+ Thread.sleep(100);
+
+ testing.waitAndAssertMetrics(instrumentationName, "test", AbstractIterableAssert::isEmpty);
+ }
+
@Test
void doubleUpDownCounter() {
DoubleUpDownCounter instrument =
@@ -168,6 +302,49 @@ class MeterTest {
equalTo(AttributeKey.stringKey("q"), "r"))))));
}
+ @Test
+ void observableDoubleUpDownCounter() throws InterruptedException {
+ ObservableDoubleUpDownCounter observableCounter =
+ meter
+ .upDownCounterBuilder("test")
+ .ofDoubles()
+ .setDescription("d")
+ .setUnit("u")
+ .buildWithCallback(
+ result -> result.record(12.1, Attributes.of(AttributeKey.stringKey("q"), "r")));
+
+ testing.waitAndAssertMetrics(
+ instrumentationName,
+ "test",
+ metrics ->
+ metrics.anySatisfy(
+ metric ->
+ assertThat(metric)
+ .hasDescription("d")
+ .hasUnit("u")
+ .hasInstrumentationScope(
+ InstrumentationScopeInfo.create(
+ instrumentationName, "1.2.3", /* schemaUrl= */ null))
+ .hasDoubleSumSatisfying(
+ sum ->
+ sum.isNotMonotonic()
+ .hasPointsSatisfying(
+ point ->
+ point
+ .hasValue(12.1)
+ .hasAttributesSatisfying(
+ equalTo(AttributeKey.stringKey("q"), "r"))))));
+
+ observableCounter.close();
+
+ // sleep exporter interval
+ Thread.sleep(100);
+ testing.clearData();
+ Thread.sleep(100);
+
+ testing.waitAndAssertMetrics(instrumentationName, "test", AbstractIterableAssert::isEmpty);
+ }
+
@Test
void longHistogram() {
LongHistogram instrument =
@@ -229,7 +406,8 @@ class MeterTest {
}
@Test
- void longGauge() {
+ void longGauge() throws InterruptedException {
+ ObservableLongGauge observableGauge =
meter
.gaugeBuilder("test")
.ofLongs()
@@ -258,10 +436,20 @@ class MeterTest {
.hasValue(123)
.hasAttributesSatisfying(
equalTo(AttributeKey.stringKey("q"), "r"))))));
+
+ observableGauge.close();
+
+ // sleep exporter interval
+ Thread.sleep(100);
+ testing.clearData();
+ Thread.sleep(100);
+
+ testing.waitAndAssertMetrics(instrumentationName, "test", AbstractIterableAssert::isEmpty);
}
@Test
- void doubleGauge() {
+ void doubleGauge() throws InterruptedException {
+ ObservableDoubleGauge observableGauge =
meter
.gaugeBuilder("test")
.setDescription("d")
@@ -289,5 +477,14 @@ class MeterTest {
.hasValue(1.23)
.hasAttributesSatisfying(
equalTo(AttributeKey.stringKey("q"), "r"))))));
+
+ observableGauge.close();
+
+ // sleep exporter interval
+ Thread.sleep(100);
+ testing.clearData();
+ Thread.sleep(100);
+
+ testing.waitAndAssertMetrics(instrumentationName, "test", AbstractIterableAssert::isEmpty);
}
}

MODIFY
opentelemetry-api-shaded-for-instrumenting/build.gradle.kts
opentelemetry-api-shaded-for-instrumenting/build.gradle.kts
+import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
+
plugins {
id("com.github.johnrengelman.shadow")
@@ -7,15 +9,53 @@ plugins {
description = "opentelemetry-api shaded for internal javaagent usage"
group = "io.opentelemetry.javaagent"
+val latestDeps by configurations.creating {
+ isCanBeResolved = true
+ isCanBeConsumed = false
+}
+val v1_10Deps by configurations.creating {
+ isCanBeResolved = true
+ isCanBeConsumed = false
+ // exclude the bom added by dependencyManagement
+ exclude("io.opentelemetry", "opentelemetry-bom")
+}
+
+// configuration for publishing the shadowed artifact
+val v1_10 by configurations.creating {
+ isCanBeConsumed = true
+ isCanBeResolved = false
+}
+
dependencies {
- implementation("io.opentelemetry:opentelemetry-api")
+ latestDeps("io.opentelemetry:opentelemetry-api")
+
+ listOf("opentelemetry-api", "opentelemetry-context").forEach {
+ v1_10Deps("io.opentelemetry:$it") {
+ version {
+ strictly("1.10.0")
+ }
+ }
+ }
}
// OpenTelemetry API shaded so that it can be used in instrumentation of OpenTelemetry API itself,
// and then its usage can be unshaded after OpenTelemetry API is shaded
// (see more explanation in opentelemetry-api-1.0.gradle)
tasks {
- shadowJar {
+ withType<ShadowJar>().configureEach {
relocate("io.opentelemetry", "application.io.opentelemetry")
}
+
+ shadowJar {
+ configurations = listOf(latestDeps)
+ }
+
+ val v1_10Shadow by registering(ShadowJar::class) {
+ configurations = listOf(v1_10Deps)
+ archiveClassifier.set("v1_10")
+ }
+
+ artifacts {
+ add(v1_10.name, v1_10Shadow)
+ }
}

Fix a metrics API bridging issue (#6034)