ClassLoaderMatcher switch to Guava Cache
This commit is contained in:
parent
51ca429915
commit
37bcb4e288
|
@ -1,10 +1,11 @@
|
|||
package datadog.trace.agent.tooling;
|
||||
|
||||
import static datadog.trace.bootstrap.WeakMap.Provider.newWeakMap;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import datadog.trace.bootstrap.PatchLogger;
|
||||
import datadog.trace.bootstrap.WeakMap;
|
||||
import io.opentracing.util.GlobalTracer;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
|
@ -26,12 +27,20 @@ public class ClassLoaderMatcher {
|
|||
return new ClassLoaderHasClassMatcher(names);
|
||||
}
|
||||
|
||||
private static class SkipClassLoaderMatcher
|
||||
extends ElementMatcher.Junction.AbstractBase<ClassLoader>
|
||||
implements WeakMap.ValueSupplier<ClassLoader, Boolean> {
|
||||
private static final class SkipClassLoaderMatcher
|
||||
extends ElementMatcher.Junction.AbstractBase<ClassLoader> {
|
||||
public static final SkipClassLoaderMatcher INSTANCE = new SkipClassLoaderMatcher();
|
||||
/* Cache of classloader-instance -> (true|false). True = skip instrumentation. False = safe to instrument. */
|
||||
private static final WeakMap<ClassLoader, Boolean> SKIP_CACHE = newWeakMap();
|
||||
private static final LoadingCache<ClassLoader, Boolean> skipCache =
|
||||
CacheBuilder.newBuilder()
|
||||
.weakKeys()
|
||||
.build(
|
||||
new CacheLoader<ClassLoader, Boolean>() {
|
||||
@Override
|
||||
public Boolean load(ClassLoader loader) {
|
||||
return !delegatesToBootstrap(loader);
|
||||
}
|
||||
});
|
||||
private static final String DATADOG_CLASSLOADER_NAME =
|
||||
"datadog.trace.bootstrap.DatadogClassLoader";
|
||||
|
||||
|
@ -46,7 +55,7 @@ public class ClassLoaderMatcher {
|
|||
return shouldSkipClass(target) || shouldSkipInstance(target);
|
||||
}
|
||||
|
||||
private boolean shouldSkipClass(final ClassLoader loader) {
|
||||
private static boolean shouldSkipClass(final ClassLoader loader) {
|
||||
switch (loader.getClass().getName()) {
|
||||
case "org.codehaus.groovy.runtime.callsite.CallSiteClassLoader":
|
||||
case "sun.reflect.DelegatingClassLoader":
|
||||
|
@ -60,19 +69,13 @@ public class ClassLoaderMatcher {
|
|||
return false;
|
||||
}
|
||||
|
||||
private boolean shouldSkipInstance(final ClassLoader loader) {
|
||||
return SKIP_CACHE.computeIfAbsent(loader, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean get(final ClassLoader loader) {
|
||||
final boolean skip = !delegatesToBootstrap(loader);
|
||||
if (skip) {
|
||||
log.debug(
|
||||
"skipping classloader instance {} of type {}", loader, loader.getClass().getName());
|
||||
private static boolean shouldSkipInstance(final ClassLoader loader) {
|
||||
try {
|
||||
return skipCache.get(loader);
|
||||
} catch (ExecutionException e) {
|
||||
log.warn("Exception while getting from cache", e);
|
||||
}
|
||||
|
||||
return skip;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,7 +84,7 @@ public class ClassLoaderMatcher {
|
|||
* class loading is issued from this check and {@code false} for 'real' class loads. We should
|
||||
* come up with some sort of hack to avoid this problem.
|
||||
*/
|
||||
private boolean delegatesToBootstrap(final ClassLoader loader) {
|
||||
private static boolean delegatesToBootstrap(final ClassLoader loader) {
|
||||
boolean delegates = true;
|
||||
if (!loadsExpectedClass(loader, GlobalTracer.class)) {
|
||||
log.debug("loader {} failed to delegate bootstrap opentracing class", loader);
|
||||
|
@ -94,7 +97,8 @@ public class ClassLoaderMatcher {
|
|||
return delegates;
|
||||
}
|
||||
|
||||
private boolean loadsExpectedClass(final ClassLoader loader, final Class<?> expectedClass) {
|
||||
private static boolean loadsExpectedClass(
|
||||
final ClassLoader loader, final Class<?> expectedClass) {
|
||||
try {
|
||||
return loader.loadClass(expectedClass.getName()) == expectedClass;
|
||||
} catch (final ClassNotFoundException e) {
|
||||
|
@ -104,10 +108,23 @@ public class ClassLoaderMatcher {
|
|||
}
|
||||
|
||||
public static class ClassLoaderHasClassMatcher
|
||||
extends ElementMatcher.Junction.AbstractBase<ClassLoader>
|
||||
implements WeakMap.ValueSupplier<ClassLoader, Boolean> {
|
||||
extends ElementMatcher.Junction.AbstractBase<ClassLoader> {
|
||||
|
||||
private final WeakMap<ClassLoader, Boolean> cache = newWeakMap();
|
||||
private final LoadingCache<ClassLoader, Boolean> cache =
|
||||
CacheBuilder.newBuilder()
|
||||
.weakKeys()
|
||||
.build(
|
||||
new CacheLoader<ClassLoader, Boolean>() {
|
||||
@Override
|
||||
public Boolean load(ClassLoader cl) {
|
||||
for (final String name : names) {
|
||||
if (cl.getResource(Utils.getResourceName(name)) == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
private final String[] names;
|
||||
|
||||
|
@ -118,21 +135,13 @@ public class ClassLoaderMatcher {
|
|||
@Override
|
||||
public boolean matches(final ClassLoader target) {
|
||||
if (target != null) {
|
||||
return cache.computeIfAbsent(target, this);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean get(final ClassLoader target) {
|
||||
for (final String name : names) {
|
||||
if (target.getResource(Utils.getResourceName(name)) == null) {
|
||||
return false;
|
||||
try {
|
||||
return cache.get(target);
|
||||
} catch (ExecutionException e) {
|
||||
log.warn("Can't get from cache", e);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue