1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.handler.codec.http2;
17
18 import io.netty5.buffer.BufferUtil;
19 import io.netty5.buffer.api.Buffer;
20 import io.netty5.channel.ChannelHandlerContext;
21 import io.netty5.handler.logging.LogLevel;
22 import io.netty5.util.internal.UnstableApi;
23 import io.netty5.util.internal.logging.InternalLogLevel;
24 import io.netty5.util.internal.logging.InternalLogger;
25 import io.netty5.util.internal.logging.InternalLoggerFactory;
26
27 import static java.util.Objects.requireNonNull;
28
29
30
31
32 @UnstableApi
33 public class Http2FrameLogger {
34
35 public enum Direction {
36 INBOUND,
37 OUTBOUND
38 }
39
40 private static final int BUFFER_LENGTH_THRESHOLD = 64;
41 private final InternalLogger logger;
42 private final InternalLogLevel level;
43
44 public Http2FrameLogger(LogLevel level) {
45 this(checkAndConvertLevel(level), InternalLoggerFactory.getInstance(Http2FrameLogger.class));
46 }
47
48 public Http2FrameLogger(LogLevel level, String name) {
49 this(checkAndConvertLevel(level), InternalLoggerFactory.getInstance(requireNonNull(name, "name")));
50 }
51
52 public Http2FrameLogger(LogLevel level, Class<?> clazz) {
53 this(checkAndConvertLevel(level), InternalLoggerFactory.getInstance(requireNonNull(clazz, "clazz")));
54 }
55
56 private Http2FrameLogger(InternalLogLevel level, InternalLogger logger) {
57 this.level = level;
58 this.logger = logger;
59 }
60
61 private static InternalLogLevel checkAndConvertLevel(LogLevel level) {
62 return requireNonNull(level, "level").toInternalLevel();
63 }
64
65 public boolean isEnabled() {
66 return logger.isEnabled(level);
67 }
68
69 public void logData(Direction direction, ChannelHandlerContext ctx, int streamId, Buffer data, int padding,
70 boolean endStream) {
71 if (isEnabled()) {
72 logger.log(level, "{} {} DATA: streamId={} padding={} endStream={} length={} bytes={}", ctx.channel(),
73 direction.name(), streamId, padding, endStream, data.readableBytes(), toString(data));
74 }
75 }
76
77 public void logHeaders(Direction direction, ChannelHandlerContext ctx, int streamId, Http2Headers headers,
78 int padding, boolean endStream) {
79 if (isEnabled()) {
80 logger.log(level, "{} {} HEADERS: streamId={} headers={} padding={} endStream={}", ctx.channel(),
81 direction.name(), streamId, headers, padding, endStream);
82 }
83 }
84
85 public void logHeaders(Direction direction, ChannelHandlerContext ctx, int streamId, Http2Headers headers,
86 int streamDependency, short weight, boolean exclusive, int padding, boolean endStream) {
87 if (isEnabled()) {
88 logger.log(level, "{} {} HEADERS: streamId={} headers={} streamDependency={} weight={} exclusive={} " +
89 "padding={} endStream={}", ctx.channel(),
90 direction.name(), streamId, headers, streamDependency, weight, exclusive, padding, endStream);
91 }
92 }
93
94 public void logPriority(Direction direction, ChannelHandlerContext ctx, int streamId, int streamDependency,
95 short weight, boolean exclusive) {
96 if (isEnabled()) {
97 logger.log(level, "{} {} PRIORITY: streamId={} streamDependency={} weight={} exclusive={}", ctx.channel(),
98 direction.name(), streamId, streamDependency, weight, exclusive);
99 }
100 }
101
102 public void logRstStream(Direction direction, ChannelHandlerContext ctx, int streamId, long errorCode) {
103 if (isEnabled()) {
104 logger.log(level, "{} {} RST_STREAM: streamId={} errorCode={}", ctx.channel(),
105 direction.name(), streamId, errorCode);
106 }
107 }
108
109 public void logSettingsAck(Direction direction, ChannelHandlerContext ctx) {
110 logger.log(level, "{} {} SETTINGS: ack=true", ctx.channel(), direction.name());
111 }
112
113 public void logSettings(Direction direction, ChannelHandlerContext ctx, Http2Settings settings) {
114 if (isEnabled()) {
115 logger.log(level, "{} {} SETTINGS: ack=false settings={}", ctx.channel(), direction.name(), settings);
116 }
117 }
118
119 public void logPing(Direction direction, ChannelHandlerContext ctx, long data) {
120 if (isEnabled()) {
121 logger.log(level, "{} {} PING: ack=false bytes={}", ctx.channel(),
122 direction.name(), data);
123 }
124 }
125
126 public void logPingAck(Direction direction, ChannelHandlerContext ctx, long data) {
127 if (isEnabled()) {
128 logger.log(level, "{} {} PING: ack=true bytes={}", ctx.channel(),
129 direction.name(), data);
130 }
131 }
132
133 public void logPushPromise(Direction direction, ChannelHandlerContext ctx, int streamId, int promisedStreamId,
134 Http2Headers headers, int padding) {
135 if (isEnabled()) {
136 logger.log(level, "{} {} PUSH_PROMISE: streamId={} promisedStreamId={} headers={} padding={}",
137 ctx.channel(), direction.name(), streamId, promisedStreamId, headers, padding);
138 }
139 }
140
141 public void logGoAway(Direction direction, ChannelHandlerContext ctx, int lastStreamId, long errorCode,
142 Buffer debugData) {
143 if (isEnabled()) {
144 logger.log(level, "{} {} GO_AWAY: lastStreamId={} errorCode={} length={} bytes={}", ctx.channel(),
145 direction.name(), lastStreamId, errorCode, debugData.readableBytes(), toString(debugData));
146 }
147 }
148
149 public void logWindowsUpdate(Direction direction, ChannelHandlerContext ctx, int streamId,
150 int windowSizeIncrement) {
151 if (isEnabled()) {
152 logger.log(level, "{} {} WINDOW_UPDATE: streamId={} windowSizeIncrement={}", ctx.channel(),
153 direction.name(), streamId, windowSizeIncrement);
154 }
155 }
156
157 public void logUnknownFrame(Direction direction, ChannelHandlerContext ctx, byte frameType, int streamId,
158 Http2Flags flags, Buffer data) {
159 if (isEnabled()) {
160 logger.log(level, "{} {} UNKNOWN: frameType={} streamId={} flags={} length={} bytes={}", ctx.channel(),
161 direction.name(), frameType & 0xFF, streamId, flags.value(), data.readableBytes(), toString(data));
162 }
163 }
164
165 private String toString(Buffer buf) {
166 if (level == InternalLogLevel.TRACE || buf.readableBytes() <= BUFFER_LENGTH_THRESHOLD) {
167
168 return BufferUtil.hexDump(buf);
169 }
170
171
172 int length = Math.min(buf.readableBytes(), BUFFER_LENGTH_THRESHOLD);
173 return BufferUtil.hexDump(buf, buf.readerOffset(), length) + "...";
174 }
175 }