WeakCache instead of WeakMap (#1256)
WeakCache abstraction in addition to WeakMap
This commit is contained in:
parent
8e6f342e55
commit
a5a5743f7c
|
@ -0,0 +1,19 @@
|
|||
package datadog.trace.bootstrap;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public interface WeakCache<K, V> {
|
||||
interface Provider<K, V> {
|
||||
WeakCache<K, V> newWeakCache();
|
||||
|
||||
WeakCache<K, V> newWeakCache(final long maxSize);
|
||||
}
|
||||
|
||||
V getIfPresent(final K key);
|
||||
|
||||
V getIfPresentOrCompute(final K key, final Callable<? extends V> loader);
|
||||
|
||||
V get(final K key, final Callable<? extends V> loader);
|
||||
|
||||
void put(final K key, final V value);
|
||||
}
|
|
@ -6,11 +6,11 @@ class WeakMapTest extends Specification {
|
|||
|
||||
def supplier = new CounterSupplier()
|
||||
|
||||
def sut = new WeakMap.MapAdapter<String, Integer>(new WeakHashMap<>())
|
||||
def weakMap = new WeakMap.MapAdapter<String, Integer>(new WeakHashMap<>())
|
||||
|
||||
def "getOrCreate a value"() {
|
||||
when:
|
||||
def count = sut.computeIfAbsent('key', supplier)
|
||||
def count = weakMap.computeIfAbsent('key', supplier)
|
||||
|
||||
then:
|
||||
count == 1
|
||||
|
@ -19,8 +19,8 @@ class WeakMapTest extends Specification {
|
|||
|
||||
def "getOrCreate a value multiple times same class loader same key"() {
|
||||
when:
|
||||
def count1 = sut.computeIfAbsent('key', supplier)
|
||||
def count2 = sut.computeIfAbsent('key', supplier)
|
||||
def count1 = weakMap.computeIfAbsent('key', supplier)
|
||||
def count2 = weakMap.computeIfAbsent('key', supplier)
|
||||
|
||||
then:
|
||||
count1 == 1
|
||||
|
@ -30,8 +30,8 @@ class WeakMapTest extends Specification {
|
|||
|
||||
def "getOrCreate a value multiple times same class loader different keys"() {
|
||||
when:
|
||||
def count1 = sut.computeIfAbsent('key1', supplier)
|
||||
def count2 = sut.computeIfAbsent('key2', supplier)
|
||||
def count1 = weakMap.computeIfAbsent('key1', supplier)
|
||||
def count2 = weakMap.computeIfAbsent('key2', supplier)
|
||||
|
||||
then:
|
||||
count1 == 1
|
||||
|
|
|
@ -2,7 +2,11 @@ package datadog.trace.agent.tooling;
|
|||
|
||||
import datadog.trace.agent.tooling.bytebuddy.DDCachingPoolStrategy;
|
||||
import datadog.trace.agent.tooling.bytebuddy.DDLocationStrategy;
|
||||
import datadog.trace.bootstrap.WeakCache;
|
||||
import datadog.trace.bootstrap.WeakCache.Provider;
|
||||
import datadog.trace.bootstrap.WeakMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
/**
|
||||
* This class contains class references for objects shared by the agent installer as well as muzzle
|
||||
|
@ -16,9 +20,41 @@ public class AgentTooling {
|
|||
registerWeakMapProvider();
|
||||
}
|
||||
|
||||
private static void registerWeakMapProvider() {
|
||||
if (!WeakMap.Provider.isProviderRegistered()) {
|
||||
WeakMap.Provider.registerIfAbsent(new WeakMapSuppliers.WeakConcurrent(new Cleaner()));
|
||||
// WeakMap.Provider.registerIfAbsent(new WeakMapSuppliers.WeakConcurrent.Inline());
|
||||
// WeakMap.Provider.registerIfAbsent(new WeakMapSuppliers.Guava());
|
||||
}
|
||||
}
|
||||
|
||||
private static <K, V> Provider loadWeakCacheProvider() {
|
||||
final Iterator<Provider> providers =
|
||||
ServiceLoader.load(Provider.class, AgentInstaller.class.getClassLoader()).iterator();
|
||||
if (providers.hasNext()) {
|
||||
final Provider provider = providers.next();
|
||||
if (providers.hasNext()) {
|
||||
throw new IllegalStateException(
|
||||
"Only one implementation of WeakCache.Provider suppose to be in classpath");
|
||||
}
|
||||
return provider;
|
||||
}
|
||||
throw new IllegalStateException("Can't load implementation of WeakCache.Provider");
|
||||
}
|
||||
|
||||
private static final Provider weakCacheProvider = loadWeakCacheProvider();
|
||||
|
||||
private static final DDLocationStrategy LOCATION_STRATEGY = new DDLocationStrategy();
|
||||
private static final DDCachingPoolStrategy POOL_STRATEGY = new DDCachingPoolStrategy();
|
||||
|
||||
public static <K, V> WeakCache<K, V> newWeakCache() {
|
||||
return weakCacheProvider.newWeakCache();
|
||||
}
|
||||
|
||||
public static <K, V> WeakCache<K, V> newWeakCache(final long maxSize) {
|
||||
return weakCacheProvider.newWeakCache(maxSize);
|
||||
}
|
||||
|
||||
public static DDLocationStrategy locationStrategy() {
|
||||
return LOCATION_STRATEGY;
|
||||
}
|
||||
|
@ -26,12 +62,4 @@ public class AgentTooling {
|
|||
public static DDCachingPoolStrategy poolStrategy() {
|
||||
return POOL_STRATEGY;
|
||||
}
|
||||
|
||||
private static void registerWeakMapProvider() {
|
||||
if (!WeakMap.Provider.isProviderRegistered()) {
|
||||
WeakMap.Provider.registerIfAbsent(new WeakMapSuppliers.WeakConcurrent(new Cleaner()));
|
||||
// WeakMap.Provider.registerIfAbsent(new WeakMapSuppliers.WeakConcurrent.Inline());
|
||||
// WeakMap.Provider.registerIfAbsent(new WeakMapSuppliers.Guava());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import java.util.Set;
|
|||
public class ClassHierarchyIterable implements Iterable<Class<?>> {
|
||||
private final Class<?> baseClass;
|
||||
|
||||
public ClassHierarchyIterable(final Class baseClass) {
|
||||
public ClassHierarchyIterable(final Class<?> baseClass) {
|
||||
this.baseClass = baseClass;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package datadog.trace.agent.tooling;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import datadog.trace.bootstrap.PatchLogger;
|
||||
import datadog.trace.bootstrap.WeakCache;
|
||||
import io.opentracing.util.GlobalTracer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
@ -10,9 +9,6 @@ import net.bytebuddy.matcher.ElementMatcher;
|
|||
@Slf4j
|
||||
public final class ClassLoaderMatcher {
|
||||
public static final ClassLoader BOOTSTRAP_CLASSLOADER = null;
|
||||
public static final int CACHE_MAX_SIZE = 25; // limit number of cached responses for each matcher.
|
||||
public static final int CACHE_CONCURRENCY =
|
||||
Math.max(8, Runtime.getRuntime().availableProcessors());
|
||||
|
||||
/** A private constructor that must not be invoked. */
|
||||
private ClassLoaderMatcher() {
|
||||
|
@ -39,10 +35,9 @@ public final class ClassLoaderMatcher {
|
|||
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 Cache<ClassLoader, Boolean> skipCache =
|
||||
CacheBuilder.newBuilder().weakKeys().concurrencyLevel(CACHE_CONCURRENCY).build();
|
||||
private static final String DATADOG_CLASSLOADER_NAME =
|
||||
"datadog.trace.bootstrap.DatadogClassLoader";
|
||||
private static final WeakCache<ClassLoader, Boolean> skipCache = AgentTooling.newWeakCache();
|
||||
|
||||
private SkipClassLoaderMatcher() {}
|
||||
|
||||
|
@ -115,12 +110,7 @@ public final class ClassLoaderMatcher {
|
|||
private static class ClassLoaderHasClassesNamedMatcher
|
||||
extends ElementMatcher.Junction.AbstractBase<ClassLoader> {
|
||||
|
||||
private final Cache<ClassLoader, Boolean> cache =
|
||||
CacheBuilder.newBuilder()
|
||||
.weakKeys()
|
||||
.maximumSize(CACHE_MAX_SIZE)
|
||||
.concurrencyLevel(CACHE_CONCURRENCY)
|
||||
.build();
|
||||
private final WeakCache<ClassLoader, Boolean> cache = AgentTooling.newWeakCache(25);
|
||||
|
||||
private final String[] resources;
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
package datadog.trace.agent.tooling;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import datadog.trace.bootstrap.WeakCache;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* no null keys nor null values are permitted
|
||||
*
|
||||
* @param <K>
|
||||
* @param <V>
|
||||
*/
|
||||
@Slf4j
|
||||
public final class GuavaWeakCache<K, V> implements WeakCache<K, V> {
|
||||
@AutoService(WeakCache.Provider.class)
|
||||
public static final class Provider<K, V> implements WeakCache.Provider<K, V> {
|
||||
private static final int CACHE_CONCURRENCY =
|
||||
Math.max(8, Runtime.getRuntime().availableProcessors());
|
||||
|
||||
@Override
|
||||
public GuavaWeakCache<K, V> newWeakCache() {
|
||||
return new GuavaWeakCache(
|
||||
CacheBuilder.newBuilder()
|
||||
.weakKeys()
|
||||
.concurrencyLevel(CACHE_CONCURRENCY)
|
||||
.expireAfterAccess(10, TimeUnit.MINUTES)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuavaWeakCache<K, V> newWeakCache(final long maxSize) {
|
||||
return new GuavaWeakCache(
|
||||
CacheBuilder.newBuilder()
|
||||
.weakKeys()
|
||||
.maximumSize(maxSize)
|
||||
.concurrencyLevel(CACHE_CONCURRENCY)
|
||||
.expireAfterAccess(10, TimeUnit.MINUTES)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
private final Cache<K, V> cache;
|
||||
|
||||
private GuavaWeakCache(final Cache<K, V> cache) {
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null if key is not present
|
||||
* @param key
|
||||
*/
|
||||
@Override
|
||||
public V getIfPresent(final K key) {
|
||||
return cache.getIfPresent(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V getIfPresentOrCompute(final K key, final Callable<? extends V> loader) {
|
||||
final V v = cache.getIfPresent(key);
|
||||
if (v != null) {
|
||||
return v;
|
||||
}
|
||||
try {
|
||||
return cache.get(key, loader);
|
||||
} catch (ExecutionException e) {
|
||||
log.error("Can't get value from cache", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(final K key, final Callable<? extends V> loader) {
|
||||
try {
|
||||
return cache.get(key, loader);
|
||||
} catch (ExecutionException e) {
|
||||
log.error("Can't get value from cache", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(final K key, final V value) {
|
||||
cache.put(key, value);
|
||||
}
|
||||
}
|
|
@ -1,19 +1,19 @@
|
|||
package datadog.trace.agent.tooling.muzzle;
|
||||
|
||||
import static datadog.trace.bootstrap.WeakMap.Provider.newWeakMap;
|
||||
import static net.bytebuddy.dynamic.loading.ClassLoadingStrategy.BOOTSTRAP_LOADER;
|
||||
|
||||
import datadog.trace.agent.tooling.AgentTooling;
|
||||
import datadog.trace.agent.tooling.Utils;
|
||||
import datadog.trace.agent.tooling.muzzle.Reference.Mismatch;
|
||||
import datadog.trace.agent.tooling.muzzle.Reference.Source;
|
||||
import datadog.trace.bootstrap.WeakMap;
|
||||
import datadog.trace.bootstrap.WeakCache;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.bytebuddy.description.field.FieldDescription;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
|
@ -22,8 +22,8 @@ import net.bytebuddy.pool.TypePool;
|
|||
|
||||
/** Matches a set of references against a classloader. */
|
||||
@Slf4j
|
||||
public final class ReferenceMatcher implements WeakMap.ValueSupplier<ClassLoader, Boolean> {
|
||||
private final WeakMap<ClassLoader, Boolean> mismatchCache = newWeakMap();
|
||||
public final class ReferenceMatcher {
|
||||
private final WeakCache<ClassLoader, Boolean> mismatchCache = AgentTooling.newWeakCache();
|
||||
private final Reference[] references;
|
||||
private final Set<String> helperClassNames;
|
||||
|
||||
|
@ -50,12 +50,18 @@ public final class ReferenceMatcher implements WeakMap.ValueSupplier<ClassLoader
|
|||
if (loader == BOOTSTRAP_LOADER) {
|
||||
loader = Utils.getBootstrapProxy();
|
||||
}
|
||||
|
||||
return mismatchCache.computeIfAbsent(loader, this);
|
||||
final ClassLoader cl = loader;
|
||||
return mismatchCache.getIfPresentOrCompute(
|
||||
loader,
|
||||
new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() {
|
||||
return doesMatch(cl);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean get(final ClassLoader loader) {
|
||||
private boolean doesMatch(final ClassLoader loader) {
|
||||
for (final Reference reference : references) {
|
||||
// Don't reference-check helper classes.
|
||||
// They will be injected by the instrumentation's HelperInjector.
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
package datadog.trace.agent.tooling
|
||||
|
||||
import spock.lang.Specification
|
||||
|
||||
import java.util.concurrent.Callable
|
||||
|
||||
class WeakCacheTest extends Specification {
|
||||
def supplier = new CounterSupplier()
|
||||
|
||||
def weakCache = AgentTooling.newWeakCache()
|
||||
def weakCacheFor1elem = AgentTooling.newWeakCache(1)
|
||||
|
||||
def "getOrCreate a value"() {
|
||||
when:
|
||||
def count = weakCache.get('key', supplier)
|
||||
|
||||
then:
|
||||
count == 1
|
||||
supplier.counter == 1
|
||||
weakCache.cache.size() == 1
|
||||
}
|
||||
|
||||
def "getOrCreate a value multiple times same class loader same key"() {
|
||||
when:
|
||||
def count1 = weakCache.get('key', supplier)
|
||||
def count2 = weakCache.get('key', supplier)
|
||||
|
||||
then:
|
||||
count1 == 1
|
||||
count2 == 1
|
||||
supplier.counter == 1
|
||||
weakCache.cache.size() == 1
|
||||
}
|
||||
|
||||
def "getOrCreate a value multiple times same class loader different keys"() {
|
||||
when:
|
||||
def count1 = weakCache.get('key1', supplier)
|
||||
def count2 = weakCache.get('key2', supplier)
|
||||
|
||||
then:
|
||||
count1 == 1
|
||||
count2 == 2
|
||||
supplier.counter == 2
|
||||
weakCache.cache.size() == 2
|
||||
}
|
||||
|
||||
def "max size check"() {
|
||||
when:
|
||||
def sizeBefore = weakCacheFor1elem.cache.size()
|
||||
def valBefore = weakCacheFor1elem.getIfPresent("key1")
|
||||
def sizeAfter = weakCacheFor1elem.cache.size()
|
||||
def valAfterGet = weakCacheFor1elem.getIfPresentOrCompute("key1", supplier)
|
||||
def sizeAfterCompute = weakCacheFor1elem.cache.size()
|
||||
weakCacheFor1elem.put("key1", 42)
|
||||
def valAfterPut = weakCacheFor1elem.getIfPresentOrCompute("key1", supplier)
|
||||
def valByKey2 = weakCacheFor1elem.getIfPresentOrCompute("key2", supplier)
|
||||
def valAfterReplace = weakCacheFor1elem.getIfPresent("key1")
|
||||
|
||||
then:
|
||||
valBefore == null
|
||||
valAfterGet == 1
|
||||
sizeBefore == 0
|
||||
sizeAfter == 0
|
||||
sizeAfterCompute == 1
|
||||
valAfterPut == 42
|
||||
valByKey2 == 2
|
||||
valAfterReplace == null
|
||||
weakCacheFor1elem.cache.size() == 1
|
||||
}
|
||||
|
||||
class CounterSupplier implements Callable<Integer> {
|
||||
def counter = 0
|
||||
@Override
|
||||
Integer call() {
|
||||
counter = counter + 1
|
||||
return counter
|
||||
}
|
||||
}
|
||||
}
|
|
@ -114,8 +114,8 @@ tasks.withType(Test).configureEach {
|
|||
jvmArgs "-Ddd.service.name=java-agent-tests"
|
||||
jvmArgs "-Ddd.writer.type=LoggingWriter"
|
||||
// Multi-threaded logging seems to be causing deadlocks with Gradle's log capture.
|
||||
// jvmArgs "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=debug"
|
||||
// jvmArgs "-Dorg.slf4j.simpleLogger.defaultLogLevel=debug"
|
||||
// jvmArgs "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=debug"
|
||||
// jvmArgs "-Dorg.slf4j.simpleLogger.defaultLogLevel=debug"
|
||||
|
||||
doFirst {
|
||||
// Defining here to allow jacoco to be first on the command line.
|
||||
|
|
|
@ -19,7 +19,7 @@ import javax.ws.rs.Path;
|
|||
public class JaxRsAnnotationsDecorator extends BaseDecorator {
|
||||
public static JaxRsAnnotationsDecorator DECORATE = new JaxRsAnnotationsDecorator();
|
||||
|
||||
private final WeakMap<Class, Map<Method, String>> resourceNames = newWeakMap();
|
||||
private final WeakMap<Class<?>, Map<Method, String>> resourceNames = newWeakMap();
|
||||
|
||||
@Override
|
||||
protected String[] instrumentationNames() {
|
||||
|
@ -37,7 +37,7 @@ public class JaxRsAnnotationsDecorator extends BaseDecorator {
|
|||
}
|
||||
|
||||
public void onControllerStart(
|
||||
final AgentSpan span, final AgentSpan parent, final Class target, final Method method) {
|
||||
final AgentSpan span, final AgentSpan parent, final Class<?> target, final Method method) {
|
||||
final String resourceName = getPathResourceName(target, method);
|
||||
updateParent(parent, resourceName);
|
||||
|
||||
|
@ -70,9 +70,8 @@ public class JaxRsAnnotationsDecorator extends BaseDecorator {
|
|||
*
|
||||
* @return The result can be an empty string but will never be {@code null}.
|
||||
*/
|
||||
private String getPathResourceName(final Class target, final Method method) {
|
||||
private String getPathResourceName(final Class<?> target, final Method method) {
|
||||
Map<Method, String> classMap = resourceNames.get(target);
|
||||
|
||||
if (classMap == null) {
|
||||
resourceNames.putIfAbsent(target, new ConcurrentHashMap<Method, String>());
|
||||
classMap = resourceNames.get(target);
|
||||
|
@ -127,7 +126,7 @@ public class JaxRsAnnotationsDecorator extends BaseDecorator {
|
|||
return method.getAnnotation(Path.class);
|
||||
}
|
||||
|
||||
private Path findClassPath(final Class<Object> target) {
|
||||
private Path findClassPath(final Class<?> target) {
|
||||
for (final Class<?> currentClass : new ClassHierarchyIterable(target)) {
|
||||
final Path annotation = currentClass.getAnnotation(Path.class);
|
||||
if (annotation != null) {
|
||||
|
|
|
@ -14,7 +14,7 @@ import java.lang.reflect.Method
|
|||
|
||||
import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace
|
||||
|
||||
class JaxRsAnnotationsInstrumentationTest extends AgentTestRunner {
|
||||
class JaxRsAnnotations1InstrumentationTest extends AgentTestRunner {
|
||||
|
||||
def "instrumentation can be used as root span and resource is set to METHOD PATH"() {
|
||||
setup:
|
||||
|
@ -136,7 +136,7 @@ class JaxRsAnnotationsInstrumentationTest extends AgentTestRunner {
|
|||
// TODO: uncomment when we drop support for Java 7
|
||||
// "GET /child/invoke" | new JavaInterfaces.DefaultChildClassOnInterface()
|
||||
|
||||
className = getName(obj.class)
|
||||
className = getClassName(obj.class)
|
||||
|
||||
// JavaInterfaces classes are loaded on a different classloader, so we need to find the right cache instance.
|
||||
decorator = obj.class.classLoader.loadClass(JaxRsAnnotationsDecorator.name).getField("DECORATE").get(null)
|
||||
|
@ -193,18 +193,4 @@ class JaxRsAnnotationsInstrumentationTest extends AgentTestRunner {
|
|||
void call() {
|
||||
}
|
||||
}
|
||||
|
||||
def getName(Class clazz) {
|
||||
String className = clazz.getSimpleName()
|
||||
if (className.isEmpty()) {
|
||||
className = clazz.getName()
|
||||
if (clazz.getPackage() != null) {
|
||||
final String pkgName = clazz.getPackage().getName()
|
||||
if (!pkgName.isEmpty()) {
|
||||
className = clazz.getName().replace(pkgName, "").substring(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
return className
|
||||
}
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
package datadog.trace.instrumentation.jaxrs2;
|
||||
|
||||
import static datadog.trace.bootstrap.WeakMap.Provider.newWeakMap;
|
||||
|
||||
import datadog.trace.agent.tooling.ClassHierarchyIterable;
|
||||
import datadog.trace.api.DDSpanTypes;
|
||||
import datadog.trace.api.DDTags;
|
||||
|
@ -27,7 +25,8 @@ public class JaxRsAnnotationsDecorator extends BaseDecorator {
|
|||
|
||||
public static final JaxRsAnnotationsDecorator DECORATE = new JaxRsAnnotationsDecorator();
|
||||
|
||||
private final WeakMap<Class, Map<Method, String>> resourceNames = newWeakMap();
|
||||
private final WeakMap<Class<?>, Map<Method, String>> resourceNames =
|
||||
WeakMap.Provider.newWeakMap();
|
||||
|
||||
@Override
|
||||
protected String[] instrumentationNames() {
|
||||
|
@ -45,7 +44,7 @@ public class JaxRsAnnotationsDecorator extends BaseDecorator {
|
|||
}
|
||||
|
||||
public void onJaxRsSpan(
|
||||
final AgentSpan span, final AgentSpan parent, final Class target, final Method method) {
|
||||
final AgentSpan span, final AgentSpan parent, final Class<?> target, final Method method) {
|
||||
|
||||
final String resourceName = getPathResourceName(target, method);
|
||||
updateParent(parent, resourceName);
|
||||
|
@ -81,7 +80,7 @@ public class JaxRsAnnotationsDecorator extends BaseDecorator {
|
|||
*
|
||||
* @return The result can be an empty string but will never be {@code null}.
|
||||
*/
|
||||
private String getPathResourceName(final Class target, final Method method) {
|
||||
private String getPathResourceName(final Class<?> target, final Method method) {
|
||||
Map<Method, String> classMap = resourceNames.get(target);
|
||||
|
||||
if (classMap == null) {
|
||||
|
@ -138,7 +137,7 @@ public class JaxRsAnnotationsDecorator extends BaseDecorator {
|
|||
return method.getAnnotation(Path.class);
|
||||
}
|
||||
|
||||
private Path findClassPath(final Class<Object> target) {
|
||||
private Path findClassPath(final Class<?> target) {
|
||||
for (final Class<?> currentClass : new ClassHierarchyIterable(target)) {
|
||||
final Path annotation = currentClass.getAnnotation(Path.class);
|
||||
if (annotation != null) {
|
||||
|
|
|
@ -14,7 +14,7 @@ import java.lang.reflect.Method
|
|||
|
||||
import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace
|
||||
|
||||
class JaxRsAnnotationsInstrumentationTest extends AgentTestRunner {
|
||||
class JaxRsAnnotations2InstrumentationTest extends AgentTestRunner {
|
||||
|
||||
def "instrumentation can be used as root span and resource is set to METHOD PATH"() {
|
||||
setup:
|
||||
|
@ -136,7 +136,7 @@ class JaxRsAnnotationsInstrumentationTest extends AgentTestRunner {
|
|||
// TODO: uncomment when we drop support for Java 7
|
||||
// "GET /child/invoke" | new JavaInterfaces.DefaultChildClassOnInterface()
|
||||
|
||||
className = getName(obj.class)
|
||||
className = getClassName(obj.class)
|
||||
|
||||
// JavaInterfaces classes are loaded on a different classloader, so we need to find the right cache instance.
|
||||
decorator = obj.class.classLoader.loadClass(JaxRsAnnotationsDecorator.name).getField("DECORATE").get(null)
|
||||
|
@ -193,18 +193,4 @@ class JaxRsAnnotationsInstrumentationTest extends AgentTestRunner {
|
|||
void call() {
|
||||
}
|
||||
}
|
||||
|
||||
def getName(Class clazz) {
|
||||
String className = clazz.getSimpleName()
|
||||
if (className.isEmpty()) {
|
||||
className = clazz.getName()
|
||||
if (clazz.getPackage() != null) {
|
||||
final String pkgName = clazz.getPackage().getName()
|
||||
if (!pkgName.isEmpty()) {
|
||||
className = clazz.getName().replace(pkgName, "").substring(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
return className
|
||||
}
|
||||
}
|
|
@ -6,19 +6,17 @@ import datadog.trace.context.TraceScope;
|
|||
import datadog.trace.instrumentation.netty40.client.HttpClientTracingHandler;
|
||||
import datadog.trace.instrumentation.netty40.server.HttpServerTracingHandler;
|
||||
import io.netty.util.AttributeKey;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class AttributeKeys {
|
||||
|
||||
private static final WeakMap<ClassLoader, Map<String, AttributeKey<?>>> map =
|
||||
private static final WeakMap<ClassLoader, ConcurrentMap<String, AttributeKey<?>>> map =
|
||||
WeakMap.Implementation.DEFAULT.get();
|
||||
|
||||
private static final WeakMap.ValueSupplier<ClassLoader, Map<String, AttributeKey<?>>>
|
||||
private static final WeakMap.ValueSupplier<ClassLoader, ConcurrentMap<String, AttributeKey<?>>>
|
||||
mapSupplier =
|
||||
new WeakMap.ValueSupplier<ClassLoader, Map<String, AttributeKey<?>>>() {
|
||||
new WeakMap.ValueSupplier<ClassLoader, ConcurrentMap<String, AttributeKey<?>>>() {
|
||||
@Override
|
||||
public Map<String, AttributeKey<?>> get(final ClassLoader ignored) {
|
||||
public ConcurrentMap<String, AttributeKey<?>> get(final ClassLoader ignore) {
|
||||
return new ConcurrentHashMap<>();
|
||||
}
|
||||
};
|
||||
|
@ -44,7 +42,7 @@ public class AttributeKeys {
|
|||
* cassandra driver.
|
||||
*/
|
||||
private static <T> AttributeKey<T> attributeKey(final String key) {
|
||||
final Map<String, AttributeKey<?>> classLoaderMap =
|
||||
final ConcurrentMap<String, AttributeKey<?>> classLoaderMap =
|
||||
map.computeIfAbsent(AttributeKey.class.getClassLoader(), mapSupplier);
|
||||
if (classLoaderMap.containsKey(key)) {
|
||||
return (AttributeKey<T>) classLoaderMap.get(key);
|
||||
|
|
|
@ -6,19 +6,17 @@ import datadog.trace.context.TraceScope;
|
|||
import datadog.trace.instrumentation.netty41.client.HttpClientTracingHandler;
|
||||
import datadog.trace.instrumentation.netty41.server.HttpServerTracingHandler;
|
||||
import io.netty.util.AttributeKey;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class AttributeKeys {
|
||||
|
||||
private static final WeakMap<ClassLoader, Map<String, AttributeKey<?>>> map =
|
||||
private static final WeakMap<ClassLoader, ConcurrentMap<String, AttributeKey<?>>> map =
|
||||
WeakMap.Implementation.DEFAULT.get();
|
||||
|
||||
private static final WeakMap.ValueSupplier<ClassLoader, Map<String, AttributeKey<?>>>
|
||||
private static final WeakMap.ValueSupplier<ClassLoader, ConcurrentMap<String, AttributeKey<?>>>
|
||||
mapSupplier =
|
||||
new WeakMap.ValueSupplier<ClassLoader, Map<String, AttributeKey<?>>>() {
|
||||
new WeakMap.ValueSupplier<ClassLoader, ConcurrentMap<String, AttributeKey<?>>>() {
|
||||
@Override
|
||||
public Map<String, AttributeKey<?>> get(final ClassLoader ignored) {
|
||||
public ConcurrentMap<String, AttributeKey<?>> get(final ClassLoader ignore) {
|
||||
return new ConcurrentHashMap<>();
|
||||
}
|
||||
};
|
||||
|
@ -48,7 +46,7 @@ public class AttributeKeys {
|
|||
* cassandra driver.
|
||||
*/
|
||||
private static <T> AttributeKey<T> attributeKey(final String key) {
|
||||
final Map<String, AttributeKey<?>> classLoaderMap =
|
||||
final ConcurrentMap<String, AttributeKey<?>> classLoaderMap =
|
||||
map.computeIfAbsent(AttributeKey.class.getClassLoader(), mapSupplier);
|
||||
if (classLoaderMap.containsKey(key)) {
|
||||
return (AttributeKey<T>) classLoaderMap.get(key);
|
||||
|
|
|
@ -307,4 +307,18 @@ public abstract class AgentTestRunner extends DDSpecification {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static String getClassName(Class clazz) {
|
||||
String className = clazz.getSimpleName();
|
||||
if (className.isEmpty()) {
|
||||
className = clazz.getName();
|
||||
if (clazz.getPackage() != null) {
|
||||
final String pkgName = clazz.getPackage().getName();
|
||||
if (!pkgName.isEmpty()) {
|
||||
className = clazz.getName().replace(pkgName, "").substring(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return className;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue