diff options
author | mojahidi <mojahidul.islam@amdocs.com> | 2018-07-18 15:14:50 +0530 |
---|---|---|
committer | mojahidi <mojahidul.islam@amdocs.com> | 2018-07-19 13:52:31 +0530 |
commit | c2e03cb65ddca44c66616b2fd32455866c5eafa5 (patch) | |
tree | 2593eafc09983ef34b620d8186905b73ae7157c4 | |
parent | cf576292b7c646854da61a383748bb839dfda233 (diff) |
Add Logging support for WF
Reverted changes of application.properties
Added logging supprt for workflow application
Change-Id: Ibdefa1f2bb42c4182821a95f130a7c3f3a01a7d9
Issue-ID: SDC-1530
Signed-off-by: mojahidi <mojahidul.islam@amdocs.com>
6 files changed, 376 insertions, 0 deletions
diff --git a/workflow/workflow-designer-be/pom.xml b/workflow/workflow-designer-be/pom.xml index b76dc467..3a88d4c0 100644 --- a/workflow/workflow-designer-be/pom.xml +++ b/workflow/workflow-designer-be/pom.xml @@ -75,6 +75,12 @@ </dependency> <dependency> <groupId>org.openecomp.sdc</groupId> + <artifactId>openecomp-sdc-logging-core</artifactId> + <version>${onap.version}</version> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>org.openecomp.sdc</groupId> <artifactId>openecomp-sdc-versioning-api</artifactId> <version>${onap.version}</version> </dependency> diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/logging/LoggingInterceptor.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/logging/LoggingInterceptor.java new file mode 100644 index 00000000..f5731125 --- /dev/null +++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/logging/LoggingInterceptor.java @@ -0,0 +1,40 @@ +package org.onap.sdc.workflow.logging; + +import org.onap.sdc.workflow.logging.utils.LoggingUtils; +import org.openecomp.sdc.logging.api.LoggingContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.lang.Nullable; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; +import org.springframework.web.util.ContentCachingResponseWrapper; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@Component +public class LoggingInterceptor extends HandlerInterceptorAdapter { + + @Autowired + LoggingUtils loggingUtils; + + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, + @Nullable Exception ex) throws Exception { + if (!(response instanceof ContentCachingResponseWrapper)) { + response = new ContentCachingResponseWrapper(response); + } + try { + loggingUtils.logResponse(request, response); + } finally { + LoggingContext.clear(); + } + } + + @Override + public boolean preHandle(HttpServletRequest request, + HttpServletResponse response, Object object) throws Exception { + request.setAttribute(LoggingUtils.START_TIME_KEY, System.currentTimeMillis()); + loggingUtils.logRequest(request); + return true; + } + +} diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/logging/config/InterceptorConfig.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/logging/config/InterceptorConfig.java new file mode 100644 index 00000000..a7d46171 --- /dev/null +++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/logging/config/InterceptorConfig.java @@ -0,0 +1,19 @@ +package org.onap.sdc.workflow.logging.config; + +import org.onap.sdc.workflow.logging.LoggingInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class InterceptorConfig implements WebMvcConfigurer { + + @Autowired + LoggingInterceptor loggingInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(loggingInterceptor); + } +} diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/logging/utils/LoggingUtils.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/logging/utils/LoggingUtils.java new file mode 100644 index 00000000..10e4fb7e --- /dev/null +++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/logging/utils/LoggingUtils.java @@ -0,0 +1,87 @@ +package org.onap.sdc.workflow.logging.utils; + +import org.openecomp.sdc.logging.api.AuditData; +import org.openecomp.sdc.logging.api.ContextData; +import org.openecomp.sdc.logging.api.LoggerFactory; +import org.openecomp.sdc.logging.api.LoggingContext; +import org.openecomp.sdc.logging.api.StatusCode; +import org.openecomp.sdc.logging.servlet.HttpHeader; +import org.springframework.stereotype.Component; +import org.openecomp.sdc.logging.api.Logger; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.UUID; + +import static org.openecomp.sdc.logging.LoggingConstants.DEFAULT_PARTNER_NAME_HEADER; +import static org.openecomp.sdc.logging.LoggingConstants.DEFAULT_REQUEST_ID_HEADER; +import static org.openecomp.sdc.logging.api.StatusCode.COMPLETE; +import static org.openecomp.sdc.logging.api.StatusCode.ERROR; + +@Component +public class LoggingUtils { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + public static final String START_TIME_KEY = "audit.start.time"; + private HttpHeader requestIdHeader = new HttpHeader(DEFAULT_REQUEST_ID_HEADER); + private HttpHeader partnerNameHeader = new HttpHeader(DEFAULT_PARTNER_NAME_HEADER); + + public void logResponse(HttpServletRequest request, HttpServletResponse response) { + writeAudit(request, response); + } + + private StatusCode getStatusCode(HttpServletResponse response) { + return isSuccess(response.getStatus()) ? COMPLETE : ERROR; + } + + private String getReasonPhrase(int code) { + return Status.getReason(code); + } + + private long getStartTime(HttpServletRequest request) { + return Long.class.cast(request.getAttribute(START_TIME_KEY)); + } + public void logRequest(HttpServletRequest request) { + LoggingContext.clear(); + ContextData.ContextDataBuilder contextData = ContextData.builder(); + contextData.serviceName(createServiceName(request)); + + String partnerName = partnerNameHeader.getAny(request::getHeader); + if (partnerName != null) { + contextData.partnerName(partnerName); + } + + String requestId = requestIdHeader.getAny(request::getHeader); + contextData.requestId(requestId == null ? UUID.randomUUID().toString() : requestId); + + LoggingContext.put(contextData.build()); + } + + private String createServiceName(HttpServletRequest request) { + return request.getMethod() + " " + request.getServletPath(); + } + + private void writeAudit(HttpServletRequest request, + HttpServletResponse response) { + + if (!logger.isAuditEnabled()) { + return; + } + + long start = getStartTime(request); + long end = System.currentTimeMillis(); + + int responseCode = response.getStatus(); + StatusCode statusCode = getStatusCode(response); + AuditData auditData = AuditData.builder() + .startTime(start) + .endTime(end) + .statusCode(statusCode) + .responseCode(Integer.toString(responseCode)) + .responseDescription(getReasonPhrase(responseCode)) + .clientIpAddress(request.getRemoteAddr()).build(); + logger.audit(auditData); + } + + private boolean isSuccess(int responseCode) { + return responseCode > 199 && responseCode < 400; + } +} diff --git a/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/logging/utils/Status.java b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/logging/utils/Status.java new file mode 100644 index 00000000..07ca8725 --- /dev/null +++ b/workflow/workflow-designer-be/src/main/java/org/onap/sdc/workflow/logging/utils/Status.java @@ -0,0 +1,57 @@ +package org.onap.sdc.workflow.logging.utils; + +public enum Status { + OK(200, "OK"), + CREATED(201, "Created"), + ACCEPTED(202, "Accepted"), + NO_CONTENT(204, "No Content"), + RESET_CONTENT(205, "Reset Content"), + PARTIAL_CONTENT(206, "Partial Content"), + MOVED_PERMANENTLY(301, "Moved Permanently"), + FOUND(302, "Found"), + SEE_OTHER(303, "See Other"), + NOT_MODIFIED(304, "Not Modified"), + USE_PROXY(305, "Use Proxy"), + TEMPORARY_REDIRECT(307, "Temporary Redirect"), + BAD_REQUEST(400, "Bad Request"), + UNAUTHORIZED(401, "Unauthorized"), + PAYMENT_REQUIRED(402, "Payment Required"), + FORBIDDEN(403, "Forbidden"), + NOT_FOUND(404, "Not Found"), + METHOD_NOT_ALLOWED(405, "Method Not Allowed"), + NOT_ACCEPTABLE(406, "Not Acceptable"), + PROXY_AUTHENTICATION_REQUIRED(407, "Proxy Authentication Required"), + REQUEST_TIMEOUT(408, "Request Timeout"), + CONFLICT(409, "Conflict"), + GONE(410, "Gone"), + LENGTH_REQUIRED(411, "Length Required"), + PRECONDITION_FAILED(412, "Precondition Failed"), + REQUEST_ENTITY_TOO_LARGE(413, "Request Entity Too Large"), + REQUEST_URI_TOO_LONG(414, "Request-URI Too Long"), + UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type"), + REQUESTED_RANGE_NOT_SATISFIABLE(416, "Requested Range Not Satisfiable"), + EXPECTATION_FAILED(417, "Expectation Failed"), + INTERNAL_SERVER_ERROR(500, "Internal Server Error"), + NOT_IMPLEMENTED(501, "Not Implemented"), + BAD_GATEWAY(502, "Bad Gateway"), + SERVICE_UNAVAILABLE(503, "Service Unavailable"), + GATEWAY_TIMEOUT(504, "Gateway Timeout"), + HTTP_VERSION_NOT_SUPPORTED(505, "HTTP Version Not Supported"); + + private final int code; + private final String reason; + + Status(int statusCode, String reasonPhrase) { + this.code = statusCode; + this.reason = reasonPhrase; + } + + public static String getReason(int code) { + for(Status status : Status.values()) { + if(status.code == code) + return status.reason; + } + return null; + } + +} diff --git a/workflow/workflow-designer-be/src/main/resources/logback.xml b/workflow/workflow-designer-be/src/main/resources/logback.xml new file mode 100644 index 00000000..6f33b864 --- /dev/null +++ b/workflow/workflow-designer-be/src/main/resources/logback.xml @@ -0,0 +1,167 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<configuration scan="true" scanPeriod="5 seconds"> + <property scope="system" name="ONAP-component-name" value="workflow-designer" /> + <property scope="system" name="ONAP-subcomponent-name" value="be" /> + <property name="log.location" value="logs"/> + + + <!-- Error log --> + <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"> + + <file>${log.location}/error.log</file> + + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>INFO</level> + </filter> + + <filter class="ch.qos.logback.core.filter.EvaluatorFilter"> + <evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator"> + <marker>AUDIT</marker> + </evaluator> + <onMismatch>NEUTRAL</onMismatch> + <onMatch>DENY</onMatch> + </filter> + + <filter class="ch.qos.logback.core.filter.EvaluatorFilter"> + <evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator"> + <marker>METRICS</marker> + </evaluator> + <onMismatch>NEUTRAL</onMismatch> + <onMatch>DENY</onMatch> + </filter> + + <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${log.location}/error.log.%i + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>10</maxIndex> + </rollingPolicy> + + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>20MB</maxFileSize> + </triggeringPolicy> + + <encoder> + <pattern> + %d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%X{RequestId}|%thread||%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%level||%X{ErrorCode}|%X{ErrorDescription}|%msg%n + </pattern> + </encoder> + </appender> + + + <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender"> + + <file>${log.location}/debug.log</file> + + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>DEBUG</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + + <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${log.location}/debug.log.%i + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>10</maxIndex> + </rollingPolicy> + + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>20MB</maxFileSize> + </triggeringPolicy> + + <encoder> + <pattern> + %d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%X{RequestId}|%msg%n + </pattern> + </encoder> + </appender> + + <!-- Asynchronicity Configurations --> + <appender name="ASYNC_DEBUG" class="ch.qos.logback.classic.AsyncAppender"> + <appender-ref ref="DEBUG" /> + </appender> + + <appender name="AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender"> + + <file>${log.location}/audit.log</file> + + <filter class="ch.qos.logback.core.filter.EvaluatorFilter"> + <evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator"> + <marker>AUDIT</marker> + </evaluator> + <onMismatch>DENY</onMismatch> + <onMatch>ACCEPT</onMatch> + </filter> + + <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${log.location}/audit.log.%i + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>10</maxIndex> + </rollingPolicy> + + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>20MB</maxFileSize> + </triggeringPolicy> + + <encoder> + <pattern> + %X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread||%X{ServiceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceId}|%level||%X{ServerIpAddress}|%X{ElapsedTime}|%X{Server}|%X{ClientIpAddress}||||||||%msg%n + </pattern> + </encoder> + </appender> + + <appender name="METRICS" class="ch.qos.logback.core.rolling.RollingFileAppender"> + + <file>${log.location}/metrics.log</file> + + <filter class="ch.qos.logback.core.filter.EvaluatorFilter"> + <evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator"> + <marker>METRICS</marker> + </evaluator> + <onMismatch>DENY</onMismatch> + <onMatch>ACCEPT</onMatch> + </filter> + + <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> + <fileNamePattern>${log.location}/metrics.log.%i + </fileNamePattern> + <minIndex>1</minIndex> + <maxIndex>10</maxIndex> + </rollingPolicy> + + <triggeringPolicy + class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> + <maxFileSize>20MB</maxFileSize> + </triggeringPolicy> + + <encoder> + <pattern> + %X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread||%X{ServiceName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceId}|%level||%X{ServerIpAddress}|%X{ElapsedTime}|%X{Server}|%X{ClientIpAddress}||||||||||%msg%n + </pattern> + </encoder> + </appender> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern> + %X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestId}|%X{ServiceInstanceId}|%thread||%X{ServiceName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceId}|%level||%X{ServerIpAddress}|%X{ElapsedTime}|%X{Server}|%X{ClientIpAddress}||||||||||%msg%n + </pattern> + </encoder> + </appender> + + <root level="INFO"> + <appender-ref ref="ERROR"/> + <appender-ref ref="ASYNC_DEBUG"/> + <appender-ref ref="AUDIT"/> + <appender-ref ref="METRICS"/> + <appender-ref ref="STDOUT"/> + </root> + <logger name="org.springframework.web.filter.CommonsRequestLoggingFilter"> + <level value="DEBUG" /> + </logger> +</configuration>
\ No newline at end of file |