class PrometheusHandler implements MiddlewareHandler {
    public static final String CONFIG_NAME = "prometheus";
    public static PrometheusConfig config =(PrometheusConfig)Config.getInstance().getJsonObjectConfig(CONFIG_NAME, PrometheusConfig.class);

    private CollectorRegistry registry;

    static final Logger logger = LoggerFactory.getLogger(PrometheusHandler.class);

    private volatile HttpHandler next;
    private final ConcurrentMap<String, Counter> counters = new ConcurrentHashMap<>();
    private final ConcurrentMap<String, Summary> response_times = new ConcurrentHashMap<>();

    public static final String REQUEST_TOTAL = "requests_total";
    public static final String SUCCESS_TOTAL = "success_total";
    public static final String AUTO_ERROR_TOTAL = "auth_error_total";
    public static final String REQUEST_ERROR_TOTAL = "request_error_total";
    public static final String SERVER_ERROR_TOTAL = "server_error_total";
    public static final String RESPONSE_TIME_SECOND = "response_time_seconds";



    public PrometheusHandler() {
        registry=  CollectorRegistry.defaultRegistry;
    }

    @Override
    public HttpHandler getNext() {
        return this.next;
    }

    @Override
    public MiddlewareHandler setNext(final HttpHandler next) {
        Handlers.handlerNotNull(next);
        this.next = next;
        return this;

    }

    @Override
    public void handleRequest(final HttpServerExchange exchange) throws Exception {<FILL_FUNCTION_BODY>}

    @Override
    public boolean isEnabled() {
        return config.isEnabled();
    }

    @Override
    public void register() {
        ModuleRegistry.registerModule(PrometheusConfig.CONFIG_NAME, PrometheusHandler.class.getName(), Config.getNoneDecryptedInstance().getJsonMapConfigNoCache(CONFIG_NAME), null);
    }

    @Override
    public void reload() {
        config =(PrometheusConfig)Config.getInstance().getJsonObjectConfig(CONFIG_NAME, PrometheusConfig.class);
    }

    private void incCounterForStatusCode(int statusCode, List<String> labels,  List<String> labelValues) {

        counter(REQUEST_TOTAL, labels).labels(labelValues.stream().toArray(String[]::new)).inc();
        if(statusCode >= 200 && statusCode < 400) {
            counter(SUCCESS_TOTAL , labels).labels(labelValues.stream().toArray(String[]::new)).inc();
        } else if(statusCode == 401 || statusCode == 403) {
            counter(AUTO_ERROR_TOTAL , labels).labels(labelValues.stream().toArray(String[]::new)).inc();
        } else if(statusCode >= 400 && statusCode < 500) {
            counter(REQUEST_ERROR_TOTAL , labels).labels(labelValues.stream().toArray(String[]::new)).inc();
        } else if(statusCode >= 500) {
            counter(SERVER_ERROR_TOTAL , labels).labels(labelValues.stream().toArray(String[]::new)).inc();
        }

    }

    private Counter counter(String name, List<String> labels) {
        String key = sanitizeName(name);
        return counters.computeIfAbsent(key, k-> Counter.build().name(k).help(k).labelNames(labels.stream().toArray(String[]::new)).register(registry));
    }

    private Summary summary(String name, List<String> labels) {
        String key = sanitizeName(name);
        return response_times.computeIfAbsent(key, k-> Summary.build().name(k).help(k).labelNames(labels.stream().toArray(String[]::new)).register(registry));
    }

    private String sanitizeName(String name) {
        return name.replaceAll("[^a-zA-Z0-9_:]", "_");
    }
}

        SimpleTimer respTimer = new SimpleTimer();

        exchange.addExchangeCompleteListener((exchange1, nextListener) -> {
            try {
                Map<String, Object> auditInfo = exchange1.getAttachment(AttachmentConstants.AUDIT_INFO);
                if(auditInfo != null) {
                    Map<String, String> tags = new HashMap<>();
                    tags.put("endpoint", (String)auditInfo.get(Constants.ENDPOINT_STRING));
                    tags.put("clientId", auditInfo.get(Constants.CLIENT_ID_STRING) != null ? (String)auditInfo.get(Constants.CLIENT_ID_STRING) : "unknown");

                    // The tags can be empty in error cases.
                    if (!tags.isEmpty()) {
                        List<String> labels = new ArrayList<>(tags.keySet());
                        List<String> labelValues = new ArrayList<>(tags.values());

                        summary(RESPONSE_TIME_SECOND, labels).labels(labelValues.stream().toArray(String[]::new)).observe(respTimer.elapsedSeconds());

                        incCounterForStatusCode(exchange1.getStatusCode(), labels, labelValues);
                        if (config.enableHotspot) {
                            logger.info("Prometheus hotspot monitor enabled.");
                            DefaultExports.initialize();
                        }
                    } else {
                        logger.debug("Tags was empty. AuditInfo size " + auditInfo.size());
                    }
                }
            } catch (Throwable e) {
                logger.error("ExchangeListener throwable", e);
            } finally {
                nextListener.proceed();
            }
        });

        Handler.next(exchange, next);
    
<no_super_class>