Allow instrumentation to be disabled
By default, instrumentation is enabled, and can be disabled by default by overriding the `defaultEnabled` method. Instrumentation can also be disabled individually or enabled when default is disabled.
This commit is contained in:
parent
3eeb27b900
commit
7d28a32fba
|
@ -35,10 +35,8 @@ dependencies {
|
|||
Project java_agent_project = project
|
||||
subprojects { subProj ->
|
||||
if (subProj.getPath().startsWith(java_agent_project.getPath() + ':instrumentation:')) {
|
||||
if (!subProj.getPath().startsWith(java_agent_project.getPath() + ':instrumentation:kafka')) {
|
||||
java_agent_project.dependencies {
|
||||
compile(project(subProj.getPath()))
|
||||
}
|
||||
java_agent_project.dependencies {
|
||||
compile(project(subProj.getPath()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,14 @@ import org.apache.http.impl.client.DefaultRedirectStrategy;
|
|||
import org.apache.http.impl.execchain.ClientExecChain;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public class ApacheHttpClientInstrumentation implements Instrumenter {
|
||||
public class ApacheHttpClientInstrumentation extends Instrumenter.Configurable {
|
||||
|
||||
public ApacheHttpClientInstrumentation() {
|
||||
super("httpclient");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
named("org.apache.http.impl.client.HttpClientBuilder"),
|
||||
|
|
|
@ -23,10 +23,14 @@ import net.bytebuddy.agent.builder.AgentBuilder;
|
|||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class AWSClientInstrumentation implements Instrumenter {
|
||||
public final class AWSClientInstrumentation extends Instrumenter.Configurable {
|
||||
|
||||
public AWSClientInstrumentation() {
|
||||
super("aws-sdk");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
hasSuperType(named("com.amazonaws.client.builder.AwsClientBuilder")),
|
||||
|
|
|
@ -18,9 +18,14 @@ import net.bytebuddy.agent.builder.AgentBuilder;
|
|||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public class CassandraClientInstrumentation implements Instrumenter {
|
||||
public class CassandraClientInstrumentation extends Instrumenter.Configurable {
|
||||
|
||||
public CassandraClientInstrumentation() {
|
||||
super("cassandra");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
named("com.datastax.driver.core.Cluster$Manager"),
|
||||
|
|
|
@ -22,14 +22,18 @@ import net.bytebuddy.agent.builder.AgentBuilder;
|
|||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class ConnectionInstrumentation implements Instrumenter {
|
||||
public final class ConnectionInstrumentation extends Instrumenter.Configurable {
|
||||
public static final Map<Connection, DBInfo> connectionInfo =
|
||||
Collections.synchronizedMap(new WeakHashMap<Connection, DBInfo>());
|
||||
public static final Map<PreparedStatement, String> preparedStatements =
|
||||
Collections.synchronizedMap(new WeakHashMap<PreparedStatement, String>());
|
||||
|
||||
public ConnectionInstrumentation() {
|
||||
super("jdbc");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(not(isInterface()).and(hasSuperType(named(Connection.class.getName()))))
|
||||
.transform(
|
||||
|
|
|
@ -24,11 +24,15 @@ import net.bytebuddy.agent.builder.AgentBuilder;
|
|||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class PreparedStatementInstrumentation implements Instrumenter {
|
||||
public final class PreparedStatementInstrumentation extends Instrumenter.Configurable {
|
||||
private static final String UNKNOWN_QUERY = "Unknown Query";
|
||||
|
||||
public PreparedStatementInstrumentation() {
|
||||
super("jdbc");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(not(isInterface()).and(hasSuperType(named(PreparedStatement.class.getName()))))
|
||||
.transform(
|
||||
|
|
|
@ -24,10 +24,14 @@ import net.bytebuddy.agent.builder.AgentBuilder;
|
|||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class StatementInstrumentation implements Instrumenter {
|
||||
public final class StatementInstrumentation extends Instrumenter.Configurable {
|
||||
|
||||
public StatementInstrumentation() {
|
||||
super("jdbc");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(not(isInterface()).and(hasSuperType(named(Statement.class.getName()))))
|
||||
.transform(
|
||||
|
|
|
@ -30,14 +30,18 @@ import net.bytebuddy.agent.builder.AgentBuilder;
|
|||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class JMS1MessageConsumerInstrumentation implements Instrumenter {
|
||||
public final class JMS1MessageConsumerInstrumentation extends Instrumenter.Configurable {
|
||||
public static final HelperInjector JMS1_HELPER_INJECTOR =
|
||||
new HelperInjector(
|
||||
"datadog.trace.instrumentation.jms.util.JmsUtil",
|
||||
"datadog.trace.instrumentation.jms.util.MessagePropertyTextMap");
|
||||
|
||||
public JMS1MessageConsumerInstrumentation() {
|
||||
super("jms", "jms-1");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
not(isInterface()).and(hasSuperType(named("javax.jms.MessageConsumer"))),
|
||||
|
|
|
@ -28,10 +28,14 @@ import net.bytebuddy.agent.builder.AgentBuilder;
|
|||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class JMS1MessageListenerInstrumentation implements Instrumenter {
|
||||
public final class JMS1MessageListenerInstrumentation extends Instrumenter.Configurable {
|
||||
|
||||
public JMS1MessageListenerInstrumentation() {
|
||||
super("jms", "jms-1");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
not(isInterface()).and(hasSuperType(named("javax.jms.MessageListener"))),
|
||||
|
|
|
@ -29,10 +29,14 @@ import net.bytebuddy.agent.builder.AgentBuilder;
|
|||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class JMS1MessageProducerInstrumentation implements Instrumenter {
|
||||
public final class JMS1MessageProducerInstrumentation extends Instrumenter.Configurable {
|
||||
|
||||
public JMS1MessageProducerInstrumentation() {
|
||||
super("jms", "jms-1");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
not(isInterface()).and(hasSuperType(named("javax.jms.MessageProducer"))),
|
||||
|
|
|
@ -30,14 +30,18 @@ import net.bytebuddy.agent.builder.AgentBuilder;
|
|||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class JMS2MessageConsumerInstrumentation implements Instrumenter {
|
||||
public final class JMS2MessageConsumerInstrumentation extends Instrumenter.Configurable {
|
||||
public static final HelperInjector JMS2_HELPER_INJECTOR =
|
||||
new HelperInjector(
|
||||
"datadog.trace.instrumentation.jms.util.JmsUtil",
|
||||
"datadog.trace.instrumentation.jms.util.MessagePropertyTextMap");
|
||||
|
||||
public JMS2MessageConsumerInstrumentation() {
|
||||
super("jms", "jms-2");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
not(isInterface()).and(hasSuperType(named("javax.jms.MessageConsumer"))),
|
||||
|
|
|
@ -28,10 +28,14 @@ import net.bytebuddy.agent.builder.AgentBuilder;
|
|||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class JMS2MessageListenerInstrumentation implements Instrumenter {
|
||||
public final class JMS2MessageListenerInstrumentation extends Instrumenter.Configurable {
|
||||
|
||||
public JMS2MessageListenerInstrumentation() {
|
||||
super("jms", "jms-2");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
not(isInterface()).and(hasSuperType(named("javax.jms.MessageListener"))),
|
||||
|
|
|
@ -29,10 +29,14 @@ import net.bytebuddy.agent.builder.AgentBuilder;
|
|||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class JMS2MessageProducerInstrumentation implements Instrumenter {
|
||||
public final class JMS2MessageProducerInstrumentation extends Instrumenter.Configurable {
|
||||
|
||||
public JMS2MessageProducerInstrumentation() {
|
||||
super("jms", "jms-2");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
not(isInterface()).and(hasSuperType(named("javax.jms.MessageProducer"))),
|
||||
|
|
|
@ -25,7 +25,7 @@ import net.bytebuddy.asm.Advice;
|
|||
import org.apache.kafka.clients.consumer.ConsumerRecord;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class KafkaConsumerInstrumentation implements Instrumenter {
|
||||
public final class KafkaConsumerInstrumentation extends Instrumenter.Configurable {
|
||||
public static final HelperInjector HELPER_INJECTOR =
|
||||
new HelperInjector(
|
||||
"datadog.trace.instrumentation.kafka_clients.TextMapExtractAdapter",
|
||||
|
@ -38,8 +38,17 @@ public final class KafkaConsumerInstrumentation implements Instrumenter {
|
|||
private static final String OPERATION = "kafka.consume";
|
||||
private static final String COMPONENT_NAME = "java-kafka";
|
||||
|
||||
public KafkaConsumerInstrumentation() {
|
||||
super("kafka");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
protected boolean defaultEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
named("org.apache.kafka.clients.consumer.ConsumerRecords"),
|
||||
|
|
|
@ -25,7 +25,7 @@ import org.apache.kafka.clients.producer.ProducerRecord;
|
|||
import org.apache.kafka.clients.producer.RecordMetadata;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class KafkaProducerInstrumentation implements Instrumenter {
|
||||
public final class KafkaProducerInstrumentation extends Instrumenter.Configurable {
|
||||
public static final HelperInjector HELPER_INJECTOR =
|
||||
new HelperInjector(
|
||||
"datadog.trace.instrumentation.kafka_clients.TextMapInjectAdapter",
|
||||
|
@ -34,8 +34,17 @@ public final class KafkaProducerInstrumentation implements Instrumenter {
|
|||
private static final String OPERATION = "kafka.produce";
|
||||
private static final String COMPONENT_NAME = "java-kafka";
|
||||
|
||||
public KafkaProducerInstrumentation() {
|
||||
super("kafka");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
protected boolean defaultEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
named("org.apache.kafka.clients.producer.KafkaProducer"),
|
||||
|
|
|
@ -18,12 +18,13 @@ import spock.lang.Shared
|
|||
import java.util.concurrent.LinkedBlockingQueue
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class KafkaTest extends AgentTestRunner {
|
||||
class KafkaClientTest extends AgentTestRunner {
|
||||
static final SHARED_TOPIC = "shared.topic"
|
||||
|
||||
static {
|
||||
((Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME)).setLevel(Level.WARN)
|
||||
((Logger) LoggerFactory.getLogger("datadog")).setLevel(Level.DEBUG)
|
||||
System.setProperty("dd.integration.kafka.enabled", "true")
|
||||
}
|
||||
|
||||
@Shared
|
|
@ -26,7 +26,7 @@ import net.bytebuddy.asm.Advice;
|
|||
import org.apache.kafka.streams.processor.internals.StampedRecord;
|
||||
|
||||
public class KafkaStreamsProcessorInstrumentation {
|
||||
// These two instrumentations work together to instrument StreamTask.process.
|
||||
// These two instrumentations work together to apply StreamTask.process.
|
||||
// The combination of these are needed because there's not a good instrumentation point.
|
||||
|
||||
public static final HelperInjector HELPER_INJECTOR =
|
||||
|
@ -36,10 +36,19 @@ public class KafkaStreamsProcessorInstrumentation {
|
|||
private static final String COMPONENT_NAME = "java-kafka";
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public static class StartInstrumentation implements Instrumenter {
|
||||
public static class StartInstrumentation extends Instrumenter.Configurable {
|
||||
|
||||
public StartInstrumentation() {
|
||||
super("kafka", "kafka-streams");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
protected boolean defaultEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
named("org.apache.kafka.streams.processor.internals.PartitionGroup"),
|
||||
|
@ -88,10 +97,19 @@ public class KafkaStreamsProcessorInstrumentation {
|
|||
}
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public static class StopInstrumentation implements Instrumenter {
|
||||
public static class StopInstrumentation extends Instrumenter.Configurable {
|
||||
|
||||
public StopInstrumentation() {
|
||||
super("kafka", "kafka-streams");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
protected boolean defaultEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
named("org.apache.kafka.streams.processor.internals.StreamTask"),
|
||||
|
|
|
@ -19,10 +19,19 @@ import org.apache.kafka.common.record.TimestampType;
|
|||
public class KafkaStreamsSourceNodeRecordDeserializerInstrumentation {
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public static class StartInstrumentation implements Instrumenter {
|
||||
public static class StartInstrumentation extends Instrumenter.Configurable {
|
||||
|
||||
public StartInstrumentation() {
|
||||
super("kafka", "kafka-streams");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
protected boolean defaultEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
named("org.apache.kafka.streams.processor.internals.SourceNodeRecordDeserializer"),
|
||||
|
|
|
@ -32,6 +32,7 @@ class KafkaStreamsTest extends AgentTestRunner {
|
|||
static {
|
||||
((Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME)).setLevel(Level.WARN)
|
||||
((Logger) LoggerFactory.getLogger("datadog")).setLevel(Level.DEBUG)
|
||||
System.setProperty("dd.integration.kafka.enabled", "true")
|
||||
}
|
||||
|
||||
@Shared
|
||||
|
|
|
@ -19,12 +19,16 @@ import net.bytebuddy.asm.Advice;
|
|||
import net.bytebuddy.description.type.TypeDescription;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class MongoClientInstrumentation implements Instrumenter {
|
||||
public final class MongoClientInstrumentation extends Instrumenter.Configurable {
|
||||
public static final HelperInjector MONGO_HELPER_INJECTOR =
|
||||
new HelperInjector("datadog.trace.instrumentation.mongo.DDTracingCommandListener");
|
||||
|
||||
public MongoClientInstrumentation() {
|
||||
super("mongo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
named("com.mongodb.MongoClientOptions$Builder")
|
||||
|
|
|
@ -18,10 +18,14 @@ import net.bytebuddy.asm.Advice;
|
|||
import net.bytebuddy.description.type.TypeDescription;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class MongoAsyncClientInstrumentation implements Instrumenter {
|
||||
public final class MongoAsyncClientInstrumentation extends Instrumenter.Configurable {
|
||||
|
||||
public MongoAsyncClientInstrumentation() {
|
||||
super("mongo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
named("com.mongodb.async.client.MongoClientSettings$Builder")
|
||||
|
|
|
@ -19,10 +19,14 @@ import okhttp3.Interceptor;
|
|||
import okhttp3.OkHttpClient;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public class OkHttp3Instrumentation implements Instrumenter {
|
||||
public class OkHttp3Instrumentation extends Instrumenter.Configurable {
|
||||
|
||||
public OkHttp3Instrumentation() {
|
||||
super("okhttp", "okhttp-3");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
named("okhttp3.OkHttpClient"),
|
||||
|
|
|
@ -31,11 +31,15 @@ import net.bytebuddy.agent.builder.AgentBuilder;
|
|||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class FilterChain2Instrumentation implements Instrumenter {
|
||||
public final class FilterChain2Instrumentation extends Instrumenter.Configurable {
|
||||
public static final String FILTER_CHAIN_OPERATION_NAME = "servlet.request";
|
||||
|
||||
public FilterChain2Instrumentation() {
|
||||
super("servlet", "servlet-2");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
not(isInterface()).and(hasSuperType(named("javax.servlet.FilterChain"))),
|
||||
|
|
|
@ -31,11 +31,15 @@ import net.bytebuddy.agent.builder.AgentBuilder;
|
|||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class HttpServlet2Instrumentation implements Instrumenter {
|
||||
public final class HttpServlet2Instrumentation extends Instrumenter.Configurable {
|
||||
public static final String SERVLET_OPERATION_NAME = "servlet.request";
|
||||
|
||||
public HttpServlet2Instrumentation() {
|
||||
super("servlet", "servlet-2");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
not(isInterface()).and(hasSuperType(named("javax.servlet.http.HttpServlet"))),
|
||||
|
|
|
@ -35,11 +35,15 @@ import net.bytebuddy.agent.builder.AgentBuilder;
|
|||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class FilterChain3Instrumentation implements Instrumenter {
|
||||
public final class FilterChain3Instrumentation extends Instrumenter.Configurable {
|
||||
public static final String SERVLET_OPERATION_NAME = "servlet.request";
|
||||
|
||||
public FilterChain3Instrumentation() {
|
||||
super("servlet", "servlet-3");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
not(isInterface()).and(hasSuperType(named("javax.servlet.FilterChain"))),
|
||||
|
|
|
@ -33,11 +33,15 @@ import net.bytebuddy.agent.builder.AgentBuilder;
|
|||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class HttpServlet3Instrumentation implements Instrumenter {
|
||||
public final class HttpServlet3Instrumentation extends Instrumenter.Configurable {
|
||||
public static final String SERVLET_OPERATION_NAME = "servlet.request";
|
||||
|
||||
public HttpServlet3Instrumentation() {
|
||||
super("servlet", "servlet-3");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
not(isInterface()).and(hasSuperType(named("javax.servlet.http.HttpServlet"))),
|
||||
|
|
|
@ -23,10 +23,14 @@ import net.bytebuddy.asm.Advice;
|
|||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class SpringWebInstrumentation implements Instrumenter {
|
||||
public final class SpringWebInstrumentation extends Instrumenter.Configurable {
|
||||
|
||||
public SpringWebInstrumentation() {
|
||||
super("spring-web");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(
|
||||
not(isInterface())
|
||||
|
|
|
@ -18,10 +18,14 @@ import net.bytebuddy.agent.builder.AgentBuilder;
|
|||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
@AutoService(Instrumenter.class)
|
||||
public final class TraceAnnotationInstrumentation implements Instrumenter {
|
||||
public final class TraceAnnotationInstrumentation extends Instrumenter.Configurable {
|
||||
|
||||
public TraceAnnotationInstrumentation() {
|
||||
super("trace", "trace-annotation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
public AgentBuilder apply(final AgentBuilder agentBuilder) {
|
||||
return agentBuilder
|
||||
.type(hasSuperType(declaresMethod(isAnnotatedWith(Trace.class))))
|
||||
.transform(
|
||||
|
|
|
@ -55,8 +55,8 @@ public class AgentInstaller {
|
|||
"org.codehaus.groovy.runtime.callsite.CallSiteClassLoader")));
|
||||
int numInstrumenters = 0;
|
||||
for (final Instrumenter instrumenter : ServiceLoader.load(Instrumenter.class)) {
|
||||
agentBuilder = instrumenter.instrument(agentBuilder);
|
||||
log.debug("Loading instrumentation {}", instrumenter);
|
||||
agentBuilder = instrumenter.instrument(agentBuilder);
|
||||
numInstrumenters++;
|
||||
}
|
||||
log.debug("Installed {} instrumenter(s)", numInstrumenters);
|
||||
|
|
|
@ -1,7 +1,56 @@
|
|||
package datadog.trace.agent.tooling;
|
||||
|
||||
import static datadog.trace.agent.tooling.Utils.getConfigEnabled;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||
|
||||
public interface Instrumenter {
|
||||
|
||||
AgentBuilder instrument(AgentBuilder agentBuilder);
|
||||
|
||||
@Slf4j
|
||||
abstract class Configurable implements Instrumenter {
|
||||
private final Set<String> instrumentationNames;
|
||||
protected final boolean enabled;
|
||||
|
||||
public Configurable(final String instrumentationName, final String... additionalNames) {
|
||||
this.instrumentationNames = new HashSet(Arrays.asList(additionalNames));
|
||||
instrumentationNames.add(instrumentationName);
|
||||
|
||||
// If default is enabled, we want to enable individually,
|
||||
// if default is disabled, we want to disable individually.
|
||||
final boolean defaultEnabled = defaultEnabled();
|
||||
boolean anyEnabled = defaultEnabled;
|
||||
for (final String name : instrumentationNames) {
|
||||
final boolean configEnabled =
|
||||
getConfigEnabled("dd.integration." + name + ".enabled", defaultEnabled);
|
||||
if (defaultEnabled) {
|
||||
anyEnabled &= configEnabled;
|
||||
} else {
|
||||
anyEnabled |= configEnabled;
|
||||
}
|
||||
}
|
||||
enabled = anyEnabled;
|
||||
}
|
||||
|
||||
protected boolean defaultEnabled() {
|
||||
return getConfigEnabled("dd.integrations.enabled", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final AgentBuilder instrument(final AgentBuilder agentBuilder) {
|
||||
if (enabled) {
|
||||
return apply(agentBuilder);
|
||||
} else {
|
||||
log.debug("Instrumentation {} is disabled", this);
|
||||
return agentBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract AgentBuilder apply(AgentBuilder agentBuilder);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,5 +36,12 @@ public class Utils {
|
|||
}
|
||||
}
|
||||
|
||||
static boolean getConfigEnabled(final String name, final boolean fallback) {
|
||||
final String property =
|
||||
System.getProperty(
|
||||
name, System.getenv(name.toUpperCase().replaceAll("[^a-zA-Z0-9_]", "_")));
|
||||
return property == null ? fallback : Boolean.parseBoolean(property);
|
||||
}
|
||||
|
||||
private Utils() {}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package datadog.trace.agent.test;
|
||||
package datadog.trace.agent.tooling;
|
||||
|
||||
import net.bytebuddy.asm.Advice;
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
package datadog.trace.agent.tooling
|
||||
|
||||
import net.bytebuddy.agent.builder.AgentBuilder
|
||||
import org.junit.Rule
|
||||
import org.junit.contrib.java.lang.system.EnvironmentVariables
|
||||
import org.junit.contrib.java.lang.system.RestoreSystemProperties
|
||||
import spock.lang.Specification
|
||||
import spock.lang.Unroll
|
||||
|
||||
class ConfigurableInstrumenterTest extends Specification {
|
||||
@Rule
|
||||
public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties()
|
||||
@Rule
|
||||
public final EnvironmentVariables environmentVariables = new EnvironmentVariables()
|
||||
|
||||
def setup() {
|
||||
assert System.getenv().findAll { it.key.startsWith("DD_") }.isEmpty()
|
||||
assert System.getProperties().findAll { it.key.toString().startsWith("dd.") }.isEmpty()
|
||||
}
|
||||
|
||||
def "default enabled"() {
|
||||
setup:
|
||||
def target = new TestConfigurableInstrumenter("test")
|
||||
target.instrument(null)
|
||||
|
||||
expect:
|
||||
target.enabled
|
||||
target.applyCalled
|
||||
}
|
||||
|
||||
def "default enabled override"() {
|
||||
expect:
|
||||
target.instrument(null) == null
|
||||
target.enabled == enabled
|
||||
target.applyCalled == enabled
|
||||
|
||||
where:
|
||||
enabled | target
|
||||
true | new TestConfigurableInstrumenter("test") {
|
||||
@Override
|
||||
protected boolean defaultEnabled() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
false | new TestConfigurableInstrumenter("test") {
|
||||
@Override
|
||||
protected boolean defaultEnabled() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def "default disabled can override to enabled"() {
|
||||
setup:
|
||||
System.setProperty("dd.integration.test.enabled", "$enabled")
|
||||
def target = new TestConfigurableInstrumenter("test") {
|
||||
@Override
|
||||
protected boolean defaultEnabled() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
expect:
|
||||
target.instrument(null) == null
|
||||
target.enabled == enabled
|
||||
target.applyCalled == enabled
|
||||
|
||||
where:
|
||||
enabled << [true, false]
|
||||
}
|
||||
|
||||
@Unroll
|
||||
def "configure default sys prop as #value"() {
|
||||
setup:
|
||||
System.setProperty("dd.integrations.enabled", value)
|
||||
def target = new TestConfigurableInstrumenter("test")
|
||||
|
||||
expect:
|
||||
target.instrument(null) == null
|
||||
target.enabled == enabled
|
||||
target.applyCalled == enabled
|
||||
|
||||
where:
|
||||
value | enabled
|
||||
"true" | true
|
||||
"false" | false
|
||||
"asdf" | false
|
||||
}
|
||||
|
||||
@Unroll
|
||||
def "configure default env var as #value"() {
|
||||
setup:
|
||||
environmentVariables.set("DD_INTEGRATIONS_ENABLED", value)
|
||||
def target = new TestConfigurableInstrumenter("test")
|
||||
|
||||
expect:
|
||||
target.instrument(null) == null
|
||||
target.enabled == enabled
|
||||
target.applyCalled == enabled
|
||||
|
||||
where:
|
||||
value | enabled
|
||||
"true" | true
|
||||
"false" | false
|
||||
"asdf" | false
|
||||
}
|
||||
|
||||
@Unroll
|
||||
def "configure sys prop enabled for #value when default is disabled"() {
|
||||
setup:
|
||||
System.setProperty("dd.integrations.enabled", "false")
|
||||
System.setProperty("dd.integration.${value}.enabled", "true")
|
||||
def target = new TestConfigurableInstrumenter(name, altName)
|
||||
|
||||
expect:
|
||||
target.instrument(null) == null
|
||||
target.enabled == enabled
|
||||
target.applyCalled == enabled
|
||||
|
||||
where:
|
||||
value | enabled | name | altName
|
||||
"test" | true | "test" | "asdf"
|
||||
"duplicate" | true | "duplicate" | "duplicate"
|
||||
"bad" | false | "not" | "valid"
|
||||
"altTest" | true | "asdf" | "altTest"
|
||||
"dash-test" | true | "dash-test" | "asdf"
|
||||
"underscore_test" | true | "asdf" | "underscore_test"
|
||||
"period.test" | true | "period.test" | "asdf"
|
||||
}
|
||||
|
||||
@Unroll
|
||||
def "configure env var enabled for #value when default is disabled"() {
|
||||
setup:
|
||||
environmentVariables.set("DD_INTEGRATIONS_ENABLED", "false")
|
||||
environmentVariables.set("DD_INTEGRATION_${value}_ENABLED", "true")
|
||||
def target = new TestConfigurableInstrumenter(name, altName)
|
||||
|
||||
expect:
|
||||
System.getenv("DD_INTEGRATION_${value}_ENABLED") == "true"
|
||||
target.instrument(null) == null
|
||||
target.enabled == enabled
|
||||
target.applyCalled == enabled
|
||||
|
||||
where:
|
||||
value | enabled | name | altName
|
||||
"TEST" | true | "test" | "asdf"
|
||||
"DUPLICATE" | true | "duplicate" | "duplicate"
|
||||
"BAD" | false | "not" | "valid"
|
||||
"ALTTEST" | true | "asdf" | "altTest"
|
||||
"DASH_TEST" | true | "dash-test" | "asdf"
|
||||
"UNDERSCORE_TEST" | true | "asdf" | "underscore_test"
|
||||
"PERIOD_TEST" | true | "period.test" | "asdf"
|
||||
}
|
||||
|
||||
class TestConfigurableInstrumenter extends Instrumenter.Configurable {
|
||||
boolean applyCalled = false
|
||||
|
||||
TestConfigurableInstrumenter(
|
||||
String instrumentationName) {
|
||||
super(instrumentationName)
|
||||
}
|
||||
|
||||
TestConfigurableInstrumenter(
|
||||
String instrumentationName, String additionalName) {
|
||||
super(instrumentationName, [additionalName])
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AgentBuilder apply(AgentBuilder agentBuilder) {
|
||||
applyCalled = true
|
||||
return null
|
||||
}
|
||||
|
||||
def getEnabled() {
|
||||
return super.enabled
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +1,18 @@
|
|||
package datadog.trace.agent.test
|
||||
package datadog.trace.agent.tooling
|
||||
|
||||
import datadog.trace.agent.tooling.ExceptionHandlers
|
||||
import ch.qos.logback.classic.Level
|
||||
import ch.qos.logback.classic.Logger
|
||||
import ch.qos.logback.core.read.ListAppender
|
||||
import net.bytebuddy.agent.ByteBuddyAgent
|
||||
import net.bytebuddy.agent.builder.AgentBuilder
|
||||
import net.bytebuddy.dynamic.ClassFileLocator
|
||||
import org.slf4j.LoggerFactory
|
||||
import spock.lang.Shared
|
||||
import spock.lang.Specification
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isMethod
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named
|
||||
|
||||
import net.bytebuddy.agent.builder.AgentBuilder
|
||||
import spock.lang.Specification
|
||||
import spock.lang.Shared
|
||||
|
||||
import org.slf4j.LoggerFactory
|
||||
import ch.qos.logback.classic.Logger
|
||||
import ch.qos.logback.core.read.ListAppender
|
||||
import ch.qos.logback.classic.Level
|
||||
|
||||
class ExceptionHandlerTest extends Specification {
|
||||
@Shared
|
||||
ListAppender testAppender = new ListAppender()
|
||||
|
@ -24,7 +21,7 @@ class ExceptionHandlerTest extends Specification {
|
|||
AgentBuilder builder = new AgentBuilder.Default()
|
||||
.disableClassFormatChanges()
|
||||
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
|
||||
.type(named(getClass().getName()+'$SomeClass'))
|
||||
.type(named(getClass().getName() + '$SomeClass'))
|
||||
.transform(
|
||||
new AgentBuilder.Transformer.ForAdvice()
|
||||
.with(new AgentBuilder.LocationStrategy.Simple(ClassFileLocator.ForClassLoader.of(BadAdvice.getClassLoader())))
|
||||
|
@ -60,11 +57,11 @@ class ExceptionHandlerTest extends Specification {
|
|||
testAppender.list.get(testAppender.list.size() - 1).getMessage() == "exception in instrumentation"
|
||||
}
|
||||
|
||||
def "exception on non-delegating classloader" () {
|
||||
def "exception on non-delegating classloader"() {
|
||||
setup:
|
||||
int initLogEvents = testAppender.list.size()
|
||||
URL[] classpath = [ SomeClass.getProtectionDomain().getCodeSource().getLocation(),
|
||||
GroovyObject.getProtectionDomain().getCodeSource().getLocation() ]
|
||||
URL[] classpath = [SomeClass.getProtectionDomain().getCodeSource().getLocation(),
|
||||
GroovyObject.getProtectionDomain().getCodeSource().getLocation()]
|
||||
URLClassLoader loader = new URLClassLoader(classpath, (ClassLoader) null)
|
||||
when:
|
||||
loader.loadClass(LoggerFactory.getName())
|
|
@ -1,4 +1,4 @@
|
|||
package datadog.trace.agent.test;
|
||||
package datadog.trace.agent.tooling;
|
||||
|
||||
/** Used by {@link HelperInjectionTest} */
|
||||
class HelperClass {}
|
|
@ -1,7 +1,5 @@
|
|||
package datadog.trace.agent.test
|
||||
package datadog.trace.agent.tooling
|
||||
|
||||
import datadog.trace.agent.tooling.HelperInjector
|
||||
import datadog.trace.agent.tooling.Utils
|
||||
import spock.lang.Specification
|
||||
|
||||
import java.lang.reflect.Method
|
|
@ -40,6 +40,7 @@ dependencies {
|
|||
|
||||
testCompile group: 'org.objenesis', name: 'objenesis', version: '2.6'
|
||||
testCompile group: 'cglib', name: 'cglib-nodep', version: '3.2.5'
|
||||
testCompile 'com.github.stefanbirkner:system-rules:1.17.1'
|
||||
}
|
||||
|
||||
jmh {
|
||||
|
|
|
@ -6,56 +6,23 @@ import datadog.trace.common.sampling.AllSampler
|
|||
import datadog.trace.common.writer.DDAgentWriter
|
||||
import datadog.trace.common.writer.ListWriter
|
||||
import datadog.trace.common.writer.LoggingWriter
|
||||
import org.junit.Rule
|
||||
import org.junit.contrib.java.lang.system.EnvironmentVariables
|
||||
import org.junit.contrib.java.lang.system.RestoreSystemProperties
|
||||
import spock.lang.Specification
|
||||
import spock.lang.Unroll
|
||||
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Modifier
|
||||
|
||||
import static datadog.trace.common.DDTraceConfig.*
|
||||
|
||||
class DDTraceConfigTest extends Specification {
|
||||
static originalEnvMap
|
||||
static overrideEnvMap = new HashMap<String, String>()
|
||||
|
||||
def setupSpec() {
|
||||
def envMapField = ProcessEnvironment.getDeclaredField("theUnmodifiableEnvironment")
|
||||
envMapField.setAccessible(true)
|
||||
|
||||
Field modifiersField = Field.getDeclaredField("modifiers")
|
||||
modifiersField.setAccessible(true)
|
||||
modifiersField.setInt(envMapField, envMapField.getModifiers() & ~Modifier.FINAL)
|
||||
|
||||
originalEnvMap = envMapField.get(null)
|
||||
overrideEnvMap.putAll(originalEnvMap)
|
||||
envMapField.set(null, overrideEnvMap)
|
||||
}
|
||||
|
||||
def cleanupSpec() {
|
||||
def envMapField = ProcessEnvironment.getDeclaredField("theUnmodifiableEnvironment")
|
||||
envMapField.setAccessible(true)
|
||||
|
||||
Field modifiersField = Field.getDeclaredField("modifiers")
|
||||
modifiersField.setAccessible(true)
|
||||
modifiersField.setInt(envMapField, envMapField.getModifiers() & ~Modifier.FINAL)
|
||||
|
||||
originalEnvMap = envMapField.get(null)
|
||||
envMapField.set(null, originalEnvMap)
|
||||
}
|
||||
|
||||
def setup() {
|
||||
overrideEnvMap.clear()
|
||||
overrideEnvMap.putAll(originalEnvMap)
|
||||
|
||||
System.clearProperty(PREFIX + SERVICE_NAME)
|
||||
System.clearProperty(PREFIX + WRITER_TYPE)
|
||||
System.clearProperty(PREFIX + AGENT_HOST)
|
||||
System.clearProperty(PREFIX + AGENT_PORT)
|
||||
}
|
||||
@Rule
|
||||
public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties()
|
||||
@Rule
|
||||
public final EnvironmentVariables environmentVariables = new EnvironmentVariables()
|
||||
|
||||
def "verify env override"() {
|
||||
setup:
|
||||
overrideEnvMap.put("SOME_RANDOM_ENTRY", "asdf")
|
||||
environmentVariables.set("SOME_RANDOM_ENTRY", "asdf")
|
||||
|
||||
expect:
|
||||
System.getenv("SOME_RANDOM_ENTRY") == "asdf"
|
||||
|
@ -94,8 +61,8 @@ class DDTraceConfigTest extends Specification {
|
|||
|
||||
def "specify overrides via env vars"() {
|
||||
when:
|
||||
overrideEnvMap.put(propToEnvName(PREFIX + SERVICE_NAME), "still something else")
|
||||
overrideEnvMap.put(propToEnvName(PREFIX + WRITER_TYPE), LoggingWriter.simpleName)
|
||||
environmentVariables.set(propToEnvName(PREFIX + SERVICE_NAME), "still something else")
|
||||
environmentVariables.set(propToEnvName(PREFIX + WRITER_TYPE), LoggingWriter.simpleName)
|
||||
def tracer = new DDTracer()
|
||||
|
||||
then:
|
||||
|
@ -105,8 +72,8 @@ class DDTraceConfigTest extends Specification {
|
|||
|
||||
def "sys props override env vars"() {
|
||||
when:
|
||||
overrideEnvMap.put(propToEnvName(PREFIX + SERVICE_NAME), "still something else")
|
||||
overrideEnvMap.put(propToEnvName(PREFIX + WRITER_TYPE), ListWriter.simpleName)
|
||||
environmentVariables.set(propToEnvName(PREFIX + SERVICE_NAME), "still something else")
|
||||
environmentVariables.set(propToEnvName(PREFIX + WRITER_TYPE), ListWriter.simpleName)
|
||||
|
||||
System.setProperty(PREFIX + SERVICE_NAME, "what we actually want")
|
||||
System.setProperty(PREFIX + WRITER_TYPE, DDAgentWriter.simpleName)
|
||||
|
|
|
@ -43,6 +43,7 @@ dependencies {
|
|||
testCompile deps.groovy
|
||||
testCompile deps.testLogging
|
||||
testCompile group: 'io.ratpack', name: 'ratpack-groovy-test', version: '1.4.6'
|
||||
testCompile group: 'com.github.stefanbirkner', name: 'system-rules', version: '1.17.1'
|
||||
}
|
||||
|
||||
tasks.withType(Javadoc) {
|
||||
|
|
Loading…
Reference in New Issue