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..8d76b334e5dd --- /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 methodExit( + @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..c3a158a059b6 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/TestInstrumentationModule.java @@ -0,0 +1,32 @@ +/* + * 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 io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule; +import java.util.List; + +@AutoService(InstrumentationModule.class) +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()); + } +} 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..199979130805 --- /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; + +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")