aboutsummaryrefslogtreecommitdiffstats
path: root/openecomp-be/lib/openecomp-sdc-logging-lib
diff options
context:
space:
mode:
authorvempo <vitaliy.emporopulo@amdocs.com>2018-03-26 20:37:06 +0300
committerOren Kleks <orenkle@amdocs.com>2018-04-01 07:57:35 +0000
commit8eff104effad587c04a00cdd008935af38ee7dc9 (patch)
tree25d6307d7e90cb8d49d0a6cd1f94097747ce7eea /openecomp-be/lib/openecomp-sdc-logging-lib
parent8d74513329f8b6c6783024de866784f32c4b0f2c (diff)
Introduced metrics to logging API
Metrics data can now be passed to logger. Also general cleanup, refactoring, simpler implementation, javadocs. Change-Id: I037101aa9626b3e011737ec2e3497ab348319e4c Issue-ID: SDC-772 Signed-off-by: vempo <vitaliy.emporopulo@amdocs.com>
Diffstat (limited to 'openecomp-be/lib/openecomp-sdc-logging-lib')
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/AuditData.java10
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ContextData.java5
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/Logger.java16
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggerFactory.java22
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/MetricsData.java248
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/package-info.java38
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggerFactoryTest.java11
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/MetricsDataTest.java71
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/pom.xml6
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/GlobalLoggingContext.java123
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/aspects/MetricsAspect.java64
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/context/HostAddress.java89
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/context/InstanceId.java52
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/AuditField.java44
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/ContextField.java4
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/GlobalContextProvider.java9
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCField.java (renamed from openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/annotations/Metrics.java)16
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MetricsField.java47
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapper.java134
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/LogFileCreationTest.java66
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/aspects/MetricsAspectTest.java429
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/context/HostAddressTest.java68
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/context/InstanceIdTest.java36
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapperTest.java199
24 files changed, 953 insertions, 854 deletions
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/AuditData.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/AuditData.java
index ecf795b2d5..b7c4e0d78f 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/AuditData.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/AuditData.java
@@ -17,19 +17,15 @@
package org.openecomp.sdc.logging.api;
/**
- * Builder to populate audit data for logging according to
- * <a href="https://wiki.onap.org/download/attachments/1015849/ONAP%20application%20logging%20guidelines.pdf?api=v2>
- * ONAP application logging guidelines</a>. This includes only data known to an application, and not otherwise available
- * to the logging framework.
+ * Builder to populate <i>audit</i> data. This includes only data known to an application, and not otherwise available
+ * to the logging framework. As opposed, for example, to local runtime, host address, etc.
*
* @author KATYR, evitaliy
* @since February 15, 2018
*/
public class AuditData {
- // A concrete implementation interface was chosen over an interface to enable to gracefully add new fields without
- // affecting client code. Also, the builder can be implemented differently if needed, without affecting client code.
- // For instance, it may delegate the population and instantiation to a service provider.
+ // don't inherit from MetricsData because it has a very different meaning
private final long startTime;
private final long endTime;
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ContextData.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ContextData.java
index ea777d5907..43f0143774 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ContextData.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ContextData.java
@@ -17,8 +17,9 @@
package org.openecomp.sdc.logging.api;
/**
- * Builder to populate logging context data. This includes only data known to an application, and not otherwise
- * available to the logging framework.
+ * Builder to populate logging <i>context</i> data, i.e. data that should be available to any log writing event
+ * throughout an application. This includes only data known at some point to the application (e.g. at an API call),
+ * and not otherwise available to the logging framework (e.g. information about local runtime, machine, etc.).
*
* @author evitaliy
* @since Mar 22, 2018
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/Logger.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/Logger.java
index d02e99f9a2..d100a2d7f9 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/Logger.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/Logger.java
@@ -31,16 +31,16 @@ public interface Logger {
boolean isMetricsEnabled();
+ void metrics(MetricsData data);
+
+ /**
+ * Kept for backward compatibility.
+ *
+ * @deprecated will be removed soon, {@link #metrics(MetricsData)} must be used instead
+ */
+ @Deprecated
void metrics(String msg);
- void metrics(String msg, Object arg);
-
- void metrics(String msg, Object arg1, Object arg2);
-
- void metrics(String msg, Object... arguments);
-
- void metrics(String msg, Throwable t);
-
boolean isAuditEnabled();
void audit(AuditData data);
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggerFactory.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggerFactory.java
index 399fd3717e..1f3df8bcc0 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggerFactory.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggerFactory.java
@@ -16,9 +16,8 @@
package org.openecomp.sdc.logging.api;
-import org.openecomp.sdc.logging.spi.LoggerCreationService;
-
import java.util.Objects;
+import org.openecomp.sdc.logging.spi.LoggerCreationService;
/**
* <a>Factory to hide a concrete, framework-specific implementation of logger creation.</a>
@@ -69,27 +68,12 @@ public class LoggerFactory {
}
@Override
- public void metrics(String msg) {
+ public void metrics(MetricsData msg) {
// no-op
}
@Override
- public void metrics(String msg, Object arg) {
- // no-op
- }
-
- @Override
- public void metrics(String msg, Object arg1, Object arg2) {
- // no-op
- }
-
- @Override
- public void metrics(String msg, Object... arguments) {
- // no-op
- }
-
- @Override
- public void metrics(String msg, Throwable t) {
+ public void metrics(String msg) {
// no-op
}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/MetricsData.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/MetricsData.java
new file mode 100644
index 0000000000..c44ab42efa
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/MetricsData.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.openecomp.sdc.logging.api;
+
+/**
+ * Builder to populate <i>metrics</i> data. This includes only data known to an application, and not otherwise available
+ * to the logging framework.
+ *
+ * @author evitaliy
+ * @since 26 Mar 2018
+ */
+public class MetricsData {
+
+ // don't inherit from AuditData because it has a very different meaning
+
+ private final long startTime;
+ private final long endTime;
+ private final StatusCode statusCode;
+ private final String responseCode;
+ private final String responseDescription;
+ private final String clientIpAddress;
+ private final String targetVirtualEntity;
+ private final String targetEntity;
+
+ private MetricsData(final MetricsDataBuilder builder) {
+ this.startTime = builder.startTime;
+ this.endTime = builder.endTime;
+ this.statusCode = builder.statusCode;
+ this.responseCode = builder.responseCode;
+ this.responseDescription = builder.responseDescription;
+ this.clientIpAddress = builder.clientIpAddress;
+ this.targetEntity = builder.targetEntity;
+ this.targetVirtualEntity = builder.targetVirtualEntity;
+ }
+
+ /**
+ * Begin timestamp of an API invocation.
+ *
+ * @return timestamp
+ */
+ public long getStartTime() {
+ return startTime;
+ }
+
+ /**
+ * End timestamp of an API invocation.
+ *
+ * @return timestamp
+ */
+ public long getEndTime() {
+ return endTime;
+ }
+
+ /**
+ * Result status of an API invocation.
+ *
+ * @return protocol and application agnostic status code
+ */
+ public StatusCode getStatusCode() {
+ return statusCode;
+ }
+
+ /**
+ * Application/protocol specific response status of an API invocation.
+ *
+ * @return response code
+ */
+ public String getResponseCode() {
+ return responseCode;
+ }
+
+ /**
+ * Application/protocol specific response in a human-friendly way.
+ *
+ * @return human-friendly response description
+ */
+ public String getResponseDescription() {
+ return responseDescription;
+ }
+
+ /**
+ * IP address of the invoking client when available.
+ *
+ * @return IP address
+ */
+ public String getClientIpAddress() {
+ return clientIpAddress;
+ }
+
+ /**
+ * External entity invoked by the local system.
+ *
+ * @return identifier of an external entity (system, component, sub-component)
+ */
+ public String getTargetEntity() {
+ return targetEntity;
+ }
+
+ /**
+ * External API invoked by the local system.
+ *
+ * @return name of an external API
+ */
+ public String getTargetVirtualEntity() {
+ return targetVirtualEntity;
+ }
+
+ @Override
+ public String toString() {
+ return "AuditData{startTime=" + startTime + ", endTime=" + endTime + ", statusCode=" + statusCode
+ + ", responseCode=" + responseCode + ", responseDescription=" + responseDescription
+ + ", clientIpAddress=" + clientIpAddress + '}';
+ }
+
+ public static MetricsDataBuilder builder() {
+ return new MetricsDataBuilder();
+ }
+
+ /**
+ * Fluent API for building metrics data.
+ */
+ public static class MetricsDataBuilder {
+
+ private long startTime;
+ private long endTime;
+ private StatusCode statusCode;
+ private String responseCode;
+ private String responseDescription;
+ private String clientIpAddress;
+ private String targetEntity;
+ private String targetVirtualEntity;
+
+ MetricsDataBuilder() { /* package-private default constructor to hide the public one */ }
+
+ /**
+ * Begin timestamp of an activity being audited.
+ *
+ * @param startTime local timestamp, usually received from {@link System#currentTimeMillis()}
+ * @return this builder for fluent API
+ */
+ public MetricsDataBuilder startTime(final long startTime) {
+ this.startTime = startTime;
+ return this;
+ }
+
+ /**
+ * End timestamp of an activity being audited.
+ *
+ * @param endTime local timestamp, usually received from {@link System#currentTimeMillis()}
+ * @return this builder for fluent API
+ */
+ public MetricsDataBuilder endTime(final long endTime) {
+ this.endTime = endTime;
+ return this;
+ }
+
+ /**
+ * Indicate whether an invocation was successful. It is up the the application to decide if a particular result
+ * must be treated as a success or a failure.
+ *
+ * @param statusCode invocation status success/failure
+ * @return this builder for fluent API
+ */
+ public MetricsDataBuilder statusCode(final StatusCode statusCode) {
+ this.statusCode = statusCode;
+ return this;
+ }
+
+ /**
+ * Application/protocol specific response code. For a Web API, it is likely a standard HTTP response code.
+ *
+ * @param responseCode response code that depends on application and invocation protocol
+ * @return this builder for fluent API
+ */
+ public MetricsDataBuilder responseCode(final String responseCode) {
+ this.responseCode = responseCode;
+ return this;
+ }
+
+ /**
+ * Response description that explains {@link #responseCode(String)} in a human-friendly way. For a Web API, it
+ * is likely to be a standard HTTP response phrase.
+ *
+ * @param responseDescription human-friendly response description
+ * @return this builder for fluent API
+ */
+ public MetricsDataBuilder responseDescription(final String responseDescription) {
+ this.responseDescription = responseDescription;
+ return this;
+ }
+
+ /**
+ * IP address of an invoking client.
+ *
+ * @param clientIpAddress IP address
+ * @return this builder for fluent API
+ */
+ public MetricsDataBuilder clientIpAddress(final String clientIpAddress) {
+ this.clientIpAddress = clientIpAddress;
+ return this;
+ }
+
+ /**
+ * External entity at which the operation is invoked.
+ *
+ * @param targetEntity external entity identifier
+ * @return this builder for fluent API
+ */
+ public MetricsDataBuilder targetEntity(String targetEntity) {
+ this.targetEntity = targetEntity;
+ return this;
+ }
+
+ /**
+ * Name of the API or operation activities invoked at the external entity.
+ *
+ * @param targetVirtualEntity invoked external API
+ * @return this builder for fluent API
+ */
+ public MetricsDataBuilder targetVirtualEntity(String targetVirtualEntity) {
+ this.targetVirtualEntity = targetVirtualEntity;
+ return this;
+ }
+
+ /**
+ * Create an instance of {@link MetricsData}.
+ *
+ * @return a populated instance of audit data
+ */
+ public MetricsData build() {
+ return new MetricsData(this);
+ }
+ }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/package-info.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/package-info.java
new file mode 100644
index 0000000000..a8ecad0c55
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/package-info.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+
+/**
+ * <p>Client-visible API for logging, implemented according to
+ * <a href="https://wiki.onap.org/download/attachments/1015849/ONAP%20application%20logging%20guidelines.pdf?api=v2">
+ * ONAP application logging guidelines</a>. The actual implementation is delegated to a service provider bound through
+ * the <a href="https://docs.oracle.com/javase/tutorial/ext/basics/spi.html">Java SPI</a> mechanism. The provider must
+ * implement {@link org.openecomp.sdc.logging.spi.LoggingServiceProvider}.</p>
+ * <p>The logging API collects the following types of data:</p>
+ * <ol>
+ * <li>Context that must be propagated throughout the application, and available at any point for debug and error
+ * reporting.</li>
+ * <li>Audit data, reflecting the invocation of a local, usually REST, API.</li>
+ * <li>Metrics data, reflecting the invocation of a remote API by current system (component).</li>
+ * </ol>
+ * <p>The construction of all three types of data follows the same pattern for consistency. The builder pattern has
+ * been chosen over an interface to enable to gracefully add new fields without affecting the client code. Also, the
+ * builder can be implemented differently if needed, also without affecting client code. For instance, it may delegate
+ * the instantiation and population of a data object to the service provider.</p>
+ *
+ * @author evitaliy
+ * @since 26 Mar 2018
+ */
+package org.openecomp.sdc.logging.api; \ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggerFactoryTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggerFactoryTest.java
index 1889f3e172..a1fe8c2b0f 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggerFactoryTest.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggerFactoryTest.java
@@ -16,14 +16,15 @@
package org.openecomp.sdc.logging.api;
-import org.testng.annotations.Test;
-
-import java.lang.reflect.Field;
-
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
+import java.lang.reflect.Field;
+import org.testng.annotations.Test;
+
/**
+ * Unit-test creation of a logger via factory, assuming not default binding.
+ *
* @author evitaliy
* @since 14/09/2016.
*/
@@ -71,6 +72,6 @@ public class LoggerFactoryTest {
logger.info("");
logger.debug("");
logger.audit(null);
- logger.metrics("");
+ logger.metrics(MetricsData.builder().build());
}
}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/MetricsDataTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/MetricsDataTest.java
new file mode 100644
index 0000000000..a3c8b1039a
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/MetricsDataTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.openecomp.sdc.logging.api;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+import org.testng.annotations.Test;
+
+/**
+ * Unit-testing metrics builder and structure.
+ *
+ * @author evitaliy
+ * @since 04 Mar 18
+ */
+public class MetricsDataTest {
+
+ @Test
+ public void allMetricsPropertiesReadWhenPopulated() {
+
+ final long start = System.currentTimeMillis();
+ final long end = start + 1000;
+ final String responseCode = "Metrics-Response-Code";
+ final String responseDescription = "Metrics-Response-Description";
+ final String ipAddress = "10.56.20.72";
+ final String targetEntity = "Metrics-Target-Entity";
+ final String targetVirtualEntity = "Metrics-Target-Virtual-Entity";
+
+ MetricsData data = MetricsData.builder().startTime(start).endTime(end).statusCode(StatusCode.COMPLETE)
+ .responseCode(responseCode).responseDescription(responseDescription)
+ .clientIpAddress(ipAddress).targetEntity(targetEntity)
+ .targetVirtualEntity(targetVirtualEntity).build();
+
+ assertEquals(data.getClientIpAddress(), ipAddress);
+ assertEquals(data.getEndTime(), end);
+ assertEquals(data.getStartTime(), start);
+ assertEquals(data.getResponseCode(), responseCode);
+ assertEquals(data.getResponseDescription(), responseDescription);
+ assertEquals(data.getStatusCode(), StatusCode.COMPLETE);
+ assertEquals(data.getTargetEntity(), targetEntity);
+ assertEquals(data.getTargetVirtualEntity(), targetVirtualEntity);
+
+ }
+
+ @Test
+ public void allMetricsPropertiesEmptyWhenUnpopulated() {
+ MetricsData data = MetricsData.builder().build();
+ assertEquals(data.getStartTime(), 0);
+ assertEquals(data.getEndTime(), 0);
+ assertNull(data.getClientIpAddress());
+ assertNull(data.getResponseCode());
+ assertNull(data.getResponseDescription());
+ assertNull(data.getStatusCode());
+ assertNull(data.getTargetEntity());
+ assertNull(data.getTargetVirtualEntity());
+ }
+} \ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/pom.xml b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/pom.xml
index dbaef2ada6..e3fb79915e 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/pom.xml
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/pom.xml
@@ -19,12 +19,6 @@
<version>${project.version}</version>
</dependency>
<dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>${aspectj.version}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j-api.version}</version>
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/GlobalLoggingContext.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/GlobalLoggingContext.java
deleted file mode 100644
index a708ed6715..0000000000
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/GlobalLoggingContext.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright © 2016-2017 European Support Limited
- *
- * 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.
- */
-
-package org.openecomp.sdc.logging;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.prefs.BackingStoreException;
-import java.util.prefs.Preferences;
-
-/**
- * Collect information the is required for logging, but should not concern the business code of an application. For
- * example, host name and IP address.
- *
- * @author evitaliy
- * @since 04 Mar 2018
- */
-@SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace", "squid:S106", "squid:S1148"})
-public class GlobalLoggingContext {
-
- // should be cashed to avoid low-level call, but with a timeout to account for IP or FQDN changes
- private static final HostAddressCache HOST_ADDRESS_CACHE = new HostAddressCache();
-
- @SuppressWarnings("squid:S1075")
- private static final String INSTANCE_UUID_PREFERENCES_PATH = "/logging/instance/uuid";
-
- private static final String INSTANCE_ID;
-
- static {
- INSTANCE_ID = readInstanceId();
- }
-
- private GlobalLoggingContext() {
- // prevent instantiation
- }
-
- /**
- * A unique ID of the logging entity. Is useful to distinguish between different nodes of the same application. It
- * is assumed, that the node can be re-started, in which case the unique ID must be retained.
- *
- * @return unique logging entity ID
- */
- public static String getInstanceId() {
- return INSTANCE_ID;
- }
-
- /**
- * Local host address as returned by Java runtime. A value of host address will be cached for the interval specified
- * in {@link HostAddressCache#REFRESH_TIME}
- *
- * @return local host address, may be null if could not be read for some reason
- */
- public static InetAddress getHostAddress() {
- return HOST_ADDRESS_CACHE.get();
- }
-
- private static String readInstanceId() {
-
- try {
-
- // On Linux, by default this will be ~/.java/.userPrefs/prefs.xml
- final Preferences preferences = Preferences.userRoot();
- String existingId = preferences.get(INSTANCE_UUID_PREFERENCES_PATH, null);
- if (existingId != null) {
- return existingId;
- }
-
- String newId = UUID.randomUUID().toString();
- preferences.put(INSTANCE_UUID_PREFERENCES_PATH, newId);
- preferences.flush();
- return newId;
-
- } catch (BackingStoreException e) {
- e.printStackTrace();
- // don't fail if there's a problem to use the store for some unexpected reason
- return UUID.randomUUID().toString();
- }
- }
-
- private static class HostAddressCache {
-
- private static final long REFRESH_TIME = 60000L;
-
- private final AtomicLong lastUpdated = new AtomicLong(0L);
- private InetAddress hostAddress;
-
- InetAddress get() {
-
- long current = System.currentTimeMillis();
- if (current - lastUpdated.get() > REFRESH_TIME) {
-
- synchronized (this) {
-
- try {
- // set now to register the attempt even if failed
- lastUpdated.set(current);
- hostAddress = InetAddress.getLocalHost();
- } catch (UnknownHostException e) {
- e.printStackTrace(); // can't really use logging
- hostAddress = null;
- }
- }
- }
-
- return hostAddress;
- }
- }
-}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/aspects/MetricsAspect.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/aspects/MetricsAspect.java
deleted file mode 100644
index a99a97d0a6..0000000000
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/aspects/MetricsAspect.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright © 2016-2017 European Support Limited
- *
- * 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.
- */
-
-package org.openecomp.sdc.logging.aspects;
-
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.annotation.Around;
-import org.aspectj.lang.annotation.Aspect;
-import org.openecomp.sdc.logging.api.Logger;
-import org.openecomp.sdc.logging.api.LoggerFactory;
-import org.openecomp.sdc.logging.api.annotations.Metrics;
-
-/**
- * <p>Wraps around any method annotated with {@link Metrics} to measure and log its execution time
- * in milliseconds.</p>
- * <p>In order for the aspect to be used, AspectJ annotation processing must be tuned on and this
- * particular aspect enabled. Conversely, it can be disabled completely if the application does not
- * need to log metrics.</p>
- * <p>See, for example, <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html">
- * Aspect Oriented Programming with Spring</a>.</p>
- *
- * @author evitaliy
- * @see Metrics
- * @since 27/07/2016.
- */
-@Aspect
-public class MetricsAspect {
-
- private static final String MESSAGE_TEMPLATE = "'{}' took {} milliseconds";
-
- @Around("@annotation(org.openecomp.sdc.logging.api.annotations.Metrics)")
- public Object logExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
-
- final Logger logger = LoggerFactory.getLogger(pjp.getSignature().getDeclaringTypeName());
- // measure and log only if the logger for this class is enabled
- if (logger.isMetricsEnabled()) {
-
- final String method = pjp.getSignature().getName();
- final long start = System.currentTimeMillis();
-
- try {
- return pjp.proceed();
- } finally {
- logger.metrics(MESSAGE_TEMPLATE, method, System.currentTimeMillis() - start);
- }
-
- } else {
- return pjp.proceed();
- }
- }
-}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/context/HostAddress.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/context/HostAddress.java
new file mode 100644
index 0000000000..bcfef6ca01
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/context/HostAddress.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.openecomp.sdc.logging.context;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * Holds a reference to local host address as returned by Java runtime. A value of host address will be cached for the
+ * interval specified in the constructor or {@link #DEFAULT_REFRESH_INTERVAL}. The caching helps to avoid many low-level
+ * calls, but at the same time pick up any IP or FQDN changes. Although the underlying JDK implementation uses caching
+ * too, the refresh interval for logging may be much longer due to the nature of the use.
+ *
+ * @author evitaliy
+ * @since 26 Mar 2018
+ */
+@SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace", "squid:S106", "squid:S1148"})
+public class HostAddress {
+
+ private static final long DEFAULT_REFRESH_INTERVAL = 60000L; // 1 min
+
+ private final long interval;
+
+ private CacheEntry cachedAddress;
+
+ public HostAddress() {
+ this(DEFAULT_REFRESH_INTERVAL);
+ }
+
+ /**
+ * Creates a cache for host address with a custom refresh interval.
+ */
+ public HostAddress(long refreshInterval) {
+ this.interval = refreshInterval;
+ this.cachedAddress = new CacheEntry(System.currentTimeMillis(), read());
+ }
+
+ /**
+ * Returns an address (host name and IP address) of the local system.
+ *
+ * @return local host address or <code>null</code> if it could not be read for some reason
+ */
+ public synchronized InetAddress get() {
+
+ long current = System.currentTimeMillis();
+ if (current - cachedAddress.lastUpdated < interval) {
+ return cachedAddress.address;
+ }
+
+ InetAddress address = read();
+ cachedAddress = new CacheEntry(current, address);
+ return address;
+ }
+
+ private InetAddress read() {
+
+ try {
+ return InetAddress.getLocalHost();
+ } catch (UnknownHostException e) {
+ e.printStackTrace(); // can't really use logging
+ return null; // let register the attempt even if failed
+ }
+ }
+
+ private static class CacheEntry {
+
+ private final long lastUpdated;
+ private final InetAddress address;
+
+ private CacheEntry(long lastUpdated, InetAddress address) {
+ this.lastUpdated = lastUpdated;
+ this.address = address;
+ }
+ }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/context/InstanceId.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/context/InstanceId.java
new file mode 100644
index 0000000000..73544e1d9f
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/context/InstanceId.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.openecomp.sdc.logging.context;
+
+import java.util.UUID;
+
+/**
+ * Holds a unique ID of the logging entity. Is useful to distinguish between different nodes of the same application. If
+ * it can be assumed, that the node can be re-started, then the unique ID must be retained on the disk.
+ *
+ * @author evitaliy
+ * @since 04 Mar 2018
+ */
+@SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace", "squid:S106", "squid:S1148"})
+public class InstanceId {
+
+ private static final String INSTANCE_ID;
+
+ static {
+ // for some reason Java Preferences API
+ // https://docs.oracle.com/javase/8/docs/technotes/guides/preferences/overview.html
+ // didn't work in a Docker container, so for now just generate an ID every time
+ INSTANCE_ID = UUID.randomUUID().toString();
+ }
+
+ private InstanceId() {
+ // prevent instantiation
+ }
+
+ /**
+ * A unique ID of the logging entity.
+ *
+ * @return unique logging entity ID
+ */
+ public static String get() {
+ return INSTANCE_ID;
+ }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/AuditField.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/AuditField.java
new file mode 100644
index 0000000000..3e44a34722
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/AuditField.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.openecomp.sdc.logging.slf4j;
+
+/**
+ * MDC fields that represent audit data.
+ *
+ * @author evitaliy
+ * @since 25 Mar 2018
+ */
+enum AuditField implements MDCField {
+
+ BEGIN_TIMESTAMP("BeginTimestamp"),
+ END_TIMESTAMP("EndTimestamp"),
+ ELAPSED_TIME("ElapsedTime"),
+ STATUS_CODE("StatusCode"),
+ RESPONSE_CODE("ResponseCode"),
+ RESPONSE_DESCRIPTION("ResponseDescription"),
+ CLIENT_IP_ADDRESS("ClientIpAddress");
+
+ private final String key;
+
+ AuditField(String key) {
+ this.key = key;
+ }
+
+ public String asKey() {
+ return key;
+ }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/ContextField.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/ContextField.java
index 6aa689bf21..cce5f44863 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/ContextField.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/ContextField.java
@@ -17,12 +17,12 @@
package org.openecomp.sdc.logging.slf4j;
/**
- * MDC fields to work with - populate, clear, copy.
+ * MDC fields that represent context data.
*
* @author evitaliy
* @since 23 Mar 2018
*/
-enum ContextField {
+enum ContextField implements MDCField {
REQUEST_ID("RequestId"),
SERVICE_NAME("ServiceName"),
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/GlobalContextProvider.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/GlobalContextProvider.java
index a415e22c63..5f2963ec40 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/GlobalContextProvider.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/GlobalContextProvider.java
@@ -19,7 +19,8 @@ package org.openecomp.sdc.logging.slf4j;
import java.net.InetAddress;
import java.util.EnumMap;
import java.util.Map;
-import org.openecomp.sdc.logging.GlobalLoggingContext;
+import org.openecomp.sdc.logging.context.HostAddress;
+import org.openecomp.sdc.logging.context.InstanceId;
/**
* Maps global logging context to corresponding MDC fields.
@@ -29,13 +30,15 @@ import org.openecomp.sdc.logging.GlobalLoggingContext;
*/
class GlobalContextProvider implements ContextProvider {
+ private static final HostAddress HOST_ADDRESS_CACHE = new HostAddress();
+
@Override
public Map<ContextField, String> values() {
Map<ContextField, String> values = new EnumMap<>(ContextField.class);
- values.put(ContextField.INSTANCE_ID, GlobalLoggingContext.getInstanceId());
+ values.put(ContextField.INSTANCE_ID, InstanceId.get());
- InetAddress hostAddress = GlobalLoggingContext.getHostAddress();
+ InetAddress hostAddress = HOST_ADDRESS_CACHE.get();
if (hostAddress != null) {
values.put(ContextField.SERVER, hostAddress.getHostName());
values.put(ContextField.SERVER_IP_ADDRESS, hostAddress.getHostAddress());
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/annotations/Metrics.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCField.java
index 2be7eac01c..1096face85 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/annotations/Metrics.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCField.java
@@ -1,12 +1,12 @@
/*
- * Copyright © 2016-2017 European Support Limited
+ * Copyright © 2016-2018 European Support Limited
*
* 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.
@@ -14,14 +14,16 @@
* limitations under the License.
*/
-package org.openecomp.sdc.logging.api.annotations;
+package org.openecomp.sdc.logging.slf4j;
/**
- * Indicates a method whose execution time should be measured and logged as required for Open OPENECOMP metrics.
+ * Represents an MDC field. Maps a Java type to an MDC key that can be referred to in logger configuration.
*
* @author evitaliy
- * @since 27/07/2016.
+ * @since 25 Mar 2018
*/
+interface MDCField {
+
+ String asKey();
-public @interface Metrics {
}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MetricsField.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MetricsField.java
new file mode 100644
index 0000000000..fda0c8b683
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MetricsField.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.openecomp.sdc.logging.slf4j;
+
+/**
+ * DC fields that represent metrics data.
+ *
+ * @author evitaliy
+ * @since 26 Mar 2018
+ */
+public enum MetricsField implements MDCField {
+
+ BEGIN_TIMESTAMP("BeginTimestamp"),
+ END_TIMESTAMP("EndTimestamp"),
+ ELAPSED_TIME("ElapsedTime"),
+ STATUS_CODE("StatusCode"),
+ RESPONSE_CODE("ResponseCode"),
+ RESPONSE_DESCRIPTION("ResponseDescription"),
+ CLIENT_IP_ADDRESS("ClientIpAddress"),
+ TARGET_VIRTUAL_ENTITY("TargetVirtualEntity"),
+ TARGET_ENTITY("TargetEntity");
+
+ private final String key;
+
+ MetricsField(String key) {
+ this.key = key;
+ }
+
+ public String asKey() {
+ return key;
+ }
+
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapper.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapper.java
index 783dac4ed4..fbb5fbf1f2 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapper.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapper.java
@@ -16,22 +16,16 @@
package org.openecomp.sdc.logging.slf4j;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.BEGIN_TIMESTAMP;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.CLIENT_IP_ADDRESS;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.ELAPSED_TIME;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.END_TIMESTAMP;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.RESPONSE_CODE;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.RESPONSE_DESCRIPTION;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.STATUS_CODE;
-
-import java.text.Format;
import java.text.SimpleDateFormat;
import org.openecomp.sdc.logging.api.AuditData;
import org.openecomp.sdc.logging.api.Logger;
+import org.openecomp.sdc.logging.api.MetricsData;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
/**
+ * Delegates log calls to SLF4J API and MDC.
+ *
* @author evitaliy
* @since 08 Jan 18
*/
@@ -40,40 +34,17 @@ class SLF4JLoggerWrapper implements Logger {
//The specified format presents time in UTC formatted per ISO 8601, as required by ONAP logging guidelines
private static final String DATE_TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
- private static final String PREFIX = "";
-
- enum AuditField {
-
- BEGIN_TIMESTAMP(PREFIX + "BeginTimestamp"),
- END_TIMESTAMP(PREFIX + "EndTimestamp"),
- ELAPSED_TIME(PREFIX + "ElapsedTime"),
- STATUS_CODE(PREFIX + "StatusCode"),
- RESPONSE_CODE(PREFIX + "ResponseCode"),
- RESPONSE_DESCRIPTION(PREFIX + "ResponseDescription"),
- CLIENT_IP_ADDRESS(PREFIX + "ClientIpAddress");
-
- private final String key;
-
- AuditField(String key) {
- this.key = key;
- }
-
- public String asKey() {
- return key;
- }
- }
-
private final org.slf4j.Logger logger;
- SLF4JLoggerWrapper(org.slf4j.Logger delegate) {
- this.logger = delegate;
- }
-
// May cause http://www.slf4j.org/codes.html#loggerNameMismatch
SLF4JLoggerWrapper(Class<?> clazz) {
this(LoggerFactory.getLogger(clazz));
}
+ SLF4JLoggerWrapper(org.slf4j.Logger delegate) {
+ this.logger = delegate;
+ }
+
SLF4JLoggerWrapper(String className) {
this(LoggerFactory.getLogger(className));
}
@@ -90,27 +61,55 @@ class SLF4JLoggerWrapper implements Logger {
@Override
public void metrics(String msg) {
- logger.info(Markers.METRICS, msg);
+ // do nothing, left for backward compatibility
}
@Override
- public void metrics(String msg, Object arg) {
- logger.info(Markers.METRICS, msg, arg);
+ public void metrics(MetricsData data) {
+
+ if (data == null) {
+ return; // not going to fail because of null
+ }
+
+ try {
+ putMetricsOnMdc(data);
+ logger.info(Markers.METRICS, "");
+ } finally {
+ clearMetricsFromMdc();
+ }
}
- @Override
- public void metrics(String msg, Object arg1, Object arg2) {
- logger.info(Markers.METRICS, msg, arg1, arg2);
+ private void putMetricsOnMdc(MetricsData metrics) {
+
+ SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_TIME_PATTERN);
+ unsafePutOnMdc(MetricsField.BEGIN_TIMESTAMP, dateFormat.format(metrics.getStartTime()));
+ unsafePutOnMdc(MetricsField.END_TIMESTAMP, dateFormat.format(metrics.getEndTime()));
+ unsafePutOnMdc(MetricsField.ELAPSED_TIME, String.valueOf(metrics.getEndTime() - metrics.getStartTime()));
+ safePutOnMdc(MetricsField.RESPONSE_CODE, metrics.getResponseCode());
+ safePutOnMdc(MetricsField.RESPONSE_DESCRIPTION, metrics.getResponseDescription());
+ safePutOnMdc(MetricsField.CLIENT_IP_ADDRESS, metrics.getClientIpAddress());
+ safePutOnMdc(MetricsField.TARGET_ENTITY, metrics.getTargetEntity());
+ safePutOnMdc(MetricsField.TARGET_VIRTUAL_ENTITY, metrics.getTargetVirtualEntity());
+
+ if (metrics.getStatusCode() != null) {
+ unsafePutOnMdc(MetricsField.STATUS_CODE, metrics.getStatusCode().name());
+ }
}
- @Override
- public void metrics(String msg, Object... arguments) {
- logger.info(Markers.METRICS, msg, arguments);
+ private void clearMetricsFromMdc() {
+ for (MetricsField f : MetricsField.values()) {
+ MDC.remove(f.asKey());
+ }
}
- @Override
- public void metrics(String msg, Throwable t) {
- logger.info(Markers.METRICS, msg, t);
+ private static void unsafePutOnMdc(MDCField field, String value) {
+ MDC.put(field.asKey(), value);
+ }
+
+ private static void safePutOnMdc(MDCField field, String value) {
+ if (value != null) {
+ unsafePutOnMdc(field, value);
+ }
}
@Override
@@ -125,36 +124,33 @@ class SLF4JLoggerWrapper implements Logger {
return; // not failing if null
}
- putTimes(data);
- putIfNotNull(RESPONSE_CODE.key, data.getResponseCode());
- putIfNotNull(RESPONSE_DESCRIPTION.key, data.getResponseDescription());
- putIfNotNull(CLIENT_IP_ADDRESS.key, data.getClientIpAddress());
-
- if (data.getStatusCode() != null) {
- MDC.put(STATUS_CODE.key, data.getStatusCode().name());
- }
-
try {
+ putAuditOnMdc(data);
logger.info(Markers.AUDIT, "");
} finally {
- for (AuditField f : AuditField.values()) {
- MDC.remove(f.key);
- }
+ clearAuditFromMdc();
}
}
- private void putIfNotNull(String key, String value) {
- if (value != null) {
- MDC.put(key, value);
+ private void putAuditOnMdc(AuditData audit) {
+
+ SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_TIME_PATTERN);
+ unsafePutOnMdc(AuditField.BEGIN_TIMESTAMP, dateFormat.format(audit.getStartTime()));
+ unsafePutOnMdc(AuditField.END_TIMESTAMP, dateFormat.format(audit.getEndTime()));
+ unsafePutOnMdc(AuditField.ELAPSED_TIME, String.valueOf(audit.getEndTime() - audit.getStartTime()));
+ safePutOnMdc(AuditField.RESPONSE_CODE, audit.getResponseCode());
+ safePutOnMdc(AuditField.RESPONSE_DESCRIPTION, audit.getResponseDescription());
+ safePutOnMdc(AuditField.CLIENT_IP_ADDRESS, audit.getClientIpAddress());
+
+ if (audit.getStatusCode() != null) {
+ unsafePutOnMdc(AuditField.STATUS_CODE, audit.getStatusCode().name());
}
}
- private void putTimes(AuditData data) {
- // SimpleDateFormat is not thread-safe and cannot be a constant
- Format dateTimeFormat = new SimpleDateFormat(DATE_TIME_PATTERN);
- MDC.put(BEGIN_TIMESTAMP.key, dateTimeFormat.format(data.getStartTime()));
- MDC.put(END_TIMESTAMP.key, dateTimeFormat.format(data.getEndTime()));
- MDC.put(ELAPSED_TIME.key, String.valueOf(data.getEndTime() - data.getStartTime()));
+ private void clearAuditFromMdc() {
+ for (AuditField f : AuditField.values()) {
+ MDC.remove(f.asKey());
+ }
}
@Override
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/LogFileCreationTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/LogFileCreationTest.java
deleted file mode 100644
index 14dab13c9e..0000000000
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/LogFileCreationTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright © 2016-2018 European Support Limited
- *
- * 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.
- */
-
-package org.openecomp.sdc.logging;
-
-import org.openecomp.sdc.logging.api.AuditData;
-import org.openecomp.sdc.logging.api.Logger;
-import org.openecomp.sdc.logging.api.LoggerFactory;
-import org.testng.annotations.Test;
-
-/**
- * This is only for manual testing to make sure that a log file is created as expected.
- * To run change {@link #ENABLED} to 'true'
- *
- * @author evitaliy
- * @since 13/09/2016.
- */
-public class LogFileCreationTest {
-
- private static final boolean ENABLED = false; // for manual testing change to 'true'
-
- private static final Logger LOGGER = LoggerFactory.getLogger(LogFileCreationTest.class);
-
- @Test(enabled = ENABLED)
- public void testMetrics() {
- LOGGER.metrics("This is metrics");
- }
-
- @Test(enabled = ENABLED)
- public void testAudit() {
- LOGGER.audit(AuditData.builder().build());
- }
-
- @Test(enabled = ENABLED)
- public void testDebug() {
- LOGGER.debug("This is debug");
- }
-
- @Test(enabled = ENABLED)
- public void testInfo() {
- LOGGER.info("This is info");
- }
-
- @Test(enabled = ENABLED)
- public void testWarn() {
- LOGGER.warn("This is warning");
- }
-
- @Test(enabled = ENABLED)
- public void testError() {
- LOGGER.error("This is error");
- }
-}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/aspects/MetricsAspectTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/aspects/MetricsAspectTest.java
deleted file mode 100644
index e4cd37995a..0000000000
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/aspects/MetricsAspectTest.java
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Copyright © 2016-2018 European Support Limited
- *
- * 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.
- */
-
-package org.openecomp.sdc.logging.aspects;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Predicate;
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.Signature;
-import org.aspectj.lang.reflect.SourceLocation;
-import org.aspectj.runtime.internal.AroundClosure;
-import org.easymock.EasyMock;
-import org.openecomp.sdc.logging.api.AuditData;
-import org.openecomp.sdc.logging.api.Logger;
-import org.openecomp.sdc.logging.api.LoggerFactory;
-import org.powermock.api.easymock.PowerMock;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.testng.PowerMockTestCase;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-/**
- * Unit-tests metrics aspect (AOP) behavior.
- *
- * @author evitaliy
- * @since 17 Aug 2016
- */
-@PrepareForTest(LoggerFactory.class)
-public class MetricsAspectTest extends PowerMockTestCase {
-
- private static final Object OBJ_TO_RETURN = new Object();
- private static final String EXPECTED_MESSAGE = "'{}' took {} milliseconds";
-
- @Test
- public void testLogExecutionTime() throws Throwable {
-
- String className = UUID.randomUUID().toString();
- String methodName = UUID.randomUUID().toString();
-
- TestLogger logger = initLogging(className, true);
-
- MetricsAspect aspect = new MetricsAspect();
- MockProceedingJoinPoint pjp = new MockProceedingJoinPoint(className, methodName);
- Object returned = aspect.logExecutionTime(pjp);
-
- Assert.assertEquals(OBJ_TO_RETURN, returned);
- assertExecution(methodName, pjp, logger);
- }
-
- private TestLogger initLogging(String className, boolean enabled) {
- TestLogger logger = new TestLogger(enabled);
- PowerMock.mockStatic(LoggerFactory.class);
- EasyMock.expect(LoggerFactory.getLogger(className)).andReturn(logger);
- PowerMock.replay(LoggerFactory.class);
- return logger;
- }
-
- private void assertExecution(String methodName, MockProceedingJoinPoint pjp, TestLogger logger) {
-
- Assert.assertEquals(1, pjp.getCount());
- Assert.assertTrue(logger.contains(
- (event) -> (event != null) && (event.length == 3) && EXPECTED_MESSAGE.equals(event[0]) && methodName
- .equals(event[1]) && (event[2] instanceof Long)));
- }
-
- @Test
- public void testMetricsDisabled() throws Throwable {
-
- String className = UUID.randomUUID().toString();
- String methodName = UUID.randomUUID().toString();
-
- TestLogger logger = initLogging(className, false);
-
- MetricsAspect aspect = new MetricsAspect();
- MockProceedingJoinPoint pjp = new MockProceedingJoinPoint(className, methodName);
- Object returned = aspect.logExecutionTime(pjp);
-
- Assert.assertEquals(OBJ_TO_RETURN, returned);
- Assert.assertEquals(1, pjp.getCount());
- // return any event - must be empty
- Assert.assertFalse(logger.contains((event) -> true));
- }
-
- @Test(expectedExceptions = IllegalArgumentException.class)
- public void testThrowingError() throws Throwable {
-
- String className = UUID.randomUUID().toString();
- String methodName = UUID.randomUUID().toString();
-
- final TestLogger logger = initLogging(className, true);
-
- MetricsAspect aspect = new MetricsAspect();
- MockProceedingJoinPoint pjp = new MockProceedingJoinPointWithException(className, methodName);
-
- try {
- aspect.logExecutionTime(pjp);
- } finally {
- assertExecution(methodName, pjp, logger);
- }
- }
-
- private static class MockSignature implements Signature {
-
- private final String className;
- private final String methodName;
-
- private MockSignature(String className, String methodName) {
- this.className = className;
- this.methodName = methodName;
- }
-
- @Override
- public String toShortString() {
- return null;
- }
-
- @Override
- public String toLongString() {
- return null;
- }
-
- @Override
- public String getName() {
- return methodName;
- }
-
- @Override
- public int getModifiers() {
- return 0;
- }
-
- @Override
- public Class getDeclaringType() {
- return null;
- }
-
- @Override
- public String getDeclaringTypeName() {
- return className;
- }
- }
-
- private static class MockProceedingJoinPoint implements ProceedingJoinPoint {
-
- private final AtomicInteger count = new AtomicInteger(0);
- private final Signature signature;
-
- MockProceedingJoinPoint(String className, String methodName) {
- this.signature = new MockSignature(className, methodName);
- }
-
- int getCount() {
- return count.get();
- }
-
- @Override
- public void set$AroundClosure(AroundClosure aroundClosure) {
-
- }
-
- @Override
- public Object proceed() throws Throwable {
- count.incrementAndGet();
- return OBJ_TO_RETURN;
- }
-
- @Override
- public Object proceed(Object[] objects) {
- return null;
- }
-
- @Override
- public String toShortString() {
- return null;
- }
-
- @Override
- public String toLongString() {
- return null;
- }
-
- @Override
- public Object getThis() {
- return null;
- }
-
- @Override
- public Object getTarget() {
- return null;
- }
-
- @Override
- public Object[] getArgs() {
- return new Object[0];
- }
-
- @Override
- public Signature getSignature() {
- return this.signature;
- }
-
- @Override
- public SourceLocation getSourceLocation() {
- return null;
- }
-
- @Override
- public String getKind() {
- return null;
- }
-
- @Override
- public StaticPart getStaticPart() {
- return null;
- }
- }
-
- private static class MockProceedingJoinPointWithException extends MockProceedingJoinPoint {
-
- MockProceedingJoinPointWithException(String className, String methodName) {
- super(className, methodName);
- }
-
- @Override
- public Object proceed() throws Throwable {
- super.proceed();
- throw new IllegalArgumentException();
- }
- }
-
- private class TestLogger implements Logger {
-
- private final boolean enabled;
- private final List<Object[]> events = Collections.synchronizedList(new ArrayList<>(10));
-
- TestLogger(boolean enabled) {
- this.enabled = enabled;
- }
-
- @Override
- public String getName() {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public boolean isMetricsEnabled() {
- return this.enabled;
- }
-
- @Override
- public void metrics(String var1) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void metrics(String var1, Object var2) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void metrics(String var1, Object var2, Object var3) {
-
- if (this.enabled) {
- events.add(new Object[] {var1, var2, var3});
- }
- }
-
- @Override
- public void metrics(String var1, Object... var2) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void metrics(String var1, Throwable throwable) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public boolean isAuditEnabled() {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void audit(AuditData var1) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public boolean isDebugEnabled() {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void debug(String var1) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void debug(String var1, Object var2) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void debug(String var1, Object var2, Object var3) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void debug(String var1, Object... var2) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void debug(String var1, Throwable throwable) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public boolean isInfoEnabled() {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void info(String var1) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void info(String var1, Object var2) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void info(String var1, Object var2, Object var3) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void info(String var1, Object... var2) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void info(String var1, Throwable throwable) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public boolean isWarnEnabled() {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void warn(String var1) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void warn(String var1, Object var2) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void warn(String var1, Object... var2) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void warn(String var1, Object var2, Object var3) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void warn(String var1, Throwable throwable) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public boolean isErrorEnabled() {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void error(String var1) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void error(String var1, Object var2) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void error(String var1, Object var2, Object var3) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void error(String var1, Object... var2) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void error(String var1, Throwable throwable) {
- throw new RuntimeException("Not implemented");
- }
-
- boolean contains(Predicate<Object[]> predicate) {
- return events.stream().anyMatch(predicate);
- }
- }
-}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/context/HostAddressTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/context/HostAddressTest.java
new file mode 100644
index 0000000000..319bf19dcc
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/context/HostAddressTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.openecomp.sdc.logging.context;
+
+import static org.testng.Assert.assertNotNull;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import org.easymock.EasyMock;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockTestCase;
+import org.testng.annotations.Test;
+
+/**
+ * Retrieval and caching of host address.
+ *
+ * @author evitaliy
+ * @since 28 Mar 2018
+ */
+@PrepareForTest(InetAddress.class)
+public class HostAddressTest extends PowerMockTestCase {
+
+ @Test
+ public void hostAddressIsAlwaysPopulated() {
+ assertNotNull(new HostAddress().get());
+ }
+
+ @Test
+ public void cachedAddressRemainsTheSameWhenGotWithingRefreshInterval() throws UnknownHostException {
+ mockInetAddress(1);
+ HostAddress addressCache = new HostAddress(1000);
+ addressCache.get();
+ addressCache.get();
+ }
+
+ @Test
+ public void cachedAddressReplacedWhenGotAfterRefreshInterval() throws UnknownHostException {
+ mockInetAddress(2);
+ HostAddress addressCache = new HostAddress(-1);
+ addressCache.get();
+ addressCache.get();
+ }
+
+ private void mockInetAddress(int times) throws UnknownHostException {
+ InetAddress inetAddress = EasyMock.mock(InetAddress.class);
+ EasyMock.replay(inetAddress);
+ PowerMock.mockStatic(InetAddress.class);
+ //noinspection ResultOfMethodCallIgnored
+ InetAddress.getLocalHost();
+ PowerMock.expectLastCall().andReturn(inetAddress).times(times);
+ PowerMock.replay(InetAddress.class);
+ }
+} \ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/context/InstanceIdTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/context/InstanceIdTest.java
new file mode 100644
index 0000000000..984cb3bade
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/context/InstanceIdTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.openecomp.sdc.logging.context;
+
+import static org.testng.Assert.assertNotNull;
+
+import org.testng.annotations.Test;
+
+/**
+ * Retrieval of instance ID.
+ *
+ * @author evitaliy
+ * @since 28 Mar 2018
+ */
+public class InstanceIdTest {
+
+ @Test
+ public void makeSureInstanceIdNotNull() {
+ assertNotNull(InstanceId.get());
+ }
+
+} \ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapperTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapperTest.java
index 2c5233f9c9..f4a29efe8b 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapperTest.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapperTest.java
@@ -16,13 +16,6 @@
package org.openecomp.sdc.logging.slf4j;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.BEGIN_TIMESTAMP;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.CLIENT_IP_ADDRESS;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.ELAPSED_TIME;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.END_TIMESTAMP;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.RESPONSE_CODE;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.RESPONSE_DESCRIPTION;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.STATUS_CODE;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
@@ -33,9 +26,11 @@ import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Map;
import org.openecomp.sdc.logging.api.AuditData;
+import org.openecomp.sdc.logging.api.MetricsData;
import org.openecomp.sdc.logging.api.StatusCode;
import org.slf4j.Logger;
import org.slf4j.MDC;
+import org.slf4j.Marker;
import org.testng.annotations.Test;
/**
@@ -53,101 +48,209 @@ public class SLF4JLoggerWrapperTest {
}
@Test
- public void beginTimeAvailableWhenPassed() {
+ public void metricsDoesNotFailWhenInputNull() {
+ new SLF4JLoggerWrapper(this.getClass()).metrics((MetricsData) null);
+ }
+
+ @Test
+ public void auditBeginTimeAvailableWhenPassed() {
SpyLogger spy = createSpy();
long start = System.currentTimeMillis();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().startTime(start).build());
- assertNotNull(spy.mdc().get(BEGIN_TIMESTAMP.asKey()));
+ assertNotNull(spy.mdc().get(AuditField.BEGIN_TIMESTAMP.asKey()));
}
@Test
- public void entTimeAvailableWhenPassed() {
+ public void metricsBeginTimeAvailableWhenPassed() {
+ SpyLogger spy = createSpy();
+ long start = System.currentTimeMillis();
+ new SLF4JLoggerWrapper(spy).metrics(MetricsData.builder().startTime(start).build());
+ assertNotNull(spy.mdc().get(MetricsField.BEGIN_TIMESTAMP.asKey()));
+ }
+
+ @Test
+ public void auditEndTimeAvailableWhenPassed() {
SpyLogger spy = createSpy();
long end = System.currentTimeMillis();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().endTime(end).build());
- assertNotNull(spy.mdc().get(END_TIMESTAMP.asKey()));
+ assertNotNull(spy.mdc().get(AuditField.END_TIMESTAMP.asKey()));
}
@Test
- public void elapsedTimeAvailableWhenPassed() {
+ public void metricsEndTimeAvailableWhenPassed() {
+ SpyLogger spy = createSpy();
+ long end = System.currentTimeMillis();
+ new SLF4JLoggerWrapper(spy).metrics(MetricsData.builder().endTime(end).build());
+ assertNotNull(spy.mdc().get(MetricsField.END_TIMESTAMP.asKey()));
+ }
+
+ @Test
+ public void auditElapsedTimeAvailableWhenPassed() {
SpyLogger spy = createSpy();
long start = System.currentTimeMillis();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder()
- .startTime(start).endTime(start).build());
- assertNotNull(spy.mdc().get(ELAPSED_TIME.asKey()));
+ .startTime(start).endTime(start + 777).build());
+ assertEquals("777", spy.mdc().get(AuditField.ELAPSED_TIME.asKey()));
+ }
+
+ @Test
+ public void metricsElapsedTimeAvailableWhenPassed() {
+ SpyLogger spy = createSpy();
+ long start = System.currentTimeMillis();
+ new SLF4JLoggerWrapper(spy).metrics(MetricsData.builder()
+ .startTime(start).endTime(start + 1024).build());
+ assertEquals("1024", spy.mdc().get(MetricsField.ELAPSED_TIME.asKey()));
}
@Test
- public void statusCodeAvailableWhenPassed() {
+ public void auditStatusCodeAvailableWhenPassed() {
SpyLogger spy = createSpy();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().statusCode(StatusCode.COMPLETE).build());
- assertEquals(spy.mdc().get(STATUS_CODE.asKey()), StatusCode.COMPLETE.name());
+ assertEquals(spy.mdc().get(AuditField.STATUS_CODE.asKey()), StatusCode.COMPLETE.name());
+ }
+
+ @Test
+ public void metricsStatusCodeAvailableWhenPassed() {
+ SpyLogger spy = createSpy();
+ new SLF4JLoggerWrapper(spy).metrics(MetricsData.builder().statusCode(StatusCode.COMPLETE).build());
+ assertEquals(spy.mdc().get(MetricsField.STATUS_CODE.asKey()), StatusCode.COMPLETE.name());
}
@Test
- public void statusCodeEmptyWhenNotPassed() {
+ public void auditStatusCodeEmptyWhenNotPassed() {
SpyLogger spy = createSpy();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().build());
- assertNull(spy.mdc().get(STATUS_CODE.asKey()));
+ assertNull(spy.mdc().get(AuditField.STATUS_CODE.asKey()));
+ }
+
+ @Test
+ public void metricsStatusCodeEmptyWhenNotPassed() {
+ SpyLogger spy = createSpy();
+ new SLF4JLoggerWrapper(spy).metrics(MetricsData.builder().build());
+ assertNull(spy.mdc().get(MetricsField.STATUS_CODE.asKey()));
}
@Test
- public void responseCodeAvailableWhenPassed() {
- final String responseCode = "SpyResponse";
+ public void auditResponseCodeAvailableWhenPassed() {
+ final String responseCode = "AuditSpyResponse";
SpyLogger spy = createSpy();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().responseCode(responseCode).build());
- assertEquals(spy.mdc().get(RESPONSE_CODE.asKey()), responseCode);
+ assertEquals(spy.mdc().get(AuditField.RESPONSE_CODE.asKey()), responseCode);
}
@Test
- public void responseCodeEmptyWhenNotPassed() {
+ public void metricsResponseCodeAvailableWhenPassed() {
+ final String responseCode = "MetricsSpyResponse";
+ SpyLogger spy = createSpy();
+ new SLF4JLoggerWrapper(spy).metrics(MetricsData.builder().responseCode(responseCode).build());
+ assertEquals(spy.mdc().get(MetricsField.RESPONSE_CODE.asKey()), responseCode);
+ }
+
+ @Test
+ public void auditResponseCodeEmptyWhenNotPassed() {
SpyLogger spy = createSpy();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().build());
- assertNull(spy.mdc().get(RESPONSE_CODE.asKey()));
+ assertNull(spy.mdc().get(AuditField.RESPONSE_CODE.asKey()));
+ }
+
+ @Test
+ public void metricsResponseCodeEmptyWhenNotPassed() {
+ SpyLogger spy = createSpy();
+ new SLF4JLoggerWrapper(spy).metrics(MetricsData.builder().build());
+ assertNull(spy.mdc().get(MetricsField.RESPONSE_CODE.asKey()));
}
@Test
- public void responseDescriptionAvailableWhenPassed() {
- final String responseDescription = "SpyDescription";
+ public void auditResponseDescriptionAvailableWhenPassed() {
+ final String responseDescription = "AuditSpyDescription";
SpyLogger spy = createSpy();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().responseDescription(responseDescription).build());
- assertEquals(spy.mdc().get(RESPONSE_DESCRIPTION.asKey()), responseDescription);
+ assertEquals(spy.mdc().get(AuditField.RESPONSE_DESCRIPTION.asKey()), responseDescription);
}
@Test
- public void responseDescriptionEmptyWhenNotPassed() {
+ public void metricsResponseDescriptionAvailableWhenPassed() {
+ final String responseDescription = "MetricsSpyDescription";
+ SpyLogger spy = createSpy();
+ new SLF4JLoggerWrapper(spy).metrics(MetricsData.builder().responseDescription(responseDescription).build());
+ assertEquals(spy.mdc().get(MetricsField.RESPONSE_DESCRIPTION.asKey()), responseDescription);
+ }
+
+ @Test
+ public void auditResponseDescriptionEmptyWhenNotPassed() {
SpyLogger spy = createSpy();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().build());
- assertNull(spy.mdc().get(RESPONSE_DESCRIPTION.asKey()));
+ assertNull(spy.mdc().get(AuditField.RESPONSE_DESCRIPTION.asKey()));
}
@Test
- public void clientIpAddressAvailableWhenPassed() {
+ public void metricsResponseDescriptionEmptyWhenNotPassed() {
+ SpyLogger spy = createSpy();
+ new SLF4JLoggerWrapper(spy).metrics(MetricsData.builder().build());
+ assertNull(spy.mdc().get(MetricsField.RESPONSE_DESCRIPTION.asKey()));
+ }
+
+ @Test
+ public void auditClientIpAddressAvailableWhenPassed() {
final String ipAddress = "10.56.20.20";
SpyLogger spy = createSpy();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().clientIpAddress(ipAddress).build());
- assertEquals(spy.mdc().get(CLIENT_IP_ADDRESS.asKey()), ipAddress);
+ assertEquals(spy.mdc().get(AuditField.CLIENT_IP_ADDRESS.asKey()), ipAddress);
}
@Test
- public void clientIpAddressEmptyWhenNotPassed() {
+ public void metricsClientIpAddressAvailableWhenPassed() {
+ final String ipAddress = "10.56.20.22";
+ SpyLogger spy = createSpy();
+ new SLF4JLoggerWrapper(spy).metrics(MetricsData.builder().clientIpAddress(ipAddress).build());
+ assertEquals(spy.mdc().get(MetricsField.CLIENT_IP_ADDRESS.asKey()), ipAddress);
+ }
+
+ @Test
+ public void auditClientIpAddressEmptyWhenNotPassed() {
SpyLogger spy = createSpy();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().build());
- assertNull(spy.mdc().get(CLIENT_IP_ADDRESS.asKey()));
+ assertNull(spy.mdc().get(AuditField.CLIENT_IP_ADDRESS.asKey()));
}
@Test
- public void elapsedTimeEqualsDifferenceBetweenStartAndEnd() {
+ public void metricsClientIpAddressEmptyWhenNotPassed() {
SpyLogger spy = createSpy();
- final long diff = 1024;
- long start = System.currentTimeMillis();
- long end = start + diff;
- new SLF4JLoggerWrapper(spy).audit(AuditData.builder().startTime(start).endTime(end).build());
- assertEquals(spy.mdc().get(ELAPSED_TIME.asKey()), Long.toString(diff));
+ new SLF4JLoggerWrapper(spy).metrics(MetricsData.builder().build());
+ assertNull(spy.mdc().get(MetricsField.CLIENT_IP_ADDRESS.asKey()));
}
- interface SpyLogger extends Logger {
+ @Test
+ public void metricsTargetEntityAvailableWhenPassed() {
+ final String targetEntity = "MetricsTargetEntity";
+ SpyLogger spy = createSpy();
+ new SLF4JLoggerWrapper(spy).metrics(MetricsData.builder().targetEntity(targetEntity).build());
+ assertEquals(spy.mdc().get(MetricsField.TARGET_ENTITY.asKey()), targetEntity);
+ }
+ @Test
+ public void metricsTargetEntityEmptyWhenNotPassed() {
+ SpyLogger spy = createSpy();
+ new SLF4JLoggerWrapper(spy).metrics(MetricsData.builder().build());
+ assertNull(spy.mdc().get(MetricsField.TARGET_ENTITY.asKey()));
+ }
+
+ @Test
+ public void metricsTargetVirtualEntityAvailableWhenPassed() {
+ final String targetEntity = "MetricsTargetVirtualEntity";
+ SpyLogger spy = createSpy();
+ new SLF4JLoggerWrapper(spy).metrics(MetricsData.builder().targetVirtualEntity(targetEntity).build());
+ assertEquals(spy.mdc().get(MetricsField.TARGET_VIRTUAL_ENTITY.asKey()), targetEntity);
+ }
+
+ @Test
+ public void metricsTargetVirtualEntityEmptyWhenNotPassed() {
+ SpyLogger spy = createSpy();
+ new SLF4JLoggerWrapper(spy).metrics(MetricsData.builder().build());
+ assertNull(spy.mdc().get(MetricsField.TARGET_VIRTUAL_ENTITY.asKey()));
+ }
+
+ interface SpyLogger extends Logger {
Map<String, String> mdc();
}
@@ -168,16 +271,16 @@ public class SLF4JLoggerWrapperTest {
private static class SpyingInvocationHandler implements InvocationHandler {
- private Map<String, String> mdc;
+ private Map<String, String> lastMdc;
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
if (isReturnMdcMethod(method)) {
- return mdc;
+ return lastMdc;
}
- if (!isAuditMethod(method, args)) {
+ if (!isAuditMethod(method, args) && !isMetricsMethod(method, args)) {
throw new UnsupportedOperationException("Method " + method.getName() + " with arguments "
+ Arrays.toString(args) + " wasn't supposed to be called");
}
@@ -186,12 +289,20 @@ public class SLF4JLoggerWrapperTest {
return null;
}
+ private boolean isMetricsMethod(Method method, Object[] args) {
+ return isSpecialLogMethod(method, args, Markers.METRICS);
+ }
+
private boolean isAuditMethod(Method method, Object[] args) {
- return (method.getName().equals("info") && args.length > 0 && args[0].equals(Markers.AUDIT));
+ return isSpecialLogMethod(method, args, Markers.AUDIT);
+ }
+
+ private boolean isSpecialLogMethod(Method method, Object[] args, Marker marker) {
+ return method.getName().equals("info") && args.length > 0 && args[0].equals(marker);
}
private void storeEffectiveMdc() {
- mdc = MDC.getCopyOfContextMap();
+ lastMdc = MDC.getCopyOfContextMap();
}
private boolean isReturnMdcMethod(Method method) {