diff --git a/dd-java-agent/build.gradle b/dd-java-agent/build.gradle index f05fe7ca779..de03c37d4e5 100644 --- a/dd-java-agent/build.gradle +++ b/dd-java-agent/build.gradle @@ -467,7 +467,7 @@ tasks.register('checkAgentJarSize') { doLast { // Arbitrary limit to prevent unintentional increases to the agent jar size // Raise or lower as required - assert tasks.named("shadowJar", ShadowJar).get().archiveFile.get().getAsFile().length() <= 32 * 1024 * 1024 + assert tasks.named("shadowJar", ShadowJar).get().archiveFile.get().getAsFile().length() <= 33 * 1024 * 1024 } dependsOn "shadowJar" diff --git a/dd-java-agent/instrumentation/sofarpc/build.gradle b/dd-java-agent/instrumentation/sofarpc/build.gradle new file mode 100644 index 00000000000..5e69c67bd78 --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/build.gradle @@ -0,0 +1 @@ +apply from: "$rootDir/gradle/java.gradle" diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/build.gradle b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/build.gradle new file mode 100644 index 00000000000..bb063fa43be --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/build.gradle @@ -0,0 +1,35 @@ +muzzle { + pass { + group = "com.alipay.sofa" + module = "sofa-rpc-all" + versions = "[5.0.0,)" + assertInverse = true + } +} + +apply from: "$rootDir/gradle/java.gradle" + +addTestSuiteForDir('latestDepTest', 'test') + +configurations.testRuntimeClasspath { + resolutionStrategy.force "com.google.guava:guava:32.1.3-jre" +} + +dependencies { + compileOnly group: "com.alipay.sofa", name: "sofa-rpc-all", version: "5.6.0" + + testImplementation group: "com.alipay.sofa", name: "sofa-rpc-all", version: "5.14.2" + // JAX-RS annotations required for the REST protocol test interface (@Path, @GET, etc.) + testImplementation group: "javax.ws.rs", name: "javax.ws.rs-api", version: "2.1.1" + // Required so that GrpcServerModule / GrpcClientModule are discovered via ServiceLoader + // in SofaRpcTripleWithGrpcForkedTest. + testImplementation project(':dd-java-agent:instrumentation:grpc-1.5') + testImplementation group: "io.grpc", name: "grpc-netty", version: "1.53.0" + testImplementation group: "io.grpc", name: "grpc-core", version: "1.53.0" + testImplementation group: "io.grpc", name: "grpc-stub", version: "1.53.0" + testImplementation group: "com.google.protobuf", name: "protobuf-java", version: "3.25.3" + testImplementation group: "com.alibaba", name: "fastjson", version: "1.2.83" + testImplementation group: "com.google.guava", name: "guava", version: "32.1.3-jre" + + latestDepTestImplementation group: "com.alipay.sofa", name: "sofa-rpc-all", version: "+" +} diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/gradle.lockfile b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/gradle.lockfile new file mode 100644 index 00000000000..9a4fcc80e00 --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/gradle.lockfile @@ -0,0 +1,243 @@ +# This is a Gradle generated file for dependency locking. +# Manual edits can break the build and are not advised. +# This file is expected to be part of source control. +cafe.cryptography:curve25519-elisabeth:0.1.0=latestDepTestRuntimeClasspath,testRuntimeClasspath +cafe.cryptography:ed25519-elisabeth:0.1.0=latestDepTestRuntimeClasspath,testRuntimeClasspath +ch.qos.logback:logback-classic:1.2.13=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +ch.qos.logback:logback-core:1.2.13=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.alibaba:fastjson:1.2.83=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.alibaba:transmittable-thread-local:2.12.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.alipay.sofa.common:sofa-common-tools:1.0.18=compileClasspath +com.alipay.sofa.common:sofa-common-tools:1.4.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.alipay.sofa.lookout:lookout-api:1.4.1=compileClasspath +com.alipay.sofa:bolt:1.5.2=compileClasspath +com.alipay.sofa:bolt:1.6.10=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.alipay.sofa:hessian:3.3.6=compileClasspath +com.alipay.sofa:hessian:3.5.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.alipay.sofa:sofa-rpc-all:5.14.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.alipay.sofa:sofa-rpc-all:5.6.0=compileClasspath +com.alipay.sofa:tracer-core:2.1.2=compileClasspath +com.alipay.sofa:tracer-core:3.1.10=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.blogspot.mydailyjava:weak-lock-free:0.17=buildTimeInstrumentationPlugin,compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq.okhttp3:okhttp:3.12.15=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq.okio:okio:1.17.6=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq:dd-instrument-java:0.0.3=buildTimeInstrumentationPlugin,compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq:dd-javac-plugin-client:0.2.2=buildTimeInstrumentationPlugin,compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq:java-dogstatsd-client:4.4.3=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.datadoghq:sketches-java:0.8.3=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.14.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.9.8=compileClasspath +com.fasterxml.jackson.core:jackson-core:2.14.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.9.8=compileClasspath +com.fasterxml.jackson.core:jackson-databind:2.14.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.9.8=compileClasspath +com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.14.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:2.14.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:2.9.8=compileClasspath +com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.14.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.9.8=compileClasspath +com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.14.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.9.8=compileClasspath +com.fasterxml.jackson:jackson-bom:2.14.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.github.fge:btf:1.2=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.github.fge:jackson-coreutils:1.6=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.github.fge:json-patch:1.9=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.github.fge:msg-simple:1.1=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.github.javaparser:javaparser-core:3.25.6=codenarc +com.github.jnr:jffi:1.3.14=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-a64asm:1.0.0=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-constants:0.10.4=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-enxio:0.32.19=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-ffi:2.2.18=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-posix:3.1.21=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-unixsocket:0.38.24=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-x86asm:1.0.2=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.github.spotbugs:spotbugs-annotations:4.9.8=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +com.github.spotbugs:spotbugs:4.9.8=spotbugs +com.github.stephenc.jcip:jcip-annotations:1.0-1=spotbugs +com.google.android:annotations:4.1.1.4=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.google.api.grpc:proto-google-common-protos:2.9.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.auth:google-auth-library-credentials:1.4.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.auth:google-auth-library-oauth2-http:1.4.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.auto.service:auto-service-annotations:1.1.1=annotationProcessor,compileClasspath,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,testAnnotationProcessor,testCompileClasspath +com.google.auto.service:auto-service:1.1.1=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.auto.value:auto-value-annotations:1.9=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.auto:auto-common:1.2.1=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,compileClasspath,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +com.google.code.gson:gson:2.13.2=spotbugs +com.google.code.gson:gson:2.9.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.errorprone:error_prone_annotations:2.18.0=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.errorprone:error_prone_annotations:2.21.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.errorprone:error_prone_annotations:2.41.0=spotbugs +com.google.guava:failureaccess:1.0.1=annotationProcessor,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +com.google.guava:guava:16.0.1=compileClasspath +com.google.guava:guava:32.0.1-jre=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.guava:guava:32.1.3-jre=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +com.google.http-client:google-http-client-gson:1.41.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.http-client:google-http-client:1.41.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.j2objc:j2objc-annotations:1.3=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.google.j2objc:j2objc-annotations:2.8=annotationProcessor,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,testAnnotationProcessor,testCompileClasspath +com.google.protobuf:protobuf-java-util:3.21.7=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.protobuf:protobuf-java:3.25.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.re2j:re2j:1.6=latestDepTestCompileClasspath,testCompileClasspath +com.google.re2j:re2j:1.7=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.squareup.moshi:moshi:1.11.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okhttp3:logging-interceptor:3.12.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okhttp3:okhttp:3.12.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okio:okio:1.17.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.thoughtworks.qdox:qdox:1.12.1=codenarc +commons-codec:commons-codec:1.10=compileClasspath +commons-codec:commons-codec:1.11=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +commons-fileupload:commons-fileupload:1.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +commons-io:commons-io:2.15.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +commons-io:commons-io:2.20.0=spotbugs +commons-io:commons-io:2.5=compileClasspath +commons-logging:commons-logging:1.2=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +de.thetaphi:forbiddenapis:3.10=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-all:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-alts:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-api:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-auth:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-context:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-core:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-grpclb:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-netty-shaded:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-netty:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-okhttp:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-protobuf-lite:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-protobuf:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-rls:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-services:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-servlet-jakarta:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-servlet:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-stub:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-testing:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.grpc:grpc-xds:1.53.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.leangen.geantyref:geantyref:1.3.16=latestDepTestRuntimeClasspath,testRuntimeClasspath +io.netty:netty-all:4.1.32.Final=compileClasspath +io.netty:netty-all:4.1.44.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-buffer:4.1.79.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-codec-http2:4.1.79.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-codec-http:4.1.79.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-codec-socks:4.1.79.Final=latestDepTestRuntimeClasspath,testRuntimeClasspath +io.netty:netty-codec:4.1.79.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-common:4.1.79.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-handler-proxy:4.1.79.Final=latestDepTestRuntimeClasspath,testRuntimeClasspath +io.netty:netty-handler:4.1.79.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-resolver:4.1.79.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-transport-native-unix-common:4.1.79.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.netty:netty-transport:4.1.79.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.opencensus:opencensus-api:0.28.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.opencensus:opencensus-contrib-http-util:0.28.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.opencensus:opencensus-proto:0.2.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.opentracing:opentracing-api:0.22.0=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.opentracing:opentracing-mock:0.22.0=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.opentracing:opentracing-noop:0.22.0=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.opentracing:opentracing-util:0.22.0=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.perfmark:perfmark-api:0.25.0=latestDepTestRuntimeClasspath,testRuntimeClasspath +io.sqreen:libsqreen:17.3.0=latestDepTestRuntimeClasspath,testRuntimeClasspath +io.swagger:swagger-annotations:1.6.9=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.swagger:swagger-core:1.6.9=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.swagger:swagger-models:1.6.9=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +jakarta.activation:jakarta.activation-api:1.2.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +jakarta.xml.bind:jakarta.xml.bind-api:2.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +javax.activation:activation:1.1.1=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +javax.servlet:javax.servlet-api:3.1.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +javax.validation:validation-api:2.0.1.Final=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +javax.ws.rs:javax.ws.rs-api:2.1.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +jaxen:jaxen:2.0.0=spotbugs +junit:junit:4.13.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +net.bytebuddy:byte-buddy-agent:1.18.3=buildTimeInstrumentationPlugin,compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +net.bytebuddy:byte-buddy:1.18.3=buildTimeInstrumentationPlugin,compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +net.java.dev.jna:jna-platform:5.8.0=latestDepTestRuntimeClasspath,testRuntimeClasspath +net.java.dev.jna:jna:5.8.0=latestDepTestRuntimeClasspath,testRuntimeClasspath +net.jcip:jcip-annotations:1.0=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +net.sf.saxon:Saxon-HE:12.9=spotbugs +org.apache.ant:ant-antlr:1.10.14=codenarc +org.apache.ant:ant-junit:1.10.14=codenarc +org.apache.bcel:bcel:6.11.0=spotbugs +org.apache.commons:commons-compress:1.26.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-lang3:3.14.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-lang3:3.19.0=spotbugs +org.apache.commons:commons-text:1.14.0=spotbugs +org.apache.httpcomponents:httpclient:4.5.13=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.httpcomponents:httpclient:4.5.4=compileClasspath +org.apache.httpcomponents:httpcore:4.4.15=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.httpcomponents:httpcore:4.4.7=compileClasspath +org.apache.httpcomponents:httpmime:4.5.13=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.logging.log4j:log4j-api:2.25.2=spotbugs +org.apache.logging.log4j:log4j-core:2.25.2=spotbugs +org.apiguardian:apiguardian-api:1.1.2=latestDepTestCompileClasspath,testCompileClasspath +org.checkerframework:checker-qual:3.33.0=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +org.checkerframework:checker-qual:3.37.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-ant:3.0.23=codenarc +org.codehaus.groovy:groovy-docgenerator:3.0.23=codenarc +org.codehaus.groovy:groovy-groovydoc:3.0.23=codenarc +org.codehaus.groovy:groovy-json:3.0.23=codenarc +org.codehaus.groovy:groovy-json:3.0.25=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-templates:3.0.23=codenarc +org.codehaus.groovy:groovy-xml:3.0.23=codenarc +org.codehaus.groovy:groovy:3.0.23=codenarc +org.codehaus.groovy:groovy:3.0.25=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.mojo:animal-sniffer-annotations:1.21=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.codenarc:CodeNarc:3.7.0=codenarc +org.conscrypt:conscrypt-openjdk-uber:2.5.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.dom4j:dom4j:2.2.0=spotbugs +org.furyio:fury-core:0.4.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.gmetrics:GMetrics:2.1.0=codenarc +org.hamcrest:hamcrest-core:1.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.hamcrest:hamcrest:3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.javassist:javassist:3.20.0-GA=compileClasspath +org.javassist:javassist:3.29.2-GA=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.jboss.logging:jboss-logging:3.3.2.Final=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.jboss.resteasy:resteasy-client:3.6.3.Final=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.jboss.resteasy:resteasy-jackson2-provider:3.6.3.Final=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.jboss.resteasy:resteasy-jaxrs:3.6.3.Final=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.jboss.resteasy:resteasy-netty4:3.6.3.Final=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.jboss.spec.javax.annotation:jboss-annotations-api_1.3_spec:1.0.1.Final=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.jboss.spec.javax.ws.rs:jboss-jaxrs-api_2.1_spec:1.0.2.Final=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.jboss.spec.javax.xml.bind:jboss-jaxb-api_2.3_spec:1.0.1.Final=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.jctools:jctools-core-jdk11:4.0.6=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.jctools:jctools-core:4.0.6=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-api:5.14.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-engine:5.14.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-params:5.14.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter:5.14.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-commons:1.14.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-engine:1.14.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-launcher:1.14.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-runner:1.14.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-suite-api:1.14.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.junit.platform:junit-platform-suite-commons:1.14.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.junit:junit-bom:5.14.0=spotbugs +org.junit:junit-bom:5.14.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.mockito:mockito-core:4.4.0=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.objenesis:objenesis:3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.opentest4j:opentest4j:1.3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.ow2.asm:asm-analysis:9.7.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-analysis:9.9=spotbugs +org.ow2.asm:asm-commons:9.9=spotbugs +org.ow2.asm:asm-commons:9.9.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-tree:9.9=spotbugs +org.ow2.asm:asm-tree:9.9.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-util:9.7.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-util:9.9=spotbugs +org.ow2.asm:asm:9.9=spotbugs +org.ow2.asm:asm:9.9.1=buildTimeInstrumentationPlugin,compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.reactivestreams:reactive-streams:1.0.2=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.slf4j:jcl-over-slf4j:1.7.30=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.slf4j:jul-to-slf4j:1.7.30=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.slf4j:log4j-over-slf4j:1.7.30=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.slf4j:slf4j-api:1.7.30=buildTimeInstrumentationPlugin,compileClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath +org.slf4j:slf4j-api:1.7.32=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.slf4j:slf4j-api:2.0.17=spotbugs,spotbugsSlf4j +org.slf4j:slf4j-simple:2.0.17=spotbugsSlf4j +org.snakeyaml:snakeyaml-engine:2.9=buildTimeInstrumentationPlugin,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.spockframework:spock-bom:2.4-groovy-3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.spockframework:spock-core:2.4-groovy-3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.tabletest:tabletest-junit:1.2.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.tabletest:tabletest-parser:1.2.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.xmlresolver:xmlresolver:5.3.3=spotbugs +org.yaml:snakeyaml:1.33=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +empty=spotbugsPlugins diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/AbstractClusterInstrumentation.java b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/AbstractClusterInstrumentation.java new file mode 100644 index 00000000000..41b52996c5f --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/AbstractClusterInstrumentation.java @@ -0,0 +1,74 @@ +package datadog.trace.instrumentation.sofarpc; + +import static datadog.context.propagation.Propagators.defaultPropagator; +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan; +import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.startSpan; +import static datadog.trace.instrumentation.sofarpc.SofaRpcClientDecorator.DECORATE; +import static datadog.trace.instrumentation.sofarpc.SofaRpcClientDecorator.SOFA_RPC_CLIENT; +import static datadog.trace.instrumentation.sofarpc.SofaRpcInjectAdapter.SETTER; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +import com.alipay.sofa.rpc.client.AbstractCluster; +import com.alipay.sofa.rpc.config.ConsumerConfig; +import com.alipay.sofa.rpc.core.request.SofaRequest; +import com.alipay.sofa.rpc.core.response.SofaResponse; +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import net.bytebuddy.asm.Advice; + +public class AbstractClusterInstrumentation + implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice { + + @Override + public String instrumentedType() { + return "com.alipay.sofa.rpc.client.AbstractCluster"; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + transformer.applyAdvice( + isMethod() + .and(named("invoke")) + .and(takesArguments(1)) + .and(takesArgument(0, named("com.alipay.sofa.rpc.core.request.SofaRequest"))), + getClass().getName() + "$InvokeAdvice"); + } + + public static class InvokeAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static AgentScope enter( + @Advice.This AbstractCluster self, @Advice.Argument(0) SofaRequest request) { + ConsumerConfig config = self.getConsumerConfig(); + String protocol = config != null ? config.getProtocol() : null; + AgentSpan span = startSpan(SOFA_RPC_CLIENT); + DECORATE.afterStart(span); + DECORATE.onRequest(span, request); + if (protocol != null) { + span.setTag("sofarpc.protocol", protocol); + } + AgentScope scope = activateSpan(span); + defaultPropagator().inject(span, request, SETTER); + return scope; + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void exit( + @Advice.Enter AgentScope scope, + @Advice.Return SofaResponse response, + @Advice.Thrown Throwable throwable) { + if (scope == null) { + return; + } + AgentSpan span = scope.span(); + DECORATE.onResponse(span, response); + DECORATE.onError(span, throwable); + DECORATE.beforeFinish(span); + scope.close(); + span.finish(); + } + } +} diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/BoltServerProcessorInstrumentation.java b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/BoltServerProcessorInstrumentation.java new file mode 100644 index 00000000000..35622f2a105 --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/BoltServerProcessorInstrumentation.java @@ -0,0 +1,40 @@ +package datadog.trace.instrumentation.sofarpc; + +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +import datadog.trace.agent.tooling.Instrumenter; +import net.bytebuddy.asm.Advice; + +public class BoltServerProcessorInstrumentation + implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice { + + @Override + public String instrumentedType() { + return "com.alipay.sofa.rpc.server.bolt.BoltServerProcessor"; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + transformer.applyAdvice( + isMethod() + .and(named("handleRequest")) + .and(takesArguments(3)) + .and(takesArgument(2, named("com.alipay.sofa.rpc.core.request.SofaRequest"))), + getClass().getName() + "$HandleRequestAdvice"); + } + + public static class HandleRequestAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void enter() { + SofaRpcProtocolContext.set("bolt"); + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void exit() { + SofaRpcProtocolContext.clear(); + } + } +} diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/H2cServerTaskInstrumentation.java b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/H2cServerTaskInstrumentation.java new file mode 100644 index 00000000000..8657125dac3 --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/H2cServerTaskInstrumentation.java @@ -0,0 +1,35 @@ +package datadog.trace.instrumentation.sofarpc; + +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.takesNoArguments; + +import datadog.trace.agent.tooling.Instrumenter; +import net.bytebuddy.asm.Advice; + +public class H2cServerTaskInstrumentation + implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice { + + @Override + public String instrumentedType() { + return "com.alipay.sofa.rpc.server.http.AbstractHttpServerTask"; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + transformer.applyAdvice( + isMethod().and(named("run")).and(takesNoArguments()), getClass().getName() + "$RunAdvice"); + } + + public static class RunAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void enter() { + SofaRpcProtocolContext.set("h2c"); + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void exit() { + SofaRpcProtocolContext.clear(); + } + } +} diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/ProviderProxyInvokerInstrumentation.java b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/ProviderProxyInvokerInstrumentation.java new file mode 100644 index 00000000000..ca8baee6f8b --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/ProviderProxyInvokerInstrumentation.java @@ -0,0 +1,80 @@ +package datadog.trace.instrumentation.sofarpc; + +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static datadog.trace.bootstrap.instrumentation.api.AgentPropagation.extractContextAndGetSpanContext; +import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan; +import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.startSpan; +import static datadog.trace.instrumentation.sofarpc.SofaRpcExtractAdapter.GETTER; +import static datadog.trace.instrumentation.sofarpc.SofaRpcServerDecorator.DECORATE; +import static datadog.trace.instrumentation.sofarpc.SofaRpcServerDecorator.SOFA_RPC_SERVER; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +import com.alipay.sofa.rpc.core.request.SofaRequest; +import com.alipay.sofa.rpc.core.response.SofaResponse; +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.bootstrap.instrumentation.api.AgentScope; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.AgentSpanContext; +import net.bytebuddy.asm.Advice; + +public class ProviderProxyInvokerInstrumentation + implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice { + + @Override + public String instrumentedType() { + return "com.alipay.sofa.rpc.server.ProviderProxyInvoker"; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + transformer.applyAdvice( + isMethod() + .and(named("invoke")) + .and(takesArguments(1)) + .and(takesArgument(0, named("com.alipay.sofa.rpc.core.request.SofaRequest"))), + getClass().getName() + "$InvokeAdvice"); + } + + public static class InvokeAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static AgentScope enter(@Advice.Argument(0) SofaRequest request) { + // Protocol is set in thread-local by transport-specific instrumentation before this call. + // If null, the transport is not instrumented — skip. + String protocol = SofaRpcProtocolContext.get(); + if (protocol == null) { + return null; + } + // For Bolt and H2C the client injects trace context into SofaRequest.requestProps; + // extract it here. For Triple, parentContext will be null and startSpan() without an + // explicit parent naturally attaches to the active grpc.server span. For REST, + // parentContext will also be null and the active netty.request span becomes the parent. + AgentSpanContext parentContext = extractContextAndGetSpanContext(request, GETTER); + AgentSpan span = + parentContext != null + ? startSpan(SOFA_RPC_SERVER, parentContext) + : startSpan(SOFA_RPC_SERVER); + DECORATE.afterStart(span); + DECORATE.onRequest(span, request); + span.setTag("sofarpc.protocol", protocol); + return activateSpan(span); + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void exit( + @Advice.Enter AgentScope scope, + @Advice.Return SofaResponse response, + @Advice.Thrown Throwable throwable) { + if (scope == null) { + return; + } + AgentSpan span = scope.span(); + DECORATE.onResponse(span, response); + DECORATE.onError(span, throwable); + DECORATE.beforeFinish(span); + scope.close(); + span.finish(); + } + } +} diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/RestServerHandlerInstrumentation.java b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/RestServerHandlerInstrumentation.java new file mode 100644 index 00000000000..7ac377311a2 --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/RestServerHandlerInstrumentation.java @@ -0,0 +1,36 @@ +package datadog.trace.instrumentation.sofarpc; + +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +import datadog.trace.agent.tooling.Instrumenter; +import net.bytebuddy.asm.Advice; + +public class RestServerHandlerInstrumentation + implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice { + + @Override + public String instrumentedType() { + return "com.alipay.sofa.rpc.server.rest.SofaRestRequestHandler"; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + transformer.applyAdvice( + isMethod().and(named("channelRead0")).and(takesArguments(2)), + getClass().getName() + "$ChannelRead0Advice"); + } + + public static class ChannelRead0Advice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void enter() { + SofaRpcProtocolContext.set("rest"); + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void exit() { + SofaRpcProtocolContext.clear(); + } + } +} diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcClientDecorator.java b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcClientDecorator.java new file mode 100644 index 00000000000..4e9cc7e29f9 --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcClientDecorator.java @@ -0,0 +1,67 @@ +package datadog.trace.instrumentation.sofarpc; + +import com.alipay.sofa.rpc.core.request.SofaRequest; +import com.alipay.sofa.rpc.core.response.SofaResponse; +import datadog.trace.api.naming.SpanNaming; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.InternalSpanTypes; +import datadog.trace.bootstrap.instrumentation.api.Tags; +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import datadog.trace.bootstrap.instrumentation.decorator.ClientDecorator; + +public class SofaRpcClientDecorator extends ClientDecorator { + + public static final CharSequence SOFA_RPC_CLIENT = + UTF8BytesString.create( + SpanNaming.instance().namingSchema().client().operationForProtocol("sofarpc")); + + private static final CharSequence COMPONENT_NAME = UTF8BytesString.create("sofarpc-client"); + + public static final SofaRpcClientDecorator DECORATE = new SofaRpcClientDecorator(); + + @Override + protected String[] instrumentationNames() { + return new String[] {"sofarpc"}; + } + + @Override + protected CharSequence component() { + return COMPONENT_NAME; + } + + @Override + protected CharSequence spanType() { + return InternalSpanTypes.RPC; + } + + @Override + protected String service() { + return null; + } + + public AgentSpan onRequest(AgentSpan span, SofaRequest request) { + span.setTag("rpc.system", "sofarpc"); + if (request == null) { + return span; + } + String serviceName = request.getTargetServiceUniqueName(); + String methodName = request.getMethodName(); + span.setTag(Tags.RPC_SERVICE, serviceName); + span.setTag("rpc.method", methodName); + // peer.service is derived automatically by PeerServiceCalculator from rpc.service. + if (serviceName != null && methodName != null) { + span.setResourceName(serviceName + "/" + methodName); + } else if (methodName != null) { + span.setResourceName(methodName); + } + return span; + } + + public AgentSpan onResponse(AgentSpan span, SofaResponse response) { + if (response != null && response.isError()) { + span.setError(true); + span.setTag("error.message", response.getErrorMsg()); + } + return span; + } +} diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcExtractAdapter.java b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcExtractAdapter.java new file mode 100644 index 00000000000..b5c36c45258 --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcExtractAdapter.java @@ -0,0 +1,25 @@ +package datadog.trace.instrumentation.sofarpc; + +import com.alipay.sofa.rpc.core.request.SofaRequest; +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import java.util.Map; + +public final class SofaRpcExtractAdapter implements AgentPropagation.ContextVisitor { + + public static final SofaRpcExtractAdapter GETTER = new SofaRpcExtractAdapter(); + + @Override + public void forEachKey(SofaRequest carrier, AgentPropagation.KeyClassifier classifier) { + Map props = carrier.getRequestProps(); + if (props == null || props.isEmpty()) { + return; + } + for (Map.Entry entry : props.entrySet()) { + if (entry.getValue() instanceof String) { + if (!classifier.accept(entry.getKey(), (String) entry.getValue())) { + return; + } + } + } + } +} diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcInjectAdapter.java b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcInjectAdapter.java new file mode 100644 index 00000000000..f5f8e4ebe0e --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcInjectAdapter.java @@ -0,0 +1,14 @@ +package datadog.trace.instrumentation.sofarpc; + +import com.alipay.sofa.rpc.core.request.SofaRequest; +import datadog.context.propagation.CarrierSetter; + +public final class SofaRpcInjectAdapter implements CarrierSetter { + + public static final SofaRpcInjectAdapter SETTER = new SofaRpcInjectAdapter(); + + @Override + public void set(SofaRequest carrier, String key, String value) { + carrier.addRequestProp(key, value); + } +} diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcModule.java b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcModule.java new file mode 100644 index 00000000000..ca895c910ef --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcModule.java @@ -0,0 +1,38 @@ +package datadog.trace.instrumentation.sofarpc; + +import static java.util.Arrays.asList; + +import com.google.auto.service.AutoService; +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.agent.tooling.InstrumenterModule; +import java.util.List; + +@AutoService(InstrumenterModule.class) +public class SofaRpcModule extends InstrumenterModule.Tracing { + + public SofaRpcModule() { + super("sofarpc"); + } + + @Override + public String[] helperClassNames() { + return new String[] { + packageName + ".SofaRpcClientDecorator", + packageName + ".SofaRpcServerDecorator", + packageName + ".SofaRpcInjectAdapter", + packageName + ".SofaRpcExtractAdapter", + packageName + ".SofaRpcProtocolContext", + }; + } + + @Override + public List typeInstrumentations() { + return asList( + new AbstractClusterInstrumentation(), + new BoltServerProcessorInstrumentation(), + new H2cServerTaskInstrumentation(), + new RestServerHandlerInstrumentation(), + new TripleServerInstrumentation(), + new ProviderProxyInvokerInstrumentation()); + } +} diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcProtocolContext.java b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcProtocolContext.java new file mode 100644 index 00000000000..09bbafae508 --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcProtocolContext.java @@ -0,0 +1,21 @@ +package datadog.trace.instrumentation.sofarpc; + +/** Thread-local carrier for the SOFA RPC transport protocol name. */ +public final class SofaRpcProtocolContext { + + private static final ThreadLocal PROTOCOL = new ThreadLocal<>(); + + private SofaRpcProtocolContext() {} + + public static void set(String protocol) { + PROTOCOL.set(protocol); + } + + public static String get() { + return PROTOCOL.get(); + } + + public static void clear() { + PROTOCOL.remove(); + } +} diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcServerDecorator.java b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcServerDecorator.java new file mode 100644 index 00000000000..7fbbe329934 --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcServerDecorator.java @@ -0,0 +1,76 @@ +package datadog.trace.instrumentation.sofarpc; + +import com.alipay.sofa.rpc.core.request.SofaRequest; +import com.alipay.sofa.rpc.core.response.SofaResponse; +import datadog.trace.api.naming.SpanNaming; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.InternalSpanTypes; +import datadog.trace.bootstrap.instrumentation.api.Tags; +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import datadog.trace.bootstrap.instrumentation.decorator.ServerDecorator; + +public class SofaRpcServerDecorator extends ServerDecorator { + + public static final CharSequence SOFA_RPC_SERVER = + UTF8BytesString.create( + SpanNaming.instance().namingSchema().server().operationForProtocol("sofarpc")); + + private static final CharSequence COMPONENT_NAME = UTF8BytesString.create("sofarpc-server"); + + public static final SofaRpcServerDecorator DECORATE = new SofaRpcServerDecorator(); + + @Override + protected String[] instrumentationNames() { + return new String[] {"sofarpc"}; + } + + @Override + protected CharSequence component() { + return COMPONENT_NAME; + } + + @Override + protected CharSequence spanType() { + return InternalSpanTypes.RPC; + } + + @Override + public AgentSpan afterStart(AgentSpan span) { + span.setMeasured(true); + return super.afterStart(span); + } + + public AgentSpan onRequest(AgentSpan span, SofaRequest request) { + span.setTag("rpc.system", "sofarpc"); + if (request == null) { + return span; + } + String serviceName = request.getTargetServiceUniqueName(); + String methodName = request.getMethodName(); + span.setTag(Tags.RPC_SERVICE, serviceName); + span.setTag("rpc.method", methodName); + if (serviceName != null && methodName != null) { + span.setResourceName(serviceName + "/" + methodName); + } else if (methodName != null) { + span.setResourceName(methodName); + } + return span; + } + + public AgentSpan onResponse(AgentSpan span, SofaResponse response) { + if (response == null) { + return span; + } + if (response.isError()) { + // RPC-layer error (timeout, serialization failure, etc.) + span.setError(true); + span.setTag("error.message", response.getErrorMsg()); + } else if (response.getAppResponse() instanceof Throwable) { + // Application exception: ProviderProxyInvoker catches it and stores in appResponse + Throwable t = (Throwable) response.getAppResponse(); + span.setError(true); + span.setTag("error.message", t.getMessage()); + } + return span; + } +} diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/TripleServerInstrumentation.java b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/TripleServerInstrumentation.java new file mode 100644 index 00000000000..38abc4fb22b --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/TripleServerInstrumentation.java @@ -0,0 +1,40 @@ +package datadog.trace.instrumentation.sofarpc; + +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +import datadog.trace.agent.tooling.Instrumenter; +import net.bytebuddy.asm.Advice; + +public class TripleServerInstrumentation + implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice { + + @Override + public String instrumentedType() { + return "com.alipay.sofa.rpc.server.triple.UniqueIdInvoker"; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + transformer.applyAdvice( + isMethod() + .and(named("invoke")) + .and(takesArguments(1)) + .and(takesArgument(0, named("com.alipay.sofa.rpc.core.request.SofaRequest"))), + getClass().getName() + "$InvokeAdvice"); + } + + public static class InvokeAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void enter() { + SofaRpcProtocolContext.set("tri"); + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void exit() { + SofaRpcProtocolContext.clear(); + } + } +} diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/test/groovy/datadog/trace/instrumentation/sofarpc/SofaRpcRestTest.groovy b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/test/groovy/datadog/trace/instrumentation/sofarpc/SofaRpcRestTest.groovy new file mode 100644 index 00000000000..fb2a919ffa1 --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/test/groovy/datadog/trace/instrumentation/sofarpc/SofaRpcRestTest.groovy @@ -0,0 +1,144 @@ +package datadog.trace.instrumentation.sofarpc + +import com.alipay.sofa.rpc.bootstrap.ProviderBootstrap +import com.alipay.sofa.rpc.config.ApplicationConfig +import com.alipay.sofa.rpc.config.ConsumerConfig +import com.alipay.sofa.rpc.config.ProviderConfig +import com.alipay.sofa.rpc.config.ServerConfig +import datadog.trace.agent.test.InstrumentationSpecification +import datadog.trace.bootstrap.instrumentation.api.Tags +import spock.lang.Shared + +import javax.ws.rs.GET +import javax.ws.rs.Path +import javax.ws.rs.PathParam +import javax.ws.rs.Produces +import javax.ws.rs.core.MediaType + +import static datadog.trace.agent.test.utils.TraceUtils.basicSpan +import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace + +/** + * Tests SOFA RPC REST protocol instrumentation. + * + * Our instrumentation contributes sofarpc.request[client] (AbstractClusterInstrumentation) + * and sofarpc.request[server] (RestServerHandlerInstrumentation + ProviderProxyInvokerInstrumentation). + * Distributed trace propagation is delegated to dd-trace-java's HTTP instrumentation + * (Apache HttpClient on the client side, Netty on the server side), which is not active in + * this unit test — so the server span appears as a separate trace root here. + */ +class SofaRpcRestTest extends InstrumentationSpecification { + + @Shared + int port = 12205 + + @Shared + ProviderBootstrap restProviderBootstrap + + @Shared + GreeterService greeterService + + def setupSpec() { + ServerConfig serverConfig = + new ServerConfig() + .setProtocol("rest") + .setHost("127.0.0.1") + .setPort(port) + + ProviderConfig providerConfig = + new ProviderConfig() + .setApplication(new ApplicationConfig().setAppName("test-server")) + .setInterfaceId(GreeterService.name) + .setRef(new GreeterServiceImpl()) + .setServer(serverConfig) + .setRegister(false) + + restProviderBootstrap = providerConfig.export() + + greeterService = + new ConsumerConfig() + .setApplication(new ApplicationConfig().setAppName("test-client")) + .setInterfaceId(GreeterService.name) + .setDirectUrl("rest://127.0.0.1:${port}") + .setProtocol("rest") + .setRegister(false) + .setSubscribe(false) + .refer() + } + + def cleanupSpec() { + restProviderBootstrap?.unExport() + } + + def "client and server spans created for REST call"() { + setup: + String serviceUniqueName = GreeterService.name + ":1.0" + + when: + String reply = runUnderTrace("caller") { greeterService.sayHello("World") } + + then: + reply == "Hello, World" + + and: + assertTraces(2) { + // trace(0): client side — caller + sofarpc.request[client] + trace(2) { + basicSpan(it, "caller") + span { + operationName "sofarpc.request" + resourceName "${serviceUniqueName}/sayHello" + spanType "rpc" + errored false + childOf span(0) + tags { + "$Tags.RPC_SERVICE" serviceUniqueName + "rpc.method" "sayHello" + "rpc.system" "sofarpc" + "sofarpc.protocol" "rest" + "component" "sofarpc-client" + "span.kind" "client" + peerServiceFrom(Tags.RPC_SERVICE) + defaultTags() + } + } + } + // trace(1): server side — sofarpc.request[server]. + // SofaRequest.getTargetServiceUniqueName() is null on the server side for REST + // (not propagated through the JAX-RS layer), so resourceName is the method name only + // and rpc.service tag is absent. Parent link to the client trace is provided by + // HTTP instrumentation (not active in this test), so this span is a trace root here. + trace(1) { + span { + operationName "sofarpc.request" + resourceName "sayHello" + spanType "rpc" + errored false + tags { + "rpc.method" "sayHello" + "rpc.system" "sofarpc" + "sofarpc.protocol" "rest" + "component" "sofarpc-server" + "span.kind" "server" + defaultTags(true) + } + } + } + } + } + + @Path("/greeter") + interface GreeterService { + @GET + @Path("/hello/{name}") + @Produces(MediaType.TEXT_PLAIN) + String sayHello(@PathParam("name") String name) + } + + static class GreeterServiceImpl implements GreeterService { + @Override + String sayHello(String name) { + return "Hello, ${name}" + } + } +} diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/test/groovy/datadog/trace/instrumentation/sofarpc/SofaRpcTest.groovy b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/test/groovy/datadog/trace/instrumentation/sofarpc/SofaRpcTest.groovy new file mode 100644 index 00000000000..60a02cd0233 --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/test/groovy/datadog/trace/instrumentation/sofarpc/SofaRpcTest.groovy @@ -0,0 +1,236 @@ +package datadog.trace.instrumentation.sofarpc + +import com.alipay.sofa.rpc.bootstrap.ProviderBootstrap +import com.alipay.sofa.rpc.config.ApplicationConfig +import com.alipay.sofa.rpc.config.ConsumerConfig +import com.alipay.sofa.rpc.config.ProviderConfig +import com.alipay.sofa.rpc.config.ServerConfig +import datadog.trace.agent.test.InstrumentationSpecification +import datadog.trace.bootstrap.instrumentation.api.Tags +import spock.lang.Shared + +import static datadog.trace.agent.test.utils.TraceUtils.basicSpan +import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace + +class SofaRpcTest extends InstrumentationSpecification { + + @Shared + int port = 12201 + + @Shared + int errorPort = 12202 + + @Shared + ProviderBootstrap providerBootstrap + + @Shared + ProviderBootstrap errorProviderBootstrap + + @Shared + GreeterService greeterService + + @Shared + FaultyService faultyService + + def setupSpec() { + ApplicationConfig appConfig = new ApplicationConfig().setAppName("test-server") + + // Happy-path server: Bolt on port 12201 + ServerConfig serverConfig = + new ServerConfig() + .setProtocol("bolt") + .setHost("127.0.0.1") + .setPort(port) + + ProviderConfig providerConfig = + new ProviderConfig() + .setApplication(appConfig) + .setInterfaceId(GreeterService.name) + .setRef(new GreeterServiceImpl()) + .setServer(serverConfig) + .setRegister(false) + + providerBootstrap = providerConfig.export() + + greeterService = + new ConsumerConfig() + .setApplication(new ApplicationConfig().setAppName("test-client")) + .setInterfaceId(GreeterService.name) + .setDirectUrl("bolt://127.0.0.1:${port}") + .setProtocol("bolt") + .setRegister(false) + .setSubscribe(false) + .refer() + + // Error-path server: Bolt on port 12202, separate interface to avoid registry conflict + ServerConfig errorServerConfig = + new ServerConfig() + .setProtocol("bolt") + .setHost("127.0.0.1") + .setPort(errorPort) + + ProviderConfig errorProviderConfig = + new ProviderConfig() + .setApplication(appConfig) + .setInterfaceId(FaultyService.name) + .setRef(new FaultyServiceImpl()) + .setServer(errorServerConfig) + .setRegister(false) + + errorProviderBootstrap = errorProviderConfig.export() + + faultyService = + new ConsumerConfig() + .setApplication(new ApplicationConfig().setAppName("test-client")) + .setInterfaceId(FaultyService.name) + .setDirectUrl("bolt://127.0.0.1:${errorPort}") + .setProtocol("bolt") + .setRegister(false) + .setSubscribe(false) + .refer() + } + + def cleanupSpec() { + providerBootstrap?.unExport() + errorProviderBootstrap?.unExport() + } + + def "client and server spans created for synchronous Bolt RPC call"() { + setup: + String serviceUniqueName = GreeterService.name + ":1.0" + + when: + // runUnderTrace gives the client trace 2 spans (caller + sofarpc.request), making it + // unambiguously distinguishable from the 1-span server trace in assertTraces below. + String reply = runUnderTrace("caller") { greeterService.sayHello("World") } + + then: + reply == "Hello, World" + + and: + assertTraces(2) { + // trace(0): client side — 2 spans [caller, sofarpc.request(client)] + trace(2) { + basicSpan(it, "caller") + span { + operationName "sofarpc.request" + resourceName "${serviceUniqueName}/sayHello" + spanType "rpc" + errored false + childOf span(0) + tags { + "$Tags.RPC_SERVICE" serviceUniqueName + "rpc.method" "sayHello" + "rpc.system" "sofarpc" + "sofarpc.protocol" "bolt" + "component" "sofarpc-client" + "span.kind" "client" + peerServiceFrom(Tags.RPC_SERVICE) + defaultTags() + } + } + } + // trace(1): server side — 1 span [sofarpc.request(server)], child of client span + trace(1) { + span { + operationName "sofarpc.request" + resourceName "${serviceUniqueName}/sayHello" + spanType "rpc" + errored false + childOf trace(0).get(1) + tags { + "$Tags.RPC_SERVICE" serviceUniqueName + "rpc.method" "sayHello" + "rpc.system" "sofarpc" + "sofarpc.protocol" "bolt" + "component" "sofarpc-server" + "span.kind" "server" + defaultTags(true) + } + } + } + } + } + + def "server error is marked on server span"() { + setup: + String serviceUniqueName = FaultyService.name + ":1.0" + + when: + // SOFA RPC Bolt propagates server exceptions back to the client as a SofaRpcException. + // The client-side AbstractCluster.invoke() returns the SofaResponse to the proxy layer, + // which then throws — after our instrumentation's OnMethodExit has already closed the scope. + // So the CLIENT span is not errored; only the SERVER span reflects the error. + faultyService.fail() + + then: + thrown(Exception) + + and: + assertTraces(2) { + // Traces sorted by root-span start time. Client span starts first (initiates the call), + // so the client trace is trace(0) and the server trace is trace(1). + trace(1) { + span { + operationName "sofarpc.request" + resourceName "${serviceUniqueName}/fail" + spanType "rpc" + errored false + tags { + "$Tags.RPC_SERVICE" serviceUniqueName + "rpc.method" "fail" + "rpc.system" "sofarpc" + "sofarpc.protocol" "bolt" + "component" "sofarpc-client" + "span.kind" "client" + peerServiceFrom(Tags.RPC_SERVICE) + defaultTags() + } + } + } + trace(1) { + span { + operationName "sofarpc.request" + resourceName "${serviceUniqueName}/fail" + spanType "rpc" + errored true + childOf trace(0).get(0) + tags { + "$Tags.RPC_SERVICE" serviceUniqueName + "rpc.method" "fail" + "rpc.system" "sofarpc" + "sofarpc.protocol" "bolt" + "component" "sofarpc-server" + "span.kind" "server" + "error.message" { String } + defaultTags(true) + } + } + } + } + } + + interface GreeterService { + String sayHello(String name) + } + + static class GreeterServiceImpl implements GreeterService { + @Override + String sayHello(String name) { + return "Hello, ${name}" + } + } + + interface FaultyService { + // Non-void return type: SOFA RPC Bolt throws SofaRpcException on client side + // when the server returns an error response, which is what we verify in the test. + String fail() + } + + static class FaultyServiceImpl implements FaultyService { + @Override + String fail() { + throw new IllegalStateException("something went wrong") + } + } +} diff --git a/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/test/groovy/datadog/trace/instrumentation/sofarpc/SofaRpcTripleWithGrpcForkedTest.groovy b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/test/groovy/datadog/trace/instrumentation/sofarpc/SofaRpcTripleWithGrpcForkedTest.groovy new file mode 100644 index 00000000000..ceea44eb9a9 --- /dev/null +++ b/dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/test/groovy/datadog/trace/instrumentation/sofarpc/SofaRpcTripleWithGrpcForkedTest.groovy @@ -0,0 +1,113 @@ +package datadog.trace.instrumentation.sofarpc + +import com.alipay.sofa.rpc.bootstrap.ProviderBootstrap +import com.alipay.sofa.rpc.config.ApplicationConfig +import com.alipay.sofa.rpc.config.ConsumerConfig +import com.alipay.sofa.rpc.config.ProviderConfig +import com.alipay.sofa.rpc.config.ServerConfig +import datadog.trace.agent.test.InstrumentationSpecification +import spock.lang.Shared + +import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace + +/** + * Forked test: runs in an isolated JVM with gRPC instrumentation ENABLED (the default). + * + * When gRPC instrumentation is active, SOFA RPC Triple calls produce both gRPC spans + * (grpc.client / grpc.server) and sofarpc spans. All spans run in-process and share + * one trace. Expected hierarchy: + * + * caller + * └─ sofarpc.request [client] + * └─ grpc.client + * └─ grpc.server + * └─ sofarpc.request [server] ← asserted below + * + * The key assertion is that sofarpc.request[server] is a direct child of grpc.server, + * NOT of grpc.client. Before the fix, TripleServerInstrumentation would extract the + * parent context from gRPC Metadata regardless of whether a grpc.server span was active, + * which caused sofarpc.request[server] to become a sibling of grpc.server instead. + */ +class SofaRpcTripleWithGrpcForkedTest extends InstrumentationSpecification { + // No configurePreAgent() override — gRPC instrumentation is enabled by default. + + @Shared + int triplePort = 12204 + + @Shared + ProviderBootstrap tripleProviderBootstrap + + @Shared + GreeterService greeterService + + def setupSpec() { + ServerConfig serverConfig = + new ServerConfig() + .setProtocol("tri") + .setHost("127.0.0.1") + .setPort(triplePort) + + ProviderConfig providerConfig = + new ProviderConfig() + .setApplication(new ApplicationConfig().setAppName("test-server")) + .setInterfaceId(GreeterService.name) + .setRef(new GreeterServiceImpl()) + .setServer(serverConfig) + .setRegister(false) + + tripleProviderBootstrap = providerConfig.export() + + greeterService = + new ConsumerConfig() + .setApplication(new ApplicationConfig().setAppName("test-client")) + .setInterfaceId(GreeterService.name) + .setDirectUrl("tri://127.0.0.1:${triplePort}") + .setProtocol("tri") + .setRegister(false) + .setSubscribe(false) + .refer() + } + + def cleanupSpec() { + tripleProviderBootstrap?.unExport() + } + + def "Triple: server span is nested under grpc.server when gRPC instrumentation is enabled"() { + when: + String reply = runUnderTrace("caller") { greeterService.sayHello("World") } + + then: + reply == "Hello, World" + + and: + // Client spans (caller, sofarpc[client], grpc.client) are flushed when the client-side + // root span finishes. Server spans (grpc.server, sofarpc[server], grpc.message) are + // flushed when grpc.server — the server-side local root — finishes on its own thread. + // That gives two separate ListWriter entries even though both share the same trace_id. + TEST_WRITER.waitForTraces(2) + def allSpans = TEST_WRITER.flatten() + + def serverSofaSpan = allSpans.find { + it.operationName.toString() == "sofarpc.request" && it.getTag("span.kind") == "server" + } + def grpcServerSpan = allSpans.find { + it.operationName.toString() == "grpc.server" + } + + assert serverSofaSpan != null : "Expected sofarpc[server]. Spans found: ${allSpans.collect { it.operationName.toString() + '[' + it.getTag('span.kind') + ']' }}" + assert grpcServerSpan != null : "Expected grpc.server. Spans found: ${allSpans.collect { it.operationName.toString() + '[' + it.getTag('span.kind') + ']' }}" + // sofarpc.request[server] must be a direct child of grpc.server, not grpc.client + serverSofaSpan.parentId == grpcServerSpan.spanId + } + + interface GreeterService { + String sayHello(String name) + } + + static class GreeterServiceImpl implements GreeterService { + @Override + String sayHello(String name) { + return "Hello, ${name}" + } + } +} diff --git a/metadata/supported-configurations.json b/metadata/supported-configurations.json index ac7935039e3..af6c4bfc94a 100644 --- a/metadata/supported-configurations.json +++ b/metadata/supported-configurations.json @@ -9889,6 +9889,30 @@ "aliases": ["DD_TRACE_INTEGRATION_SOCKET_ENABLED", "DD_INTEGRATION_SOCKET_ENABLED"] } ], + "DD_TRACE_SOFARPC_ANALYTICS_ENABLED": [ + { + "version": "A", + "type": "boolean", + "default": "false", + "aliases": ["DD_SOFARPC_ANALYTICS_ENABLED"] + } + ], + "DD_TRACE_SOFARPC_ANALYTICS_SAMPLE_RATE": [ + { + "version": "A", + "type": "decimal", + "default": "1.0", + "aliases": ["DD_SOFARPC_ANALYTICS_SAMPLE_RATE"] + } + ], + "DD_TRACE_SOFARPC_ENABLED": [ + { + "version": "A", + "type": "boolean", + "default": "true", + "aliases": ["DD_TRACE_INTEGRATION_SOFARPC_ENABLED", "DD_INTEGRATION_SOFARPC_ENABLED"] + } + ], "DD_TRACE_SPAN_ATTRIBUTE_SCHEMA": [ { "version": "B", diff --git a/settings.gradle.kts b/settings.gradle.kts index 074514e7126..0a1f22be364 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -560,6 +560,8 @@ include( ":dd-java-agent:instrumentation:servlet:javax-servlet:javax-servlet-iast", ":dd-java-agent:instrumentation:slick-3.2", ":dd-java-agent:instrumentation:snakeyaml-1.33", + ":dd-java-agent:instrumentation:sofarpc", + ":dd-java-agent:instrumentation:sofarpc:sofarpc-5.0", ":dd-java-agent:instrumentation:spark:spark-common", ":dd-java-agent:instrumentation:spark:spark_2.12", ":dd-java-agent:instrumentation:spark:spark_2.13",