Skip to content

Commit c20644b

Browse files
committed
try to support proxy client
1 parent c8cd109 commit c20644b

File tree

5 files changed

+125
-4
lines changed

5 files changed

+125
-4
lines changed

instrumentation/jsonrpc4j-1.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jsonrpc4j/v1_3/JsonRpcClientInstrumentation.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,16 @@ public static void onEnter(
6161
@Advice.Argument(1) Object argument,
6262
@Advice.Argument(3) Map<String, String> extraHeaders,
6363
@Advice.Local("otelContext") Context context,
64-
@Advice.Local("otelScope") Scope scope) {}
64+
@Advice.Local("otelScope") Scope scope) {
65+
Context parentContext = Context.current();
66+
SimpleJsonRpcRequest request = new SimpleJsonRpcRequest(methodName, argument);
67+
if (!CLIENT_INSTRUMENTER.shouldStart(parentContext, request)) {
68+
return;
69+
}
70+
71+
context = CLIENT_INSTRUMENTER.start(parentContext, request);
72+
scope = context.makeCurrent();
73+
}
6574

6675
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
6776
public static void onExit(

instrumentation/jsonrpc4j-1.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jsonrpc4j/v1_3/JsonRpcInstrumentationModule.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ public JsonRpcInstrumentationModule() {
2020

2121
@Override
2222
public List<TypeInstrumentation> typeInstrumentations() {
23-
return asList(new JsonRpcServerInstrumentation(), new JsonRpcClientInstrumentation());
23+
return asList(
24+
new JsonRpcServerInstrumentation(),
25+
new JsonRpcClientInstrumentation(),
26+
new JsonRpcProxyInstrumentation());
2427
}
2528
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.jsonrpc4j.v1_3;
7+
8+
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
9+
import static io.opentelemetry.javaagent.instrumentation.jsonrpc4j.v1_3.JsonRpcSingletons.CLIENT_INSTRUMENTER;
10+
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
11+
import static net.bytebuddy.matcher.ElementMatchers.isPrivate;
12+
import static net.bytebuddy.matcher.ElementMatchers.isStatic;
13+
import static net.bytebuddy.matcher.ElementMatchers.named;
14+
15+
import com.googlecode.jsonrpc4j.IJsonRpcClient;
16+
import com.googlecode.jsonrpc4j.ReflectionUtil;
17+
import io.opentelemetry.context.Context;
18+
import io.opentelemetry.context.Scope;
19+
import io.opentelemetry.instrumentation.jsonrpc4j.v1_3.SimpleJsonRpcRequest;
20+
import io.opentelemetry.instrumentation.jsonrpc4j.v1_3.SimpleJsonRpcResponse;
21+
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
22+
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
23+
import java.lang.reflect.InvocationHandler;
24+
import java.lang.reflect.Method;
25+
import java.lang.reflect.Proxy;
26+
import java.util.Map;
27+
import net.bytebuddy.asm.Advice;
28+
import net.bytebuddy.description.type.TypeDescription;
29+
import net.bytebuddy.matcher.ElementMatcher;
30+
31+
public class JsonRpcProxyInstrumentation implements TypeInstrumentation {
32+
33+
@Override
34+
public ElementMatcher<ClassLoader> classLoaderOptimization() {
35+
return hasClassesNamed("com.googlecode.jsonrpc4j.ProxyUtil");
36+
}
37+
38+
@Override
39+
public ElementMatcher<TypeDescription> typeMatcher() {
40+
return named("com.googlecode.jsonrpc4j.ProxyUtil");
41+
}
42+
43+
@Override
44+
public void transform(TypeTransformer transformer) {
45+
transformer.applyAdviceToMethod(
46+
isMethod().and(isStatic()).and(isPrivate()).and(named("createClientProxy")),
47+
this.getClass().getName() + "$CreateClientProxyAdvice");
48+
}
49+
50+
@SuppressWarnings({"unused", "unchecked"})
51+
public static class CreateClientProxyAdvice {
52+
53+
@Advice.OnMethodExit(suppress = Throwable.class)
54+
public static <T> void onExit(
55+
@Advice.Argument(0) ClassLoader classLoader,
56+
@Advice.Argument(1) Class<T> proxyInterface,
57+
@Advice.Argument(2) IJsonRpcClient client,
58+
@Advice.Argument(3) Map<String, String> extraHeaders,
59+
@Advice.Return(readOnly = false) Object proxy) {
60+
61+
proxy =
62+
(T)
63+
Proxy.newProxyInstance(
64+
classLoader,
65+
new Class<?>[] {proxyInterface},
66+
new InvocationHandler() {
67+
@Override
68+
public Object invoke(Object proxy, Method method, Object[] args)
69+
throws Throwable {
70+
71+
Object arguments = ReflectionUtil.parseArguments(method, args);
72+
String methodName = method.getName(); // todo
73+
74+
// before invoke
75+
Context parentContext = Context.current();
76+
SimpleJsonRpcRequest request = new SimpleJsonRpcRequest(method, args);
77+
if (!CLIENT_INSTRUMENTER.shouldStart(parentContext, request)) {
78+
return client.invoke(
79+
methodName, arguments, method.getGenericReturnType(), extraHeaders);
80+
}
81+
82+
Context context = CLIENT_INSTRUMENTER.start(parentContext, request);
83+
Scope scope = context.makeCurrent();
84+
try {
85+
Object result =
86+
client.invoke(
87+
methodName, arguments, method.getGenericReturnType(), extraHeaders);
88+
scope.close();
89+
CLIENT_INSTRUMENTER.end(
90+
context,
91+
new SimpleJsonRpcRequest(method, args),
92+
new SimpleJsonRpcResponse(result),
93+
null);
94+
return result;
95+
} catch (Throwable t) {
96+
// after invoke
97+
scope.close();
98+
CLIENT_INSTRUMENTER.end(context, request, null, t);
99+
throw t;
100+
}
101+
}
102+
});
103+
}
104+
}
105+
}

instrumentation/jsonrpc4j-1.3/library/src/main/java/io/opentelemetry/instrumentation/jsonrpc4j/v1_3/JsonRpcClientAttributesGetter.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ public String getSystem(SimpleJsonRpcRequest request) {
2020

2121
@Override
2222
public String getService(SimpleJsonRpcRequest request) {
23-
// TODO
2423
if (request.getMethod() != null) {
2524
return request.getMethod().getDeclaringClass().getName();
2625
}

instrumentation/jsonrpc4j-1.3/library/src/main/java/io/opentelemetry/instrumentation/jsonrpc4j/v1_3/JsonRpcClientSpanNameExtractor.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@
66
package io.opentelemetry.instrumentation.jsonrpc4j.v1_3;
77

88
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
9+
import java.lang.reflect.Method;
910

1011
public class JsonRpcClientSpanNameExtractor implements SpanNameExtractor<SimpleJsonRpcRequest> {
1112
@Override
1213
public String extract(SimpleJsonRpcRequest request) {
13-
return request.getMethodName();
14+
if (request.getMethod() == null) {
15+
return request.getMethodName();
16+
}
17+
Method method = request.getMethod();
18+
return String.format("%s/%s", method.getDeclaringClass().getName(), method.getName());
1419
}
1520
}

0 commit comments

Comments
 (0)