27
27
import io .opentelemetry .api .common .AttributeKey ;
28
28
import io .opentelemetry .api .trace .Span ;
29
29
import io .opentelemetry .context .Context ;
30
+ import io .opentelemetry .context .Scope ;
30
31
import io .opentelemetry .javaagent .instrumentation .hypertrace .netty .v4_0 .AttributeKeys ;
31
32
import io .opentelemetry .javaagent .instrumentation .hypertrace .netty .v4_0 .DataCaptureUtils ;
32
33
import java .nio .charset .Charset ;
33
34
import java .util .HashMap ;
34
35
import java .util .Map ;
36
+
37
+ import io .opentelemetry .javaagent .instrumentation .hypertrace .netty .v4_0 .client .OtelHttpClientRequestTracingHandler ;
35
38
import org .hypertrace .agent .core .config .InstrumentationConfig ;
36
39
import org .hypertrace .agent .core .instrumentation .HypertraceSemanticAttributes ;
37
40
import org .hypertrace .agent .core .instrumentation .buffer .BoundedBuffersFactory ;
@@ -57,47 +60,55 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) {
57
60
ctx .fireChannelRead (msg );
58
61
return ;
59
62
}
60
- Span span = Span .fromContext (context );
61
63
62
- if (msg instanceof HttpRequest ) {
63
- HttpRequest httpRequest = (HttpRequest ) msg ;
64
64
65
- Map < String , String > headersMap = headersToMap ( httpRequest );
66
- if ( instrumentationConfig . httpHeaders (). request ()) {
67
- headersMap . forEach ( span :: setAttribute );
68
- }
69
- // used by blocking handler
70
- channel . attr ( AttributeKeys . REQUEST_HEADERS ). set ( headersMap );
65
+ // Store the server context in our ThreadLocal for later use by client handlers
66
+ // This is CRITICAL for proper context propagation to client spans
67
+ OtelHttpClientRequestTracingHandler . storeServerContext ( context );
68
+
69
+ try ( Scope ignored = context . makeCurrent ()) {
70
+ Span span = Span . fromContext ( context );
71
71
72
- CharSequence contentType = DataCaptureUtils .getContentType (httpRequest );
73
- if (instrumentationConfig .httpBody ().request ()
74
- && contentType != null
75
- && ContentTypeUtils .shouldCapture (contentType .toString ())) {
72
+ if (msg instanceof HttpRequest ) {
73
+ HttpRequest httpRequest = (HttpRequest ) msg ;
76
74
77
- CharSequence contentLengthHeader = DataCaptureUtils .getContentLength (httpRequest );
78
- int contentLength = ContentLengthUtils .parseLength (contentLengthHeader );
75
+ Map <String , String > headersMap = headersToMap (httpRequest );
76
+ if (instrumentationConfig .httpHeaders ().request ()) {
77
+ headersMap .forEach (span ::setAttribute );
78
+ }
79
+ // used by blocking handler
80
+ channel .attr (AttributeKeys .REQUEST_HEADERS ).set (headersMap );
79
81
80
- String charsetString = ContentTypeUtils .parseCharset (contentType .toString ());
81
- Charset charset = ContentTypeCharsetUtils .toCharset (charsetString );
82
+ CharSequence contentType = DataCaptureUtils .getContentType (httpRequest );
83
+ if (instrumentationConfig .httpBody ().request ()
84
+ && contentType != null
85
+ && ContentTypeUtils .shouldCapture (contentType .toString ())) {
82
86
83
- // set the buffer to capture response body
84
- // the buffer is used byt captureBody method
85
- Attribute <BoundedByteArrayOutputStream > bufferAttr =
86
- ctx .channel ().attr (AttributeKeys .REQUEST_BODY_BUFFER );
87
- bufferAttr .set (BoundedBuffersFactory .createStream (contentLength , charset ));
87
+ CharSequence contentLengthHeader = DataCaptureUtils .getContentLength (httpRequest );
88
+ int contentLength = ContentLengthUtils .parseLength (contentLengthHeader );
88
89
89
- channel .attr (AttributeKeys .CHARSET ).set (charset );
90
+ String charsetString = ContentTypeUtils .parseCharset (contentType .toString ());
91
+ Charset charset = ContentTypeCharsetUtils .toCharset (charsetString );
92
+
93
+ // set the buffer to capture response body
94
+ // the buffer is used byt captureBody method
95
+ Attribute <BoundedByteArrayOutputStream > bufferAttr =
96
+ ctx .channel ().attr (AttributeKeys .REQUEST_BODY_BUFFER );
97
+ bufferAttr .set (BoundedBuffersFactory .createStream (contentLength , charset ));
98
+
99
+ channel .attr (AttributeKeys .CHARSET ).set (charset );
100
+ }
90
101
}
91
- }
92
102
93
- if ((msg instanceof HttpContent || msg instanceof ByteBuf )
94
- && instrumentationConfig .httpBody ().request ()) {
95
- Charset charset = channel .attr (AttributeKeys .CHARSET ).get ();
96
- if (charset == null ) {
97
- charset = ContentTypeCharsetUtils .getDefaultCharset ();
103
+ if ((msg instanceof HttpContent || msg instanceof ByteBuf )
104
+ && instrumentationConfig .httpBody ().request ()) {
105
+ Charset charset = channel .attr (AttributeKeys .CHARSET ).get ();
106
+ if (charset == null ) {
107
+ charset = ContentTypeCharsetUtils .getDefaultCharset ();
108
+ }
109
+ DataCaptureUtils .captureBody (
110
+ span , channel , AttributeKeys .REQUEST_BODY_BUFFER , msg , null , charset );
98
111
}
99
- DataCaptureUtils .captureBody (
100
- span , channel , AttributeKeys .REQUEST_BODY_BUFFER , msg , null , charset );
101
112
}
102
113
103
114
ctx .fireChannelRead (msg );
0 commit comments