Remove dead code
This commit is contained in:
parent
e9b6f5278d
commit
f5ecd47379
|
@ -1,46 +0,0 @@
|
||||||
package com.datadoghq.agent;
|
|
||||||
|
|
||||||
import com.datadoghq.trace.DDTraceAnnotationsInfo;
|
|
||||||
import com.datadoghq.trace.DDTraceInfo;
|
|
||||||
import com.datadoghq.trace.resolver.DDTracerFactory;
|
|
||||||
import com.datadoghq.trace.resolver.FactoryUtils;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class AgentRulesManager {
|
|
||||||
|
|
||||||
// Initialize the info classes so they print out their version info:
|
|
||||||
private static final String ddJavaAgentVersion = DDJavaAgentInfo.VERSION;
|
|
||||||
private static final String ddTraceVersion = DDTraceInfo.VERSION;
|
|
||||||
private static final String ddTraceAnnotationsVersion = DDTraceAnnotationsInfo.VERSION;
|
|
||||||
|
|
||||||
private static final String INITIALIZER_RULES = "initializer-rules.btm";
|
|
||||||
|
|
||||||
protected static volatile AgentRulesManager INSTANCE;
|
|
||||||
|
|
||||||
protected final TracingAgentConfig agentTracerConfig;
|
|
||||||
protected final InstrumentationRulesManager instrumentationRulesManager;
|
|
||||||
|
|
||||||
public AgentRulesManager(final TracingAgentConfig config) {
|
|
||||||
agentTracerConfig = config;
|
|
||||||
instrumentationRulesManager = new InstrumentationRulesManager(config, this);
|
|
||||||
instrumentationRulesManager.initTracer();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This method initializes the manager. */
|
|
||||||
public static void initialize() {
|
|
||||||
log.debug("Initializing {}", AgentRulesManager.class.getSimpleName());
|
|
||||||
|
|
||||||
final TracingAgentConfig config =
|
|
||||||
FactoryUtils.loadConfigFromFilePropertyOrResource(
|
|
||||||
DDTracerFactory.SYSTEM_PROPERTY_CONFIG_PATH,
|
|
||||||
DDTracerFactory.CONFIG_PATH,
|
|
||||||
TracingAgentConfig.class);
|
|
||||||
|
|
||||||
log.debug("Configuration: {}", config.toString());
|
|
||||||
|
|
||||||
final AgentRulesManager manager = new AgentRulesManager(config);
|
|
||||||
|
|
||||||
INSTANCE = manager;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,93 +0,0 @@
|
||||||
package com.datadoghq.agent;
|
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
// TODO: consider augmenting with com.sun.xml.internal.bind.v2.runtime.reflect.opt.Injector
|
|
||||||
public class ClassLoaderIntegrationInjector {
|
|
||||||
private final Map<ZipEntry, byte[]> entries;
|
|
||||||
private final Map<ClassLoader, Method> invocationPoints = Maps.newConcurrentMap();
|
|
||||||
|
|
||||||
public ClassLoaderIntegrationInjector(final Map<ZipEntry, byte[]> allEntries) {
|
|
||||||
this.entries = Maps.newHashMap(allEntries);
|
|
||||||
for (final Iterator<Map.Entry<ZipEntry, byte[]>> it = entries.entrySet().iterator();
|
|
||||||
it.hasNext();
|
|
||||||
) {
|
|
||||||
final Map.Entry<ZipEntry, byte[]> entry = it.next();
|
|
||||||
if (!entry.getKey().getName().endsWith(".class")) {
|
|
||||||
// remove all non-class files
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void inject(final ClassLoader cl) {
|
|
||||||
try {
|
|
||||||
final Method inovcationPoint = getInovcationPoint(cl);
|
|
||||||
final Map<ZipEntry, byte[]> toInject = Maps.newHashMap(entries);
|
|
||||||
final Map<ZipEntry, byte[]> injectedEntries = Maps.newHashMap();
|
|
||||||
final List<Throwable> lastErrors = new LinkedList<>();
|
|
||||||
boolean successfulyAdded = true;
|
|
||||||
while (!toInject.isEmpty() && successfulyAdded) {
|
|
||||||
log.debug("Attempting to inject {} entries into {}", toInject.size(), cl);
|
|
||||||
successfulyAdded = false;
|
|
||||||
lastErrors.clear();
|
|
||||||
for (final Map.Entry<ZipEntry, byte[]> entry : toInject.entrySet()) {
|
|
||||||
final byte[] bytes = entry.getValue();
|
|
||||||
try {
|
|
||||||
inovcationPoint.invoke(cl, bytes, 0, bytes.length);
|
|
||||||
injectedEntries.put(entry.getKey(), entry.getValue());
|
|
||||||
successfulyAdded = true;
|
|
||||||
} catch (final InvocationTargetException e) {
|
|
||||||
lastErrors.add(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
toInject.keySet().removeAll(injectedEntries.keySet());
|
|
||||||
}
|
|
||||||
log.info("Successfully injected {} classes into {}", injectedEntries.size(), cl);
|
|
||||||
log.info("Failed injecting {} classes into {}", toInject.size(), cl);
|
|
||||||
log.debug("\nSuccesses: {}", injectedEntries);
|
|
||||||
log.debug("\nFailures: {}", toInject);
|
|
||||||
for (final Throwable error : lastErrors) {
|
|
||||||
log.debug("Injection error", error.getCause());
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (final NoSuchMethodException e) {
|
|
||||||
log.error("Error getting 'defineClass' method from {}", cl);
|
|
||||||
} catch (final IllegalAccessException e) {
|
|
||||||
log.error("Error accessing 'defineClass' method on {}", cl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Method getInovcationPoint(final ClassLoader cl) throws NoSuchMethodException {
|
|
||||||
if (invocationPoints.containsKey(invocationPoints)) {
|
|
||||||
return invocationPoints.get(invocationPoints);
|
|
||||||
}
|
|
||||||
Class<?> clazz = cl.getClass();
|
|
||||||
NoSuchMethodException firstException = null;
|
|
||||||
while (clazz != null) {
|
|
||||||
try {
|
|
||||||
// defineClass is protected so we may need to check up the class hierarchy.
|
|
||||||
final Method invocationPoint =
|
|
||||||
clazz.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
|
||||||
invocationPoint.setAccessible(true);
|
|
||||||
invocationPoints.put(cl, invocationPoint);
|
|
||||||
return invocationPoint;
|
|
||||||
} catch (final NoSuchMethodException e) {
|
|
||||||
if (firstException == null) {
|
|
||||||
firstException = e;
|
|
||||||
}
|
|
||||||
clazz = clazz.getSuperclass();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw firstException;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,141 +0,0 @@
|
||||||
package com.datadoghq.agent;
|
|
||||||
|
|
||||||
import com.datadoghq.trace.resolver.FactoryUtils;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility class to check the validity of the classpath concerning the java automated
|
|
||||||
* instrumentations
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class InstrumentationChecker {
|
|
||||||
|
|
||||||
private static final String CONFIG_FILE = "dd-trace-supported-framework";
|
|
||||||
|
|
||||||
private final Map<String, List<ArtifactSupport>> rules;
|
|
||||||
|
|
||||||
/* For testing purpose */
|
|
||||||
InstrumentationChecker(
|
|
||||||
final Map<String, List<ArtifactSupport>> rules, final Map<String, String> frameworks) {
|
|
||||||
this.rules = rules;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InstrumentationChecker() {
|
|
||||||
rules =
|
|
||||||
FactoryUtils.loadConfigFromResource(
|
|
||||||
CONFIG_FILE, new TypeReference<Map<String, List<ArtifactSupport>>>() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getUnsupportedRules(final ClassLoader classLoader) {
|
|
||||||
log.debug("Checking rule compatibility on classloader {}", classLoader);
|
|
||||||
|
|
||||||
final List<String> unsupportedRules = new ArrayList<>();
|
|
||||||
for (final String rule : rules.keySet()) {
|
|
||||||
|
|
||||||
// Check rules
|
|
||||||
boolean supported = false;
|
|
||||||
for (final ArtifactSupport check : rules.get(rule)) {
|
|
||||||
log.debug("Checking rule {}", check);
|
|
||||||
|
|
||||||
boolean matched =
|
|
||||||
(check.identifyingPresentClasses != null
|
|
||||||
&& !check.identifyingPresentClasses.entrySet().isEmpty())
|
|
||||||
|| (check.identifyingMissingClasses != null
|
|
||||||
&& !check.identifyingMissingClasses.isEmpty());
|
|
||||||
if (check.identifyingPresentClasses != null) {
|
|
||||||
for (final Map.Entry<String, String> identifier :
|
|
||||||
check.identifyingPresentClasses.entrySet()) {
|
|
||||||
final boolean classPresent = isClassPresent(identifier.getKey(), classLoader);
|
|
||||||
if (!classPresent) {
|
|
||||||
log.debug(
|
|
||||||
"Instrumentation {} not applied due to missing class {}.", rule, identifier);
|
|
||||||
} else {
|
|
||||||
final String identifyingMethod = identifier.getValue();
|
|
||||||
if (identifyingMethod != null && !identifyingMethod.isEmpty()) {
|
|
||||||
final Class clazz = getClassIfPresent(identifier.getKey(), classLoader);
|
|
||||||
// already confirmed above the class is there.
|
|
||||||
final Method[] declaredMethods = clazz.getDeclaredMethods();
|
|
||||||
boolean methodFound = false;
|
|
||||||
for (final Method m : declaredMethods) {
|
|
||||||
if (m.getName().equals(identifyingMethod)) {
|
|
||||||
methodFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!methodFound) {
|
|
||||||
log.debug(
|
|
||||||
"Instrumentation {} not applied due to missing method {}.{}",
|
|
||||||
rule,
|
|
||||||
identifier.getKey(),
|
|
||||||
identifyingMethod);
|
|
||||||
matched = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
matched &= classPresent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (check.identifyingMissingClasses != null) {
|
|
||||||
for (final String identifyingClass : check.identifyingMissingClasses) {
|
|
||||||
final boolean classMissing = !isClassPresent(identifyingClass, classLoader);
|
|
||||||
if (!classMissing) {
|
|
||||||
log.debug(
|
|
||||||
"Instrumentation {} not applied due to present class {}.",
|
|
||||||
rule,
|
|
||||||
identifyingClass);
|
|
||||||
}
|
|
||||||
matched &= classMissing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
supported |= matched;
|
|
||||||
if (supported) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!supported) {
|
|
||||||
log.info("Instrumentation rule={} is not supported", rule);
|
|
||||||
unsupportedRules.add(rule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return unsupportedRules;
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean isClassPresent(
|
|
||||||
final String identifyingPresentClass, final ClassLoader classLoader) {
|
|
||||||
return getClassIfPresent(identifyingPresentClass, classLoader) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Class getClassIfPresent(
|
|
||||||
final String identifyingPresentClass, final ClassLoader classLoader) {
|
|
||||||
try {
|
|
||||||
return Class.forName(identifyingPresentClass, false, classLoader);
|
|
||||||
} catch (final Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
|
||||||
static class ArtifactSupport {
|
|
||||||
private String artifact;
|
|
||||||
|
|
||||||
@JsonProperty("supported_version")
|
|
||||||
private String supportedVersion;
|
|
||||||
|
|
||||||
@JsonProperty("identifying_present_classes")
|
|
||||||
private Map<String, String> identifyingPresentClasses = Collections.emptyMap();
|
|
||||||
|
|
||||||
@JsonProperty("identifying_missing_classes")
|
|
||||||
private List<String> identifyingMissingClasses = Collections.emptyList();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
package com.datadoghq.agent;
|
|
||||||
|
|
||||||
import io.opentracing.Tracer;
|
|
||||||
import io.opentracing.contrib.tracerresolver.TracerResolver;
|
|
||||||
import io.opentracing.util.GlobalTracer;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This manager is loaded at pre-main. It loads all the scripts contained in all the 'oatrules.btm'
|
|
||||||
* resource files.
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class InstrumentationRulesManager {
|
|
||||||
private static final Object SYNC = new Object();
|
|
||||||
|
|
||||||
public InstrumentationRulesManager(
|
|
||||||
final TracingAgentConfig config, final AgentRulesManager agentRulesManager) {}
|
|
||||||
|
|
||||||
void initTracer() {
|
|
||||||
synchronized (SYNC) {
|
|
||||||
if (!GlobalTracer.isRegistered()) {
|
|
||||||
// Try to obtain a tracer using the TracerResolver
|
|
||||||
final Tracer resolved = TracerResolver.resolveTracer();
|
|
||||||
if (resolved != null) {
|
|
||||||
try {
|
|
||||||
GlobalTracer.register(resolved);
|
|
||||||
} catch (final RuntimeException re) {
|
|
||||||
log.warn("Failed to register tracer '" + resolved + "'", re);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.warn("Failed to resolve dd tracer");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
package com.datadoghq.agent;
|
|
||||||
|
|
||||||
import com.datadoghq.trace.resolver.TracerConfig;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/** Configuration POJO for the agent */
|
|
||||||
public class TracingAgentConfig extends TracerConfig {
|
|
||||||
|
|
||||||
private List<String> disabledInstrumentations = new ArrayList<>();
|
|
||||||
|
|
||||||
private String[] enableCustomAnnotationTracingOver = {};
|
|
||||||
|
|
||||||
public String[] getEnableCustomAnnotationTracingOver() {
|
|
||||||
return enableCustomAnnotationTracingOver;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEnableCustomAnnotationTracingOver(
|
|
||||||
final String[] enableCustomAnnotationTracingOver) {
|
|
||||||
this.enableCustomAnnotationTracingOver = enableCustomAnnotationTracingOver;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getDisabledInstrumentations() {
|
|
||||||
return disabledInstrumentations;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDisabledInstrumentations(final List<String> uninstallContributions) {
|
|
||||||
this.disabledInstrumentations = uninstallContributions;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
package com.datadoghq.agent
|
|
||||||
|
|
||||||
import com.datadoghq.trace.resolver.FactoryUtils
|
|
||||||
import com.fasterxml.jackson.core.type.TypeReference
|
|
||||||
import spock.lang.Specification
|
|
||||||
|
|
||||||
class InstrumentationCheckerTest extends Specification {
|
|
||||||
Map<String, List<Map<String, String>>> rules =
|
|
||||||
FactoryUtils.loadConfigFromResource("supported-version-test", new TypeReference<Map<String, List<InstrumentationChecker.ArtifactSupport>>>() {
|
|
||||||
})
|
|
||||||
Map<String, String> frameworks = [
|
|
||||||
"artifact-1": "1.2.3.1232",
|
|
||||||
"artifact-2": "4.y.z",
|
|
||||||
"artifact-3": "5.123-1"
|
|
||||||
]
|
|
||||||
|
|
||||||
def checker = new InstrumentationChecker(rules, frameworks)
|
|
||||||
|
|
||||||
def "test rules"() {
|
|
||||||
setup:
|
|
||||||
def rules = checker.getUnsupportedRules(getClass().getClassLoader())
|
|
||||||
|
|
||||||
expect:
|
|
||||||
rules.sort() == ["unsupportedRuleOne", "unsupportedRuleThree", "unsupportedRuleTwo"]
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DemoClass1 {
|
|
||||||
void testMethod(String arg) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DemoClass2 {}
|
|
||||||
|
|
||||||
static class DemoClass3 {}
|
|
||||||
}
|
|
Loading…
Reference in New Issue