-
Notifications
You must be signed in to change notification settings - Fork 333
Expand file tree
/
Copy pathAdviceAppliesOnScanner.java
More file actions
108 lines (99 loc) · 4.26 KB
/
AdviceAppliesOnScanner.java
File metadata and controls
108 lines (99 loc) · 4.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package datadog.trace.agent.tooling;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyMap;
import datadog.trace.util.Strings;
import java.io.IOException;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.bytebuddy.jar.asm.AnnotationVisitor;
import net.bytebuddy.jar.asm.ClassReader;
import net.bytebuddy.jar.asm.ClassVisitor;
import net.bytebuddy.jar.asm.Opcodes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Scans an {@link InstrumenterModule} to extract, custom {@link
* datadog.trace.agent.tooling.annotation.AppliesOn} annotation in any advices that are applied.
*/
public final class AdviceAppliesOnScanner {
private static final Logger log = LoggerFactory.getLogger(AdviceAppliesOnScanner.class);
private static final String APPLIESON_ANNOTATION_DESC =
"Ldatadog/trace/agent/tooling/annotation/AppliesOn;";
public static Map<String, Set<InstrumenterModule.TargetSystem>> extractTargetSystemOverrides(
Instrumenter instrumenter) throws IOException {
if (!(instrumenter instanceof Instrumenter.HasMethodAdvice)) {
return emptyMap();
}
final String instrumenterClassName = instrumenter.getClass().getName();
log.debug("Processing instrumenter class: {}", instrumenterClassName);
final Map<String, Set<InstrumenterModule.TargetSystem>> map = new HashMap<>();
final Set<InstrumenterModule.TargetSystem> overriddenTargetSystems =
EnumSet.noneOf(InstrumenterModule.TargetSystem.class);
// collect the advices
final Set<String> adviceClassNames = new HashSet<>();
((Instrumenter.HasMethodAdvice) instrumenter)
.methodAdvice(
(matcher, adviceClass, additionalClasses) -> {
adviceClassNames.add(adviceClass);
if (additionalClasses != null) {
adviceClassNames.addAll(asList(additionalClasses));
}
});
for (String adviceClassName : adviceClassNames) {
// process each advice
new ClassReader(adviceClassName)
.accept(
new ClassVisitor(Opcodes.ASM8) {
private String className;
@Override
public void visit(
int version,
int access,
String name,
String signature,
String superName,
String[] interfaces) {
className = name.replace('/', '.');
}
@Override
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
if (APPLIESON_ANNOTATION_DESC.equals(descriptor)) {
return new AnnotationVisitor(Opcodes.ASM8) {
@Override
public AnnotationVisitor visitArray(String name) {
if ("value".equals(name)) {
return new AnnotationVisitor(Opcodes.ASM8) {
@Override
public void visitEnum(String name, String descriptor, String value) {
try {
overriddenTargetSystems.add(
InstrumenterModule.TargetSystem.valueOf(value));
} catch (IllegalArgumentException e) {
log.warn("Unknown target system: {}", value);
}
}
};
}
return null;
}
@Override
public void visitEnd() {
if (!overriddenTargetSystems.isEmpty()) {
log.debug(
"Found @AppliesOn on {} → {}", className, overriddenTargetSystems);
map.put(Strings.getSimpleName(adviceClassName), overriddenTargetSystems);
}
}
};
}
return null;
}
},
ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
}
return map;
}
}