Merge pull request #417 from DataDog/mar-kolya/apache-http-client-fix-exception-handling

Apache http client fix exception handling
This commit is contained in:
Nikolay Martynov 2018-08-01 14:58:28 -04:00 committed by GitHub
commit 911ad5f231
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 653 additions and 454 deletions

View File

@ -1,17 +1,22 @@
package datadog.trace.agent.integration.classloading
import datadog.test.ClassToInstrument
import datadog.test.ClassToInstrumentChild
import datadog.trace.agent.test.IntegrationTestUtils
import datadog.trace.api.Trace
import spock.lang.Specification
import java.lang.ref.WeakReference
import static datadog.trace.agent.test.IntegrationTestUtils.createJarWithClasses
class ClassLoadingTest extends Specification {
final URL[] classpath = [createJarWithClasses(ClassToInstrument, ClassToInstrumentChild, Trace)]
/** Assert that we can instrument classloaders which cannot resolve agent advice classes. */
def "instrument classloader without agent classes"() {
setup:
final URL[] classpath = [createJarWithClasses(ClassToInstrument, Trace)]
final URLClassLoader loader = new URLClassLoader(classpath, (ClassLoader) null)
when:
@ -25,6 +30,61 @@ class ClassLoadingTest extends Specification {
instrumentedClass.getClassLoader() == loader
}
def "make sure ByteBuddy does not hold strong references to ClassLoader"() {
setup:
final URLClassLoader loader = new URLClassLoader(classpath, (ClassLoader) null)
final WeakReference<URLClassLoader> ref = new WeakReference<>(loader)
when:
loader.loadClass(ClassToInstrument.getName())
loader = null
IntegrationTestUtils.awaitGC()
then:
null == ref.get()
}
// We are doing this because Grovy cannot properly resolve constructor argument types in anonymous classes
static class CountingClassLoader extends URLClassLoader {
public int count = 0
CountingClassLoader(URL[] urls) {
super(urls, (ClassLoader) null)
}
@Override
URL getResource(String name) {
count++
}
}
def "make sure that ByteBuddy reads classes's bytes only once"() {
setup:
final CountingClassLoader loader = new CountingClassLoader(classpath)
when:
loader.loadClass(ClassToInstrument.getName())
loader.loadClass(ClassToInstrumentChild.getName())
then:
loader.count == 2
}
def "make sure that ByteBuddy doesn't resue cached type descriptions between different classloaders"() {
setup:
final CountingClassLoader loader1 = new CountingClassLoader(classpath)
final CountingClassLoader loader2 = new CountingClassLoader(classpath)
when:
loader1.loadClass(ClassToInstrument.getName())
loader2.loadClass(ClassToInstrument.getName())
then:
loader1.count == 1
loader2.count == 1
}
def "can find bootstrap resources"() {
expect:
IntegrationTestUtils.getAgentClassLoader().getResources('datadog/trace/api/Trace.class') != null

View File

@ -1,8 +0,0 @@
package datadog.trace.agent.integration.classloading;
import datadog.trace.api.Trace;
class ClassToInstrument {
@Trace
public static void someMethod() {}
}

View File

@ -0,0 +1,9 @@
package datadog.test;
import datadog.trace.api.Trace;
/** Note: this has to stay in 'datadog.test' package to be considered for instrumentation */
public class ClassToInstrument {
@Trace
public static void someMethod() {}
}

View File

@ -0,0 +1,4 @@
package datadog.test;
/** Note: this has to stay in 'datadog.test' package to be considered for instrumentation */
public class ClassToInstrumentChild extends ClassToInstrument {}

View File

@ -7,6 +7,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.UUID;
@ -156,4 +157,14 @@ public class IntegrationTestUtils {
.getField("AGENT_PACKAGE_PREFIXES");
return (String[]) f.get(null);
}
public static void awaitGC() {
System.gc(); // For good measure.
Object obj = new Object();
final WeakReference ref = new WeakReference<>(obj);
obj = null;
while (ref.get() != null) {
System.gc();
}
}
}

View File

@ -42,6 +42,7 @@ public class AgentInstaller {
new AgentBuilder.Default()
.disableClassFormatChanges()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.with(AgentBuilder.DescriptionStrategy.Default.POOL_ONLY)
.with(new LoggingListener())
.with(new DDLocationStrategy())
.ignore(any(), skipClassLoader())

View File

@ -0,0 +1,143 @@
package datadog.trace.agent.tooling;
import static net.bytebuddy.matcher.ElementMatchers.erasure;
import java.util.HashSet;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import net.bytebuddy.description.type.TypeDefinition;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.description.type.TypeList;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
/**
* This class provides some custom ByteBuddy element matchers to use when applying instrumentation
*/
@Slf4j
public class ByteBuddyElementMatchers {
/**
* Matches any type description that declares a super type that matches the provided matcher.
* Exceptions during matching process are logged and ignored.
*
* @param matcher The type to be checked for being a super type of the matched type.
* @param <T> The type of the matched object.
* @return A matcher that matches any type description that declares a super type that matches the
* provided matcher.
* @see ElementMatchers#hasSuperType(net.bytebuddy.matcher.ElementMatcher)
*/
public static <T extends TypeDescription> ElementMatcher.Junction<T> safeHasSuperType(
final ElementMatcher<? super TypeDescription> matcher) {
return safeHasGenericSuperType(erasure(matcher));
}
/**
* Matches any type description that declares a super type that matches the provided matcher.
* Exceptions during matching process are logged and ignored.
*
* @param matcher The type to be checked for being a super type of the matched type.
* @param <T> The type of the matched object.
* @return A matcher that matches any type description that declares a super type that matches the
* provided matcher.
* @see ElementMatchers#hasGenericSuperType(net.bytebuddy.matcher.ElementMatcher)
*/
public static <T extends TypeDescription> ElementMatcher.Junction<T> safeHasGenericSuperType(
final ElementMatcher<? super TypeDescription.Generic> matcher) {
return new SafeHasSuperTypeMatcher<>(matcher);
}
/**
* An element matcher that matches a super type. This is different from {@link
* net.bytebuddy.matcher.HasSuperTypeMatcher} in the following way:
*
* <ul>
* <li>Exceptions are logged
* <li>When exception happens the rest of the inheritance subtree is discarded (since ByteBuddy
* cannot load/parse type information for it) but search in other subtrees continues
* </ul>
*
* <p>This is useful because this allows us to see when matcher's check is not complete (i.e. part
* of it fails), at the same time it makes best effort instead of failing quickly (like {@code
* failSafe(hasSuperType(...))} does) which means the code is more resilient to classpath
* inconsistencies
*
* @param <T> The type of the matched entity.
* @see net.bytebuddy.matcher.HasSuperTypeMatcher
*/
@HashCodeAndEqualsPlugin.Enhance
public static class SafeHasSuperTypeMatcher<T extends TypeDescription>
extends ElementMatcher.Junction.AbstractBase<T> {
/** The matcher to apply to any super type of the matched type. */
private final ElementMatcher<? super TypeDescription.Generic> matcher;
/**
* Creates a new matcher for a super type.
*
* @param matcher The matcher to apply to any super type of the matched type.
*/
public SafeHasSuperTypeMatcher(final ElementMatcher<? super TypeDescription.Generic> matcher) {
this.matcher = matcher;
}
@Override
public boolean matches(final T target) {
final Set<TypeDescription> checkedInterfaces = new HashSet<>();
// We do not use foreach loop and iterator interface here because we need to catch exceptions
// in {@code getSuperClass} calls
TypeDefinition typeDefinition = target;
while (typeDefinition != null) {
if (matcher.matches(typeDefinition.asGenericType())
|| hasInterface(typeDefinition, checkedInterfaces)) {
return true;
}
typeDefinition = safeGetSuperClass(typeDefinition);
}
return false;
}
private TypeDefinition safeGetSuperClass(final TypeDefinition typeDefinition) {
try {
return typeDefinition.getSuperClass();
} catch (final Exception e) {
log.info("Exception trying to get next type definition:", e);
return null;
}
}
/**
* Matches a type's interfaces against the provided matcher.
*
* @param typeDefinition The type for which to check all implemented interfaces.
* @param checkedInterfaces The interfaces that have already been checked.
* @return {@code true} if any interface matches the supplied matcher.
*/
private boolean hasInterface(
final TypeDefinition typeDefinition, final Set<TypeDescription> checkedInterfaces) {
for (final TypeDefinition interfaceType : safeGetInterfaces(typeDefinition)) {
if (checkedInterfaces.add(interfaceType.asErasure())
&& (matcher.matches(interfaceType.asGenericType())
|| hasInterface(interfaceType, checkedInterfaces))) {
return true;
}
}
return false;
}
private TypeList.Generic safeGetInterfaces(final TypeDefinition typeDefinition) {
try {
return typeDefinition.getInterfaces();
} catch (final Exception e) {
log.info("Exception trying to get interfaces:", e);
return new TypeList.Generic.Empty();
}
}
@Override
public String toString() {
return "safeHasSuperType(" + matcher + ")";
}
}
}

View File

@ -1,33 +0,0 @@
package datadog.trace.agent.tooling;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.agent.builder.AgentBuilder.LocationStrategy;
import net.bytebuddy.dynamic.ClassFileLocator;
/** A bytebuddy advice builder with default DataDog settings. */
public class DDAdvice extends AgentBuilder.Transformer.ForAdvice {
private static final ClassFileLocator AGENT_CLASS_LOCATOR =
ClassFileLocator.ForClassLoader.of(Utils.getAgentClassLoader());
/** Location strategy for resolving classes in the agent's jar. */
private static final LocationStrategy AGENT_CLASS_LOCATION_STRATEGY =
new AgentBuilder.LocationStrategy.Simple(AGENT_CLASS_LOCATOR);
/**
* Create bytebuddy advice with default datadog settings.
*
* @return the bytebuddy advice
*/
public static AgentBuilder.Transformer.ForAdvice create() {
return create(true);
}
public static AgentBuilder.Transformer.ForAdvice create(final boolean includeExceptionHandler) {
ForAdvice advice = new DDAdvice().with(AGENT_CLASS_LOCATION_STRATEGY);
if (includeExceptionHandler) {
advice = advice.withExceptionHandler(ExceptionHandlers.defaultExceptionHandler());
}
return advice;
}
private DDAdvice() {}
}

View File

@ -12,16 +12,14 @@ import net.bytebuddy.utility.JavaModule;
* reached.
*/
public class DDLocationStrategy implements AgentBuilder.LocationStrategy {
private static final ClassLoader BOOTSTRAP_RESOURCE_LOCATOR = new ClassLoader(null) {};
@Override
public ClassFileLocator classFileLocator(ClassLoader classLoader, JavaModule javaModule) {
List<ClassFileLocator> locators = new ArrayList<ClassFileLocator>();
public ClassFileLocator classFileLocator(ClassLoader classLoader, final JavaModule javaModule) {
final List<ClassFileLocator> locators = new ArrayList<>();
while (classLoader != null) {
locators.add(ClassFileLocator.ForClassLoader.of(classLoader));
classLoader = classLoader.getParent();
}
locators.add(ClassFileLocator.ForClassLoader.of(BOOTSTRAP_RESOURCE_LOCATOR));
locators.add(ClassFileLocator.ForClassLoader.of(Utils.getBootstrapProxy()));
return new ClassFileLocator.Compound(locators.toArray(new ClassFileLocator[0]));
}
}

View File

@ -30,9 +30,10 @@ public class HelperInjector implements Transformer {
* Construct HelperInjector.
*
* @param helperClassNames binary names of the helper classes to inject. These class names must be
* resolvable by the classloader returned by DDAdvice#getAgentClassLoader(). Classes are
* injected in the order provided. This is important if there is interdependency between
* helper classes that requires them to be injected in a specific order.
* resolvable by the classloader returned by
* datadog.trace.agent.tooling.Utils#getAgentClassLoader(). Classes are injected in the order
* provided. This is important if there is interdependency between helper classes that
* requires them to be injected in a specific order.
*/
public HelperInjector(final String... helperClassNames) {
this.helperClassNames = new LinkedHashSet<>(Arrays.asList(helperClassNames));

View File

@ -51,7 +51,7 @@ public interface Instrumenter {
protected final boolean enabled;
public Default(final String instrumentationName, final String... additionalNames) {
this.instrumentationNames = new HashSet<>(Arrays.asList(additionalNames));
instrumentationNames = new HashSet<>(Arrays.asList(additionalNames));
instrumentationNames.add(instrumentationName);
instrumentationPrimaryName = instrumentationName;
@ -72,17 +72,46 @@ public interface Instrumenter {
}
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
public AgentBuilder instrument(final AgentBuilder parentAgentBuilder) {
if (!enabled) {
log.debug("Instrumentation {} is disabled", this);
return parentAgentBuilder;
}
AgentBuilder.Identified.Extendable agentBuilder =
parentAgentBuilder
.type(typeMatcher(), classLoaderMatcher())
.and(new MuzzleMatcher())
.transform(DDTransformers.defaultTransformers());
agentBuilder = injectHelperClasses(agentBuilder);
agentBuilder = applyInstrumentationTransformers(agentBuilder);
return agentBuilder.asDecorator();
}
private AgentBuilder.Identified.Extendable injectHelperClasses(
AgentBuilder.Identified.Extendable agentBuilder) {
final String[] helperClassNames = helperClassNames();
if (helperClassNames.length > 0) {
agentBuilder = agentBuilder.transform(new HelperInjector(helperClassNames));
}
return agentBuilder;
}
AgentBuilder.Identified.Extendable advice =
agentBuilder
.type(typeMatcher(), classLoaderMatcher())
.and(
new AgentBuilder.RawMatcher() {
private AgentBuilder.Identified.Extendable applyInstrumentationTransformers(
AgentBuilder.Identified.Extendable agentBuilder) {
for (final Map.Entry<ElementMatcher, String> entry : transformers().entrySet()) {
agentBuilder =
agentBuilder.transform(
new AgentBuilder.Transformer.ForAdvice()
.include(Utils.getAgentClassLoader())
.withExceptionHandler(ExceptionHandlers.defaultExceptionHandler())
.advice(entry.getKey(), entry.getValue()));
}
return agentBuilder;
}
/** Matches classes for which instrumentation is not muzzled. */
private class MuzzleMatcher implements AgentBuilder.RawMatcher {
@Override
public boolean matches(
final TypeDescription typeDescription,
@ -102,7 +131,7 @@ public interface Instrumenter {
log.debug(
"Instrumentation muzzled: {} -- {} on {}",
instrumentationPrimaryName,
this.getClass().getName(),
getClass().getName(),
classLoader);
}
for (final Reference.Mismatch mismatch : mismatches) {
@ -112,16 +141,6 @@ public interface Instrumenter {
}
return true;
}
})
.transform(DDTransformers.defaultTransformers());
final String[] helperClassNames = helperClassNames();
if (helperClassNames.length > 0) {
advice = advice.transform(new HelperInjector(helperClassNames));
}
for (final Map.Entry<ElementMatcher, String> entry : transformers().entrySet()) {
advice = advice.transform(DDAdvice.create().advice(entry.getKey(), entry.getValue()));
}
return advice.asDecorator();
}
/**

View File

@ -21,11 +21,11 @@ public class ReferenceMatcher {
private final Reference[] references;
private final Set<String> helperClassNames;
public ReferenceMatcher(Reference... references) {
public ReferenceMatcher(final Reference... references) {
this(new String[0], references);
}
public ReferenceMatcher(String[] helperClassNames, Reference[] references) {
public ReferenceMatcher(final String[] helperClassNames, final Reference[] references) {
this.references = references;
this.helperClassNames = new HashSet<>(Arrays.asList(helperClassNames));
}
@ -34,7 +34,7 @@ public class ReferenceMatcher {
* @param loader Classloader to validate against (or null for bootstrap)
* @return true if all references match the classpath of loader
*/
public boolean matches(ClassLoader loader) {
public boolean matches(final ClassLoader loader) {
return getMismatchedReferenceSources(loader).size() == 0;
}
@ -52,7 +52,7 @@ public class ReferenceMatcher {
mismatches = mismatchCache.get(loader);
if (null == mismatches) {
mismatches = new ArrayList<>(0);
for (Reference reference : references) {
for (final Reference reference : references) {
// Don't reference-check helper classes.
// They will be injected by the instrumentation's HelperInjector.
if (!helperClassNames.contains(reference.getClassName())) {

View File

@ -6,7 +6,6 @@ import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.api.DDSpanTypes
import datadog.trace.api.DDTags
import io.opentracing.tag.Tags
import net.bytebuddy.utility.JavaModule
import play.inject.guice.GuiceApplicationBuilder
import spock.lang.Shared
@ -25,27 +24,13 @@ class LagomTest extends AgentTestRunner {
@Shared
private TestServer server
@Override
protected boolean onInstrumentationError(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded, Throwable throwable) {
if (throwable.getMessage().contains('Cannot resolve type description for akka.stream.impl.VirtualProcessor$WrappedSubscription$$SubscriptionState')) {
// 'akka/stream/impl/VirtualProcessor$WrappedSubscription$PassThrough$.class' declares
// itself an implementation of 'VirtualProcessor$WrappedSubscription$$SubscriptionState',
// but this interface does not exist on the classpath.
// The closest thing on the classpath is 'VirtualProcessor$WrappedSubscription$SubscriptionState' (only one $).
// Looks like a compiler/packaging issue on akka's end. Or maybe this interface is dynamically generated.
return false
}
return super.onInstrumentationError(typeName, classLoader, module, loaded, throwable)
}
def setupSpec() {
server = startServer(defaultSetup()
.withCluster(false)
.withPersistence(false)
.withCassandra(false)
.withJdbc(false)
.withConfigureBuilder(
.configureBuilder(
new Function<GuiceApplicationBuilder, GuiceApplicationBuilder>() {
@Override
GuiceApplicationBuilder apply(GuiceApplicationBuilder builder) {

View File

@ -0,0 +1,6 @@
lagom.circuit-breaker {
// Disable Lagom circuit-breaker
default {
enabled = off
}
}

View File

@ -1,18 +1,25 @@
package datadog.trace.instrumentation.apachehttpclient;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.isAbstract;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.Tracer;
import io.opentracing.tag.Tags;
import io.opentracing.util.GlobalTracer;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.apache.http.impl.client.DefaultRedirectStrategy;
import org.apache.http.impl.execchain.ClientExecChain;
@AutoService(Instrumenter.class)
@ -23,8 +30,9 @@ public class ApacheHttpClientInstrumentation extends Instrumenter.Default {
}
@Override
public ElementMatcher<? super TypeDescription> typeMatcher() {
return named("org.apache.http.impl.client.HttpClientBuilder");
public ElementMatcher typeMatcher() {
return named("org.apache.http.impl.client.HttpClientBuilder")
.or(safeHasSuperType(named("org.apache.http.impl.client.CloseableHttpClient")));
}
@Override
@ -38,7 +46,9 @@ public class ApacheHttpClientInstrumentation extends Instrumenter.Default {
"org.apache.http.client.methods.HttpRequestWrapper",
"org.apache.http.client.protocol.HttpClientContext",
"org.apache.http.conn.routing.HttpRoute",
"org.apache.http.impl.execchain.ClientExecChain");
"org.apache.http.impl.execchain.ClientExecChain",
"org.apache.http.impl.client.CloseableHttpClient",
"org.apache.http.impl.client.InternalHttpClient");
}
@Override
@ -51,19 +61,42 @@ public class ApacheHttpClientInstrumentation extends Instrumenter.Default {
@Override
public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(
isMethod().and(named("decorateProtocolExec")), ApacheHttpClientAdvice.class.getName());
isMethod().and(not(isAbstract())).and(named("doExecute")), ClientAdvice.class.getName());
transformers.put(
isMethod().and(named("decorateProtocolExec")), ClientExecAdvice.class.getName());
return transformers;
}
public static class ApacheHttpClientAdvice {
/** Strategy: add our tracing exec to the apache exec chain. */
public static class ClientAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static Scope methodEnter() {
final Tracer.SpanBuilder spanBuilder =
GlobalTracer.get()
.buildSpan(DDTracingClientExec.OPERATION_NAME)
.withTag(Tags.COMPONENT.getKey(), DDTracingClientExec.COMPONENT_NAME);
return spanBuilder.startActive(true);
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void methodExit(
@Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) {
final Span span = scope.span();
if (throwable != null) {
Tags.ERROR.set(span, Boolean.TRUE);
span.log(Collections.singletonMap(ERROR_OBJECT, throwable));
span.finish();
}
scope.close();
}
}
public static class ClientExecAdvice {
@Advice.OnMethodExit(suppress = Throwable.class)
public static void addTracingExec(@Advice.Return(readOnly = false) ClientExecChain execChain) {
execChain =
new DDTracingClientExec(
execChain, DefaultRedirectStrategy.INSTANCE, false, GlobalTracer.get());
execChain = new DDTracingClientExec(execChain, GlobalTracer.get());
}
}
}

View File

@ -18,7 +18,6 @@ import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.client.RedirectStrategy;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpExecutionAware;
import org.apache.http.client.methods.HttpRequestWrapper;
@ -33,36 +32,15 @@ import org.apache.http.impl.execchain.ClientExecChain;
*/
@Slf4j
public class DDTracingClientExec implements ClientExecChain {
private static final String COMPONENT_NAME = "apache-httpclient";
private static final String OPERATION_NAME = "http.request";
/**
* Id of {@link HttpClientContext#setAttribute(String, Object)} representing span associated with
* the current client processing. Referenced span is local span not a span representing HTTP
* communication.
*/
private static final String ACTIVE_SPAN = DDTracingClientExec.class.getName() + ".activeSpan";
/**
* Tracing {@link ClientExecChain} is executed after redirect exec, so on redirects it is called
* multiple times. This is used as an id for {@link HttpClientContext#setAttribute(String,
* Object)} to store number of redirects.
*/
private static final String REDIRECT_COUNT =
DDTracingClientExec.class.getName() + ".redirectCount";
static final String COMPONENT_NAME = "apache-httpclient";
static final String OPERATION_NAME = "http.request";
private final RedirectStrategy redirectStrategy;
private final ClientExecChain requestExecutor;
private final boolean redirectHandlingDisabled;
private final Tracer tracer;
public DDTracingClientExec(
final ClientExecChain clientExecChain,
final RedirectStrategy redirectStrategy,
final boolean redirectHandlingDisabled,
final Tracer tracer) {
this.requestExecutor = clientExecChain;
this.redirectStrategy = redirectStrategy;
this.redirectHandlingDisabled = redirectHandlingDisabled;
public DDTracingClientExec(final ClientExecChain clientExecChain, final Tracer tracer) {
requestExecutor = clientExecChain;
this.tracer = tracer;
}
@ -73,91 +51,37 @@ public class DDTracingClientExec implements ClientExecChain {
final HttpClientContext clientContext,
final HttpExecutionAware execAware)
throws IOException, HttpException {
Scope localScope = clientContext.getAttribute(ACTIVE_SPAN, Scope.class);
CloseableHttpResponse response = null;
try {
if (localScope == null) {
localScope = createLocalScope(request, clientContext);
}
return (response = createNetworkSpan(localScope, route, request, clientContext, execAware));
} catch (final Exception e) {
localScope.close();
throw e;
} finally {
if (response != null) {
/**
* This exec runs after {@link org.apache.http.impl.execchain.RedirectExec} which loops
* until there is no redirect or reaches max redirect count. {@link RedirectStrategy} is
* used to decide whether localScope should be finished or not. If there is a redirect
* localScope is not finished and redirect is logged.
*/
Integer redirectCount = clientContext.getAttribute(REDIRECT_COUNT, Integer.class);
if (!redirectHandlingDisabled
&& clientContext.getRequestConfig().isRedirectsEnabled()
&& redirectStrategy.isRedirected(request, response, clientContext)
&& ++redirectCount < clientContext.getRequestConfig().getMaxRedirects()) {
clientContext.setAttribute(REDIRECT_COUNT, redirectCount);
} else {
localScope.close();
}
}
}
}
private Scope createLocalScope(
final HttpRequest httpRequest, final HttpClientContext clientContext) {
final Tracer.SpanBuilder spanBuilder =
tracer.buildSpan(OPERATION_NAME).withTag(Tags.COMPONENT.getKey(), COMPONENT_NAME);
final Scope scope = spanBuilder.startActive(true);
clientContext.setAttribute(ACTIVE_SPAN, scope);
clientContext.setAttribute(REDIRECT_COUNT, 0);
return scope;
}
private CloseableHttpResponse createNetworkSpan(
final Scope parentScope,
final HttpRoute route,
final HttpRequestWrapper request,
final HttpClientContext clientContext,
final HttpExecutionAware execAware)
throws IOException, HttpException {
Scope networkScope = null;
Span networkSpan = null;
Scope scope = null;
Span span = null;
try {
// This handlers runs untrapped in the client code
// so we must ensure any unexpected agent errors are caught.
try {
networkScope =
scope =
tracer
.buildSpan(OPERATION_NAME)
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT)
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.HTTP_CLIENT)
.asChildOf(parentScope.span())
.startActive(true);
networkSpan = networkScope.span();
span = scope.span();
final boolean awsClientCall = request.getHeaders("amz-sdk-invocation-id").length > 0;
// AWS calls are often signed, so we can't add headers without breaking the signature.
if (!awsClientCall) {
tracer.inject(
networkSpan.context(),
Format.Builtin.HTTP_HEADERS,
new HttpHeadersInjectAdapter(request));
span.context(), Format.Builtin.HTTP_HEADERS, new HttpHeadersInjectAdapter(request));
}
// request tags
Tags.HTTP_METHOD.set(networkSpan, request.getRequestLine().getMethod());
Tags.HTTP_URL.set(networkSpan, request.getRequestLine().getUri());
Tags.HTTP_METHOD.set(span, request.getRequestLine().getMethod());
Tags.HTTP_URL.set(span, request.getRequestLine().getUri());
final URI uri = request.getURI();
// zuul users have encountered cases where getURI returns null
if (null != uri) {
Tags.PEER_PORT.set(networkSpan, uri.getPort() == -1 ? 80 : uri.getPort());
Tags.PEER_HOSTNAME.set(networkSpan, uri.getHost());
Tags.PEER_PORT.set(span, uri.getPort() == -1 ? 80 : uri.getPort());
Tags.PEER_HOSTNAME.set(span, uri.getHost());
}
} catch (final Exception e) {
log.debug("failed to create network span", e);
log.debug("failed to create span", e);
}
final CloseableHttpResponse response =
@ -165,23 +89,23 @@ public class DDTracingClientExec implements ClientExecChain {
try {
// response tags
if (null != networkSpan) {
Tags.HTTP_STATUS.set(networkSpan, response.getStatusLine().getStatusCode());
if (null != span) {
Tags.HTTP_STATUS.set(span, response.getStatusLine().getStatusCode());
}
} catch (final Exception e) {
log.debug("failed to set network span status", e);
log.debug("failed to set span status", e);
}
return response;
} catch (IOException | HttpException | RuntimeException e) {
} catch (final IOException | HttpException | RuntimeException e) {
// error tags
Tags.ERROR.set(networkSpan, Boolean.TRUE);
networkSpan.log(Collections.singletonMap(ERROR_OBJECT, e));
Tags.ERROR.set(span, Boolean.TRUE);
span.log(Collections.singletonMap(ERROR_OBJECT, e));
throw e;
} finally {
if (null != networkScope) {
networkScope.close();
if (null != scope) {
scope.close();
}
}
}

View File

@ -1,17 +1,21 @@
import datadog.opentracing.DDSpan
import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.agent.test.ListWriterAssert
import datadog.trace.agent.test.RatpackUtils
import datadog.trace.agent.test.TraceAssert
import datadog.trace.api.DDSpanTypes
import datadog.trace.api.DDTags
import io.opentracing.tag.Tags
import org.apache.http.HttpResponse
import org.apache.http.client.ClientProtocolException
import org.apache.http.client.HttpClient
import org.apache.http.client.config.RequestConfig
import org.apache.http.client.methods.HttpGet
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.message.BasicHeader
import spock.lang.Shared
import static datadog.trace.agent.test.ListWriterAssert.assertTraces
import static datadog.trace.agent.test.TestUtils.runUnderTrace
import static ratpack.groovy.test.embed.GroovyEmbeddedApp.ratpack
class ApacheHttpClientTest extends AgentTestRunner {
@ -19,6 +23,7 @@ class ApacheHttpClientTest extends AgentTestRunner {
@Shared
def server = ratpack {
handlers {
prefix("success") {
get {
RatpackUtils.handleDistributedRequest(context)
@ -26,31 +31,147 @@ class ApacheHttpClientTest extends AgentTestRunner {
response.status(200).send(msg)
}
}
prefix("redirect") {
get {
RatpackUtils.handleDistributedRequest(context)
redirect(server.address.resolve("/success").toURL().toString())
}
}
prefix("another-redirect") {
get {
RatpackUtils.handleDistributedRequest(context)
redirect(server.address.resolve("/redirect").toURL().toString())
}
}
}
}
@Shared
int port = server.getAddress().port
int port = server.address.port
@Shared
def successUrl = server.address.resolve("/success")
@Shared
def redirectUrl = server.address.resolve("/redirect")
@Shared
def twoRedirectsUrl = server.address.resolve("/another-redirect")
final HttpClientBuilder builder = HttpClientBuilder.create()
final HttpClient client = builder.build()
def "trace request with propagation"() {
setup:
final HttpClientBuilder builder = HttpClientBuilder.create()
when:
HttpResponse response = client.execute(new HttpGet(successUrl))
final HttpClient client = builder.build()
runUnderTrace("someTrace") {
try {
HttpResponse response = client.execute(new HttpGet(server.getAddress()))
assert response.getStatusLine().getStatusCode() == 200
} catch (Exception e) {
e.printStackTrace()
throw new RuntimeException(e)
}
}
expect:
then:
response.getStatusLine().getStatusCode() == 200
// one trace on the server, one trace on the client
assertTraces(TEST_WRITER, 2) {
trace(0, 1) {
serverTrace(it, 0, TEST_WRITER[1][1])
trace(1, 2) {
clientParentSpan(it, 0)
successClientSpan(it, 1, span(0))
}
}
}
def "trace redirected request with propagation many redirects allowed"() {
setup:
final RequestConfig.Builder requestConfigBuilder = new RequestConfig.Builder()
requestConfigBuilder.setMaxRedirects(10)
HttpGet request = new HttpGet(redirectUrl)
request.setConfig(requestConfigBuilder.build())
when:
HttpResponse response = client.execute(request)
then:
response.getStatusLine().getStatusCode() == 200
// two traces on the server, one trace on the client
assertTraces(TEST_WRITER, 3) {
serverTrace(it, 0, TEST_WRITER[2][2])
serverTrace(it, 1, TEST_WRITER[2][1])
trace(2, 3) {
clientParentSpan(it, 0)
successClientSpan(it, 1, span(0))
redirectClientSpan(it, 2, span(0))
}
}
}
def "trace redirected request with propagation 1 redirect allowed"() {
setup:
final RequestConfig.Builder requestConfigBuilder = new RequestConfig.Builder()
requestConfigBuilder.setMaxRedirects(1)
HttpGet request = new HttpGet(redirectUrl)
request.setConfig(requestConfigBuilder.build())
when:
HttpResponse response = client.execute(request)
then:
response.getStatusLine().getStatusCode() == 200
// two traces on the server, one trace on the client
assertTraces(TEST_WRITER, 3) {
serverTrace(it, 0, TEST_WRITER[2][2])
serverTrace(it, 1, TEST_WRITER[2][1])
trace(2, 3) {
clientParentSpan(it, 0)
successClientSpan(it, 1, span(0))
redirectClientSpan(it, 2, span(0))
}
}
}
def "trace redirected request with propagation too many redirects"() {
setup:
final RequestConfig.Builder requestConfigBuilder = new RequestConfig.Builder()
requestConfigBuilder.setMaxRedirects(1)
HttpGet request = new HttpGet(twoRedirectsUrl)
request.setConfig(requestConfigBuilder.build())
when:
client.execute(request)
then:
def exception = thrown(ClientProtocolException)
// two traces on the server, one trace on the client
assertTraces(TEST_WRITER, 3) {
serverTrace(it, 0, TEST_WRITER[2][2])
serverTrace(it, 1, TEST_WRITER[2][1])
trace(2, 3) {
clientParentSpan(it, 0, exception)
redirectClientSpan(it, 1, span(0))
redirectClientSpan(it, 2, span(0), "another-redirect")
}
}
}
def "trace request without propagation"() {
setup:
HttpGet request = new HttpGet(successUrl)
request.addHeader(new BasicHeader("is-dd-server", "false"))
when:
HttpResponse response = client.execute(request)
then:
response.getStatusLine().getStatusCode() == 200
// only one trace (client).
assertTraces(TEST_WRITER, 1) {
trace(0, 2) {
clientParentSpan(it, 0)
successClientSpan(it, 1, span(0))
}
}
}
def serverTrace(ListWriterAssert writer, int index, DDSpan parent) {
writer.trace(index, 1) {
span(0) {
childOf TEST_WRITER[1][2]
childOf parent
serviceName "unnamed-java-app"
operationName "test-http-server"
resourceName "test-http-server"
@ -60,39 +181,36 @@ class ApacheHttpClientTest extends AgentTestRunner {
}
}
}
trace(1, 3) {
span(0) {
}
def clientParentSpan(TraceAssert trace, int index, Throwable exception = null) {
trace.span(index) {
parent()
serviceName "unnamed-java-app"
operationName "someTrace"
resourceName "someTrace"
errored false
tags {
defaultTags()
}
}
span(1) {
childOf span(0)
serviceName "unnamed-java-app"
operationName "apache.http"
resourceName "apache.http"
errored false
errored exception != null
tags {
defaultTags()
"$Tags.COMPONENT.key" "apache-httpclient"
if (exception) {
errorTags(exception.class)
}
}
span(2) {
childOf span(1)
}
}
def successClientSpan(TraceAssert trace, int index, DDSpan parent, status = 200, route = "success") {
trace.span(index) {
childOf parent
serviceName "unnamed-java-app"
operationName "http.request"
resourceName "GET /"
spanType DDSpanTypes.HTTP_CLIENT
resourceName "GET /$route"
errored false
tags {
defaultTags()
"$Tags.HTTP_STATUS.key" 200
"$Tags.HTTP_URL.key" "http://localhost:$port/"
"$Tags.HTTP_STATUS.key" status
"$Tags.HTTP_URL.key" "http://localhost:$port/$route"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.getAddress().port
"$Tags.HTTP_METHOD.key" "GET"
@ -101,69 +219,8 @@ class ApacheHttpClientTest extends AgentTestRunner {
}
}
}
}
}
def "trace request without propagation"() {
setup:
final HttpClientBuilder builder = HttpClientBuilder.create()
final HttpClient client = builder.build()
runUnderTrace("someTrace") {
try {
HttpGet request = new HttpGet(server.getAddress())
request.addHeader(new BasicHeader("is-dd-server", "false"))
HttpResponse response = client.execute(request)
assert response.getStatusLine().getStatusCode() == 200
} catch (Exception e) {
e.printStackTrace()
throw new RuntimeException(e)
}
}
expect:
// only one trace (client).
assertTraces(TEST_WRITER, 1) {
trace(0, 3) {
span(0) {
parent()
serviceName "unnamed-java-app"
operationName "someTrace"
resourceName "someTrace"
errored false
tags {
defaultTags()
}
}
span(1) {
childOf span(0)
serviceName "unnamed-java-app"
operationName "apache.http"
resourceName "apache.http"
errored false
tags {
defaultTags()
"$Tags.COMPONENT.key" "apache-httpclient"
}
}
span(2) {
childOf span(1)
serviceName "unnamed-java-app"
operationName "http.request"
resourceName "GET /"
spanType DDSpanTypes.HTTP_CLIENT
errored false
tags {
defaultTags()
"$Tags.HTTP_STATUS.key" 200
"$Tags.HTTP_URL.key" "http://localhost:$port/"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_PORT.key" server.getAddress().port
"$Tags.HTTP_METHOD.key" "GET"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
}
}
}
}
def redirectClientSpan(TraceAssert trace, int index, DDSpan parent, route = "redirect") {
successClientSpan(trace, index, parent, 302, route)
}
}

View File

@ -1,7 +1,6 @@
package datadog.trace.instrumentation.classloaders;
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
import static net.bytebuddy.matcher.ElementMatchers.isSubTypeOf;
import com.google.auto.service.AutoService;
import datadog.opentracing.DDTracer;
@ -28,12 +27,12 @@ public final class ClassLoaderInstrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return isSubTypeOf(ClassLoader.class);
return safeHasSuperType(named("java.lang.ClassLoader"));
}
@Override
public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(isConstructor(), ClassloaderAdvice.class.getName());
return transformers;
}

View File

@ -41,7 +41,7 @@ public class Elasticsearch2TransportClientInstrumentation extends Instrumenter.D
@Override
public ElementMatcher typeMatcher() {
// If we want to be more generic, we could instrument the interface instead:
// .and(hasSuperType(named("org.elasticsearch.client.ElasticsearchClient"))))
// .and(safeHasSuperType(named("org.elasticsearch.client.ElasticsearchClient"))))
return not(isInterface()).and(named("org.elasticsearch.client.support.AbstractClient"));
}

View File

@ -41,7 +41,7 @@ public class Elasticsearch5TransportClientInstrumentation extends Instrumenter.D
@Override
public ElementMatcher typeMatcher() {
// If we want to be more generic, we could instrument the interface instead:
// .and(hasSuperType(named("org.elasticsearch.client.ElasticsearchClient"))))
// .and(safeHasSuperType(named("org.elasticsearch.client.ElasticsearchClient"))))
return not(isInterface()).and(named("org.elasticsearch.client.support.AbstractClient"));
}

View File

@ -45,7 +45,7 @@ public class Elasticsearch6TransportClientInstrumentation extends Instrumenter.D
@Override
public ElementMatcher typeMatcher() {
// If we want to be more generic, we could instrument the interface instead:
// .and(hasSuperType(named("org.elasticsearch.client.ElasticsearchClient"))))
// .and(safeHasSuperType(named("org.elasticsearch.client.ElasticsearchClient"))))
return not(isInterface()).and(named("org.elasticsearch.client.support.AbstractClient"));
}

View File

@ -1,9 +1,9 @@
package datadog.trace.instrumentation.http_url_connection;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.isSubTypeOf;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
@ -43,7 +43,7 @@ public class HttpUrlConnectionInstrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return isSubTypeOf(HttpURLConnection.class)
return safeHasSuperType(named("java.net.HttpURLConnection"))
// This class is a simple delegator. Skip because it does not update its `connected` field.
.and(not(named("sun.net.www.protocol.https.HttpsURLConnectionImpl")));
}
@ -58,7 +58,7 @@ public class HttpUrlConnectionInstrumentation extends Instrumenter.Default {
@Override
public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(
isMethod()
.and(isPublic())
@ -177,7 +177,7 @@ public class HttpUrlConnectionInstrumentation extends Instrumenter.Default {
private static final Map<HttpURLConnection, HttpURLState> STATE_MAP =
Collections.synchronizedMap(new WeakHashMap<HttpURLConnection, HttpURLState>());
public static HttpURLState get(HttpURLConnection connection) {
public static HttpURLState get(final HttpURLConnection connection) {
HttpURLState state = STATE_MAP.get(connection);
if (state == null) {
// not thread-safe, but neither is HttpURLConnection
@ -195,8 +195,8 @@ public class HttpUrlConnectionInstrumentation extends Instrumenter.Default {
return hasDoneIO;
}
public void setHasDoneIO(boolean value) {
this.hasDoneIO = value;
public void setHasDoneIO(final boolean value) {
hasDoneIO = value;
}
}
}

View File

@ -1,7 +1,7 @@
package datadog.trace.instrumentation.hystrix;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static io.opentracing.log.Fields.ERROR_OBJECT;
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.named;
@ -31,7 +31,7 @@ public class HystrixCommandInstrumentation extends Instrumenter.Default {
public ElementMatcher typeMatcher() {
// Not adding a version restriction because this should work with any version and add some
// benefit.
return not(isInterface()).and(hasSuperType(named("com.netflix.hystrix.HystrixCommand")));
return not(isInterface()).and(safeHasSuperType(named("com.netflix.hystrix.HystrixCommand")));
}
@Override

View File

@ -1,6 +1,6 @@
package datadog.trace.instrumentation.java.concurrent;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.nameMatches;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -95,7 +95,7 @@ public final class ExecutorInstrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return not(isInterface())
.and(hasSuperType(named(Executor.class.getName())))
.and(safeHasSuperType(named(Executor.class.getName())))
.and(
new ElementMatcher<TypeDescription>() {
@Override

View File

@ -1,6 +1,6 @@
package datadog.trace.instrumentation.java.concurrent;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
@ -70,7 +70,7 @@ public final class FutureInstrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return not(isInterface())
.and(hasSuperType(named(Future.class.getName())))
.and(safeHasSuperType(named(Future.class.getName())))
.and(
new ElementMatcher<TypeDescription>() {
@Override

View File

@ -1,8 +1,7 @@
package datadog.trace.instrumentation.jaxrs;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.declaresMethod;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -31,16 +30,14 @@ public final class JaxRsAnnotationsInstrumentation extends Instrumenter.Default
@Override
public ElementMatcher typeMatcher() {
return hasSuperType(
return safeHasSuperType(
isAnnotatedWith(named("javax.ws.rs.Path"))
.or(
failSafe(
hasSuperType(declaresMethod(isAnnotatedWith(named("javax.ws.rs.Path")))))));
.or(safeHasSuperType(declaresMethod(isAnnotatedWith(named("javax.ws.rs.Path"))))));
}
@Override
public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(
isAnnotatedWith(
named("javax.ws.rs.Path")

View File

@ -1,7 +1,6 @@
package datadog.trace.instrumentation.jaxrs;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns;
@ -22,7 +21,7 @@ public final class JaxRsClientInstrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return failSafe(hasSuperType(named("javax.ws.rs.client.ClientBuilder")));
return safeHasSuperType(named("javax.ws.rs.client.ClientBuilder"));
}
@Override
@ -38,7 +37,7 @@ public final class JaxRsClientInstrumentation extends Instrumenter.Default {
public Map<ElementMatcher, String> transformers() {
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(
named("build").and(returns(hasSuperType(named("javax.ws.rs.client.Client")))),
named("build").and(returns(safeHasSuperType(named("javax.ws.rs.client.Client")))),
ClientBuilderAdvice.class.getName());
return transformers;
}

View File

@ -1,9 +1,9 @@
package datadog.trace.instrumentation.jdbc;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isSubTypeOf;
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.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
@ -11,7 +11,6 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.bootstrap.JDBCMaps;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.HashMap;
import java.util.Map;
@ -27,12 +26,12 @@ public final class ConnectionInstrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(failSafe(isSubTypeOf(Connection.class)));
return not(isInterface()).and(safeHasSuperType(named("java.sql.Connection")));
}
@Override
public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(
nameStartsWith("prepare")
.and(takesArgument(0, String.class))

View File

@ -1,10 +1,11 @@
package datadog.trace.instrumentation.jdbc;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.isSubTypeOf;
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.takesArguments;
@ -36,7 +37,7 @@ public final class PreparedStatementInstrumentation extends Instrumenter.Default
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(isSubTypeOf(PreparedStatement.class));
return not(isInterface()).and(safeHasSuperType(named("java.sql.PreparedStatement")));
}
@Override

View File

@ -1,10 +1,11 @@
package datadog.trace.instrumentation.jdbc;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.isSubTypeOf;
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;
@ -37,7 +38,7 @@ public final class StatementInstrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(isSubTypeOf(Statement.class));
return not(isInterface()).and(safeHasSuperType(named("java.sql.Statement")));
}
@Override

View File

@ -1,7 +1,7 @@
package datadog.trace.instrumentation.jetty8;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -30,7 +30,7 @@ public final class HandlerInstrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return not(isInterface())
.and(hasSuperType(named("org.eclipse.jetty.server.Handler")))
.and(safeHasSuperType(named("org.eclipse.jetty.server.Handler")))
.and(not(named("org.eclipse.jetty.server.handler.HandlerWrapper")));
}

View File

@ -1,9 +1,9 @@
package datadog.trace.instrumentation.jms1;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static datadog.trace.instrumentation.jms.util.JmsUtil.toResourceName;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -47,7 +47,7 @@ public final class JMS1MessageConsumerInstrumentation extends Instrumenter.Defau
@Override
public ElementMatcher<? super TypeDescription> typeMatcher() {
return not(isInterface()).and(hasSuperType(named("javax.jms.MessageConsumer")));
return not(isInterface()).and(safeHasSuperType(named("javax.jms.MessageConsumer")));
}
@Override
@ -62,7 +62,7 @@ public final class JMS1MessageConsumerInstrumentation extends Instrumenter.Defau
@Override
public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(
named("receive").and(takesArguments(0).or(takesArguments(1))).and(isPublic()),
ConsumerAdvice.class.getName());

View File

@ -1,10 +1,9 @@
package datadog.trace.instrumentation.jms1;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static datadog.trace.instrumentation.jms.util.JmsUtil.toResourceName;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -40,7 +39,7 @@ public final class JMS1MessageListenerInstrumentation extends Instrumenter.Defau
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(failSafe(hasSuperType(named("javax.jms.MessageListener"))));
return not(isInterface()).and(safeHasSuperType(named("javax.jms.MessageListener")));
}
@Override
@ -55,7 +54,7 @@ public final class JMS1MessageListenerInstrumentation extends Instrumenter.Defau
@Override
public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(
named("onMessage").and(takesArgument(0, named("javax.jms.Message"))).and(isPublic()),
MessageListenerAdvice.class.getName());

View File

@ -1,10 +1,9 @@
package datadog.trace.instrumentation.jms1;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static datadog.trace.instrumentation.jms.util.JmsUtil.toResourceName;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -40,7 +39,7 @@ public final class JMS1MessageProducerInstrumentation extends Instrumenter.Defau
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(failSafe(hasSuperType(named("javax.jms.MessageProducer"))));
return not(isInterface()).and(safeHasSuperType(named("javax.jms.MessageProducer")));
}
@Override
@ -55,7 +54,7 @@ public final class JMS1MessageProducerInstrumentation extends Instrumenter.Defau
@Override
public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(
named("send").and(takesArgument(0, named("javax.jms.Message"))).and(isPublic()),
ProducerAdvice.class.getName());

View File

@ -1,10 +1,9 @@
package datadog.trace.instrumentation.jms2;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static datadog.trace.instrumentation.jms.util.JmsUtil.toResourceName;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -47,7 +46,7 @@ public final class JMS2MessageConsumerInstrumentation extends Instrumenter.Defau
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(failSafe(hasSuperType(named("javax.jms.MessageConsumer"))));
return not(isInterface()).and(safeHasSuperType(named("javax.jms.MessageConsumer")));
}
@Override
@ -62,7 +61,7 @@ public final class JMS2MessageConsumerInstrumentation extends Instrumenter.Defau
@Override
public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(
named("receive").and(takesArguments(0).or(takesArguments(1))).and(isPublic()),
ConsumerAdvice.class.getName());

View File

@ -1,10 +1,9 @@
package datadog.trace.instrumentation.jms2;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static datadog.trace.instrumentation.jms.util.JmsUtil.toResourceName;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -40,7 +39,7 @@ public final class JMS2MessageListenerInstrumentation extends Instrumenter.Defau
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(failSafe(hasSuperType(named("javax.jms.MessageListener"))));
return not(isInterface()).and(safeHasSuperType(named("javax.jms.MessageListener")));
}
@Override
@ -55,7 +54,7 @@ public final class JMS2MessageListenerInstrumentation extends Instrumenter.Defau
@Override
public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(
named("onMessage").and(takesArgument(0, named("javax.jms.Message"))).and(isPublic()),
MessageListenerAdvice.class.getName());

View File

@ -1,10 +1,9 @@
package datadog.trace.instrumentation.jms2;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static datadog.trace.instrumentation.jms.util.JmsUtil.toResourceName;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -40,7 +39,7 @@ public final class JMS2MessageProducerInstrumentation extends Instrumenter.Defau
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(failSafe(hasSuperType(named("javax.jms.MessageProducer"))));
return not(isInterface()).and(safeHasSuperType(named("javax.jms.MessageProducer")));
}
@Override
@ -55,7 +54,7 @@ public final class JMS2MessageProducerInstrumentation extends Instrumenter.Defau
@Override
public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(
named("send").and(takesArgument(0, named("javax.jms.Message"))).and(isPublic()),
ProducerAdvice.class.getName());

View File

@ -1,7 +1,7 @@
package datadog.trace.instrumentation.jsp;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -39,12 +39,12 @@ public final class JSPInstrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(hasSuperType(named("javax.servlet.jsp.HttpJspPage")));
return not(isInterface()).and(safeHasSuperType(named("javax.servlet.jsp.HttpJspPage")));
}
@Override
public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(
named("_jspService")
.and(takesArgument(0, named("javax.servlet.http.HttpServletRequest")))
@ -68,14 +68,14 @@ public final class JSPInstrumentation extends Instrumenter.Default {
final Span span = scope.span();
// get the JSP file name being rendered in an include action
Object includeServletPath = req.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH);
final Object includeServletPath = req.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH);
String resourceName = req.getServletPath();
if (includeServletPath != null && includeServletPath instanceof String) {
resourceName = includeServletPath.toString();
}
span.setTag(DDTags.RESOURCE_NAME, resourceName);
Object forwardOrigin = req.getAttribute(RequestDispatcher.FORWARD_SERVLET_PATH);
final Object forwardOrigin = req.getAttribute(RequestDispatcher.FORWARD_SERVLET_PATH);
if (forwardOrigin != null && forwardOrigin instanceof String) {
span.setTag("jsp.forwardOrigin", forwardOrigin.toString());
}

View File

@ -1,7 +1,7 @@
package datadog.trace.instrumentation.netty40;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
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.nameStartsWith;
@ -48,7 +48,7 @@ public class NettyChannelPipelineInstrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(hasSuperType(named("io.netty.channel.ChannelPipeline")));
return not(isInterface()).and(safeHasSuperType(named("io.netty.channel.ChannelPipeline")));
}
@Override
@ -99,7 +99,9 @@ public class NettyChannelPipelineInstrumentation extends Instrumenter.Default {
@Advice.Enter final int depth,
@Advice.This final ChannelPipeline pipeline,
@Advice.Argument(2) final ChannelHandler handler) {
if (depth > 0) return;
if (depth > 0) {
return;
}
try {
// Server pipeline handlers

View File

@ -1,7 +1,7 @@
package datadog.trace.instrumentation.netty41;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
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.nameStartsWith;
@ -48,7 +48,7 @@ public class NettyChannelPipelineInstrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(hasSuperType(named("io.netty.channel.ChannelPipeline")));
return not(isInterface()).and(safeHasSuperType(named("io.netty.channel.ChannelPipeline")));
}
@Override
@ -99,7 +99,9 @@ public class NettyChannelPipelineInstrumentation extends Instrumenter.Default {
@Advice.Enter final int depth,
@Advice.This final ChannelPipeline pipeline,
@Advice.Argument(2) final ChannelHandler handler) {
if (depth > 0) return;
if (depth > 0) {
return;
}
try {
// Server pipeline handlers

View File

@ -1,9 +1,9 @@
package datadog.trace.instrumentation.play;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClassWithMethod;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
@ -46,7 +46,7 @@ public final class PlayInstrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return hasSuperType(named("play.api.mvc.Action"));
return safeHasSuperType(named("play.api.mvc.Action"));
}
@Override

View File

@ -1,7 +1,7 @@
package datadog.trace.instrumentation.ratpack;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.instrumentation.ratpack.RatpackInstrumentation.CLASSLOADER_CONTAINS_RATPACK_1_4_OR_ABOVE;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
@ -35,7 +35,7 @@ public final class RatpackHttpClientInstrumentation extends Instrumenter.Default
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(hasSuperType(named("ratpack.http.client.HttpClient")));
return not(isInterface()).and(safeHasSuperType(named("ratpack.http.client.HttpClient")));
}
@Override
@ -63,7 +63,7 @@ public final class RatpackHttpClientInstrumentation extends Instrumenter.Default
@Override
public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(
named("request")
.and(

View File

@ -1,7 +1,7 @@
package datadog.trace.instrumentation.ratpack;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClassWithMethod;
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.isStatic;
@ -91,7 +91,7 @@ public final class RatpackInstrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(hasSuperType(named("ratpack.exec.ExecStarter")));
return not(isInterface()).and(safeHasSuperType(named("ratpack.exec.ExecStarter")));
}
@Override
@ -136,7 +136,7 @@ public final class RatpackInstrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return named("ratpack.exec.Execution")
.or(not(isInterface()).and(hasSuperType(named("ratpack.exec.Execution"))));
.or(not(isInterface()).and(safeHasSuperType(named("ratpack.exec.Execution"))));
}
@Override

View File

@ -1,8 +1,7 @@
package datadog.trace.instrumentation.servlet2;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -24,7 +23,7 @@ public final class FilterChain2Instrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(failSafe(hasSuperType(named("javax.servlet.FilterChain"))));
return not(isInterface()).and(safeHasSuperType(named("javax.servlet.FilterChain")));
}
@Override

View File

@ -1,8 +1,7 @@
package datadog.trace.instrumentation.servlet2;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isProtected;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -29,7 +28,7 @@ public final class HttpServlet2Instrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(failSafe(hasSuperType(named("javax.servlet.http.HttpServlet"))));
return not(isInterface()).and(safeHasSuperType(named("javax.servlet.http.HttpServlet")));
}
@Override

View File

@ -1,8 +1,7 @@
package datadog.trace.instrumentation.servlet3;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -22,7 +21,7 @@ public class AbstractServlet3Instrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(failSafe(hasSuperType(named("javax.servlet.FilterChain"))));
return not(isInterface()).and(safeHasSuperType(named("javax.servlet.FilterChain")));
}
@Override

View File

@ -1,7 +1,6 @@
package datadog.trace.instrumentation.servlet3;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -19,7 +18,7 @@ public final class FilterChain3Instrumentation extends AbstractServlet3Instrumen
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(failSafe(hasSuperType(named("javax.servlet.FilterChain"))));
return not(isInterface()).and(safeHasSuperType(named("javax.servlet.FilterChain")));
}
@Override

View File

@ -1,7 +1,6 @@
package datadog.trace.instrumentation.servlet3;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isProtected;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -19,7 +18,7 @@ public final class HttpServlet3Instrumentation extends AbstractServlet3Instrumen
@Override
public ElementMatcher typeMatcher() {
return not(isInterface()).and(failSafe(hasSuperType(named("javax.servlet.http.HttpServlet"))));
return not(isInterface()).and(safeHasSuperType(named("javax.servlet.http.HttpServlet")));
}
@Override

View File

@ -1,9 +1,8 @@
package datadog.trace.instrumentation.springweb;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClassWithField;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.failSafe;
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.isProtected;
@ -39,7 +38,7 @@ public final class SpringWebInstrumentation extends Instrumenter.Default {
@Override
public ElementMatcher typeMatcher() {
return not(isInterface())
.and(failSafe(hasSuperType(named("org.springframework.web.servlet.HandlerAdapter"))));
.and(safeHasSuperType(named("org.springframework.web.servlet.HandlerAdapter")));
}
@Override
@ -50,7 +49,7 @@ public final class SpringWebInstrumentation extends Instrumenter.Default {
@Override
public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(
isMethod()
.and(isPublic())
@ -74,7 +73,7 @@ public final class SpringWebInstrumentation extends Instrumenter.Default {
@Override
public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(
isMethod()
.and(isProtected())

View File

@ -1,8 +1,8 @@
package datadog.trace.instrumentation.trace_annotation;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static datadog.trace.instrumentation.trace_annotation.TraceConfigInstrumentation.PACKAGE_CLASS_NAME_REGEX;
import static net.bytebuddy.matcher.ElementMatchers.declaresMethod;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.is;
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -79,12 +79,12 @@ public final class TraceAnnotationsInstrumentation extends Instrumenter.Default
@Override
public ElementMatcher typeMatcher() {
return hasSuperType(declaresMethod(isAnnotatedWith(methodTraceMatcher)));
return safeHasSuperType(declaresMethod(isAnnotatedWith(methodTraceMatcher)));
}
@Override
public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(isAnnotatedWith(methodTraceMatcher), TraceAdvice.class.getName());
return transformers;
}

View File

@ -1,6 +1,6 @@
package datadog.trace.instrumentation.trace_annotation;
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.named;
import com.google.auto.service.AutoService;
@ -92,7 +92,7 @@ public class TraceConfigInstrumentation implements Instrumenter {
}
for (final Map.Entry<String, Set<String>> entry : classMethodsToTrace.entrySet()) {
TracerClassInstrumentation tracerConfigClass =
final TracerClassInstrumentation tracerConfigClass =
new TracerClassInstrumentation(entry.getKey(), entry.getValue());
agentBuilder = tracerConfigClass.instrument(agentBuilder);
}
@ -109,7 +109,7 @@ public class TraceConfigInstrumentation implements Instrumenter {
this("noop", Collections.singleton("noop"));
}
public TracerClassInstrumentation(String className, Set<String> methodNames) {
public TracerClassInstrumentation(final String className, final Set<String> methodNames) {
super("trace", "trace-config");
this.className = className;
this.methodNames = methodNames;
@ -117,7 +117,7 @@ public class TraceConfigInstrumentation implements Instrumenter {
@Override
public ElementMatcher<? super TypeDescription> typeMatcher() {
return hasSuperType(named(className));
return safeHasSuperType(named(className));
}
@Override
@ -131,7 +131,7 @@ public class TraceConfigInstrumentation implements Instrumenter {
}
}
Map<ElementMatcher, String> transformers = new HashMap<>();
final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put(methodMatchers, TraceAdvice.class.getName());
return transformers;
}