From 30de9ff26674ed7eef90193aabdd86d6adde0851 Mon Sep 17 00:00:00 2001 From: Mateusz Rzeszutek Date: Thu, 12 Jan 2023 02:19:43 +0100 Subject: [PATCH] Disable internal TaskScheduler spans in Spring Kafka instrumentation (#7553) Resolves #7511 I used the same pattern we already have for suppressing the wrapping of the Kafka consumer records lists. --- .../javaagent/build.gradle.kts | 2 ++ ...a => ListenerConsumerInstrumentation.java} | 22 +++++++++++++++++- .../SpringKafkaInstrumentationModule.java | 2 +- .../bootstrap/build.gradle.kts | 3 +++ .../spring/SpringSchedulingTaskTracing.java | 23 +++++++++++++++++++ .../javaagent/build.gradle.kts | 2 ++ .../TaskSchedulerInstrumentation.java | 5 +++- settings.gradle.kts | 1 + 8 files changed, 57 insertions(+), 3 deletions(-) rename instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/{SuppressingKafkaClientsInstrumentation.java => ListenerConsumerInstrumentation.java} (63%) create mode 100644 instrumentation/spring/spring-scheduling-3.1/bootstrap/build.gradle.kts create mode 100644 instrumentation/spring/spring-scheduling-3.1/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/spring/SpringSchedulingTaskTracing.java diff --git a/instrumentation/spring/spring-kafka-2.7/javaagent/build.gradle.kts b/instrumentation/spring/spring-kafka-2.7/javaagent/build.gradle.kts index 78a2e6ca6c..ebd165acfe 100644 --- a/instrumentation/spring/spring-kafka-2.7/javaagent/build.gradle.kts +++ b/instrumentation/spring/spring-kafka-2.7/javaagent/build.gradle.kts @@ -16,12 +16,14 @@ dependencies { annotationProcessor("com.google.auto.value:auto-value") bootstrap(project(":instrumentation:kafka:kafka-clients:kafka-clients-0.11:bootstrap")) + bootstrap(project(":instrumentation:spring:spring-scheduling-3.1:bootstrap")) implementation(project(":instrumentation:kafka:kafka-clients:kafka-clients-common:library")) implementation(project(":instrumentation:spring:spring-kafka-2.7:library")) library("org.springframework.kafka:spring-kafka:2.7.0") testInstrumentation(project(":instrumentation:kafka:kafka-clients:kafka-clients-0.11:javaagent")) + testInstrumentation(project(":instrumentation:spring:spring-scheduling-3.1:javaagent")) testImplementation(project(":instrumentation:spring:spring-kafka-2.7:testing")) diff --git a/instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/SuppressingKafkaClientsInstrumentation.java b/instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/ListenerConsumerInstrumentation.java similarity index 63% rename from instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/SuppressingKafkaClientsInstrumentation.java rename to instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/ListenerConsumerInstrumentation.java index cf8d85b2bb..c76b7df7ce 100644 --- a/instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/SuppressingKafkaClientsInstrumentation.java +++ b/instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/ListenerConsumerInstrumentation.java @@ -5,16 +5,18 @@ package io.opentelemetry.javaagent.instrumentation.spring.kafka; +import static net.bytebuddy.matcher.ElementMatchers.isConstructor; import static net.bytebuddy.matcher.ElementMatchers.named; import io.opentelemetry.javaagent.bootstrap.kafka.KafkaClientsConsumerProcessTracing; +import io.opentelemetry.javaagent.bootstrap.spring.SpringSchedulingTaskTracing; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -public class SuppressingKafkaClientsInstrumentation implements TypeInstrumentation { +public class ListenerConsumerInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { @@ -25,11 +27,14 @@ public class SuppressingKafkaClientsInstrumentation implements TypeInstrumentati @Override public void transform(TypeTransformer transformer) { transformer.applyAdviceToMethod(named("run"), this.getClass().getName() + "$RunLoopAdvice"); + transformer.applyAdviceToMethod( + isConstructor(), this.getClass().getName() + "$ConstructorAdvice"); } // this advice suppresses the CONSUMER spans created by the kafka-clients instrumentation @SuppressWarnings("unused") public static class RunLoopAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) public static boolean onEnter() { return KafkaClientsConsumerProcessTracing.setEnabled(false); @@ -40,4 +45,19 @@ public class SuppressingKafkaClientsInstrumentation implements TypeInstrumentati KafkaClientsConsumerProcessTracing.setEnabled(previousValue); } } + + // this advice suppresses the spans generated by spring scheduling instrumentation + @SuppressWarnings("unused") + public static class ConstructorAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static boolean onEnter() { + return SpringSchedulingTaskTracing.setEnabled(false); + } + + @Advice.OnMethodExit(suppress = Throwable.class) + public static void onExit(@Advice.Enter boolean previousValue) { + SpringSchedulingTaskTracing.setEnabled(previousValue); + } + } } diff --git a/instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/SpringKafkaInstrumentationModule.java b/instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/SpringKafkaInstrumentationModule.java index 54e0cb3ded..53aca03385 100644 --- a/instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/SpringKafkaInstrumentationModule.java +++ b/instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/SpringKafkaInstrumentationModule.java @@ -22,6 +22,6 @@ public class SpringKafkaInstrumentationModule extends InstrumentationModule { public List typeInstrumentations() { return asList( new AbstractMessageListenerContainerInstrumentation(), - new SuppressingKafkaClientsInstrumentation()); + new ListenerConsumerInstrumentation()); } } diff --git a/instrumentation/spring/spring-scheduling-3.1/bootstrap/build.gradle.kts b/instrumentation/spring/spring-scheduling-3.1/bootstrap/build.gradle.kts new file mode 100644 index 0000000000..072a96df45 --- /dev/null +++ b/instrumentation/spring/spring-scheduling-3.1/bootstrap/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("otel.javaagent-bootstrap") +} diff --git a/instrumentation/spring/spring-scheduling-3.1/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/spring/SpringSchedulingTaskTracing.java b/instrumentation/spring/spring-scheduling-3.1/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/spring/SpringSchedulingTaskTracing.java new file mode 100644 index 0000000000..6026897818 --- /dev/null +++ b/instrumentation/spring/spring-scheduling-3.1/bootstrap/src/main/java/io/opentelemetry/javaagent/bootstrap/spring/SpringSchedulingTaskTracing.java @@ -0,0 +1,23 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.bootstrap.spring; + +public final class SpringSchedulingTaskTracing { + + private static final ThreadLocal wrappingEnabled = ThreadLocal.withInitial(() -> true); + + private SpringSchedulingTaskTracing() {} + + public static boolean setEnabled(boolean enabled) { + boolean previous = wrappingEnabled.get(); + wrappingEnabled.set(enabled); + return previous; + } + + public static boolean wrappingEnabled() { + return wrappingEnabled.get(); + } +} diff --git a/instrumentation/spring/spring-scheduling-3.1/javaagent/build.gradle.kts b/instrumentation/spring/spring-scheduling-3.1/javaagent/build.gradle.kts index da5495a922..06df6d1fb2 100644 --- a/instrumentation/spring/spring-scheduling-3.1/javaagent/build.gradle.kts +++ b/instrumentation/spring/spring-scheduling-3.1/javaagent/build.gradle.kts @@ -12,6 +12,8 @@ muzzle { } dependencies { + bootstrap(project(":instrumentation:spring:spring-scheduling-3.1:bootstrap")) + // 3.2.3 is the first version with which the tests will run. Lower versions require other // classes and packages to be imported. Versions 3.1.0+ work with the instrumentation. library("org.springframework:spring-context:3.1.0.RELEASE") diff --git a/instrumentation/spring/spring-scheduling-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/scheduling/TaskSchedulerInstrumentation.java b/instrumentation/spring/spring-scheduling-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/scheduling/TaskSchedulerInstrumentation.java index db6997f25e..0fecd8f7eb 100644 --- a/instrumentation/spring/spring-scheduling-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/scheduling/TaskSchedulerInstrumentation.java +++ b/instrumentation/spring/spring-scheduling-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/scheduling/TaskSchedulerInstrumentation.java @@ -10,6 +10,7 @@ import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import io.opentelemetry.javaagent.bootstrap.spring.SpringSchedulingTaskTracing; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import net.bytebuddy.asm.Advice; @@ -34,7 +35,9 @@ public class TaskSchedulerInstrumentation implements TypeInstrumentation { @Advice.OnMethodEnter(suppress = Throwable.class) public static void onSchedule(@Advice.Argument(value = 0, readOnly = false) Runnable runnable) { - runnable = SpringSchedulingRunnableWrapper.wrapIfNeeded(runnable); + if (SpringSchedulingTaskTracing.wrappingEnabled()) { + runnable = SpringSchedulingRunnableWrapper.wrapIfNeeded(runnable); + } } } } diff --git a/settings.gradle.kts b/settings.gradle.kts index f499dca4c8..c55cbb8044 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -445,6 +445,7 @@ hideFromDependabot(":instrumentation:spring:spring-kafka-2.7:library") hideFromDependabot(":instrumentation:spring:spring-kafka-2.7:testing") hideFromDependabot(":instrumentation:spring:spring-rabbit-1.0:javaagent") hideFromDependabot(":instrumentation:spring:spring-rmi-4.0:javaagent") +hideFromDependabot(":instrumentation:spring:spring-scheduling-3.1:bootstrap") hideFromDependabot(":instrumentation:spring:spring-scheduling-3.1:javaagent") hideFromDependabot(":instrumentation:spring:spring-web:spring-web-3.1:javaagent") hideFromDependabot(":instrumentation:spring:spring-web:spring-web-3.1:library")