From e2c77490982e448fb94477cebc5b7d4b8110321d Mon Sep 17 00:00:00 2001 From: "Smokowski, Steve (ss835w)" Date: Tue, 4 Sep 2018 15:31:38 -0400 Subject: Client Logging Update Client Logging to use interceptor Move CXF to own project due to dependency hell Issue-ID: SO-947 Change-Id: I2597ff6d32231b8625b04ef63ab5e8f589e2545c Signed-off-by: Smokowski, Steve (ss835w) --- .../main/java/org/onap/so/client/RestClient.java | 55 +++---- .../java/org/onap/so/client/RestClientSSL.java | 10 +- .../so/client/adapter/rest/AdapterRestClient.java | 2 +- .../org/onap/so/client/policy/LoggingFilter.java | 157 -------------------- .../cxf/interceptor/SOAPLoggingInInterceptor.java | 96 ------------ .../cxf/interceptor/SOAPLoggingOutInterceptor.java | 63 -------- .../logging/jaxrs/filter/JaxRsClientLogging.java | 163 ++++++++++++--------- .../logging/jaxrs/filter/PayloadLoggingFilter.java | 159 ++++++++++++++++++++ .../main/java/org/onap/so/utils/TargetEntity.java | 15 +- 9 files changed, 288 insertions(+), 432 deletions(-) delete mode 100644 common/src/main/java/org/onap/so/client/policy/LoggingFilter.java delete mode 100644 common/src/main/java/org/onap/so/logging/cxf/interceptor/SOAPLoggingInInterceptor.java delete mode 100644 common/src/main/java/org/onap/so/logging/cxf/interceptor/SOAPLoggingOutInterceptor.java create mode 100644 common/src/main/java/org/onap/so/logging/jaxrs/filter/PayloadLoggingFilter.java (limited to 'common/src/main/java') diff --git a/common/src/main/java/org/onap/so/client/RestClient.java b/common/src/main/java/org/onap/so/client/RestClient.java index cb8e1f0a91..007c666ac2 100644 --- a/common/src/main/java/org/onap/so/client/RestClient.java +++ b/common/src/main/java/org/onap/so/client/RestClient.java @@ -36,7 +36,6 @@ import java.util.Map.Entry; import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; - import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Invocation.Builder; @@ -46,29 +45,28 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriBuilder; - import org.onap.so.client.policy.CommonObjectMapperProvider; -import org.onap.so.client.policy.LoggingFilter; -import org.onap.so.logger.MsoLogger; import org.onap.so.logging.jaxrs.filter.JaxRsClientLogging; +import org.onap.so.logging.jaxrs.filter.PayloadLoggingFilter; import org.onap.so.utils.CryptoUtils; import org.onap.so.utils.TargetEntity; -import org.slf4j.MDC; - +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; - import net.jodah.failsafe.Failsafe; import net.jodah.failsafe.RetryPolicy; public abstract class RestClient { - public static final String ECOMP_COMPONENT_NAME = "MSO"; + private static final String APPLICATION_MERGE_PATCH_JSON = "application/merge-patch+json"; + + public static final String ECOMP_COMPONENT_NAME = "MSO"; private static final int MAX_PAYLOAD_SIZE = 1024 * 1024; private WebTarget webTarget; protected final Map headerMap; - protected final MsoLogger msoLogger; + protected final Logger logger = LoggerFactory.getLogger(RestClient.class); protected URL host; protected Optional path; protected String accept; @@ -79,11 +77,6 @@ public abstract class RestClient { protected RestClient(RestProperties props, Optional path) { - msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.GENERAL, RestClient.class); - this.requestId = MDC.get(MsoLogger.REQUEST_ID); - if (requestId == null) { - requestId = ""; - } headerMap = new HashMap<>(); try { host = props.getEndpoint(); @@ -99,24 +92,14 @@ public abstract class RestClient { this(props, path); this.accept = accept; this.contentType = contentType; - this.requestId = MDC.get(MsoLogger.REQUEST_ID); - if (requestId == null) { - requestId = ""; - } this.props = props; } protected RestClient(URL host, String contentType) { headerMap = new HashMap<>(); - - msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.GENERAL, RestClient.class); this.path = Optional.empty(); this.host = host; this.contentType = contentType; - this.requestId = MDC.get(MsoLogger.REQUEST_ID); - if (requestId == null) { - requestId = ""; - } this.props = new DefaultProperties(host); } @@ -143,15 +126,13 @@ public abstract class RestClient { if (webTarget == null) { initializeClient(getClient()); - } - Builder builder = webTarget.request(); - initializeHeaderMap(headerMap); - - headerMap.put("X-ECOMP-RequestID", requestId); - for (Entry entry : headerMap.entrySet()) { - builder.header(entry.getKey(), entry.getValue()); - } - return builder; + } + Builder builder = webTarget.request(); + initializeHeaderMap(headerMap); + for (Entry entry : headerMap.entrySet()) { + builder.header(entry.getKey(), entry.getValue()); + } + return builder; } protected WebTarget getWebTarget() { @@ -179,7 +160,7 @@ public abstract class RestClient { String authHeaderValue = "Basic " + Base64.getEncoder().encodeToString(decryptedAuth); headerMap.put("Authorization", authHeaderValue); } catch (GeneralSecurityException e) { - msoLogger.error(e.getMessage(), e); + logger.error(e.getMessage(), e); } } @@ -192,7 +173,7 @@ public abstract class RestClient { } protected String getMergeContentType() { - return "application/merge-patch+json"; + return APPLICATION_MERGE_PATCH_JSON; } protected Client getClient() { @@ -203,11 +184,11 @@ public abstract class RestClient { protected void initializeClient(Client client) { if (this.enableLogging()) { - client.register(new LoggingFilter(this.getMaxPayloadSize())); + client.register(new PayloadLoggingFilter(this.getMaxPayloadSize())); } CommonObjectMapperProvider provider = this.getCommonObjectMapperProvider(); client.register(new JacksonJsonProvider(provider.getMapper())); - + jaxRsClientLogging = new JaxRsClientLogging(); jaxRsClientLogging.setTargetService(getTargetEntity()); client.register(jaxRsClientLogging); diff --git a/common/src/main/java/org/onap/so/client/RestClientSSL.java b/common/src/main/java/org/onap/so/client/RestClientSSL.java index 8eaeee97ee..cb2839ae1f 100644 --- a/common/src/main/java/org/onap/so/client/RestClientSSL.java +++ b/common/src/main/java/org/onap/so/client/RestClientSSL.java @@ -32,7 +32,8 @@ import javax.ws.rs.client.ClientBuilder; public abstract class RestClientSSL extends RestClient { - public static final String SSL_KEY_STORE_KEY = "javax.net.ssl.keyStore"; + private static final String TRUE = "true"; + public static final String SSL_KEY_STORE_KEY = "javax.net.ssl.keyStore"; public static final String SSL_KEY_STORE_PASSWORD_KEY = "javax.net.ssl.keyStorePassword"; public static final String MSO_LOAD_SSL_CLIENT_KEYSTORE_KEY = "mso.load.ssl.client.keystore"; @@ -51,19 +52,18 @@ public abstract class RestClientSSL extends RestClient { Client client = null; try { String loadSSLKeyStore = System.getProperty(RestClientSSL.MSO_LOAD_SSL_CLIENT_KEYSTORE_KEY); - if(loadSSLKeyStore != null && loadSSLKeyStore.equalsIgnoreCase("true")) { + if(loadSSLKeyStore != null && loadSSLKeyStore.equalsIgnoreCase(TRUE)) { KeyStore ks = getKeyStore(); if(ks != null) { client = ClientBuilder.newBuilder().keyStore(ks, System.getProperty(RestClientSSL.SSL_KEY_STORE_PASSWORD_KEY)).build(); - this.msoLogger.debug("RestClientSSL not using default SSL context - setting keystore here."); + logger.debug("RestClientSSL not using default SSL context - setting keystore here."); return client; } } //Use default SSL context client = ClientBuilder.newBuilder().sslContext(SSLContext.getDefault()).build(); - this.msoLogger.debug("RestClientSSL using default SSL context!"); + logger.info("RestClientSSL using default SSL context!"); } catch (NoSuchAlgorithmException e) { - //this.logger.error(MessageEnum.APIH_GENERAL_EXCEPTION, "AAI", "Client init", MsoLogger.ErrorCode.UnknownError, "could not create SSL client", e); throw new RuntimeException(e); } return client; diff --git a/common/src/main/java/org/onap/so/client/adapter/rest/AdapterRestClient.java b/common/src/main/java/org/onap/so/client/adapter/rest/AdapterRestClient.java index 2329a5acb9..9d72fdf85b 100644 --- a/common/src/main/java/org/onap/so/client/adapter/rest/AdapterRestClient.java +++ b/common/src/main/java/org/onap/so/client/adapter/rest/AdapterRestClient.java @@ -72,7 +72,7 @@ public class AdapterRestClient extends RestClient { encodedString = "Basic " + encodedString; return encodedString; } catch (GeneralSecurityException e) { - this.msoLogger.debug(e.getMessage()); + logger.error(e.getMessage(),e); return null; } } diff --git a/common/src/main/java/org/onap/so/client/policy/LoggingFilter.java b/common/src/main/java/org/onap/so/client/policy/LoggingFilter.java deleted file mode 100644 index 83cf08f77f..0000000000 --- a/common/src/main/java/org/onap/so/client/policy/LoggingFilter.java +++ /dev/null @@ -1,157 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - SO - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.so.client.policy; - -import java.io.BufferedInputStream; -import java.io.ByteArrayOutputStream; -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; - -import javax.annotation.Priority; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.client.ClientRequestContext; -import javax.ws.rs.client.ClientRequestFilter; -import javax.ws.rs.client.ClientResponseContext; -import javax.ws.rs.client.ClientResponseFilter; -import javax.ws.rs.ext.Provider; -import javax.ws.rs.ext.WriterInterceptor; -import javax.ws.rs.ext.WriterInterceptorContext; - -import org.onap.so.logger.MsoLogger; - - -@Provider -@Priority(0) -public class LoggingFilter implements ClientRequestFilter, ClientResponseFilter, WriterInterceptor { - - private static final MsoLogger logger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, LoggingFilter.class); - private static final String ENTITY_STREAM_PROPERTY = "LoggingFilter.entityStream"; - private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; - private final int maxEntitySize; - - public LoggingFilter() { - maxEntitySize = 1024 * 1024; - } - - public LoggingFilter(int maxPayloadSize) { - this.maxEntitySize = Integer.min(maxPayloadSize, 1024 * 1024); - } - - private void log(StringBuilder sb) { - logger.debug(sb.toString()); - } - - protected InputStream logInboundEntity(final StringBuilder b, InputStream stream, final Charset charset) - throws IOException { - if (!stream.markSupported()) { - stream = new BufferedInputStream(stream); - } - stream.mark(maxEntitySize + 1); - final byte[] entity = new byte[maxEntitySize + 1]; - final int entitySize = stream.read(entity); - if (entitySize != -1) { - b.append(new String(entity, 0, Math.min(entitySize, maxEntitySize), charset)); - } - if (entitySize > maxEntitySize) { - b.append("...more..."); - } - b.append('\n'); - stream.reset(); - return stream; - } - - @Override - public void filter(ClientRequestContext requestContext) throws IOException { - if (requestContext.hasEntity()) { - final OutputStream stream = new LoggingStream(requestContext.getEntityStream()); - requestContext.setEntityStream(stream); - requestContext.setProperty(ENTITY_STREAM_PROPERTY, stream); - } - String method = formatMethod(requestContext); - log(new StringBuilder("Making " + method + " request to: " + requestContext.getUri() + "\nRequest Headers: " + requestContext.getHeaders().toString())); - - } - - @Override - public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException { - final StringBuilder sb = new StringBuilder(); - if (responseContext.hasEntity()) { - responseContext.setEntityStream(logInboundEntity(sb, responseContext.getEntityStream(), DEFAULT_CHARSET)); - String method = formatMethod(requestContext); - log(sb.insert(0, "Response from " + method + ": " + requestContext.getUri() + "\nResponse Headers: " + responseContext.getHeaders().toString())); - } - } - - @Override - public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException { - final LoggingStream stream = (LoggingStream) context.getProperty(ENTITY_STREAM_PROPERTY); - context.proceed(); - if (stream != null) { - log(stream.getStringBuilder(DEFAULT_CHARSET)); - } - } - - private class LoggingStream extends FilterOutputStream { - - private final StringBuilder sb = new StringBuilder(); - private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - LoggingStream(OutputStream out) { - super(out); - } - - StringBuilder getStringBuilder(Charset charset) { - // write entity to the builder - final byte[] entity = baos.toByteArray(); - - sb.append(new String(entity, 0, entity.length, charset)); - if (entity.length > maxEntitySize) { - sb.append("...more..."); - } - sb.append('\n'); - - return sb; - } - - @Override - public void write(final int i) throws IOException { - if (baos.size() <= maxEntitySize) { - baos.write(i); - } - out.write(i); - } - } - - private String formatMethod(ClientRequestContext requestContext) { - String method = requestContext.getHeaderString("X-HTTP-Method-Override"); - if (method == null) { - method = requestContext.getMethod(); - } else { - method = requestContext.getMethod() + " (overridden to " + method + ")"; - } - - return method; - } -} \ No newline at end of file diff --git a/common/src/main/java/org/onap/so/logging/cxf/interceptor/SOAPLoggingInInterceptor.java b/common/src/main/java/org/onap/so/logging/cxf/interceptor/SOAPLoggingInInterceptor.java deleted file mode 100644 index 9aed537668..0000000000 --- a/common/src/main/java/org/onap/so/logging/cxf/interceptor/SOAPLoggingInInterceptor.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.onap.so.logging.cxf.interceptor; - - -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.xml.namespace.QName; -import org.apache.cxf.binding.soap.SoapMessage; -import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor; -import org.apache.cxf.interceptor.Fault; -import org.apache.cxf.message.Message; -import org.apache.cxf.phase.Phase; -import org.apache.cxf.service.model.MessageInfo; -import org.apache.cxf.service.model.OperationInfo; -import org.apache.cxf.transport.http.AbstractHTTPDestination; -import org.onap.logging.ref.slf4j.ONAPLogConstants; -import org.onap.so.logging.jaxrs.filter.JaxRsFilterLogging; -import org.onap.so.logging.jaxrs.filter.MDCSetup; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Component -public class SOAPLoggingInInterceptor extends AbstractSoapInterceptor{ - - protected static Logger logger = LoggerFactory.getLogger(SOAPLoggingInInterceptor.class); - - @Autowired - MDCSetup mdcSetup; - - public SOAPLoggingInInterceptor() { - super(Phase.READ); - } - - @Override - public void handleMessage(SoapMessage message) throws Fault { - try { - - Map> headers = (Map>) message.get(Message.PROTOCOL_HEADERS); - HttpServletRequest request = (HttpServletRequest)message.get(AbstractHTTPDestination.HTTP_REQUEST); - request.getRemoteAddr(); - - setRequestId(headers); - setInvocationId(headers); - setServiceName(message); - setMDCPartnerName(headers); - mdcSetup.setServerFQDN(); - mdcSetup.setClientIPAddress(request); - mdcSetup.setInstanceUUID(); - mdcSetup.setEntryTimeStamp(); - MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, "INPROGRESS"); - logger.info(ONAPLogConstants.Markers.ENTRY, "Entering"); - } catch (Exception e) { - logger.warn("Error in incoming SOAP Message Inteceptor", e); - } - } - - private void setServiceName(SoapMessage message) { - String requestURI = (String) message.get(Message.REQUEST_URI); - MDC.put(ONAPLogConstants.MDCs.SERVICE_NAME, requestURI); - } - - //CXF Appears to flatten headers to lower case - private void setMDCPartnerName(Map> headers){ - String partnerName=getValueOrDefault(headers, ONAPLogConstants.Headers.PARTNER_NAME.toLowerCase(),""); - MDC.put(ONAPLogConstants.MDCs.PARTNER_NAME,partnerName); - } - - private void setInvocationId(Map> headers) { - String invocationId=getValueOrDefault(headers, ONAPLogConstants.Headers.INVOCATION_ID.toLowerCase(),UUID.randomUUID().toString()); - MDC.put(ONAPLogConstants.MDCs.INVOCATION_ID, invocationId); - } - - private void setRequestId(Map> headers) { - String requestId=getValueOrDefault(headers, ONAPLogConstants.Headers.REQUEST_ID.toLowerCase(),UUID.randomUUID().toString()); - MDC.put(ONAPLogConstants.MDCs.REQUEST_ID,requestId); - } - - private String getValueOrDefault(Map> headers, String headerName, String defaultValue){ - String headerValue; - List headerList=headers.get(headerName); - if(headerList != null && !headerList.isEmpty()){ - headerValue= headerList.get(0); - if(headerValue == null || headerValue.isEmpty()) - headerValue = defaultValue; - }else - headerValue = defaultValue; - return headerValue; - } - -} diff --git a/common/src/main/java/org/onap/so/logging/cxf/interceptor/SOAPLoggingOutInterceptor.java b/common/src/main/java/org/onap/so/logging/cxf/interceptor/SOAPLoggingOutInterceptor.java deleted file mode 100644 index c50e505cd8..0000000000 --- a/common/src/main/java/org/onap/so/logging/cxf/interceptor/SOAPLoggingOutInterceptor.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.onap.so.logging.cxf.interceptor; - - -import java.util.Collections; -import java.util.Map; -import java.util.UUID; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.xml.namespace.QName; -import org.apache.cxf.binding.soap.SoapMessage; -import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor; -import org.apache.cxf.interceptor.Fault; -import org.apache.cxf.message.Message; -import org.apache.cxf.phase.Phase; -import org.apache.cxf.service.model.MessageInfo; -import org.apache.cxf.service.model.OperationInfo; -import org.apache.cxf.transport.http.AbstractHTTPDestination; -import org.onap.logging.ref.slf4j.ONAPLogConstants; -import org.onap.so.exceptions.MSOException; -import org.onap.so.logging.jaxrs.filter.JaxRsFilterLogging; -import org.onap.so.logging.jaxrs.filter.MDCSetup; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Component -public class SOAPLoggingOutInterceptor extends AbstractSoapInterceptor{ - - private static final String _500 = "500"; - - protected static Logger logger = LoggerFactory.getLogger(SOAPLoggingOutInterceptor.class); - - @Autowired - MDCSetup mdcSetup; - - public SOAPLoggingOutInterceptor() { - super(Phase.WRITE); - } - - @Override - public void handleMessage(SoapMessage message) throws Fault { - try { - Exception ex = message.getContent(Exception.class); - if (ex == null) { - MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, ONAPLogConstants.ResponseStatus.COMPLETED.toString()); - }else{ - int responseCode = 0; - responseCode = (int) message.get(Message.RESPONSE_CODE); - if(responseCode != 0 ) - MDC.put(ONAPLogConstants.MDCs.RESPONSE_CODE, String.valueOf(responseCode)); - else - MDC.put(ONAPLogConstants.MDCs.RESPONSE_CODE, _500); - - MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, ONAPLogConstants.ResponseStatus.ERROR.toString()); - } - logger.info(ONAPLogConstants.Markers.EXIT, "Exiting"); - } catch (Exception e) { - logger.warn("Error in incoming SOAP Message Inteceptor", e); - } - } -} diff --git a/common/src/main/java/org/onap/so/logging/jaxrs/filter/JaxRsClientLogging.java b/common/src/main/java/org/onap/so/logging/jaxrs/filter/JaxRsClientLogging.java index 2cb375bed8..49dc71e773 100644 --- a/common/src/main/java/org/onap/so/logging/jaxrs/filter/JaxRsClientLogging.java +++ b/common/src/main/java/org/onap/so/logging/jaxrs/filter/JaxRsClientLogging.java @@ -22,104 +22,126 @@ package org.onap.so.logging.jaxrs.filter; import org.apache.commons.io.IOUtils; -import org.onap.so.logger.MsoLogger; +import org.onap.logging.ref.slf4j.ONAPLogConstants; import org.onap.so.utils.TargetEntity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.slf4j.MDC; +import org.slf4j.MarkerFactory; import org.springframework.stereotype.Component; - +import javax.annotation.Priority; import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestFilter; import javax.ws.rs.client.ClientResponseContext; import javax.ws.rs.client.ClientResponseFilter; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; - +import javax.ws.rs.ext.MessageBodyWriter; +import javax.ws.rs.ext.Providers; import java.io.*; - -import java.time.Instant; -import java.time.ZoneId; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import java.util.Locale; +import java.util.Map; import java.util.UUID; @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") @Component +@Priority(0) public class JaxRsClientLogging implements ClientRequestFilter,ClientResponseFilter { - - private static MsoLogger logger = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA,JaxRsClientLogging.class); + + @Context + private Providers providers; - private TargetEntity targetEntity; + private static final String TRACE = "trace-#"; + private static final String SO = "SO"; + private static Logger logger = LoggerFactory.getLogger(JaxRsClientLogging.class); - public void setTargetService(TargetEntity targetEntity){ - this.targetEntity = targetEntity; + public void setTargetService(TargetEntity targetEntity){ + MDC.put("TargetEntity", targetEntity.toString()); } - @Override - public void filter(ClientRequestContext clientRequest) { + @Override + public void filter(ClientRequestContext clientRequest) { try{ - MultivaluedMap headers = clientRequest.getHeaders(); - - - Instant instant = Instant.now(); - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX" ) - .withLocale( Locale.US ) - .withZone( ZoneId.systemDefault() ); - - String requestId = MDC.get(MsoLogger.REQUEST_ID); - if(requestId == null || requestId.isEmpty()){ - requestId = UUID.randomUUID().toString(); - logger.warnSimple(clientRequest.getUri().getPath(),"Could not Find Request ID Generating New One"); - } - - MDC.put(MsoLogger.METRIC_BEGIN_TIME, formatter.format(instant)); - MDC.put(MsoLogger.METRIC_START_TIME, String.valueOf(System.currentTimeMillis())); - MDC.put(MsoLogger.REQUEST_ID,requestId); - MDC.put(MsoLogger.TARGETSERVICENAME, clientRequest.getUri().toString()); + setupMDC(clientRequest); + setupHeaders(clientRequest); + logger.info(ONAPLogConstants.Markers.INVOKE, "Invoke"); } catch (Exception e) { - logger.warnSimple("Error in incoming JAX-RS Inteceptor", e); - } - } + logger.warn("Error in incoming JAX-RS Inteceptor", e); + } + } + + private void setupHeaders(ClientRequestContext clientRequest) { + MultivaluedMap headers = clientRequest.getHeaders(); + headers.add(ONAPLogConstants.Headers.REQUEST_ID, extractRequestID(clientRequest)); + headers.add(ONAPLogConstants.Headers.INVOCATION_ID, MDC.get(ONAPLogConstants.MDCs.INVOCATION_ID)); + headers.add(ONAPLogConstants.Headers.PARTNER_NAME, SO); + } + + private void setupMDC(ClientRequestContext clientRequest) { + MDC.put(ONAPLogConstants.MDCs.INVOKE_TIMESTAMP, ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)); + MDC.put(ONAPLogConstants.MDCs.TARGET_SERVICE_NAME, clientRequest.getUri().toString()); + MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, ONAPLogConstants.ResponseStatus.INPROGRESS.toString()); + setInvocationId(); + MDC.put("TargetEntity",MDC.get("TargetEntity")); + } + private String extractRequestID(ClientRequestContext clientRequest) { + String requestId = MDC.get(ONAPLogConstants.MDCs.REQUEST_ID); + if(requestId == null || requestId.isEmpty() || requestId.equals(TRACE)){ + requestId = UUID.randomUUID().toString(); + logger.warn("Could not Find Request ID Generating New One: {}",clientRequest.getUri().getPath()); + } + return requestId; + } + + private void setInvocationId() { + String invocationId = MDC.get(ONAPLogConstants.MDCs.INVOCATION_ID); + if(invocationId == null || invocationId.isEmpty()) + invocationId =UUID.randomUUID().toString(); + MDC.put(ONAPLogConstants.MDCs.INVOCATION_ID, invocationId); + } - @Override - public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) { + + @Override + public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) { try { - Instant instant = Instant.now(); - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX" ) - .withLocale( Locale.US ) - .withZone( ZoneId.systemDefault() ); - String startTime= MDC.get(MsoLogger.METRIC_START_TIME); - - long elapsedTime = System.currentTimeMillis()-Long.parseLong(startTime); - String statusCode; - if(Response.Status.Family.familyOf(responseContext.getStatus()).equals(Response.Status.Family.SUCCESSFUL)){ - statusCode=MsoLogger.COMPLETE; - }else{ - statusCode=MsoLogger.StatusCode.ERROR.toString(); - } - MultivaluedMap headers = responseContext.getHeaders(); - - String partnerName = headers.getFirst(MsoLogger.HEADER_FROM_APP_ID ); - if(partnerName == null || partnerName.isEmpty()) - partnerName="UNKNOWN"; - MDC.put(MsoLogger.RESPONSEDESC,getStringFromInputStream(responseContext)); - MDC.put(MsoLogger.STATUSCODE, statusCode); - MDC.put(MsoLogger.RESPONSECODE,String.valueOf(responseContext.getStatus())); - MDC.put(MsoLogger.METRIC_TIMER, String.valueOf(elapsedTime)); - MDC.put(MsoLogger.METRIC_END_TIME,formatter.format(instant)); - MDC.put(MsoLogger.PARTNERNAME,partnerName); - MDC.put(MsoLogger.TARGETENTITY, targetEntity.toString()); - logger.recordMetricEvent(); - } catch ( Exception e) { - logger.warnSimple("Error in outgoing JAX-RS Inteceptor", e); - } - } + String statusCode; + if(Response.Status.Family.familyOf(responseContext.getStatus()).equals(Response.Status.Family.SUCCESSFUL)){ + statusCode=ONAPLogConstants.ResponseStatus.COMPLETED.toString(); + }else{ + statusCode=ONAPLogConstants.ResponseStatus.ERROR.toString(); + } + MDC.put(ONAPLogConstants.MDCs.RESPONSE_CODE, String.valueOf(responseContext.getStatus())); + MDC.put(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION,getStringFromInputStream(responseContext)); + MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, statusCode); + logger.info(MarkerFactory.getMarker("INVOKE_RETURN"), "InvokeReturn"); + clearClientMDCs(); + } catch ( Exception e) { + logger.warn("Error in outgoing JAX-RS Inteceptor", e); + } + } + + private void clearClientMDCs() { + MDC.remove(ONAPLogConstants.MDCs.INVOCATION_ID); + MDC.remove(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION); + MDC.remove(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE); + MDC.remove(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION); + MDC.remove(ONAPLogConstants.MDCs.RESPONSE_CODE); + } private static String getStringFromInputStream(ClientResponseContext clientResponseContext) { - InputStream is = clientResponseContext.getEntityStream(); - ByteArrayOutputStream boas = new ByteArrayOutputStream(); + InputStream is = clientResponseContext.getEntityStream(); + ByteArrayOutputStream boas = new ByteArrayOutputStream(); try { IOUtils.copy(is,boas); @@ -128,8 +150,9 @@ public class JaxRsClientLogging implements ClientRequestFilter,ClientResponseFil return boas.toString(); } catch (IOException e) { - logger.warnSimple("Failed to read response body", e); + logger.warn("Failed to read response body", e); } return "Unable to read input stream"; } + } diff --git a/common/src/main/java/org/onap/so/logging/jaxrs/filter/PayloadLoggingFilter.java b/common/src/main/java/org/onap/so/logging/jaxrs/filter/PayloadLoggingFilter.java new file mode 100644 index 0000000000..29264f4e42 --- /dev/null +++ b/common/src/main/java/org/onap/so/logging/jaxrs/filter/PayloadLoggingFilter.java @@ -0,0 +1,159 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.so.logging.jaxrs.filter; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +import javax.annotation.Priority; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; +import javax.ws.rs.ext.Provider; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; + +import org.onap.so.logger.MsoLogger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +@Provider +@Priority(1) +public class PayloadLoggingFilter implements ClientRequestFilter, ClientResponseFilter, WriterInterceptor { + + private static final Logger logger = LoggerFactory.getLogger(PayloadLoggingFilter.class); + private static final String ENTITY_STREAM_PROPERTY = "LoggingFilter.entityStream"; + private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; + private final int maxEntitySize; + + public PayloadLoggingFilter() { + maxEntitySize = 1024 * 1024; + } + + public PayloadLoggingFilter(int maxPayloadSize) { + this.maxEntitySize = Integer.min(maxPayloadSize, 1024 * 1024); + } + + private void log(StringBuilder sb) { + logger.debug(sb.toString()); + } + + protected InputStream logInboundEntity(final StringBuilder b, InputStream stream, final Charset charset) + throws IOException { + if (!stream.markSupported()) { + stream = new BufferedInputStream(stream); + } + stream.mark(maxEntitySize + 1); + final byte[] entity = new byte[maxEntitySize + 1]; + final int entitySize = stream.read(entity); + if (entitySize != -1) { + b.append(new String(entity, 0, Math.min(entitySize, maxEntitySize), charset)); + } + if (entitySize > maxEntitySize) { + b.append("...more..."); + } + b.append('\n'); + stream.reset(); + return stream; + } + + @Override + public void filter(ClientRequestContext requestContext) throws IOException { + if (requestContext.hasEntity()) { + final OutputStream stream = new LoggingStream(requestContext.getEntityStream()); + requestContext.setEntityStream(stream); + requestContext.setProperty(ENTITY_STREAM_PROPERTY, stream); + } + String method = formatMethod(requestContext); + log(new StringBuilder("Making " + method + " request to: " + requestContext.getUri() + "\nRequest Headers: " + requestContext.getHeaders().toString())); + + } + + @Override + public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException { + final StringBuilder sb = new StringBuilder(); + if (responseContext.hasEntity()) { + responseContext.setEntityStream(logInboundEntity(sb, responseContext.getEntityStream(), DEFAULT_CHARSET)); + String method = formatMethod(requestContext); + log(sb.insert(0, "Response from " + method + ": " + requestContext.getUri() + "\nResponse Headers: " + responseContext.getHeaders().toString())); + } + } + + @Override + public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException { + final LoggingStream stream = (LoggingStream) context.getProperty(ENTITY_STREAM_PROPERTY); + context.proceed(); + if (stream != null) { + log(stream.getStringBuilder(DEFAULT_CHARSET)); + } + } + + private class LoggingStream extends FilterOutputStream { + + private final StringBuilder sb = new StringBuilder(); + private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + LoggingStream(OutputStream out) { + super(out); + } + + StringBuilder getStringBuilder(Charset charset) { + // write entity to the builder + final byte[] entity = baos.toByteArray(); + + sb.append(new String(entity, 0, entity.length, charset)); + if (entity.length > maxEntitySize) { + sb.append("...more..."); + } + sb.append('\n'); + + return sb; + } + + @Override + public void write(final int i) throws IOException { + if (baos.size() <= maxEntitySize) { + baos.write(i); + } + out.write(i); + } + } + + private String formatMethod(ClientRequestContext requestContext) { + String method = requestContext.getHeaderString("X-HTTP-Method-Override"); + if (method == null) { + method = requestContext.getMethod(); + } else { + method = requestContext.getMethod() + " (overridden to " + method + ")"; + } + + return method; + } +} \ No newline at end of file diff --git a/common/src/main/java/org/onap/so/utils/TargetEntity.java b/common/src/main/java/org/onap/so/utils/TargetEntity.java index ad76e56a56..84dae957ba 100644 --- a/common/src/main/java/org/onap/so/utils/TargetEntity.java +++ b/common/src/main/java/org/onap/so/utils/TargetEntity.java @@ -20,13 +20,22 @@ package org.onap.so.utils; +import java.util.EnumSet; public enum TargetEntity { OPENSTACK_ADAPTER, BPMN, GRM ,AAI, DMAAP, POLICY, CATALOG_DB, REQUEST_DB, VNF_ADAPTER, SDNC_ADAPTER, NARAD; - private static final String PREFIX = "MSO"; + private static final String PREFIX = "SO"; + + public static EnumSet getSOInternalComponents() { + return EnumSet.of(OPENSTACK_ADAPTER, BPMN,CATALOG_DB,REQUEST_DB,VNF_ADAPTER,SDNC_ADAPTER); + } + @Override public String toString(){ - return TargetEntity.PREFIX + "." + this.name(); + if(getSOInternalComponents().contains(this)) + return TargetEntity.PREFIX + "." + this.name(); + else + return this.name(); } -} +} \ No newline at end of file -- cgit 1.2.3-korg