@Override
    public void log(Request request, Response response) {
        try {
            RequestLogEntry.Builder builder = new RequestLogEntry.Builder();

            String peerAddress = request.getRemoteAddr();
            int peerPort = request.getRemotePort();
            long startTime = request.getTimeStamp();
            long endTime = System.currentTimeMillis();
            Integer statusCodeOverride = (Integer) request.getAttribute(HttpRequestDispatch.ACCESS_LOG_STATUS_CODE_OVERRIDE);
            builder.peerAddress(peerAddress)
                    .peerPort(peerPort)
                    .localPort(getLocalPort(request))
                    .timestamp(Instant.ofEpochMilli(startTime))
                    .duration(Duration.ofMillis(Math.max(0, endTime - startTime)))
                    .responseSize(response.getHttpChannel().getBytesWritten())
                    .requestSize(request.getHttpInput().getContentReceived())
                    .statusCode(statusCodeOverride != null ? statusCodeOverride : response.getCommittedMetaData().getStatus());

            addNonNullValue(builder, request.getMethod(), RequestLogEntry.Builder::httpMethod);
            addNonNullValue(builder, request.getRequestURI(), RequestLogEntry.Builder::rawPath);
            addNonNullValue(builder, request.getProtocol(), RequestLogEntry.Builder::httpVersion);
            addNonNullValue(builder, request.getScheme(), RequestLogEntry.Builder::scheme);
            addNonNullValue(builder, request.getHeader("User-Agent"), RequestLogEntry.Builder::userAgent);
            addNonNullValue(builder, getServerName(request), RequestLogEntry.Builder::hostString);
            addNonNullValue(builder, request.getHeader("Referer"), RequestLogEntry.Builder::referer);
            addNonNullValue(builder, request.getQueryString(), RequestLogEntry.Builder::rawQuery);

            HttpRequest jdiscRequest  = (HttpRequest) request.getAttribute(HttpRequest.class.getName());
            if (jdiscRequest != null) {
                addNonNullValue(builder, jdiscRequest.getUserPrincipal(), RequestLogEntry.Builder::userPrincipal);
            }

            String requestFilterId = (String) request.getAttribute(RequestUtils.JDISC_REQUEST_CHAIN);
            addNonNullValue(builder, requestFilterId, (b, chain) -> b.addExtraAttribute("request-chain", chain));

            String responseFilterId = (String) request.getAttribute(RequestUtils.JDISC_RESPONSE_CHAIN);
            addNonNullValue(builder, responseFilterId, (b, chain) -> b.addExtraAttribute("response-chain", chain));

            UUID connectionId = (UUID) request.getAttribute(JettyConnectionLogger.CONNECTION_ID_REQUEST_ATTRIBUTE);
            addNonNullValue(builder, connectionId, (b, uuid) -> b.connectionId(uuid.toString()));

            String remoteAddress = getRemoteAddress(request);
            if (!Objects.equal(remoteAddress, peerAddress)) {
                builder.remoteAddress(remoteAddress);
            }
            int remotePort = getRemotePort(request);
            if (remotePort != peerPort) {
                builder.remotePort(remotePort);
            }
            LOGGED_REQUEST_HEADERS.forEach(header -> {
                String value = request.getHeader(header);
                if (value != null) {
                    builder.addExtraAttribute(header, value);
                }
            });
            X509Certificate[] clientCert = (X509Certificate[]) request.getAttribute(RequestUtils.SERVLET_REQUEST_X509CERT);
            if (clientCert != null && clientCert.length > 0) {
                builder.sslPrincipal(clientCert[0].getSubjectX500Principal());
            }

            AccessLogEntry accessLogEntry = (AccessLogEntry) request.getAttribute(JDiscHttpServlet.ATTRIBUTE_NAME_ACCESS_LOG_ENTRY);
            if (accessLogEntry != null) {
                var extraAttributes = accessLogEntry.getKeyValues();
                if (extraAttributes != null) {
                    extraAttributes.forEach(builder::addExtraAttributes);
                }
                addNonNullValue(builder, accessLogEntry.getHitCounts(), RequestLogEntry.Builder::hitCounts);
                addNonNullValue(builder, accessLogEntry.getTrace(), RequestLogEntry.Builder::traceNode);
                accessLogEntry.getContent().ifPresent(builder::content);
            }
            http2StreamId(request).ifPresent(streamId -> builder.addExtraAttribute("http2-stream-id", Integer.toString(streamId)));

            requestLog.log(builder.build());
        } catch (Exception e) {
            // Catching any exceptions here as it is unclear how Jetty handles exceptions from a RequestLog.
            logger.log(Level.SEVERE, "Failed to log access log entry: " + e.getMessage(), e);
        }
    }
@Test
    void requireThatStatusCodeCanBeOverridden() {
        Request jettyRequest = createRequestBuilder()
                .uri("http", "localhost", 12345, "/api/", null)
                .build();

        InMemoryRequestLog requestLog = new InMemoryRequestLog();
        new AccessLogRequestLog(requestLog).log(jettyRequest, JettyMockResponseBuilder.newBuilder().build());
        assertEquals(200, requestLog.entries().remove(0).statusCode().getAsInt());

        jettyRequest.setAttribute(HttpRequestDispatch.ACCESS_LOG_STATUS_CODE_OVERRIDE, 404);
        new AccessLogRequestLog(requestLog).log(jettyRequest, JettyMockResponseBuilder.newBuilder().build());
        assertEquals(404, requestLog.entries().remove(0).statusCode().getAsInt());
    }