From a4c5a0917cd4115ca70366437f86138e0cad0af2 Mon Sep 17 00:00:00 2001 From: Jordan Wong Date: Mon, 13 Jul 2026 15:32:30 -0400 Subject: [PATCH] eval: blind regeneration of sparkjava-2.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This branch contains the output of an automated integration-authoring pass on `sparkjava-2.3`, produced against the draft skill in #11927. Opened as a draft PR for reviewer reference during discussion of that skill PR; not intended to be merged as-is. Base: master @ cd03735159 Target module deleted before the run so the authoring flow had to generate it from scratch (blind test — output has no visibility of the shipping module). Diff scope: only `dd-java-agent/instrumentation/spark/sparkjava-2.3/` plus entries in `metadata/supported-configurations.json`. All other generation artifacts (`.analysis/**`, workflow state) are excluded. --- .../spark/sparkjava-2.3/build.gradle | 14 +- .../spark/sparkjava-2.3/gradle.lockfile | 172 ----------------- .../sparkjava/ExtractAdapter.java | 49 +++++ .../JettyHandlerInstrumentation.java | 50 +++++ .../MatcherFilterInstrumentation.java | 93 +++++++++ .../sparkjava/RequestURIDataAdapter.java | 43 +++++ .../RouteHandlerInstrumentation.java | 50 +++++ .../sparkjava/RoutesInstrumentation.java | 58 ------ .../sparkjava/SparkJavaDecorator.java | 66 +++++++ .../sparkjava/SparkJavaModule.java | 34 ++++ .../src/test/groovy/SparkJavaBasedTest.groovy | 73 -------- .../sparkjava/SparkJavaForkedTest.groovy | 176 ++++++++++++++++++ .../sparkjava/SparkJavaTest.groovy | 164 ++++++++++++++++ .../test/java/TestSparkJavaApplication.java | 19 -- metadata/supported-configurations.json | 24 +++ 15 files changed, 755 insertions(+), 330 deletions(-) delete mode 100644 dd-java-agent/instrumentation/spark/sparkjava-2.3/gradle.lockfile create mode 100644 dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/ExtractAdapter.java create mode 100644 dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/JettyHandlerInstrumentation.java create mode 100644 dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/MatcherFilterInstrumentation.java create mode 100644 dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/RequestURIDataAdapter.java create mode 100644 dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/RouteHandlerInstrumentation.java delete mode 100644 dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/RoutesInstrumentation.java create mode 100644 dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/SparkJavaDecorator.java create mode 100644 dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/SparkJavaModule.java delete mode 100644 dd-java-agent/instrumentation/spark/sparkjava-2.3/src/test/groovy/SparkJavaBasedTest.groovy create mode 100644 dd-java-agent/instrumentation/spark/sparkjava-2.3/src/test/groovy/datadog/trace/instrumentation/sparkjava/SparkJavaForkedTest.groovy create mode 100644 dd-java-agent/instrumentation/spark/sparkjava-2.3/src/test/groovy/datadog/trace/instrumentation/sparkjava/SparkJavaTest.groovy delete mode 100644 dd-java-agent/instrumentation/spark/sparkjava-2.3/src/test/java/TestSparkJavaApplication.java diff --git a/dd-java-agent/instrumentation/spark/sparkjava-2.3/build.gradle b/dd-java-agent/instrumentation/spark/sparkjava-2.3/build.gradle index d2c1dabe2a2..bac7b0d548c 100644 --- a/dd-java-agent/instrumentation/spark/sparkjava-2.3/build.gradle +++ b/dd-java-agent/instrumentation/spark/sparkjava-2.3/build.gradle @@ -1,24 +1,22 @@ -// building against 2.3 and testing against 2.4 because JettyHandler is available since 2.4 only muzzle { pass { - group = "com.sparkjava" + group = 'com.sparkjava' module = 'spark-core' - versions = "[2.3,)" + versions = "[2.3,2.4)" assertInverse = true } } -apply from: "$rootDir/gradle/java.gradle" +apply from: "${rootDir}/gradle/java.gradle" addTestSuiteForDir('latestDepTest', 'test') dependencies { compileOnly group: 'com.sparkjava', name: 'spark-core', version: '2.3' - testImplementation project(':dd-java-agent:instrumentation:jetty:jetty-server:jetty-server-9.0') + testImplementation group: 'com.sparkjava', name: 'spark-core', version: '2.3' + testImplementation project(':dd-java-agent:instrumentation-testing') - testImplementation group: 'com.sparkjava', name: 'spark-core', version: '2.4' - - latestDepTestImplementation group: 'com.sparkjava', name: 'spark-core', version: '+' + latestDepTestImplementation group: 'com.sparkjava', name: 'spark-core', version: '2.3' } diff --git a/dd-java-agent/instrumentation/spark/sparkjava-2.3/gradle.lockfile b/dd-java-agent/instrumentation/spark/sparkjava-2.3/gradle.lockfile deleted file mode 100644 index f64a04e7326..00000000000 --- a/dd-java-agent/instrumentation/spark/sparkjava-2.3/gradle.lockfile +++ /dev/null @@ -1,172 +0,0 @@ -# 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. -# To regenerate this file, run: ./gradlew :dd-java-agent:instrumentation:spark:sparkjava-2.3:dependencies --write-locks -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.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.4=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.5=latestDepTestRuntimeClasspath,testRuntimeClasspath -com.datadoghq:sketches-java:0.8.3=latestDepTestRuntimeClasspath,testRuntimeClasspath -com.github.javaparser:javaparser-core:3.25.6=codenarc -com.github.jnr:jffi:1.3.15=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.20=latestDepTestRuntimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-ffi:2.2.19=latestDepTestRuntimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-posix:3.1.22=latestDepTestRuntimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-unixsocket:0.38.25=latestDepTestRuntimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-x86asm:1.0.2=latestDepTestRuntimeClasspath,testRuntimeClasspath -com.github.spotbugs:spotbugs-annotations:4.9.8=compileClasspath,spotbugs -com.github.spotbugs:spotbugs:4.9.8=spotbugs -com.github.stephenc.jcip:jcip-annotations:1.0-1=spotbugs -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: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.errorprone:error_prone_annotations:2.18.0=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor -com.google.errorprone:error_prone_annotations:2.41.0=spotbugs -com.google.errorprone:error_prone_annotations:2.47.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.guava:failureaccess:1.0.1=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor -com.google.guava:failureaccess:1.0.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.guava:guava:32.0.1-jre=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor -com.google.guava:guava:33.6.0-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.j2objc:j2objc-annotations:2.8=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor -com.google.j2objc:j2objc-annotations:3.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.re2j:re2j:1.8=latestDepTestRuntimeClasspath,testRuntimeClasspath -com.sparkjava:spark-core:2.3=compileClasspath -com.sparkjava:spark-core:2.4=testCompileClasspath,testRuntimeClasspath -com.sparkjava:spark-core:2.9.4=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -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-fileupload:commons-fileupload:1.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -commons-io:commons-io:2.11.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -commons-io:commons-io:2.20.0=spotbugs -de.thetaphi:forbiddenapis:3.10=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -io.leangen.geantyref:geantyref:1.3.16=latestDepTestRuntimeClasspath,testRuntimeClasspath -io.sqreen:libsqreen:17.3.0=latestDepTestRuntimeClasspath,testRuntimeClasspath -javax.servlet:javax.servlet-api:3.1.0=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -jaxen:jaxen:2.0.0=spotbugs -junit:junit:4.13.2=latestDepTestRuntimeClasspath,testRuntimeClasspath -net.bytebuddy:byte-buddy-agent:1.18.10=buildTimeInstrumentationPlugin,compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -net.bytebuddy:byte-buddy:1.18.10=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.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-lang3:3.19.0=spotbugs -org.apache.commons:commons-text:1.14.0=spotbugs -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.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.codenarc:CodeNarc:3.7.0=codenarc -org.dom4j:dom4j:2.2.0=spotbugs -org.eclipse.jetty.websocket:websocket-api:9.3.2.v20150730=compileClasspath -org.eclipse.jetty.websocket:websocket-api:9.3.6.v20151106=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty.websocket:websocket-api:9.4.48.v20220622=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.eclipse.jetty.websocket:websocket-client:9.3.2.v20150730=compileClasspath -org.eclipse.jetty.websocket:websocket-client:9.3.6.v20151106=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty.websocket:websocket-client:9.4.48.v20220622=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.eclipse.jetty.websocket:websocket-common:9.3.2.v20150730=compileClasspath -org.eclipse.jetty.websocket:websocket-common:9.3.6.v20151106=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty.websocket:websocket-common:9.4.48.v20220622=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.eclipse.jetty.websocket:websocket-server:9.3.2.v20150730=compileClasspath -org.eclipse.jetty.websocket:websocket-server:9.3.6.v20151106=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty.websocket:websocket-server:9.4.48.v20220622=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.eclipse.jetty.websocket:websocket-servlet:9.3.2.v20150730=compileClasspath -org.eclipse.jetty.websocket:websocket-servlet:9.3.6.v20151106=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty.websocket:websocket-servlet:9.4.48.v20220622=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.eclipse.jetty:jetty-client:9.4.48.v20220622=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.eclipse.jetty:jetty-http:9.3.2.v20150730=compileClasspath -org.eclipse.jetty:jetty-http:9.3.6.v20151106=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-http:9.4.48.v20220622=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.eclipse.jetty:jetty-io:9.3.2.v20150730=compileClasspath -org.eclipse.jetty:jetty-io:9.3.6.v20151106=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-io:9.4.48.v20220622=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.eclipse.jetty:jetty-security:9.3.2.v20150730=compileClasspath -org.eclipse.jetty:jetty-security:9.3.6.v20151106=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-security:9.4.48.v20220622=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.eclipse.jetty:jetty-server:9.3.2.v20150730=compileClasspath -org.eclipse.jetty:jetty-server:9.3.6.v20151106=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-server:9.4.48.v20220622=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.eclipse.jetty:jetty-servlet:9.3.2.v20150730=compileClasspath -org.eclipse.jetty:jetty-servlet:9.3.6.v20151106=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-servlet:9.4.48.v20220622=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.eclipse.jetty:jetty-util-ajax:9.4.48.v20220622=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.eclipse.jetty:jetty-util:9.3.2.v20150730=compileClasspath -org.eclipse.jetty:jetty-util:9.3.6.v20151106=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-util:9.4.48.v20220622=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.eclipse.jetty:jetty-webapp:9.3.2.v20150730=compileClasspath -org.eclipse.jetty:jetty-webapp:9.3.6.v20151106=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-webapp:9.4.48.v20220622=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.eclipse.jetty:jetty-xml:9.3.2.v20150730=compileClasspath -org.eclipse.jetty:jetty-xml:9.3.6.v20151106=testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-xml:9.4.48.v20220622=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.gmetrics:GMetrics:2.1.0=codenarc -org.hamcrest:hamcrest-core:1.3=latestDepTestRuntimeClasspath,testRuntimeClasspath -org.hamcrest:hamcrest:3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.jctools:jctools-core-jdk11:4.0.6=latestDepTestRuntimeClasspath,testRuntimeClasspath -org.jctools:jctools-core:4.0.6=latestDepTestRuntimeClasspath,testRuntimeClasspath -org.jspecify:jspecify:1.0.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,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.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:1.7.12=compileClasspath -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 -empty=spotbugsPlugins diff --git a/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/ExtractAdapter.java b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/ExtractAdapter.java new file mode 100644 index 00000000000..41fa8f37ceb --- /dev/null +++ b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/ExtractAdapter.java @@ -0,0 +1,49 @@ +package datadog.trace.instrumentation.sparkjava; + +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import java.util.Collection; +import java.util.Enumeration; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public abstract class ExtractAdapter { + + public static final class Request + implements AgentPropagation.ContextVisitor { + public static final Request GETTER = new Request(); + + @Override + public void forEachKey( + HttpServletRequest carrier, AgentPropagation.KeyClassifier classifier) { + Enumeration headerNames = carrier.getHeaderNames(); + if (headerNames == null) { + return; + } + while (headerNames.hasMoreElements()) { + String headerName = headerNames.nextElement(); + if (!classifier.accept(headerName, carrier.getHeader(headerName))) { + return; + } + } + } + } + + public static final class Response + implements AgentPropagation.ContextVisitor { + public static final Response GETTER = new Response(); + + @Override + public void forEachKey( + HttpServletResponse carrier, AgentPropagation.KeyClassifier classifier) { + Collection headerNames = carrier.getHeaderNames(); + if (headerNames == null) { + return; + } + for (String headerName : headerNames) { + if (!classifier.accept(headerName, carrier.getHeader(headerName))) { + return; + } + } + } + } +} diff --git a/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/JettyHandlerInstrumentation.java b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/JettyHandlerInstrumentation.java new file mode 100644 index 00000000000..0dc5023739d --- /dev/null +++ b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/JettyHandlerInstrumentation.java @@ -0,0 +1,50 @@ +package datadog.trace.instrumentation.sparkjava; + +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static datadog.trace.instrumentation.sparkjava.SparkJavaDecorator.DECORATE; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import datadog.context.Context; +import datadog.context.ContextScope; +import datadog.trace.agent.tooling.Instrumenter; +import javax.servlet.http.HttpServletRequest; +import net.bytebuddy.asm.Advice; + +public class JettyHandlerInstrumentation + implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice { + + @Override + public String instrumentedType() { + return "spark.webserver.JettyHandler"; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + transformer.applyAdvice( + named("doHandle") + .and(takesArgument(0, String.class)) + .and( + takesArgument( + 1, named("org.eclipse.jetty.server.Request"))) + .and(takesArgument(2, named("javax.servlet.http.HttpServletRequest"))) + .and(takesArgument(3, named("javax.servlet.http.HttpServletResponse"))), + JettyHandlerInstrumentation.class.getName() + "$JettyHandlerAdvice"); + } + + public static class JettyHandlerAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static ContextScope onEnter( + @Advice.Argument(2) final HttpServletRequest request) { + final Context parentContext = DECORATE.extract(request); + return parentContext.attach(); + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void onExit(@Advice.Enter final ContextScope scope) { + if (scope != null) { + scope.close(); + } + } + } +} diff --git a/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/MatcherFilterInstrumentation.java b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/MatcherFilterInstrumentation.java new file mode 100644 index 00000000000..d71e2802bda --- /dev/null +++ b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/MatcherFilterInstrumentation.java @@ -0,0 +1,93 @@ +package datadog.trace.instrumentation.sparkjava; + +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static datadog.trace.bootstrap.instrumentation.api.Java8BytecodeBridge.spanFromContext; +import static datadog.trace.bootstrap.instrumentation.decorator.HttpServerDecorator.DD_CONTEXT_ATTRIBUTE; +import static datadog.trace.instrumentation.sparkjava.SparkJavaDecorator.DECORATE; +import static net.bytebuddy.matcher.ElementMatchers.isPublic; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import datadog.context.Context; +import datadog.context.ContextScope; +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import net.bytebuddy.asm.Advice; + +public class MatcherFilterInstrumentation + implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice { + + @Override + public String instrumentedType() { + return "spark.webserver.MatcherFilter"; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + transformer.applyAdvice( + named("doFilter") + .and(takesArgument(0, named("javax.servlet.ServletRequest"))) + .and(takesArgument(1, named("javax.servlet.ServletResponse"))) + .and(isPublic()), + MatcherFilterInstrumentation.class.getName() + "$MatcherFilterAdvice"); + } + + public static class MatcherFilterAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static ContextScope onEnter( + @Advice.Argument(0) final javax.servlet.ServletRequest servletRequest) { + if (!(servletRequest instanceof HttpServletRequest)) { + return null; + } + + final HttpServletRequest request = (HttpServletRequest) servletRequest; + + final Object contextAttr = request.getAttribute(DD_CONTEXT_ATTRIBUTE); + if (contextAttr instanceof Context) { + // Already instrumented by another HTTP server integration (e.g. Jetty) + return null; + } + + final Context parentContext = DECORATE.extract(request); + final Context context = DECORATE.startSpan(request, parentContext); + final AgentSpan span = spanFromContext(context); + DECORATE.afterStart(span); + DECORATE.onRequest(span, request, request, parentContext); + + final ContextScope scope = context.attach(); + request.setAttribute(DD_CONTEXT_ATTRIBUTE, context); + + return scope; + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void onExit( + @Advice.Argument(0) final javax.servlet.ServletRequest servletRequest, + @Advice.Argument(1) final javax.servlet.ServletResponse servletResponse, + @Advice.Enter final ContextScope scope, + @Advice.Thrown final Throwable throwable) { + if (scope == null) { + return; + } + + final Context context = scope.context(); + final AgentSpan span = spanFromContext(context); + + if (servletResponse instanceof HttpServletResponse) { + DECORATE.onResponse(span, (HttpServletResponse) servletResponse); + } + if (throwable != null) { + DECORATE.onError(span, throwable); + } + DECORATE.beforeFinish(context); + scope.close(); + span.finish(); + + if (servletRequest instanceof HttpServletRequest) { + ((HttpServletRequest) servletRequest).removeAttribute(DD_CONTEXT_ATTRIBUTE); + } + } + } +} diff --git a/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/RequestURIDataAdapter.java b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/RequestURIDataAdapter.java new file mode 100644 index 00000000000..4c5b25a814e --- /dev/null +++ b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/RequestURIDataAdapter.java @@ -0,0 +1,43 @@ +package datadog.trace.instrumentation.sparkjava; + +import datadog.trace.bootstrap.instrumentation.api.URIRawDataAdapter; +import javax.servlet.http.HttpServletRequest; + +final class RequestURIDataAdapter extends URIRawDataAdapter { + + private final HttpServletRequest request; + + RequestURIDataAdapter(HttpServletRequest request) { + this.request = request; + } + + @Override + public String scheme() { + return request.getScheme(); + } + + @Override + public String host() { + return request.getServerName(); + } + + @Override + public int port() { + return request.getServerPort(); + } + + @Override + protected String innerRawPath() { + return request.getRequestURI(); + } + + @Override + public String fragment() { + return null; + } + + @Override + protected String innerRawQuery() { + return request.getQueryString(); + } +} diff --git a/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/RouteHandlerInstrumentation.java b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/RouteHandlerInstrumentation.java new file mode 100644 index 00000000000..8e2626bacac --- /dev/null +++ b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/RouteHandlerInstrumentation.java @@ -0,0 +1,50 @@ +package datadog.trace.instrumentation.sparkjava; + +import static datadog.trace.agent.tooling.bytebuddy.matcher.HierarchyMatchers.extendsClass; +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static datadog.trace.bootstrap.instrumentation.api.Java8BytecodeBridge.currentSpan; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +public class RouteHandlerInstrumentation + implements Instrumenter.ForTypeHierarchy, Instrumenter.HasMethodAdvice { + + @Override + public String hierarchyMarkerType() { + return "spark.RouteImpl"; + } + + @Override + public ElementMatcher hierarchyMatcher() { + return extendsClass(named("spark.RouteImpl")); + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + transformer.applyAdvice( + named("handle") + .and(isMethod()) + .and(takesArgument(0, named("spark.Request"))) + .and(takesArgument(1, named("spark.Response"))), + RouteHandlerInstrumentation.class.getName() + "$RouteHandlerAdvice"); + } + + public static class RouteHandlerAdvice { + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void onExit(@Advice.Thrown final Throwable throwable) { + if (throwable != null) { + final AgentSpan span = currentSpan(); + if (span != null) { + span.addThrowable(throwable); + } + } + } + } +} diff --git a/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/RoutesInstrumentation.java b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/RoutesInstrumentation.java deleted file mode 100644 index b4dbe6e5c02..00000000000 --- a/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/RoutesInstrumentation.java +++ /dev/null @@ -1,58 +0,0 @@ -package datadog.trace.instrumentation.sparkjava; - -import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeSpan; -import static datadog.trace.bootstrap.instrumentation.decorator.http.HttpResourceDecorator.HTTP_RESOURCE_DECORATOR; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.returns; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import datadog.trace.agent.tooling.Instrumenter; -import datadog.trace.agent.tooling.InstrumenterModule; -import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import net.bytebuddy.asm.Advice; -import spark.route.HttpMethod; -import spark.routematch.RouteMatch; - -@AutoService(InstrumenterModule.class) -public class RoutesInstrumentation extends InstrumenterModule.Tracing - implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice { - - public RoutesInstrumentation() { - super("sparkjava", "sparkjava-2.4"); - } - - @Override - public boolean defaultEnabled() { - return false; - } - - @Override - public String instrumentedType() { - return "spark.route.Routes"; - } - - @Override - public void methodAdvice(MethodTransformer transformer) { - transformer.applyAdvice( - named("find") - .and(takesArgument(0, named("spark.route.HttpMethod"))) - .and(returns(named("spark.routematch.RouteMatch"))) - .and(isPublic()), - RoutesInstrumentation.class.getName() + "$RoutesAdvice"); - } - - public static class RoutesAdvice { - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void routeMatchEnricher( - @Advice.Argument(0) final HttpMethod method, @Advice.Return final RouteMatch routeMatch) { - - final AgentSpan span = activeSpan(); - if (span != null && routeMatch != null) { - HTTP_RESOURCE_DECORATOR.withRoute(span, method.name(), routeMatch.getMatchUri()); - } - } - } -} diff --git a/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/SparkJavaDecorator.java b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/SparkJavaDecorator.java new file mode 100644 index 00000000000..c44a9e0a018 --- /dev/null +++ b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/SparkJavaDecorator.java @@ -0,0 +1,66 @@ +package datadog.trace.instrumentation.sparkjava; + +import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; +import datadog.trace.bootstrap.instrumentation.api.URIDataAdapter; +import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; +import datadog.trace.bootstrap.instrumentation.decorator.HttpServerDecorator; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public class SparkJavaDecorator + extends HttpServerDecorator< + HttpServletRequest, HttpServletRequest, HttpServletResponse, HttpServletRequest> { + public static final CharSequence SPARK_JAVA = UTF8BytesString.create("spark-java"); + public static final CharSequence SPARK_REQUEST = UTF8BytesString.create("spark.request"); + public static final SparkJavaDecorator DECORATE = new SparkJavaDecorator(); + + @Override + protected String[] instrumentationNames() { + return new String[] {"sparkjava"}; + } + + @Override + protected CharSequence component() { + return SPARK_JAVA; + } + + @Override + protected AgentPropagation.ContextVisitor getter() { + return ExtractAdapter.Request.GETTER; + } + + @Override + protected AgentPropagation.ContextVisitor responseGetter() { + return ExtractAdapter.Response.GETTER; + } + + @Override + public CharSequence spanName() { + return SPARK_REQUEST; + } + + @Override + protected String method(final HttpServletRequest request) { + return request.getMethod(); + } + + @Override + protected URIDataAdapter url(final HttpServletRequest request) { + return new RequestURIDataAdapter(request); + } + + @Override + protected String peerHostIP(final HttpServletRequest request) { + return request.getRemoteAddr(); + } + + @Override + protected int peerPort(final HttpServletRequest request) { + return request.getRemotePort(); + } + + @Override + protected int status(final HttpServletResponse response) { + return response.getStatus(); + } +} diff --git a/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/SparkJavaModule.java b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/SparkJavaModule.java new file mode 100644 index 00000000000..274c616a68c --- /dev/null +++ b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/main/java/datadog/trace/instrumentation/sparkjava/SparkJavaModule.java @@ -0,0 +1,34 @@ +package datadog.trace.instrumentation.sparkjava; + +import com.google.auto.service.AutoService; +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.agent.tooling.InstrumenterModule; +import java.util.Arrays; +import java.util.List; + +@AutoService(InstrumenterModule.class) +public final class SparkJavaModule extends InstrumenterModule.Tracing { + + public SparkJavaModule() { + super("sparkjava", "sparkjava-2.3"); + } + + @Override + public String[] helperClassNames() { + return new String[] { + packageName + ".SparkJavaDecorator", + packageName + ".ExtractAdapter", + packageName + ".ExtractAdapter$Request", + packageName + ".ExtractAdapter$Response", + packageName + ".RequestURIDataAdapter", + }; + } + + @Override + public List typeInstrumentations() { + return Arrays.asList( + new MatcherFilterInstrumentation(), + new JettyHandlerInstrumentation(), + new RouteHandlerInstrumentation()); + } +} diff --git a/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/test/groovy/SparkJavaBasedTest.groovy b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/test/groovy/SparkJavaBasedTest.groovy deleted file mode 100644 index 2c33e8d745b..00000000000 --- a/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/test/groovy/SparkJavaBasedTest.groovy +++ /dev/null @@ -1,73 +0,0 @@ -import datadog.trace.agent.test.InstrumentationSpecification -import datadog.trace.agent.test.utils.OkHttpUtils -import datadog.trace.agent.test.utils.PortUtils -import datadog.trace.api.DDSpanTypes -import datadog.trace.bootstrap.instrumentation.api.Tags -import okhttp3.OkHttpClient -import okhttp3.Request -import spark.Spark -import spock.lang.Shared - -class SparkJavaBasedTest extends InstrumentationSpecification { - - @Override - void configurePreAgent() { - super.configurePreAgent() - injectSysConfig("dd.integration.jetty.enabled", "true") - injectSysConfig("dd.integration.sparkjava.enabled", "true") - } - - @Shared - int port - - OkHttpClient client = OkHttpUtils.client() - - def setupSpec() { - port = PortUtils.randomOpenPort() - TestSparkJavaApplication.initSpark(port) - } - - def cleanupSpec() { - Spark.stop() - } - - def "generates spans"() { - setup: - def request = new Request.Builder() - .url("http://localhost:$port/param/asdf1234") - .get() - .build() - def response = client.newCall(request).execute() - - expect: - port != 0 - response.body().string() == "Hello asdf1234" - - assertTraces(1) { - trace(1) { - span { - operationName "servlet.request" - resourceName "GET /param/:param" - spanType DDSpanTypes.HTTP_SERVER - errored false - parent() - tags { - "$Tags.COMPONENT" "jetty-server" - "$Tags.SPAN_KIND" Tags.SPAN_KIND_SERVER - "$Tags.PEER_HOST_IPV4" "127.0.0.1" - "$Tags.PEER_PORT" Integer - "$Tags.HTTP_URL" "http://localhost:$port/param/asdf1234" - "$Tags.HTTP_HOSTNAME" "localhost" - "$Tags.HTTP_METHOD" "GET" - "$Tags.HTTP_STATUS" 200 - "$Tags.HTTP_ROUTE" String - "$Tags.HTTP_USER_AGENT" String - "$Tags.HTTP_CLIENT_IP" "127.0.0.1" - "$Tags.NETWORK_CLIENT_IP" "127.0.0.1" - defaultTags() - } - } - } - } - } -} diff --git a/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/test/groovy/datadog/trace/instrumentation/sparkjava/SparkJavaForkedTest.groovy b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/test/groovy/datadog/trace/instrumentation/sparkjava/SparkJavaForkedTest.groovy new file mode 100644 index 00000000000..970c60b5631 --- /dev/null +++ b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/test/groovy/datadog/trace/instrumentation/sparkjava/SparkJavaForkedTest.groovy @@ -0,0 +1,176 @@ +import datadog.trace.agent.test.base.HttpServer +import datadog.trace.agent.test.base.HttpServerTest +import spark.Spark + +import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.* +import static datadog.trace.agent.test.base.HttpServerTest.IG_RESPONSE_HEADER +import static datadog.trace.agent.test.base.HttpServerTest.IG_RESPONSE_HEADER_VALUE + +/** + * SparkJava uses static singletons for routing setup, which means tests + * that modify the server state must run in a forked JVM to avoid interference. + * This forked test ensures isolation for the SparkJava instrumentation tests. + */ +class SparkJavaForkedTest extends HttpServerTest { + + class SparkJavaServer implements HttpServer { + def port = 0 + + SparkJavaServer() { + port = datadog.trace.agent.test.utils.PortUtils.randomOpenPort() + Spark.port(port) + + Spark.get(SUCCESS.path) { req, res -> + controller(SUCCESS) { + res.status(SUCCESS.status) + SUCCESS.body + } + } + + Spark.get(FORWARDED.path) { req, res -> + controller(FORWARDED) { + res.status(FORWARDED.status) + req.headers("x-forwarded-for") + } + } + + Spark.get(QUERY_PARAM.path) { req, res -> + controller(QUERY_PARAM) { + res.status(QUERY_PARAM.status) + req.queryString() + } + } + + Spark.get(QUERY_ENCODED_BOTH.path) { req, res -> + controller(QUERY_ENCODED_BOTH) { + res.status(QUERY_ENCODED_BOTH.status) + "some=" + req.queryParams("some") + } + } + + Spark.get(QUERY_ENCODED_QUERY.path) { req, res -> + controller(QUERY_ENCODED_QUERY) { + res.status(QUERY_ENCODED_QUERY.status) + "some=" + req.queryParams("some") + } + } + + Spark.get(REDIRECT.path) { req, res -> + controller(REDIRECT) { + res.redirect(REDIRECT.body, REDIRECT.status) + null + } + } + + Spark.get(ERROR.path) { req, res -> + controller(ERROR) { + res.status(ERROR.status) + ERROR.body + } + } + + Spark.get(EXCEPTION.path) { req, res -> + controller(EXCEPTION) { + throw new Exception(EXCEPTION.body) + } + } + + Spark.post(CREATED.path) { req, res -> + controller(CREATED) { + res.status(CREATED.status) + CREATED.body + } + } + + Spark.after { req, res -> + res.header(IG_RESPONSE_HEADER, IG_RESPONSE_HEADER_VALUE) + } + } + + @Override + void start() { + Spark.awaitInitialization() + } + + @Override + void stop() { + Spark.stop() + } + + @Override + URI address() { + return new URI("http://localhost:$port/") + } + } + + @Override + HttpServer server() { + return new SparkJavaServer() + } + + @Override + String component() { + return 'spark-java' + } + + @Override + String expectedOperationName() { + return 'spark.request' + } + + @Override + protected boolean enabledFinishTimingChecks() { + true + } + + @Override + boolean redirectHasBody() { + true + } + + @Override + boolean testExceptionBody() { + false + } + + @Override + boolean hasExtraErrorInformation() { + true + } + + @Override + Map expectedExtraErrorInformation(ServerEndpoint endpoint) { + if (endpoint.throwsException) { + ["error.message": "${endpoint.body}", + "error.type": { it == Exception.name }, + "error.stack": String] + } else { + Collections.emptyMap() + } + } + + @Override + boolean testRequestBody() { + false + } + + @Override + boolean testRequestBodyISVariant() { + false + } + + @Override + boolean testBlocking() { + false + } + + @Override + boolean testBlockingOnResponse() { + false + } + + @Override + boolean testBadUrl() { + false + } +} diff --git a/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/test/groovy/datadog/trace/instrumentation/sparkjava/SparkJavaTest.groovy b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/test/groovy/datadog/trace/instrumentation/sparkjava/SparkJavaTest.groovy new file mode 100644 index 00000000000..64b578f86e4 --- /dev/null +++ b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/test/groovy/datadog/trace/instrumentation/sparkjava/SparkJavaTest.groovy @@ -0,0 +1,164 @@ +import datadog.trace.agent.test.base.HttpServer +import datadog.trace.agent.test.base.HttpServerTest +import spark.Spark + +import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.* +import static datadog.trace.agent.test.base.HttpServerTest.IG_RESPONSE_HEADER +import static datadog.trace.agent.test.base.HttpServerTest.IG_RESPONSE_HEADER_VALUE + +class SparkJavaTest extends HttpServerTest { + + class SparkJavaServer implements HttpServer { + def port = 0 + + SparkJavaServer() { + port = datadog.trace.agent.test.utils.PortUtils.randomOpenPort() + Spark.port(port) + + Spark.get(SUCCESS.path) { req, res -> + controller(SUCCESS) { + res.status(SUCCESS.status) + SUCCESS.body + } + } + + Spark.get(FORWARDED.path) { req, res -> + controller(FORWARDED) { + res.status(FORWARDED.status) + req.headers("x-forwarded-for") + } + } + + Spark.get(QUERY_PARAM.path) { req, res -> + controller(QUERY_PARAM) { + res.status(QUERY_PARAM.status) + req.queryString() + } + } + + Spark.get(QUERY_ENCODED_BOTH.path) { req, res -> + controller(QUERY_ENCODED_BOTH) { + res.status(QUERY_ENCODED_BOTH.status) + "some=" + req.queryParams("some") + } + } + + Spark.get(QUERY_ENCODED_QUERY.path) { req, res -> + controller(QUERY_ENCODED_QUERY) { + res.status(QUERY_ENCODED_QUERY.status) + "some=" + req.queryParams("some") + } + } + + Spark.get(REDIRECT.path) { req, res -> + controller(REDIRECT) { + res.redirect(REDIRECT.body, REDIRECT.status) + null + } + } + + Spark.get(ERROR.path) { req, res -> + controller(ERROR) { + res.status(ERROR.status) + ERROR.body + } + } + + Spark.get(EXCEPTION.path) { req, res -> + controller(EXCEPTION) { + throw new Exception(EXCEPTION.body) + } + } + + Spark.after { req, res -> + res.header(IG_RESPONSE_HEADER, IG_RESPONSE_HEADER_VALUE) + } + } + + @Override + void start() { + Spark.awaitInitialization() + } + + @Override + void stop() { + Spark.stop() + } + + @Override + URI address() { + return new URI("http://localhost:$port/") + } + } + + @Override + HttpServer server() { + return new SparkJavaServer() + } + + @Override + String component() { + return 'spark-java' + } + + @Override + String expectedOperationName() { + return 'spark.request' + } + + @Override + protected boolean enabledFinishTimingChecks() { + true + } + + @Override + boolean redirectHasBody() { + true + } + + @Override + boolean testExceptionBody() { + false + } + + @Override + boolean hasExtraErrorInformation() { + true + } + + @Override + Map expectedExtraErrorInformation(ServerEndpoint endpoint) { + if (endpoint.throwsException) { + ["error.message": "${endpoint.body}", + "error.type": { it == Exception.name }, + "error.stack": String] + } else { + Collections.emptyMap() + } + } + + @Override + boolean testRequestBody() { + false + } + + @Override + boolean testRequestBodyISVariant() { + false + } + + @Override + boolean testBlocking() { + false + } + + @Override + boolean testBlockingOnResponse() { + false + } + + @Override + boolean testBadUrl() { + false + } +} diff --git a/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/test/java/TestSparkJavaApplication.java b/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/test/java/TestSparkJavaApplication.java deleted file mode 100644 index 93f904c7206..00000000000 --- a/dd-java-agent/instrumentation/spark/sparkjava-2.3/src/test/java/TestSparkJavaApplication.java +++ /dev/null @@ -1,19 +0,0 @@ -import spark.Spark; - -public class TestSparkJavaApplication { - - public static void initSpark(final int port) { - Spark.port(port); - Spark.get("/", (req, res) -> "Hello World"); - - Spark.get("/param/:param", (req, res) -> "Hello " + req.params("param")); - - Spark.get( - "/exception/:param", - (req, res) -> { - throw new RuntimeException(req.params("param")); - }); - - Spark.awaitInitialization(); - } -} diff --git a/metadata/supported-configurations.json b/metadata/supported-configurations.json index 733f3736cbb..65d90eb84b9 100644 --- a/metadata/supported-configurations.json +++ b/metadata/supported-configurations.json @@ -10185,6 +10185,14 @@ "aliases": [] } ], + "DD_TRACE_SPARKJAVA_2_3_ENABLED": [ + { + "version": "A", + "type": "boolean", + "default": "false", + "aliases": ["DD_TRACE_INTEGRATION_SPARKJAVA_2_3_ENABLED", "DD_INTEGRATION_SPARKJAVA_2_3_ENABLED"] + } + ], "DD_TRACE_SPARKJAVA_2_4_ENABLED": [ { "version": "A", @@ -10193,6 +10201,22 @@ "aliases": ["DD_TRACE_INTEGRATION_SPARKJAVA_2_4_ENABLED", "DD_INTEGRATION_SPARKJAVA_2_4_ENABLED"] } ], + "DD_TRACE_SPARKJAVA_ANALYTICS_ENABLED": [ + { + "version": "A", + "type": "boolean", + "default": "false", + "aliases": ["DD_SPARKJAVA_ANALYTICS_ENABLED"] + } + ], + "DD_TRACE_SPARKJAVA_ANALYTICS_SAMPLE_RATE": [ + { + "version": "A", + "type": "decimal", + "default": "1.0", + "aliases": ["DD_SPARKJAVA_ANALYTICS_SAMPLE_RATE"] + } + ], "DD_TRACE_SPARKJAVA_ENABLED": [ { "version": "A",