diff options
23 files changed, 2945 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2a1a0ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.classpath
+.project
+.settings/
+target/
+eelf-logging/debug-logs/
+eelf-logging/logs/
+blackDuckHubProjectVersionName.txt
+blackDuckHubProjectName.txt
diff --git a/License.txt b/License.txt new file mode 100644 index 0000000..1ec51b5 --- /dev/null +++ b/License.txt @@ -0,0 +1,20 @@ +============LICENSE_START======================================================= +Common Logging Service +================================================================================ +Copyright © 2017 AT&T Intellectual Property. +Copyright © 2017 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========================================================= + +ECOMP and OpenECOMP are trademarks +and service marks of AT&T Intellectual Property.
\ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..09adc76 --- /dev/null +++ b/README.md @@ -0,0 +1,168 @@ +/*- + * ============LICENSE_START======================================================= + * Common Logging Library + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +# Common Logging Library + +The common logging library provides a single library that can be used by any microservice to produce logs. +An abstraction layer is provided which exposes a public API to the microservices and shields them from the underlying implementation. + +The current version of the library is backed by an implementation which wraps the EELF Logging framework, however, the intent is that other logging implementations could be substituted in the future without impacting the public API used by the microservice clients. + +--- + +## Getting Started + +### Making The Library Available To Your Microservice +In order to make the logging library available to your microservice, include the following dependency in your service's pom.xml: + + + <!-- Common logging framework --> + <dependency> + <groupId>org.openecomp.aai.logging-service</groupId> + <artifactId>common-service</artifactId> + <version>1.0.0</version> + </dependency> + + +### Getting a Logger +There are three classes of _logger_ provided by the logging library: +* Standard logger - Used to generate most typical log statements. +* Audit logger - Used specifically to generate audit logs. +* Metrics logger - Used specifically to generate metrics logs. + +In order to generate log statements, your code needs to acquire an instance of whichever *Logger* type that you need. This is accomplished by requesting a *Logger* from the *LoggerFactory* + + Logger logger = LoggerFactory.getInstance().getLogger( {my logger name} ); + Logger auditLogger = LoggerFactory.getInstance().getAuditLogger( {my logger name} ); + Logger metricsLogger = LoggerFactory.getInstance().getMetricsLogger( {my logger name} ); + +where *{my logger name}* should be replaced with whatever name you want assigned to your logger instance. + + +### Log Statement Templates +The current version of the logging library is backed by the EELF Logging Framework. This provides the ability to create log statement templates with arguments to be filled in at runtime. + +**IMPORTANT:** When creating an enumerated class for message keys using the Common Logging Library, the class must implement `LogMessageEnum` and not `EELFResolvableErrorEnum` as detailed in the wiki link. + +### Generating Basic Log Statements +Log statements can be generated at the following log levels: **DEBUG**, **TRACE** **INFO**, **WARNING** and **ERROR** as follows: + + // Note, see the next section for a description of how to set the 'fields' argument. + + // Debug Level Logs. + logger.debug("Some debug message") + logger.debug(MyMsgEnum.A_DEBUG_MSG, fields, "arg1", "arg2"...) + + // Trace Level Logs. + logger.trace(MyMsgEnum.A_TRACE_MSG, fields, "arg1", "arg2"...) + + // Info Level Logs. + logger.info(MyMsgEnum.AN_INFO_MSG, fields, "arg1", "arg2"...) + logger.info(MyMsgEnum.AN_INFO_MSG, fields, "a status string", a_status_code, "arg1", "arg2"...) + logger.info(MyMsgEnum.AN_INFO_MSG, fields, "a status string", a_status_code, an_MDC_override, "arg1"...) + + // Warning Level Logs. + logger.warn(MyMsgEnum.A_WARNING_MSG, "arg1", "arg2"...) + + // Error Level Logs. + logger.error(MyMsgEnum.AN_ERROR_MSG, "arg1", "arg2"...) + +### Standardized Log Fields +There are a number of standard fields which the client may provide values for. These fields will be automatically populated with the supplied values, in fixed positions within the generated log string. + +The client may pass values for these fields by populating a _LogFields_ object with _field name_/_value_ pairs as illustrated in the following example: + + LogFields fields = new LogFields() + .setField(LogLine.DefinedFields.CLIENT_IP, "1.2.3.4") + .setField(LogLine.DefinedFields.CLASS_NAME, "somename"); + +In the logging examples in the previous section, the _fields_ argument, which we glossed over, would be set it this manner. + +The following fields are currently defined as settable by the client: + + STATUS_CODE, // High level success or failure of the request (COMPLETE or ERROR) + RESPONSE_CODE, // Application-specific error code + RESPONSE_DESCRIPTION, // Human readable description of the application specific response code + INSTANCE_UUID, // universally unique identifier used to differentiate between multiple + // instances of the same (named), log writing component + SEVERITY, // 0, 1, 2, 3 + SERVER_IP, // The logging component host server’s IP address + CLIENT_IP, // Requesting remote client application’s IP address + CLASS_NAME, // This is the name of the class that has caused the log record to be created + PROCESS_KEY, + TARGET_SVC_NAME, // External API/operation activities invoked on TargetEntity + TARGET_ENTITY, // Component or subcomponent invoked for this operation. + CUSTOM_1, // For whatever custom use the client determines. + CUSTOM_2, // For whatever custom use the client determines. + CUSTOM_3, // For whatever custom use the client determines. + CUSTOM_4; // For whatever custom use the client determines. + +### The Mapped Diagnostic Context +The _Mapped Diagnostic Context_ or MDC is a tool to help distinguish interleaved log output from different sources. It lets the application thread place information in a diagnostic context that can later be retrieved by the logging components. + +#### Initializing the _MDC Context_ +Application threads may initialize their MDC Context according to the following pattern: + + MDCContext.initialize({transaction id}, {service name}, {service instance}, {partner name} {client address}); + +Once initialized, the values stored in the _MDC Context_ will be used by the logger to auto populate the relevant fields in the standard log statement. + +#### Supported Fields +The logging library makes use of a number of 'known' fields in the _MDC Context_. These field names are exposed as static variables by the _MDCContext_ class: + + MDCContext.MDC_REQUEST_ID + MDCContext.MDC_SERVER_FQDN + MDCContext.MDC_SERVICE_NAME + MDCContext.MDC_PARTNER_NAME + MDCContext.MDC_START_TIME + MDCContext.MDC_REMOTE_HOST + MDCContext.MDC_SERVICE_INSTANCE_ID + MDCContext.MDC_CLIENT_ADDRESS + +If values are assigned to any of these fields, then they will be automatically inserted into the appropriate fields in the standard log statement generated by the logger, although it is not *required* that they be set. + +#### Overriding the Contents of the _MDC Context_ +In certain situations, it is useful for the application thread to override or insert a value into one of the _MDC Context_ fields on a one-time basis when invoking the _logger_ (a good example is passing time stamp data to a metrics logger). + +The following example illustrates how to achieve this: + + public void doSomeOperation() { + + // Instantiate a new MDCOverride object. + MDCOverride override = new MDCOverride(); + + // Grab the current time to use later for metrics calculations. + long startTimeInMs = System.currentTimeMillis(); + + // ...and add it as an attribute to our MDC Override + // object. + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + override.addAttribute(MDCContext.MDC_START_TIME, formatter.format(startTimeInMs)); + + // do a bunch of really important stuff... + + // Finally, invoke a metrics logger, passing in our instance of the + // MDCOverride object. + metricsLogger.info(MyMsgEnum.A_LOG_CODE, + a_status_code, + override, + an_argument, + another_argument); + } diff --git a/common-logging/pom.xml b/common-logging/pom.xml new file mode 100644 index 0000000..bacd431 --- /dev/null +++ b/common-logging/pom.xml @@ -0,0 +1,41 @@ +<!-- + ============LICENSE_START======================================================= + Common Logging Library + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.openecomp.aai.logging-service</groupId> + <artifactId>logging-service</artifactId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <groupId>org.openecomp.aai</groupId> + <artifactId>common-logging</artifactId> + <name>Common Logging Distribution</name> + + <dependencies> + <dependency> + <groupId>org.openecomp.cl</groupId> + <artifactId>eelf-logging</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> +</project> diff --git a/eelf-logging/pom.xml b/eelf-logging/pom.xml new file mode 100644 index 0000000..c9952d0 --- /dev/null +++ b/eelf-logging/pom.xml @@ -0,0 +1,57 @@ +<!-- + ============LICENSE_START======================================================= + Common Logging Library + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.openecomp.aai.logging-service</groupId> + <artifactId>logging-service</artifactId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <groupId>org.openecomp.aai</groupId> + <artifactId>eelf-logging</artifactId> + <name>EELF Logging Implementation</name> + + <dependencies> + + <!-- Common logging API. --> + <dependency> + <groupId>org.openecomp.aai</groupId> + <artifactId>logging-api</artifactId> + <version>${project.version}</version> + </dependency> + + <!-- EELF logging library --> + <dependency> + <groupId>com.att.eelf</groupId> + <artifactId>eelf-core</artifactId> + <version>0.0.1</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.11</version> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/eelf-logging/src/main/java/org/openecomp/cl/eelf/AaiLoggerAdapter.java b/eelf-logging/src/main/java/org/openecomp/cl/eelf/AaiLoggerAdapter.java new file mode 100644 index 0000000..0f05532 --- /dev/null +++ b/eelf-logging/src/main/java/org/openecomp/cl/eelf/AaiLoggerAdapter.java @@ -0,0 +1,349 @@ +/*- + * ============LICENSE_START======================================================= + * Common Logging Library + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.cl.eelf; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFLogger.Level; +import com.att.eelf.i18n.EELFResolvableErrorEnum; +import com.att.eelf.i18n.EELFResourceManager; + +import org.openecomp.cl.api.LogFields; +import org.openecomp.cl.api.LogLine; +import org.openecomp.cl.api.LogLine.LogLineType; +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.mdc.MdcOverride; + +import java.util.HashMap; +import java.util.Map; + +/** + * This class provides a logging implementation which wraps the EELF logging + * framework. + */ +public class AaiLoggerAdapter implements Logger { + + public static final String BAD_ENUM_MSG = "UNRECOGNIZABLE ERROR CODE "; + + /** Field name to use for the message portion of our log lines. */ + public static final String MESSAGE_PREFIX = "Msg"; + + /** + * A place holder to use for fields in the standardized log message that we + * are not explicitly setting. + */ + public static final String NOT_APPLICABLE = "na"; + + /** + * The instance of the actual EELF logger that we will be sending our messages + * to. + */ + private EELFLogger eelfLogger; + + /** + * This indicates the logging format type. It is used for deciding the string + * builder for constructing standardized log statements. + */ + private LogLineType logLineType; + + /** An identifier for the component that is generating the log statements. */ + private String component = NOT_APPLICABLE; + + /** + * Creates a new instance of the {@link AaiLoggerAdapter}, backed by the + * supplied {@link EELFLogger} instance. + * + * @param eelfLogger + * - The instance of {@link EELFLogger} that this logger will invoke. + */ + public AaiLoggerAdapter(EELFLogger eelfLogger, LogLineType logLineType, String componentName) { + + // Store the supplied EELFLogger instance. + this.eelfLogger = eelfLogger; + this.logLineType = logLineType; + this.component = componentName; + } + + @Override + public boolean isTraceEnabled() { + return eelfLogger.isTraceEnabled(); + } + + @Override + public boolean isInfoEnabled() { + return eelfLogger.isInfoEnabled(); + } + + @Override + public boolean isErrorEnabled() { + return eelfLogger.isErrorEnabled(); + } + + @Override + public boolean isWarnEnabled() { + return eelfLogger.isWarnEnabled(); + } + + @Override + public boolean isDebugEnabled() { + return eelfLogger.isDebugEnabled(); + } + + /** + * Sets a number of the common fields which prefix all standard log + * statements. + */ + private void initLogLine(LogLine logLine, String level, String logCode, String msg, + LogFields fields) { + logLine.init(component, logCode, level, msg, fields, new MdcOverride()); + } + + private void initLogLine(LogLine logLine, String level, String logCode, String msg, + LogFields fields, MdcOverride override) { + logLine.init(component, logCode, level, msg, fields, override); + } + + @Override + public void info(Enum logCode, String... arguments) { + info(logCode, new LogFields(), arguments); + } + + @Override + public void info(Enum logCode, LogFields fields, String... arguments) { + + // We expect our error code to be compatible with the templating + // functionality provided by the EELF framework, so make sure + // that this is the case before we try to decode our error code. + if (logCode instanceof LogMessageEnum) { + // Cast our error code enum to make the EELF framework happy. + LogMessageEnum eelfLogCode = (LogMessageEnum) logCode; + + // Initialize the log line + LogLine logLine = getLogLine(); + initLogLine(logLine, Level.INFO.toString(), EELFResourceManager.getIdentifier(eelfLogCode), + EELFResourceManager.format(eelfLogCode, arguments), + (fields == null) ? new LogFields() : fields); + + // Pass our log string to the EELF logging framework. + eelfLogger.info(logLine.getFormattedLine()); + } else { + eelfLogger.error(BAD_ENUM_MSG + logCode.toString()); + } + } + + @Override + public void info(Enum logCode, LogFields fields, MdcOverride override, String... arguments) { + + // We expect our error code to be compatible with the templating + // functionality provided by the EELF framework, so make sure + // that this is the case before we try to decode our error code. + if (logCode instanceof LogMessageEnum) { + // Cast our error code enum to make the EELF framework happy. + LogMessageEnum eelfLogCode = (LogMessageEnum) logCode; + + // Initialize the log line + LogLine logLine = getLogLine(); + initLogLine(logLine, Level.INFO.toString(), EELFResourceManager.getIdentifier(eelfLogCode), + EELFResourceManager.format(eelfLogCode, arguments), + (fields == null) ? new LogFields() : fields, override); + + // Pass our log string to the EELF logging framework. + eelfLogger.info(logLine.getFormattedLine()); + } else { + eelfLogger.error(BAD_ENUM_MSG + logCode.toString()); + } + } + + @Override + public void debug(String message) { + // Initialize the log line + LogLine logLine = getLogLine(); + initLogLine(logLine, Level.DEBUG.toString(), "", message, new LogFields()); + + // Pass our log string the the EELF logging framework. + eelfLogger.debug(logLine.getFormattedLine()); + } + + @Override + public void debug(Enum logCode, String... arguments) { + debug(logCode, new LogFields(), arguments); + } + + @Override + public void debug(Enum logCode, LogFields fields, String... arguments) { + + // We expect our log code to be compatible with the templating + // functionality provided by the EELF framework, so make sure + // that this is the case before we try to decode it. + if (logCode instanceof LogMessageEnum) { + // Cast our error code enum to make the EELF framework happy. + LogMessageEnum eelfLogCode = (LogMessageEnum) logCode; + + // Initialize the log lineLogLine logLine = getLogLine(); + LogLine logLine = getLogLine(); + initLogLine(logLine, Level.DEBUG.toString(), EELFResourceManager.getIdentifier(eelfLogCode), + EELFResourceManager.format(eelfLogCode, arguments), + (fields == null) ? new LogFields() : fields); + + // Pass our log string to the EELF logging framework. + eelfLogger.debug(logLine.getFormattedLine()); + } else { + eelfLogger.error(BAD_ENUM_MSG + logCode.toString()); + } + } + + @Override + public void warn(Enum logCode, String... arguments) { + warn(logCode, new LogFields(), arguments); + } + + @Override + public void warn(Enum logCode, LogFields fields, String... arguments) { + + // We expect our log code to be compatible with the templating + // functionality provided by the EELF framework, so make sure + // that this is the case before we try to decode our it. + if (logCode instanceof LogMessageEnum) { + // Cast our error code enum to make the EELF framework happy. + LogMessageEnum eelfLogCode = (LogMessageEnum) logCode; + + // Initialize the log line + LogLine logLine = getLogLine(); + initLogLine(logLine, Level.WARN.toString(), EELFResourceManager.getIdentifier(eelfLogCode), + EELFResourceManager.format(eelfLogCode, arguments), + (fields == null) ? new LogFields() : fields); + + // Pass our log string to the EELF logging framework. + eelfLogger.warn(logLine.getFormattedLine()); + } else { + eelfLogger.error(BAD_ENUM_MSG + logCode.toString()); + } + } + + @Override + public void trace(Enum logCode, String... arguments) { + trace(logCode, new LogFields(), arguments); + } + + @Override + public void trace(Enum logCode, LogFields fields, String... arguments) { + + // We expect our log code to be compatible with the templating + // functionality provided by the EELF framework, so make sure + // that this is the case before we try to decode our it. + if (logCode instanceof LogMessageEnum) { + // Cast our error code enum to make the EELF framework happy. + LogMessageEnum eelfLogCode = (LogMessageEnum) logCode; + + // Initialize the log line + LogLine logLine = getLogLine(); + initLogLine(logLine, Level.TRACE.toString(), EELFResourceManager.getIdentifier(eelfLogCode), + EELFResourceManager.format(eelfLogCode, arguments), + (fields == null) ? new LogFields() : fields); + + // Pass our log string to the EELF logging framework. + eelfLogger.trace(logLine.getFormattedLine()); + + } else { + eelfLogger.error(BAD_ENUM_MSG + logCode.toString()); + } + } + + @Override + public void error(Enum logCode, String... arguments) { + error(logCode, new LogFields(), arguments); + } + + @Override + public void error(Enum logCode, LogFields fields, String... arguments) { + + // We expect our log code to be compatible with the templating + // functionality provided by the EELF framework, so make sure + // that this is the case before we try to decode it. + if (logCode instanceof LogMessageEnum) { + + // Cast our error code enum to make the EELF framework happy. + LogMessageEnum eelfLogCode = (LogMessageEnum) logCode; + + // Initialize the log line + LogLine logLine = getLogLine(); + initLogLine(logLine, Level.ERROR.toString(), EELFResourceManager.getIdentifier(eelfLogCode), + EELFResourceManager.format(eelfLogCode, arguments), + (fields == null) ? new LogFields() : fields); + + // Pass our log string to the EELF logging framework. + eelfLogger.error(logLine.getFormattedLine()); + + } else { + eelfLogger.error(BAD_ENUM_MSG + logCode.toString()); + } + } + + @Override + public void error(Enum logCode, Throwable ex, String... arguments) { + error(logCode, new LogFields(), ex, arguments); + } + + @Override + public void error(Enum logCode, LogFields fields, Throwable ex, String... arguments) { + + // We expect our log code to be compatible with the templating + // functionality provided by the EELF framework, so make sure + // that this is the case before we try to decode it. + if (logCode instanceof LogMessageEnum) { + // Cast our error code enum to make the EELF framework happy. + LogMessageEnum eelfLogCode = (LogMessageEnum) logCode; + + // Initialize the log line + LogLine logLine = getLogLine(); + initLogLine(logLine, Level.ERROR.toString(), EELFResourceManager.getIdentifier(eelfLogCode), + EELFResourceManager.format(eelfLogCode, arguments), + (fields == null) ? new LogFields() : fields); + + // Pass our log string to the EELF logging framework. + eelfLogger.error(logLine.getFormattedLine(), ex); + + } else { + eelfLogger.error(BAD_ENUM_MSG + logCode.toString()); + } + } + + @Override + public String formatMsg(Enum logCode, String... arguments) { + return EELFResourceManager.getMessage((EELFResolvableErrorEnum) logCode, arguments); + } + + private LogLine getLogLine() { + if (logLineType == LogLineType.AUDIT) { + return new AuditLogLine(); + } + + if (logLineType == LogLineType.ERROR) { + return new ErrorLogLine(); + } + + if (logLineType == LogLineType.METRICS) { + return new MetricsLogLine(); + } + + eelfLogger.warn("Unsupported LogLineType: " + logLineType); + return null; + } +} diff --git a/eelf-logging/src/main/java/org/openecomp/cl/eelf/AuditLogLine.java b/eelf-logging/src/main/java/org/openecomp/cl/eelf/AuditLogLine.java new file mode 100644 index 0000000..457da14 --- /dev/null +++ b/eelf-logging/src/main/java/org/openecomp/cl/eelf/AuditLogLine.java @@ -0,0 +1,81 @@ +/*- + * ============LICENSE_START======================================================= + * Common Logging Library + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.cl.eelf; + +import org.openecomp.cl.api.LogLine; +import org.openecomp.cl.mdc.MdcContext; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** This class is used to help standardize how log lines are written and provide + * profiling info. */ +public class AuditLogLine extends LogLine { + + /** (non-Javadoc) + * @see org.openecomp.cl.api.LogLine#getFormattedLine() + */ + public String getFormattedLine() { + + // calculate start/end/elapsed times + Date currentDateTime = new Date(); + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + String startTimeString = getMdcValue(MdcContext.MDC_START_TIME); + String endTimeString = formatter.format(currentDateTime); + long elapsedTime = 0; + Date startDateTime; + try { + startDateTime = formatter.parse(startTimeString); + elapsedTime = currentDateTime.getTime() - startDateTime.getTime(); + } catch (ParseException e) { + // Leave an elapsed time of 0 if the start time was not properly formatted + } + String elapsedTimeString = Long.toString(elapsedTime); + + return startTimeString + "|" + // 1 start time + endTimeString + "|" + // 2 end time + getMdcValue(MdcContext.MDC_REQUEST_ID) + "|" + // 3 transaction id + getMdcValue(MdcContext.MDC_SERVICE_INSTANCE_ID) + "|" + // 4 service instance + Thread.currentThread().getName() + "|" + // 5 thread id + getMdcValue(MdcContext.MDC_SERVER_FQDN) + "|" + // 6 physical/virtual server name + getMdcValue(MdcContext.MDC_SERVICE_NAME) + "|" + // 7 service name + getMdcValue(MdcContext.MDC_PARTNER_NAME) + "|" + // 8 partner name + fieldValue(DefinedFields.STATUS_CODE) + "|" + // 9 status code + fieldValue(DefinedFields.RESPONSE_CODE) + "|" + // 10 response code + fieldValue(DefinedFields.RESPONSE_DESCRIPTION) + "|" + // 11 response description + fieldValue(DefinedFields.INSTANCE_UUID) + "|" + // 12 instance UUID + level + "|" + // 13 log level + fieldValue(DefinedFields.SEVERITY) + "|" + // 14 log severity + fieldValue(DefinedFields.SERVER_IP) + "|" + // 15 server ip + elapsedTimeString + "|" + // 16 elapsed time + getMdcValue(MdcContext.MDC_SERVER_FQDN) + "|" + // 17 server name + getMdcValue(MdcContext.MDC_CLIENT_ADDRESS) + "|" + // 18 client ip address + fieldValue(DefinedFields.CLASS_NAME) + "|" + // 19 class name + "" + "|" + // 20 deprecated + fieldValue(DefinedFields.PROCESS_KEY) + "|" + // 21 process key + fieldValue(DefinedFields.CUSTOM_1) + "|" + // 22 custom 1 + fieldValue(DefinedFields.CUSTOM_2) + "|" + // 23 custom 2 + fieldValue(DefinedFields.CUSTOM_3) + "|" + // 24 custom 3 + fieldValue(DefinedFields.CUSTOM_4) + "|" + // 25 custom 4 + message; // 26 details + } +} diff --git a/eelf-logging/src/main/java/org/openecomp/cl/eelf/ErrorLogLine.java b/eelf-logging/src/main/java/org/openecomp/cl/eelf/ErrorLogLine.java new file mode 100644 index 0000000..25c2fa3 --- /dev/null +++ b/eelf-logging/src/main/java/org/openecomp/cl/eelf/ErrorLogLine.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * Common Logging Library + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.cl.eelf; + +import org.openecomp.cl.api.LogLine; + + +/** This class is used to help standardize how log lines are written and provide + * profiling info. */ +public class ErrorLogLine extends LogLine { + + /** (non-Javadoc) + * @see org.openecomp.cl.api.LogLine#getFormattedLine() + */ + public String getFormattedLine() { + + // The error logger fields should be defined in logback.xml using the following pattern: + // %d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}|%mdc{RequestId}|%thread|<AppName>|%mdc{PartnerName}|%logger||%.-5level|%msg%n" + return logCode + "|" + // 9 error code + message + "|" + // 10 log message + ""; // 11 extra details + + } +} diff --git a/eelf-logging/src/main/java/org/openecomp/cl/eelf/LogMessageEnum.java b/eelf-logging/src/main/java/org/openecomp/cl/eelf/LogMessageEnum.java new file mode 100644 index 0000000..dc83763 --- /dev/null +++ b/eelf-logging/src/main/java/org/openecomp/cl/eelf/LogMessageEnum.java @@ -0,0 +1,31 @@ +/*- + * ============LICENSE_START======================================================= + * Common Logging Library + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.cl.eelf; + +import com.att.eelf.i18n.EELFResolvableErrorEnum; +import com.att.eelf.i18n.EELFResourceManager; + +/** This is a placeholder which client-specific message key enumerations should + * implement in order to tie into the log template functionality of the EELF + * framework. */ +public interface LogMessageEnum extends EELFResolvableErrorEnum { + +} diff --git a/eelf-logging/src/main/java/org/openecomp/cl/eelf/LoggerFactory.java b/eelf-logging/src/main/java/org/openecomp/cl/eelf/LoggerFactory.java new file mode 100644 index 0000000..c0ff5b0 --- /dev/null +++ b/eelf-logging/src/main/java/org/openecomp/cl/eelf/LoggerFactory.java @@ -0,0 +1,177 @@ +/*- + * ============LICENSE_START======================================================= + * Common Logging Library + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.cl.eelf; + +import com.att.eelf.configuration.EELFManager; + +import org.openecomp.cl.api.LogLine.LogLineType; +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.api.LoggerFactoryInterface; + +import java.util.HashMap; +import java.util.Map; + +/** This is an implementation of the {@link LoggerFactoryInterface} which + * constructs a {@link Logger} implementation which is compatible with the EELF + * framework. */ +public class LoggerFactory implements LoggerFactoryInterface { + + /** The instance for our factory singleton. */ + private static LoggerFactory instance; + + /** An instance of the log factory provided by the EELF framework. We will use + * this to get an actual EELF logger instance that we will wrap within our + * own, more generalized logger. */ + private EELFManager eelfManager; + + /** This cache maintains a mapping of logger names to instances so that if a + * logger with the same name is requested multiple times we can return the + * same instance each time. */ + private Map<String, Logger> errorLoggerCache = new HashMap<String, Logger>(); + + /** This cache maintains a mapping of metric logger names to instances so that + * if a logger with the same name is requested multiple times we can return + * the same instance each time. */ + private Map<String, Logger> metricLoggerCache = new HashMap<String, Logger>(); + + /** This cache maintains a mapping of audit logger names to instances so that + * if a logger with the same name is requested multiple times we can return + * the same instance each time. */ + private Map<String, Logger> auditLoggerCache = new HashMap<String, Logger>(); + + /** Returns the single instance of our factory singleton. + * + * @return - An instance of the {@link LoggerFactory} */ + public static synchronized LoggerFactory getInstance() { + + // If we don't already have an instance then create it now. + if (instance == null) { + instance = new LoggerFactory(); + } + + // Return our singleton instance. + return instance; + } + + /** + * Instantiates a new {@link LoggerFactory}. + */ + protected LoggerFactory() { + + // We need an instance of the factory provided by the EELF + // framework so that we can instantiate the EELF logger that + // we will be wrapping, so get one now. + if (eelfManager == null) { + eelfManager = EELFManager.getInstance(); + } + } + + /** + * (non-Javadoc) + * + * @see org.ecomp.cl.api.LoggerFactoryInterface#getLogger(java.lang.String) + */ + public Logger getLogger(String name) { + + // Check the cache to see if we have already instantiated a logger + // with the supplied name. + if (!errorLoggerCache.containsKey(name)) { + + // Nothing in the cache, so let's instantiate a logger now. + Logger logger = new AaiLoggerAdapter(eelfManager.getLogger(name), LogLineType.ERROR, name); + errorLoggerCache.put(name, logger); + } + + // Return the requested logger instance. + return errorLoggerCache.get(name); + } + + /** + * (non-Javadoc) + * + * @see org.ecomp.cl.api.LoggerFactoryInterface#getLogger(java.lang.Class) + */ + public Logger getLogger(Class<?> clazz) { + + return getLogger(clazz.getName()); + } + + /** + * (non-Javadoc) + * + * @see org.ecomp.cl.api.LoggerFactoryInterface#getAuditLogger(java.lang.String) + */ + public Logger getAuditLogger(String name) { + + // Check the cache to see if we have already instantiated a logger + // with the supplied name. + if (!auditLoggerCache.containsKey(name)) { + + // Nothing in the cache, so let's instantiate a logger now. + Logger logger = new AaiLoggerAdapter(eelfManager.getAuditLogger(), LogLineType.AUDIT, name); + auditLoggerCache.put(name, logger); + } + + // Return the requested logger instance. + return auditLoggerCache.get(name); + } + + /** + * (non-Javadoc) + * + * @see org.ecomp.cl.api.LoggerFactoryInterface#getAuditLogger(java.lang.Class) + */ + public Logger getAuditLogger(Class<?> clazz) { + + return getAuditLogger(clazz.getName()); + } + + /** + * (non-Javadoc) + * + * @see org.ecomp.cl.api.LoggerFactoryInterface#getMetricsLogger(java.lang.String) + */ + public Logger getMetricsLogger(String name) { + + // Check the cache to see if we have already instantiated a logger + // with the supplied name. + if (!metricLoggerCache.containsKey(name)) { + + // Nothing in the cache, so let's instantiate a logger now. + Logger logger = new AaiLoggerAdapter(eelfManager.getMetricsLogger(), LogLineType.METRICS, + name); + metricLoggerCache.put(name, logger); + } + + // Return the requested logger instance. + return metricLoggerCache.get(name); + } + + /** + * (non-Javadoc) + * + * @see org.ecomp.cl.api.LoggerFactoryInterface#getMetricsLogger(java.lang.Class) + */ + public Logger getMetricsLogger(Class<?> clazz) { + + return getMetricsLogger(clazz.getName()); + } +} diff --git a/eelf-logging/src/main/java/org/openecomp/cl/eelf/MetricsLogLine.java b/eelf-logging/src/main/java/org/openecomp/cl/eelf/MetricsLogLine.java new file mode 100644 index 0000000..fb5e213 --- /dev/null +++ b/eelf-logging/src/main/java/org/openecomp/cl/eelf/MetricsLogLine.java @@ -0,0 +1,83 @@ +/*- + * ============LICENSE_START======================================================= + * Common Logging Library + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.cl.eelf; + +import org.openecomp.cl.api.LogLine; +import org.openecomp.cl.mdc.MdcContext; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** This class is used to help standardize how log lines are written and provide + * profiling info. */ +public class MetricsLogLine extends LogLine { + + /** Return the log line based on what we have so far. */ + public String getFormattedLine() { + + // Calculate start/end/elapsed times + Date currentDateTime = new Date(); + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + String startTimeString = getMdcValue(MdcContext.MDC_START_TIME); + String endTimeString = formatter.format(currentDateTime); + long elapsedTime = 0; + Date startDateTime; + try { + startDateTime = formatter.parse(startTimeString); + elapsedTime = currentDateTime.getTime() - startDateTime.getTime(); + } catch (ParseException e) { + // Leave an elapsed time of 0 if the start time was not properly formatted + } + String elapsedTimeString = Long.toString(elapsedTime); + + return startTimeString + "|" + // 1 start time + endTimeString + "|" + // 2 end time + getMdcValue(MdcContext.MDC_REQUEST_ID) + "|" + // 3 transaction id + getMdcValue(MdcContext.MDC_SERVICE_INSTANCE_ID) + "|" + // 4 service instance + Thread.currentThread().getName() + "|" + // 5 thread id + getMdcValue(MdcContext.MDC_SERVER_FQDN) + "|" + // 6 physical/virtual server name + getMdcValue(MdcContext.MDC_SERVICE_NAME) + "|" + // 7 service name + getMdcValue(MdcContext.MDC_PARTNER_NAME) + "|" + // 8 partner name + fieldValue(DefinedFields.TARGET_ENTITY) + "|" + // 9 target entity + fieldValue(DefinedFields.TARGET_SVC_NAME) + "|" + // 10 target service + fieldValue(DefinedFields.STATUS_CODE) + "|" + // 11 status code + fieldValue(DefinedFields.RESPONSE_CODE) + "|" + // 12 response code + fieldValue(DefinedFields.RESPONSE_DESCRIPTION) + "|" + // 13 response description + fieldValue(DefinedFields.INSTANCE_UUID) + "|" + // 14 instance UUID + level + "|" + // 15 log level + fieldValue(DefinedFields.SEVERITY) + "|" + // 16 log severity + fieldValue(DefinedFields.SERVER_IP) + "|" + // 17 server ip + elapsedTimeString + "|" + // 18 elapsed time + getMdcValue(MdcContext.MDC_SERVER_FQDN) + "|" + // 19 server name + fieldValue(DefinedFields.CLIENT_IP) + "|" + // 20 client ip address + fieldValue(DefinedFields.CLASS_NAME) + "|" + // 21 class name + "" + "|" + // 22 deprecated + fieldValue(DefinedFields.PROCESS_KEY) + "|" + // 23 process key + fieldValue(DefinedFields.TARGET_ENTITY) + "|" + // 24 target virtual entity + fieldValue(DefinedFields.CUSTOM_1) + "|" + // 25 custom 1 + fieldValue(DefinedFields.CUSTOM_2) + "|" + // 26 custom 2 + fieldValue(DefinedFields.CUSTOM_3) + "|" + // 27 custom 3 + fieldValue(DefinedFields.CUSTOM_4) + "|" + // 28 custom 4 + message; // 29 detail message + } + +} diff --git a/eelf-logging/src/test/java/org/openecomp/cl/eelf/AAILoggerAdapterTest.java b/eelf-logging/src/test/java/org/openecomp/cl/eelf/AAILoggerAdapterTest.java new file mode 100644 index 0000000..24dab76 --- /dev/null +++ b/eelf-logging/src/test/java/org/openecomp/cl/eelf/AAILoggerAdapterTest.java @@ -0,0 +1,823 @@ +/*- + * ============LICENSE_START======================================================= + * Common Logging Library + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.cl.eelf; + +import static org.junit.Assert.*; + +import java.util.Locale; + +import org.junit.Before; +import org.junit.Test; +import org.openecomp.cl.eelf.AaiLoggerAdapter; +import org.openecomp.cl.api.LogFields; +import org.openecomp.cl.api.LogLine; +import org.openecomp.cl.api.LogLine.DefinedFields; +import org.openecomp.cl.api.LogLine.LogLineType; +import org.openecomp.cl.mdc.MdcContext; +import org.openecomp.cl.mdc.MdcOverride; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.i18n.EELFResolvableErrorEnum; + +/** This suite of tests is intended to validate the functionality of our wrapper + * around the {@link EELFLogger}. */ +public class AAILoggerAdapterTest { + + private enum InvalidLogCodeEnum { + BAD_LOGCODE1 + } + + private static final String LOGGER_NAME = "UnitTestLogAdapter"; + private static final String METRICS_LOGGER_NAME = "UnitTestMetricsLogAdapter"; + private static final String AUDIT_LOGGER_NAME = "UnitTestAuditLogAdapter"; + + private TestLogger logger; + private AaiLoggerAdapter loggerAdapter; + private AaiLoggerAdapter metricsLoggerAdapter; + private AaiLoggerAdapter auditLoggerAdapter; + + @Before + public void setup() { + logger = new TestLogger(); + loggerAdapter = new AaiLoggerAdapter(logger, LogLineType.ERROR, LOGGER_NAME); + metricsLoggerAdapter = new AaiLoggerAdapter(logger, LogLineType.METRICS, METRICS_LOGGER_NAME); + auditLoggerAdapter = new AaiLoggerAdapter(logger, LogLineType.AUDIT, AUDIT_LOGGER_NAME); + } + + /** This test validates the the {@link AaiLoggerAdapter} is able to deal with + * log code enums which do not extend the {@link EELFResolvableEnum} + * placeholder (meaning that the EELF framework would not know how to parse + * them). */ + @Test + public void badLogCodeEnumTest() { + + // For each supported log level, validate that if a log code is + // specified which does not extend EELFResolvableEnum, then a + // generic 'unparsable log code' statement is generated instead + // of a correctly parsed log statement. + + loggerAdapter.info(InvalidLogCodeEnum.BAD_LOGCODE1, "arg1"); + assertBadLogCodeMessage(logger.getMessage(), InvalidLogCodeEnum.BAD_LOGCODE1); + + loggerAdapter.debug(InvalidLogCodeEnum.BAD_LOGCODE1, "arg1", "arg2"); + assertBadLogCodeMessage(logger.getMessage(), InvalidLogCodeEnum.BAD_LOGCODE1); + + loggerAdapter.warn(InvalidLogCodeEnum.BAD_LOGCODE1, "arg1", "arg2"); + assertBadLogCodeMessage(logger.getMessage(), InvalidLogCodeEnum.BAD_LOGCODE1); + + loggerAdapter.error(InvalidLogCodeEnum.BAD_LOGCODE1, "arg1", "arg2", "arg3"); + assertBadLogCodeMessage(logger.getMessage(), InvalidLogCodeEnum.BAD_LOGCODE1); + + loggerAdapter.error(InvalidLogCodeEnum.BAD_LOGCODE1, new LogFields(), + new Throwable("Some exception"), "arg1"); + assertBadLogCodeMessage(logger.getMessage(), InvalidLogCodeEnum.BAD_LOGCODE1); + } + + /** This test validates that INFO level logs are correctly parsed from the + * resource bundle. */ + @Test + public void logStatementInfoParsingTest() { + + String FIRST_ARG = "First Arg"; + String SECOND_ARG = "Second Arg"; + + // Generate a simple INFO log. + loggerAdapter.info(UnitTestMsgs.SIMPLE_INFO_LOG, null); + + // Validate that the message was parsed from the bundle resource. + logger.validateLogMsg("UT0001I This is a simple info log with no arguments."); + + // Generate an INFO log with arguments. + LogFields fields = new LogFields().setField(LogLine.DefinedFields.TARGET_SVC_NAME, "test"); + loggerAdapter.info(UnitTestMsgs.INFO_LOG_WITH_ARGS, fields, FIRST_ARG, SECOND_ARG); + + // Validate that the message was parsed from the bundle resource. + logger.validateLogMsg( + "UT0002I This is an info log with some arguments " + FIRST_ARG + " and " + SECOND_ARG); + + // Validate that log fields are being correctly populated. + logger.validateLogFields(LogLineType.ERROR, fields); + } + + /** Validate metrics log */ + @Test + public void logStatementMetricsTest() { + // Generate an INFO log with arguments. + MdcContext.initialize("xx-yy-zz", "MyService", "MyInstance", "MyPartner", "12.0.0.2"); + metricsLoggerAdapter.info(UnitTestMsgs.INFO_LOG_WITH_ARGS, + new LogFields().setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, "Accepted") + .setField(LogLine.DefinedFields.RESPONSE_CODE, 202), + "arg1", "arg2"); + + // Validate that the log code is correctly encoded in the log statement + // and that the message was parsed from the bundle resource. + logger.validateMetricsMsg("UT0002I This is an info log with some arguments arg1 and arg2"); + logger.validateMetricsRespStatus("202", "Accepted"); + + // Validate MDC override + MdcOverride override = new MdcOverride(); + override.addAttribute(MdcContext.MDC_REQUEST_ID, "New-requestID"); + + LogFields fields = new LogFields() + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, "Accepted") + .setField(LogLine.DefinedFields.RESPONSE_CODE, 202); + + metricsLoggerAdapter.info(UnitTestMsgs.INFO_LOG_WITH_ARGS, fields, override, "arg1", "arg2"); + logger.validateMetricsRequestId("New-requestID"); + + // Validate that log fields are being correctly populated. + logger.validateLogFields(LogLineType.METRICS, fields); + } + + /** Validate metrics log */ + @Test + public void logStatementAuditTest() { + // Generate an INFO log with arguments. + MdcContext.initialize("xx-yy-aa", "MyService", "MyInstance", "MyPartner", "12.0.0.8"); + LogFields fields = new LogFields() + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, "Accepted") + .setField(LogLine.DefinedFields.RESPONSE_CODE, 202); + auditLoggerAdapter.info(UnitTestMsgs.INFO_LOG_WITH_ARGS, fields, "arg1", "arg2"); + + // Validate that the log code is correctly encoded in the log statement + // and that the message was parsed from the bundle resource. + logger.validateAuditMsg("UT0002I This is an info log with some arguments arg1 and arg2"); + logger.validateAuditRespStatus("202", "Accepted"); + + // Validate that log fields are being correctly populated. + logger.validateLogFields(LogLineType.AUDIT, fields); + } + + /** This test validates that ERROR level logs are correctly parsed from the + * resource bundle. */ + @Test + public void logStatementErrorParsingTest() { + + String FIRST_ARG = "First Arg"; + String SECOND_ARG = "Second Arg"; + + // Generate a simple ERROR log. + loggerAdapter.error(UnitTestMsgs.SIMPLE_ERROR_LOG, null); + + // Validate that the message was parsed from the bundle resource. + logger.validateLogMsg("UT0001E This is a simple error log with no arguments."); + + // Generate an ERROR log with arguments. + loggerAdapter.error(UnitTestMsgs.ERROR_LOG_WITH_ARGS, new LogFields(), FIRST_ARG, SECOND_ARG); + + // Validate that the message was parsed from the bundle resource. + logger.validateLogMsg( + "UT0002E This is an error log with some arguments " + FIRST_ARG + " and " + SECOND_ARG); + } + + /** This test validates that WARNING level logs are correctly parsed from the + * resource bundle. */ + @Test + public void logStatementWarnParsingTest() { + + String FIRST_ARG = "First Arg"; + String SECOND_ARG = "Second Arg"; + + // Generate a simple ERROR log. + loggerAdapter.warn(UnitTestMsgs.SIMPLE_WARN_LOG, null); + + // Validate that the message was parsed from the bundle resource. + logger.validateLogMsg("UT0001W This is a simple warning log with no arguments."); + + // Generate a WARNING log with arguments. + loggerAdapter.warn(UnitTestMsgs.WARN_LOG_WITH_ARGS, FIRST_ARG, SECOND_ARG); + + // Validate that the message was parsed from the bundle resource. + logger.validateLogMsg( + "UT0002W This is a warning log with some arguments " + FIRST_ARG + " and " + SECOND_ARG); + } + + /** This test validates that DEBUG level logs are correctly parsed from the + * resource bundle. */ + @Test + public void logStatementDebugParsingTest() { + + String FIRST_ARG = "First Arg"; + String SECOND_ARG = "Second Arg"; + String SIMPLE_DEBUG_MSG = "My simple debug message"; + + // Generate a simple DEBUG log with no error code. + loggerAdapter.debug(SIMPLE_DEBUG_MSG); + + // Validate that the message was parsed from the bundle resource. + logger.validateLogMsg(SIMPLE_DEBUG_MSG); + + // Generate an ERROR log with arguments. + loggerAdapter.debug(UnitTestMsgs.DEBUG_LOG_WITH_ARGS, FIRST_ARG, SECOND_ARG); + + // Validate that the message was parsed from the bundle resource. + logger.validateLogMsg( + "UT0001D This is a debug log with some arguments " + FIRST_ARG + " and " + SECOND_ARG); + } + + /** This test validates that TRACE level logs are correctly parsed from the + * resource bundle. */ + @Test + public void logStatementTraceParsingTest() { + + String FIRST_ARG = "First Arg"; + String SECOND_ARG = "Second Arg"; + + // Generate a simple TRACE log with no error code. + loggerAdapter.trace(UnitTestMsgs.SIMPLE_TRACE_LOG, null); + + // Validate that the message was parsed from the bundle resource. + logger.validateLogMsg("UT0001T This is a simple trace log with no arguments."); + logger.validateLogLevel(EELFLogger.Level.TRACE); + + // Generate an ERROR log with arguments. + loggerAdapter.trace(UnitTestMsgs.TRACE_LOG_WITH_ARGS, FIRST_ARG, SECOND_ARG); + + // Validate that the message was parsed from the bundle resource. + logger.validateLogMsg( + "UT0002T This is a trace log with some arguments " + FIRST_ARG + " and " + SECOND_ARG); + logger.validateLogLevel(EELFLogger.Level.TRACE); + } + + /** This is a convenience method that validates that a generated log message + * contains the expected values when a log code could not be parsed. + * + * @param aLogMessage + * - The log message to be validated. + * @param aLogCode + * - The error code that was passed to the logger. */ + private void assertBadLogCodeMessage(String aLogMessage, Enum aLogCode) { + + assertTrue("Expected 'unparseable log code' generic error string", + logger.getMessage().contains(AaiLoggerAdapter.BAD_ENUM_MSG)); + assertTrue("Expected error string to include log code", + logger.getMessage().contains(aLogCode.toString())); + } + + /** This test validates the formatMsg method returns a properly formatted + * message */ + @Test + public void formatMsgTest() { + + String FIRST_ARG = "First Arg"; + String SECOND_ARG = "Second Arg"; + String EXPECTED1 = "UT0001I This is a simple info log with no arguments."; + String EXPECTED2 = "UT0002I This is an info log with some arguments " + FIRST_ARG + " and " + + SECOND_ARG; + + String message1 = loggerAdapter.formatMsg(UnitTestMsgs.SIMPLE_INFO_LOG); + assertEquals("Invalid formatted msg1", message1, EXPECTED1); + + String message2 = loggerAdapter.formatMsg(UnitTestMsgs.INFO_LOG_WITH_ARGS, FIRST_ARG, + SECOND_ARG); + assertEquals("Invalid formatted msg2", message2, EXPECTED2); + } + + /** This is an implementation of the {@link EELFLogger} which just caches the + * last log statement passed to it and provides some convenience methods for + * validating the contents of the log message. + * <p> + * The instance of the {@link AaiLoggerAdapter} that we are testing against + * will use this implementation instead of a real {@link EELFLogger}. */ + private class TestLogger implements EELFLogger { + + // Some indices to use for extracting specific fields from the + // log statement. + private static final int MESSAGE_INDEX = 1; + + private static final int METRICE_TRANS_ID_INDEX = 2; + private static final int METRICS_RESP_CODE_INDEX = 11; + private static final int METRICS_RESP_STRING_INDEX = 12; + private static final int METRICS_MSG_INDEX = 28; + + private static final int AUDIT_RESP_CODE_INDEX = 9; + private static final int AUDIT_RESP_STRING_INDEX = 10; + private static final int AUDIT_MSG_INDEX = 25; + + /** Stores the last log statement passed to the logger. */ + private String logMessage; + + private EELFLogger.Level logLevel; + + @Override + public void warn(String msg) { + logMessage = msg; + logLevel = EELFLogger.Level.WARN; + } + + @Override + public void debug(String msg) { + logMessage = msg; + logLevel = EELFLogger.Level.DEBUG; + } + + @Override + public void trace(String msg) { + logMessage = msg; + logLevel = EELFLogger.Level.TRACE; + } + + @Override + public void info(String msg) { + logMessage = msg; + logLevel = EELFLogger.Level.INFO; + } + + @Override + public void error(String msg) { + logMessage = msg; + logLevel = EELFLogger.Level.ERROR; + + } + + @Override + public void warn(String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void warn(String msg, Throwable th) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void debug(String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void debug(String msg, Throwable th) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void info(String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void trace(String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void trace(String msg, Throwable th) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void error(String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void error(String msg, Throwable th) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public boolean isTraceEnabled() { + return false; + } + + @Override + public boolean isInfoEnabled() { + return false; + } + + @Override + public boolean isErrorEnabled() { + return false; + } + + @Override + public boolean isWarnEnabled() { + return false; + } + + @Override + public boolean isDebugEnabled() { + return false; + } + + @Override + public void log(Level level, String msg, Throwable th, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void auditEvent(String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void auditEvent(Level level, String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void metricsEvent(String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void metricsEvent(Level level, String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void securityEvent(String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void securityEvent(Level level, String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void performanceEvent(String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void performanceEvent(Level level, String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void applicationEvent(String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void applicationEvent(Level level, String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void serverEvent(String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void serverEvent(Level level, String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void policyEvent(String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void policyEvent(Level level, String msg, Object... arguments) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void warn(Locale locale, EELFResolvableErrorEnum errorCode, Throwable th, + String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void info(Locale locale, EELFResolvableErrorEnum errorCode, Throwable th, + String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void debug(Locale locale, EELFResolvableErrorEnum errorCode, Throwable th, + String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void error(Locale locale, EELFResolvableErrorEnum errorCode, Throwable th, + String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void trace(Locale locale, EELFResolvableErrorEnum errorCode, Throwable th, + String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void warn(Locale locale, EELFResolvableErrorEnum errorCode, String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void info(Locale locale, EELFResolvableErrorEnum errorCode, String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void debug(Locale locale, EELFResolvableErrorEnum errorCode, String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void error(Locale locale, EELFResolvableErrorEnum errorCode, String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void trace(Locale locale, EELFResolvableErrorEnum errorCode, String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void warn(EELFResolvableErrorEnum errorCode, String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void info(EELFResolvableErrorEnum errorCode, String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void debug(EELFResolvableErrorEnum errorCode, String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void error(EELFResolvableErrorEnum errorCode, String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void trace(EELFResolvableErrorEnum errorCode, String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void warn(EELFResolvableErrorEnum errorCode, Throwable th, String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void info(EELFResolvableErrorEnum errorCode, Throwable th, String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void debug(EELFResolvableErrorEnum errorCode, Throwable th, String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void error(EELFResolvableErrorEnum errorCode, Throwable th, String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void trace(EELFResolvableErrorEnum errorCode, Throwable th, String... args) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void setLevel(Level level) { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + @Override + public void disableLogging() { + throw new UnsupportedOperationException( + "AAILoggerAdapter is not expected to call into this method."); + } + + /** Convenience method to retrieve the log string that was produced by the + * logger. + * + * @return - A log string. */ + public String getMessage() { + return logMessage; + } + + /** Validates that the parsed log message encoded in the last produced log + * message matches the supplied expected value. + * + * @param aMessage + * - The expected log message. */ + public void validateLogMsg(String aMessage) { + + // Tokenize the log string. + String[] tokens = tokenizeLogString(); + + // Verify the log message. + assertTrue("Unexpected log message in log string", aMessage.equals(tokens[MESSAGE_INDEX])); + } + + public void validateLogFields(LogLineType logType, LogFields fields) { + + // Tokenize the log string. + String[] tokens = tokenizeLogString(); + + switch (logType) { + + case ERROR: + break; + + case METRICS: + if (fields.getField(DefinedFields.TARGET_SVC_NAME) != null) { + assertTrue(fields.getField(DefinedFields.TARGET_SVC_NAME).equals(tokens[9])); + } + if (fields.getField(DefinedFields.STATUS_CODE) != null) { + assertTrue(fields.getField(DefinedFields.STATUS_CODE).equals(tokens[10])); + } + if (fields.getField(DefinedFields.RESPONSE_CODE) != null) { + assertTrue(fields.getField(DefinedFields.RESPONSE_CODE).equals(tokens[11])); + } + if (fields.getField(DefinedFields.RESPONSE_DESCRIPTION) != null) { + assertTrue(fields.getField(DefinedFields.RESPONSE_DESCRIPTION).equals(tokens[12])); + } + if (fields.getField(DefinedFields.INSTANCE_UUID) != null) { + assertTrue(fields.getField(DefinedFields.INSTANCE_UUID).equals(tokens[13])); + } + if (fields.getField(DefinedFields.SEVERITY) != null) { + assertTrue(fields.getField(DefinedFields.SEVERITY).equals(tokens[15])); + } + if (fields.getField(DefinedFields.SERVER_IP) != null) { + assertTrue(fields.getField(DefinedFields.SERVER_IP).equals(tokens[16])); + } + if (fields.getField(DefinedFields.CLIENT_IP) != null) { + assertTrue(fields.getField(DefinedFields.CLIENT_IP).equals(tokens[19])); + } + if (fields.getField(DefinedFields.CLASS_NAME) != null) { + assertTrue(fields.getField(DefinedFields.CLASS_NAME).equals(tokens[20])); + } + if (fields.getField(DefinedFields.PROCESS_KEY) != null) { + assertTrue(fields.getField(DefinedFields.PROCESS_KEY).equals(tokens[22])); + } + if (fields.getField(DefinedFields.TARGET_ENTITY) != null) { + assertTrue(fields.getField(DefinedFields.TARGET_ENTITY).equals(tokens[23])); + } + if (fields.getField(DefinedFields.CUSTOM_1) != null) { + assertTrue(fields.getField(DefinedFields.CUSTOM_1).equals(tokens[24])); + } + if (fields.getField(DefinedFields.CUSTOM_2) != null) { + assertTrue(fields.getField(DefinedFields.CUSTOM_2).equals(tokens[25])); + } + if (fields.getField(DefinedFields.CUSTOM_3) != null) { + assertTrue(fields.getField(DefinedFields.CUSTOM_3).equals(tokens[26])); + } + if (fields.getField(DefinedFields.CUSTOM_4) != null) { + assertTrue(fields.getField(DefinedFields.CUSTOM_4).equals(tokens[27])); + } + break; + + case AUDIT: + if (fields.getField(DefinedFields.STATUS_CODE) != null) { + assertTrue(fields.getField(DefinedFields.STATUS_CODE).equals(tokens[8])); + } + if (fields.getField(DefinedFields.RESPONSE_CODE) != null) { + assertTrue(fields.getField(DefinedFields.RESPONSE_CODE).equals(tokens[9])); + } + if (fields.getField(DefinedFields.RESPONSE_DESCRIPTION) != null) { + assertTrue(fields.getField(DefinedFields.RESPONSE_DESCRIPTION).equals(tokens[10])); + } + if (fields.getField(DefinedFields.INSTANCE_UUID) != null) { + assertTrue(fields.getField(DefinedFields.INSTANCE_UUID).equals(tokens[11])); + } + if (fields.getField(DefinedFields.SEVERITY) != null) { + assertTrue(fields.getField(DefinedFields.SEVERITY).equals(tokens[13])); + } + if (fields.getField(DefinedFields.SERVER_IP) != null) { + assertTrue(fields.getField(DefinedFields.SERVER_IP).equals(tokens[14])); + } + if (fields.getField(DefinedFields.CLASS_NAME) != null) { + assertTrue(fields.getField(DefinedFields.CLASS_NAME).equals(tokens[18])); + } + if (fields.getField(DefinedFields.PROCESS_KEY) != null) { + assertTrue(fields.getField(DefinedFields.PROCESS_KEY).equals(tokens[20])); + } + if (fields.getField(DefinedFields.CUSTOM_1) != null) { + assertTrue(fields.getField(DefinedFields.CUSTOM_1).equals(tokens[21])); + } + if (fields.getField(DefinedFields.CUSTOM_2) != null) { + assertTrue(fields.getField(DefinedFields.CUSTOM_2).equals(tokens[22])); + } + if (fields.getField(DefinedFields.CUSTOM_3) != null) { + assertTrue(fields.getField(DefinedFields.CUSTOM_3).equals(tokens[23])); + } + if (fields.getField(DefinedFields.CUSTOM_4) != null) { + assertTrue(fields.getField(DefinedFields.CUSTOM_4).equals(tokens[24])); + } + break; + } + } + + private void validateMetricsMsg(String value) { + String[] tokens = tokenizeLogString(); + assertTrue("Unexpected message in log string", value.equals(tokens[METRICS_MSG_INDEX])); + } + + private void validateMetricsRespStatus(String code, String codeStr) { + String[] tokens = tokenizeLogString(); + assertTrue("Unexpected resp code in log string", + code.equals(tokens[METRICS_RESP_CODE_INDEX])); + assertTrue("Unexpected resp string in log string", + codeStr.equals(tokens[METRICS_RESP_STRING_INDEX])); + } + + private void validateMetricsRequestId(String value) { + String[] tokens = tokenizeLogString(); + assertTrue("Unexpected req id in log string", value.equals(tokens[METRICE_TRANS_ID_INDEX])); + } + + private void validateAuditMsg(String value) { + String[] tokens = tokenizeLogString(); + assertTrue("Unexpected message in log string", value.equals(tokens[AUDIT_MSG_INDEX])); + } + + private void validateAuditRespStatus(String code, String codeStr) { + String[] tokens = tokenizeLogString(); + assertTrue("Unexpected resp code in log string", code.equals(tokens[AUDIT_RESP_CODE_INDEX])); + assertTrue("Unexpected resp string in log string", + codeStr.equals(tokens[AUDIT_RESP_STRING_INDEX])); + } + + public void validateLogLevel(EELFLogger.Level expectedLevel) { + + assertEquals("Unexpected log level", expectedLevel, logLevel); + } + + /** This method breaks up the log string into individual tokenized fields, + * delimited by the '|' character. + * + * @return - Array of log message tokens. */ + private String[] tokenizeLogString() { + System.out.println("\n\n---\n" + logMessage + "\n-------"); + return logMessage.split("\\|"); + } + + } +} diff --git a/eelf-logging/src/test/java/org/openecomp/cl/eelf/LoggerFactoryTest.java b/eelf-logging/src/test/java/org/openecomp/cl/eelf/LoggerFactoryTest.java new file mode 100644 index 0000000..5e475aa --- /dev/null +++ b/eelf-logging/src/test/java/org/openecomp/cl/eelf/LoggerFactoryTest.java @@ -0,0 +1,134 @@ +/*- + * ============LICENSE_START======================================================= + * Common Logging Library + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.cl.eelf; + +import static org.junit.Assert.*; + +import org.junit.Test; +import org.openecomp.cl.api.Logger; +import org.openecomp.cl.eelf.LoggerFactory; + +/** This suite of tests is intended to exercise the basic functionality of the + * {@link LoggerFactory}. */ +public class LoggerFactoryTest { + + /** This test validates that the {@link LoggerFactory} is a singleton. */ + @Test + public void loggerFactorySingletonTest() { + + // Call getInstance() on the LoggerFactory twice. + LoggerFactory loggerFactory1 = LoggerFactory.getInstance(); + LoggerFactory loggerFactory2 = LoggerFactory.getInstance(); + + // Validate that what we got was two references to the same instance + // of the LoggerFactory (ie: yes, it really is a singleton). + assertTrue("Expected references to the SAME LoggerFactory instance", + loggerFactory1 == loggerFactory2); + } + + /** This test validates that we can request {@link Logger} instances from the + * {@link LoggerFactory} by specifying either a name to use as the logger's + * identifier, or a class. */ + @Test + public void getLoggerTest() { + + // Get an instance of the LoggerFactory. + LoggerFactory loggerFactory = LoggerFactory.getInstance(); + + // Request a Logger instance by specifying the name we want for + // the logger. + Logger myLoggerByName = loggerFactory.getLogger("UnitTestLogger"); + + // Validate that we got a logger back. + assertNotNull(myLoggerByName); + + // Now, request a Logger instance by specifying a class as our logger + // identifier. + Logger myLoggerByClass = loggerFactory.getLogger(LoggerFactoryTest.class); + + // Validate that we got a logger back. + assertNotNull(myLoggerByClass); + } + + /** This test validates that the {@link LoggerFactory} will only produce a + * single unique {@link Logger} instance for each requested log name. + * <p> + * In other words, two requests for a {@link Logger} with the same name will + * produce two references to the same instance, not two unique {@link Logger} + * instances. */ + @Test + public void getLoggerSingleInstanceForNameTest() { + + // Get an instance of the LoggerFactory. + LoggerFactory loggerFactory = LoggerFactory.getInstance(); + + // Request a Logger instance by specifying the name we want for + // the logger. + Logger myFirstLogger = loggerFactory.getLogger("UnitTestLogger"); + + // Request another Logger instance, but specify the same name for + // the logger's identifier. + Logger mySecondLogger = loggerFactory.getLogger("UnitTestLogger"); + + // Validate, that because there was already a Logger instance with the + // specified name, we just get back a reference to that instance. + assertTrue("Expected references to the same logger instance", myFirstLogger == mySecondLogger); + + // Now, make a third logger request, but specify a different name. + Logger myThirdLogger = loggerFactory.getLogger("AnotherUnitTestLogger"); + + // Validate that, in this case, we really do get a new instance. + assertFalse("Expected a unique logger instance", myFirstLogger == myThirdLogger); + assertFalse("Expected a unique logger instance", mySecondLogger == myThirdLogger); + } + + /** This test validates that the {@link LoggerFactory} will only produce a + * single unique {@link Logger} instance for each requested class. + * <p> + * In other words, two requests for a {@link Logger} with the same class will + * produce two references to the same instance, not two unique {@link Logger} + * instances. */ + @Test + public void getLoggerSingleInstanceForClassTest() { + + // Get an instance of the LoggerFactory. + LoggerFactory loggerFactory = LoggerFactory.getInstance(); + + // Request a Logger instance by specifying the class to use as the + // logger's identifier. + Logger myFirstLogger = loggerFactory.getLogger(LoggerFactoryTest.class); + + // Request another Logger instance, but specify the same class for + // the logger's identifier. + Logger mySecondLogger = loggerFactory.getLogger(LoggerFactoryTest.class); + + // Validate, that because there was already a Logger instance with the + // specified class, we just get back a reference to that instance. + assertTrue("Expected references to the same logger instance", myFirstLogger == mySecondLogger); + + // Now, make a third logger request, but specify a different class. + Logger myThirdLogger = loggerFactory.getLogger(LoggerFactory.class); + + // Validate that, in this case, we really do get a new instance. + assertFalse("Expected a unique logger instance", myFirstLogger == myThirdLogger); + assertFalse("Expected a unique logger instance", mySecondLogger == myThirdLogger); + } +} diff --git a/eelf-logging/src/test/java/org/openecomp/cl/eelf/UnitTestMsgs.java b/eelf-logging/src/test/java/org/openecomp/cl/eelf/UnitTestMsgs.java new file mode 100644 index 0000000..0b4eb5e --- /dev/null +++ b/eelf-logging/src/test/java/org/openecomp/cl/eelf/UnitTestMsgs.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * Common Logging Library + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.cl.eelf; + +import org.openecomp.cl.eelf.LogMessageEnum; + +import com.att.eelf.i18n.EELFResourceManager; + +public enum UnitTestMsgs implements LogMessageEnum { + + SIMPLE_INFO_LOG, + INFO_LOG_WITH_ARGS, + SIMPLE_ERROR_LOG, + ERROR_LOG_WITH_ARGS, + SIMPLE_WARN_LOG, + WARN_LOG_WITH_ARGS, + SIMPLE_TRACE_LOG, + TRACE_LOG_WITH_ARGS, + DEBUG_LOG_WITH_ARGS; + + /** Static initializer to ensure the resource bundles for this class are + * loaded... */ + static { + EELFResourceManager.loadMessageBundle("logging/UnitTestMsgs"); + } +} diff --git a/eelf-logging/src/test/resources/logging/UnitTestMsgs.properties b/eelf-logging/src/test/resources/logging/UnitTestMsgs.properties new file mode 100644 index 0000000..77f5261 --- /dev/null +++ b/eelf-logging/src/test/resources/logging/UnitTestMsgs.properties @@ -0,0 +1,77 @@ +### +# ============LICENSE_START======================================================= +# Common Logging Library +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +#Resource key=Error Code|Message text|Resolution text |Description text +####### +#Newlines can be utilized to add some clarity ensuring continuing line +#has atleast one leading space +#ResourceKey=\ +# ERR0000E\ +# Sample error msg txt\ +# Sample resolution msg\ +# Sample description txt +# +###### +#Error code classification category +#000 Info/Debug +#100 Permission errors +#200 Availability errors/Timeouts +#300 Data errors +#400 Schema Interface type/validation errors +#500 Business process errors +#900 Unknown errors +# +######################################################################## + +SIMPLE_INFO_LOG=\ + UT0001I|\ + This is a simple info log with no arguments. + +INFO_LOG_WITH_ARGS=\ + UT0002I|\ + This is an info log with some arguments {0} and {1} + +SIMPLE_ERROR_LOG=\ + UT0001E|\ + This is a simple error log with no arguments. + +ERROR_LOG_WITH_ARGS=\ + UT0002E|\ + This is an error log with some arguments {0} and {1} + +SIMPLE_WARN_LOG=\ + UT0001W|\ + This is a simple warning log with no arguments. + +WARN_LOG_WITH_ARGS=\ + UT0002W|\ + This is a warning log with some arguments {0} and {1} + +SIMPLE_TRACE_LOG=\ + UT0001T|\ + This is a simple trace log with no arguments. + +TRACE_LOG_WITH_ARGS=\ + UT0002T|\ + This is a trace log with some arguments {0} and {1} + +DEBUG_LOG_WITH_ARGS=\ + UT0001D|\ + This is a debug log with some arguments {0} and {1} diff --git a/logging-api/pom.xml b/logging-api/pom.xml new file mode 100644 index 0000000..4c4470e --- /dev/null +++ b/logging-api/pom.xml @@ -0,0 +1,41 @@ +<!-- + ============LICENSE_START======================================================= + Common Logging Library + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.openecomp.aai.logging-service</groupId> + <artifactId>logging-service</artifactId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <groupId>org.openecomp.aai</groupId> + <artifactId>logging-api</artifactId> + <name>Common Logging API</name> + + <dependencies> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>1.7.5</version> + </dependency> + </dependencies> +</project> diff --git a/logging-api/src/main/java/org/openecomp/cl/api/LogFields.java b/logging-api/src/main/java/org/openecomp/cl/api/LogFields.java new file mode 100644 index 0000000..87b3f3f --- /dev/null +++ b/logging-api/src/main/java/org/openecomp/cl/api/LogFields.java @@ -0,0 +1,84 @@ +/*- + * ============LICENSE_START======================================================= + * Common Logging Library + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.cl.api; + +import java.util.HashMap; +import java.util.Map; + +public class LogFields { + + /** Map of field names to values. */ + private Map<Integer, String> fields = new HashMap<Integer, String>(); + + /** + * Retrieve the contents of the specified field entry. + * + * @param field + * - The field to retrieve the value for. + * + * @return - The value associated with the specified field, or null if there + * is no such entry. + */ + public String getField(Enum field) { + return fields.get(field.ordinal()); + } + + /** + * Assigns a value to a specific field. + * + * @param field + * - The field to assign a value to. + * @param value + * - The value to assign to the field. + * + * @return - The {@link LogFields} object (this is useful for parameter + * chaining. + */ + public LogFields setField(Enum field, String value) { + fields.put(field.ordinal(), value); + return this; + } + + /** + * Assigns a value to a specific field. + * + * @param field - The field to assign a value to. + * @param value - The value to assign to the field. + * + * @return - The {@link LogFields} object (this is useful for parameter + * chaining. + */ + public LogFields setField(Enum field, int value) { + fields.put(field.ordinal(), String.valueOf(value)); + return this; + } + + /** + * Determines whether or not a value has been assigned to a particular field. + * + * @param field - The field to be checked. + * + * @return - true if an entry exists for the specified field, false otherwise. + */ + public boolean fieldIsSet(Enum field) { + return fields.containsKey(field.ordinal()) && (fields.get(field.ordinal()) != null); + } +} diff --git a/logging-api/src/main/java/org/openecomp/cl/api/LogLine.java b/logging-api/src/main/java/org/openecomp/cl/api/LogLine.java new file mode 100644 index 0000000..2b6f30f --- /dev/null +++ b/logging-api/src/main/java/org/openecomp/cl/api/LogLine.java @@ -0,0 +1,115 @@ +/*- + * ============LICENSE_START======================================================= + * Common Logging Library + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.cl.api; + +import org.openecomp.cl.mdc.MdcContext; +import org.openecomp.cl.mdc.MdcOverride; + +import org.slf4j.MDC; + +/** + * This class is used to help standardize how log lines are written and provide + * profiling info. + */ +public abstract class LogLine { + + public static enum LogLineType { + AUDIT, ERROR, METRICS + } + + /** + * Enumerates the predefined fields of the log line. Note that this + * enumeration only exposes those fields that the client may set via the + * {@link LogFields} object. Fields which are automatically populated by the + * logging service or sourced from the {@link MdcContext} do not appear here. + */ + public enum DefinedFields { + + STATUS_CODE, + RESPONSE_CODE, + RESPONSE_DESCRIPTION, + INSTANCE_UUID, + SEVERITY, + SERVER_IP, + CLIENT_IP, + CLASS_NAME, + PROCESS_KEY, + TARGET_SVC_NAME, + TARGET_ENTITY, + ERROR_CODE, + ERROR_DESCRIPTION, + CUSTOM_1, + CUSTOM_2, + CUSTOM_3, + CUSTOM_4; + } + + protected String component = ""; + protected String logCode = ""; + protected String level = ""; + protected String message = ""; + protected MdcOverride override = new MdcOverride(); + protected LogFields fields = new LogFields(); + + /** + * Sets common values that the log line will use for populating the log + * string. + * + * @param component + * - The entity invoking the log. + * @param logCode + * - String version of the log message code. + * @param level + * - Log level (DEBUG, TRACE, INFO, WARN, ERROR...) + * @param msg + * - The log message + * @param fields + * - A map of predefined log line fields to values. + * @param override + * - Structure which overrides selective fields in the + * {@link MdcContext} + */ + public void init(String component, String logCode, String level, String msg, LogFields fields, + MdcOverride override) { + + this.component = component; + this.logCode = logCode; + this.level = level; + this.message = msg; + this.override = override; + this.fields = fields; + } + + protected String getMdcValue(String attribute) { + if (override.hasOverride(attribute)) { + return override.getAttributeValue(attribute); + } + + String value = (String) MDC.get(attribute) == null ? "" : (String) MDC.get(attribute); + return value; + } + + public abstract String getFormattedLine(); + + protected String fieldValue(Enum field) { + return (fields.fieldIsSet(field) ? fields.getField(field) : ""); + } +} diff --git a/logging-api/src/main/java/org/openecomp/cl/api/Logger.java b/logging-api/src/main/java/org/openecomp/cl/api/Logger.java new file mode 100644 index 0000000..2b428e5 --- /dev/null +++ b/logging-api/src/main/java/org/openecomp/cl/api/Logger.java @@ -0,0 +1,216 @@ +/*- + * ============LICENSE_START======================================================= + * Common Logging Library + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.cl.api; + +import org.openecomp.cl.mdc.MdcOverride; + +/** Defines the common API which all Logger implementations must expose. */ +public interface Logger { + + /** + * Indicate whether or not TRACE level logging is enabled. + * + * @return true if TRACE level logs are enabled, false otherwise + */ + public boolean isTraceEnabled(); + + /** + * Indicate whether or not INFO level logging is enabled. + * + * @return true if INFO level logs are enabled, false otherwise + */ + public boolean isInfoEnabled(); + + /** + * Indicate whether or not ERROR level logging is enabled. + * + * @return true if ERROR level logs are enabled, false otherwise + */ + public boolean isErrorEnabled(); + + /** + * Indicate whether or not WARNING level logging is enabled. + * + * @return true if WARNING level logs are enabled, false otherwise + */ + public boolean isWarnEnabled(); + + /** + * Indicate whether or not DEBUG level logging is enabled. + * + * @return true if DEBUG level logs are enabled, false otherwise + */ + public boolean isDebugEnabled(); + + /** + * Log an INFO message based on a message key defined in a resource bundle + * with arguments. + * + * @param logCode + * - Log message identifier. + * @param arguments + * - Arguments to populate the log message template with. + */ + public void info(Enum logCode, String... arguments); + + /** + * Log an INFO message based on a message key defined in a resource bundle + * with arguments. + * + * @param logCode + * - Log message identifier. + * @param fields + * - Map containing values for any log fields which the client wants + * to populate. + * @param arguments + * - Arguments to populate the log message template with. + */ + public void info(Enum logCode, LogFields fields, String... arguments); + + /** + * Log an INFO message based on a message key defined in a resource bundle + * with arguments. + * + * @param logCode - Log message identifier. + * @param fields - Map containing values for any log fields which the + * client wants to populate. + * @param override - A set of values to override values stored in the MDC context + * @param arguments - Arguments to populate the log message template with. + */ + public void info(Enum logCode, LogFields fields, MdcOverride override, String... arguments); + + /** + * Log a WARNING message based on a message key defined in a resource bundle + * with arguments. + * + * @param logCode - Log message identifier. + * @param arguments - Arguments to populate the log message template with. + */ + public void warn(Enum logCode, String... arguments); + + /** + * Log a WARNING message based on a message key defined in a resource bundle + * with arguments. + * + * @param logCode - Log message identifier. + * @param fields - Map containing values for any log fields which the + * client wants to populate. + * @param arguments - Arguments to populate the log message template with. + */ + public void warn(Enum logCode, LogFields fields, String... arguments); + + /** + * Log a TRACE message based on a message key defined in a resource bundle + * with arguments. + * + * @param logCode - Log message identifier. + * @param arguments - Arguments to populate the log message template with. + */ + public void trace(Enum logCode, String... arguments); + + /** + * Log a TRACE message based on a message key defined in a resource bundle + * with arguments. + * + * @param logCode - Log message identifier. + * @param fields - Map containing values for any log fields which the + * client wants to populate. + * @param arguments - Arguments to populate the log message template with. + */ + public void trace(Enum logCode, LogFields fields, String... arguments); + + /** + * Log a simple, non-templated DEBUG message. + * + * @param logMessage - The message to be logged. + */ + public void debug(String logMessage); + + /** + * Log a DEBUG message based on a message key defined in a resource bundle + * with arguments. + * + * @param logCode - Log message identifier. + * @param arguments - Arguments to populate the log message template with. + */ + public void debug(Enum logCode, String... arguments); + + /** + * Log a DEBUG message based on a message key defined in a resource bundle + * with arguments. + * + * @param logCode - Log message identifier. + * @param fields - Map containing values for any log fields which the + * client wants to populate. + * @param arguments - Arguments to populate the log message template with. + */ + public void debug(Enum logCode, LogFields fields, String... arguments); + + /** + * Log an ERROR message based on a message key defined in a resource bundle + * with arguments. + * + * @param logCode - Log message identifier. + * @param arguments - Arguments to populate the log message template with. + */ + public void error(Enum logCode, String... arguments); + + /** + * Log an ERROR message based on a message key defined in a resource bundle + * with arguments. + * + * @param logCode - Log message identifier. + * @param fields - Map containing values for any log fields which the + * client wants to populate. + * @param arguments - Arguments to populate the log message template with. + */ + public void error(Enum logCode, LogFields fields, String... arguments); + + /** + * Log an ERROR message based on a message key defined in a resource bundle + * with arguments and a throwable exception. + * + * @param logCode - Log message identifier. + * @param ex - The exception to be logged. + * @param arguments - Arguments to populate the log message template with. + */ + public void error(Enum logCode, Throwable ex, String... arguments); + + /** + * Log an ERROR message based on a message key defined in a resource bundle + * with arguments and a throwable exception. + * + * @param logCode - Log message identifier. + * @param fields - Map containing values for any log fields which the + * client wants to populate. + * @param ex - The exception to be logged. + * @param arguments - Arguments to populate the log message template with. + */ + public void error(Enum logCode, LogFields fields, Throwable ex, String... arguments); + + /** + * Format the given log using the supplied arguments + * @param logCode - Log message identifier. + * @param arguments - Arguments to populate the log message template with. + */ + public String formatMsg(Enum logCode, String... arguments); + +} diff --git a/logging-api/src/main/java/org/openecomp/cl/api/LoggerFactoryInterface.java b/logging-api/src/main/java/org/openecomp/cl/api/LoggerFactoryInterface.java new file mode 100644 index 0000000..c990881 --- /dev/null +++ b/logging-api/src/main/java/org/openecomp/cl/api/LoggerFactoryInterface.java @@ -0,0 +1,43 @@ +/*- + * ============LICENSE_START======================================================= + * Common Logging Library + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.cl.api; + +/** + * Defines the common API that must be exposed by all LoggerFactory + * implementations. + */ +public interface LoggerFactoryInterface { + + /** + * Returns the logger associated with the name. + * + * @return Logger + */ + public Logger getLogger(String name); + + /** + * Returns the logger associated with the clazz. + * + * @return Logger + */ + public Logger getLogger(Class<?> clazz); + +} diff --git a/logging-api/src/main/java/org/openecomp/cl/mdc/MdcContext.java b/logging-api/src/main/java/org/openecomp/cl/mdc/MdcContext.java new file mode 100644 index 0000000..6e9e6f4 --- /dev/null +++ b/logging-api/src/main/java/org/openecomp/cl/mdc/MdcContext.java @@ -0,0 +1,78 @@ +/*- + * ============LICENSE_START======================================================= + * Common Logging Library + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.cl.mdc; + +import org.slf4j.MDC; + +import java.net.InetAddress; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * This class manages the MDC (mapped diagnostic context). Calling the init + * method when a new event is processed will save thread-specific context + * information which will be used when generating logs. + */ +public final class MdcContext { + public static String MDC_REQUEST_ID = "RequestId"; + public static String MDC_SERVER_FQDN = "ServerFQDN"; + public static String MDC_SERVICE_NAME = "ServiceName"; + public static String MDC_PARTNER_NAME = "PartnerName"; + public static String MDC_START_TIME = "StartTime"; + public static String MDC_REMOTE_HOST = "RemoteHost"; + public static String MDC_SERVICE_INSTANCE_ID = "ServiceInstanceId"; + public static String MDC_CLIENT_ADDRESS = "ClientAddress"; + + /** + * Initializes the fields of the Mapped Diagnostic Context. + * + * @param transId - Unique transaction identifier. + * @param serviceName - The name of the service generating the diagnostic. + * @param serviceInstance - Unique identifier of the specific instance + * generating the diagnostic. + * @param partnerName - Name of the entity initiating the transction to + * be logged + * @param clientAddress - IP address of the transaction client. + */ + public static void initialize(String transId, + String serviceName, + String serviceInstance, + String partnerName, + String clientAddress) { + MDC.clear(); + MDC.put(MDC_REQUEST_ID, transId); + MDC.put(MDC_SERVICE_NAME, serviceName); + MDC.put(MDC_SERVICE_INSTANCE_ID, serviceInstance); + MDC.put(MDC_PARTNER_NAME, partnerName); + MDC.put(MDC_CLIENT_ADDRESS, clientAddress); + MDC.put(MDC_START_TIME, + new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX").format(new Date())); + + try { + MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getCanonicalHostName()); + } catch (Exception e) { + // If, for some reason we are unable to get the canonical host name, we + // just want to leave the field unpopulated. There is not much value + // in doing anything else with an exception at this point. + } + + } +} diff --git a/logging-api/src/main/java/org/openecomp/cl/mdc/MdcOverride.java b/logging-api/src/main/java/org/openecomp/cl/mdc/MdcOverride.java new file mode 100644 index 0000000..413ce36 --- /dev/null +++ b/logging-api/src/main/java/org/openecomp/cl/mdc/MdcOverride.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * Common Logging Library + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.cl.mdc; + +import java.util.HashMap; +import java.util.Map; + +/** + * This class stores a map of MDC context attribute/values which can be used to + * override the actual MDC context. + */ +public class MdcOverride { + private Map<String, String> overrides = new HashMap<String, String>(); + + public void addAttribute(String attr, String val) { + overrides.put(attr, val); + } + + public String getAttributeValue(String attr) { + return overrides.get(attr); + } + + public boolean hasOverride(String attr) { + return overrides.containsKey(attr); + } +} @@ -0,0 +1,189 @@ +<!-- + ============LICENSE_START======================================================= + Common Logging Library + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>org.openecomp.aai.logging-service</groupId> + <artifactId>logging-service</artifactId> + <packaging>pom</packaging> + <version>1.0.0-SNAPSHOT</version> + <name>Common Logging Library</name> + + <properties> + <repository.id>ecomp-nexus</repository.id> + <repository.name>ecomp-releases</repository.name> + <repository.url>https://ecomp-nexus:8443/repository/maven-releases</repository.url> + <snapShotRepository.id>ecomp-nexus</snapShotRepository.id> + <snapShotRepository.name>ecomp-snapshots</snapShotRepository.name> + <snapShotRepository.url>https://ecomp-nexus:8443/repository/maven-snapshots</snapShotRepository.url> + <checkstyle.config.location>google_checks.xml</checkstyle.config.location> + </properties> + + <scm> + <connection>scm:git:ssh://git@104.130.163.223:OpenECOMP/common-logging.git</connection> + <tag>HEAD</tag> + </scm> + + <modules> + <module>logging-api</module> + <module>eelf-logging</module> + <module>common-logging</module> + </modules> + + <build> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + <plugin> + <artifactId>maven-release-plugin</artifactId> + <version>2.4.2</version> + <dependencies> + <dependency> + <groupId>org.apache.maven.scm</groupId> + <artifactId>maven-scm-provider-gitexe</artifactId> + <version>1.8.1</version> + </dependency> + </dependencies> + </plugin> + + <!-- Checkstyle plugin - used to report on compliance with --> + <!-- the Google style guide. --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-site-plugin</artifactId> + <version>3.3</version> + <configuration> + <reportPlugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-checkstyle-plugin</artifactId> + <version>2.17</version> + <reportSets> + <reportSet> + <reports> + <report>checkstyle</report> + </reports> + </reportSet> + </reportSets> + </plugin> + </reportPlugins> + </configuration> + </plugin> + </plugins> + </pluginManagement> + <plugins> + <!-- blackduck maven plugin --> + <plugin> + <groupId>com.blackducksoftware.integration</groupId> + <artifactId>hub-maven-plugin</artifactId> + <version>1.4.0</version> + <inherited>false</inherited> + <configuration> + <hubProjectName>${project.name}</hubProjectName> + <outputDirectory>${project.basedir}</outputDirectory> + </configuration> + <executions> + <execution> + <id>create-bdio-file</id> + <phase>package</phase> + <goals> + <goal>createHubOutput</goal> + </goals> + </execution> + </executions> + </plugin> + + <!-- license plugin --> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>license-maven-plugin</artifactId> + <version>1.10</version> + <configuration> + <addJavaLicenseAfterPackage>false</addJavaLicenseAfterPackage> + <verbose>true</verbose> + <excludes> + <exclude>**.json</exclude> + </excludes> + <processStartTag>============LICENSE_START=======================================================</processStartTag> + <processEndTag>============LICENSE_END=========================================================</processEndTag> + <sectionDelimiter>================================================================================</sectionDelimiter> + <licenseName>apache_v2</licenseName> + <inceptionYear>2017</inceptionYear> + <organizationName>AT&T Intellectual Property. All rights reserved.</organizationName> + <projectName>Common Logging Library</projectName> + <canUpdateCopyright>true</canUpdateCopyright> + <canUpdateDescription>true</canUpdateDescription> + <canUpdateLicense>true</canUpdateLicense> + <emptyLineAfterHeader>true</emptyLineAfterHeader> + <roots> + <root>.</root> + </roots> + <extraExtensions> + <md>java</md> + <txt>java</txt> + </extraExtensions> + </configuration> + <executions> + <execution> + <id>first</id> + <goals> + <goal>update-file-header</goal> + </goals> + <phase>process-sources</phase> + <configuration> + <licenseName>apache_v2</licenseName> + <excludes> + <exclude>*.json</exclude> + </excludes> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + <dependencies> + </dependencies> + + <distributionManagement> + + <!-- Repository to publish RELEASE artifacts to. --> + <repository> + <id>${repository.id}</id> + <name>${repository.name}</name> + <url>${repository.url}</url> + </repository> + + <!-- Repository to publish SNAPSHOT artifacts to. --> + <snapshotRepository> + <id>${snapShotRepository.id}</id> + <name>${snapShotRepository.name}</name> + <url>${snapShotRepository.url}</url> + </snapshotRepository> + </distributionManagement> + +</project> |