diff --git a/instrumentation-api/build.gradle.kts b/instrumentation-api/build.gradle.kts index b3b901763645..876742ff1043 100644 --- a/instrumentation-api/build.gradle.kts +++ b/instrumentation-api/build.gradle.kts @@ -20,6 +20,7 @@ dependencies { testImplementation(project(":testing-common")) testImplementation("io.opentelemetry:opentelemetry-sdk-testing") + testImplementation("io.opentelemetry:opentelemetry-exporter-common") testImplementation("org.junit-pioneer:junit-pioneer") jmhImplementation(project(":instrumentation-api-semconv")) diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java index ff1f5d08539a..8c68cd0890d4 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java @@ -354,7 +354,8 @@ private String getSchemaUrl() { } SpanSuppressor buildSpanSuppressor() { - return spanSuppressionStrategy.create(getSpanKeysFromAttributesExtractors()); + return new SpanSuppressors.ByContextKey( + spanSuppressionStrategy.create(getSpanKeysFromAttributesExtractors())); } private Set getSpanKeysFromAttributesExtractors() { diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/SpanSuppressors.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/SpanSuppressors.java index 0867f4b2febb..14748f778338 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/SpanSuppressors.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/SpanSuppressors.java @@ -10,6 +10,8 @@ import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.internal.SpanKey; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Map; import java.util.Set; @@ -85,4 +87,48 @@ public boolean shouldSuppress(Context parentContext, SpanKind spanKind) { return true; } } + + static class ByContextKey implements SpanSuppressor { + private final SpanSuppressor delegate; + private final Method shouldSuppressInstrumentation; + + ByContextKey(SpanSuppressor delegate) { + this.delegate = delegate; + Method shouldSuppressInstrumentation; + try { + Class instrumentationUtil = + Class.forName("io.opentelemetry.exporter.internal.InstrumentationUtil"); + shouldSuppressInstrumentation = + instrumentationUtil.getDeclaredMethod("shouldSuppressInstrumentation", Context.class); + } catch (ClassNotFoundException | NoSuchMethodException e) { + shouldSuppressInstrumentation = null; + } + this.shouldSuppressInstrumentation = shouldSuppressInstrumentation; + } + + @Override + public Context storeInContext(Context context, SpanKind spanKind, Span span) { + return delegate.storeInContext(context, spanKind, span); + } + + @Override + public boolean shouldSuppress(Context parentContext, SpanKind spanKind) { + if (suppressByContextKey(parentContext)) { + return true; + } + return delegate.shouldSuppress(parentContext, spanKind); + } + + private boolean suppressByContextKey(Context context) { + if (shouldSuppressInstrumentation == null) { + return false; + } + + try { + return (boolean) shouldSuppressInstrumentation.invoke(null, context); + } catch (IllegalAccessException | InvocationTargetException e) { + return false; + } + } + } } diff --git a/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/SpanSuppressionStrategyTest.java b/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/SpanSuppressionStrategyTest.java index 1593c4efde82..6ec5d802f874 100644 --- a/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/SpanSuppressionStrategyTest.java +++ b/instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/SpanSuppressionStrategyTest.java @@ -16,6 +16,7 @@ import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.context.Context; +import io.opentelemetry.exporter.internal.InstrumentationUtil; import io.opentelemetry.instrumentation.api.internal.SpanKey; import java.util.HashSet; import java.util.Set; @@ -157,4 +158,24 @@ void semconv_shouldNotSuppressContextWithPartiallyDifferentSpanKeys() { assertFalse(suppressor.shouldSuppress(context, SpanKind.SERVER)); } + + @Test + void context_shouldSuppressWhenKeyIsAvailableAndTrue() { + InstrumentationUtil.suppressInstrumentation( + () -> { + SpanSuppressor suppressor = + new SpanSuppressors.ByContextKey(SpanSuppressionStrategy.NONE.create(emptySet())); + + assertTrue(suppressor.shouldSuppress(Context.current(), SpanKind.CLIENT)); + }); + } + + @Test + void context_shouldNotSuppressWhenKeyIsNotAvailable() { + Context context = Context.current(); + SpanSuppressor suppressor = + new SpanSuppressors.ByContextKey(SpanSuppressionStrategy.NONE.create(emptySet())); + + assertFalse(suppressor.shouldSuppress(context, SpanKind.CLIENT)); + } }