class StatisticsFilter implements Filter {

    static final String REQUESTS_METRIC = "requests";
    private static final String CATEGORY_TAG = "category";

    private final DistributionSummary requests = Metrics.getPrometheusRegistry().summary(REQUESTS_METRIC);

    @Override
    public void init(FilterConfig fc) throws ServletException {
        //No init config Operation
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain fc)
            throws IOException, ServletException {

        requests.record(1);

        HttpServletRequest httpReq = (HttpServletRequest) servletRequest;

        Instant start = Instant.now();

        PageConfig config = PageConfig.get(httpReq);

        fc.doFilter(servletRequest, servletResponse);

        measure((HttpServletResponse) servletResponse, httpReq, Duration.between(start, Instant.now()), config);
    }

    private void measure(HttpServletResponse httpResponse, HttpServletRequest httpReq,
                         Duration duration, PageConfig config) {<FILL_FUNCTION_BODY>}

    @NotNull
    private String getCategory(HttpServletRequest httpReq, PageConfig config) {
        String category;
        if (isRoot(httpReq)) {
            category = "root";
        } else {
            String prefix = config.getPrefix().toString();
            if (prefix.isEmpty()) {
                category = "unknown";
            } else {
                category = prefix.substring(1);
                if (category.equals("xref") && httpReq.getParameter(QueryParameters.ANNOTATION_PARAM) != null) {
                    category = "annotate";
                }
            }
        }
        return category;
    }

    private boolean isRoot(final HttpServletRequest httpReq) {
        return httpReq.getRequestURI().replace(httpReq.getContextPath(), "").equals("/")
                || httpReq.getRequestURI().replace(httpReq.getContextPath(), "").equals("");
    }

    @Override
    public void destroy() {
        //No destroy Operation
    }
}

        String category;
        category = getCategory(httpReq, config);

        Timer categoryTimer = Timer.builder("requests.latency").
                tags(CATEGORY_TAG, category, "code", String.valueOf(httpResponse.getStatus())).
                register(Metrics.getPrometheusRegistry());
        categoryTimer.record(duration);

        SearchHelper helper = (SearchHelper) config.getRequestAttribute(SearchHelper.REQUEST_ATTR);
        MeterRegistry registry = Metrics.getRegistry();
        if (helper != null && registry != null) {
            if (helper.getHits() == null || helper.getHits().length == 0) {
                Timer.builder("search.latency").
                        tags(CATEGORY_TAG, "ui", "outcome", "empty").
                        register(registry).
                        record(duration);
            } else {
                Timer.builder("search.latency").
                        tags(CATEGORY_TAG, "ui", "outcome", "success").
                        register(registry).
                        record(duration);
            }
        }
    
<no_super_class>