Skip to content

Commit a09ff60

Browse files
committed
Use source file to determine helpers
1 parent 250236b commit a09ff60

6 files changed

Lines changed: 42 additions & 16 deletions

File tree

buildSrc/src/main/kotlin/datadog/gradle/plugin/instrument/BuildTimeInstrumentationPlugin.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ import org.gradle.kotlin.dsl.withType
4141
*
4242
* Requirements for ByteBuddy plugins:
4343
* 1. Must implement [net.bytebuddy.build.Plugin]
44-
* 2. Must have a constructor accepting a [java.io.File] parameter (target directory)
44+
* 2. Must have a constructor accepting a [java.io.File] (target directory), or a two-`File`
45+
* `(sourceDirectory, targetDirectory)` constructor when the plugin also needs the source folder
4546
* 3. Plugin classes must be available on `buildTimeInstrumentationPlugin` configuration
4647
*
4748
* @see BuildTimeInstrumentationExtension

buildSrc/src/main/kotlin/datadog/gradle/plugin/instrument/ByteBuddyInstrumenter.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,13 @@ object ByteBuddyInstrumenter {
3333
val factories = plugins.map {
3434
try {
3535
val pluginClass = instrumentingLoader.loadClass(it).asSubclass(Plugin::class.java)
36-
val loadedPlugin = pluginClass.getConstructor(File::class.java).newInstance(targetDirectory)
36+
// Prefer a (source, target) constructor; fall back to the single target-directory one.
37+
val loadedPlugin = try {
38+
pluginClass.getConstructor(File::class.java, File::class.java)
39+
.newInstance(sourceDirectory, targetDirectory)
40+
} catch (_: NoSuchMethodException) {
41+
pluginClass.getConstructor(File::class.java).newInstance(targetDirectory)
42+
}
3743
Plugin.Factory.Simple(loadedPlugin)
3844
} catch (throwable: Throwable) {
3945
throw IllegalStateException("Cannot resolve plugin: $it", throwable)

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/HelperClassPredicate.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@
55

66
/**
77
* Classifies a referenced class as an injectable tracer helper, a bootstrap class, or a library
8-
* class — similar to OpenTelemetry's {@code HelperClassPredicate#isHelperClass}; however, the main
9-
* signal here is whether the class was compiled from the instrumentation subproject's own output
10-
* ({@code ownOutput}). {@link #HELPER_PREFIXES} additionally covers helpers that live in other
11-
* tracer subprojects.
8+
* class — similar to OpenTelemetry's {@code HelperClassPredicate#isHelperClass}. The primary signal
9+
* is {@code ownOutput}: a class the instrumentation subproject compiled itself.
10+
*
11+
* <p>A subproject only injects helpers it owns; a helper owned by another subproject must be
12+
* declared explicitly via {@code helperClassNames()}. {@link #HELPER_PREFIXES} lists the shared
13+
* infrastructure subprojects that are not owned by a specific subproject and so are always treated
14+
* as helpers.
1215
*/
1316
public final class HelperClassPredicate {
1417

1518
static final String[] HELPER_PREFIXES = {
16-
"datadog.trace.instrumentation.",
1719
"datadog.opentelemetry.shim.",
1820
"datadog.trace.agent.tooling.iast.",
1921
"datadog.trace.agent.tooling.nativeimage.",

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/MuzzleGenerator.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,16 @@
3434

3535
/** Generates a 'Muzzle' side-class for each {@link InstrumenterModule}. */
3636
public class MuzzleGenerator implements AsmVisitorWrapper {
37+
/**
38+
* The engine's source folder, fully populated before processing. OwnOutput is decided against it
39+
* rather than the target folder, which is written incrementally as classes are processed.
40+
*/
41+
private final File sourceDir;
42+
3743
private final File targetDir;
3844

39-
public MuzzleGenerator(File targetDir) {
45+
public MuzzleGenerator(File sourceDir, File targetDir) {
46+
this.sourceDir = sourceDir;
4047
this.targetDir = targetDir;
4148
}
4249

@@ -246,12 +253,12 @@ private byte[] generateMuzzleClass(InstrumenterModule module) {
246253

247254
/** {@code true} if the class was compiled from this instrumentation subproject's own output. */
248255
private boolean isOwnOutput(String className) {
249-
return new File(targetDir, className.replace('.', '/') + ".class").isFile();
256+
return new File(sourceDir, className.replace('.', '/') + ".class").isFile();
250257
}
251258

252259
/** Adds the nested classes ({@code Foo$Bar}, {@code Foo$1}, ...) of an own-output helper. */
253260
private void addNestedClasses(String className, Set<String> helperClasses) {
254-
File classFile = new File(targetDir, className.replace('.', '/') + ".class");
261+
File classFile = new File(sourceDir, className.replace('.', '/') + ".class");
255262
File dir = classFile.getParentFile();
256263
if (dir == null || !dir.isDirectory()) {
257264
return;

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/MuzzleGradlePlugin.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,16 @@ public class MuzzleGradlePlugin extends Plugin.ForElementMatcher {
2525
HierarchyMatchers.registerIfAbsent(HierarchyMatchers.simpleChecks());
2626
}
2727

28+
private final File sourceDir;
2829
private final File targetDir;
2930

30-
public MuzzleGradlePlugin(File targetDir) {
31+
/**
32+
* @param sourceDir the engine's source folder, used to decide which helpers this subproject owns
33+
* @param targetDir the engine's target folder, where {@code $Muzzle} classes are written
34+
*/
35+
public MuzzleGradlePlugin(File sourceDir, File targetDir) {
3136
super(concreteClass().and(extendsClass(named(InstrumenterModule.class.getName()))));
37+
this.sourceDir = sourceDir;
3238
this.targetDir = targetDir;
3339
}
3440

@@ -37,7 +43,7 @@ public DynamicType.Builder<?> apply(
3743
final DynamicType.Builder<?> builder,
3844
final TypeDescription typeDescription,
3945
final ClassFileLocator classFileLocator) {
40-
return builder.visit(new MuzzleGenerator(targetDir));
46+
return builder.visit(new MuzzleGenerator(sourceDir, targetDir));
4147
}
4248

4349
@Override

dd-java-agent/agent-tooling/src/test/java/datadog/trace/agent/tooling/muzzle/HelperClassPredicateTest.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@ private static HelperClassPredicate predicateWithOwnOutput(String... ownOutput)
1818
}
1919

2020
@Test
21-
void instrumentationPackageIsHelperEvenWithoutOwnOutput() {
22-
// classes under the instrumentation package are ours regardless of where they were compiled
23-
HelperClassPredicate predicate = predicateWithOwnOutput();
24-
assertTrue(predicate.isHelperClass("datadog.trace.instrumentation.foo.FooDecorator"));
21+
void instrumentationPackageIsHelperOnlyWhenOwnOutput() {
22+
// a module's own instrumentation-package class is a helper via ownOutput
23+
HelperClassPredicate own =
24+
predicateWithOwnOutput("datadog.trace.instrumentation.foo.FooDecorator");
25+
assertTrue(own.isHelperClass("datadog.trace.instrumentation.foo.FooDecorator"));
26+
// a helper compiled by a different instrumentation subproject is not adopted just by reference
27+
HelperClassPredicate other = predicateWithOwnOutput();
28+
assertFalse(other.isHelperClass("datadog.trace.instrumentation.servlet.ServletBlockingHelper"));
2529
}
2630

2731
@Test

0 commit comments

Comments
 (0)