Merge pull request #910 from DataDog/labbati/jersey-1.19
Extend support for Jersey client to 1.9+
This commit is contained in:
commit
a13e4a0229
|
@ -107,7 +107,12 @@ public class AgentInstaller {
|
||||||
// Working around until a long-term fix for modules can be
|
// Working around until a long-term fix for modules can be
|
||||||
// put in place.
|
// put in place.
|
||||||
.and(not(named("java.util.logging.LogManager$Cleaner")))))))
|
.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(
|
.or(
|
||||||
nameStartsWith("sun.")
|
nameStartsWith("sun.")
|
||||||
.and(
|
.and(
|
||||||
|
|
|
@ -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: '+'
|
||||||
|
}
|
|
@ -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<String, Object> map;
|
||||||
|
|
||||||
|
public InjectAdapter(final MultivaluedMap<String, Object> map) {
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Map.Entry<String, String>> 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<ClientRequest, ClientResponse> {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<TypeDescription> 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<? extends ElementMatcher<? super MethodDescription>, 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<JaxRsClientV1Decorator> {
|
||||||
|
|
||||||
|
@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<String, String> 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
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,5 +18,5 @@ dependencies {
|
||||||
|
|
||||||
compile project(':dd-java-agent:agent-tooling')
|
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')
|
||||||
}
|
}
|
|
@ -18,5 +18,5 @@ dependencies {
|
||||||
|
|
||||||
compile project(':dd-java-agent:agent-tooling')
|
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')
|
||||||
}
|
}
|
|
@ -37,8 +37,8 @@ dependencies {
|
||||||
testCompile project(':dd-java-agent:testing')
|
testCompile project(':dd-java-agent:testing')
|
||||||
testCompile project(':dd-java-agent:instrumentation:java-concurrent')
|
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-2.0: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-resteasy')
|
||||||
|
|
||||||
testCompile group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.0.1'
|
testCompile group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.0.1'
|
||||||
|
|
|
@ -31,8 +31,6 @@ public class ClientTracingFilter implements ClientRequestFilter, ClientResponseF
|
||||||
DECORATE.afterStart(span);
|
DECORATE.afterStart(span);
|
||||||
DECORATE.onRequest(span, requestContext);
|
DECORATE.onRequest(span, requestContext);
|
||||||
|
|
||||||
log.debug("{} - client span started", span);
|
|
||||||
|
|
||||||
GlobalTracer.get()
|
GlobalTracer.get()
|
||||||
.inject(
|
.inject(
|
||||||
span.context(),
|
span.context(),
|
||||||
|
@ -52,7 +50,6 @@ public class ClientTracingFilter implements ClientRequestFilter, ClientResponseF
|
||||||
DECORATE.onResponse(span, responseContext);
|
DECORATE.onResponse(span, responseContext);
|
||||||
DECORATE.beforeFinish(span);
|
DECORATE.beforeFinish(span);
|
||||||
span.finish();
|
span.finish();
|
||||||
log.debug("{} - client spanObj finished", spanObj);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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:http-url-connection'
|
||||||
include ':dd-java-agent:instrumentation:hystrix-1.4'
|
include ':dd-java-agent:instrumentation:hystrix-1.4'
|
||||||
include ':dd-java-agent:instrumentation:jax-rs-annotations'
|
include ':dd-java-agent:instrumentation:jax-rs-annotations'
|
||||||
include ':dd-java-agent:instrumentation:jax-rs-client'
|
include ':dd-java-agent:instrumentation:jax-rs-client-1.9'
|
||||||
include ':dd-java-agent:instrumentation:jax-rs-client:connection-error-handling-jersey'
|
include ':dd-java-agent:instrumentation:jax-rs-client-2.0'
|
||||||
include ':dd-java-agent:instrumentation:jax-rs-client:connection-error-handling-resteasy'
|
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'
|
||||||
include ':dd-java-agent:instrumentation:java-concurrent:kotlin-testing'
|
include ':dd-java-agent:instrumentation:java-concurrent:kotlin-testing'
|
||||||
include ':dd-java-agent:instrumentation:java-concurrent:scala-testing'
|
include ':dd-java-agent:instrumentation:java-concurrent:scala-testing'
|
||||||
|
|
Loading…
Reference in New Issue