class Netty4InboundStatsHandler extends ChannelInboundHandlerAdapter implements Releasable {

    final Set<Channel> openChannels = Collections.newSetFromMap(new ConcurrentHashMap<>());

    final StatsTracker statsTracker;

    final Logger logger;

    public Netty4InboundStatsHandler(StatsTracker statsTracker, Logger logger) {
        this.statsTracker = statsTracker;
        this.logger = logger;
    }

    final ChannelFutureListener remover = new ChannelFutureListener() {
        @Override
        public void operationComplete(ChannelFuture future) throws Exception {
            boolean removed = openChannels.remove(future.channel());
            if (removed) {
                statsTracker.decrementOpenChannels();
            }
            if (logger.isTraceEnabled()) {
                logger.trace("channel closed: {}", future.channel());
            }
        }
    };

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {<FILL_FUNCTION_BODY>}

    @Override
    public void close() {
        try {
            Netty4Utils.closeChannels(openChannels);
        } catch (IOException e) {
            logger.trace("exception while closing channels", e);
        }
        openChannels.clear();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof ByteBuf bb) {
            statsTracker.incrementBytesReceived(bb.readableBytes());
            statsTracker.incrementMessagesReceived();
        } else {
            logger.warn("Message sent is: {} and not a ByteBuf, cannot track received bytes or message count",
                msg.getClass().getCanonicalName());
        }
        super.channelRead(ctx, msg);
    }
}

        if (logger.isTraceEnabled()) {
            logger.trace("channel opened: {}", ctx.channel());
        }
        final boolean added = openChannels.add(ctx.channel());
        if (added) {
            statsTracker.incrementOpenChannels();
            ctx.channel().closeFuture().addListener(remover);
        }

        super.channelActive(ctx);
    
<no_super_class>