Add post-match hook to default instrumenter api
MODIFY
dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/Instrumenter.java
dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/Instrumenter.java
@@ -86,6 +86,7 @@ public interface Instrumenter {
"Instrumentation class loader matcher unexpected exception: "
+ getClass().getName()))
.and(new MuzzleMatcher())
+ .and(new PostMatchHook())
.transform(DDTransformers.defaultTransformers());
agentBuilder = injectHelperClasses(agentBuilder);
agentBuilder = contextProvider.instrumentationTransformer(agentBuilder);
@@ -157,6 +158,19 @@ public interface Instrumenter {
}
}
+ private class PostMatchHook implements AgentBuilder.RawMatcher {
+ @Override
+ public boolean matches(
+ TypeDescription typeDescription,
+ ClassLoader classLoader,
+ JavaModule module,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain) {
+ postMatch(typeDescription, classLoader, module, classBeingRedefined, protectionDomain);
+ return true;
+ }
+ }
+
/**
* This method is implemented dynamically by compile-time bytecode transformations.
*
@@ -179,6 +193,25 @@ public interface Instrumenter {
/** @return A type matcher used to match the class under transform. */
public abstract ElementMatcher<? super TypeDescription> typeMatcher();
+ /**
+ * A hook invoked after matching has succeeded and before transformers have run.
+ *
+ * <p>Implementation note: This hook runs inside of the bytebuddy matching phase.
+ *
+ * @param typeDescription type description of the matched type
+ * @param classLoader classloader loading the class under transform
+ * @param module java module
+ * @param classBeingRedefined null when the matched class is being loaded for the first time.
+ * The instance of the active class during retransforms.
+ * @param protectionDomain protection domain of the class under load.
+ */
+ public void postMatch(
+ TypeDescription typeDescription,
+ ClassLoader classLoader,
+ JavaModule module,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain) {}
+
/** @return A map of matcher->advice */
public abstract Map<? extends ElementMatcher, String> transformers();

MODIFY
dd-java-agent/instrumentation/jboss-classloading/src/main/java/datadog/trace/instrumentation/jboss/JBossClassloadingInstrumentation.java
dd-java-agent/instrumentation/jboss-classloading/src/main/java/datadog/trace/instrumentation/jboss/JBossClassloadingInstrumentation.java
package datadog.trace.instrumentation.jboss;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.agent.tooling.Utils;
+import java.security.ProtectionDomain;
import java.util.Collections;
import java.util.Map;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
-import net.bytebuddy.matcher.NameMatcher;
-import net.bytebuddy.matcher.StringMatcher;
+import net.bytebuddy.utility.JavaModule;
@AutoService(Instrumenter.class)
public final class JBossClassloadingInstrumentation extends Instrumenter.Default {
@@ -18,14 +20,17 @@ public final class JBossClassloadingInstrumentation extends Instrumenter.Default
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
- return new NameMatcher<>(
- new StringMatcher("org.jboss.modules.Module", StringMatcher.Mode.EQUALS_FULLY) {
+ return named("org.jboss.modules.Module");
+ }
+
@Override
- public boolean matches(final String target) {
- if (super.matches(target)) {
- // This instrumentation modifies no bytes.
- // Instead it sets a system prop to tell jboss to delegate
- // classloads for datadog bootstrap classes
+ public void postMatch(
+ TypeDescription typeDescription,
+ ClassLoader classLoader,
+ JavaModule module,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain) {
+ // Set the system prop to tell jboss to delegate classloads for datadog bootstrap classes
final StringBuilder ddPrefixes = new StringBuilder("");
for (int i = 0; i < Utils.BOOTSTRAP_PACKAGE_PREFIXES.length; ++i) {
if (i > 0) {
@@ -37,13 +42,8 @@ public final class JBossClassloadingInstrumentation extends Instrumenter.Default
if (null == existing) {
System.setProperty("jboss.modules.system.pkgs", ddPrefixes.toString());
} else if (!existing.contains(ddPrefixes)) {
- System.setProperty(
- "jboss.modules.system.pkgs", existing + "," + ddPrefixes.toString());
- }
- }
- return false;
+ System.setProperty("jboss.modules.system.pkgs", existing + "," + ddPrefixes.toString());
}
- });
}
@Override

MODIFY
dd-java-agent/instrumentation/osgi-classloading/src/main/java/datadog/trace/instrumentation/osgi/OSGIClassloadingInstrumentation.java
dd-java-agent/instrumentation/osgi-classloading/src/main/java/datadog/trace/instrumentation/osgi/OSGIClassloadingInstrumentation.java
package datadog.trace.instrumentation.osgi;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.agent.tooling.Utils;
+import java.security.ProtectionDomain;
import java.util.Collections;
import java.util.Map;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
-import net.bytebuddy.matcher.NameMatcher;
-import net.bytebuddy.matcher.StringMatcher;
+import net.bytebuddy.utility.JavaModule;
@AutoService(Instrumenter.class)
public final class OSGIClassloadingInstrumentation extends Instrumenter.Default {
@@ -19,14 +21,17 @@ public final class OSGIClassloadingInstrumentation extends Instrumenter.Default
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
// OSGI Bundle class loads the sys prop which defines bootstrap classes
- return new NameMatcher<>(
- new StringMatcher("org.osgi.framework.Bundle", StringMatcher.Mode.EQUALS_FULLY) {
+ return named("org.osgi.framework.Bundle");
+ }
+
@Override
- public boolean matches(final String target) {
- if (super.matches(target)) {
- // This instrumentation modifies no bytes.
- // Instead it sets a system prop to tell osgi to delegate
- // classloads for datadog bootstrap classes
+ public void postMatch(
+ TypeDescription typeDescription,
+ ClassLoader classLoader,
+ JavaModule module,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain) {
+ // Set the system prop to tell osgi to delegate classloads for datadog bootstrap classes
final StringBuilder ddPrefixes = new StringBuilder("");
for (int i = 0; i < Utils.BOOTSTRAP_PACKAGE_PREFIXES.length; ++i) {
if (i > 0) {
@@ -44,10 +49,6 @@ public final class OSGIClassloadingInstrumentation extends Instrumenter.Default
"org.osgi.framework.bootdelegation", existing + "," + ddPrefixes.toString());
}
}
- return false;
- }
- });
- }
@Override
public Map<ElementMatcher, String> transformers() {

Add post-match hook to default instrumenter api