aboutsummaryrefslogtreecommitdiffstats
path: root/common-logging/src/main/java/org/onap/policy/common/logging/OnapLoggingContext.java
diff options
context:
space:
mode:
authorJim Hahn <jrh3@att.com>2019-07-05 13:03:06 -0400
committerJim Hahn <jrh3@att.com>2019-07-05 17:36:12 -0400
commit02ba37e23bebc5fc8831feaa4ce073295c3c93d8 (patch)
tree4b4b99ec0d2d429fe2d857e3992d5e893615f6b1 /common-logging/src/main/java/org/onap/policy/common/logging/OnapLoggingContext.java
parent53f9550501ca1854318c1f552b0aba2e255b6748 (diff)
Fix sonar issues in policy ONAP logging
Sonar fixes, other than code coverage. These changes are disruptive and will likely cause breakage in a number of policy repos. Renamed constants. Moved constants/factories from interfaces to classes. Also fixed remaining checkstyle issues, which was equally disruptive, as it required renaming of methods and classes. Split out Onap config properties from EELF config properties, in case changes are made in the future such that Onap properties can no longer subclass from EELF properties (e.g., if EELF properties are converted from a interface to a utility class with a private constructor). Attempted to eliminate some duplicate blocks of code by refactoring out common methods. Change-Id: Ie038d2d4ed553037a9af3f0ddf31baf2b3628fa3 Issue-ID: POLICY-1791 Signed-off-by: Jim Hahn <jrh3@att.com>
Diffstat (limited to 'common-logging/src/main/java/org/onap/policy/common/logging/OnapLoggingContext.java')
-rw-r--r--common-logging/src/main/java/org/onap/policy/common/logging/OnapLoggingContext.java568
1 files changed, 568 insertions, 0 deletions
diff --git a/common-logging/src/main/java/org/onap/policy/common/logging/OnapLoggingContext.java b/common-logging/src/main/java/org/onap/policy/common/logging/OnapLoggingContext.java
new file mode 100644
index 00000000..0373abfe
--- /dev/null
+++ b/common-logging/src/main/java/org/onap/policy/common/logging/OnapLoggingContext.java
@@ -0,0 +1,568 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP-Logging
+ * ================================================================================
+ * Copyright (C) 2017-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.policy.common.logging;
+
+import java.text.SimpleDateFormat;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Date;
+
+import org.onap.policy.common.logging.nsa.LoggingContextFactory;
+import org.onap.policy.common.logging.nsa.SharedLoggingContext;
+import org.slf4j.MDC;
+
+/**
+ * A facade over the org.onap.policy.common.logging.nsa.SharedLoggingContext
+ * interface/implementation that makes it more convenient to use. SharedLoggingContext builds on the
+ * SLF4J/log4j Mapped Diagnostic Context (MDC) feature, which provides a hashmap-based context for
+ * data items that need to be logged, where the hashmap is kept in ThreadLocal storage. The data
+ * items can be referenced in the log4j configuration using the EnhancedPatternLayout appender
+ * layout class, and the notation "%X{key}" in the ConversionPattern string, where "key" is one of
+ * the keys in the MDC hashmap (which is determined by what hashmap entries the application code
+ * creates). Example: log4j.appender.auditAppender.layout=org.apache.log4j.EnhancedPatternLayout
+ * log4j.appender.auditAppender.layout.ConversionPattern=%d|%X{requestId}|%X{serviceInstanceId}|...|%m%n
+ * where "requestId" and "serviceInstanceId" are entries in the MDC hashmap.
+ *
+ * <p>The notable functionality the SharedLoggingContext adds over MDC is that it maintains its own
+ * copy of the MDC data items in a hashmap (not in ThreadLocal storage), which allows more control
+ * of the data. The ONAPLoggingContext constructor that takes another ONAPLoggingContext object as a
+ * parameter makes use of this feature. For example if there is a thread pulling requests from a
+ * queue for processing, it can keep a base logging context with data that is common to all
+ * requests, and for each request, create a new logging context with that base context as a
+ * parameter; this will create a new logging context with those initial values and none of the
+ * request-specific values from the previous request such as a request ID.
+ *
+ * <p>The setter methods in this class set corresponding items in the SharedLoggingContext/MDC
+ * hashmaps. These items correspond to the fields defined in the "ONAP platform application logging
+ * guidelines" document. In addition, there is a pair of convenience functions, transactionStarted()
+ * and transactionEnded(), that can be called at the beginning and end of transaction processing to
+ * calculate the duration of the transaction and record that value in the "timer" item.
+ *
+ */
+public class OnapLoggingContext {
+
+ private static final String REQUEST_ID = "requestId";
+ private static final String SERVICE_INSTANCE_ID = "serviceInstanceId";
+ private static final String THREAD_ID = "threadId";
+ private static final String SERVER_NAME = "serverName";
+ private static final String SERVICE_NAME = "serviceName";
+ private static final String PARTNER_NAME = "partnerName";
+ private static final String STATUS_CODE = "statusCode";
+ private static final String TARGET_ENTITY = "targetEntity";
+ private static final String TARGET_SERVICE_NAME = "targetServiceName";
+ private static final String INSTANCE_UUID = "instanceUuid";
+ private static final String SEVERITY = "severity";
+ private static final String SERVER_IP_ADDRESS = "serverIpAddress";
+ private static final String SERVER = "server";
+ private static final String CLIENT_IP_ADDRESS = "clientIpAddress";
+ private static final String CLASSNAME = "classname";
+ private static final String TRANSACTION_BEGIN_TIME_STAMP = "TransactionBeginTimestamp";
+ private static final String TRANSACTION_END_TIME_STAMP = "TransactionEndTimestamp";
+ private static final String TRANSACTION_ELAPSED_TIME = "TransactionElapsedTime";
+ private static final String METRIC_BEGIN_TIME_STAMP = "MetricBeginTimestamp";
+ private static final String METRIC_END_TIME_STAMP = "MetricEndTimestamp";
+ private static final String METRIC_ELAPSED_TIME = "MetricElapsedTime";
+ private static final String POLICY = "POLICY";
+ private static final String USER = "USER";
+ private static final String COMPLETE = "COMPLETE";
+ private static final String PE_PROCESS = "PE Process";
+ private static final String TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS+00:00";
+ private static final String EMPTY_STRING = "";
+ private static final int DEFAULT_VALUE = 0;
+
+
+ private static LoggingContextFactory.Builder loggingContextBuilder = new LoggingContextFactory.Builder();
+
+ protected SharedLoggingContext context = null;
+ private Instant transactionStartTime;
+ private Instant metricStartTime;
+
+ /**
+ * Create a new ONAPLoggingContext with no base context.
+ */
+ public OnapLoggingContext() {
+ context = (SharedLoggingContext) loggingContextBuilder.forSharing().build();
+ }
+
+ /**
+ * Create a new ONAPLoggingContext initially populated with the values in the given base
+ * context. This can be used for example in a servlet where each incoming request may be
+ * processed by a separate thread, but there may be some logging data items that will be
+ * unchanging and common to all the threads. That constant data can be populated in a base
+ * context, and then each request handler creates new context passing that base context to
+ * populate the common data in the new one.
+ *
+ * @param baseContext onap logging context
+ */
+ public OnapLoggingContext(OnapLoggingContext baseContext) {
+ context = (SharedLoggingContext) loggingContextBuilder.forSharing().build();
+ // a logging context could be passed into a thread (e.g. one that is servicing a queue)
+ // that already had a logging context established, so the MDC hashmap could contain
+ // entries that are no longer appropriate; so clear out the MDC hashmap before
+ // transferring the new logging context values.
+ // x
+ MDC.clear();
+ baseContext.context.transferTo(context);
+ transactionStartTime = baseContext.transactionStartTime;
+ setServiceName(POLICY);
+ setPartnerName(USER);
+ setStatusCode(COMPLETE);
+ setTargetEntity(POLICY);
+ setTargetServiceName(PE_PROCESS);
+ }
+
+ /**
+ * Indicate the start of transaction processing. The current system time will be recorded for
+ * use by <code>transactionEnded()</code> to calculate the duration of the transaction.
+ */
+ public void transactionStarted() {
+ transactionStartTime = Instant.now();
+ setTransactionBeginTimestamp(transactionStartTime);
+ }
+
+ /**
+ * Indicate the end of transaction processing. The difference between the current system time
+ * and the time recorded by <code>transactionStarted()</code> will be recorded in the data item
+ * with key "TransactionElapsedTime".
+ */
+ public void transactionEnded() {
+ Instant transactionEndTime = Instant.now();
+ setTransactionEndTimestamp(transactionEndTime);
+ setTransactionElapsedTime(transactionEndTime);
+ }
+
+ /**
+ * Indicate the start of metric processing. The current system time will be recorded for use by
+ * <code>metricEnded()</code> to calculate the duration of the metric.
+ */
+ public void metricStarted() {
+ metricStartTime = Instant.now();
+ setMetricBeginTimestamp(metricStartTime);
+ }
+
+ /**
+ * Indicate the end of metric processing. The difference between the current system time and the
+ * time recorded by <code>metricStarted()</code> will be recorded in the data item with key
+ * "MetricElapsedTime".
+ */
+ public void metricEnded() {
+ Instant metricEndTime = Instant.now();
+ setMetricEndTimestamp(metricEndTime);
+ setMetricElapsedTime(metricEndTime);
+ }
+
+ /**
+ * Set the value for the data item with key "requestId".
+ *
+ * @param id request identifier
+ */
+ public void setRequestId(String id) {
+ context.put(REQUEST_ID, id);
+ }
+
+ /**
+ * Get the value for the data item with key "requestId".
+ *
+ * @return current value, or empty string if not set
+ */
+ public String getRequestId() {
+ return context.get(REQUEST_ID, EMPTY_STRING);
+ }
+
+ /**
+ * Set the value for the data item with key "serviceInstanceId".
+ *
+ * @param id service identifier
+ */
+ public void setServiceInstanceId(String id) {
+ context.put(SERVICE_INSTANCE_ID, id);
+ }
+
+ /**
+ * Get the value for the data item with key "serviceInstanceId".
+ *
+ * @return current value, or empty string if not set
+ */
+ public String getServiceInstanceId() {
+ return context.get(SERVICE_INSTANCE_ID, EMPTY_STRING);
+ }
+
+ /**
+ * Set the value for the data item with key "threadId". An alternative to using this item is to
+ * use the %t conversion character in the appender's conversion string.
+ *
+ * @param id thread identifier
+ */
+ public void setThreadId(String id) {
+ context.put(THREAD_ID, id);
+ }
+
+ /**
+ * Get the value for the data item with key "threadId".
+ *
+ * @return current value, or empty string if not set
+ */
+ public String getThreadId() {
+ return context.get(THREAD_ID, EMPTY_STRING);
+ }
+
+ /**
+ * Set the value for the data item with key "serverName".
+ *
+ * @param name server name
+ */
+ public void setServerName(String name) {
+ context.put(SERVER_NAME, name);
+ }
+
+ /**
+ * Get the value for the data item with key "serverName".
+ *
+ * @return current value, or empty string if not set
+ */
+ public String getServerName() {
+ return context.get(SERVER_NAME, EMPTY_STRING);
+ }
+
+ /**
+ * Set the value for the data item with key "serviceName".
+ *
+ * @param name service name
+ */
+ public void setServiceName(String name) {
+ context.put(SERVICE_NAME, name);
+ }
+
+ /**
+ * Get the value for the data item with key "serviceName".
+ *
+ * @return current value, or empty string if not set
+ */
+ public String getServiceName() {
+ return context.get(SERVICE_NAME, EMPTY_STRING);
+ }
+
+ /**
+ * Set the value for the data item with key "partnerName".
+ *
+ * @param name partner name
+ */
+ public void setPartnerName(String name) {
+ context.put(PARTNER_NAME, name);
+ }
+
+ /**
+ * Get the value for the data item with key "partnerName".
+ *
+ * @return current value, or empty string if not set
+ */
+ public String getPartnerName() {
+ return context.get(PARTNER_NAME, EMPTY_STRING);
+ }
+
+ /**
+ * Set the value for the data item with key "statusCode".
+ *
+ * @param name status code
+ */
+ public void setStatusCode(String name) {
+ context.put(STATUS_CODE, name);
+ }
+
+ /**
+ * Get the value for the data item with key "statusCode".
+ *
+ * @return current value, or empty string if not set
+ */
+ public String getStatusCode() {
+ return context.get(STATUS_CODE, EMPTY_STRING);
+ }
+
+ /**
+ * Set the value for the data item with key "targetEntity".
+ *
+ * @param name target entity
+ */
+ public void setTargetEntity(String name) {
+ context.put(TARGET_ENTITY, name);
+ }
+
+ /**
+ * Get the value for the data item with key "targetEntity".
+ *
+ * @return current value, or empty string if not set
+ */
+ public String getTargetEntity() {
+ return context.get(TARGET_ENTITY, EMPTY_STRING);
+ }
+
+ /**
+ * Set the value for the data item with key "targetServiceName".
+ *
+ * @param name target service name
+ */
+ public void setTargetServiceName(String name) {
+ context.put(TARGET_SERVICE_NAME, name);
+ }
+
+ /**
+ * Get the value for the data item with key "targetServiceName".
+ *
+ * @return current value, or empty string if not set
+ */
+ public String getTargetServiceName() {
+ return context.get(TARGET_SERVICE_NAME, EMPTY_STRING);
+ }
+
+ /**
+ * Set the value for the data item with key "instanceUuid".
+ *
+ * @param uuid instance uuid
+ */
+ public void setInstanceUuid(String uuid) {
+ context.put(INSTANCE_UUID, uuid);
+ }
+
+ /**
+ * Get the value for the data item with key "instanceUuid".
+ *
+ * @return current value, or empty string if not set
+ */
+ public String getInstanceUuid() {
+ return context.get(INSTANCE_UUID, EMPTY_STRING);
+ }
+
+ /**
+ * Set the value for the data item with key "severity".
+ *
+ * @param severity severity
+ */
+ public void setSeverity(Long severity) {
+ context.put(SEVERITY, severity);
+ }
+
+ /**
+ * Get the value for the data item with key "severity".
+ *
+ * @return current value, or empty string if not set
+ */
+ public String getSeverity() {
+ return context.get(SEVERITY, EMPTY_STRING);
+ }
+
+ /**
+ * Set the value for the data item with key "serverIp".
+ *
+ * @param serverIp server ip address
+ */
+ public void setServerIpAddress(String serverIp) {
+ context.put(SERVER_IP_ADDRESS, serverIp);
+ }
+
+ /**
+ * Get the value for the data item with key "serverIp".
+ *
+ * @return current value, or empty string if not set
+ */
+ public String getServerIpAddress() {
+ return context.get(SERVER_IP_ADDRESS, EMPTY_STRING);
+ }
+
+ /**
+ * Set the value for the data item with key "server".
+ *
+ * @param server server
+ */
+ public void setServer(String server) {
+ context.put(SERVER, server);
+ }
+
+ /**
+ * Get the value for the data item with key "server".
+ *
+ * @return current value, or empty string if not set
+ */
+ public String getServer() {
+ return context.get(SERVER, EMPTY_STRING);
+ }
+
+ /**
+ * Set the value for the data item with key "clientIp".
+ *
+ * @param clientIp client ip address
+ */
+ public void setClientIpAddress(String clientIp) {
+ context.put(CLIENT_IP_ADDRESS, clientIp);
+ }
+
+ /**
+ * Get the value for the data item with key "clientIp".
+ *
+ * @return current value, or empty string if not set
+ */
+ public String getClientIpAddress() {
+ return context.get(CLIENT_IP_ADDRESS, EMPTY_STRING);
+ }
+
+ /**
+ * Set the value for the data item with key "classname". Use of this item is not recommended
+ * (unless it is used to indicate something other than the Java classname) since it would be
+ * unwieldy to maintain a correct value across calls to/returns from methods in other classes.
+ * Use of the PatternLayout %c conversion character in the conversion string will give a more
+ * reliable value.
+ *
+ * @param classname class name
+ */
+ public void setClassname(String classname) {
+ context.put(CLASSNAME, classname);
+ }
+
+ /**
+ * Get the value for the data item with key "classname".
+ *
+ * @return current value, or empty string if not set
+ */
+ public String getClassname() {
+ return context.get(CLASSNAME, EMPTY_STRING);
+ }
+
+ /**
+ * Set the value for the data item with key "TransactionBeginTimestamp".
+ *
+ * @param transactionStartTime transaction start time
+ */
+ public void setTransactionBeginTimestamp(Instant transactionStartTime) {
+ SimpleDateFormat sdf = new SimpleDateFormat(TIME_FORMAT);
+ context.put(TRANSACTION_BEGIN_TIME_STAMP, sdf.format(Date.from(transactionStartTime)));
+ }
+
+ /**
+ * Get the value for the data item with key "TransactionBeginTimestamp".
+ *
+ * @return current value, or 0 if not set
+ */
+ public long getTransactionBeginTimestamp() {
+ return context.get(TRANSACTION_BEGIN_TIME_STAMP, DEFAULT_VALUE);
+ }
+
+ /**
+ * Set the value for the data item with key "TransactionEndTimestamp".
+ *
+ * @param transactionEndTime transaction end time
+ */
+ public void setTransactionEndTimestamp(Instant transactionEndTime) {
+ SimpleDateFormat sdf = new SimpleDateFormat(TIME_FORMAT);
+ context.put(TRANSACTION_END_TIME_STAMP, sdf.format(Date.from(transactionEndTime)));
+ }
+
+ /**
+ * Get the value for the data item with key "TransactionEndTimestamp".
+ *
+ * @return current value, or 0 if not set
+ */
+ public long getTransactionEndTimestamp() {
+ return context.get(TRANSACTION_END_TIME_STAMP, DEFAULT_VALUE);
+ }
+
+ /**
+ * Set the value for the data item with key "TransactionElapsedTime". An alternative to calling
+ * this method directly is to call <code>transactionStarted()</code> at the start of transaction
+ * processing and <code>transactionEnded()</code> at the end, which will compute the time
+ * difference in milliseconds and store the result as the "ns" value.
+ *
+ * @param transactionEndTime transaction end time
+ */
+
+ public void setTransactionElapsedTime(Instant transactionEndTime) {
+ long ns = Duration.between(transactionStartTime, transactionEndTime).toMillis();
+ context.put(TRANSACTION_ELAPSED_TIME, ns);
+ }
+
+ /**
+ * Get the value for the data item with key "TransactionElapsedTime".
+ *
+ * @return current value, or 0 if not set
+ */
+ public long getTransactionElapsedTime() {
+ return context.get(TRANSACTION_ELAPSED_TIME, DEFAULT_VALUE);
+ }
+
+ /**
+ * Set the value for the data item with key "MetricBeginTimestamp".
+ *
+ * @param metricStartTime metric start time
+ */
+ public void setMetricBeginTimestamp(Instant metricStartTime) {
+ SimpleDateFormat sdf = new SimpleDateFormat(TIME_FORMAT);
+ context.put(METRIC_BEGIN_TIME_STAMP, sdf.format(Date.from(metricStartTime)));
+ }
+
+ /**
+ * Get the value for the data item with key "MetricBeginTimestamp".
+ *
+ * @return current value, or 0 if not set
+ */
+ public long getMetricBeginTimestamp() {
+ return context.get(METRIC_BEGIN_TIME_STAMP, DEFAULT_VALUE);
+ }
+
+ /**
+ * Set the value for the data item with key "MetricEndTimestamp".
+ *
+ * @param metricEndTime metric end time
+ */
+ public void setMetricEndTimestamp(Instant metricEndTime) {
+ SimpleDateFormat sdf = new SimpleDateFormat(TIME_FORMAT);
+ context.put(METRIC_END_TIME_STAMP, sdf.format(Date.from(metricEndTime)));
+ }
+
+ /**
+ * Get the value for the data item with key "MetricEndTimestamp".
+ *
+ * @return current value, or 0 if not set
+ */
+ public long getMetricEndTimestamp() {
+ return context.get(METRIC_END_TIME_STAMP, DEFAULT_VALUE);
+ }
+
+ /**
+ * Set the value for the data item with key "MetricElapsedTime". An alternative to calling this
+ * method directly is to call <code>metricStarted()</code> at the start of metric processing and
+ * <code>metricEnded()</code> at the end, which will compute the time difference in milliseconds
+ * and store the result as the "ns" value.
+ *
+ * @param metricEndTime metric end time
+ */
+
+ public void setMetricElapsedTime(Instant metricEndTime) {
+ long ns = Duration.between(metricStartTime, metricEndTime).toMillis();
+ context.put(METRIC_ELAPSED_TIME, ns);
+ }
+
+ /**
+ * Get the value for the data item with key "MetricElapsedTime".
+ *
+ * @return current value, or 0 if not set
+ */
+ public long getMetricElapsedTime() {
+ return context.get(METRIC_ELAPSED_TIME, DEFAULT_VALUE);
+ }
+}