1
+ /*
2
+ *
3
+ * * Copyright 2024 New Relic Corporation. All rights reserved.
4
+ * * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ */
7
+
8
+ package io .netty .handler .codec .http2 ;
9
+
10
+ import com .agent .instrumentation .netty4116 .NettyUtil ;
11
+ import com .newrelic .api .agent .weaver .MatchType ;
12
+ import com .newrelic .api .agent .weaver .Weave ;
13
+ import com .newrelic .api .agent .weaver .Weaver ;
14
+ import io .netty .bootstrap .NettyDispatcher ;
15
+ import io .netty .channel .ChannelHandlerContext_Instrumentation ;
16
+ import io .netty .channel .ChannelPromise ;
17
+
18
+ @ Weave (type = MatchType .BaseClass , originalName = "io.netty.handler.codec.http2.Http2FrameCodec" )
19
+ public class Http2FrameCodec_Instrumentation {
20
+
21
+ // Handle the incoming request. For HTTP/2 there is no HttpRequest object
22
+ // but rather a stream of Http2Frame objects that make up the full request.
23
+ void onHttp2Frame (ChannelHandlerContext_Instrumentation ctx , Http2Frame frame ) {
24
+ if (!NettyUtil .START_HTTP2_FRAME_READ_LISTENER_TXN && frame instanceof Http2HeadersFrame && ctx .pipeline ().token == null ) {
25
+ Http2HeadersFrame msg = (Http2HeadersFrame ) frame ;
26
+ if (msg .isEndStream ()) {
27
+ // NettyDispatcher class is usually initialized in AbstractBootstrap; however,
28
+ // that code is not always invoked when using recent Netty versions (4.1.54)
29
+ // so we check here and initialize if we haven't yet.
30
+ if (!NettyDispatcher .instrumented .get ()) {
31
+ NettyDispatcher .get ();
32
+ }
33
+ NettyDispatcher .channelRead (ctx , msg .headers ());
34
+ }
35
+ }
36
+ // Order matters here!!! Weaver.callOriginal() must come after the call to NettyDispatcher.channelRead.
37
+ Weaver .callOriginal ();
38
+ }
39
+
40
+ // Handle the outgoing response. For HTTP/2 there is no HttpResponse object
41
+ // but rather a stream of Http2Frame objects that make up the full response.
42
+ public void write (ChannelHandlerContext_Instrumentation ctx , Object msg , ChannelPromise promise ) {
43
+ if (msg instanceof Http2HeadersFrame ) {
44
+ boolean expired = NettyUtil .processResponse (msg , ctx .pipeline ().token );
45
+ if (expired ) {
46
+ ctx .pipeline ().token = null ;
47
+ }
48
+ }
49
+ // Order matters here!!! Weaver.callOriginal() must come after the call to NettyUtil.processResponse.
50
+ Weaver .callOriginal ();
51
+ }
52
+ }
0 commit comments