Skip to content

Commit 541a699

Browse files
author
Andrew Kent
committed
Hook up muzzle to Instrumenter.Default's matcher
1 parent d61f65f commit 541a699

9 files changed

Lines changed: 124 additions & 198 deletions

File tree

dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/muzzle/MuzzleBytecodeTransformTest.groovy

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@ import spock.lang.Specification
88

99
class MuzzleBytecodeTransformTest extends Specification {
1010

11-
/*
1211
def "muzzle fields added to all instrumentation"() {
1312
setup:
1413
List<Class> unMuzzledClasses = []
1514
List<Class> nonLazyFields = []
1615
List<Class> unInitFields = []
17-
for (final Object instrumenter : ServiceLoader.load(IntegrationTestUtils.getAgentClassLoader().loadClass("datadog.trace.agent.tooling.Instrumenter"), IntegrationTestUtils.getAgentClassLoader())) {
16+
for (Object instrumenter : ServiceLoader.load(IntegrationTestUtils.getAgentClassLoader().loadClass("datadog.trace.agent.tooling.Instrumenter"), IntegrationTestUtils.getAgentClassLoader())) {
17+
if (instrumenter.getClass().getName().endsWith("TraceConfigInstrumentation")) {
18+
// TraceConfigInstrumentation doesn't do muzzle checks
19+
// check on TracerClassInstrumentation instead
20+
instrumenter = IntegrationTestUtils.getAgentClassLoader().loadClass(instrumenter.getClass().getName() + '$TracerClassInstrumentation').newInstance()
21+
}
1822
Field f
1923
Method m
2024
try {
@@ -45,6 +49,5 @@ class MuzzleBytecodeTransformTest extends Specification {
4549
nonLazyFields == []
4650
unInitFields == []
4751
}
48-
*/
4952

5053
}

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AgentInstaller.java

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
import static net.bytebuddy.matcher.ElementMatchers.named;
99
import static net.bytebuddy.matcher.ElementMatchers.not;
1010

11-
import datadog.trace.agent.tooling.muzzle.Reference.Mismatch;
12-
import datadog.trace.agent.tooling.muzzle.ReferenceMatcher.MismatchException;
1311
import java.lang.instrument.Instrumentation;
1412
import java.util.ServiceLoader;
1513
import lombok.extern.slf4j.Slf4j;
@@ -91,19 +89,11 @@ public void onError(
9189
final JavaModule module,
9290
final boolean loaded,
9391
final Throwable throwable) {
94-
if (throwable instanceof MismatchException) {
95-
final MismatchException mismatchException = (MismatchException) throwable;
96-
log.debug("{}", mismatchException.getMessage());
97-
for (final Mismatch mismatch : mismatchException.getMismatches()) {
98-
log.debug("--{}", mismatch);
99-
}
100-
} else {
101-
log.debug(
102-
"Failed to handle {} for transformation on classloader {}: {}",
103-
typeName,
104-
classLoader,
105-
throwable.getMessage());
106-
}
92+
log.debug(
93+
"Failed to handle {} for transformation on classloader {}: {}",
94+
typeName,
95+
classLoader,
96+
throwable.getMessage());
10797
}
10898

10999
@Override

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/Instrumenter.java

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
import static datadog.trace.agent.tooling.Utils.getConfigEnabled;
44
import static net.bytebuddy.matcher.ElementMatchers.any;
55

6+
import datadog.trace.agent.tooling.muzzle.Reference;
7+
import datadog.trace.agent.tooling.muzzle.ReferenceMatcher;
68
import java.security.ProtectionDomain;
79
import java.util.Arrays;
810
import java.util.HashSet;
11+
import java.util.List;
912
import java.util.Map;
1013
import java.util.Set;
11-
12-
import datadog.trace.agent.tooling.muzzle.ReferenceMatcher;
1314
import lombok.extern.slf4j.Slf4j;
1415
import net.bytebuddy.agent.builder.AgentBuilder;
1516
import net.bytebuddy.description.type.TypeDescription;
@@ -46,11 +47,13 @@ public interface Instrumenter {
4647
@Slf4j
4748
abstract class Default implements Instrumenter {
4849
private final Set<String> instrumentationNames;
50+
private final String instrumentationPrimaryName;
4951
protected final boolean enabled;
5052

5153
public Default(final String instrumentationName, final String... additionalNames) {
5254
this.instrumentationNames = new HashSet<>(Arrays.asList(additionalNames));
5355
instrumentationNames.add(instrumentationName);
56+
instrumentationPrimaryName = instrumentationName;
5457

5558
// If default is enabled, we want to enable individually,
5659
// if default is disabled, we want to disable individually.
@@ -78,13 +81,30 @@ public AgentBuilder instrument(final AgentBuilder agentBuilder) {
7881
AgentBuilder.Identified.Extendable advice =
7982
agentBuilder
8083
.type(typeMatcher(), classLoaderMatcher())
81-
.and(new AgentBuilder.RawMatcher() {
82-
@Override
83-
public boolean matches(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, Class<?> classBeingRedefined, ProtectionDomain protectionDomain) {
84-
// Optimization: calling getMuzzleReferenceMatcher() inside this method prevents unnecessary loading of muzzle references during agentBuilder setup.
85-
return getInstrumentationMuzzle().matches(classLoader);
86-
}
87-
})
84+
.and(
85+
new AgentBuilder.RawMatcher() {
86+
@Override
87+
public boolean matches(
88+
TypeDescription typeDescription,
89+
ClassLoader classLoader,
90+
JavaModule module,
91+
Class<?> classBeingRedefined,
92+
ProtectionDomain protectionDomain) {
93+
// Optimization: calling getMuzzleReferenceMatcher() inside this method prevents unnecessary loading of muzzle references during agentBuilder setup.
94+
final ReferenceMatcher muzzle = getInstrumentationMuzzle();
95+
if (null != muzzle) {
96+
List<Reference.Mismatch> mismatches = muzzle.getMismatchedReferenceSources(classLoader);
97+
if (mismatches.size() > 0) {
98+
log.debug("Instrumentation muzzled: {} on {}", instrumentationPrimaryName, classLoader);
99+
}
100+
for (Reference.Mismatch mismatch : mismatches) {
101+
log.debug("-- {}", mismatch);
102+
}
103+
return mismatches.size() == 0;
104+
}
105+
return true;
106+
}
107+
})
88108
.transform(DDTransformers.defaultTransformers());
89109
final String[] helperClassNames = helperClassNames();
90110
if (helperClassNames.length > 0) {
@@ -99,7 +119,7 @@ public boolean matches(TypeDescription typeDescription, ClassLoader classLoader,
99119
/**
100120
* This method is implemented dynamically by compile-time bytecode transformations.
101121
*
102-
* TODO bytecode magic and documentation
122+
* <p>TODO bytecode magic and documentation
103123
*/
104124
// TODO: Make final
105125
protected ReferenceMatcher getInstrumentationMuzzle() {

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

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88

99
public class MuzzleGradlePlugin implements Plugin {
1010
// TODO:
11-
// - Optimizations
12-
// - Cache safe and unsafe classloaders
13-
// - Do reference generation at compile time
14-
// - lazy-load reference muzzle field
1511
// - Additional references to check
1612
// - Fields
1713
// - methods
@@ -26,29 +22,38 @@ public class MuzzleGradlePlugin implements Plugin {
2622
// - Expose config instead of hardcoding datadog namespace (or reconfigure classpath)
2723
// - Run muzzle in matching phase (may require a rewrite of the instrumentation api)
2824
// - Documentation
25+
// - Fix TraceConfigInstrumentation
26+
// - assert no muzzle field defined in instrumentation
27+
// - make getMuzzle final in default and remove in gradle plugin
28+
// - pull muzzle field + method names into static constants
2929

30-
private static final TypeDescription InstrumenterTypeDesc =
31-
new TypeDescription.ForLoadedType(Instrumenter.class);
30+
private static final TypeDescription DefaultInstrumenterTypeDesc =
31+
new TypeDescription.ForLoadedType(Instrumenter.Default.class);
3232

3333
@Override
3434
public boolean matches(final TypeDescription target) {
35-
// AutoService annotation is not retained at runtime. Check for instrumenter supertype
35+
// AutoService annotation is not retained at runtime. Check for Instrumenter.Default supertype
3636
boolean isInstrumenter = false;
3737
TypeDefinition instrumenter = target;
3838
while (instrumenter != null) {
39-
if (instrumenter.getInterfaces().contains(InstrumenterTypeDesc)) {
39+
if (instrumenter.equals(DefaultInstrumenterTypeDesc)) {
4040
isInstrumenter = true;
4141
break;
4242
}
4343
instrumenter = instrumenter.getSuperClass();
4444
}
45-
// return isInstrumenter;
46-
return false;
45+
return isInstrumenter;
4746
}
4847

4948
@Override
5049
public Builder<?> apply(Builder<?> builder, TypeDescription typeDescription) {
51-
return builder.visit(new MuzzleVisitor());
50+
if (typeDescription.equals(DefaultInstrumenterTypeDesc)) {
51+
// FIXME
52+
System.out.println("~~~~FIXME: remove final modifier on Default: " + typeDescription);
53+
return builder;
54+
} else {
55+
return builder.visit(new MuzzleVisitor());
56+
}
5257
}
5358

5459
public static class NoOp implements Plugin {

0 commit comments

Comments
 (0)