7
7
8
8
import static io .opentelemetry .javaagent .instrumentation .graphql .v20_0 .GraphqlSingletons .addInstrumentation ;
9
9
import static net .bytebuddy .matcher .ElementMatchers .named ;
10
- import static net .bytebuddy .matcher .ElementMatchers .namedOneOf ;
11
- import static net .bytebuddy .matcher .ElementMatchers .returns ;
10
+ import static net .bytebuddy .matcher .ElementMatchers .none ;
12
11
12
+ import com .google .errorprone .annotations .CanIgnoreReturnValue ;
13
13
import graphql .execution .instrumentation .Instrumentation ;
14
14
import io .opentelemetry .javaagent .extension .instrumentation .TypeInstrumentation ;
15
15
import io .opentelemetry .javaagent .extension .instrumentation .TypeTransformer ;
16
16
import net .bytebuddy .asm .Advice ;
17
+ import net .bytebuddy .asm .AsmVisitorWrapper ;
18
+ import net .bytebuddy .description .field .FieldDescription ;
19
+ import net .bytebuddy .description .field .FieldList ;
20
+ import net .bytebuddy .description .method .MethodList ;
17
21
import net .bytebuddy .description .type .TypeDescription ;
22
+ import net .bytebuddy .implementation .Implementation ;
18
23
import net .bytebuddy .matcher .ElementMatcher ;
24
+ import net .bytebuddy .pool .TypePool ;
25
+ import org .objectweb .asm .ClassVisitor ;
26
+ import org .objectweb .asm .MethodVisitor ;
27
+ import org .objectweb .asm .Opcodes ;
28
+ import org .objectweb .asm .Type ;
19
29
20
30
class GraphqlInstrumentation implements TypeInstrumentation {
21
31
@@ -27,15 +37,78 @@ public ElementMatcher<TypeDescription> typeMatcher() {
27
37
@ Override
28
38
public void transform (TypeTransformer transformer ) {
29
39
transformer .applyAdviceToMethod (
30
- namedOneOf ("checkInstrumentationDefaultState" , "checkInstrumentation" )
31
- .and (returns (named ("graphql.execution.instrumentation.Instrumentation" ))),
32
- this .getClass ().getName () + "$AddInstrumentationAdvice" );
40
+ none (), this .getClass ().getName () + "$AddInstrumentationAdvice" );
41
+
42
+ transformer .applyTransformer (
43
+ (builder , typeDescription , classLoader , javaModule , protectionDomain ) ->
44
+ builder .visit (
45
+ new AsmVisitorWrapper () {
46
+ @ Override
47
+ public int mergeWriter (int flags ) {
48
+ return flags ;
49
+ }
50
+
51
+ @ Override
52
+ @ CanIgnoreReturnValue
53
+ public int mergeReader (int flags ) {
54
+ return flags ;
55
+ }
56
+
57
+ @ Override
58
+ public ClassVisitor wrap (
59
+ TypeDescription instrumentedType ,
60
+ ClassVisitor classVisitor ,
61
+ Implementation .Context implementationContext ,
62
+ TypePool typePool ,
63
+ FieldList <FieldDescription .InDefinedShape > fields ,
64
+ MethodList <?> methods ,
65
+ int writerFlags ,
66
+ int readerFlags ) {
67
+ return new ClassVisitor (Opcodes .ASM9 , classVisitor ) {
68
+ @ Override
69
+ public MethodVisitor visitMethod (
70
+ int access ,
71
+ String name ,
72
+ String descriptor ,
73
+ String signature ,
74
+ String [] exceptions ) {
75
+ MethodVisitor mv =
76
+ super .visitMethod (access , name , descriptor , signature , exceptions );
77
+ if ("<init>" .equals (name )
78
+ && "(Lgraphql/GraphQL$Builder;)V" .equals (descriptor )) {
79
+ return new MethodVisitor (api , mv ) {
80
+ @ Override
81
+ public void visitFieldInsn (
82
+ int opcode , String owner , String name , String descriptor ) {
83
+ // Call GraphqlSingletons.addInstrumentation on the value before it is
84
+ // written to the instrumentation field
85
+ if (opcode == Opcodes .PUTFIELD
86
+ && "instrumentation" .equals (name )
87
+ && "Lgraphql/execution/instrumentation/Instrumentation;"
88
+ .equals (descriptor )) {
89
+ mv .visitMethodInsn (
90
+ Opcodes .INVOKESTATIC ,
91
+ Type .getInternalName (GraphqlSingletons .class ),
92
+ "addInstrumentation" ,
93
+ "(Lgraphql/execution/instrumentation/Instrumentation;)Lgraphql/execution/instrumentation/Instrumentation;" ,
94
+ false );
95
+ }
96
+ super .visitFieldInsn (opcode , owner , name , descriptor );
97
+ }
98
+ };
99
+ }
100
+ return mv ;
101
+ }
102
+ };
103
+ }
104
+ }));
33
105
}
34
106
35
107
@ SuppressWarnings ("unused" )
36
108
public static class AddInstrumentationAdvice {
37
109
@ Advice .OnMethodExit (suppress = Throwable .class )
38
110
public static void onExit (@ Advice .Return (readOnly = false ) Instrumentation instrumentation ) {
111
+ // this advice is here only to get GraphqlSingletons injected and checked by muzzle
39
112
instrumentation = addInstrumentation (instrumentation );
40
113
}
41
114
}
0 commit comments