@Override
    public void channelRead(final ChannelHandlerContext ctx, Object msg) {
        if (msg instanceof FullHttpMessage) {
            final FullHttpMessage request = (FullHttpMessage) msg;
            if (request.headers().contains(USER_AGENT_HEADER_NAME)) {
                final String userAgent = request.headers().get(USER_AGENT_HEADER_NAME);
                ctx.channel().attr(USER_AGENT_ATTR_KEY).set(userAgent);
                logger.debug("New Connection on channel [{}] with user agent [{}]", ctx.channel().id().asShortText(), userAgent);

                String metricName = MetricRegistry.name(GremlinServer.class, "user-agent", userAgent);

                // This check is to address a concern that an attacker may try to fill the server's memory with a very
                // large number of unique user agents. For this reason the user agent is replaced with "other"
                // for the purpose of metrics if this cap is ever exceeded and the user agent is not already being tracked.
                if (MetricManager.INSTANCE.getCounterSize() > MAX_USER_AGENT_METRICS &&
                        !MetricManager.INSTANCE.contains(metricName)) {
                    metricName = MetricRegistry.name(GremlinServer.class, "user-agent", "other");
                }
                MetricManager.INSTANCE.getCounter(metricName).inc();
            } else {
                logger.debug("New Connection on channel [{}] with no user agent provided", ctx.channel().id().asShortText());
            }
        }
        ctx.fireChannelRead(msg);
    }
This constant caps the number of unique user agents which will be tracked in the metrics. Any new unique
user agents will be replaced with "other" in the metrics after this cap has been reached.
gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpUserAgentHandler.java