diff --git a/instrumentation/reactor-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/HooksInstrumentation.java b/instrumentation/reactor-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/HooksInstrumentation.java index 425f6b355279..73d62f973576 100644 --- a/instrumentation/reactor-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/HooksInstrumentation.java +++ b/instrumentation/reactor-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/HooksInstrumentation.java @@ -8,6 +8,7 @@ import static net.bytebuddy.matcher.ElementMatchers.isTypeInitializer; import static net.bytebuddy.matcher.ElementMatchers.named; +import io.opentelemetry.instrumentation.api.config.Config; import io.opentelemetry.instrumentation.reactor.TracingOperator; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; @@ -31,7 +32,13 @@ public void transform(TypeTransformer transformer) { public static class ResetOnEachOperatorAdvice { @Advice.OnMethodExit(suppress = Throwable.class) public static void postStaticInitializer() { - TracingOperator.registerOnEachOperator(); + TracingOperator.newBuilder() + .setCaptureExperimentalSpanAttributes( + Config.get() + .getBooleanProperty( + "otel.instrumentation.reactor.experimental-span-attributes", false)) + .build() + .registerOnEachOperator(); } } } diff --git a/instrumentation/reactor-3.1/library/src/main/java/io/opentelemetry/instrumentation/reactor/TracingOperator.java b/instrumentation/reactor-3.1/library/src/main/java/io/opentelemetry/instrumentation/reactor/TracingOperator.java index f2723bd45a14..532db89b7b93 100644 --- a/instrumentation/reactor-3.1/library/src/main/java/io/opentelemetry/instrumentation/reactor/TracingOperator.java +++ b/instrumentation/reactor-3.1/library/src/main/java/io/opentelemetry/instrumentation/reactor/TracingOperator.java @@ -23,7 +23,6 @@ package io.opentelemetry.instrumentation.reactor; import io.opentelemetry.context.Context; -import io.opentelemetry.instrumentation.api.config.Config; import io.opentelemetry.instrumentation.api.tracer.async.AsyncSpanEndStrategies; import java.util.function.BiFunction; import java.util.function.Function; @@ -35,7 +34,21 @@ import reactor.core.publisher.Operators; /** Based on Spring Sleuth's Reactor instrumentation. */ -public class TracingOperator { +public final class TracingOperator { + + public static TracingOperator create() { + return newBuilder().build(); + } + + public static TracingOperatorBuilder newBuilder() { + return new TracingOperatorBuilder(); + } + + private final boolean captureExperimentalSpanAttributes; + + TracingOperator(boolean captureExperimentalSpanAttributes) { + this.captureExperimentalSpanAttributes = captureExperimentalSpanAttributes; + } /** * Registers a hook that applies to every operator, propagating {@link Context} to downstream @@ -43,20 +56,17 @@ public class TracingOperator { * reactive stream. This should generally be called in a static initializer block in your * application. */ - public static void registerOnEachOperator() { + public void registerOnEachOperator() { Hooks.onEachOperator(TracingSubscriber.class.getName(), tracingLift()); AsyncSpanEndStrategies.getInstance() .registerStrategy( ReactorAsyncSpanEndStrategy.newBuilder() - .setCaptureExperimentalSpanAttributes( - Config.get() - .getBooleanProperty( - "otel.instrumentation.reactor.experimental-span-attributes", false)) + .setCaptureExperimentalSpanAttributes(captureExperimentalSpanAttributes) .build()); } /** Unregisters the hook registered by {@link #registerOnEachOperator()}. */ - public static void resetOnEachOperator() { + public void resetOnEachOperator() { Hooks.resetOnEachOperator(TracingSubscriber.class.getName()); AsyncSpanEndStrategies.getInstance().unregisterStrategy(ReactorAsyncSpanEndStrategy.class); } diff --git a/instrumentation/reactor-3.1/library/src/main/java/io/opentelemetry/instrumentation/reactor/TracingOperatorBuilder.java b/instrumentation/reactor-3.1/library/src/main/java/io/opentelemetry/instrumentation/reactor/TracingOperatorBuilder.java new file mode 100644 index 000000000000..99889cfa3cc2 --- /dev/null +++ b/instrumentation/reactor-3.1/library/src/main/java/io/opentelemetry/instrumentation/reactor/TracingOperatorBuilder.java @@ -0,0 +1,22 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.reactor; + +public final class TracingOperatorBuilder { + private boolean captureExperimentalSpanAttributes; + + TracingOperatorBuilder() {} + + public TracingOperatorBuilder setCaptureExperimentalSpanAttributes( + boolean captureExperimentalSpanAttributes) { + this.captureExperimentalSpanAttributes = captureExperimentalSpanAttributes; + return this; + } + + public TracingOperator build() { + return new TracingOperator(captureExperimentalSpanAttributes); + } +} diff --git a/instrumentation/reactor-3.1/library/src/test/groovy/io/opentelemetry/instrumentation/reactor/HooksTest.groovy b/instrumentation/reactor-3.1/library/src/test/groovy/io/opentelemetry/instrumentation/reactor/HooksTest.groovy index 3cf2af8a5fbe..7760696bec54 100644 --- a/instrumentation/reactor-3.1/library/src/test/groovy/io/opentelemetry/instrumentation/reactor/HooksTest.groovy +++ b/instrumentation/reactor-3.1/library/src/test/groovy/io/opentelemetry/instrumentation/reactor/HooksTest.groovy @@ -14,6 +14,7 @@ class HooksTest extends LibraryInstrumentationSpecification { def "can reset out hooks"() { setup: + def underTest = TracingOperator.create() AtomicReference subscriber = new AtomicReference<>() when: "no hook registered" @@ -23,14 +24,14 @@ class HooksTest extends LibraryInstrumentationSpecification { !(subscriber.get() instanceof TracingSubscriber) when: "hook registered" - TracingOperator.registerOnEachOperator() + underTest.registerOnEachOperator() new CapturingMono(subscriber).map { it + 1 }.subscribe() then: subscriber.get() instanceof TracingSubscriber when: "hook reset" - TracingOperator.resetOnEachOperator() + underTest.resetOnEachOperator() new CapturingMono(subscriber).map { it + 1 }.subscribe() then: diff --git a/instrumentation/reactor-3.1/library/src/test/groovy/io/opentelemetry/instrumentation/reactor/SubscriptionTest.groovy b/instrumentation/reactor-3.1/library/src/test/groovy/io/opentelemetry/instrumentation/reactor/SubscriptionTest.groovy index 41ad20821707..9bfc899474a6 100644 --- a/instrumentation/reactor-3.1/library/src/test/groovy/io/opentelemetry/instrumentation/reactor/SubscriptionTest.groovy +++ b/instrumentation/reactor-3.1/library/src/test/groovy/io/opentelemetry/instrumentation/reactor/SubscriptionTest.groovy @@ -6,13 +6,17 @@ package io.opentelemetry.instrumentation.reactor import io.opentelemetry.instrumentation.test.LibraryTestTrait +import spock.lang.Shared class SubscriptionTest extends AbstractSubscriptionTest implements LibraryTestTrait { + @Shared + TracingOperator tracingOperator = TracingOperator.create() + def setupSpec() { - TracingOperator.registerOnEachOperator() + tracingOperator.registerOnEachOperator() } def cleanupSpec() { - TracingOperator.resetOnEachOperator() + tracingOperator.resetOnEachOperator() } } diff --git a/instrumentation/rxjava/rxjava-2.0/javaagent/src/main/java/io/opentelemetry/instrumentation/rxjava2/TracingAssemblyActivation.java b/instrumentation/rxjava/rxjava-2.0/javaagent/src/main/java/io/opentelemetry/instrumentation/rxjava2/TracingAssemblyActivation.java index c0fbbe2359a9..b0735d346abc 100644 --- a/instrumentation/rxjava/rxjava-2.0/javaagent/src/main/java/io/opentelemetry/instrumentation/rxjava2/TracingAssemblyActivation.java +++ b/instrumentation/rxjava/rxjava-2.0/javaagent/src/main/java/io/opentelemetry/instrumentation/rxjava2/TracingAssemblyActivation.java @@ -5,6 +5,7 @@ package io.opentelemetry.instrumentation.rxjava2; +import io.opentelemetry.instrumentation.api.config.Config; import java.util.concurrent.atomic.AtomicBoolean; public final class TracingAssemblyActivation { @@ -19,7 +20,13 @@ protected AtomicBoolean computeValue(Class type) { public static void activate(Class clz) { if (activated.get(clz).compareAndSet(false, true)) { - TracingAssembly.enable(); + TracingAssembly.newBuilder() + .setCaptureExperimentalSpanAttributes( + Config.get() + .getBooleanProperty( + "otel.instrumentation.rxjava.experimental-span-attributes", false)) + .build() + .enable(); } } diff --git a/instrumentation/rxjava/rxjava-2.0/library/src/main/java/io/opentelemetry/instrumentation/rxjava2/TracingAssembly.java b/instrumentation/rxjava/rxjava-2.0/library/src/main/java/io/opentelemetry/instrumentation/rxjava2/TracingAssembly.java index ca237501d93d..15f4ccc3ace1 100644 --- a/instrumentation/rxjava/rxjava-2.0/library/src/main/java/io/opentelemetry/instrumentation/rxjava2/TracingAssembly.java +++ b/instrumentation/rxjava/rxjava-2.0/library/src/main/java/io/opentelemetry/instrumentation/rxjava2/TracingAssembly.java @@ -24,7 +24,6 @@ import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.config.Config; import io.opentelemetry.instrumentation.api.tracer.async.AsyncSpanEndStrategies; import io.reactivex.Completable; import io.reactivex.CompletableObserver; @@ -90,50 +89,66 @@ public final class TracingAssembly { @GuardedBy("TracingAssembly.class") private static boolean enabled; - private TracingAssembly() {} + public static TracingAssembly create() { + return newBuilder().build(); + } - public static synchronized void enable() { - if (enabled) { - return; - } + public static TracingAssemblyBuilder newBuilder() { + return new TracingAssemblyBuilder(); + } - enableObservable(); + private final boolean captureExperimentalSpanAttributes; - enableCompletable(); + TracingAssembly(boolean captureExperimentalSpanAttributes) { + this.captureExperimentalSpanAttributes = captureExperimentalSpanAttributes; + } - enableSingle(); + public void enable() { + synchronized (TracingAssembly.class) { + if (enabled) { + return; + } - enableMaybe(); + enableObservable(); - enableFlowable(); + enableCompletable(); - enableParallel(); + enableSingle(); - enableWithSpanStrategy(); + enableMaybe(); - enabled = true; - } + enableFlowable(); - public static synchronized void disable() { - if (!enabled) { - return; + enableParallel(); + + enableWithSpanStrategy(captureExperimentalSpanAttributes); + + enabled = true; } + } - disableObservable(); + public void disable() { + synchronized (TracingAssembly.class) { + if (!enabled) { + return; + } - disableCompletable(); + disableObservable(); - disableSingle(); + disableCompletable(); - disableMaybe(); + disableSingle(); - disableFlowable(); + disableMaybe(); - disableParallel(); + disableFlowable(); - disableWithSpanStrategy(); + disableParallel(); - enabled = false; + disableWithSpanStrategy(); + + enabled = false; + } } @SuppressWarnings({"rawtypes", "unchecked"}) @@ -223,14 +238,11 @@ private static void enableMaybe() { })); } - private static void enableWithSpanStrategy() { + private static void enableWithSpanStrategy(boolean captureExperimentalSpanAttributes) { AsyncSpanEndStrategies.getInstance() .registerStrategy( RxJava2AsyncSpanEndStrategy.newBuilder() - .setCaptureExperimentalSpanAttributes( - Config.get() - .getBooleanProperty( - "otel.instrumentation.rxjava.experimental-span-attributes", false)) + .setCaptureExperimentalSpanAttributes(captureExperimentalSpanAttributes) .build()); } diff --git a/instrumentation/rxjava/rxjava-2.0/library/src/main/java/io/opentelemetry/instrumentation/rxjava2/TracingAssemblyBuilder.java b/instrumentation/rxjava/rxjava-2.0/library/src/main/java/io/opentelemetry/instrumentation/rxjava2/TracingAssemblyBuilder.java new file mode 100644 index 000000000000..050d039ff29e --- /dev/null +++ b/instrumentation/rxjava/rxjava-2.0/library/src/main/java/io/opentelemetry/instrumentation/rxjava2/TracingAssemblyBuilder.java @@ -0,0 +1,22 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.rxjava2; + +public final class TracingAssemblyBuilder { + private boolean captureExperimentalSpanAttributes; + + TracingAssemblyBuilder() {} + + public TracingAssemblyBuilder setCaptureExperimentalSpanAttributes( + boolean captureExperimentalSpanAttributes) { + this.captureExperimentalSpanAttributes = captureExperimentalSpanAttributes; + return this; + } + + public TracingAssembly build() { + return new TracingAssembly(captureExperimentalSpanAttributes); + } +} diff --git a/instrumentation/rxjava/rxjava-2.0/library/src/test/groovy/RxJava2SubscriptionTest.groovy b/instrumentation/rxjava/rxjava-2.0/library/src/test/groovy/RxJava2SubscriptionTest.groovy index 15d2f624c8ae..935e49de1e1e 100644 --- a/instrumentation/rxjava/rxjava-2.0/library/src/test/groovy/RxJava2SubscriptionTest.groovy +++ b/instrumentation/rxjava/rxjava-2.0/library/src/test/groovy/RxJava2SubscriptionTest.groovy @@ -6,10 +6,13 @@ import io.opentelemetry.instrumentation.rxjava2.AbstractRxJava2SubscriptionTest import io.opentelemetry.instrumentation.rxjava2.TracingAssembly import io.opentelemetry.instrumentation.test.LibraryTestTrait +import spock.lang.Shared class RxJava2SubscriptionTest extends AbstractRxJava2SubscriptionTest implements LibraryTestTrait { + @Shared + TracingAssembly tracingAssembly = TracingAssembly.create() def setupSpec() { - TracingAssembly.enable() + tracingAssembly.enable() } } diff --git a/instrumentation/rxjava/rxjava-2.0/library/src/test/groovy/RxJava2Test.groovy b/instrumentation/rxjava/rxjava-2.0/library/src/test/groovy/RxJava2Test.groovy index d379cbce7885..8b9ca49ea48c 100644 --- a/instrumentation/rxjava/rxjava-2.0/library/src/test/groovy/RxJava2Test.groovy +++ b/instrumentation/rxjava/rxjava-2.0/library/src/test/groovy/RxJava2Test.groovy @@ -6,10 +6,13 @@ import io.opentelemetry.instrumentation.rxjava2.AbstractRxJava2Test import io.opentelemetry.instrumentation.rxjava2.TracingAssembly import io.opentelemetry.instrumentation.test.LibraryTestTrait +import spock.lang.Shared class RxJava2Test extends AbstractRxJava2Test implements LibraryTestTrait { + @Shared + TracingAssembly tracingAssembly = TracingAssembly.create() def setupSpec() { - TracingAssembly.enable() + tracingAssembly.enable() } } diff --git a/instrumentation/rxjava/rxjava-3.0/javaagent/src/main/java/io/opentelemetry/instrumentation/rxjava3/TracingAssemblyActivation.java b/instrumentation/rxjava/rxjava-3.0/javaagent/src/main/java/io/opentelemetry/instrumentation/rxjava3/TracingAssemblyActivation.java index 92c4937e87d1..8b276353d279 100644 --- a/instrumentation/rxjava/rxjava-3.0/javaagent/src/main/java/io/opentelemetry/instrumentation/rxjava3/TracingAssemblyActivation.java +++ b/instrumentation/rxjava/rxjava-3.0/javaagent/src/main/java/io/opentelemetry/instrumentation/rxjava3/TracingAssemblyActivation.java @@ -5,6 +5,7 @@ package io.opentelemetry.instrumentation.rxjava3; +import io.opentelemetry.instrumentation.api.config.Config; import java.util.concurrent.atomic.AtomicBoolean; public final class TracingAssemblyActivation { @@ -19,7 +20,13 @@ protected AtomicBoolean computeValue(Class type) { public static void activate(Class clz) { if (activated.get(clz).compareAndSet(false, true)) { - TracingAssembly.enable(); + TracingAssembly.newBuilder() + .setCaptureExperimentalSpanAttributes( + Config.get() + .getBooleanProperty( + "otel.instrumentation.rxjava.experimental-span-attributes", false)) + .build() + .enable(); } } diff --git a/instrumentation/rxjava/rxjava-3.0/library/src/main/java/io/opentelemetry/instrumentation/rxjava3/TracingAssembly.java b/instrumentation/rxjava/rxjava-3.0/library/src/main/java/io/opentelemetry/instrumentation/rxjava3/TracingAssembly.java index 0b96ba5d299c..723daabf89f7 100644 --- a/instrumentation/rxjava/rxjava-3.0/library/src/main/java/io/opentelemetry/instrumentation/rxjava3/TracingAssembly.java +++ b/instrumentation/rxjava/rxjava-3.0/library/src/main/java/io/opentelemetry/instrumentation/rxjava3/TracingAssembly.java @@ -24,7 +24,6 @@ import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.config.Config; import io.opentelemetry.instrumentation.api.tracer.async.AsyncSpanEndStrategies; import io.reactivex.rxjava3.core.Completable; import io.reactivex.rxjava3.core.CompletableObserver; @@ -90,50 +89,66 @@ public final class TracingAssembly { @GuardedBy("TracingAssembly.class") private static boolean enabled; - private TracingAssembly() {} + public static TracingAssembly create() { + return newBuilder().build(); + } - public static synchronized void enable() { - if (enabled) { - return; - } + public static TracingAssemblyBuilder newBuilder() { + return new TracingAssemblyBuilder(); + } - enableObservable(); + private final boolean captureExperimentalSpanAttributes; - enableCompletable(); + TracingAssembly(boolean captureExperimentalSpanAttributes) { + this.captureExperimentalSpanAttributes = captureExperimentalSpanAttributes; + } - enableSingle(); + public void enable() { + synchronized (TracingAssembly.class) { + if (enabled) { + return; + } - enableMaybe(); + enableObservable(); - enableFlowable(); + enableCompletable(); - enableParallel(); + enableSingle(); - enableWithSpanStrategy(); + enableMaybe(); - enabled = true; - } + enableFlowable(); - public static synchronized void disable() { - if (!enabled) { - return; + enableParallel(); + + enableWithSpanStrategy(captureExperimentalSpanAttributes); + + enabled = true; } + } - disableObservable(); + public void disable() { + synchronized (TracingAssembly.class) { + if (!enabled) { + return; + } - disableCompletable(); + disableObservable(); - disableSingle(); + disableCompletable(); - disableMaybe(); + disableSingle(); - disableFlowable(); + disableMaybe(); - disableParallel(); + disableFlowable(); - disableWithSpanStrategy(); + disableParallel(); - enabled = false; + disableWithSpanStrategy(); + + enabled = false; + } } @SuppressWarnings({"rawtypes", "unchecked"}) @@ -221,14 +236,11 @@ private static void enableMaybe() { })); } - private static void enableWithSpanStrategy() { + private static void enableWithSpanStrategy(boolean captureExperimentalSpanAttributes) { AsyncSpanEndStrategies.getInstance() .registerStrategy( RxJava3AsyncSpanEndStrategy.newBuilder() - .setCaptureExperimentalSpanAttributes( - Config.get() - .getBooleanProperty( - "otel.instrumentation.rxjava.experimental-span-attributes", false)) + .setCaptureExperimentalSpanAttributes(captureExperimentalSpanAttributes) .build()); } diff --git a/instrumentation/rxjava/rxjava-3.0/library/src/main/java/io/opentelemetry/instrumentation/rxjava3/TracingAssemblyBuilder.java b/instrumentation/rxjava/rxjava-3.0/library/src/main/java/io/opentelemetry/instrumentation/rxjava3/TracingAssemblyBuilder.java new file mode 100644 index 000000000000..c5321a7b5f39 --- /dev/null +++ b/instrumentation/rxjava/rxjava-3.0/library/src/main/java/io/opentelemetry/instrumentation/rxjava3/TracingAssemblyBuilder.java @@ -0,0 +1,22 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.rxjava3; + +public final class TracingAssemblyBuilder { + private boolean captureExperimentalSpanAttributes; + + TracingAssemblyBuilder() {} + + public TracingAssemblyBuilder setCaptureExperimentalSpanAttributes( + boolean captureExperimentalSpanAttributes) { + this.captureExperimentalSpanAttributes = captureExperimentalSpanAttributes; + return this; + } + + public TracingAssembly build() { + return new TracingAssembly(captureExperimentalSpanAttributes); + } +} diff --git a/instrumentation/rxjava/rxjava-3.0/library/src/test/groovy/RxJava3SubscriptionTest.groovy b/instrumentation/rxjava/rxjava-3.0/library/src/test/groovy/RxJava3SubscriptionTest.groovy index 0351dae24a8c..800f5adfe1ca 100644 --- a/instrumentation/rxjava/rxjava-3.0/library/src/test/groovy/RxJava3SubscriptionTest.groovy +++ b/instrumentation/rxjava/rxjava-3.0/library/src/test/groovy/RxJava3SubscriptionTest.groovy @@ -6,10 +6,13 @@ import io.opentelemetry.instrumentation.rxjava3.AbstractRxJava3SubscriptionTest import io.opentelemetry.instrumentation.rxjava3.TracingAssembly import io.opentelemetry.instrumentation.test.LibraryTestTrait +import spock.lang.Shared class RxJava3SubscriptionTest extends AbstractRxJava3SubscriptionTest implements LibraryTestTrait { + @Shared + TracingAssembly tracingAssembly = TracingAssembly.create() def setupSpec() { - TracingAssembly.enable() + tracingAssembly.enable() } } diff --git a/instrumentation/rxjava/rxjava-3.0/library/src/test/groovy/RxJava3Test.groovy b/instrumentation/rxjava/rxjava-3.0/library/src/test/groovy/RxJava3Test.groovy index 4bcf431d69a4..24215f993fab 100644 --- a/instrumentation/rxjava/rxjava-3.0/library/src/test/groovy/RxJava3Test.groovy +++ b/instrumentation/rxjava/rxjava-3.0/library/src/test/groovy/RxJava3Test.groovy @@ -6,10 +6,13 @@ import io.opentelemetry.instrumentation.rxjava3.AbstractRxJava3Test import io.opentelemetry.instrumentation.rxjava3.TracingAssembly import io.opentelemetry.instrumentation.test.LibraryTestTrait +import spock.lang.Shared class RxJava3Test extends AbstractRxJava3Test implements LibraryTestTrait { + @Shared + TracingAssembly tracingAssembly = TracingAssembly.create() def setupSpec() { - TracingAssembly.enable() + tracingAssembly.enable() } }