diff --git a/dd-java-agent/instrumentation/grpc-1.5/build.gradle b/dd-java-agent/instrumentation/grpc-1.5/build.gradle index 8c0db536c82..206eed5cb4f 100644 --- a/dd-java-agent/instrumentation/grpc-1.5/build.gradle +++ b/dd-java-agent/instrumentation/grpc-1.5/build.gradle @@ -39,7 +39,7 @@ dependencies { testImplementation group: 'io.grpc', name: 'grpc-protobuf', version: grpcVersion testImplementation group: 'io.grpc', name: 'grpc-stub', version: grpcVersion testImplementation group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2' - testImplementation project(':dd-java-agent:agent-debugger') + testImplementation project(':dd-java-agent:agent-debugger:debugger-bootstrap') testImplementation libs.bundles.mockito latestDepTestImplementation sourceSets.test.output // include the protobuf generated classes diff --git a/dd-java-agent/instrumentation/grpc-1.5/src/test/groovy/GrpcCodeOriginTest.groovy b/dd-java-agent/instrumentation/grpc-1.5/src/test/groovy/GrpcCodeOriginTest.groovy index fb1204ae45e..137ef1809f3 100644 --- a/dd-java-agent/instrumentation/grpc-1.5/src/test/groovy/GrpcCodeOriginTest.groovy +++ b/dd-java-agent/instrumentation/grpc-1.5/src/test/groovy/GrpcCodeOriginTest.groovy @@ -1,22 +1,9 @@ -import com.datadog.debugger.agent.ClassesToRetransformFinder -import com.datadog.debugger.agent.Configuration -import com.datadog.debugger.agent.ConfigurationUpdater -import com.datadog.debugger.agent.DebuggerTransformer -import com.datadog.debugger.agent.DenyListHelper -import com.datadog.debugger.agent.JsonSnapshotSerializer -import com.datadog.debugger.codeorigin.DefaultCodeOriginRecorder -import com.datadog.debugger.instrumentation.InstrumentationResult -import com.datadog.debugger.probe.ProbeDefinition -import com.datadog.debugger.sink.DebuggerSink -import com.datadog.debugger.sink.ProbeStatusSink +import datadog.trace.bootstrap.debugger.DebuggerContext.CodeOriginRecorder import com.google.common.util.concurrent.MoreExecutors import datadog.trace.agent.test.naming.VersionedNamingTestBase -import datadog.trace.api.Config import datadog.trace.api.DDSpanTypes -import datadog.trace.api.DDTags import datadog.trace.bootstrap.debugger.DebuggerContext import datadog.trace.bootstrap.instrumentation.api.Tags -import datadog.trace.util.AgentTaskScheduler import example.GreeterGrpc import example.Helloworld import io.grpc.BindableService @@ -25,7 +12,7 @@ import io.grpc.Server import io.grpc.inprocess.InProcessChannelBuilder import io.grpc.inprocess.InProcessServerBuilder import io.grpc.stub.StreamObserver -import net.bytebuddy.agent.ByteBuddyAgent +import org.mockito.internal.util.MockUtil import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.Executors @@ -33,12 +20,10 @@ import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicReference import static datadog.trace.api.config.TraceInstrumentationConfig.* -import static datadog.trace.util.AgentThreadFactory.AgentThread.TASK_SCHEDULER -import static java.lang.String.format -import static org.mockito.Mockito.mock -import static org.mockito.Mockito.when +import org.mockito.Mockito abstract class GrpcCodeOriginTest extends VersionedNamingTestBase { + private CodeOriginRecorder codeOriginRecorder @Override final String service() { @@ -81,79 +66,78 @@ abstract class GrpcCodeOriginTest extends VersionedNamingTestBase { def error = new AtomicReference() BindableService greeter = new GreeterGrpc.GreeterImplBase() { - @Override - StreamObserver conversation(StreamObserver observer) { - return new StreamObserver() { - @Override - void onNext(Helloworld.Response value) { - - serverReceived << value.message - - (1..msgCount).each { - if (TEST_TRACER.activeScope().isAsyncPropagating()) { - observer.onNext(value) - } else { - observer.onError(new IllegalStateException("not async propagating!")) + @Override + StreamObserver conversation(StreamObserver observer) { + return new StreamObserver() { + @Override + void onNext(Helloworld.Response value) { + + serverReceived << value.message + + (1..msgCount).each { + if (TEST_TRACER.activeScope().isAsyncPropagating()) { + observer.onNext(value) + } else { + observer.onError(new IllegalStateException("not async propagating!")) + } + } } - } - } - @Override - void onError(Throwable t) { - if (TEST_TRACER.activeScope().isAsyncPropagating()) { - error.set(t) - observer.onError(t) - } else { - observer.onError(new IllegalStateException("not async propagating!")) - } - } + @Override + void onError(Throwable t) { + if (TEST_TRACER.activeScope().isAsyncPropagating()) { + error.set(t) + observer.onError(t) + } else { + observer.onError(new IllegalStateException("not async propagating!")) + } + } - @Override - void onCompleted() { - if (TEST_TRACER.activeScope().isAsyncPropagating()) { - observer.onCompleted() - } else { - observer.onError(new IllegalStateException("not async propagating!")) + @Override + void onCompleted() { + if (TEST_TRACER.activeScope().isAsyncPropagating()) { + observer.onCompleted() + } else { + observer.onError(new IllegalStateException("not async propagating!")) + } + } } - } } } - } Server server = InProcessServerBuilder.forName(getClass().name).addService(greeter) - .executor(directExecutor ? MoreExecutors.directExecutor() : Executors.newCachedThreadPool()) - .build().start() + .executor(directExecutor ? MoreExecutors.directExecutor() : Executors.newCachedThreadPool()) + .build().start() - Thread.sleep(1000) ManagedChannel channel = InProcessChannelBuilder.forName(getClass().name).build() GreeterGrpc.GreeterStub client = GreeterGrpc.newStub(channel).withWaitForReady() when: def streamObserver = client.conversation(new StreamObserver() { - @Override - void onNext(Helloworld.Response value) { - if (TEST_TRACER.activeScope().isAsyncPropagating()) { - clientReceived << value.message - } else { - error.set(new IllegalStateException("not async propagating!")) + @Override + void onNext(Helloworld.Response value) { + if (TEST_TRACER.activeScope().isAsyncPropagating()) { + clientReceived << value.message + } else { + error.set(new IllegalStateException("not async propagating!")) + } } - } - @Override - void onError(Throwable t) { - if (TEST_TRACER.activeScope().isAsyncPropagating()) { - error.set(t) - } else { - error.set(new IllegalStateException("not async propagating!")) + @Override + void onError(Throwable t) { + if (TEST_TRACER.activeScope().isAsyncPropagating()) { + error.set(t) + } else { + error.set(new IllegalStateException("not async propagating!")) + } } - } - @Override - void onCompleted() { - if (!TEST_TRACER.activeScope().isAsyncPropagating()) { - error.set(new IllegalStateException("not async propagating!")) + @Override + void onCompleted() { + if (!TEST_TRACER.activeScope().isAsyncPropagating()) { + error.set(new IllegalStateException("not async propagating!")) + } } - } - }) + }) clientRange.each { def message = Helloworld.Response.newBuilder().setMessage("call $it").build() @@ -172,6 +156,9 @@ abstract class GrpcCodeOriginTest extends VersionedNamingTestBase { } }.flatten().sort() + + def invocations = MockUtil.getInvocationContainer(codeOriginRecorder) + assert invocations.invocations.stream().anyMatch { it.method.name == "captureCodeOrigin" } assertTraces(2) { trace((hasClientMessageSpans() ? clientMessageCount * serverMessageCount : 0) + 1) { span { @@ -220,14 +207,7 @@ abstract class GrpcCodeOriginTest extends VersionedNamingTestBase { "$Tags.COMPONENT" "grpc-server" "$Tags.SPAN_KIND" Tags.SPAN_KIND_SERVER "status.code" "OK" - isPresent(DDTags.DD_CODE_ORIGIN_TYPE) - isPresent(format(DDTags.DD_CODE_ORIGIN_FRAME, 0, "signature")) - for (i in 0..<8) { - for (label in ["file", "line", "method", "type"]) { - isPresent(format(DDTags.DD_CODE_ORIGIN_FRAME, i, label)) - } - } defaultTags(true) } } @@ -273,35 +253,8 @@ abstract class GrpcCodeOriginTest extends VersionedNamingTestBase { void codeOriginSetup() { injectSysConfig(CODE_ORIGIN_FOR_SPANS_ENABLED, "true", true) - - def configuration = Configuration.builder() - .setService("grpc code origin test") - .build() - - def config = mock(Config.class) - when(config.isDebuggerEnabled()).thenReturn(true) - when(config.isDebuggerClassFileDumpEnabled()).thenReturn(true) - when(config.isDebuggerVerifyByteCode()).thenReturn(false) - when(config.getFinalDebuggerSnapshotUrl()) - .thenReturn("http://localhost:8126/debugger/v1/input") - when(config.getFinalDebuggerSymDBUrl()).thenReturn("http://localhost:8126/symdb/v1/input") - when(config.getDebuggerCodeOriginMaxUserFrames()).thenReturn(8) - - def probeStatusSink = mock(ProbeStatusSink.class) - - def sink = new DebuggerSink(config, probeStatusSink) - def configurationUpdater = new ConfigurationUpdater(INSTRUMENTATION, DebuggerTransformer::new, config, sink, new ClassesToRetransformFinder()) - - def currentTransformer = new DebuggerTransformer(config, configuration, { - ProbeDefinition definition, InstrumentationResult result -> - }, sink) - INSTRUMENTATION.addTransformer(currentTransformer) - - DebuggerContext.initProbeResolver(configurationUpdater) - DebuggerContext.initClassFilter(new DenyListHelper(null)) - DebuggerContext.initValueSerializer(new JsonSnapshotSerializer()) - - DebuggerContext.initCodeOrigin(new DefaultCodeOriginRecorder(config, configurationUpdater)) + codeOriginRecorder = Mockito.mock(CodeOriginRecorder) + DebuggerContext.initCodeOrigin(codeOriginRecorder) } }