Discover instrumentation helper classes using advice-scanning (#12549) · DataDog/dd-trace-java@02d50d2 · GitHub
Skip to content

Commit 02d50d2

Browse files
authored
Discover instrumentation helper classes using advice-scanning (#12549)
Reconfigure Muzzle to use advice scanner Preserve transitive requirements reached through array owners Discover instrumentation helper classes using advice-scanning Address review comments and add documentation Preserve Muzzle hierarchy traversal during helper discovery Address review comments Merge branch 'master' into sarahchen6/add-helper-discovery Co-authored-by: sarah.chen <sarah.chen@datadoghq.com>
1 parent d90f470 commit 02d50d2

23 files changed

Lines changed: 798 additions & 129 deletions

File tree

Lines changed: 108 additions & 0 deletions

‎dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/HelperScanner.java‎

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@
2424
public final class HelperScanner extends ClassVisitor {
2525
static final int READER_OPTIONS = ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES;
2626

27+
private static final String[] SHARED_HELPER_PREFIXES = {
28+
"datadog.opentelemetry.shim.",
29+
"datadog.trace.agent.tooling.iast.",
30+
"datadog.trace.agent.tooling.nativeimage."
31+
};
32+
2733
static final ClassFileLocator locator =
2834
ClassFileLocator.ForClassLoader.of(Utils.getAgentClassLoader());
2935

@@ -49,6 +55,22 @@ public static String[] withClassDependencies(String... helperClassNames) {
4955
return new HelperScanner().simulateClassLoading(helperClassNames);
5056
}
5157

58+
/** Whether a class can be injected as an instrumentation helper. */
59+
public static boolean isHelperClass(String className, boolean fromModuleOutput) {
60+
if (isBootstrapClass(className)) {
61+
return false;
62+
}
63+
if (fromModuleOutput) {
64+
return true;
65+
}
66+
for (String prefix : SHARED_HELPER_PREFIXES) {
67+
if (className.startsWith(prefix)) {
68+
return true;
69+
}
70+
}
71+
return false;
72+
}
73+
5274
/**
5375
* Simulates class-loading by finding all classes required to load the helper classes as well as
5476
* optional classes used in method instructions that may be needed later when invoking the method.
@@ -256,26 +278,32 @@ void record(Type type, Consumer<String> action) {
256278
} else if (type.getSort() == Type.OBJECT) {
257279
String className = type.getClassName();
258280
// ignore types that we expect to be on the boot-class-path
259-
if (this.className.equals(className)
260-
|| className.startsWith("java.")
261-
|| className.startsWith("javax.")
262-
|| className.startsWith("jdk.")
263-
|| className.startsWith("com.sun.")
264-
|| className.startsWith("sun.")
265-
|| className.startsWith("org.slf4j.")
266-
|| className.startsWith("datadog.slf4j.")) {
281+
if (this.className.equals(className) || isBootstrapClass(className)) {
267282
return;
268283
}
269-
for (String prefix : Constants.BOOTSTRAP_PACKAGE_PREFIXES) {
270-
if (className.startsWith(prefix)) {
271-
return;
272-
}
273-
}
274284
action.accept(className);
275285
}
276286
}
277287
}
278288

289+
private static boolean isBootstrapClass(String className) {
290+
if (className.startsWith("java.")
291+
|| className.startsWith("javax.")
292+
|| className.startsWith("jdk.")
293+
|| className.startsWith("com.sun.")
294+
|| className.startsWith("sun.")
295+
|| className.startsWith("org.slf4j.")
296+
|| className.startsWith("datadog.slf4j.")) {
297+
return true;
298+
}
299+
for (String prefix : Constants.BOOTSTRAP_PACKAGE_PREFIXES) {
300+
if (className.startsWith(prefix)) {
301+
return true;
302+
}
303+
}
304+
return false;
305+
}
306+
279307
void record(Type[] types, Consumer<String> action) {
280308
if (null != types) {
281309
for (Type t : types) {

‎dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/InstrumenterModule.java‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,11 @@ public static ReferenceMatcher loadStaticMuzzleReferences(
113113
}
114114

115115
/**
116-
* @return Class names of helpers to inject into the user's classloader.
116+
* @return Class names of helpers to inject into the user's classloader. A non-empty list is used
117+
* exactly as declared; an empty list means helpers will be inferred from method advice at
118+
* build-time by following bytecode references. Helpers loaded only through reflection or
119+
* class name strings may not be discovered. Modules needing these undiscoverable helpers must
120+
* declare the complete helper list - declared and inferred helpers are not merged.
117121
* <p><b>NOTE:</b> The order of the returned helper classes matters. If a muzzle check fails
118122
* with a NoClassDefFoundError, as logged in build/reports/muzzle-*.txt, it is likely that one
119123
* helper class depends on another that appears later in the list. In this case, the returned

‎dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/advice/AdviceProcessorContext.java‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@
33
import datadog.trace.agent.tooling.InstrumenterModule;
44
import java.io.File;
55

6-
/** Module and output directory shared by advice processors. */
6+
/** Module, output directory, and resolved helpers shared by advice processors. */
77
public final class AdviceProcessorContext {
88
private final InstrumenterModule module;
99
private final File targetDirectory;
10+
private final String[] helperClassNames;
1011

11-
AdviceProcessorContext(InstrumenterModule module, File targetDirectory) {
12+
AdviceProcessorContext(
13+
InstrumenterModule module, File targetDirectory, String[] helperClassNames) {
1214
this.module = module;
1315
this.targetDirectory = targetDirectory;
16+
this.helperClassNames = helperClassNames;
1417
}
1518

1619
public InstrumenterModule getModule() {
@@ -20,4 +23,8 @@ public InstrumenterModule getModule() {
2023
public File getTargetDirectory() {
2124
return targetDirectory;
2225
}
26+
27+
public String[] getHelperClassNames() {
28+
return helperClassNames;
29+
}
2330
}

‎dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/advice/AdviceScanResult.java‎

Lines changed: 28 additions & 1 deletion

0 commit comments

Comments
 (0)