First draft of jersey 1.19 client instrumentation

This commit is contained in:
Luca Abbati 2019-07-09 21:13:00 -04:00
parent 2e62ca8497
commit b62266fd52
No known key found for this signature in database
GPG Key ID: 74DBB952D9BA17F2
5 changed files with 228 additions and 0 deletions

View File

@ -0,0 +1,57 @@
ext {
jerseyClientVersion = '1.19.1'
}
muzzle {
pass {
group = "javax.ws.rs"
module = "javax.ws.rs-api"
versions = "[1.0,2.0)"
}
// pass {
// // We want to support the dropwizard clients too.
// group = 'io.dropwizard'
// module = 'dropwizard-client'
// versions = "[0.8.0,)"
// assertInverse = true
// }
}
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: jerseyClientVersion
//compileOnly group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.0.1'
//compileOnly group: 'javax.annotation', name: 'javax.annotation-api', version: '1.2'
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 project(':dd-java-agent:instrumentation:java-concurrent')
testCompile group: 'com.sun.jersey', name: 'jersey-client', version: jerseyClientVersion
// testCompile group: 'org.apache.cxf', name: 'cxf-rt-rs-client', version: '3.1.0'
// Doesn't work with CXF 3.0.x because their context is wrong:
// https://github.com/apache/cxf/commit/335c7bad2436f08d6d54180212df5a52157c9f21
// testCompile group: 'javax.xml.bind', name: 'jaxb-api', version: '2.2.3'
// latestDepTestCompile group: 'org.glassfish.jersey.inject', name: 'jersey-hk2', version: '2.27'
latestDepTestCompile group: 'com.sun.jersey', name: 'jersey-client', version: jerseyClientVersion
// latestDepTestCompile group: 'org.apache.cxf', name: 'cxf-rt-rs-client', version: '3.2.6'
// latestDepTestCompile group: 'org.jboss.resteasy', name: 'resteasy-client', version: '3.0.26.Final'
}

View File

@ -0,0 +1,27 @@
package datadog.trace.instrumentation.jaxrs.v1;
import io.opentracing.propagation.TextMap;
import javax.ws.rs.core.MultivaluedMap;
import java.util.Iterator;
import java.util.Map;
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);
}
}

View File

@ -0,0 +1,47 @@
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();
}
}

View File

@ -0,0 +1,96 @@
package datadog.trace.instrumentation.jaxrs.v1;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import static datadog.trace.instrumentation.jaxrs.v1.JaxRsClientV1Decorator.DECORATE;
import com.google.auto.service.AutoService;
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.propagation.Format;
import io.opentracing.util.GlobalTracer;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import static java.util.Collections.singletonMap;
import java.util.Map;
@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 + ".JaxRsClientDecorator",
packageName + ".ClientTracingFeature",
packageName + ".ClientTracingFilter",
packageName + ".InjectAdapter",
};
}
@Override
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
return singletonMap(
named("handle")
.and(takesArgument(2, named("com.sun.jersey.api.client.ClientRequest")))
.and(returns(named("com.sun.jersey.api.client.ClientResponse"))),
HandleAdvice.class.getName()
);
}
public static class HandleAdvice {
@Advice.OnMethodEnter
public static Span onEnter(@Advice.Argument(value = 1) final ClientRequest request) {
// WARNING: this might be a chain...so we only have to trace the first int he chain.
final Span span =
GlobalTracer.get()
.buildSpan("jax-rs.client.call")
.withTag(DDTags.RESOURCE_NAME, request.getMethod() + " jax-rs.client.call")
.start();
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.afterStart(span);
DECORATE.onRequest(span, request);
GlobalTracer.get()
.inject(
span.context(),
Format.Builtin.HTTP_HEADERS,
new InjectAdapter(request.getHeaders()));
request.getProperties().put("dd.span", span);
}
return span;
}
@Advice.OnMethodExit
public static void onExit(@Advice.Argument(value = 1) final ClientRequest request, ClientResponse response) {
Span span = (Span) request.getProperties().get("dd.span");
DECORATE.onResponse(span, response);
DECORATE.beforeFinish(span);
span.finish();
}
}
}

View File

@ -52,6 +52,7 @@ 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:jax-rs-client-1'
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'