/*
 * Copyright 2017 Netflix, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.netflix.spinnaker.gate.interceptors;

import static net.logstash.logback.argument.StructuredArguments.value;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.util.ContentCachingResponseWrapper;

public class RequestLoggingInterceptor extends HandlerInterceptorAdapter {

  private Logger log = LoggerFactory.getLogger(getClass());

  @Override
  public void afterCompletion(
      HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
      throws Exception {
    // 127.0.0.1 "GET /limecat.jpg HTTP/1.0" 200 2326
    log.debug(
        "{} \"{} {} {}\" {} {}",
        value("sourceIp", sourceIpAddress(request)),
        value("requestMethod", request.getMethod()),
        value("requestEndpoint", getRequestEndpoint(request)),
        value("requestProtocol", request.getProtocol()),
        value("responseStatus", response.getStatus()),
        value("responseSize", getResponseSize(response)));
  }

  private static String sourceIpAddress(HttpServletRequest request) {
    String ip = request.getHeader("X-FORWARDED-FOR");
    if (ip == null) {
      return request.getRemoteAddr();
    }
    return ip;
  }

  private static String getRequestEndpoint(HttpServletRequest request) {
    String endpoint = request.getRequestURI();
    if (request.getQueryString() != null) {
      return endpoint + "?" + request.getQueryString();
    }
    return endpoint;
  }

  private static int getResponseSize(HttpServletResponse response) {
    if (response instanceof ContentCachingResponseWrapper) {
      return ((ContentCachingResponseWrapper) response).getContentAsByteArray().length;
    }
    return -1;
  }
}

@@ -711,16 +711,54 @@
 value;%0A%0A
+import java.util.concurrent.TimeUnit;%0A
 import j
@@ -899,16 +899,38 @@
 actory;%0A
+import org.slf4j.MDC;%0A
 import o
@@ -1137,16 +1137,77 @@
 dapter %7B
+%0A  static final String TIMER_ATTRIBUTE = %22Request_startTime%22;
 %0A%0A  priv
@@ -1261,16 +1261,238 @@
 ss());%0A%0A
+  @Override%0A  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)%0A      throws Exception %7B%0A    request.setAttribute(TIMER_ATTRIBUTE, System.nanoTime());%0A    return true;%0A  %7D%0A%0A
   @Overr
@@ -1619,39 +1619,16 @@
 tion ex)
-%0A      throws Exception
  %7B%0A    /
@@ -1676,16 +1676,91 @@
 00 2326%0A
+    try %7B%0A      MDC.put(%22requestDuration%22, getRequestDuration(request));%0A  
     log.
@@ -1766,16 +1766,18 @@
 .debug(%0A
+  
         
@@ -1801,16 +1801,18 @@
 %7B%7D %7B%7D%22,%0A
+  
         
@@ -1856,32 +1856,34 @@
 uest)),%0A        
+ 
+ 
 value(%22requestMe
@@ -1907,24 +1907,26 @@
 tMethod()),%0A
+  
         valu
@@ -1968,32 +1968,34 @@
 oint(request)),%0A
+  
         value(%22r
@@ -2035,32 +2035,34 @@
 col()),%0A        
+  
 value(%22responseS
@@ -2088,24 +2088,26 @@
 tStatus()),%0A
+  
         valu
@@ -2153,16 +2153,356 @@
 nse)));%0A
+    %7D finally %7B%0A      MDC.remove(%22requestDuration%22);%0A    %7D%0A  %7D%0A%0A  private static String getRequestDuration(HttpServletRequest request) %7B%0A    Long startTime = (Long) request.getAttribute(TIMER_ATTRIBUTE);%0A    if (startTime == null) %7B%0A      return %22n/a%22;%0A    %7D%0A%0A    return TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + %22ms%22;%0A
   %7D%0A%0A  p

Add 'requestDuration' to MDC (#838)