aboutsummaryrefslogtreecommitdiffstats
path: root/aai-els-onap-logging/src/main/java/org/onap/logging
diff options
context:
space:
mode:
authorKajur, Harish (vk250x) <vk250x@att.com>2020-02-21 14:34:10 -0500
committerHarish Venkata Kajur <vk250x@att.com>2020-02-25 23:59:33 -0500
commit98749c47bbb5f5ddcc1c4f0690b79c7288f6bdd6 (patch)
treea472ce2edabd497b643917f44785b775fa16e15e /aai-els-onap-logging/src/main/java/org/onap/logging
parente654645a50a0d028d8e67ea997f84efe8d28a6a0 (diff)
Enhancements for the aai-common library
Issue-ID: AAI-2806 Change-Id: I2dbb46b897b35136ac1bb802978d3f974af1b307 Signed-off-by: Kajur, Harish (vk250x) <vk250x@att.com>
Diffstat (limited to 'aai-els-onap-logging/src/main/java/org/onap/logging')
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AbstractAuditLogFilter.java82
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AbstractMetricLogFilter.java135
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AbstractServletFilter.java57
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AuditLogContainerFilter.java67
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AuditLogServletFilter.java85
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/Constants.java46
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/MDCSetup.java238
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/MetricLogClientFilter.java82
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/ONAPComponents.java80
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/ONAPComponentsList.java25
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/PayloadLoggingClientFilter.java162
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/PayloadLoggingServletFilter.java330
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/SimpleHashMap.java37
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/SimpleJaxrsHeadersMap.java37
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/SimpleMap.java25
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/SimpleServletHeadersMap.java37
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/ref/slf4j/ONAPLogAdapter.java616
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/ref/slf4j/ONAPLogConstants.java289
-rw-r--r--aai-els-onap-logging/src/main/java/org/onap/logging/ref/slf4j/package-info.java32
19 files changed, 2462 insertions, 0 deletions
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AbstractAuditLogFilter.java b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AbstractAuditLogFilter.java
new file mode 100644
index 00000000..ce2f4489
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AbstractAuditLogFilter.java
@@ -0,0 +1,82 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - Logging
+ * ================================================================================
+ * Copyright (C) 2019 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.logging.filter.base;
+
+import javax.servlet.http.HttpServletRequest;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+public abstract class AbstractAuditLogFilter<GenericRequest, GenericResponse> extends MDCSetup {
+ protected static final Logger logger = LoggerFactory.getLogger(AbstractAuditLogFilter.class);
+
+ protected void pre(SimpleMap headers, GenericRequest request, HttpServletRequest httpServletRequest) {
+ try {
+ String requestId = getRequestId(headers);
+ MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, requestId);
+ setInvocationId(headers);
+ setServiceName(request);
+ setMDCPartnerName(headers);
+ setServerFQDN();
+ setClientIPAddress(httpServletRequest);
+ setInstanceID();
+ setEntryTimeStamp();
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, ONAPLogConstants.ResponseStatus.INPROGRESS.toString());
+ additionalPreHandling(request);
+ setLogTimestamp();
+ setElapsedTime();
+ logger.info(ONAPLogConstants.Markers.ENTRY, "Entering");
+ } catch (Exception e) {
+ logger.warn("Error in AbstractInboundFilter pre", e);
+ }
+ }
+
+ protected void post(GenericResponse response) {
+ try {
+ int responseCode = getResponseCode(response);
+ setResponseStatusCode(responseCode);
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_CODE, String.valueOf(responseCode));
+ setResponseDescription(responseCode);
+ setLogTimestamp();
+ setElapsedTime();
+ logger.info(ONAPLogConstants.Markers.EXIT, "Exiting.");
+ additionalPostHandling(response);
+ } catch (Exception e) {
+ logger.warn("Error in AbstractInboundFilter post", e);
+ } finally {
+ MDC.clear();
+ }
+ }
+
+ protected abstract int getResponseCode(GenericResponse response);
+
+ protected abstract void setServiceName(GenericRequest request);
+
+ protected void additionalPreHandling(GenericRequest request) {
+ // override to add additional pre handling
+ }
+
+ protected void additionalPostHandling(GenericResponse response) {
+ // override to add additional post handling
+ }
+
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AbstractMetricLogFilter.java b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AbstractMetricLogFilter.java
new file mode 100644
index 00000000..ab1daab5
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AbstractMetricLogFilter.java
@@ -0,0 +1,135 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - Logging
+ * ================================================================================
+ * Copyright (C) 2019 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.logging.filter.base;
+
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.UUID;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+
+public abstract class AbstractMetricLogFilter<Request, Response, RequestHeaders> extends MDCSetup {
+ protected static final Logger logger = LoggerFactory.getLogger(AbstractMetricLogFilter.class);
+ private final String partnerName;
+ private static final Marker INVOKE_RETURN = MarkerFactory.getMarker("INVOKE-RETURN");
+
+ public AbstractMetricLogFilter() {
+ partnerName = getPartnerName();
+ }
+
+ protected abstract void addHeader(RequestHeaders requestHeaders, String headerName, String headerValue);
+
+ protected abstract String getTargetServiceName(Request request);
+
+ protected abstract String getServiceName(Request request);
+
+ protected abstract int getHttpStatusCode(Response response);
+
+ protected abstract String getResponseCode(Response response);
+
+ protected abstract String getTargetEntity(Request request);
+
+ protected void pre(Request request, RequestHeaders requestHeaders) {
+ try {
+ setupMDC(request);
+ setupHeaders(request, requestHeaders);
+ logger.info(ONAPLogConstants.Markers.INVOKE, "Invoke");
+ } catch (Exception e) {
+ logger.warn("Error in AbstractMetricLogFilter pre", e);
+ }
+ }
+
+ protected void setupHeaders(Request clientRequest, RequestHeaders requestHeaders) {
+ String requestId = extractRequestID();
+ addHeader(requestHeaders, ONAPLogConstants.Headers.REQUEST_ID, requestId);
+ addHeader(requestHeaders, Constants.HttpHeaders.HEADER_REQUEST_ID, requestId);
+ addHeader(requestHeaders, Constants.HttpHeaders.TRANSACTION_ID, requestId);
+ addHeader(requestHeaders, Constants.HttpHeaders.ECOMP_REQUEST_ID, requestId);
+ addHeader(requestHeaders, ONAPLogConstants.Headers.INVOCATION_ID, MDC.get(ONAPLogConstants.MDCs.INVOCATION_ID));
+ addHeader(requestHeaders, ONAPLogConstants.Headers.PARTNER_NAME, partnerName);
+ }
+
+ protected void setupMDC(Request request) {
+ MDC.put(ONAPLogConstants.MDCs.INVOKE_TIMESTAMP,
+ ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT));
+ // setup time stamp defaults
+ setLogTimestamp();
+ setElapsedTimeInvokeTimestamp();
+ MDC.put(ONAPLogConstants.MDCs.TARGET_SERVICE_NAME, getTargetServiceName(request));
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, ONAPLogConstants.ResponseStatus.INPROGRESS.toString());
+ setInvocationIdFromMDC();
+
+ if (MDC.get(ONAPLogConstants.MDCs.TARGET_ENTITY) == null) {
+ String targetEntity = getTargetEntity(request);
+ if (targetEntity != null) {
+ MDC.put(ONAPLogConstants.MDCs.TARGET_ENTITY, targetEntity);
+ } else {
+ MDC.put(ONAPLogConstants.MDCs.TARGET_ENTITY, Constants.DefaultValues.UNKNOWN_TARGET_ENTITY);
+ }
+ }
+
+ if (MDC.get(ONAPLogConstants.MDCs.SERVICE_NAME) == null) {
+ MDC.put(ONAPLogConstants.MDCs.SERVICE_NAME, getServiceName(request));
+ }
+ setServerFQDN();
+ }
+
+ protected String extractRequestID() {
+ String requestId = MDC.get(ONAPLogConstants.MDCs.REQUEST_ID);
+ if (requestId == null || requestId.isEmpty()) {
+ requestId = UUID.randomUUID().toString();
+ setLogTimestamp();
+ setElapsedTimeInvokeTimestamp();
+ logger.warn("No value found in MDC when checking key {} value will be set to {}",
+ ONAPLogConstants.MDCs.REQUEST_ID, requestId);
+ MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, requestId);
+ }
+ return requestId;
+ }
+
+ protected void post(Request request, Response response) {
+ try {
+ setLogTimestamp();
+ setElapsedTimeInvokeTimestamp();
+ setResponseStatusCode(getHttpStatusCode(response));
+ setResponseDescription(getHttpStatusCode(response));
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_CODE, getResponseCode(response));
+ logger.info(INVOKE_RETURN, "InvokeReturn");
+ clearClientMDCs();
+ } catch (Exception e) {
+ logger.warn("Error in AbstractMetricLogFilter post", e);
+ }
+ }
+
+ protected String getPartnerName() {
+ return getProperty(Constants.Property.PARTNER_NAME);
+ }
+
+ protected void logInvoke() {
+ logger.info(ONAPLogConstants.Markers.INVOKE, "Invoke");
+ }
+
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AbstractServletFilter.java b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AbstractServletFilter.java
new file mode 100644
index 00000000..28495c84
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AbstractServletFilter.java
@@ -0,0 +1,57 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - Logging
+ * ================================================================================
+ * Copyright (C) 2019 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.logging.filter.base;
+
+import java.util.Enumeration;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.HttpHeaders;
+
+public abstract class AbstractServletFilter {
+
+ protected String getSecureRequestHeaders(HttpServletRequest httpRequest) {
+ StringBuilder sb = new StringBuilder();
+ String header;
+ for (Enumeration<String> e = httpRequest.getHeaderNames(); e.hasMoreElements();) {
+ header = e.nextElement();
+ sb.append(header);
+ sb.append(":");
+ if (header.equalsIgnoreCase(HttpHeaders.AUTHORIZATION)) {
+ sb.append(Constants.REDACTED);
+ } else {
+ sb.append(httpRequest.getHeader(header));
+ }
+ sb.append(";");
+ }
+ return sb.toString();
+ }
+
+ protected String formatResponseHeaders(HttpServletResponse response) {
+ StringBuilder sb = new StringBuilder();
+ for (String headerName : response.getHeaderNames()) {
+ sb.append(headerName);
+ sb.append(":");
+ sb.append(response.getHeader(headerName));
+ sb.append(";");
+ }
+ return sb.toString();
+ }
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AuditLogContainerFilter.java b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AuditLogContainerFilter.java
new file mode 100644
index 00000000..a0194850
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AuditLogContainerFilter.java
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - Logging
+ * ================================================================================
+ * Copyright (C) 2019 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.logging.filter.base;
+
+import java.io.IOException;
+import javax.annotation.Priority;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.container.*;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.Providers;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+@Priority(1)
+public class AuditLogContainerFilter extends AbstractAuditLogFilter<ContainerRequestContext, ContainerResponseContext>
+ implements ContainerRequestFilter, ContainerResponseFilter {
+
+ @Context
+ private HttpServletRequest httpServletRequest;
+
+ @Context
+ private Providers providers;
+
+ @Override
+ public void filter(ContainerRequestContext containerRequest) {
+ SimpleMap headers = new SimpleJaxrsHeadersMap(containerRequest.getHeaders());
+ pre(headers, containerRequest, httpServletRequest);
+ }
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
+ throws IOException {
+ post(responseContext);
+ }
+
+ @Override
+ protected void setServiceName(ContainerRequestContext containerRequest) {
+ MDC.put(ONAPLogConstants.MDCs.SERVICE_NAME, containerRequest.getUriInfo().getPath());
+ }
+
+ @Override
+ protected int getResponseCode(ContainerResponseContext response) {
+ return response.getStatus();
+ }
+
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AuditLogServletFilter.java b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AuditLogServletFilter.java
new file mode 100644
index 00000000..a8f5eae9
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/AuditLogServletFilter.java
@@ -0,0 +1,85 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - Logging
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.logging.filter.base;
+
+import java.io.IOException;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.slf4j.MDC;
+
+public class AuditLogServletFilter extends AbstractAuditLogFilter<HttpServletRequest, HttpServletResponse>
+ implements Filter {
+
+ @Override
+ public void destroy() {
+ // this method does nothing
+ }
+
+ @Override
+ public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain)
+ throws IOException, ServletException {
+ try {
+ if (request != null && request instanceof HttpServletRequest) {
+ pre((HttpServletRequest) request);
+ }
+ filterChain.doFilter(request, response);
+ } finally {
+ if (request != null && request instanceof HttpServletRequest) {
+ post((HttpServletRequest) request, (HttpServletResponse) response);
+ }
+ MDC.clear();
+ }
+ }
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ // this method does nothing
+ }
+
+ protected void pre(HttpServletRequest request) {
+ SimpleMap headers = new SimpleServletHeadersMap(request);
+ pre(headers, request, request);
+ }
+
+ @Override
+ protected void setServiceName(HttpServletRequest request) {
+ MDC.put(ONAPLogConstants.MDCs.SERVICE_NAME, request.getRequestURI());
+ }
+
+ private void post(HttpServletRequest request, HttpServletResponse response) {
+ post(response);
+ }
+
+ @Override
+ protected int getResponseCode(HttpServletResponse response) {
+ return response.getStatus();
+ }
+
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/Constants.java b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/Constants.java
new file mode 100644
index 00000000..be28f0bc
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/Constants.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - Logging
+ * ================================================================================
+ * Copyright (C) 2019 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.logging.filter.base;
+
+public class Constants {
+ protected static final String REDACTED = "***REDACTED***";
+
+ public static final class DefaultValues {
+ public static final String UNKNOWN = "UNKNOWN";
+ public static final String UNKNOWN_TARGET_ENTITY = "Unknown-Target-Entity";
+ }
+
+ public static final class HttpHeaders {
+ public static final String HEADER_FROM_APP_ID = "X-FromAppId";
+ public static final String ONAP_PARTNER_NAME = "X-ONAP-PartnerName";
+ public static final String HEADER_REQUEST_ID = "X-RequestID";
+ public static final String TRANSACTION_ID = "X-TransactionID";
+ public static final String ECOMP_REQUEST_ID = "X-ECOMP-RequestID";
+ public static final String ONAP_REQUEST_ID = "X-ONAP-RequestID";
+ public static final String CLIENT_ID = "X-ClientID";
+ public static final String INVOCATION_ID_HEADER = "X-InvocationID";
+ public static final String TARGET_ENTITY_HEADER = "X-Target-Entity";
+ }
+
+ public static final class Property {
+ public static final String PARTNER_NAME = "partnerName";
+ }
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/MDCSetup.java b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/MDCSetup.java
new file mode 100644
index 00000000..369a9f20
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/MDCSetup.java
@@ -0,0 +1,238 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - Logging
+ * ================================================================================
+ * Copyright (C) 2019 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.logging.filter.base;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.UUID;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+public class MDCSetup {
+
+ protected static Logger logger = LoggerFactory.getLogger(MDCSetup.class);
+
+ private static final String INSTANCE_UUID = UUID.randomUUID().toString();
+
+ public void setInstanceID() {
+ MDC.put(ONAPLogConstants.MDCs.INSTANCE_UUID, INSTANCE_UUID);
+ }
+
+ public void setServerFQDN() {
+ String serverFQDN = "";
+ InetAddress addr = null;
+ try {
+ addr = InetAddress.getLocalHost();
+ serverFQDN = addr.getCanonicalHostName();
+ MDC.put(ONAPLogConstants.MDCs.SERVER_IP_ADDRESS, addr.getHostAddress());
+ } catch (UnknownHostException e) {
+ logger.warn("Cannot Resolve Host Name");
+ serverFQDN = "";
+ }
+ MDC.put(ONAPLogConstants.MDCs.SERVER_FQDN, serverFQDN);
+ }
+
+ public void setClientIPAddress(HttpServletRequest httpServletRequest) {
+ String clientIpAddress = "";
+ if (httpServletRequest != null) {
+ // This logic is to avoid setting the client ip address to that of the load
+ // balancer in front of the application
+ String getForwadedFor = httpServletRequest.getHeader("X-Forwarded-For");
+ if (getForwadedFor != null) {
+ clientIpAddress = getForwadedFor;
+ } else {
+ clientIpAddress = httpServletRequest.getRemoteAddr();
+ }
+ }
+ MDC.put(ONAPLogConstants.MDCs.CLIENT_IP_ADDRESS, clientIpAddress);
+ }
+
+ public void setEntryTimeStamp() {
+ MDC.put(ONAPLogConstants.MDCs.ENTRY_TIMESTAMP,
+ ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT));
+ }
+
+ public String getRequestId(SimpleMap headers) {
+ logger.trace("Checking X-ONAP-RequestID header for requestId.");
+ String requestId = headers.get(ONAPLogConstants.Headers.REQUEST_ID);
+ if (requestId != null && !requestId.isEmpty() && isValidUUID(requestId)) {
+ return requestId;
+ }
+ if (requestId != null && !requestId.isEmpty()) {
+ //invalid
+ return UUID.randomUUID().toString();
+ }
+ logger.trace("No valid X-ONAP-RequestID header value. Checking X-RequestID header for requestId.");
+ requestId = headers.get(Constants.HttpHeaders.HEADER_REQUEST_ID);
+ if (requestId != null && !requestId.isEmpty() && isValidUUID(requestId)) {
+ return requestId;
+ }
+ if (requestId != null && !requestId.isEmpty()) {
+ //invalid
+ return UUID.randomUUID().toString();
+ }
+ logger.trace("No valid X-RequestID header value. Checking X-TransactionID header for requestId.");
+ requestId = headers.get(Constants.HttpHeaders.TRANSACTION_ID);
+ if (requestId != null && !requestId.isEmpty() && isValidUUID(requestId)) {
+ return requestId;
+ }
+ if (requestId != null && !requestId.isEmpty()) {
+ //invalid
+ return UUID.randomUUID().toString();
+ }
+ logger.trace("No valid X-TransactionID header value. Checking X-ECOMP-RequestID header for requestId.");
+ requestId = headers.get(Constants.HttpHeaders.ECOMP_REQUEST_ID);
+ if (requestId != null && !requestId.isEmpty() && isValidUUID(requestId)) {
+ return requestId;
+ }
+ if (requestId != null && !requestId.isEmpty()) {
+ //invalid
+ return UUID.randomUUID().toString();
+ }
+ return requestId;
+ }
+ protected boolean isValidUUID(String transId) {
+ try {
+ UUID.fromString(transId);
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ return true;
+ }
+ public void setInvocationId(SimpleMap headers) {
+ String invocationId = headers.get(ONAPLogConstants.Headers.INVOCATION_ID);
+ if (invocationId == null || invocationId.isEmpty())
+ invocationId = UUID.randomUUID().toString();
+ MDC.put(ONAPLogConstants.MDCs.INVOCATION_ID, invocationId);
+ }
+
+ public void setInvocationIdFromMDC() {
+ String invocationId = MDC.get(ONAPLogConstants.MDCs.INVOCATION_ID);
+ if (invocationId == null || invocationId.isEmpty())
+ invocationId = UUID.randomUUID().toString();
+ MDC.put(ONAPLogConstants.MDCs.INVOCATION_ID, invocationId);
+ }
+
+ public void setMDCPartnerName(SimpleMap headers) {
+ logger.trace("Checking X-ONAP-PartnerName header for partnerName.");
+ String partnerName = headers.get(ONAPLogConstants.Headers.PARTNER_NAME);
+ if (partnerName == null || partnerName.isEmpty()) {
+ logger.trace("No valid X-ONAP-PartnerName header value. Checking User-Agent header for partnerName.");
+ partnerName = headers.get(HttpHeaders.USER_AGENT);
+ if (partnerName == null || partnerName.isEmpty()) {
+ logger.trace("No valid User-Agent header value. Checking X-ClientID header for partnerName.");
+ partnerName = headers.get(Constants.HttpHeaders.CLIENT_ID);
+ if (partnerName == null || partnerName.isEmpty()) {
+ logger.trace("No valid partnerName headers. Defaulting partnerName to UNKNOWN.");
+ partnerName = Constants.DefaultValues.UNKNOWN;
+ }
+ }
+ }
+ MDC.put(ONAPLogConstants.MDCs.PARTNER_NAME, partnerName);
+ }
+
+ public void setLogTimestamp() {
+ MDC.put(ONAPLogConstants.MDCs.LOG_TIMESTAMP,
+ ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT));
+ }
+
+ public void setElapsedTime() {
+ DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_ZONED_DATE_TIME;
+ ZonedDateTime entryTimestamp =
+ ZonedDateTime.parse(MDC.get(ONAPLogConstants.MDCs.ENTRY_TIMESTAMP), timeFormatter);
+ ZonedDateTime endTimestamp = ZonedDateTime.parse(MDC.get(ONAPLogConstants.MDCs.LOG_TIMESTAMP), timeFormatter);
+
+ MDC.put(ONAPLogConstants.MDCs.ELAPSED_TIME,
+ Long.toString(ChronoUnit.MILLIS.between(entryTimestamp, endTimestamp)));
+ }
+
+ public void setElapsedTimeInvokeTimestamp() {
+ DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_ZONED_DATE_TIME;
+ ZonedDateTime entryTimestamp =
+ ZonedDateTime.parse(MDC.get(ONAPLogConstants.MDCs.INVOKE_TIMESTAMP), timeFormatter);
+ ZonedDateTime endTimestamp = ZonedDateTime.parse(MDC.get(ONAPLogConstants.MDCs.LOG_TIMESTAMP), timeFormatter);
+
+ MDC.put(ONAPLogConstants.MDCs.ELAPSED_TIME,
+ Long.toString(ChronoUnit.MILLIS.between(entryTimestamp, endTimestamp)));
+ }
+
+ public void setResponseStatusCode(int code) {
+ String statusCode;
+ if (Response.Status.Family.familyOf(code).equals(Response.Status.Family.SUCCESSFUL)) {
+ statusCode = ONAPLogConstants.ResponseStatus.COMPLETE.toString();
+ } else {
+ statusCode = ONAPLogConstants.ResponseStatus.ERROR.toString();
+ setErrorCode(code);
+ setErrorDesc(code);
+ }
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, statusCode);
+ }
+
+ public void setTargetEntity(ONAPComponentsList targetEntity) {
+ MDC.put(ONAPLogConstants.MDCs.TARGET_ENTITY, targetEntity.toString());
+ }
+
+ public 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_CODE);
+ MDC.remove(ONAPLogConstants.MDCs.TARGET_ENTITY);
+ MDC.remove(ONAPLogConstants.MDCs.TARGET_SERVICE_NAME);
+ MDC.remove(ONAPLogConstants.MDCs.INVOKE_TIMESTAMP);
+ MDC.remove(ONAPLogConstants.MDCs.ERROR_CODE);
+ MDC.remove(ONAPLogConstants.MDCs.ERROR_DESC);
+ }
+
+ public void setResponseDescription(int statusCode) {
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION, Response.Status.fromStatusCode(statusCode).toString());
+ }
+
+ public void setErrorCode(int statusCode) {
+ MDC.put(ONAPLogConstants.MDCs.ERROR_CODE, String.valueOf(statusCode));
+ }
+
+ public void setErrorDesc(int statusCode) {
+ MDC.put(ONAPLogConstants.MDCs.ERROR_DESC, Response.Status.fromStatusCode(statusCode).toString());
+ }
+
+ public String getProperty(String property) {
+ logger.info("Checking for system property [{}]", property);
+ String propertyValue = System.getProperty(property);
+ if (propertyValue == null || propertyValue.isEmpty()) {
+ logger.info("System property was null or empty. Checking environment variable for: {}", property);
+ propertyValue = System.getenv(property);
+ if (propertyValue == null || propertyValue.isEmpty()) {
+ logger.info("Environment variable: {} was null or empty", property );
+ }
+ }
+ return propertyValue;
+ }
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/MetricLogClientFilter.java b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/MetricLogClientFilter.java
new file mode 100644
index 00000000..da4d9827
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/MetricLogClientFilter.java
@@ -0,0 +1,82 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - Logging
+ * ================================================================================
+ * Copyright (C) 2019 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.logging.filter.base;
+
+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.PreMatching;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.Providers;
+
+@Priority(0)
+public class MetricLogClientFilter
+ extends AbstractMetricLogFilter<ClientRequestContext, ClientResponseContext, MultivaluedMap<String, Object>>
+ implements ClientRequestFilter, ClientResponseFilter {
+
+ @Context
+ private Providers providers;
+
+ @Override
+ public void filter(ClientRequestContext clientRequest) {
+ pre(clientRequest, clientRequest.getHeaders());
+ }
+
+ @Override
+ public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) {
+ post(requestContext, responseContext);
+ }
+
+ @Override
+ protected void addHeader(MultivaluedMap<String, Object> requestHeaders, String headerName, String headerValue) {
+ requestHeaders.add(headerName, headerValue);
+ }
+
+ @Override
+ protected String getTargetServiceName(ClientRequestContext request) {
+ return request.getUri().toString();
+ }
+
+ @Override
+ protected String getServiceName(ClientRequestContext request) {
+ return request.getUri().getPath();
+ }
+
+ @Override
+ protected int getHttpStatusCode(ClientResponseContext response) {
+ return response.getStatus();
+ }
+
+ @Override
+ protected String getResponseCode(ClientResponseContext response) {
+ return String.valueOf(response.getStatus());
+ }
+
+ @Override
+ protected String getTargetEntity(ClientRequestContext request) {
+ return Constants.DefaultValues.UNKNOWN_TARGET_ENTITY;
+ }
+
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/ONAPComponents.java b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/ONAPComponents.java
new file mode 100644
index 00000000..06fbba9a
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/ONAPComponents.java
@@ -0,0 +1,80 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - Logging
+ * ================================================================================
+ * Copyright (C) 2019 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.logging.filter.base;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+public enum ONAPComponents implements ONAPComponentsList {
+ OPENSTACK_ADAPTER,
+ BPMN,
+ GRM,
+ AAI,
+ DMAAP,
+ POLICY,
+ CATALOG_DB,
+ REQUEST_DB,
+ SNIRO,
+ SDC,
+ EXTERNAL,
+ VNF_ADAPTER,
+ SDNC_ADAPTER,
+ MULTICLOUD,
+ CLAMP,
+ PORTAL,
+ VID,
+ APPC,
+ DCAE,
+ HOLMES,
+ SDNC,
+ SO,
+ VFC,
+ ESR,
+ DBC,
+ DR,
+ MR,
+ OPTF;
+
+
+ public static Set<ONAPComponents> getSOInternalComponents() {
+ return EnumSet.of(OPENSTACK_ADAPTER, BPMN, CATALOG_DB, REQUEST_DB, VNF_ADAPTER, SDNC_ADAPTER);
+ }
+
+ public static Set<ONAPComponents> getDMAAPInternalComponents() {
+ return EnumSet.of(DBC, DR, MR);
+ }
+
+ public static Set<ONAPComponents> getAAIInternalComponents() {
+ return EnumSet.of(ESR);
+ }
+
+ @Override
+ public String toString() {
+ if (getSOInternalComponents().contains(this))
+ return SO + "." + this.name();
+ else if (getDMAAPInternalComponents().contains(this))
+ return DMAAP + "." + this.name();
+ else if (getAAIInternalComponents().contains(this))
+ return AAI + "." + this.name();
+ else
+ return this.name();
+ }
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/ONAPComponentsList.java b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/ONAPComponentsList.java
new file mode 100644
index 00000000..7ffc2517
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/ONAPComponentsList.java
@@ -0,0 +1,25 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - Logging
+ * ================================================================================
+ * Copyright (C) 2019 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.logging.filter.base;
+
+public interface ONAPComponentsList {
+
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/PayloadLoggingClientFilter.java b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/PayloadLoggingClientFilter.java
new file mode 100644
index 00000000..88c95aa4
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/PayloadLoggingClientFilter.java
@@ -0,0 +1,162 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - Logging
+ * ================================================================================
+ * Copyright (C) 2019 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.logging.filter.base;
+
+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.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.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PayloadLoggingClientFilter implements ClientRequestFilter, ClientResponseFilter, WriterInterceptor {
+
+ private static final Logger logger = LoggerFactory.getLogger(PayloadLoggingClientFilter.class);
+ private static final String ENTITY_STREAM_PROPERTY = "LoggingFilter.entityStream";
+ private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
+ private final int maxEntitySize;
+
+ public PayloadLoggingClientFilter() {
+ maxEntitySize = 1024 * 1024;
+ }
+
+ public PayloadLoggingClientFilter(int maxPayloadSize) {
+ this.maxEntitySize = Integer.min(maxPayloadSize, 1024 * 1024);
+ }
+
+ 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);
+ logger.debug("Sending HTTP {} to:{} with request headers:{}", method, requestContext.getUri(),
+ getHeaders(requestContext.getHeaders()));
+ }
+
+ protected String getHeaders(MultivaluedMap<String, Object> headers) {
+ MultivaluedMap<String, Object> printHeaders = new MultivaluedHashMap<>();
+ for (String header : headers.keySet()) {
+ if (!header.equals(HttpHeaders.AUTHORIZATION)) {
+ printHeaders.add(header, headers.getFirst(header));
+ } else {
+ printHeaders.add(header, Constants.REDACTED);;
+ }
+ }
+ return printHeaders.toString();
+ }
+
+ @Override
+ public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
+ String method = formatMethod(requestContext);
+ logger.debug("Response from method:{} performed on uri:{} has http status code:{} and response headers:{}",
+ method, requestContext.getUri(), responseContext.getStatus(), responseContext.getHeaders().toString());
+ if (responseContext.hasEntity()) {
+ final StringBuilder sb = new StringBuilder();
+ responseContext.setEntityStream(logInboundEntity(sb, responseContext.getEntityStream(), DEFAULT_CHARSET));
+ logger.debug(sb.toString());
+ }
+ }
+
+ @Override
+ public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
+ final LoggingStream stream = (LoggingStream) context.getProperty(ENTITY_STREAM_PROPERTY);
+ context.proceed();
+ if (stream != null) {
+ logger.debug(stream.getStringBuilder(DEFAULT_CHARSET).toString());
+ }
+ }
+
+ 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);
+ }
+ }
+
+ protected String formatMethod(ClientRequestContext requestContext) {
+ String httpMethodOverride = requestContext.getHeaderString("X-HTTP-Method-Override");
+ if (httpMethodOverride == null) {
+ return requestContext.getMethod();
+ } else {
+ return requestContext.getMethod() + " (overridden to " + httpMethodOverride + ")";
+ }
+ }
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/PayloadLoggingServletFilter.java b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/PayloadLoggingServletFilter.java
new file mode 100644
index 00000000..fa8533a7
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/PayloadLoggingServletFilter.java
@@ -0,0 +1,330 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - Logging
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.logging.filter.base;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.util.zip.GZIPInputStream;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ReadListener;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.WriteListener;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+
+public class PayloadLoggingServletFilter extends AbstractServletFilter implements Filter {
+
+ private static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(PayloadLoggingServletFilter.class);
+
+ private static class ByteArrayServletStream extends ServletOutputStream {
+ ByteArrayOutputStream baos;
+
+ ByteArrayServletStream(ByteArrayOutputStream baos) {
+ this.baos = baos;
+ }
+
+ @Override
+ public void write(int param) throws IOException {
+ baos.write(param);
+ }
+
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+
+ @Override
+ public void setWriteListener(WriteListener arg0) {
+ // this method does nothing
+ }
+ }
+
+ private static class ByteArrayPrintWriter extends PrintWriter {
+ private ByteArrayOutputStream baos;
+ private int errorCode = -1;
+ private String errorMsg = "";
+ private boolean errored = false;
+
+ public ByteArrayPrintWriter(ByteArrayOutputStream out) {
+ super(out);
+ this.baos = out;
+ }
+
+ public ServletOutputStream getStream() {
+ return new ByteArrayServletStream(baos);
+ }
+
+ public Boolean hasErrored() {
+ return errored;
+ }
+
+ public int getErrorCode() {
+ return errorCode;
+ }
+
+ public String getErrorMsg() {
+ return errorMsg;
+ }
+
+ public void setError(int code) {
+ errorCode = code;
+ errored = true;
+ }
+
+ public void setError(int code, String msg) {
+ errorMsg = msg;
+ errorCode = code;
+ errored = true;
+ }
+
+ }
+
+ private class BufferedServletInputStream extends ServletInputStream {
+ ByteArrayInputStream bais;
+
+ public BufferedServletInputStream(ByteArrayInputStream bais) {
+ this.bais = bais;
+ }
+
+ @Override
+ public int available() {
+ return bais.available();
+ }
+
+ @Override
+ public int read() {
+ return bais.read();
+ }
+
+ @Override
+ public int read(byte[] buf, int off, int len) {
+ return bais.read(buf, off, len);
+ }
+
+ @Override
+ public boolean isFinished() {
+ return available() < 1;
+ }
+
+ @Override
+ public boolean isReady() {
+ return true;
+ }
+
+ @Override
+ public void setReadListener(ReadListener arg0) {
+ // this method does nothing
+ }
+
+ }
+
+ private class BufferedRequestWrapper extends HttpServletRequestWrapper {
+ ByteArrayInputStream bais;
+ ByteArrayOutputStream baos;
+ BufferedServletInputStream bsis;
+ byte[] buffer;
+
+ public BufferedRequestWrapper(HttpServletRequest req) throws IOException {
+ super(req);
+
+ InputStream is = req.getInputStream();
+ baos = new ByteArrayOutputStream();
+ byte[] buf = new byte[1024];
+ int letti;
+ while ((letti = is.read(buf)) > 0) {
+ baos.write(buf, 0, letti);
+ }
+ buffer = baos.toByteArray();
+ }
+
+ @Override
+ public ServletInputStream getInputStream() {
+ try {
+ bais = new ByteArrayInputStream(buffer);
+ bsis = new BufferedServletInputStream(bais);
+ } catch (Exception ex) {
+ log.error("Exception in getInputStream", ex);
+ }
+ return bsis;
+ }
+
+ public byte[] getBuffer() {
+ return buffer;
+ }
+ }
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ // this method does nothing
+ }
+
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
+ throws IOException, ServletException {
+ final HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
+ BufferedRequestWrapper bufferedRequest = new BufferedRequestWrapper(httpRequest);
+
+ StringBuilder requestHeaders = new StringBuilder("REQUEST|");
+ requestHeaders.append(httpRequest.getMethod());
+ requestHeaders.append(":");
+ requestHeaders.append(httpRequest.getRequestURL().toString());
+ requestHeaders.append("|");
+ requestHeaders.append(getSecureRequestHeaders(httpRequest));
+ log.info(requestHeaders.toString());
+
+ log.info("REQUEST BODY|" + new String(bufferedRequest.getBuffer()));
+
+ final HttpServletResponse response = (HttpServletResponse) servletResponse;
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final ByteArrayPrintWriter pw = new ByteArrayPrintWriter(baos);
+
+ HttpServletResponse wrappedResp = new HttpServletResponseWrapper(response) {
+ @Override
+ public PrintWriter getWriter() {
+ return pw;
+ }
+
+ @Override
+ public ServletOutputStream getOutputStream() {
+ return pw.getStream();
+ }
+
+ @Override
+ public void sendError(int sc) throws IOException {
+ super.sendError(sc);
+ pw.setError(sc);
+
+ }
+
+ @Override
+ public void sendError(int sc, String msg) throws IOException {
+ super.sendError(sc, msg);
+ pw.setError(sc, msg);
+ }
+ };
+
+ try {
+ filterChain.doFilter(bufferedRequest, wrappedResp);
+ } catch (Exception e) {
+ log.error("Chain Exception", e);
+ throw e;
+ } finally {
+ try {
+ byte[] bytes = baos.toByteArray();
+ StringBuilder responseHeaders = new StringBuilder("RESPONSE HEADERS|");
+ responseHeaders.append(formatResponseHeaders(response));
+ responseHeaders.append("Status:");
+ responseHeaders.append(response.getStatus());
+ responseHeaders.append(";IsCommited:" + wrappedResp.isCommitted());
+
+ log.info(responseHeaders.toString());
+
+ if ("gzip".equals(response.getHeader("Content-Encoding"))) {
+ log.info("UNGZIPED RESPONSE BODY|" + decompressGZIPByteArray(bytes));
+ } else {
+ log.info("RESPONSE BODY|" + new String(bytes));
+ }
+
+ if (pw.hasErrored()) {
+ log.info("ERROR RESPONSE|" + pw.getErrorCode() + ":" + pw.getErrorMsg());
+ } else {
+ if (!wrappedResp.isCommitted()) {
+ response.getOutputStream().write(bytes);
+ response.getOutputStream().flush();
+ }
+ }
+ } catch (Exception e) {
+ log.error("Exception in response filter", e);
+ }
+ }
+ }
+
+ @Override
+ public void destroy() {
+ // this method does nothing
+ }
+
+ private String decompressGZIPByteArray(byte[] bytes) {
+ BufferedReader in = null;
+ InputStreamReader inR = null;
+ ByteArrayInputStream byteS = null;
+ GZIPInputStream gzS = null;
+ StringBuilder str = new StringBuilder();
+ try {
+ byteS = new ByteArrayInputStream(bytes);
+ gzS = new GZIPInputStream(byteS);
+ inR = new InputStreamReader(gzS);
+ in = new BufferedReader(inR);
+
+ if (in != null) {
+ String content;
+ while ((content = in.readLine()) != null) {
+ str.append(content);
+ }
+ }
+
+ } catch (Exception e) {
+ log.error("Failed get read GZIPInputStream", e);
+ } finally {
+ if (byteS != null)
+ try {
+ byteS.close();
+ } catch (IOException e1) {
+ log.error("Failed to close ByteStream", e1);
+ }
+ if (gzS != null)
+ try {
+ gzS.close();
+ } catch (IOException e2) {
+ log.error("Failed to close GZStream", e2);
+ }
+ if (inR != null)
+ try {
+ inR.close();
+ } catch (IOException e3) {
+ log.error("Failed to close InputReader", e3);
+ }
+ if (in != null)
+ try {
+ in.close();
+ } catch (IOException e) {
+ log.error("Failed to close BufferedReader", e);
+ }
+ }
+ return str.toString();
+ }
+
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/SimpleHashMap.java b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/SimpleHashMap.java
new file mode 100644
index 00000000..1e9cedb7
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/SimpleHashMap.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - Logging
+ * ================================================================================
+ * Copyright (C) 2019 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.logging.filter.base;
+
+import java.util.HashMap;
+
+public class SimpleHashMap implements SimpleMap {
+ private HashMap<String, String> map;
+
+ public SimpleHashMap(HashMap<String, String> map) {
+ this.map = map;
+ }
+
+ @Override
+ public String get(String key) {
+ return map.get(key);
+ }
+
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/SimpleJaxrsHeadersMap.java b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/SimpleJaxrsHeadersMap.java
new file mode 100644
index 00000000..50074782
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/SimpleJaxrsHeadersMap.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - Logging
+ * ================================================================================
+ * Copyright (C) 2019 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.logging.filter.base;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+public class SimpleJaxrsHeadersMap implements SimpleMap {
+ MultivaluedMap<String, String> map;
+
+ public SimpleJaxrsHeadersMap(MultivaluedMap<String, String> map) {
+ this.map = map;
+ }
+
+ @Override
+ public String get(String key) {
+ return map.getFirst(key);
+ }
+
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/SimpleMap.java b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/SimpleMap.java
new file mode 100644
index 00000000..9543721f
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/SimpleMap.java
@@ -0,0 +1,25 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - Logging
+ * ================================================================================
+ * Copyright (C) 2019 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.logging.filter.base;
+
+public interface SimpleMap {
+ String get(String key);
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/SimpleServletHeadersMap.java b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/SimpleServletHeadersMap.java
new file mode 100644
index 00000000..e6a91fbe
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/filter/base/SimpleServletHeadersMap.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - Logging
+ * ================================================================================
+ * Copyright (C) 2019 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.logging.filter.base;
+
+import javax.servlet.http.HttpServletRequest;
+
+public class SimpleServletHeadersMap implements SimpleMap {
+ private HttpServletRequest request;
+
+ public SimpleServletHeadersMap(HttpServletRequest request) {
+ this.request = request;
+ }
+
+ @Override
+ public String get(String key) {
+ return request.getHeader(key);
+ }
+
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/ref/slf4j/ONAPLogAdapter.java b/aai-els-onap-logging/src/main/java/org/onap/logging/ref/slf4j/ONAPLogAdapter.java
new file mode 100644
index 00000000..aafc74d4
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/ref/slf4j/ONAPLogAdapter.java
@@ -0,0 +1,616 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j;
+
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.UUID;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.MDC;
+import org.slf4j.Marker;
+import org.slf4j.event.Level;
+
+/**
+ * Extensible adapter for cheaply meeting ONAP logging obligations using
+ * an SLF4J facade.
+ *
+ * <p>This can be used with any SLF4J-compatible logging provider, with
+ * appropriate provider configuration.</p>
+ *
+ * <p>The basics are that:
+ * <ul>
+ * <li>{@link #entering} sets all MDCs.</li>
+ * <li>{@link #exiting} unsets all MDCs *and* logs response information.</li>
+ * <li>{@link #invoke} logs and returns a UUID to passed during invocation,
+ * and optionally sets these for you on your downstream request by way of
+ * an adapter.</li>
+ * <li>Call {@link #getServiceDescriptor()} and its setters to set service-related MDCs.</li>
+ * <li>Call {@link #getResponseDescriptor()} and its setters to set response-related MDCs.</li>
+ * </ul>
+ * </p>
+ *
+ * <p>Minimal usage is:
+ * <ol>
+ * <li>#entering(RequestAdapter)</li>
+ * <li>#invoke, #invoke, ...</li>
+ * <li>#getResponse + setters (or #setResponse)</li>
+ * <li>#exiting</li>
+ * </ol>
+ * </p>
+ *
+ * <p> ... if you're happy for service information to be automatically derived as follows:
+ * <ul>
+ * <li><tt>ServiceName</tt> - from <tt>HttpServletRequest#getRequestURI()</tt></li>
+ * <li><tt>InstanceUUID</tt> - classloader-scope UUID.</li>
+ * </ul>
+ * </p>
+ *
+ * <p>... and if those defaults don't suit, then you can override using properties on
+ * {@link #getServiceDescriptor()}, or by injecting your own adapter using
+ * {@link #setServiceDescriptor(ServiceDescriptor)}, or by overriding
+ * a <tt>protected</tt> methods like{@link #setEnteringMDCs}.</p>
+ *
+ * <p>For everything else:
+ * <ul>
+ * <li>The underlying SLF4J {@link Logger} can be retrieved using {@link #unwrap}.
+ * Use this or create your own using the usual SLF4J factor.</li>
+ * <li>Set whatever MDCs you like.</li>
+ * <li>Log whatever else you like.</li>
+ * </ul>
+ * </p>
+ */
+public class ONAPLogAdapter {
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Constants.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /** String constant for messages <tt>ENTERING</tt>, <tt>EXITING</tt>, etc. */
+ private static final String EMPTY_MESSAGE = "";
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Fields.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /** Automatic UUID, overrideable per adapter or per invocation. */
+ private static UUID sInstanceUUID = UUID.randomUUID();
+
+ /** Logger delegate. */
+ private Logger mLogger;
+
+ /** Overrideable descriptor for the service doing the logging. */
+ private ServiceDescriptor mServiceDescriptor = new ServiceDescriptor();
+
+ /** Overrideable descriptor for the response returned by the service doing the logging. */
+ private ResponseDescriptor mResponseDescriptor = new ResponseDescriptor();
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Constructors.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Construct adapter.
+ *
+ * @param logger non-null logger.
+ */
+ public ONAPLogAdapter(final Logger logger) {
+ this.mLogger = checkNotNull(logger);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Public methods.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Get logger.
+ *
+ * @return unwrapped logger.
+ */
+ public Logger unwrap() {
+ return this.mLogger;
+ }
+
+ /**
+ * Report <tt>ENTERING</tt> marker.
+ *
+ * @param request non-null incoming request (wrapper).
+ * @return this.
+ */
+ public ONAPLogAdapter entering(final RequestAdapter request) {
+
+ checkNotNull(request);
+
+ // Default the service name.
+
+ this.setEnteringMDCs(request);
+ this.mLogger.info(ONAPLogConstants.Markers.ENTRY, EMPTY_MESSAGE);
+
+ return this;
+ }
+
+ /**
+ * Report <tt>ENTERING</tt> marker.
+ *
+ * @param request non-null incoming request.
+ * @return this.
+ */
+ public ONAPLogAdapter entering(final HttpServletRequest request) {
+ return this.entering(new HttpServletRequestAdapter(checkNotNull(request)));
+ }
+
+ /**
+ * Report <tt>EXITING</tt> marker.
+ *
+ * @return this.
+ */
+ public ONAPLogAdapter exiting() {
+ try {
+ this.mResponseDescriptor.setMDCs();
+ this.mLogger.info(ONAPLogConstants.Markers.EXIT, EMPTY_MESSAGE);
+ }
+ finally {
+ MDC.clear();
+ }
+ return this;
+ }
+
+ /**
+ * Report pending invocation with <tt>INVOKE</tt> marker.
+ *
+ * <p>If you call this variant, then YOU are assuming responsibility for
+ * setting the requisite ONAP headers.</p>
+ *
+ * @param sync whether synchronous.
+ * @return invocation ID to be passed with invocation.
+ */
+ public UUID invoke(final ONAPLogConstants.InvocationMode sync) {
+
+ final UUID invocationID = UUID.randomUUID();
+
+ // Derive SYNC/ASYNC marker.
+
+ final Marker marker = (sync == null) ? ONAPLogConstants.Markers.INVOKE : sync.getMarker();
+
+ // Log INVOKE*, with the invocationID as the message body.
+ // (We didn't really want this kind of behavior in the standard,
+ // but is it worse than new, single-message MDC?)
+
+ this.mLogger.info(marker, "{}", invocationID);
+ return invocationID;
+ }
+
+ /**
+ * Report pending invocation with <tt>INVOKE</tt> marker,
+ * setting standard ONAP logging headers automatically.
+ *
+ * @param builder request builder, for setting headers.
+ * @param sync whether synchronous, nullable.
+ * @return invocation ID to be passed with invocation.
+ */
+ public UUID invoke(final RequestBuilder builder,
+ final ONAPLogConstants.InvocationMode sync) {
+
+ // Sync can be defaulted. Builder cannot.
+
+ checkNotNull(builder);
+
+ // Log INVOKE, and retain invocation ID for header + return.
+
+ final UUID invocationID = this.invoke(sync);
+
+ // Set standard HTTP headers on (southbound request) builder.
+
+ builder.setHeader(ONAPLogConstants.Headers.REQUEST_ID,
+ defaultToEmpty(MDC.get(ONAPLogConstants.MDCs.REQUEST_ID)));
+ builder.setHeader(ONAPLogConstants.Headers.INVOCATION_ID,
+ defaultToEmpty(invocationID));
+ builder.setHeader(ONAPLogConstants.Headers.PARTNER_NAME,
+ defaultToEmpty(MDC.get(ONAPLogConstants.MDCs.PARTNER_NAME)));
+
+ return invocationID;
+ }
+
+ /**
+ * Report vanilla <tt>INVOKE</tt> marker.
+ *
+ * @param builder builder for downstream requests, if you want the
+ * standard ONAP headers to be added automatically.
+ * @return invocation ID to be passed with invocation.
+ */
+ public UUID invoke(final RequestBuilder builder) {
+ return this.invoke(builder, (ONAPLogConstants.InvocationMode)null);
+ }
+
+ /**
+ * Get descriptor, for overriding service details.
+ * @return non-null descriptor.
+ */
+ public ServiceDescriptor getServiceDescriptor() {
+ return checkNotNull(this.mServiceDescriptor);
+ }
+
+ /**
+ * Override {@link ServiceDescriptor}.
+ * @param d non-null override.
+ * @return this.
+ */
+ public ONAPLogAdapter setServiceDescriptor(final ServiceDescriptor d) {
+ this.mServiceDescriptor = checkNotNull(d);
+ return this;
+ }
+
+ /**
+ * Get descriptor, for setting response details.
+ * @return non-null descriptor.
+ */
+ public ResponseDescriptor getResponseDescriptor() {
+ return checkNotNull(this.mResponseDescriptor);
+ }
+
+ /**
+ * Override {@link ResponseDescriptor}.
+ * @param d non-null override.
+ * @return this.
+ */
+ public ONAPLogAdapter setResponseDescriptor(final ResponseDescriptor d) {
+ this.mResponseDescriptor = checkNotNull(d);
+ return this;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Protected methods.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Set MDCs that persist for the duration of an invocation.
+ *
+ * <p>It would be better to roll this into {@link #entering}, like
+ * with {@link #exiting}. Then it would be easier to do, but it
+ * would mean more work. </p>
+ *
+ * @param request incoming HTTP request.
+ * @return this.
+ */
+ protected ONAPLogAdapter setEnteringMDCs(final RequestAdapter<?> request) {
+
+ // Extract MDC values from standard HTTP headers.
+
+ final String requestID = defaultToUUID(request.getHeader(ONAPLogConstants.Headers.REQUEST_ID));
+ final String invocationID = defaultToUUID(request.getHeader(ONAPLogConstants.Headers.INVOCATION_ID));
+ final String partnerName = defaultToEmpty(request.getHeader(ONAPLogConstants.Headers.PARTNER_NAME));
+
+ // Set standard MDCs. Override this entire method if you want to set
+ // others, OR set them BEFORE or AFTER the invocation of #entering,
+ // depending on where you need them to appear, OR extend the
+ // ServiceDescriptor to add them.
+
+ MDC.put(ONAPLogConstants.MDCs.INVOKE_TIMESTAMP,
+ ZonedDateTime.now(ZoneOffset.UTC)
+ .format(DateTimeFormatter.ISO_INSTANT));
+ MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, requestID);
+ MDC.put(ONAPLogConstants.MDCs.INVOCATION_ID, invocationID);
+ MDC.put(ONAPLogConstants.MDCs.PARTNER_NAME, partnerName);
+ MDC.put(ONAPLogConstants.MDCs.CLIENT_IP_ADDRESS, defaultToEmpty(request.getClientAddress()));
+ MDC.put(ONAPLogConstants.MDCs.SERVER_FQDN, defaultToEmpty(request.getServerAddress()));
+
+ // Delegate to the service adapter, for service-related DMCs.
+
+ this.mServiceDescriptor.setMDCs();
+
+ // Default the service name to the requestURI, in the event that
+ // no value has been provided.
+
+ if (MDC.get(ONAPLogConstants.MDCs.SERVICE_NAME) == null ||
+ MDC.get(ONAPLogConstants.MDCs.SERVICE_NAME).equalsIgnoreCase(EMPTY_MESSAGE)) {
+ MDC.put(ONAPLogConstants.MDCs.SERVICE_NAME, request.getRequestURI());
+ }
+
+ return this;
+ }
+
+ /**
+ * Dependency-free nullcheck.
+ *
+ * @param in to be checked.
+ * @param <T> argument (and return) type.
+ * @return input arg.
+ */
+ protected static <T> T checkNotNull(final T in) {
+ if (in == null) {
+ throw new NullPointerException();
+ }
+ return in;
+ }
+
+ /**
+ * Dependency-free string default.
+ *
+ * @param in to be filtered.
+ * @return input string or null.
+ */
+ protected static String defaultToEmpty(final Object in) {
+ if (in == null) {
+ return "";
+ }
+ return in.toString();
+ }
+
+ /**
+ * Dependency-free string default.
+ *
+ * @param in to be filtered.
+ * @return input string or null.
+ */
+ protected static String defaultToUUID(final String in) {
+ if (in == null) {
+ return UUID.randomUUID().toString();
+ }
+ return in;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Inner classes.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Extensible descriptor for reporting service details.
+ *
+ * <p>In most cases extension isn't required. </p>
+ */
+ public static class ServiceDescriptor {
+
+ /** <tt>ServiceName</tt>. */
+ protected String mName;
+
+ /** <tt>InstanceUUID</tt>. */
+ protected String mUUID = sInstanceUUID.toString();
+
+ /**
+ * Set name.
+ * @param name <tt>ServiceName</tt>.
+ * @return this.
+ */
+ public ServiceDescriptor setServiceName(final String name) {
+ this.mName = name;
+ return this;
+ }
+
+ /**
+ * Set name.
+ * @param uuid <tt>InstanceUUID</tt>.
+ * @return this.
+ */
+ public ServiceDescriptor setServiceUUID(final String uuid) {
+ this.mUUID = uuid;
+ return this;
+ }
+
+ /**
+ * Set MDCs. Once set they remain set until everything is cleared.
+ */
+ protected void setMDCs() {
+ MDC.put(ONAPLogConstants.MDCs.SERVICE_NAME, defaultToEmpty(this.mName));
+ MDC.put(ONAPLogConstants.MDCs.INSTANCE_UUID, defaultToEmpty(this.mUUID));
+ }
+ }
+
+ /**
+ * Response is different in that response MDCs are normally only
+ * reported once, for a single log message. (But there's no method
+ * for clearing them, because this is only expected to be called
+ * during <tt>#exiting</tt>.)
+ */
+ public static class ResponseDescriptor {
+
+ /** Response errorcode. */
+ protected String mCode;
+
+ /** Response description. */
+ protected String mDescription;
+
+ /** Response severity. */
+ protected Level mSeverity;
+
+ /** Response status, of {<tt>COMPLETED</tt>, <tt>ERROR</tt>}. */
+ protected ONAPLogConstants.ResponseStatus mStatus;
+
+ /**
+ * Setter.
+ *
+ * @param code response (error) code.
+ * @return this.
+ */
+ public ResponseDescriptor setResponseCode(final String code) {
+ this.mCode = code;
+ return this;
+ }
+
+ /**
+ * Setter.
+ *
+ * @param description response description.
+ * @return this.
+ */
+ public ResponseDescriptor setResponseDescription(final String description) {
+ this.mDescription = description;
+ return this;
+ }
+
+ /**
+ * Setter.
+ *
+ * @param severity response outcome severity.
+ * @return this.
+ */
+ public ResponseDescriptor setResponseSeverity(final Level severity) {
+ this.mSeverity = severity;
+ return this;
+ }
+
+ /**
+ * Setter.
+ *
+ * @param status response overall status.
+ * @return this.
+ */
+ public ResponseDescriptor setResponseStatus(final ONAPLogConstants.ResponseStatus status) {
+ this.mStatus = status;
+ return this;
+ }
+
+ /**
+ * Overrideable method to set MDCs based on property values.
+ */
+ protected void setMDCs() {
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_CODE, defaultToEmpty(this.mCode));
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION, defaultToEmpty(this.mDescription));
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_SEVERITY, defaultToEmpty(this.mSeverity));
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, defaultToEmpty(this.mStatus));
+ }
+ }
+
+ /**
+ * Adapter for reading information from an incoming HTTP request.
+ *
+ * <p>Incoming is generally easy, because in most cases you'll be able to
+ * get your hands on the <tt>HttpServletRequest</tt>.</p>
+ *
+ * <p>Perhaps should be generalized to refer to constants instead of
+ * requiring the implementation of specific methods.</p>
+ *
+ * @param <T> type, for chaining.
+ */
+ public interface RequestAdapter<T extends RequestAdapter> {
+
+ /**
+ * Get header by name.
+ * @param name header name.
+ * @return header value, or null.
+ */
+ String getHeader(String name);
+
+ /**
+ * Get client address.
+ * @return address, if available.
+ */
+ String getClientAddress();
+
+ /**
+ * Get server address.
+ * @return address, if available.
+ */
+ String getServerAddress();
+
+ /**
+ * Get default service name, from service URI.
+ * @return service name default.
+ */
+ String getRequestURI();
+ }
+
+ /**
+ * Default {@link RequestBuilder} impl for {@link HttpServletRequest}, which
+ * will should available for most incoming REST requests.
+ */
+ public static class HttpServletRequestAdapter implements RequestAdapter<HttpServletRequestAdapter> {
+
+ /** Wrapped HTTP request. */
+ private final HttpServletRequest mRequest;
+
+ /**
+ * Construct adapter for HTTP request.
+ * @param request to be wrapped;
+ */
+ public HttpServletRequestAdapter(final HttpServletRequest request) {
+ this.mRequest = checkNotNull(request);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getHeader(final String name) {
+ return this.mRequest.getHeader(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getClientAddress() {
+ return this.mRequest.getRemoteAddr();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getServerAddress() {
+ return this.mRequest.getServerName();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getRequestURI() {
+ return this.mRequest.getRequestURI();
+ }
+ }
+
+ /**
+ * Header builder, which (unlike {@link RequestAdapter} will tend to
+ * vary a lot from caller to caller, since they each get to choose their
+ * own REST (or HTTP, or whatever) client APIs.
+ *
+ * <p>No default implementation, because there's no HTTP client that's
+ * sufficiently ubiquitous to warrant incurring a mandatory dependency.</p>
+ *
+ * @param <T> type, for chaining.
+ */
+ public interface RequestBuilder<T extends RequestBuilder> {
+
+ /**
+ * Set HTTP header.
+ * @param name header name.
+ * @param value header value.
+ * @return this.
+ */
+ T setHeader(String name, String value);
+ }
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/ref/slf4j/ONAPLogConstants.java b/aai-els-onap-logging/src/main/java/org/onap/logging/ref/slf4j/ONAPLogConstants.java
new file mode 100644
index 00000000..77ca084d
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/ref/slf4j/ONAPLogConstants.java
@@ -0,0 +1,289 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j;
+
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+
+/**
+ * Constants for standard ONAP headers, MDCs, etc.
+ *
+ * <p>See <tt>package-info.java</tt>.</p>
+ */
+public final class ONAPLogConstants {
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Constructors.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Hide and forbid construction.
+ */
+ private ONAPLogConstants() {
+ throw new UnsupportedOperationException();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Inner classes.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Marker constants.
+ */
+ public static final class Markers {
+
+ /** Marker reporting invocation. */
+ public static final Marker INVOKE = MarkerFactory.getMarker("INVOKE");
+
+ /** Marker reporting invocation return. */
+ public static final Marker INVOKE_RETURN = MarkerFactory.getMarker("INVOKE_RETURN");
+
+ /** Marker reporting synchronous invocation. */
+ public static final Marker INVOKE_SYNCHRONOUS = build("INVOKE", "SYNCHRONOUS");
+
+ /** Marker reporting asynchronous invocation. */
+ public static final Marker INVOKE_ASYNCHRONOUS = build("INVOKE", "ASYNCHRONOUS");
+
+ /** Marker reporting entry into a component. */
+ public static final Marker ENTRY = MarkerFactory.getMarker("ENTRY");
+
+ /** Marker reporting exit from a component. */
+ public static final Marker EXIT = MarkerFactory.getMarker("EXIT");
+
+ /**
+ * Build nested, detached marker.
+ * @param m1 top token.
+ * @param m2 sub-token.
+ * @return detached Marker.
+ */
+ private static Marker build(final String m1, final String m2) {
+ final Marker marker = MarkerFactory.getDetachedMarker(m1);
+ marker.add(MarkerFactory.getDetachedMarker(m2));
+ return marker;
+ }
+
+ /**
+ * Hide and forbid construction.
+ */
+ private Markers() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * MDC name constants.
+ */
+ public static final class MDCs {
+
+ // Tracing. ////////////////////////////////////////////////////////////
+
+ /** MDC correlating messages for an invocation. */
+ public static final String INVOCATION_ID = "InvocationID";
+
+ /** MDC correlating messages for a logical transaction. */
+ public static final String REQUEST_ID = "RequestID";
+
+ /** MDC recording calling partner name. */
+ public static final String PARTNER_NAME = "PartnerName";
+
+ /** MDC recording current service. */
+ public static final String SERVICE_NAME = "ServiceName";
+
+ /** MDC recording target service. */
+ public static final String TARGET_SERVICE_NAME = "TargetServiceName";
+
+ /** MDC recording target entity. */
+ public static final String TARGET_ENTITY = "TargetEntity";
+
+ /** MDC recording target element. */
+ public static final String TARGET_ELEMENT = "TargetElement";
+
+ /** MDC recording current service instance id. */
+ public static final String SERVICE_INSTANCE_ID = "ServiceInstanceID";
+
+ /** MDC recording current instance id. */
+ public static final String INSTANCE_UUID = "InstanceID";
+
+ // Network. ////////////////////////////////////////////////////////////
+
+ /** MDC recording caller address. */
+ public static final String CLIENT_IP_ADDRESS = "ClientIPAddress";
+
+ /** MDC recording server IP address. */
+ public static final String SERVER_IP_ADDRESS = "ServerIPAddress";
+
+ /** MDC recording server FQDN. */
+ public static final String SERVER_FQDN = "ServerFQDN";
+
+ /** MDC recording virtual server name. */
+ public static final String VIRTUAL_SERVER_NAME = "VirtualServerName";
+
+ /** MDC recording context name. */
+ public static final String CONTEXT_NAME = "ContextName";
+
+ /**
+ * MDC recording timestamp at the start of the current request,
+ * with the same scope as {@link #REQUEST_ID}.
+ *
+ * <p>Open issues:
+ * <ul>
+ * <ul>Easily confused with {@link #INVOKE_TIMESTAMP}.</ul>
+ * <ul>No mechanism for propagation between components, e.g. via HTTP headers.</ul>
+ * <ul>Whatever mechanism we define, it's going to be costly.</ul>
+ * </ul>
+ * </p>
+ * */
+ public static final String ENTRY_TIMESTAMP = "EntryTimestamp";
+
+ /** MDC recording timestamp at the start of the current invocation. */
+ public static final String INVOKE_TIMESTAMP = "InvokeTimestamp";
+
+ /** MDC recording elapsed time. */
+ public static final String ELAPSED_TIME = "ElapsedTime";
+
+ /** MDC recording log timestamp. */
+ public static final String LOG_TIMESTAMP = "LogTimestamp";
+
+ // Outcomes. ///////////////////////////////////////////////////////////
+
+ /** MDC reporting outcome code. */
+ public static final String RESPONSE_CODE = "ResponseCode";
+
+ /** MDC reporting outcome description. */
+ public static final String RESPONSE_DESCRIPTION = "ResponseDesc";
+
+ /** MDC reporting severity */
+ public static final String RESPONSE_SEVERITY = "Severity";
+
+ /** MDC reporting response status code */
+ public static final String RESPONSE_STATUS_CODE = "StatusCode";
+
+ /** MDC recording error code. */
+ public static final String ERROR_CODE = "ErrorCode";
+
+ /** MDC recording error description. */
+ public static final String ERROR_DESC = "ErrorDesc";
+
+ // Unsorted. ///////////////////////////////////////////////////////////
+
+ /**
+ * Hide and forbid construction.
+ */
+ private MDCs() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * Header name constants.
+ */
+ public static final class Headers {
+
+ /** HTTP <tt>X-ONAP-RequestID</tt> header. */
+ public static final String REQUEST_ID = "X-ONAP-RequestID";
+
+ /** HTTP <tt>X-ONAP-InvocationID</tt> header. */
+ public static final String INVOCATION_ID = "X-ONAP-InvocationID";
+
+ /** HTTP <tt>X-ONAP-PartnerName</tt> header. */
+ public static final String PARTNER_NAME = "X-ONAP-PartnerName";
+
+ /**
+ * Hide and forbid construction.
+ */
+ private Headers() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Enums.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Response success or not, for setting <tt>StatusCode</tt>.
+ */
+ public enum ResponseStatus {
+
+ /** Success. */
+ COMPLETE,
+
+ /** Not. */
+ ERROR,
+
+ /** In Progress. */
+ INPROGRESS
+ }
+
+ /**
+ * Synchronous or asynchronous execution, for setting invocation marker.
+ */
+ public enum InvocationMode {
+
+ /** Synchronous, blocking. */
+ SYNCHRONOUS("SYNCHRONOUS", Markers.INVOKE_SYNCHRONOUS),
+
+ /** Asynchronous, non-blocking. */
+ ASYNCHRONOUS("ASYNCHRONOUS", Markers.INVOKE_ASYNCHRONOUS);
+
+ /** Enum value. */
+ private String mString;
+
+ /** Corresponding marker. */
+ private Marker mMarker;
+
+ /**
+ * Construct enum.
+ *
+ * @param s enum value.
+ * @param m corresponding Marker.
+ */
+ InvocationMode(final String s, final Marker m) {
+ this.mString = s;
+ this.mMarker = m;
+ }
+
+ /**
+ * Get Marker for enum.
+ *
+ * @return Marker.
+ */
+ public Marker getMarker() {
+ return this.mMarker;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return this.mString;
+ }
+ }
+
+}
diff --git a/aai-els-onap-logging/src/main/java/org/onap/logging/ref/slf4j/package-info.java b/aai-els-onap-logging/src/main/java/org/onap/logging/ref/slf4j/package-info.java
new file mode 100644
index 00000000..d9a62472
--- /dev/null
+++ b/aai-els-onap-logging/src/main/java/org/onap/logging/ref/slf4j/package-info.java
@@ -0,0 +1,32 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * 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.logging.ref.slf4j;
+
+/**
+ * <p>Code in here has potential application outside this reference
+ * example, and accordingly:
+ * <ul>
+ * <li>Packaged in <tt>common</tt>.</li>
+ * <li>Has minimal dependencies.</li>
+ * </ul>
+ * </p>
+ */ \ No newline at end of file