Skip to content

Commit 1da8f5e

Browse files
authoredApr 18, 2024··
Fix instrumentation for graphql-java-22.0 (#11142)
1 parent 4325eb2 commit 1da8f5e

File tree

3 files changed

+90
-5
lines changed

3 files changed

+90
-5
lines changed
 

‎instrumentation/graphql-java/graphql-java-20.0/javaagent/build.gradle.kts

+6
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,9 @@ dependencies {
2222

2323
testImplementation(project(":instrumentation:graphql-java:graphql-java-common:testing"))
2424
}
25+
26+
if (findProperty("testLatestDeps") as Boolean) {
27+
otelJava {
28+
minJavaVersionSupported.set(JavaVersion.VERSION_11)
29+
}
30+
}

‎instrumentation/graphql-java/graphql-java-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v20_0/GraphqlInstrumentation.java

+78-5
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,25 @@
77

88
import static io.opentelemetry.javaagent.instrumentation.graphql.v20_0.GraphqlSingletons.addInstrumentation;
99
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;
1211

12+
import com.google.errorprone.annotations.CanIgnoreReturnValue;
1313
import graphql.execution.instrumentation.Instrumentation;
1414
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1515
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
1616
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;
1721
import net.bytebuddy.description.type.TypeDescription;
22+
import net.bytebuddy.implementation.Implementation;
1823
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;
1929

2030
class GraphqlInstrumentation implements TypeInstrumentation {
2131

@@ -27,15 +37,78 @@ public ElementMatcher<TypeDescription> typeMatcher() {
2737
@Override
2838
public void transform(TypeTransformer transformer) {
2939
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+
}));
33105
}
34106

35107
@SuppressWarnings("unused")
36108
public static class AddInstrumentationAdvice {
37109
@Advice.OnMethodExit(suppress = Throwable.class)
38110
public static void onExit(@Advice.Return(readOnly = false) Instrumentation instrumentation) {
111+
// this advice is here only to get GraphqlSingletons injected and checked by muzzle
39112
instrumentation = addInstrumentation(instrumentation);
40113
}
41114
}

‎instrumentation/graphql-java/graphql-java-20.0/library/build.gradle.kts

+6
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,9 @@ dependencies {
88

99
testImplementation(project(":instrumentation:graphql-java:graphql-java-common:testing"))
1010
}
11+
12+
if (findProperty("testLatestDeps") as Boolean) {
13+
otelJava {
14+
minJavaVersionSupported.set(JavaVersion.VERSION_11)
15+
}
16+
}

0 commit comments

Comments
 (0)
Please sign in to comment.