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 );
    }
}

@@ -2394,16 +2394,74 @@
 metrics%0A
+            if ( sliMetricSet != null )%0A            %7B%0A    
         
@@ -2565,16 +2565,20 @@
         
+  
+  
 ms.laten
@@ -2596,24 +2596,28 @@
  ).call();%0A%0A
+    
             
@@ -2686,34 +2686,40 @@
                 
-%7B%0A
+    %7B%0A  
                 
@@ -2722,16 +2722,18 @@
         
+  
 ms.error
@@ -2736,16 +2736,20 @@
 rror();%0A
+    
         
@@ -2774,12 +2774,30 @@
     
-%7D );
+    %7D );%0A            %7D
 %0A%0A  

fix NPE in tests where sliMetrics aren't available