<commit_before>package org.commonjava.indy.httprox.util;

import org.apache.http.HttpRequest;
import org.commonjava.indy.sli.metrics.GoldenSignalsMetricSet;
import org.slf4j.Logger;
import org.slf4j.MDC;

import java.net.SocketAddress;

import static java.lang.Integer.parseInt;
import static org.commonjava.indy.bind.jaxrs.RequestContextHelper.HTTP_METHOD;
import static org.commonjava.indy.bind.jaxrs.RequestContextHelper.HTTP_STATUS;
import static org.commonjava.indy.bind.jaxrs.RequestContextHelper.REQUEST_LATENCY_NS;
import static org.commonjava.indy.bind.jaxrs.RequestContextHelper.REQUEST_PHASE;
import static org.commonjava.indy.bind.jaxrs.RequestContextHelper.REQUEST_PHASE_END;
import static org.commonjava.indy.bind.jaxrs.RequestContextHelper.getContext;
import static org.commonjava.indy.bind.jaxrs.RequestContextHelper.setContext;

public class ProxyMeter
{
    private boolean summaryReported;

    private final String method;

    private final String requestLine;

    private final long startNanos;

    private final GoldenSignalsMetricSet sliMetricSet;

    private final Logger restLogger;

    private final SocketAddress peerAddress;

    public ProxyMeter( final String method, final String requestLine, final long startNanos, final GoldenSignalsMetricSet sliMetricSet, final Logger restLogger,
                       final SocketAddress peerAddress )
    {
        this.method = method;
        this.requestLine = requestLine;
        this.startNanos = startNanos;
        this.sliMetricSet = sliMetricSet;
        this.restLogger = restLogger;
        this.peerAddress = peerAddress;
    }

    public void reportResponseSummary()
    {
        /*
         Here, we make this call idempotent to make the logic easier in the doHandleEvent method.
         This way, for content-transfer requests we will call this JUST BEFORE the transfer begins,
         while for all other requests we will handle it in the finally block of the doHandleEvent() method.

         NOTE: This will probably result in incorrect latency measurements for any client using HTTPS via the
         CONNECT method.
        */
        if ( !summaryReported )
        {
            summaryReported = true;

            long latency = System.nanoTime() - startNanos;

            MDC.put( REQUEST_LATENCY_NS, String.valueOf( latency ) );
            setContext( HTTP_METHOD, method );

            // log SLI metrics
            sliMetricSet.function( GoldenSignalsMetricSet.FN_CONTENT_GENERIC ).ifPresent( ms ->{
                ms.latency( latency ).call();

                if ( parseInt( getContext( HTTP_STATUS, "200" ) ) > 499 )
                {
                    ms.error();
                }
            } );

            MDC.put( REQUEST_PHASE, REQUEST_PHASE_END );
            restLogger.info( "END {} (from: {})", requestLine, peerAddress );
            MDC.remove( REQUEST_PHASE );
        }
    }

    public ProxyMeter copy( final long startNanos, final String method, final String requestLine )
    {
        return new ProxyMeter( method, requestLine, startNanos, sliMetricSet, restLogger, peerAddress );
    }
}
<commit_msg>fix NPE in tests where sliMetrics aren't available<commit_after>package org.commonjava.indy.httprox.util;

import org.apache.http.HttpRequest;
import org.commonjava.indy.sli.metrics.GoldenSignalsMetricSet;
import org.slf4j.Logger;
import org.slf4j.MDC;

import java.net.SocketAddress;

import static java.lang.Integer.parseInt;
import static org.commonjava.indy.bind.jaxrs.RequestContextHelper.HTTP_METHOD;
import static org.commonjava.indy.bind.jaxrs.RequestContextHelper.HTTP_STATUS;
import static org.commonjava.indy.bind.jaxrs.RequestContextHelper.REQUEST_LATENCY_NS;
import static org.commonjava.indy.bind.jaxrs.RequestContextHelper.REQUEST_PHASE;
import static org.commonjava.indy.bind.jaxrs.RequestContextHelper.REQUEST_PHASE_END;
import static org.commonjava.indy.bind.jaxrs.RequestContextHelper.getContext;
import static org.commonjava.indy.bind.jaxrs.RequestContextHelper.setContext;

public class ProxyMeter
{
    private boolean summaryReported;

    private final String method;

    private final String requestLine;

    private final long startNanos;

    private final GoldenSignalsMetricSet sliMetricSet;

    private final Logger restLogger;

    private final SocketAddress peerAddress;

    public ProxyMeter( final String method, final String requestLine, final long startNanos, final GoldenSignalsMetricSet sliMetricSet, final Logger restLogger,
                       final SocketAddress peerAddress )
    {
        this.method = method;
        this.requestLine = requestLine;
        this.startNanos = startNanos;
        this.sliMetricSet = sliMetricSet;
        this.restLogger = restLogger;
        this.peerAddress = peerAddress;
    }

    public void reportResponseSummary()
    {
        /*
         Here, we make this call idempotent to make the logic easier in the doHandleEvent method.
         This way, for content-transfer requests we will call this JUST BEFORE the transfer begins,
         while for all other requests we will handle it in the finally block of the doHandleEvent() method.

         NOTE: This will probably result in incorrect latency measurements for any client using HTTPS via the
         CONNECT method.
        */
        if ( !summaryReported )
        {
            summaryReported = true;

            long latency = System.nanoTime() - startNanos;

            MDC.put( REQUEST_LATENCY_NS, String.valueOf( latency ) );
            setContext( HTTP_METHOD, method );

            // log SLI metrics
            if ( sliMetricSet != null )
            {
                sliMetricSet.function( GoldenSignalsMetricSet.FN_CONTENT_GENERIC ).ifPresent( ms ->{
                    ms.latency( latency ).call();

                    if ( parseInt( getContext( HTTP_STATUS, "200" ) ) > 499 )
                    {
                        ms.error();
                    }
                } );
            }

            MDC.put( REQUEST_PHASE, REQUEST_PHASE_END );
            restLogger.info( "END {} (from: {})", requestLine, peerAddress );
            MDC.remove( REQUEST_PHASE );
        }
    }

    public ProxyMeter copy( final long startNanos, final String method, final String requestLine )
    {
        return new ProxyMeter( method, requestLine, startNanos, sliMetricSet, restLogger, peerAddress );
    }
}

{'fraction_non_alphanumeric': 0.07399906527496494, 'fraction_numerical': 0.0024926000934725034, 'mean_word_length': 2.754385964912281, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1569602', 'n_tokens_mistral': 1818, 'n_tokens_neox': 1720, 'n_words': 466}