New Instrumentation outline
@@ -10,27 +10,57 @@ import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.agent.builder.AgentBuilder.Matchable;
+import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
-public interface Instrumenter {
+/**
+ * Built-in bytebuddy-based instrumentation for the datadog javaagent.
+ *
+ * It is strongly recommended to extend {@link Configurable} rather than implement this interface directly.
+ */
+public interface NewInstrumenter {
- // implemented by final method in Default
+ /**
+ * Add this instrumentation to an AgentBuilder.
+ *
+ * @param agentBuilder AgentBuilder to base instrumentation config off of.
+ * @return the original agentBuilder and this instrumentation
+ */
AgentBuilder instrument(AgentBuilder agentBuilder);
// the following methods would be implemented by the instrumentation author
- ElementMatcher<? super TypeDescriptor> getTypeMatcher();
+ /**
+ * @return A type matcher used to match the class under transform.
+ */
+ ElementMatcher<? super TypeDescription> getTypeMatcher();
+
+ /**
+ * @return A type matcher used to match the classloader under transform
+ */
ElementMatcher<? super ClassLoaderMatcher> getClassLoaderMatcher();
+ /**
+ *
+ * @return
+ */
Set<String> getHelperClassNames();
Map<ElementMatcher, String> getTransformers();
- abstract class Default implements Instrumenter {
+ // TODO: rename Configurable -> Default
+ @Slf4j
+ abstract class Configurable implements NewInstrumenter {
// omitted: config and name logic
@Override
public final AgentBuilder instrument(final AgentBuilder agentBuilder) {
+ if (!enabled) {
+ log.debug("Instrumentation {} is disabled", this);
+ return agentBuilder;
+ }
+
+ /*
Transformer transformer = AgentBuilder.type(createTypeMatcher(), <all-cl>)
.and(safeToInject()) // implementation generated by muzzle
.transform(DDTransformers.defaultTransformers())
@@ -40,17 +70,61 @@ public interface Instrumenter {
transformer = transformer.transform(DDAdvice.create().advice(entry.getKey(), entry.getValue()));
}
return transformer.asDecorator()
+ */
+ // FIXME
+ return null;
}
@Override
public Set<String> getHelperClassNames() {
- return EMPTY_SET;
+ // FIXME
+ return null;
}
- public abstract ElementMatcher<? super TypeDescriptor> getTypeMatcher();
+ public abstract ElementMatcher<? super TypeDescription> getTypeMatcher();
public abstract ElementMatcher<? super ClassLoaderMatcher> getClassLoaderMatcher();
public abstract Map<ElementMatcher, String> getTransformers();
+
+
+ // TODO merge in config logic from previous 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);
+ }
+
+ protected abstract AgentBuilder apply(AgentBuilder agentBuilder);
+
+ protected static String getPropOrEnv(final String name) {
+ return System.getProperty(name, System.getenv(propToEnvName(name)));
+ }
+
+ private static String propToEnvName(final String name) {
+ return name.toUpperCase().replace(".", "_");
+ }
}
}
