2015-01-20 01:48:11 +01:00
|
|
|
/*
|
|
|
|
* Copyright 2014 The Netty Project
|
|
|
|
*
|
|
|
|
* The Netty Project licenses this file to you under the Apache License,
|
|
|
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
|
|
|
* with the License. You may obtain a copy of the License at:
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
* License for the specific language governing permissions and limitations
|
|
|
|
* under the License.
|
|
|
|
*/
|
|
|
|
package io.netty.handler.codec.http2;
|
|
|
|
|
|
|
|
import io.netty.buffer.ByteBuf;
|
|
|
|
import io.netty.buffer.ByteBufUtil;
|
|
|
|
import io.netty.channel.ChannelHandlerAdapter;
|
2016-01-16 22:13:50 +01:00
|
|
|
import io.netty.channel.ChannelHandlerContext;
|
2015-03-17 15:52:02 +01:00
|
|
|
import io.netty.handler.logging.LogLevel;
|
2016-04-12 14:22:41 +02:00
|
|
|
import io.netty.util.internal.UnstableApi;
|
2015-01-20 01:48:11 +01:00
|
|
|
import io.netty.util.internal.logging.InternalLogLevel;
|
|
|
|
import io.netty.util.internal.logging.InternalLogger;
|
|
|
|
import io.netty.util.internal.logging.InternalLoggerFactory;
|
|
|
|
|
2017-06-21 02:22:56 +02:00
|
|
|
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
|
|
|
|
2015-01-20 01:48:11 +01:00
|
|
|
/**
|
|
|
|
* Logs HTTP2 frames for debugging purposes.
|
|
|
|
*/
|
2016-04-12 14:22:41 +02:00
|
|
|
@UnstableApi
|
2015-01-20 01:48:11 +01:00
|
|
|
public class Http2FrameLogger extends ChannelHandlerAdapter {
|
|
|
|
|
|
|
|
public enum Direction {
|
|
|
|
INBOUND,
|
|
|
|
OUTBOUND
|
|
|
|
}
|
|
|
|
|
2015-03-12 22:01:43 +01:00
|
|
|
private static final int BUFFER_LENGTH_THRESHOLD = 64;
|
2015-01-20 01:48:11 +01:00
|
|
|
private final InternalLogger logger;
|
|
|
|
private final InternalLogLevel level;
|
|
|
|
|
2015-03-17 15:52:02 +01:00
|
|
|
public Http2FrameLogger(LogLevel level) {
|
|
|
|
this(level.toInternalLevel(), InternalLoggerFactory.getInstance(Http2FrameLogger.class));
|
|
|
|
}
|
|
|
|
|
|
|
|
public Http2FrameLogger(LogLevel level, String name) {
|
|
|
|
this(level.toInternalLevel(), InternalLoggerFactory.getInstance(name));
|
|
|
|
}
|
|
|
|
|
|
|
|
public Http2FrameLogger(LogLevel level, Class<?> clazz) {
|
|
|
|
this(level.toInternalLevel(), InternalLoggerFactory.getInstance(clazz));
|
2015-01-20 01:48:11 +01:00
|
|
|
}
|
|
|
|
|
2015-03-17 15:52:02 +01:00
|
|
|
private Http2FrameLogger(InternalLogLevel level, InternalLogger logger) {
|
2015-01-20 01:48:11 +01:00
|
|
|
this.level = checkNotNull(level, "level");
|
|
|
|
this.logger = checkNotNull(logger, "logger");
|
|
|
|
}
|
|
|
|
|
2018-05-15 09:06:32 +02:00
|
|
|
public boolean isEnabled() {
|
|
|
|
return logger.isEnabled(level);
|
|
|
|
}
|
|
|
|
|
2016-01-16 22:13:50 +01:00
|
|
|
public void logData(Direction direction, ChannelHandlerContext ctx, int streamId, ByteBuf data, int padding,
|
2015-01-20 01:48:11 +01:00
|
|
|
boolean endStream) {
|
2018-05-15 09:06:32 +02:00
|
|
|
if (isEnabled()) {
|
|
|
|
logger.log(level, "{} {} DATA: streamId={} padding={} endStream={} length={} bytes={}", ctx.channel(),
|
|
|
|
direction.name(), streamId, padding, endStream, data.readableBytes(), toString(data));
|
|
|
|
}
|
2015-01-20 01:48:11 +01:00
|
|
|
}
|
|
|
|
|
2016-01-16 22:13:50 +01:00
|
|
|
public void logHeaders(Direction direction, ChannelHandlerContext ctx, int streamId, Http2Headers headers,
|
|
|
|
int padding, boolean endStream) {
|
2018-05-15 09:06:32 +02:00
|
|
|
if (isEnabled()) {
|
|
|
|
logger.log(level, "{} {} HEADERS: streamId={} headers={} padding={} endStream={}", ctx.channel(),
|
|
|
|
direction.name(), streamId, headers, padding, endStream);
|
|
|
|
}
|
2015-01-20 01:48:11 +01:00
|
|
|
}
|
|
|
|
|
2016-01-16 22:13:50 +01:00
|
|
|
public void logHeaders(Direction direction, ChannelHandlerContext ctx, int streamId, Http2Headers headers,
|
2015-01-20 01:48:11 +01:00
|
|
|
int streamDependency, short weight, boolean exclusive, int padding, boolean endStream) {
|
2018-05-15 09:06:32 +02:00
|
|
|
if (isEnabled()) {
|
|
|
|
logger.log(level, "{} {} HEADERS: streamId={} headers={} streamDependency={} weight={} exclusive={} " +
|
|
|
|
"padding={} endStream={}", ctx.channel(),
|
|
|
|
direction.name(), streamId, headers, streamDependency, weight, exclusive, padding, endStream);
|
|
|
|
}
|
2015-01-20 01:48:11 +01:00
|
|
|
}
|
|
|
|
|
2016-01-16 22:13:50 +01:00
|
|
|
public void logPriority(Direction direction, ChannelHandlerContext ctx, int streamId, int streamDependency,
|
|
|
|
short weight, boolean exclusive) {
|
2018-05-15 09:06:32 +02:00
|
|
|
if (isEnabled()) {
|
|
|
|
logger.log(level, "{} {} PRIORITY: streamId={} streamDependency={} weight={} exclusive={}", ctx.channel(),
|
|
|
|
direction.name(), streamId, streamDependency, weight, exclusive);
|
|
|
|
}
|
2015-01-20 01:48:11 +01:00
|
|
|
}
|
|
|
|
|
2016-01-16 22:13:50 +01:00
|
|
|
public void logRstStream(Direction direction, ChannelHandlerContext ctx, int streamId, long errorCode) {
|
2018-05-15 09:06:32 +02:00
|
|
|
if (isEnabled()) {
|
|
|
|
logger.log(level, "{} {} RST_STREAM: streamId={} errorCode={}", ctx.channel(),
|
|
|
|
direction.name(), streamId, errorCode);
|
|
|
|
}
|
2015-01-20 01:48:11 +01:00
|
|
|
}
|
|
|
|
|
2016-01-16 22:13:50 +01:00
|
|
|
public void logSettingsAck(Direction direction, ChannelHandlerContext ctx) {
|
2017-06-21 02:22:56 +02:00
|
|
|
logger.log(level, "{} {} SETTINGS: ack=true", ctx.channel(), direction.name());
|
2015-01-20 01:48:11 +01:00
|
|
|
}
|
|
|
|
|
2016-01-16 22:13:50 +01:00
|
|
|
public void logSettings(Direction direction, ChannelHandlerContext ctx, Http2Settings settings) {
|
2018-05-15 09:06:32 +02:00
|
|
|
if (isEnabled()) {
|
|
|
|
logger.log(level, "{} {} SETTINGS: ack=false settings={}", ctx.channel(), direction.name(), settings);
|
|
|
|
}
|
2015-01-20 01:48:11 +01:00
|
|
|
}
|
|
|
|
|
2018-02-05 11:57:49 +01:00
|
|
|
public void logPing(Direction direction, ChannelHandlerContext ctx, long data) {
|
2018-05-15 09:06:32 +02:00
|
|
|
if (isEnabled()) {
|
|
|
|
logger.log(level, "{} {} PING: ack=false bytes={}", ctx.channel(),
|
|
|
|
direction.name(), data);
|
|
|
|
}
|
2015-01-20 01:48:11 +01:00
|
|
|
}
|
|
|
|
|
2018-02-05 11:57:49 +01:00
|
|
|
public void logPingAck(Direction direction, ChannelHandlerContext ctx, long data) {
|
2018-05-15 09:06:32 +02:00
|
|
|
if (isEnabled()) {
|
|
|
|
logger.log(level, "{} {} PING: ack=true bytes={}", ctx.channel(),
|
|
|
|
direction.name(), data);
|
|
|
|
}
|
2015-01-20 01:48:11 +01:00
|
|
|
}
|
|
|
|
|
2016-01-16 22:13:50 +01:00
|
|
|
public void logPushPromise(Direction direction, ChannelHandlerContext ctx, int streamId, int promisedStreamId,
|
2015-01-20 01:48:11 +01:00
|
|
|
Http2Headers headers, int padding) {
|
2018-05-15 09:06:32 +02:00
|
|
|
if (isEnabled()) {
|
|
|
|
logger.log(level, "{} {} PUSH_PROMISE: streamId={} promisedStreamId={} headers={} padding={}",
|
|
|
|
ctx.channel(), direction.name(), streamId, promisedStreamId, headers, padding);
|
|
|
|
}
|
2015-01-20 01:48:11 +01:00
|
|
|
}
|
|
|
|
|
2016-01-16 22:13:50 +01:00
|
|
|
public void logGoAway(Direction direction, ChannelHandlerContext ctx, int lastStreamId, long errorCode,
|
|
|
|
ByteBuf debugData) {
|
2018-05-15 09:06:32 +02:00
|
|
|
if (isEnabled()) {
|
|
|
|
logger.log(level, "{} {} GO_AWAY: lastStreamId={} errorCode={} length={} bytes={}", ctx.channel(),
|
|
|
|
direction.name(), lastStreamId, errorCode, debugData.readableBytes(), toString(debugData));
|
|
|
|
}
|
2015-01-20 01:48:11 +01:00
|
|
|
}
|
|
|
|
|
2016-01-16 22:13:50 +01:00
|
|
|
public void logWindowsUpdate(Direction direction, ChannelHandlerContext ctx, int streamId,
|
|
|
|
int windowSizeIncrement) {
|
2018-05-15 09:06:32 +02:00
|
|
|
if (isEnabled()) {
|
|
|
|
logger.log(level, "{} {} WINDOW_UPDATE: streamId={} windowSizeIncrement={}", ctx.channel(),
|
|
|
|
direction.name(), streamId, windowSizeIncrement);
|
|
|
|
}
|
2015-01-20 01:48:11 +01:00
|
|
|
}
|
|
|
|
|
2016-01-16 22:13:50 +01:00
|
|
|
public void logUnknownFrame(Direction direction, ChannelHandlerContext ctx, byte frameType, int streamId,
|
|
|
|
Http2Flags flags, ByteBuf data) {
|
2018-05-15 09:06:32 +02:00
|
|
|
if (isEnabled()) {
|
|
|
|
logger.log(level, "{} {} UNKNOWN: frameType={} streamId={} flags={} length={} bytes={}", ctx.channel(),
|
|
|
|
direction.name(), frameType & 0xFF, streamId, flags.value(), data.readableBytes(), toString(data));
|
|
|
|
}
|
2015-03-12 22:01:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private String toString(ByteBuf buf) {
|
|
|
|
if (level == InternalLogLevel.TRACE || buf.readableBytes() <= BUFFER_LENGTH_THRESHOLD) {
|
|
|
|
// Log the entire buffer.
|
|
|
|
return ByteBufUtil.hexDump(buf);
|
2015-01-20 01:48:11 +01:00
|
|
|
}
|
2015-03-12 22:01:43 +01:00
|
|
|
|
|
|
|
// Otherwise just log the first 64 bytes.
|
|
|
|
int length = Math.min(buf.readableBytes(), BUFFER_LENGTH_THRESHOLD);
|
|
|
|
return ByteBufUtil.hexDump(buf, buf.readerIndex(), length) + "...";
|
|
|
|
}
|
2015-01-20 01:48:11 +01:00
|
|
|
}
|