Skip to content

Commit

Permalink
Only check that the first frame tags are present. (#8049)
Browse files Browse the repository at this point in the history
mock the code origin recorder and simply check for invocations
restrict the test dep to a narrower scope
  • Loading branch information
evanchooly authored Dec 3, 2024
1 parent 64347d6 commit 7698f2f
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 111 deletions.
2 changes: 1 addition & 1 deletion dd-java-agent/instrumentation/grpc-1.5/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -25,20 +12,18 @@ 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
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() {
Expand Down Expand Up @@ -81,79 +66,78 @@ abstract class GrpcCodeOriginTest extends VersionedNamingTestBase {
def error = new AtomicReference()

BindableService greeter = new GreeterGrpc.GreeterImplBase() {
@Override
StreamObserver<Helloworld.Response> conversation(StreamObserver<Helloworld.Response> observer) {
return new StreamObserver<Helloworld.Response>() {
@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<Helloworld.Response> conversation(StreamObserver<Helloworld.Response> observer) {
return new StreamObserver<Helloworld.Response>() {
@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<Helloworld.Response>() {
@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()
Expand All @@ -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 {
Expand Down Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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)
}
}

Expand Down

0 comments on commit 7698f2f

Please sign in to comment.