From f3cbf25a89c2373d76050328d651bc1526f15de7 Mon Sep 17 00:00:00 2001 From: Mateusz Rzeszutek Date: Thu, 4 Nov 2021 18:23:51 +0100 Subject: [PATCH] Migrate opentelemetry-api testing module to Instrumenter API (#4580) --- .../src/test/groovy/ContextBridgeTest.groovy | 12 --- .../src/main/java/AgentSpanTesting.java | 8 -- .../java/AgentSpanTestingInstrumentation.java | 52 ++--------- ...AgentSpanTestingInstrumentationModule.java | 2 +- .../java/AgentSpanTestingInstrumenter.java | 89 +++++++++++++++++++ .../src/main/java/AgentSpanTestingTracer.java | 85 ------------------ 6 files changed, 96 insertions(+), 152 deletions(-) create mode 100644 instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTestingInstrumenter.java delete mode 100644 instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTestingTracer.java diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/test/groovy/ContextBridgeTest.groovy b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/test/groovy/ContextBridgeTest.groovy index e64e37639a..5d0afc3384 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/test/groovy/ContextBridgeTest.groovy +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/test/groovy/ContextBridgeTest.groovy @@ -11,7 +11,6 @@ import io.opentelemetry.context.ContextKey import io.opentelemetry.extension.annotations.WithSpan import io.opentelemetry.instrumentation.api.instrumenter.SpanKey import io.opentelemetry.instrumentation.api.tracer.ClientSpan -import io.opentelemetry.instrumentation.api.tracer.ConsumerSpan import io.opentelemetry.instrumentation.api.tracer.ServerSpan import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification @@ -161,17 +160,6 @@ class ContextBridgeTest extends AgentInstrumentationSpecification { } } - def "test consumer span bridge"() { - expect: - AgentSpanTesting.runWithConsumerSpan("consumer") { - assert Span.current() != null - assert ConsumerSpan.fromContextOrNull(Context.current()) != null - runWithSpan("internal") { - assert ConsumerSpan.fromContextOrNull(Context.current()) != null - } - } - } - def "test client span bridge"() { expect: AgentSpanTesting.runWithClientSpan("client") { diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTesting.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTesting.java index 835fee2281..c3b702923d 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTesting.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTesting.java @@ -13,14 +13,6 @@ public class AgentSpanTesting { runnable.run(); } - /** - * Runs the provided {@code runnable} inside the scope of an CONSUMER span with name {@code - * spanName}. - */ - public static void runWithConsumerSpan(String spanName, Runnable runnable) { - runnable.run(); - } - /** * Runs the provided {@code runnable} inside the scope of an CLIENT span with name {@code * spanName}. diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTestingInstrumentation.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTestingInstrumentation.java index a9ee221ff4..ae254d22d5 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTestingInstrumentation.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTestingInstrumentation.java @@ -24,8 +24,6 @@ public class AgentSpanTestingInstrumentation implements TypeInstrumentation { public void transform(TypeTransformer transformer) { transformer.applyAdviceToMethod( named("runWithServerSpan"), this.getClass().getName() + "$RunWithServerSpanAdvice"); - transformer.applyAdviceToMethod( - named("runWithConsumerSpan"), this.getClass().getName() + "$RunWithConsumerSpanAdvice"); transformer.applyAdviceToMethod( named("runWithClientSpan"), this.getClass().getName() + "$RunWithClientSpanAdvice"); transformer.applyAdviceToMethod( @@ -40,7 +38,7 @@ public class AgentSpanTestingInstrumentation implements TypeInstrumentation { @Advice.Argument(0) String spanName, @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { - context = AgentSpanTestingTracer.tracer().startServerSpan(spanName); + context = AgentSpanTestingInstrumenter.startServerSpan(spanName); scope = context.makeCurrent(); } @@ -50,37 +48,7 @@ public class AgentSpanTestingInstrumentation implements TypeInstrumentation { @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { scope.close(); - if (throwable != null) { - AgentSpanTestingTracer.tracer().endExceptionally(context, throwable); - } else { - AgentSpanTestingTracer.tracer().end(context); - } - } - } - - @SuppressWarnings("unused") - public static class RunWithConsumerSpanAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) String spanName, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - context = AgentSpanTestingTracer.tracer().startConsumerSpan(spanName); - scope = context.makeCurrent(); - } - - @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void onExit( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - scope.close(); - if (throwable != null) { - AgentSpanTestingTracer.tracer().endExceptionally(context, throwable); - } else { - AgentSpanTestingTracer.tracer().end(context); - } + AgentSpanTestingInstrumenter.end(context, throwable); } } @@ -92,7 +60,7 @@ public class AgentSpanTestingInstrumentation implements TypeInstrumentation { @Advice.Argument(0) String spanName, @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { - context = AgentSpanTestingTracer.tracer().startClientSpan(spanName); + context = AgentSpanTestingInstrumenter.startClientSpan(spanName); scope = context.makeCurrent(); } @@ -102,11 +70,7 @@ public class AgentSpanTestingInstrumentation implements TypeInstrumentation { @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { scope.close(); - if (throwable != null) { - AgentSpanTestingTracer.tracer().endExceptionally(context, throwable); - } else { - AgentSpanTestingTracer.tracer().end(context); - } + AgentSpanTestingInstrumenter.end(context, throwable); } } @@ -118,7 +82,7 @@ public class AgentSpanTestingInstrumentation implements TypeInstrumentation { @Advice.Argument(0) String spanName, @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { - context = AgentSpanTestingTracer.tracer().startSpanWithAllKeys(spanName); + context = AgentSpanTestingInstrumenter.startSpanWithAllKeys(spanName); scope = context.makeCurrent(); } @@ -128,11 +92,7 @@ public class AgentSpanTestingInstrumentation implements TypeInstrumentation { @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { scope.close(); - if (throwable != null) { - AgentSpanTestingTracer.tracer().endExceptionally(context, throwable); - } else { - AgentSpanTestingTracer.tracer().end(context); - } + AgentSpanTestingInstrumenter.end(context, throwable); } } } diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTestingInstrumentationModule.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTestingInstrumentationModule.java index 131b46b7cb..76fe713249 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTestingInstrumentationModule.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTestingInstrumentationModule.java @@ -18,7 +18,7 @@ public class AgentSpanTestingInstrumentationModule extends InstrumentationModule @Override public boolean isHelperClass(String className) { - return className.startsWith("AgentSpanTestingTracer"); + return className.startsWith("AgentSpanTestingInstrumenter"); } @Override diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTestingInstrumenter.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTestingInstrumenter.java new file mode 100644 index 0000000000..e2df91dfb3 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTestingInstrumenter.java @@ -0,0 +1,89 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.ContextKey; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.SpanKey; +import java.lang.reflect.Field; + +public final class AgentSpanTestingInstrumenter { + + private static final ContextKey REQUEST_CONTEXT_KEY = + ContextKey.named("test-request-key"); + + private static final Instrumenter INSTRUMENTER = + Instrumenter.builder( + GlobalOpenTelemetry.get(), "test", request -> request.name) + .addContextCustomizer( + (context, request, startAttributes) -> context.with(REQUEST_CONTEXT_KEY, request)) + .newInstrumenter(request -> request.kind); + + public static Context startServerSpan(String name) { + return start(name, SpanKind.SERVER); + } + + public static Context startClientSpan(String name) { + return start(name, SpanKind.CLIENT); + } + + public static Context startSpanWithAllKeys(String name) { + Context context = start(name, SpanKind.INTERNAL); + Span span = Span.fromContext(context); + for (SpanKey spanKey : SpanKeyAccess.getSpanKeys()) { + context = spanKey.storeInContext(context, span); + } + return context; + } + + private static Context start(String name, SpanKind kind) { + return INSTRUMENTER.start(Context.current(), new Request(name, kind)); + } + + public static void end(Context context, Throwable error) { + INSTRUMENTER.end(context, context.get(REQUEST_CONTEXT_KEY), null, error); + } + + private static final class Request { + private final String name; + private final SpanKind kind; + + public Request(String name, SpanKind kind) { + this.name = name; + this.kind = kind; + } + } + + private static final class SpanKeyAccess { + + public static SpanKey[] getSpanKeys() { + return new SpanKey[] { + SpanKey.SERVER, + getSpanKeyByName("HTTP_CLIENT"), + getSpanKeyByName("RPC_CLIENT"), + getSpanKeyByName("DB_CLIENT"), + SpanKey.ALL_CLIENTS, + getSpanKeyByName("PRODUCER"), + getSpanKeyByName("CONSUMER_RECEIVE"), + getSpanKeyByName("CONSUMER_PROCESS") + }; + } + + private static SpanKey getSpanKeyByName(String name) { + try { + Field field = SpanKey.class.getDeclaredField(name); + field.setAccessible(true); + return (SpanKey) field.get(name); + } catch (NoSuchFieldException | IllegalAccessException exception) { + throw new IllegalStateException("Failed to find span key named " + name, exception); + } + } + } + + private AgentSpanTestingInstrumenter() {} +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTestingTracer.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTestingTracer.java deleted file mode 100644 index 44939a45ad..0000000000 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/testing/src/main/java/AgentSpanTestingTracer.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanBuilder; -import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.context.Context; -import io.opentelemetry.instrumentation.api.instrumenter.SpanKey; -import io.opentelemetry.instrumentation.api.tracer.BaseTracer; -import java.lang.reflect.Field; - -public class AgentSpanTestingTracer extends BaseTracer { - private static final AgentSpanTestingTracer TRACER = new AgentSpanTestingTracer(); - - private AgentSpanTestingTracer() { - super(GlobalOpenTelemetry.get()); - } - - public static AgentSpanTestingTracer tracer() { - return TRACER; - } - - public Context startServerSpan(String name) { - Context parentContext = Context.current(); - SpanBuilder spanBuilder = spanBuilder(parentContext, name, SpanKind.SERVER); - return withServerSpan(parentContext, spanBuilder.startSpan()); - } - - public Context startConsumerSpan(String name) { - Context parentContext = Context.current(); - SpanBuilder spanBuilder = spanBuilder(parentContext, name, SpanKind.CONSUMER); - return withConsumerSpan(parentContext, spanBuilder.startSpan()); - } - - public Context startClientSpan(String name) { - Context parentContext = Context.current(); - SpanBuilder spanBuilder = spanBuilder(parentContext, name, SpanKind.CLIENT); - return withClientSpan(parentContext, spanBuilder.startSpan()); - } - - public Context startSpanWithAllKeys(String name) { - Context parentContext = Context.current(); - SpanBuilder spanBuilder = spanBuilder(parentContext, name, SpanKind.INTERNAL); - Span span = spanBuilder.startSpan(); - Context newContext = parentContext.with(span); - for (SpanKey spanKey : SpanKeyAccess.getSpanKeys()) { - newContext = spanKey.storeInContext(newContext, span); - } - return newContext; - } - - @Override - protected String getInstrumentationName() { - return "agent-span-test-instrumentation"; - } - - private static class SpanKeyAccess { - - public static SpanKey[] getSpanKeys() { - return new SpanKey[] { - SpanKey.SERVER, - getSpanKeyByName("HTTP_CLIENT"), - getSpanKeyByName("RPC_CLIENT"), - getSpanKeyByName("DB_CLIENT"), - SpanKey.ALL_CLIENTS, - getSpanKeyByName("PRODUCER"), - getSpanKeyByName("CONSUMER_RECEIVE"), - getSpanKeyByName("CONSUMER_PROCESS") - }; - } - - private static SpanKey getSpanKeyByName(String name) { - try { - Field field = SpanKey.class.getDeclaredField(name); - field.setAccessible(true); - return (SpanKey) field.get(name); - } catch (NoSuchFieldException | IllegalAccessException exception) { - throw new IllegalStateException("Failed to find span key named " + name, exception); - } - } - } -}