use logging interceptor in SDC client
[vid.git] / vid-app-common / src / main / java / org / onap / vid / logging / VidLoggerAspect.java
index 514779f..f87297c 100644 (file)
 
 package org.onap.vid.logging;
 
+import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;
+import static org.apache.commons.lang3.StringUtils.defaultIfEmpty;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import javax.servlet.http.HttpServletRequest;
 import org.apache.commons.lang3.StringUtils;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Pointcut;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
 import org.onap.portalsdk.core.logging.aspect.EELFLoggerAdvice;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.onap.portalsdk.core.service.AppService;
 import org.onap.portalsdk.core.util.SystemProperties;
+import org.onap.portalsdk.core.web.support.UserUtils;
+import org.onap.vid.controller.ControllersUtils;
+import org.onap.vid.utils.SystemPropertiesWrapper;
+import org.slf4j.MDC;
 import org.springframework.beans.factory.annotation.Autowired;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
 
 
 @Aspect
@@ -41,10 +51,14 @@ import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;
 public class VidLoggerAspect {
 
     private String canonicalHostName;
-    @Autowired
-    EELFLoggerAdvice advice;
+    private final ControllersUtils controllersUtils;
+    private final String appName;
 
-    public VidLoggerAspect() {
+    private final EELFLoggerAdvice advice;
+
+    @Autowired
+    public VidLoggerAspect(EELFLoggerAdvice advice, SystemPropertiesWrapper systemPropertiesWrapper,
+        AppService appService) {
         try {
             final InetAddress localHost = InetAddress.getLocalHost();
             canonicalHostName = localHost.getCanonicalHostName();
@@ -52,9 +66,13 @@ public class VidLoggerAspect {
             // YOLO
             canonicalHostName = null;
         }
+        this.advice = advice;
+        this.controllersUtils = new ControllersUtils(systemPropertiesWrapper);
+
+        this.appName = defaultIfEmpty(appService.getDefaultAppName(), SystemProperties.SDK_NAME);
     }
 
-    @Pointcut("execution(public * org.onap.vid.controller.*Controller.*(..))")
+    @Pointcut("execution(public * org.onap.vid.controller..*Controller.*(..))")
     public void vidControllers() {}
 
     @Around("vidControllers() && (" +
@@ -69,8 +87,12 @@ public class VidLoggerAspect {
     private Object logAroundMethod(ProceedingJoinPoint joinPoint, SystemProperties.SecurityEventTypeEnum securityEventType) throws Throwable {
         //Before
         Object[] passOnArgs = new Object[] {joinPoint.getSignature().getDeclaringType().getName(),joinPoint.getSignature().getName()};
-        Object[] returnArgs = advice.before(securityEventType, joinPoint.getArgs(), passOnArgs);
+        Object[] returnArgs = advice.before(securityEventType, fabricateArgsWithNull(), passOnArgs);
 
+        HttpServletRequest httpServletRequest = httpServletRequestOrNull(joinPoint);
+        fixSetRequestBasedDefaultsIntoGlobalLoggingContext(httpServletRequest,
+            joinPoint.getSignature().getDeclaringType().getName());
+        addRequestIdToMdcForMetricFilter(httpServletRequest);
         fixServerFqdnInMDC();
 
         //Execute the actual method
@@ -89,11 +111,65 @@ public class VidLoggerAspect {
         return result;
     }
 
+    //prepare MDC for org.onap.logging.filter.base.AbstractMetricLogFilter
+    private void addRequestIdToMdcForMetricFilter(HttpServletRequest httpServletRequest) {
+        if (httpServletRequest!=null) {
+            String requestId = UserUtils.getRequestId(httpServletRequest);
+            MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, requestId);
+        }
+    }
+
     // Set the status code into MDC *before* the metrics log is written by advice.after()
     private void fixStatusCodeInMDC(String restStatus) {
         EELFLoggerDelegate.mdcPut(SystemProperties.STATUS_CODE, restStatus);
     }
 
+    /**
+     * Returns an array with a single entry with a null value. This will stop org.onap.portalsdk.core.logging.aspect.EELFLoggerAdvice.before
+     * from throwing on ArrayIndexOutOfBound, and also prevent SessionExpiredException.
+     */
+    private Object[] fabricateArgsWithNull() {
+        return new Object[]{null};
+    }
+
+    /**
+     * Finds the first joinPoint's param which is an HttpServletRequest. If not found, use Spring's RequestContextHolder
+     * to retrieve it.
+     *
+     * @return null or the current httpServletRequest
+     */
+    private HttpServletRequest httpServletRequestOrNull(ProceedingJoinPoint joinPoint) {
+        final Object httpServletRequest = Arrays.stream(joinPoint.getArgs())
+            .filter(param -> param instanceof HttpServletRequest)
+            .findFirst()
+            .orElseGet(() -> {
+                try {
+                    return ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
+                } catch (Exception e) { // ClassCast, IllegalState, etc.
+                    return null;
+                }
+            });
+
+        return (HttpServletRequest) httpServletRequest;
+    }
+
+    /**
+     * Mimics a part from org.onap.portalsdk.core.logging.aspect.EELFLoggerAdvice.before, but with much more carefulness
+     * of exceptions and defaults. Main difference is that if no session, function does not throw. It just fallback to
+     * an empty loginId.
+     */
+    private void fixSetRequestBasedDefaultsIntoGlobalLoggingContext(HttpServletRequest httpServletRequest, String className) {
+        if (httpServletRequest != null) {
+
+            EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(className);
+            String requestId = UserUtils.getRequestId(httpServletRequest);
+            String loginId = controllersUtils.extractUserId(httpServletRequest);
+
+            logger.setRequestBasedDefaultsIntoGlobalLoggingContext(httpServletRequest, appName, requestId, loginId);
+
+        }
+    }
+
     // Override the non-canonical hostname set by EELFLoggerDelegate::setGlobalLoggingContext()
     // that was invoked by advice.before() (and some other SDK cases)
     private void fixServerFqdnInMDC() {