From 350d05f59ada13c1e7dd7a7dbdad41b47c1ed19a Mon Sep 17 00:00:00 2001 From: Lauri Tulmin Date: Mon, 1 Sep 2025 18:45:42 +0300 Subject: [PATCH 1/3] Instrument instrumentation suppression api --- .../InstrumentationUtilInstrumentation.java | 65 +++++++++++++++++++ ...OpenTelemetryApiInstrumentationModule.java | 3 +- .../testing/build.gradle.kts | 9 +++ .../opentelemetryapi/TestInstrumentation.java | 42 ++++++++++++ .../TestInstrumentationModule.java | 25 +++++++ .../InstrumentationUtilTest.java | 24 +++++++ .../opentelemetryapi/TestClass.java | 19 ++++++ settings.gradle.kts | 1 + 8 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/InstrumentationUtilInstrumentation.java create mode 100644 instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/build.gradle.kts create mode 100644 instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestInstrumentation.java create mode 100644 instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestInstrumentationModule.java create mode 100644 instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/InstrumentationUtilTest.java create mode 100644 instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestClass.java diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/InstrumentationUtilInstrumentation.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/InstrumentationUtilInstrumentation.java new file mode 100644 index 000000000000..645f791befb6 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/InstrumentationUtilInstrumentation.java @@ -0,0 +1,65 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.returns; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import application.io.opentelemetry.context.Context; +import io.opentelemetry.api.internal.InstrumentationUtil; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.context.AgentContextStorage; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +public class InstrumentationUtilInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("application.io.opentelemetry.api.internal.InstrumentationUtil"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + named("shouldSuppressInstrumentation") + .and(takesArgument(0, named("application.io.opentelemetry.context.Context"))) + .and(returns(boolean.class)), + this.getClass().getName() + "$ShouldSuppressAdvice"); + transformer.applyAdviceToMethod( + named("suppressInstrumentation").and(takesArgument(0, Runnable.class)), + this.getClass().getName() + "$SuppressAdvice"); + } + + @SuppressWarnings("unused") + public static class ShouldSuppressAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class, skipOn = Advice.OnNonDefaultValue.class) + public static boolean methodEnter() { + return true; + } + + @Advice.OnMethodExit(suppress = Throwable.class) + public static void methodEnter( + @Advice.Argument(0) Context context, @Advice.Return(readOnly = false) boolean result) { + result = + InstrumentationUtil.shouldSuppressInstrumentation( + AgentContextStorage.getAgentContext(context)); + } + } + + @SuppressWarnings("unused") + public static class SuppressAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class, skipOn = Advice.OnNonDefaultValue.class) + public static boolean methodEnter(@Advice.Argument(0) Runnable runnable) { + InstrumentationUtil.suppressInstrumentation(runnable); + return true; + } + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/OpenTelemetryApiInstrumentationModule.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/OpenTelemetryApiInstrumentationModule.java index 6ce2d6ddcec4..f0fb67e48f56 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/OpenTelemetryApiInstrumentationModule.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/OpenTelemetryApiInstrumentationModule.java @@ -27,7 +27,8 @@ public List typeInstrumentations() { new ContextInstrumentation(), new ContextStorageWrappersInstrumentation(), new OpenTelemetryInstrumentation(), - new SpanInstrumentation()); + new SpanInstrumentation(), + new InstrumentationUtilInstrumentation()); } @Override diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/build.gradle.kts b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/build.gradle.kts new file mode 100644 index 000000000000..a5cdafa34246 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/build.gradle.kts @@ -0,0 +1,9 @@ +plugins { + id("otel.javaagent-testing") +} + +dependencies { + compileOnly(project(":opentelemetry-api-shaded-for-instrumenting", configuration = "shadow")) + implementation(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.0:javaagent")) + testInstrumentation(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.0:javaagent")) +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestInstrumentation.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestInstrumentation.java new file mode 100644 index 000000000000..46d5ec170e2d --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestInstrumentation.java @@ -0,0 +1,42 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +import application.io.opentelemetry.context.Context; +import io.opentelemetry.api.internal.InstrumentationUtil; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.context.AgentContextStorage; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +public class TestInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("io.opentelemetry.javaagent.instrumentation.opentelemetryapi.TestClass"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + named("shouldSuppressInstrumentation"), this.getClass().getName() + "$TestAdvice"); + } + + @SuppressWarnings("unused") + public static class TestAdvice { + + @Advice.OnMethodExit(suppress = Throwable.class) + public static void onExit( + @Advice.Argument(0) Context context, @Advice.Return(readOnly = false) boolean result) { + result = + InstrumentationUtil.shouldSuppressInstrumentation( + AgentContextStorage.getAgentContext(context)); + } + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestInstrumentationModule.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestInstrumentationModule.java new file mode 100644 index 000000000000..5cd6610ae3a0 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestInstrumentationModule.java @@ -0,0 +1,25 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi; + +import static java.util.Collections.singletonList; + +import com.google.auto.service.AutoService; +import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import java.util.List; + +@AutoService(InstrumentationModule.class) +public class TestInstrumentationModule extends InstrumentationModule { + public TestInstrumentationModule() { + super("test"); + } + + @Override + public List typeInstrumentations() { + return singletonList(new TestInstrumentation()); + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/InstrumentationUtilTest.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/InstrumentationUtilTest.java new file mode 100644 index 000000000000..bbaac42361bd --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/InstrumentationUtilTest.java @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.internal.InstrumentationUtil; +import io.opentelemetry.context.Context; +import org.junit.jupiter.api.Test; + +public class InstrumentationUtilTest { + + @Test + void instrumentationSuppression() { + Context[] contexts = new Context[1]; + InstrumentationUtil.suppressInstrumentation(() -> contexts[0] = Context.current()); + + assertThat(InstrumentationUtil.shouldSuppressInstrumentation(contexts[0])).isTrue(); + assertThat(TestClass.shouldSuppressInstrumentation(contexts[0])).isTrue(); + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestClass.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestClass.java new file mode 100644 index 000000000000..29725af0b144 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestClass.java @@ -0,0 +1,19 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi; + +import io.opentelemetry.context.Context; + +class TestClass { + static boolean shouldSuppressInstrumentation(Context context) { + // this method is instrumented to call + // InstrumentationUtil.shouldSuppressInstrumentation(context) to simulate agent code calling + // that method + return false; + } + + private TestClass() {} +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 7e171f79605a..fd25a43d40c6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -434,6 +434,7 @@ include(":instrumentation:opensearch:opensearch-rest-3.0:javaagent") include(":instrumentation:opensearch:opensearch-rest-common:javaagent") include(":instrumentation:opensearch:opensearch-rest-common:testing") include(":instrumentation:opentelemetry-api:opentelemetry-api-1.0:javaagent") +include(":instrumentation:opentelemetry-api:opentelemetry-api-1.0:testing") include(":instrumentation:opentelemetry-api:opentelemetry-api-1.4:javaagent") include(":instrumentation:opentelemetry-api:opentelemetry-api-1.10:javaagent") include(":instrumentation:opentelemetry-api:opentelemetry-api-1.15:javaagent") From 0caf2a9bae359efba2166f430ab7de011b92e50d Mon Sep 17 00:00:00 2001 From: Lauri Tulmin Date: Mon, 1 Sep 2025 19:35:10 +0300 Subject: [PATCH 2/3] fix indy --- .../opentelemetryapi/TestInstrumentationModule.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestInstrumentationModule.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestInstrumentationModule.java index 5cd6610ae3a0..c3a158a059b6 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestInstrumentationModule.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestInstrumentationModule.java @@ -10,14 +10,21 @@ import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule; import java.util.List; @AutoService(InstrumentationModule.class) -public class TestInstrumentationModule extends InstrumentationModule { +public class TestInstrumentationModule extends InstrumentationModule + implements ExperimentalInstrumentationModule { public TestInstrumentationModule() { super("test"); } + @Override + public String getModuleGroup() { + return "opentelemetry-api-bridge"; + } + @Override public List typeInstrumentations() { return singletonList(new TestInstrumentation()); From 1a2f0288a208c5417f176104056c0eeb5568747f Mon Sep 17 00:00:00 2001 From: Lauri Tulmin Date: Tue, 2 Sep 2025 14:04:06 +0300 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Jay DeLuca --- .../opentelemetryapi/InstrumentationUtilInstrumentation.java | 2 +- .../opentelemetryapi/InstrumentationUtilTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/InstrumentationUtilInstrumentation.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/InstrumentationUtilInstrumentation.java index 645f791befb6..8d76b334e5dd 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/InstrumentationUtilInstrumentation.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/InstrumentationUtilInstrumentation.java @@ -45,7 +45,7 @@ public static boolean methodEnter() { } @Advice.OnMethodExit(suppress = Throwable.class) - public static void methodEnter( + public static void methodExit( @Advice.Argument(0) Context context, @Advice.Return(readOnly = false) boolean result) { result = InstrumentationUtil.shouldSuppressInstrumentation( diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/InstrumentationUtilTest.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/InstrumentationUtilTest.java index bbaac42361bd..199979130805 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/InstrumentationUtilTest.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/InstrumentationUtilTest.java @@ -11,7 +11,7 @@ import io.opentelemetry.context.Context; import org.junit.jupiter.api.Test; -public class InstrumentationUtilTest { +class InstrumentationUtilTest { @Test void instrumentationSuppression() {