I want to add a metricsHandler
that measures the time taken for a request-response cycle.
@Sharable
public class MetricCalcHandler extends ChannelDuplexHandler {
private static final AttributeKey<Long> TIME_TAKEN = AttributeKey.newInstance("time");
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
ctx.channel().attr(TIME_TAKEN).set(System.currentTimeMillis());
ctx.fireChannelRegistered();
}
@Override
public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
Long ms = System.currentTimeMillis() - ctx.channel().attr(TIME_TAKEN).get());
log.info("time taken " + ms);
ctx.deregister(promise);
}
}
public class MyInitializer extends ChannelInitializer<SocketChannel> {
@Override
public void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
p.addLast(new MetricCalcHandler());
p.addLast(new LoggingHandler(LogLevel.INFO));
p.addLast(new HttpServerCodec());
p.addLast(new HttpObjectAggregator(1024 * 1024, true));
p.addLast(new Handler1());
p.addLast(new Handler2());
}
}
Now the questions I have are
- I added
@Sharable
but maintaining a state in the channel (per request). Is this right? Since a single channel is shared across multiple requests, wouldn't there be a collison/data-corruption. - I calculated the processing start time in
ChannelRegistered
and finished inderegister
. Is that the right place to do? or usechannelActive()/channelInActive()
methods? - Does Netty provides any handler out of the box for these use-cases?
- I am adding MetricCalcHandler first followed by other handlers in MyInitializer. so that handler is invoked first. is that correct?
Thanks