Set resource name using the route pattern from spring.
This provides a better static resorce name than trying to conjure one out of the original URL.
MODIFY
dd-java-agent/dd-java-agent.gradle
dd-java-agent/dd-java-agent.gradle
@@ -18,9 +18,13 @@ whitelistedInstructionClasses += whitelistedBranchClasses += [
dependencies {
compile project(':dd-trace')
+ compile project(':dd-java-agent:tooling')
compile project(':dd-trace-annotations')
- compile group: 'net.bytebuddy', name: 'byte-buddy', version: '1.7.6'
+
+ compile project(':dd-java-agent:integrations:spring-web')
+
+ compile deps.bytebuddy
compile group: 'org.jboss.byteman', name: 'byteman', version: '3.0.10'
compile group: 'com.google.auto.service', name: 'auto-service', version: '1.0-rc3'

ADD
dd-java-agent/integrations/spring-web/spring-web.gradle
+//apply plugin: 'version-scan'
+//
+//versionScan {
+// group = 'org.springframework'
+// module = 'spring-webmvc'
+// legacyModule = "servlet-api"
+// versions = "[3.0,)"
+// verifyPresent = [
+// "javax.servlet.AsyncEvent" : null,
+// "javax.servlet.AsyncListener": null,
+// ]
+//}
+
+apply from: "${rootDir}/gradle/java.gradle"
+
+dependencies {
+ compileOnly group: 'org.springframework', name: 'spring-webmvc', version: '4.0.0.RELEASE'
+ compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0'
+// compileOnly group: 'org.springframework', name: 'spring-webmvc', version: '2.5.6'
+// compileOnly group: 'javax.servlet', name: 'servlet-api', version: '2.4'
+
+ compile project(':dd-trace')
+ compile project(':dd-java-agent:tooling')
+
+ compile deps.bytebuddy
+ compile deps.opentracing
+
+ compile group: 'com.google.auto.service', name: 'auto-service', version: '1.0-rc3'
+}

ADD
dd-java-agent/integrations/spring-web/src/main/java/dd/inst/springweb/SpringWebInstrumentation.java
+package dd.inst.springweb;
+
+import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
+import static net.bytebuddy.matcher.ElementMatchers.isInterface;
+import static net.bytebuddy.matcher.ElementMatchers.isMethod;
+import static net.bytebuddy.matcher.ElementMatchers.isPublic;
+import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static net.bytebuddy.matcher.ElementMatchers.not;
+import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
+
+import com.datadoghq.trace.DDTags;
+import com.google.auto.service.AutoService;
+import dd.trace.Instrumenter;
+import io.opentracing.ActiveSpan;
+import io.opentracing.util.GlobalTracer;
+import java.sql.PreparedStatement;
+import java.util.Map;
+import java.util.WeakHashMap;
+import javax.servlet.http.HttpServletRequest;
+import net.bytebuddy.agent.builder.AgentBuilder;
+import net.bytebuddy.asm.Advice;
+import org.springframework.web.servlet.HandlerMapping;
+
+@AutoService(Instrumenter.class)
+public final class SpringWebInstrumentation implements Instrumenter {
+ public static final Map<PreparedStatement, String> preparedStatements = new WeakHashMap<>();
+
+ @Override
+ public AgentBuilder instrument(final AgentBuilder agentBuilder) {
+ return agentBuilder
+ .type(
+ not(isInterface())
+ .and(hasSuperType(named("org.springframework.web.servlet.HandlerAdapter"))))
+ .transform(
+ new AgentBuilder.Transformer.ForAdvice()
+ .advice(
+ isMethod()
+ .and(isPublic())
+ .and(nameStartsWith("handle"))
+ .and(takesArgument(0, named("javax.servlet.http.HttpServletRequest"))),
+ SpringWebAdvice.class.getName()));
+ }
+
+ public static class SpringWebAdvice {
+
+ @Advice.OnMethodEnter
+ public static void nameResource(@Advice.Argument(0) final HttpServletRequest request) {
+ final ActiveSpan span = GlobalTracer.get().activeSpan();
+ if (span != null) {
+ final String method = request.getMethod();
+ final String bestMatchingPattern =
+ request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE).toString();
+ final String resourceName = method + " " + bestMatchingPattern;
+ span.setTag(DDTags.RESOURCE_NAME, resourceName);
+ }
+ }
+ }
+}

MODIFY
dd-java-agent/src/main/java/com/datadoghq/agent/TracingAgent.java
dd-java-agent/src/main/java/com/datadoghq/agent/TracingAgent.java
@@ -23,7 +23,7 @@ import static net.bytebuddy.matcher.ElementMatchers.isBootstrapClassLoader;
import static net.bytebuddy.matcher.ElementMatchers.nameContains;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
-import com.datadoghq.agent.instrumentation.Instrumenter;
+import dd.trace.Instrumenter;
import java.lang.instrument.Instrumentation;
import java.util.ServiceLoader;
import lombok.extern.slf4j.Slf4j;
@@ -71,6 +71,9 @@ public class TracingAgent {
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.with(new Listener())
.ignore(nameStartsWith("com.datadoghq.agent.integration"))
+ .or(nameStartsWith("dd.trace"))
+ .or(nameStartsWith("dd.inst"))
+ .or(nameStartsWith("dd.deps"))
.or(nameStartsWith("java."))
.or(nameStartsWith("com.sun."))
.or(nameStartsWith("sun."))

MODIFY
dd-java-agent/src/main/java/com/datadoghq/agent/instrumentation/annotation/TraceAnnotationInstrumentation.java
dd-java-agent/src/main/java/com/datadoghq/agent/instrumentation/annotation/TraceAnnotationInstrumentation.java
@@ -4,9 +4,9 @@ import static net.bytebuddy.matcher.ElementMatchers.declaresMethod;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
-import com.datadoghq.agent.instrumentation.Instrumenter;
import com.datadoghq.trace.Trace;
import com.google.auto.service.AutoService;
+import dd.trace.Instrumenter;
import io.opentracing.ActiveSpan;
import io.opentracing.tag.Tags;
import io.opentracing.util.GlobalTracer;

MODIFY
dd-java-agent/src/main/java/com/datadoghq/agent/instrumentation/jdbc/ConnectionInstrumentation.java
dd-java-agent/src/main/java/com/datadoghq/agent/instrumentation/jdbc/ConnectionInstrumentation.java
@@ -8,8 +8,8 @@ import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
-import com.datadoghq.agent.instrumentation.Instrumenter;
import com.google.auto.service.AutoService;
+import dd.trace.Instrumenter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Map;

MODIFY
dd-java-agent/src/main/java/com/datadoghq/agent/instrumentation/jdbc/DriverInstrumentation.java
dd-java-agent/src/main/java/com/datadoghq/agent/instrumentation/jdbc/DriverInstrumentation.java
@@ -6,8 +6,8 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
-import com.datadoghq.agent.instrumentation.Instrumenter;
import com.google.auto.service.AutoService;
+import dd.trace.Instrumenter;
import java.sql.Connection;
import java.sql.Driver;
import java.util.Map;

MODIFY
dd-java-agent/src/main/java/com/datadoghq/agent/instrumentation/jdbc/PreparedStatementInstrumentation.java
dd-java-agent/src/main/java/com/datadoghq/agent/instrumentation/jdbc/PreparedStatementInstrumentation.java
@@ -8,9 +8,9 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
-import com.datadoghq.agent.instrumentation.Instrumenter;
import com.datadoghq.trace.DDTags;
import com.google.auto.service.AutoService;
+import dd.trace.Instrumenter;
import io.opentracing.ActiveSpan;
import io.opentracing.NoopActiveSpanSource;
import io.opentracing.tag.Tags;

MODIFY
dd-java-agent/src/main/java/com/datadoghq/agent/instrumentation/jdbc/StatementInstrumentation.java
dd-java-agent/src/main/java/com/datadoghq/agent/instrumentation/jdbc/StatementInstrumentation.java
@@ -8,9 +8,9 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
-import com.datadoghq.agent.instrumentation.Instrumenter;
import com.datadoghq.trace.DDTags;
import com.google.auto.service.AutoService;
+import dd.trace.Instrumenter;
import io.opentracing.ActiveSpan;
import io.opentracing.NoopActiveSpanSource;
import io.opentracing.tag.Tags;

RENAME
dd-java-agent/src/main/java/com/datadoghq/agent/instrumentation/Instrumenter.java
dd-java-agent/tooling/src/main/java/dd/trace/Instrumenter.java
-package com.datadoghq.agent.instrumentation;
+package dd.trace;
import net.bytebuddy.agent.builder.AgentBuilder;

ADD
dd-java-agent/tooling/tooling.gradle
+apply from: "${rootDir}/gradle/java.gradle"
+
+dependencies {
+ compile deps.bytebuddy
+}

MODIFY
gradle/dependencies.gradle
gradle/dependencies.gradle
@@ -29,6 +29,7 @@ ext {
dependencies.create(group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: version.jackson),
dependencies.create(group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: version.jackson),
],
+ bytebuddy : dependencies.create(group: 'net.bytebuddy', name: 'byte-buddy', version: '1.7.6'),
// Testing
spock : dependencies.create("org.spockframework:spock-core:${version.spock}", {

MODIFY
settings.gradle
settings.gradle
@@ -2,6 +2,7 @@ rootProject.name = 'dd-trace-java'
include ':dd-trace'
include ':dd-java-agent'
+include ':dd-java-agent:tooling'
include ':dd-java-agent-ittests'
include ':dd-trace-examples:async-tracing'
include ':dd-trace-examples:dropwizard-mongo-client'
@@ -21,6 +22,7 @@ include ':dd-java-agent:integrations:mongo-async'
include ':dd-java-agent:integrations:okhttp'
include ':dd-java-agent:integrations:servlet-2'
include ':dd-java-agent:integrations:servlet-3'
+include ':dd-java-agent:integrations:spring-web'
def setBuildFile(project) {
project.buildFileName = "${project.name}.gradle"

Set resource name using the route pattern from spring.

This provides a better static resorce name than trying to conjure one out of the original URL.