Skip to content

Commit b3f3860

Browse files
Fix Bolt server span: store protocol in SofaRequest props instead of ThreadLocal
1 parent 1f553d7 commit b3f3860

3 files changed

Lines changed: 30 additions & 7 deletions

File tree

dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/BoltServerProcessorInstrumentation.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
66
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
77

8+
import com.alipay.sofa.rpc.core.request.SofaRequest;
89
import datadog.trace.agent.tooling.Instrumenter;
910
import net.bytebuddy.asm.Advice;
1011

@@ -28,13 +29,16 @@ public void methodAdvice(MethodTransformer transformer) {
2829

2930
public static class HandleRequestAdvice {
3031
@Advice.OnMethodEnter(suppress = Throwable.class)
31-
public static void enter() {
32-
SofaRpcProtocolContext.set("bolt");
32+
public static void enter(@Advice.Argument(2) SofaRequest request) {
33+
// Bolt dispatches business logic to a thread pool, so a ThreadLocal would not survive the
34+
// handoff. Store the protocol on the SofaRequest itself — the same object is passed to
35+
// ProviderProxyInvoker.invoke() on the worker thread.
36+
if (request != null) {
37+
request.addRequestProp(SofaRpcProtocolContext.REQUEST_PROP_PROTOCOL, "bolt");
38+
}
3339
}
3440

3541
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
36-
public static void exit() {
37-
SofaRpcProtocolContext.clear();
38-
}
42+
public static void exit() {}
3943
}
4044
}

dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/ProviderProxyInvokerInstrumentation.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
1818
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
1919
import datadog.trace.bootstrap.instrumentation.api.AgentSpanContext;
20+
import java.util.Map;
2021
import net.bytebuddy.asm.Advice;
2122

2223
public class ProviderProxyInvokerInstrumentation
@@ -40,9 +41,20 @@ public void methodAdvice(MethodTransformer transformer) {
4041
public static class InvokeAdvice {
4142
@Advice.OnMethodEnter(suppress = Throwable.class)
4243
public static AgentScope enter(@Advice.Argument(0) SofaRequest request) {
43-
// Protocol is set in thread-local by transport-specific instrumentation before this call.
44-
// If null, the transport is not instrumented — skip.
44+
// For H2C / REST / Triple the protocol is set in a thread-local by transport-specific
45+
// instrumentation that runs on the same thread as this method.
46+
// For Bolt the business logic is dispatched to a thread pool, so the protocol is stored
47+
// directly on the SofaRequest instead (see BoltServerProcessorInstrumentation).
4548
String protocol = SofaRpcProtocolContext.get();
49+
if (protocol == null && request != null) {
50+
Map<String, Object> props = request.getRequestProps();
51+
if (props != null) {
52+
Object p = props.get(SofaRpcProtocolContext.REQUEST_PROP_PROTOCOL);
53+
if (p instanceof String) {
54+
protocol = (String) p;
55+
}
56+
}
57+
}
4658
if (protocol == null) {
4759
return null;
4860
}

dd-java-agent/instrumentation/sofarpc/sofarpc-5.0/src/main/java/datadog/trace/instrumentation/sofarpc/SofaRpcProtocolContext.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
/** Thread-local carrier for the SOFA RPC transport protocol name. */
44
public final class SofaRpcProtocolContext {
55

6+
/**
7+
* Key used to store the transport protocol in {@code SofaRequest.requestProps} for transports
8+
* that dispatch business logic to a thread pool (e.g. Bolt). Using a request prop instead of a
9+
* ThreadLocal ensures the value survives the handoff to the worker thread.
10+
*/
11+
public static final String REQUEST_PROP_PROTOCOL = "_dd.sofarpc.protocol";
12+
613
private static final ThreadLocal<String> PROTOCOL = new ThreadLocal<>();
714

815
private SofaRpcProtocolContext() {}

0 commit comments

Comments
 (0)