diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AgentInstaller.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AgentInstaller.java index b51197d4ad..7af1543707 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AgentInstaller.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AgentInstaller.java @@ -107,7 +107,12 @@ public class AgentInstaller { // Working around until a long-term fix for modules can be // put in place. .and(not(named("java.util.logging.LogManager$Cleaner"))))))) - .or(nameStartsWith("com.sun.").and(not(nameStartsWith("com.sun.messaging.")))) + .or( + nameStartsWith("com.sun.") + .and( + not( + nameStartsWith("com.sun.messaging.") + .or(nameStartsWith("com.sun.jersey.api.client"))))) .or( nameStartsWith("sun.") .and( diff --git a/dd-java-agent/instrumentation/jax-rs-client-1.9/jax-rs-client-1.9.gradle b/dd-java-agent/instrumentation/jax-rs-client-1.9/jax-rs-client-1.9.gradle new file mode 100644 index 0000000000..395265d0ec --- /dev/null +++ b/dd-java-agent/instrumentation/jax-rs-client-1.9/jax-rs-client-1.9.gradle @@ -0,0 +1,40 @@ +muzzle { + pass { + group = "com.sun.jersey" + module = "jersey-client" + versions = "[1.9,)" + // We can't assert inverse because 1.1.5.2 was a weird release that also works. + } + fail { + group = "com.sun.jersey" + module = "jersey-client" + versions = "[1.2,1.9)" + } +} + +apply from: "${rootDir}/gradle/java.gradle" + +apply plugin: 'org.unbroken-dome.test-sets' + +testSets { + latestDepTest { + dirName = 'test' + } +} + +dependencies { + compileOnly group: 'com.sun.jersey', name: 'jersey-client', version: '1.9' + + compile deps.bytebuddy + compile deps.opentracing + annotationProcessor deps.autoservice + implementation deps.autoservice + + compile project(':dd-java-agent:agent-tooling') + + testCompile project(':dd-java-agent:testing') + + testCompile group: 'com.sun.jersey', name: 'jersey-client', version: '1.9' + + latestDepTestCompile group: 'com.sun.jersey', name: 'jersey-client', version: '+' +} diff --git a/dd-java-agent/instrumentation/jax-rs-client-1.9/src/main/java/datadog/trace/instrumentation/jaxrs/v1/InjectAdapter.java b/dd-java-agent/instrumentation/jax-rs-client-1.9/src/main/java/datadog/trace/instrumentation/jaxrs/v1/InjectAdapter.java new file mode 100644 index 0000000000..98f4ec6c5a --- /dev/null +++ b/dd-java-agent/instrumentation/jax-rs-client-1.9/src/main/java/datadog/trace/instrumentation/jaxrs/v1/InjectAdapter.java @@ -0,0 +1,26 @@ +package datadog.trace.instrumentation.jaxrs.v1; + +import io.opentracing.propagation.TextMap; +import java.util.Iterator; +import java.util.Map; +import javax.ws.rs.core.MultivaluedMap; + +public final class InjectAdapter implements TextMap { + private final MultivaluedMap map; + + public InjectAdapter(final MultivaluedMap map) { + this.map = map; + } + + @Override + public Iterator> iterator() { + throw new UnsupportedOperationException( + "InjectAdapter should only be used with Tracer.inject()"); + } + + @Override + public void put(final String key, final String value) { + // Don't allow duplicates. + map.putSingle(key, value); + } +} diff --git a/dd-java-agent/instrumentation/jax-rs-client-1.9/src/main/java/datadog/trace/instrumentation/jaxrs/v1/JaxRsClientV1Decorator.java b/dd-java-agent/instrumentation/jax-rs-client-1.9/src/main/java/datadog/trace/instrumentation/jaxrs/v1/JaxRsClientV1Decorator.java new file mode 100644 index 0000000000..0ee31cef43 --- /dev/null +++ b/dd-java-agent/instrumentation/jax-rs-client-1.9/src/main/java/datadog/trace/instrumentation/jaxrs/v1/JaxRsClientV1Decorator.java @@ -0,0 +1,45 @@ +package datadog.trace.instrumentation.jaxrs.v1; + +import com.sun.jersey.api.client.ClientRequest; +import com.sun.jersey.api.client.ClientResponse; +import datadog.trace.agent.decorator.HttpClientDecorator; +import java.net.URI; + +public class JaxRsClientV1Decorator extends HttpClientDecorator { + public static final JaxRsClientV1Decorator DECORATE = new JaxRsClientV1Decorator(); + + @Override + protected String[] instrumentationNames() { + return new String[] {"jax-rs", "jaxrs", "jax-rs-client"}; + } + + @Override + protected String component() { + return "jax-rs.client"; + } + + @Override + protected String method(final ClientRequest httpRequest) { + return httpRequest.getMethod(); + } + + @Override + protected URI url(final ClientRequest httpRequest) { + return httpRequest.getURI(); + } + + @Override + protected String hostname(final ClientRequest httpRequest) { + return httpRequest.getURI().getHost(); + } + + @Override + protected Integer port(final ClientRequest httpRequest) { + return httpRequest.getURI().getPort(); + } + + @Override + protected Integer status(ClientResponse clientResponse) { + return clientResponse.getStatus(); + } +} diff --git a/dd-java-agent/instrumentation/jax-rs-client-1.9/src/main/java/datadog/trace/instrumentation/jaxrs/v1/JaxRsClientV1Instrumentation.java b/dd-java-agent/instrumentation/jax-rs-client-1.9/src/main/java/datadog/trace/instrumentation/jaxrs/v1/JaxRsClientV1Instrumentation.java new file mode 100644 index 0000000000..517fc5a94c --- /dev/null +++ b/dd-java-agent/instrumentation/jax-rs-client-1.9/src/main/java/datadog/trace/instrumentation/jaxrs/v1/JaxRsClientV1Instrumentation.java @@ -0,0 +1,102 @@ +package datadog.trace.instrumentation.jaxrs.v1; + +import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType; +import static datadog.trace.instrumentation.jaxrs.v1.JaxRsClientV1Decorator.DECORATE; +import static java.util.Collections.singletonMap; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.returns; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import com.google.auto.service.AutoService; +import com.sun.jersey.api.client.ClientHandler; +import com.sun.jersey.api.client.ClientRequest; +import com.sun.jersey.api.client.ClientResponse; +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.api.DDTags; +import io.opentracing.Scope; +import io.opentracing.Span; +import io.opentracing.Tracer; +import io.opentracing.propagation.Format; +import io.opentracing.util.GlobalTracer; +import java.util.Map; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +@AutoService(Instrumenter.class) +public final class JaxRsClientV1Instrumentation extends Instrumenter.Default { + + public JaxRsClientV1Instrumentation() { + super("jax-rs", "jaxrs", "jax-rs-client"); + } + + @Override + public ElementMatcher typeMatcher() { + return safeHasSuperType(named("com.sun.jersey.api.client.ClientHandler")); + } + + @Override + public String[] helperClassNames() { + return new String[] { + "datadog.trace.agent.decorator.BaseDecorator", + "datadog.trace.agent.decorator.ClientDecorator", + "datadog.trace.agent.decorator.HttpClientDecorator", + packageName + ".JaxRsClientV1Decorator", + packageName + ".InjectAdapter", + }; + } + + @Override + public Map, String> transformers() { + return singletonMap( + named("handle") + .and( + takesArgument( + 0, safeHasSuperType(named("com.sun.jersey.api.client.ClientRequest")))) + .and(returns(safeHasSuperType(named("com.sun.jersey.api.client.ClientResponse")))), + HandleAdvice.class.getName()); + } + + public static class HandleAdvice { + + @Advice.OnMethodEnter + public static Scope onEnter( + @Advice.Argument(value = 0) final ClientRequest request, + @Advice.This final ClientHandler thisObj) { + + // WARNING: this might be a chain...so we only have to trace the first in the chain. + final boolean isRootClientHandler = null == request.getProperties().get("dd.span"); + if (isRootClientHandler) { + final Tracer tracer = GlobalTracer.get(); + final Span span = + tracer + .buildSpan("jax-rs.client.call") + .withTag(DDTags.RESOURCE_NAME, request.getMethod() + " jax-rs.client.call") + .start(); + DECORATE.afterStart(span); + DECORATE.onRequest(span, request); + request.getProperties().put("dd.span", span); + + tracer.inject( + span.context(), Format.Builtin.HTTP_HEADERS, new InjectAdapter(request.getHeaders())); + return tracer.scopeManager().activate(span, true); + } + return null; + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void onExit( + @Advice.Enter final Scope scope, + @Advice.Return final ClientResponse response, + @Advice.Thrown final Throwable throwable) { + if (null != scope) { + final Span span = scope.span(); + DECORATE.onResponse(span, response); + DECORATE.onError(span, throwable); + DECORATE.beforeFinish(span); + scope.close(); + } + } + } +} diff --git a/dd-java-agent/instrumentation/jax-rs-client-1.9/src/test/groovy/JaxRsClientV1Test.groovy b/dd-java-agent/instrumentation/jax-rs-client-1.9/src/test/groovy/JaxRsClientV1Test.groovy new file mode 100644 index 0000000000..ac24e76c2a --- /dev/null +++ b/dd-java-agent/instrumentation/jax-rs-client-1.9/src/test/groovy/JaxRsClientV1Test.groovy @@ -0,0 +1,46 @@ +import com.sun.jersey.api.client.Client +import com.sun.jersey.api.client.ClientResponse +import com.sun.jersey.api.client.filter.CsrfProtectionFilter +import com.sun.jersey.api.client.filter.GZIPContentEncodingFilter +import com.sun.jersey.api.client.filter.LoggingFilter +import datadog.trace.agent.test.base.HttpClientTest +import datadog.trace.instrumentation.jaxrs.v1.JaxRsClientV1Decorator +import spock.lang.Shared + +class JaxRsClientV1Test extends HttpClientTest { + + @Shared + Client client = Client.create() + + def setupSpec() { + // Add filters to ensure spans aren't duplicated. + client.addFilter(new LoggingFilter()) + client.addFilter(new GZIPContentEncodingFilter()) + client.addFilter(new CsrfProtectionFilter()) + } + + @Override + int doRequest(String method, URI uri, Map headers, Closure callback) { + def resource = client.resource(uri).requestBuilder + headers.each { resource.header(it.key, it.value) } + def body = BODY_METHODS.contains(method) ? "" : null + ClientResponse response = resource.method(method, ClientResponse, body) + callback?.call() + + return response.status + } + + @Override + JaxRsClientV1Decorator decorator() { + return JaxRsClientV1Decorator.DECORATE + } + + @Override + String expectedOperationName() { + return "jax-rs.client.call" + } + + boolean testRedirects() { + false + } +} diff --git a/dd-java-agent/instrumentation/jax-rs-client/connection-error-handling-jersey/connection-error-handling-jersey.gradle b/dd-java-agent/instrumentation/jax-rs-client-2.0/connection-error-handling-jersey/connection-error-handling-jersey.gradle similarity index 98% rename from dd-java-agent/instrumentation/jax-rs-client/connection-error-handling-jersey/connection-error-handling-jersey.gradle rename to dd-java-agent/instrumentation/jax-rs-client-2.0/connection-error-handling-jersey/connection-error-handling-jersey.gradle index 4176977ab8..e52bb3dc2f 100644 --- a/dd-java-agent/instrumentation/jax-rs-client/connection-error-handling-jersey/connection-error-handling-jersey.gradle +++ b/dd-java-agent/instrumentation/jax-rs-client-2.0/connection-error-handling-jersey/connection-error-handling-jersey.gradle @@ -18,5 +18,5 @@ dependencies { compile project(':dd-java-agent:agent-tooling') - compileOnly project(':dd-java-agent:instrumentation:jax-rs-client') + compileOnly project(':dd-java-agent:instrumentation:jax-rs-client-2.0') } diff --git a/dd-java-agent/instrumentation/jax-rs-client/connection-error-handling-jersey/src/main/java/datadog/trace/instrumentation/connection_error/jersey/JerseyClientConnectionErrorInstrumentation.java b/dd-java-agent/instrumentation/jax-rs-client-2.0/connection-error-handling-jersey/src/main/java/datadog/trace/instrumentation/connection_error/jersey/JerseyClientConnectionErrorInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/jax-rs-client/connection-error-handling-jersey/src/main/java/datadog/trace/instrumentation/connection_error/jersey/JerseyClientConnectionErrorInstrumentation.java rename to dd-java-agent/instrumentation/jax-rs-client-2.0/connection-error-handling-jersey/src/main/java/datadog/trace/instrumentation/connection_error/jersey/JerseyClientConnectionErrorInstrumentation.java diff --git a/dd-java-agent/instrumentation/jax-rs-client/connection-error-handling-resteasy/connection-error-handling-resteasy.gradle b/dd-java-agent/instrumentation/jax-rs-client-2.0/connection-error-handling-resteasy/connection-error-handling-resteasy.gradle similarity index 98% rename from dd-java-agent/instrumentation/jax-rs-client/connection-error-handling-resteasy/connection-error-handling-resteasy.gradle rename to dd-java-agent/instrumentation/jax-rs-client-2.0/connection-error-handling-resteasy/connection-error-handling-resteasy.gradle index cbcc82521f..d0ff0a908a 100644 --- a/dd-java-agent/instrumentation/jax-rs-client/connection-error-handling-resteasy/connection-error-handling-resteasy.gradle +++ b/dd-java-agent/instrumentation/jax-rs-client-2.0/connection-error-handling-resteasy/connection-error-handling-resteasy.gradle @@ -18,5 +18,5 @@ dependencies { compile project(':dd-java-agent:agent-tooling') - compileOnly project(':dd-java-agent:instrumentation:jax-rs-client') + compileOnly project(':dd-java-agent:instrumentation:jax-rs-client-2.0') } diff --git a/dd-java-agent/instrumentation/jax-rs-client/connection-error-handling-resteasy/src/main/java/datadog/trace/instrumentation/connection_error/resteasy/ResteasyClientConnectionErrorInstrumentation.java b/dd-java-agent/instrumentation/jax-rs-client-2.0/connection-error-handling-resteasy/src/main/java/datadog/trace/instrumentation/connection_error/resteasy/ResteasyClientConnectionErrorInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/jax-rs-client/connection-error-handling-resteasy/src/main/java/datadog/trace/instrumentation/connection_error/resteasy/ResteasyClientConnectionErrorInstrumentation.java rename to dd-java-agent/instrumentation/jax-rs-client-2.0/connection-error-handling-resteasy/src/main/java/datadog/trace/instrumentation/connection_error/resteasy/ResteasyClientConnectionErrorInstrumentation.java diff --git a/dd-java-agent/instrumentation/jax-rs-client/jax-rs-client.gradle b/dd-java-agent/instrumentation/jax-rs-client-2.0/jax-rs-client-2.0.gradle similarity index 95% rename from dd-java-agent/instrumentation/jax-rs-client/jax-rs-client.gradle rename to dd-java-agent/instrumentation/jax-rs-client-2.0/jax-rs-client-2.0.gradle index 17017e084b..b862293722 100644 --- a/dd-java-agent/instrumentation/jax-rs-client/jax-rs-client.gradle +++ b/dd-java-agent/instrumentation/jax-rs-client-2.0/jax-rs-client-2.0.gradle @@ -37,8 +37,8 @@ dependencies { testCompile project(':dd-java-agent:testing') testCompile project(':dd-java-agent:instrumentation:java-concurrent') - testCompile project(':dd-java-agent:instrumentation:jax-rs-client:connection-error-handling-jersey') - testCompile project(':dd-java-agent:instrumentation:jax-rs-client:connection-error-handling-resteasy') + testCompile project(':dd-java-agent:instrumentation:jax-rs-client-2.0:connection-error-handling-jersey') + testCompile project(':dd-java-agent:instrumentation:jax-rs-client-2.0:connection-error-handling-resteasy') testCompile group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.0.1' diff --git a/dd-java-agent/instrumentation/jax-rs-client/src/main/java/datadog/trace/instrumentation/jaxrs/ClientTracingFeature.java b/dd-java-agent/instrumentation/jax-rs-client-2.0/src/main/java/datadog/trace/instrumentation/jaxrs/ClientTracingFeature.java similarity index 100% rename from dd-java-agent/instrumentation/jax-rs-client/src/main/java/datadog/trace/instrumentation/jaxrs/ClientTracingFeature.java rename to dd-java-agent/instrumentation/jax-rs-client-2.0/src/main/java/datadog/trace/instrumentation/jaxrs/ClientTracingFeature.java diff --git a/dd-java-agent/instrumentation/jax-rs-client/src/main/java/datadog/trace/instrumentation/jaxrs/ClientTracingFilter.java b/dd-java-agent/instrumentation/jax-rs-client-2.0/src/main/java/datadog/trace/instrumentation/jaxrs/ClientTracingFilter.java similarity index 94% rename from dd-java-agent/instrumentation/jax-rs-client/src/main/java/datadog/trace/instrumentation/jaxrs/ClientTracingFilter.java rename to dd-java-agent/instrumentation/jax-rs-client-2.0/src/main/java/datadog/trace/instrumentation/jaxrs/ClientTracingFilter.java index a32c1942d4..d3e54a4c2b 100644 --- a/dd-java-agent/instrumentation/jax-rs-client/src/main/java/datadog/trace/instrumentation/jaxrs/ClientTracingFilter.java +++ b/dd-java-agent/instrumentation/jax-rs-client-2.0/src/main/java/datadog/trace/instrumentation/jaxrs/ClientTracingFilter.java @@ -31,8 +31,6 @@ public class ClientTracingFilter implements ClientRequestFilter, ClientResponseF DECORATE.afterStart(span); DECORATE.onRequest(span, requestContext); - log.debug("{} - client span started", span); - GlobalTracer.get() .inject( span.context(), @@ -52,7 +50,6 @@ public class ClientTracingFilter implements ClientRequestFilter, ClientResponseF DECORATE.onResponse(span, responseContext); DECORATE.beforeFinish(span); span.finish(); - log.debug("{} - client spanObj finished", spanObj); } } } diff --git a/dd-java-agent/instrumentation/jax-rs-client/src/main/java/datadog/trace/instrumentation/jaxrs/InjectAdapter.java b/dd-java-agent/instrumentation/jax-rs-client-2.0/src/main/java/datadog/trace/instrumentation/jaxrs/InjectAdapter.java similarity index 100% rename from dd-java-agent/instrumentation/jax-rs-client/src/main/java/datadog/trace/instrumentation/jaxrs/InjectAdapter.java rename to dd-java-agent/instrumentation/jax-rs-client-2.0/src/main/java/datadog/trace/instrumentation/jaxrs/InjectAdapter.java diff --git a/dd-java-agent/instrumentation/jax-rs-client/src/main/java/datadog/trace/instrumentation/jaxrs/JaxRsClientDecorator.java b/dd-java-agent/instrumentation/jax-rs-client-2.0/src/main/java/datadog/trace/instrumentation/jaxrs/JaxRsClientDecorator.java similarity index 100% rename from dd-java-agent/instrumentation/jax-rs-client/src/main/java/datadog/trace/instrumentation/jaxrs/JaxRsClientDecorator.java rename to dd-java-agent/instrumentation/jax-rs-client-2.0/src/main/java/datadog/trace/instrumentation/jaxrs/JaxRsClientDecorator.java diff --git a/dd-java-agent/instrumentation/jax-rs-client/src/main/java/datadog/trace/instrumentation/jaxrs/JaxRsClientInstrumentation.java b/dd-java-agent/instrumentation/jax-rs-client-2.0/src/main/java/datadog/trace/instrumentation/jaxrs/JaxRsClientInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/jax-rs-client/src/main/java/datadog/trace/instrumentation/jaxrs/JaxRsClientInstrumentation.java rename to dd-java-agent/instrumentation/jax-rs-client-2.0/src/main/java/datadog/trace/instrumentation/jaxrs/JaxRsClientInstrumentation.java diff --git a/dd-java-agent/instrumentation/jax-rs-client/src/test/groovy/JaxRsClientAsyncTest.groovy b/dd-java-agent/instrumentation/jax-rs-client-2.0/src/test/groovy/JaxRsClientAsyncTest.groovy similarity index 100% rename from dd-java-agent/instrumentation/jax-rs-client/src/test/groovy/JaxRsClientAsyncTest.groovy rename to dd-java-agent/instrumentation/jax-rs-client-2.0/src/test/groovy/JaxRsClientAsyncTest.groovy diff --git a/dd-java-agent/instrumentation/jax-rs-client/src/test/groovy/JaxRsClientTest.groovy b/dd-java-agent/instrumentation/jax-rs-client-2.0/src/test/groovy/JaxRsClientTest.groovy similarity index 100% rename from dd-java-agent/instrumentation/jax-rs-client/src/test/groovy/JaxRsClientTest.groovy rename to dd-java-agent/instrumentation/jax-rs-client-2.0/src/test/groovy/JaxRsClientTest.groovy diff --git a/settings.gradle b/settings.gradle index 23b68dd31f..dcd99258c7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -49,9 +49,10 @@ include ':dd-java-agent:instrumentation:hibernate:core-4.3' include ':dd-java-agent:instrumentation:http-url-connection' include ':dd-java-agent:instrumentation:hystrix-1.4' include ':dd-java-agent:instrumentation:jax-rs-annotations' -include ':dd-java-agent:instrumentation:jax-rs-client' -include ':dd-java-agent:instrumentation:jax-rs-client:connection-error-handling-jersey' -include ':dd-java-agent:instrumentation:jax-rs-client:connection-error-handling-resteasy' +include ':dd-java-agent:instrumentation:jax-rs-client-1.9' +include ':dd-java-agent:instrumentation:jax-rs-client-2.0' +include ':dd-java-agent:instrumentation:jax-rs-client-2.0:connection-error-handling-jersey' +include ':dd-java-agent:instrumentation:jax-rs-client-2.0:connection-error-handling-resteasy' include ':dd-java-agent:instrumentation:java-concurrent' include ':dd-java-agent:instrumentation:java-concurrent:kotlin-testing' include ':dd-java-agent:instrumentation:java-concurrent:scala-testing'