2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.vid.logging;
23 import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;
24 import static org.apache.commons.lang3.StringUtils.defaultIfEmpty;
26 import java.net.InetAddress;
27 import java.net.UnknownHostException;
28 import java.util.Arrays;
29 import javax.servlet.http.HttpServletRequest;
30 import org.apache.commons.lang3.StringUtils;
31 import org.aspectj.lang.ProceedingJoinPoint;
32 import org.aspectj.lang.annotation.Around;
33 import org.aspectj.lang.annotation.Aspect;
34 import org.aspectj.lang.annotation.Pointcut;
35 import org.onap.logging.ref.slf4j.ONAPLogConstants;
36 import org.onap.portalsdk.core.logging.aspect.EELFLoggerAdvice;
37 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
38 import org.onap.portalsdk.core.service.AppService;
39 import org.onap.portalsdk.core.util.SystemProperties;
40 import org.onap.portalsdk.core.web.support.UserUtils;
41 import org.onap.vid.controller.ControllersUtils;
42 import org.onap.vid.utils.SystemPropertiesWrapper;
44 import org.springframework.beans.factory.annotation.Autowired;
45 import org.springframework.web.context.request.RequestContextHolder;
46 import org.springframework.web.context.request.ServletRequestAttributes;
50 @org.springframework.context.annotation.Configuration
51 public class VidLoggerAspect {
53 private String canonicalHostName;
54 private final ControllersUtils controllersUtils;
55 private final String appName;
57 private final EELFLoggerAdvice advice;
60 public VidLoggerAspect(EELFLoggerAdvice advice, SystemPropertiesWrapper systemPropertiesWrapper,
61 AppService appService) {
63 final InetAddress localHost = InetAddress.getLocalHost();
64 canonicalHostName = localHost.getCanonicalHostName();
65 } catch (UnknownHostException e) {
67 canonicalHostName = null;
70 this.controllersUtils = new ControllersUtils(systemPropertiesWrapper);
72 this.appName = defaultIfEmpty(appService.getDefaultAppName(), SystemProperties.SDK_NAME);
75 @Pointcut("execution(public * org.onap.vid.controller..*Controller.*(..))")
76 public void vidControllers() {}
78 @Around("vidControllers() && (" +
79 " @within(org.onap.portalsdk.core.logging.aspect.AuditLog)" +
80 " || @annotation(org.onap.portalsdk.core.logging.aspect.AuditLog)" +
81 " || @annotation(org.springframework.web.bind.annotation.RequestMapping)" +
83 public Object logAuditMethodClassAround(ProceedingJoinPoint joinPoint) throws Throwable {
84 return logAroundMethod(joinPoint, SystemProperties.SecurityEventTypeEnum.INCOMING_REST_MESSAGE);
87 private Object logAroundMethod(ProceedingJoinPoint joinPoint, SystemProperties.SecurityEventTypeEnum securityEventType) throws Throwable {
89 Object[] passOnArgs = new Object[] {joinPoint.getSignature().getDeclaringType().getName(),joinPoint.getSignature().getName()};
90 Object[] returnArgs = advice.before(securityEventType, fabricateArgsWithNull(), passOnArgs);
92 HttpServletRequest httpServletRequest = httpServletRequestOrNull(joinPoint);
93 fixSetRequestBasedDefaultsIntoGlobalLoggingContext(httpServletRequest,
94 joinPoint.getSignature().getDeclaringType().getName());
95 addRequestIdToMdcForMetricFilter(httpServletRequest);
98 //Execute the actual method
100 String restStatus = "COMPLETE";
102 result = joinPoint.proceed();
103 } catch(Exception e) {
104 restStatus = "ERROR";
107 fixStatusCodeInMDC(restStatus);
108 advice.after(securityEventType, restStatus, joinPoint.getArgs(), returnArgs, passOnArgs);
114 //prepare MDC for org.onap.logging.filter.base.AbstractMetricLogFilter
115 private void addRequestIdToMdcForMetricFilter(HttpServletRequest httpServletRequest) {
116 if (httpServletRequest!=null) {
117 String requestId = UserUtils.getRequestId(httpServletRequest);
118 MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, requestId);
122 // Set the status code into MDC *before* the metrics log is written by advice.after()
123 private void fixStatusCodeInMDC(String restStatus) {
124 EELFLoggerDelegate.mdcPut(SystemProperties.STATUS_CODE, restStatus);
128 * Returns an array with a single entry with a null value. This will stop org.onap.portalsdk.core.logging.aspect.EELFLoggerAdvice.before
129 * from throwing on ArrayIndexOutOfBound, and also prevent SessionExpiredException.
131 private Object[] fabricateArgsWithNull() {
132 return new Object[]{null};
136 * Finds the first joinPoint's param which is an HttpServletRequest. If not found, use Spring's RequestContextHolder
139 * @return null or the current httpServletRequest
141 private HttpServletRequest httpServletRequestOrNull(ProceedingJoinPoint joinPoint) {
142 final Object httpServletRequest = Arrays.stream(joinPoint.getArgs())
143 .filter(param -> param instanceof HttpServletRequest)
147 return ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
148 } catch (Exception e) { // ClassCast, IllegalState, etc.
153 return (HttpServletRequest) httpServletRequest;
157 * Mimics a part from org.onap.portalsdk.core.logging.aspect.EELFLoggerAdvice.before, but with much more carefulness
158 * of exceptions and defaults. Main difference is that if no session, function does not throw. It just fallback to
161 private void fixSetRequestBasedDefaultsIntoGlobalLoggingContext(HttpServletRequest httpServletRequest, String className) {
162 if (httpServletRequest != null) {
164 EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(className);
165 String requestId = UserUtils.getRequestId(httpServletRequest);
166 String loginId = controllersUtils.extractUserId(httpServletRequest);
168 logger.setRequestBasedDefaultsIntoGlobalLoggingContext(httpServletRequest, appName, requestId, loginId);
173 // Override the non-canonical hostname set by EELFLoggerDelegate::setGlobalLoggingContext()
174 // that was invoked by advice.before() (and some other SDK cases)
175 private void fixServerFqdnInMDC() {
176 if (!StringUtils.isBlank(canonicalHostName)) {
177 EELFLoggerDelegate.mdcPut(MDC_SERVER_FQDN, canonicalHostName);