summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvempo <vitaliy.emporopulo@amdocs.com>2018-03-23 23:10:30 +0300
committervempo <vitaliy.emporopulo@amdocs.com>2018-03-23 23:10:30 +0300
commit6eceb46537df31756446760484ad1925a997205a (patch)
treee6a9675ca1c80d55cf5a884a5868491a7d648814
parent79550d5dc1c5bcb79123128aa37b381a368e38d9 (diff)
Logging refactoring and global context
Implemented global context (instance ID, host address). Refactored the logging context API for clarity and separation of concerns. Added unit tests. Fixed Javadoc. Change-Id: I6e29b7b3613aebf23112dc017490ad2828e0fb91 Issue-ID: SDC-772 Signed-off-by: vempo <vitaliy.emporopulo@amdocs.com>
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/AuditData.java34
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ContextData.java128
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggingContext.java29
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggingContextService.java12
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/ContextDataTest.java54
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggingContextTest.java18
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/pom.xml8
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/GlobalLoggingContext.java82
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/BaseMDCCopyingWrapper.java73
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/Context.java56
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/ContextField.java43
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/ContextProvider.java29
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/GlobalContextProvider.java46
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCCallableWrapper.java14
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCDelegate.java101
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCRunnableWrapper.java14
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/RequestContextProvider.java55
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggingServiceProvider.java48
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/BaseContextPropagationTest.java97
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/CallableContextPropagationTest.java65
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/ContextPropagationTestHelper.java50
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/ContextTest.java73
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/GlobalContextProviderTest.java41
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/LoggingContextTest.java110
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/RequestContextProviderTest.java62
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/RunnableContextPropagationTest.java83
26 files changed, 932 insertions, 493 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 fdef45a57f..ecf795b2d5 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
@@ -27,8 +27,9 @@ package org.openecomp.sdc.logging.api;
*/
public class AuditData {
- // A concrete implementation interface was chosen over an interface to enable to gracefully
- // add new fields without affecting client code
+ // 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.
private final long startTime;
private final long endTime;
@@ -37,7 +38,7 @@ public class AuditData {
private final String responseDescription;
private final String clientIpAddress;
- AuditData(final AuditDataBuilder builder) {
+ private AuditData(final AuditDataBuilder builder) {
this.startTime = builder.startTime;
this.endTime = builder.endTime;
this.statusCode = builder.statusCode;
@@ -47,7 +48,7 @@ public class AuditData {
}
/**
- * Begin timestamp of an API invocation
+ * Begin timestamp of an API invocation.
*
* @return timestamp
*/
@@ -56,7 +57,7 @@ public class AuditData {
}
/**
- * End timestamp of an API invocation
+ * End timestamp of an API invocation.
*
* @return timestamp
*/
@@ -65,7 +66,7 @@ public class AuditData {
}
/**
- * Result status of an API invocation
+ * Result status of an API invocation.
*
* @return protocol and application agnostic status code
*/
@@ -74,7 +75,7 @@ public class AuditData {
}
/**
- * Application/protocol specific response status of an API invocation
+ * Application/protocol specific response status of an API invocation.
*
* @return response code
*/
@@ -83,7 +84,7 @@ public class AuditData {
}
/**
- * Application/protocol specific response in a human-friendly way
+ * Application/protocol specific response in a human-friendly way.
*
* @return human-friendly response description
*/
@@ -92,7 +93,7 @@ public class AuditData {
}
/**
- * IP address of the invoking client when available
+ * IP address of the invoking client when available.
*
* @return IP address
*/
@@ -102,15 +103,18 @@ public class AuditData {
@Override
public String toString() {
- return "AuditData{startTime=" + startTime + ", endTime=" + endTime + ", statusCode=" + statusCode +
- ", responseCode='" + responseCode + ", responseDescription=" + responseDescription + ", clientIpAddress="
- + clientIpAddress + '}';
+ return "AuditData{startTime=" + startTime + ", endTime=" + endTime + ", statusCode=" + statusCode
+ + ", responseCode=" + responseCode + ", responseDescription=" + responseDescription
+ + ", clientIpAddress=" + clientIpAddress + '}';
}
public static AuditDataBuilder builder() {
return new AuditDataBuilder();
}
+ /**
+ * Fluent API for building audit data.
+ */
public static class AuditDataBuilder {
private long startTime;
@@ -123,7 +127,7 @@ public class AuditData {
AuditDataBuilder() { /* package-private default constructor to hide the public one */ }
/**
- * Begin timestamp of an activity being audited
+ * Begin timestamp of an activity being audited.
*
* @param startTime local timestamp, usually received from {@link System#currentTimeMillis()}
* @return this builder for fluent API
@@ -134,7 +138,7 @@ public class AuditData {
}
/**
- * End timestamp of an activity being audited
+ * End timestamp of an activity being audited.
*
* @param endTime local timestamp, usually received from {@link System#currentTimeMillis()}
* @return this builder for fluent API
@@ -191,7 +195,7 @@ public class AuditData {
}
/**
- * Create an instance of {@link AuditData}
+ * Create an instance of {@link AuditData}.
*
* @return a populated instance of audit data
*/
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
new file mode 100644
index 0000000000..ea777d5907
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ContextData.java
@@ -0,0 +1,128 @@
+/*
+ * 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 logging context data. This includes only data known to an application, and not otherwise
+ * available to the logging framework.
+ *
+ * @author evitaliy
+ * @since Mar 22, 2018
+ */
+public class ContextData {
+
+ private final String requestId;
+ private final String serviceName;
+ private final String partnerName;
+
+ private ContextData(final ContextDataBuilder builder) {
+ this.requestId = builder.requestId;
+ this.serviceName = builder.serviceName;
+ this.partnerName = builder.partnerName;
+ }
+
+ /**
+ * Uniques request ID received from a calling peer, or created.
+ *
+ * @return unique identifier of a request
+ */
+ public String getRequestId() {
+ return requestId;
+ }
+
+ /**
+ * Service, in the context of which logs will be written.
+ *
+ * @return a string that identifies an exposed service
+ */
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ /**
+ * Identifies a peer (if any).
+ *
+ * @return identification of a calling partner
+ */
+ public String getPartnerName() {
+ return partnerName;
+ }
+
+ @Override
+ public String toString() {
+ return "ContextData{responseCode=" + requestId + ", responseDescription=" + serviceName
+ + ", clientIpAddress=" + partnerName + '}';
+ }
+
+ public static ContextDataBuilder builder() {
+ return new ContextDataBuilder();
+ }
+
+ /**
+ * Fluent API for building context data.
+ */
+ public static class ContextDataBuilder {
+
+ private String requestId;
+ private String serviceName;
+ private String partnerName;
+
+ ContextDataBuilder() { /* package-private default constructor to hide the public one */ }
+
+ /**
+ * Unique request ID, most likely propagated via an HTTP header.
+ *
+ * @param requestId generated or propagated request ID.
+ * @return this builder for fluent API
+ */
+ public ContextDataBuilder requestId(final String requestId) {
+ this.requestId = requestId;
+ return this;
+ }
+
+ /**
+ * Name of a invoked API, by which it can be identified in the application.
+ *
+ * @param serviceName human-friendly service identifier
+ * @return this builder for fluent API
+ */
+ public ContextDataBuilder serviceName(final String serviceName) {
+ this.serviceName = serviceName;
+ return this;
+ }
+
+ /**
+ * Identifier of a peer calling a service {@link #serviceName(String)}).
+ *
+ * @param partnerName an string that is received from a calling peer and can identify it
+ * @return this builder for fluent API
+ */
+ public ContextDataBuilder partnerName(final String partnerName) {
+ this.partnerName = partnerName;
+ return this;
+ }
+
+ /**
+ * Create an instance of {@link ContextData}.
+ *
+ * @return a populated instance of audit data
+ */
+ public ContextData build() {
+ return new ContextData(this);
+ }
+ }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggingContext.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggingContext.java
index 879d9cf098..2dc4afdf58 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggingContext.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggingContext.java
@@ -16,10 +16,9 @@
package org.openecomp.sdc.logging.api;
-import org.openecomp.sdc.logging.spi.LoggingContextService;
-
import java.util.Objects;
import java.util.concurrent.Callable;
+import org.openecomp.sdc.logging.spi.LoggingContextService;
/**
* <p>Factory to hide a concrete, framework-specific implementation of diagnostic context.</p>
@@ -44,16 +43,8 @@ public class LoggingContext {
// prevent instantiation
}
- public static void putRequestId(String requestId) {
- SERVICE.putRequestId(requestId);
- }
-
- public static void putServiceName(String serviceName) {
- SERVICE.putServiceName(serviceName);
- }
-
- public static void putPartnerName(String partnerName) {
- SERVICE.putPartnerName(partnerName);
+ public static void put(ContextData contextData) {
+ SERVICE.put(contextData);
}
public static void clear() {
@@ -71,18 +62,8 @@ public class LoggingContext {
private static class NoOpLoggingContextService implements LoggingContextService {
@Override
- public void putRequestId(String requestId) {
- Objects.requireNonNull(requestId, "Request ID cannot be null");
- }
-
- @Override
- public void putServiceName(String serviceName) {
- Objects.requireNonNull(serviceName, "Service name cannot be null");
- }
-
- @Override
- public void putPartnerName(String partnerName) {
- Objects.requireNonNull(partnerName, "Partner name cannot be null");
+ public void put(ContextData contextData) {
+ Objects.requireNonNull(contextData, "Context data cannot be null");
}
@Override
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggingContextService.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggingContextService.java
index 07b93c1468..b90ce63982 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggingContextService.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggingContextService.java
@@ -17,6 +17,7 @@
package org.openecomp.sdc.logging.spi;
import java.util.concurrent.Callable;
+import org.openecomp.sdc.logging.api.ContextData;
/**
* Should be used to implement a framework-specific mechanism of managing a per-thread diagnostic context (for instance
@@ -33,14 +34,13 @@ import java.util.concurrent.Callable;
public interface LoggingContextService {
- void putRequestId(String requestId);
-
- void putServiceName(String serviceName);
-
- void putPartnerName(String partnerName);
+ /**
+ * Put logging data on the context.
+ */
+ void put(ContextData contextData);
/**
- * Clear logging thread context
+ * Clear logging thread context.
*/
void clear();
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/ContextDataTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/ContextDataTest.java
new file mode 100644
index 0000000000..8a173b452a
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/ContextDataTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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 context data builder.
+ *
+ * @author evitaliy
+ * @since 04 Mar 18
+ */
+public class ContextDataTest {
+
+ @Test
+ public void allPropertiesReadWhenPopulated() {
+
+ final String serviceName = "running-service";
+ final String partnerName = "remote-partner";
+ final String requestId = "123412341234";
+
+ ContextData data = ContextData.builder()
+ .serviceName(serviceName).partnerName(partnerName).requestId(requestId).build();
+
+ assertEquals(data.getRequestId(), requestId);
+ assertEquals(data.getServiceName(), serviceName);
+ assertEquals(data.getPartnerName(), partnerName);
+ }
+
+ @Test
+ public void allPropertiesEmptyWhenUnpopulated() {
+ ContextData data = ContextData.builder().build();
+ assertNull(data.getRequestId());
+ assertNull(data.getServiceName());
+ assertNull(data.getPartnerName());
+ }
+} \ 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/LoggingContextTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggingContextTest.java
index bfc53a3146..3e7bbe14e0 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggingContextTest.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggingContextTest.java
@@ -24,7 +24,9 @@ import java.util.concurrent.Callable;
import org.testng.annotations.Test;
/**
- * @author EVITALIY
+ * Unit-testing default context service implementation.
+ *
+ * @author evitaliy
* @since 08 Jan 18
*/
public class LoggingContextTest {
@@ -39,18 +41,8 @@ public class LoggingContextTest {
}
@Test(expectedExceptions = NullPointerException.class)
- public void throwNpeWhenPartnerNameIsNull() {
- LoggingContext.putPartnerName(null);
- }
-
- @Test(expectedExceptions = NullPointerException.class)
- public void throwNpeWhenServiceNameIsNull() {
- LoggingContext.putServiceName(null);
- }
-
- @Test(expectedExceptions = NullPointerException.class)
- public void throwNpeWhenRequestIdIsNull() {
- LoggingContext.putRequestId(null);
+ public void throwNpeWhenContextIsNull() {
+ LoggingContext.put(null);
}
@Test
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 2bbd0d2d01..14f54b0835 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
@@ -32,7 +32,11 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
- <version>${logback.version}</version>
+ <!--
+ Use latest version for proper testing of context propagation.
+ Will not affect the application because the scope is "provided".
+ -->
+ <version>1.2.3</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -41,7 +45,7 @@
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
-
+
<!-- for testing -->
<dependency>
<groupId>org.testng</groupId>
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
index 95dc52c85c..a708ed6715 100644
--- 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
@@ -16,13 +16,8 @@
package org.openecomp.sdc.logging;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
-import java.nio.charset.StandardCharsets;
-import java.util.Properties;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import java.util.prefs.BackingStoreException;
@@ -38,45 +33,20 @@ import java.util.prefs.Preferences;
@SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace", "squid:S106", "squid:S1148"})
public class GlobalLoggingContext {
- private static final String APPLICATION_ID_KEY = "ApplicationId";
-
- private static final String CONFIGURATION_RESOURCE = "META-INF/logging/logger.properties";
-
- @SuppressWarnings("squid:S1075")
- private static final String ID_PREFERENCES_PATH = "/logging/instance/uuid";
-
- private static final String APP_DISTINGUISHER_KEY = "app.distinguisher";
-
// 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 = new HostAddressCache();
-
- private static final String DISTINGUISHER;
+ private static final HostAddressCache HOST_ADDRESS_CACHE = new HostAddressCache();
- private static final String APPLICATION_ID;
+ @SuppressWarnings("squid:S1075")
+ private static final String INSTANCE_UUID_PREFERENCES_PATH = "/logging/instance/uuid";
private static final String INSTANCE_ID;
static {
- APPLICATION_ID = System.getProperty(APPLICATION_ID_KEY);
- DISTINGUISHER = readDistinguisher();
INSTANCE_ID = readInstanceId();
}
- private GlobalLoggingContext() { /* prevent instantiation */ }
-
- public static String getApplicationId() {
- return APPLICATION_ID;
- }
-
- /**
- * A distinguisher to allow separation of logs created by applications running with the same configuration, but
- * different class-loaders. For instance, when multiple web application are running in the same container and their
- * logger configuration is passed at the JVM level.
- *
- * @return application distinguisher defined in a properties file
- */
- public static String getDistinguisher() {
- return DISTINGUISHER;
+ private GlobalLoggingContext() {
+ // prevent instantiation
}
/**
@@ -96,25 +66,22 @@ public class GlobalLoggingContext {
* @return local host address, may be null if could not be read for some reason
*/
public static InetAddress getHostAddress() {
- return HOST_ADDRESS.get();
+ return HOST_ADDRESS_CACHE.get();
}
private static String readInstanceId() {
- String appId = System.getProperty(APPLICATION_ID_KEY);
- String key = ID_PREFERENCES_PATH + (appId == null ? "" : "/" + appId);
-
try {
- // By default, this will be ~/.java/.userPrefs/prefs.xml
+ // On Linux, by default this will be ~/.java/.userPrefs/prefs.xml
final Preferences preferences = Preferences.userRoot();
- String existingId = preferences.get(key, null);
+ String existingId = preferences.get(INSTANCE_UUID_PREFERENCES_PATH, null);
if (existingId != null) {
return existingId;
}
String newId = UUID.randomUUID().toString();
- preferences.put(key, newId);
+ preferences.put(INSTANCE_UUID_PREFERENCES_PATH, newId);
preferences.flush();
return newId;
@@ -125,35 +92,6 @@ public class GlobalLoggingContext {
}
}
- private static String readDistinguisher() {
-
- try {
- Properties properties = loadConfiguration();
- return properties.getProperty(APP_DISTINGUISHER_KEY, "");
- } catch (IOException e) {
- e.printStackTrace(); // can't write to a log
- return "";
- }
- }
-
- private static Properties loadConfiguration() throws IOException {
-
- Properties properties = new Properties();
-
- try (InputStream is = Thread.currentThread().getContextClassLoader()
- .getResourceAsStream(CONFIGURATION_RESOURCE)) {
-
- if (is == null) {
- return properties;
- }
-
- try (InputStreamReader reader = new InputStreamReader(is, StandardCharsets.UTF_8)) {
- properties.load(reader);
- return properties;
- }
- }
- }
-
private static class HostAddressCache {
private static final long REFRESH_TIME = 60000L;
@@ -161,7 +99,7 @@ public class GlobalLoggingContext {
private final AtomicLong lastUpdated = new AtomicLong(0L);
private InetAddress hostAddress;
- public InetAddress get() {
+ InetAddress get() {
long current = System.currentTimeMillis();
if (current - lastUpdated.get() > REFRESH_TIME) {
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/BaseMDCCopyingWrapper.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/BaseMDCCopyingWrapper.java
deleted file mode 100644
index d667ff769c..0000000000
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/BaseMDCCopyingWrapper.java
+++ /dev/null
@@ -1,73 +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.slf4j;
-
-import java.util.EnumMap;
-import java.util.Map;
-import org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField;
-import org.slf4j.MDC;
-
-/**
- * Because we don't know which information should be carried over from MDC, and which shouldn't, copy just the keys that
- * the logging service uses.
- *
- * @author evitaliy
- * @since 08 Jan 2018
- */
-abstract class BaseMDCCopyingWrapper {
-
- private final Map<ContextField, String> context;
-
- BaseMDCCopyingWrapper() {
- this.context = fromMdc();
- }
-
- final Map<ContextField, String> replace() {
- Map<ContextField, String> old = fromMdc();
- toMdc(this.context);
- return old;
- }
-
- final void revert(Map<ContextField, String> old) {
- toMdc(old);
- }
-
- private Map<ContextField, String> fromMdc() {
-
- Map<ContextField, String> copy = new EnumMap<>(ContextField.class);
- for (ContextField k : ContextField.values()) {
- String v = MDC.get(k.asKey());
- if (v != null) {
- copy.put(k, v);
- }
- }
-
- return copy;
- }
-
- private static void toMdc(Map<ContextField, String> context) {
-
- for (ContextField k : ContextField.values()) {
- String v = context.get(k);
- if (v != null) {
- MDC.put(k.asKey(), v);
- } else {
- MDC.remove(k.asKey());
- }
- }
- }
-}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/Context.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/Context.java
new file mode 100644
index 0000000000..25784fefcd
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/Context.java
@@ -0,0 +1,56 @@
+/*
+ * 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.slf4j;
+
+import java.util.Map;
+
+/**
+ * Does not store a state other than initial context values. Objects of this class may be reused by multiple threads,
+ * therefore they must be stateless to prevent inadvertent exchange of context values between threads.
+ *
+ * @author evitaliy
+ * @since 08 Jan 2018
+ */
+final class Context {
+
+ private final Map<ContextField, String> originalCtx;
+
+ Context() {
+ this.originalCtx = MDCDelegate.copy();
+ }
+
+ /**
+ * Pushes the initial context onto current thread, and returns the existing context. The result cannot be stored as
+ * local state (see the class comments), and must be kept in a local variable to work properly.
+ *
+ * @return previous context values
+ */
+ final Map<ContextField, String> replace() {
+ Map<ContextField, String> old = MDCDelegate.copy();
+ MDCDelegate.replace(this.originalCtx);
+ return old;
+ }
+
+ /**
+ * Pushes an old context onto current thread.
+ *
+ * @param old copy of the old context returned by {@link #replace()}
+ */
+ final void revert(Map<ContextField, String> old) {
+ MDCDelegate.replace(old);
+ }
+}
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
new file mode 100644
index 0000000000..6aa689bf21
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/ContextField.java
@@ -0,0 +1,43 @@
+/*
+ * 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 to work with - populate, clear, copy.
+ *
+ * @author evitaliy
+ * @since 23 Mar 2018
+ */
+enum ContextField {
+
+ REQUEST_ID("RequestId"),
+ SERVICE_NAME("ServiceName"),
+ PARTNER_NAME("PartnerName"),
+ INSTANCE_ID("InstanceId"),
+ SERVER("Server"),
+ SERVER_IP_ADDRESS("ServerIpAddress");
+
+ private final String key;
+
+ ContextField(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/ContextProvider.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/ContextProvider.java
new file mode 100644
index 0000000000..f9a7144b22
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/ContextProvider.java
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+import java.util.Map;
+
+/**
+ * Abstracts a source of MDC values.
+ *
+ * @author evitaliy
+ * @since 23 Mar 2018
+ */
+interface ContextProvider {
+ Map<ContextField, String> values();
+}
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
new file mode 100644
index 0000000000..a415e22c63
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/GlobalContextProvider.java
@@ -0,0 +1,46 @@
+/*
+ * 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;
+
+import java.net.InetAddress;
+import java.util.EnumMap;
+import java.util.Map;
+import org.openecomp.sdc.logging.GlobalLoggingContext;
+
+/**
+ * Maps global logging context to corresponding MDC fields.
+ *
+ * @author evitaliy
+ * @since 23 Mar 2018
+ */
+class GlobalContextProvider implements ContextProvider {
+
+ @Override
+ public Map<ContextField, String> values() {
+
+ Map<ContextField, String> values = new EnumMap<>(ContextField.class);
+ values.put(ContextField.INSTANCE_ID, GlobalLoggingContext.getInstanceId());
+
+ InetAddress hostAddress = GlobalLoggingContext.getHostAddress();
+ if (hostAddress != null) {
+ values.put(ContextField.SERVER, hostAddress.getHostName());
+ values.put(ContextField.SERVER_IP_ADDRESS, hostAddress.getHostAddress());
+ }
+
+ return values;
+ }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCCallableWrapper.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCCallableWrapper.java
index 07d0f935f7..84aa256d95 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCCallableWrapper.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCCallableWrapper.java
@@ -18,30 +18,32 @@ package org.openecomp.sdc.logging.slf4j;
import java.util.Map;
import java.util.concurrent.Callable;
-import org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField;
/**
- * @author EVITALIY
+ * Carries MDC values over to a Callable from the instantiating thread to the moment the callable will run.
+ *
+ * @author evitaliy
* @since 08 Jan 18
*/
-class MDCCallableWrapper<V> extends BaseMDCCopyingWrapper implements Callable<V> {
+class MDCCallableWrapper<V> implements Callable<V> {
+
+ private final Context context = new Context();
private final Callable<V> task;
MDCCallableWrapper(Callable<V> task) {
- super();
this.task = task;
}
@Override
public V call() throws Exception {
- Map<ContextField, String> oldContext = replace();
+ Map<ContextField, String> oldContext = context.replace();
try {
return task.call();
} finally {
- revert(oldContext);
+ context.revert(oldContext);
}
}
}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCDelegate.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCDelegate.java
new file mode 100644
index 0000000000..8d719a2da8
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCDelegate.java
@@ -0,0 +1,101 @@
+/*
+ * 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;
+
+import java.util.EnumMap;
+import java.util.Map;
+import org.slf4j.MDC;
+
+/**
+ * Because we don't know which information should be carried over from MDC, and which shouldn't, copy just the keys that
+ * the logging service uses.
+ *
+ * @author evitaliy
+ * @since 23 Mar 2018
+ */
+class MDCDelegate {
+
+ private MDCDelegate() {
+ // static methods only, prevent instantiation
+ }
+
+ /**
+ * Get a copy of logging MDC fields.
+ */
+ static Map<ContextField, String> copy() {
+
+ Map<ContextField, String> copy = new EnumMap<>(ContextField.class);
+ for (ContextField k : ContextField.values()) {
+ String v = MDC.get(k.asKey());
+ if (v != null) {
+ copy.put(k, v);
+ }
+ }
+
+ return copy;
+ }
+
+ /**
+ * Entirely replaces the logging MDC context with the content of the argument. Logging keys that are not present in
+ * the input map will be cleared from MDC.
+ */
+ static void replace(Map<ContextField, String> values) {
+
+ for (ContextField key : ContextField.values()) {
+ updateKey(key, values.get(key));
+ }
+ }
+
+ /**
+ * Push data by multiple data providers on MDC.
+ */
+ static void put(ContextProvider... dataProviders) {
+
+ clear();
+
+ for (ContextProvider provider : dataProviders) {
+ push(provider.values());
+ }
+ }
+
+ /**
+ * Updates the logging MDC context with the content of the argument. Logging keys that are not present in the input
+ * map will remain "as is", keys with null values will be cleared from MDC.
+ */
+ private static void push(Map<ContextField, String> values) {
+
+ for (Map.Entry<ContextField, String> entry : values.entrySet()) {
+ updateKey(entry.getKey(), entry.getValue());
+ }
+ }
+
+ private static void updateKey(ContextField key, String value) {
+
+ if (value != null) {
+ MDC.put(key.asKey(), value);
+ } else {
+ MDC.remove(key.asKey());
+ }
+ }
+
+ static void clear() {
+
+ for (ContextField field : ContextField.values()) {
+ MDC.remove(field.asKey());
+ }
+ }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCRunnableWrapper.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCRunnableWrapper.java
index e1b8f1e5c5..9d93246181 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCRunnableWrapper.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCRunnableWrapper.java
@@ -17,30 +17,32 @@
package org.openecomp.sdc.logging.slf4j;
import java.util.Map;
-import org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField;
/**
- * @author EVITALIY
+ * Carries MDC values over to a Runnable from the instantiating thread to the moment the callable will run.
+ *
+ * @author evitaliy
* @since 08 Jan 18
*/
-class MDCRunnableWrapper extends BaseMDCCopyingWrapper implements Runnable {
+class MDCRunnableWrapper implements Runnable {
+
+ private final Context context = new Context();
private final Runnable task;
MDCRunnableWrapper(Runnable task) {
- super();
this.task = task;
}
@Override
public void run() {
- Map<ContextField, String> oldContext = replace();
+ Map<ContextField, String> oldContext = context.replace();
try {
task.run();
} finally {
- revert(oldContext);
+ context.revert(oldContext);
}
}
}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/RequestContextProvider.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/RequestContextProvider.java
new file mode 100644
index 0000000000..d79771c1c5
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/RequestContextProvider.java
@@ -0,0 +1,55 @@
+/*
+ * 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;
+
+import java.util.EnumMap;
+import java.util.Map;
+import org.openecomp.sdc.logging.api.ContextData;
+
+/**
+ * Maps request data sent to the context service to corresponding MDC fields.
+ *
+ * @author evitaliy
+ * @since 23 Mar 2018
+ */
+class RequestContextProvider implements ContextProvider {
+
+ private final ContextData data;
+
+ RequestContextProvider(ContextData contextData) {
+ this.data = contextData;
+ }
+
+ @Override
+ public Map<ContextField, String> values() {
+
+ Map<ContextField, String> values = new EnumMap<>(ContextField.class);
+
+ putIfNotNull(values, ContextField.REQUEST_ID, data.getRequestId());
+ putIfNotNull(values, ContextField.SERVICE_NAME, data.getServiceName());
+ putIfNotNull(values, ContextField.PARTNER_NAME, data.getPartnerName());
+
+ return values;
+ }
+
+ private void putIfNotNull(Map<ContextField, String> values, ContextField field, String value) {
+
+ if (value != null) {
+ values.put(field, value);
+ }
+ }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggingServiceProvider.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggingServiceProvider.java
index 6f69aae1b6..1a5d6facc2 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggingServiceProvider.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggingServiceProvider.java
@@ -16,39 +16,20 @@
package org.openecomp.sdc.logging.slf4j;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField.PARTNER_NAME;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField.REQUEST_ID;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField.SERVICE_NAME;
-
import java.util.Objects;
import java.util.concurrent.Callable;
+import org.openecomp.sdc.logging.api.ContextData;
import org.openecomp.sdc.logging.api.Logger;
import org.openecomp.sdc.logging.spi.LoggingServiceProvider;
-import org.slf4j.MDC;
/**
+ * Uses SLF4J as backend for logging service.
+ *
* @author evitaliy
* @since 13 Sep 2016
*/
public class SLF4JLoggingServiceProvider implements LoggingServiceProvider {
- enum ContextField {
-
- REQUEST_ID("RequestId"),
- SERVICE_NAME("ServiceName"),
- PARTNER_NAME("PartnerName");
-
- private final String key;
-
- ContextField(String key) {
- this.key = key;
- }
-
- String asKey() {
- return key;
- }
- }
-
@Override
public Logger getLogger(String className) {
Objects.requireNonNull(className, "Name cannot be null");
@@ -62,29 +43,14 @@ public class SLF4JLoggingServiceProvider implements LoggingServiceProvider {
}
@Override
- public void putRequestId(String requestId) {
- put(REQUEST_ID.key, requestId);
- }
-
- @Override
- public void putServiceName(String serviceName) {
- put(SERVICE_NAME.key, serviceName);
- }
-
- @Override
- public void putPartnerName(String partnerName) {
- put(PARTNER_NAME.key, partnerName);
+ public void put(ContextData contextData) {
+ Objects.requireNonNull(contextData, "Context data cannot be null");
+ MDCDelegate.put(new RequestContextProvider(contextData), new GlobalContextProvider());
}
@Override
public void clear() {
- for (ContextField s : ContextField.values()) {
- MDC.remove(s.key);
- }
- }
-
- private void put(String key, String value) {
- MDC.put(key, Objects.requireNonNull(value, key));
+ MDCDelegate.clear();
}
@Override
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/BaseContextPropagationTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/BaseContextPropagationTest.java
deleted file mode 100644
index 52a794f937..0000000000
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/BaseContextPropagationTest.java
+++ /dev/null
@@ -1,97 +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.slf4j;
-
-import org.openecomp.sdc.logging.api.LoggingContext;
-import org.openecomp.sdc.logging.spi.LoggingContextService;
-import org.testng.annotations.DataProvider;
-
-import java.util.concurrent.Callable;
-
-/**
- * @author evitaliy
- * @since 08 Jan 18
- */
-public abstract class BaseContextPropagationTest {
-
- // Disable if an old version of logback implementation is being used.
- // Context propagation should be used when ctx is not propagated to child threads.
- // See https://jira.qos.ch/browse/LOGBACK-422 and https://jira.qos.ch/browse/LOGBACK-624
- static final boolean ENABLED = false;
-
- static final String PROVIDER = "context";
-
- static final String EXPECT_PROPAGATED_TO_CHILD = "Expected the data to be propagated to the child thread's context";
- static final String EXPECT_RETAINED_IN_CURRENT = "Expected the data to be retained in this thread";
- static final String EXPECT_REPLACED_WITH_STORED = "Expected context data to be replaced with stored data";
- static final String EXPECT_INNER_RUN = "Expected the inner thread to run";
- static final String EXPECT_OUTER_RUN = "Expected the outer thread to run";
- static final String EXPECT_NOT_COPIED = "Expected context data not to be copied to this thread";
- static final String EXPECT_RETAINED_IN_PARENT = "Expected context data to be retained in parent thread";
- static final String EXPECT_POPULATED = "Expected context data to be populated in this thread";
- static final String EXPECT_EMPTY = "Expected context data to be empty";
- static final String EXPECT_REMAIN_EMPTY = "Expected context data to remain empty in this thread";
- static final String EXPECT_REVERTED_ON_EXCEPTION = "Expected context data to be reverted even in case of exception";
- static final String EXPECT_EXCEPTION_FROM_INNER = "Expected the inner class to throw exception";
-
- @DataProvider(name = PROVIDER)
- public static Object[][] contextServices() {
- // try both directly call the implementation and get it via the binding
- return new Object[][]{
- {new SLF4JLoggingServiceProvider()},
- {new LoggingContextAdaptor()}
- };
- }
-
- private static class LoggingContextAdaptor implements LoggingContextService {
-
- @Override
- public void putRequestId(String requestId) {
- LoggingContext.putRequestId(requestId);
- }
-
- @Override
- public void putServiceName(String serviceName) {
- LoggingContext.putServiceName(serviceName);
- }
-
- @Override
- public void putPartnerName(String partnerName) {
- LoggingContext.putPartnerName(partnerName);
- }
-
- @Override
- public void clear() {
- LoggingContext.clear();
- }
-
- @Override
- public Runnable copyToRunnable(Runnable runnable) {
- return LoggingContext.copyToRunnable(runnable);
- }
-
- @Override
- public <V> Callable<V> copyToCallable(Callable<V> callable) {
- return LoggingContext.copyToCallable(callable);
- }
-
- @Override
- public String toString() {
- return this.getClass().getName();
- }
- }
-}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/CallableContextPropagationTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/CallableContextPropagationTest.java
index 58d52bfa0f..897a87193f 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/CallableContextPropagationTest.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/CallableContextPropagationTest.java
@@ -16,6 +16,19 @@
package org.openecomp.sdc.logging.slf4j;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_EMPTY;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_EXCEPTION_FROM_INNER;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_INNER_RUN;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_NOT_COPIED;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_OUTER_RUN;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_POPULATED;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_PROPAGATED_TO_CHILD;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_REMAIN_EMPTY;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_REPLACED_WITH_STORED;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_RETAINED_IN_CURRENT;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_RETAINED_IN_PARENT;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_REVERTED_ON_EXCEPTION;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.IS_SUITABLE_LOGBACK_VERSION;
import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.assertContextEmpty;
import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.assertContextFields;
import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.putUniqueValues;
@@ -28,24 +41,28 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
-import org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField;
import org.openecomp.sdc.logging.spi.LoggingContextService;
import org.testng.annotations.Test;
/**
+ * Tests propagation of logging fields to Callable via the logging service.
+ *
* @author evitaliy
* @since 08 Jan 18
*/
-public class CallableContextPropagationTest extends BaseContextPropagationTest {
+@SuppressWarnings("DefaultAnnotationParam") // see the comment to ENABLED
+public class CallableContextPropagationTest {
- @Test(enabled = ENABLED, dataProvider = PROVIDER)
- public void testContextPropagated(LoggingContextService ctx) throws Exception {
+ private final LoggingContextService ctxService = new SLF4JLoggingServiceProvider();
- Map<ContextField, String> values = putUniqueValues(ctx);
+ @Test(enabled = IS_SUITABLE_LOGBACK_VERSION)
+ public void testContextPropagated() throws Exception {
+
+ Map<ContextField, String> values = putUniqueValues();
AtomicBoolean complete = new AtomicBoolean(false);
// pass the callable to the context service first
- execute(ctx.copyToCallable(() -> {
+ execute(ctxService.copyToCallable(() -> {
assertContextFields(values, EXPECT_PROPAGATED_TO_CHILD);
complete.set(true);
return null;
@@ -55,14 +72,14 @@ public class CallableContextPropagationTest extends BaseContextPropagationTest {
assertTrue(complete.get(), EXPECT_INNER_RUN);
}
- @Test(enabled = ENABLED, dataProvider = PROVIDER)
- public void testContextReplacement(LoggingContextService ctx) throws Exception {
+ @Test(enabled = IS_SUITABLE_LOGBACK_VERSION)
+ public void testContextReplacement() throws Exception {
- Map<ContextField, String> innerValues = putUniqueValues(ctx);
+ Map<ContextField, String> innerValues = putUniqueValues();
AtomicBoolean innerComplete = new AtomicBoolean(false);
// should run with the context of main thread
- Callable inner = ctx.copyToCallable(() -> {
+ Callable inner = ctxService.copyToCallable(() -> {
assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
innerComplete.set(true);
return null;
@@ -71,7 +88,7 @@ public class CallableContextPropagationTest extends BaseContextPropagationTest {
// pushes its own context, but the inner must run with its own context
AtomicBoolean outerComplete = new AtomicBoolean(false);
execute(() -> {
- Map<ContextField, String> outerValues = putUniqueValues(ctx);
+ Map<ContextField, String> outerValues = putUniqueValues();
inner.call();
assertContextFields(outerValues, EXPECT_REPLACED_WITH_STORED);
outerComplete.set(true);
@@ -83,14 +100,14 @@ public class CallableContextPropagationTest extends BaseContextPropagationTest {
assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
}
- @Test(enabled = ENABLED, dataProvider = PROVIDER)
- public void testContextRemainsEmpty(LoggingContextService ctx) throws Exception {
+ @Test(enabled = IS_SUITABLE_LOGBACK_VERSION)
+ public void testContextRemainsEmpty() throws Exception {
- ctx.clear();
+ ctxService.clear();
assertContextEmpty(EXPECT_EMPTY);
final AtomicBoolean complete = new AtomicBoolean(false);
- execute(ctx.copyToCallable(() -> {
+ execute(ctxService.copyToCallable(() -> {
assertContextEmpty(EXPECT_EMPTY);
complete.set(true);
return null;
@@ -100,14 +117,14 @@ public class CallableContextPropagationTest extends BaseContextPropagationTest {
assertTrue(complete.get(), EXPECT_INNER_RUN);
}
- @Test(enabled = ENABLED, dataProvider = PROVIDER)
- public void testContextCleanedUp(LoggingContextService ctx) throws Exception {
+ @Test(enabled = IS_SUITABLE_LOGBACK_VERSION)
+ public void testContextCleanedUp() throws Exception {
- Map<ContextField, String> innerValues = putUniqueValues(ctx);
+ Map<ContextField, String> innerValues = putUniqueValues();
AtomicBoolean innerComplete = new AtomicBoolean(false);
// should run with the context of main thread
- Callable inner = ctx.copyToCallable((() -> {
+ Callable inner = ctxService.copyToCallable((() -> {
assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
innerComplete.set(true);
return null;
@@ -128,14 +145,14 @@ public class CallableContextPropagationTest extends BaseContextPropagationTest {
assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
}
- @Test(enabled = ENABLED, dataProvider = PROVIDER)
- public void testCleanupAfterError(LoggingContextService ctx) throws Exception {
+ @Test(enabled = IS_SUITABLE_LOGBACK_VERSION)
+ public void testCleanupAfterError() throws Exception {
- Map<ContextField, String> innerValues = putUniqueValues(ctx);
+ Map<ContextField, String> innerValues = putUniqueValues();
// should run with the context of main thread
AtomicBoolean innerComplete = new AtomicBoolean(false);
- Callable inner = ctx.copyToCallable(() -> {
+ Callable inner = ctxService.copyToCallable(() -> {
assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
innerComplete.set(true);
throw new IllegalArgumentException();
@@ -146,7 +163,7 @@ public class CallableContextPropagationTest extends BaseContextPropagationTest {
AtomicBoolean exceptionThrown = new AtomicBoolean(false);
execute(() -> {
- Map<ContextField, String> outerValues = putUniqueValues(ctx);
+ Map<ContextField, String> outerValues = putUniqueValues();
assertContextFields(outerValues, EXPECT_POPULATED);
try {
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/ContextPropagationTestHelper.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/ContextPropagationTestHelper.java
index 5112d37ac5..fccc6ba59a 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/ContextPropagationTestHelper.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/ContextPropagationTestHelper.java
@@ -17,39 +17,44 @@
package org.openecomp.sdc.logging.slf4j;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
-import java.util.Collections;
import java.util.EnumMap;
import java.util.Map;
import java.util.UUID;
-import org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField;
-import org.openecomp.sdc.logging.spi.LoggingContextService;
import org.slf4j.MDC;
-/**
- * @author evitaliy
- * @since 08 Mar 18
- */
class ContextPropagationTestHelper {
- private static final Map<ContextField, String> EMPTY_CONTEXT =
- Collections.unmodifiableMap(new EnumMap<>(ContextField.class));
+ // Set to "false" if an old version of logback implementation is being used.
+ // Explicit context propagation should be used when the context is not propagated to child threads.
+ // See https://jira.qos.ch/browse/LOGBACK-422 and https://jira.qos.ch/browse/LOGBACK-624
+ static final boolean IS_SUITABLE_LOGBACK_VERSION = true;
- static Map<ContextField, String> putUniqueValues(LoggingContextService ctx) {
+ static final String EXPECT_PROPAGATED_TO_CHILD = "Expected the data to be propagated to the child thread's context";
+ static final String EXPECT_RETAINED_IN_CURRENT = "Expected the data to be retained in this thread";
+ static final String EXPECT_REPLACED_WITH_STORED = "Expected context data to be replaced with stored data";
+ static final String EXPECT_INNER_RUN = "Expected the inner thread to run";
+ static final String EXPECT_OUTER_RUN = "Expected the outer thread to run";
+ static final String EXPECT_NOT_COPIED = "Expected context data not to be copied to this thread";
+ static final String EXPECT_RETAINED_IN_PARENT = "Expected context data to be retained in parent thread";
+ static final String EXPECT_POPULATED = "Expected context data to be populated in this thread";
+ static final String EXPECT_EMPTY = "Expected context data to be empty";
+ static final String EXPECT_REMAIN_EMPTY = "Expected context data to remain empty in this thread";
+ static final String EXPECT_REVERTED_ON_EXCEPTION = "Expected context data to be reverted even in case of exception";
+ static final String EXPECT_EXCEPTION_FROM_INNER = "Expected the inner class to throw exception";
- Map<ContextField, String> values = new EnumMap<>(ContextField.class);
+ static Map<ContextField, String> putUniqueValues() {
- String service = UUID.randomUUID().toString();
- ctx.putServiceName(service);
- values.put(ContextField.SERVICE_NAME, service);
+ Map<ContextField, String> values = new EnumMap<>(ContextField.class);
- String partner = UUID.randomUUID().toString();
- ctx.putPartnerName(partner);
- values.put(ContextField.PARTNER_NAME, partner);
+ String random = UUID.randomUUID().toString();
- String request = UUID.randomUUID().toString();
- ctx.putRequestId(request);
- values.put(ContextField.REQUEST_ID, request);
+ for (ContextField key : ContextField.values()) {
+ String value = random + "-" + key.name();
+ values.put(key, value);
+ MDC.put(key.asKey(), value);
+ }
return values;
}
@@ -62,6 +67,9 @@ class ContextPropagationTestHelper {
}
static void assertContextEmpty(String error) {
- assertContextFields(EMPTY_CONTEXT, error);
+
+ for (ContextField key : ContextField.values()) {
+ assertNull(MDC.get(key.asKey()), error);
+ }
}
}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/ContextTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/ContextTest.java
new file mode 100644
index 0000000000..bed5cec20e
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/ContextTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.EnumMap;
+import java.util.Map;
+import org.slf4j.MDC;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Unit-tests context replacement on MDC.
+ *
+ * @author evitaliy
+ * @since 23 Mar 2018
+ */
+public class ContextTest {
+
+ private static final ContextField FIELD = ContextField.SERVICE_NAME;
+ private static final String KEY = FIELD.asKey();
+ private static final String VALUE = "service-name-value";
+
+ @AfterMethod
+ public void clearMdc() {
+ MDC.clear();
+ }
+
+ @Test
+ public void mdcUpdatedWhenContextReplaced() {
+
+ MDC.put(KEY, VALUE);
+ Context context = new Context();
+ MDC.put(KEY, "modified-" + VALUE);
+
+ context.replace();
+ assertEquals(MDC.get(KEY), VALUE);
+ }
+
+ @Test
+ public void oldValueReturnedWhenContextReplaced() {
+
+ MDC.put(KEY, VALUE);
+ Map<ContextField, String> old = new Context().replace();
+ assertEquals(old.size(), 1);
+ assertEquals(old.get(FIELD), VALUE);
+ }
+
+ @Test
+ public void mdcUpdatedWhenContextReverted() {
+
+ Context context = new Context();
+ Map<ContextField, String> values = new EnumMap<>(ContextField.class);
+ values.put(FIELD, VALUE);
+ context.revert(values);
+ assertEquals(MDC.get(KEY), VALUE);
+ }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/GlobalContextProviderTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/GlobalContextProviderTest.java
new file mode 100644
index 0000000000..d1e4be38a6
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/GlobalContextProviderTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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;
+
+import static org.testng.Assert.assertNotNull;
+
+import java.util.Map;
+import org.testng.annotations.Test;
+
+/**
+ * Tests data supplied by the global logging context.
+ *
+ * @author evitaliy
+ * @since 23 Mar 2018
+ */
+
+public class GlobalContextProviderTest {
+
+ @Test
+ public void providedValuesPopulated() {
+ GlobalContextProvider provider = new GlobalContextProvider();
+ Map<ContextField, String> values = provider.values();
+ assertNotNull(values.get(ContextField.INSTANCE_ID));
+ assertNotNull(values.get(ContextField.SERVER));
+ assertNotNull(values.get(ContextField.SERVER_IP_ADDRESS));
+ }
+} \ 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/LoggingContextTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/LoggingContextTest.java
index 430d4d4c54..47386d4cf3 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/LoggingContextTest.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/LoggingContextTest.java
@@ -16,22 +16,30 @@
package org.openecomp.sdc.logging.slf4j;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+
+import java.util.UUID;
+import org.openecomp.sdc.logging.api.ContextData;
import org.openecomp.sdc.logging.api.LoggingContext;
-import org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField;
import org.slf4j.MDC;
+import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
-import java.util.UUID;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNull;
-
/**
+ * Unit-testing logging context service via its facade.
+ *
* @author evitaliy
* @since 12 Sep 2016
*/
public class LoggingContextTest {
+ @AfterMethod
+ public void clearMdc() {
+ MDC.clear();
+ }
+
@Test
public void returnMdcWrapperWhenToRunnableCalled() {
assertEquals(LoggingContext.copyToRunnable(() -> {}).getClass(), MDCRunnableWrapper.class);
@@ -57,18 +65,12 @@ public class LoggingContextTest {
String value = UUID.randomUUID().toString();
- try {
- LoggingContext.putPartnerName(value);
- LoggingContext.putServiceName(value);
- LoggingContext.putRequestId(value);
- LoggingContext.clear();
-
- for (ContextField field : ContextField.values()) {
- assertNull(MDC.get(field.asKey()));
- }
+ ContextData context = ContextData.builder().partnerName(value).requestId(value).serviceName(value).build();
+ LoggingContext.put(context);
+ LoggingContext.clear();
- } finally {
- MDC.clear();
+ for (ContextField field : ContextField.values()) {
+ assertNull(MDC.get(field.asKey()));
}
}
@@ -78,68 +80,64 @@ public class LoggingContextTest {
String randomValue = UUID.randomUUID().toString();
String randomKey = "Key-" + randomValue;
- try {
-
- MDC.put(randomKey, randomValue);
- LoggingContext.clear();
- assertEquals(MDC.get(randomKey), randomValue);
-
- } finally {
- MDC.clear();
- }
+ MDC.put(randomKey, randomValue);
+ LoggingContext.clear();
+ assertEquals(MDC.get(randomKey), randomValue);
}
@Test
public void contextHasServiceNameWhenPut() {
String random = UUID.randomUUID().toString();
-
- try {
- LoggingContext.putServiceName(random);
- assertEquals(random, MDC.get(ContextField.SERVICE_NAME.asKey()));
- } finally {
- MDC.clear();
- }
+ ContextData context = ContextData.builder().serviceName(random).build();
+ LoggingContext.put(context);
+ assertEquals(random, MDC.get(ContextField.SERVICE_NAME.asKey()));
}
@Test(expectedExceptions = NullPointerException.class)
- public void throwNpeWhenServiceNameNull() {
- LoggingContext.putServiceName(null);
+ public void throwNpeWhenContextDataNull() {
+ LoggingContext.put(null);
}
@Test
public void contextHasRequestIdWhenPut() {
String random = UUID.randomUUID().toString();
-
- try {
- LoggingContext.putRequestId(random);
- assertEquals(random, MDC.get(ContextField.REQUEST_ID.asKey()));
- } finally {
- MDC.clear();
- }
- }
-
- @Test(expectedExceptions = NullPointerException.class)
- public void throwNpeWhenRequestIdNull() {
- LoggingContext.putRequestId(null);
+ ContextData context = ContextData.builder().requestId(random).build();
+ LoggingContext.put(context);
+ assertEquals(random, MDC.get(ContextField.REQUEST_ID.asKey()));
}
@Test
public void contextHasPartnerNameWhenPut() {
String random = UUID.randomUUID().toString();
+ ContextData context = ContextData.builder().partnerName(random).build();
+ LoggingContext.put(context);
+ assertEquals(random, MDC.get(ContextField.PARTNER_NAME.asKey()));
+ }
- try {
- LoggingContext.putPartnerName(random);
- assertEquals(random, MDC.get(ContextField.PARTNER_NAME.asKey()));
- } finally {
- MDC.clear();
- }
+ @Test
+ public void contextHasServerHostWhenPopulated() {
+
+ ContextData context = ContextData.builder().build();
+ LoggingContext.put(context);
+ assertNotNull(MDC.get(ContextField.SERVER.asKey()));
}
- @Test(expectedExceptions = NullPointerException.class)
- public void throwNpeWhenPartnerNameNull() {
- LoggingContext.putPartnerName(null);
+ @Test
+ public void contextHasServerAddressWhenPopulated() {
+
+ ContextData context = ContextData.builder().build();
+ LoggingContext.put(context);
+ assertNotNull(MDC.get(ContextField.SERVER_IP_ADDRESS.asKey()));
+ }
+
+ @Test
+ public void contextHasInstanceIdWhenPopulated() {
+
+ ContextData context = ContextData.builder().build();
+ LoggingContext.put(context);
+ assertNotNull(MDC.get(ContextField.INSTANCE_ID.asKey()));
}
}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/RequestContextProviderTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/RequestContextProviderTest.java
new file mode 100644
index 0000000000..fa7926acef
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/RequestContextProviderTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.openecomp.sdc.logging.api.ContextData;
+import org.testng.annotations.Test;
+
+/**
+ * Unit-test retrieving values from client-provided request data.
+ *
+ * @author evitaliy
+ * @since 23 Mar 2018
+ */
+public class RequestContextProviderTest {
+
+ @Test
+ public void valuesEmptyWhenInputEmpty() {
+ RequestContextProvider provider = new RequestContextProvider(ContextData.builder().build());
+ assertTrue(provider.values().isEmpty());
+ }
+
+ @Test
+ public void serviceNameReturnedWhenSupplied() {
+ final String service = "supplied-service-name";
+ RequestContextProvider provider =
+ new RequestContextProvider(ContextData.builder().serviceName(service).build());
+ assertEquals(provider.values().get(ContextField.SERVICE_NAME), service);
+ }
+
+ @Test
+ public void partnerNameReturnedWhenSupplied() {
+ final String partner = "supplied-partner-name";
+ RequestContextProvider provider =
+ new RequestContextProvider(ContextData.builder().partnerName(partner).build());
+ assertEquals(provider.values().get(ContextField.PARTNER_NAME), partner);
+ }
+
+ @Test
+ public void requestIdReturnedWhenSupplied() {
+ final String request = "supplied-request-id";
+ RequestContextProvider provider =
+ new RequestContextProvider(ContextData.builder().requestId(request).build());
+ assertEquals(provider.values().get(ContextField.REQUEST_ID), request);
+ }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/RunnableContextPropagationTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/RunnableContextPropagationTest.java
index fcd1a56252..6f988c22d5 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/RunnableContextPropagationTest.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/RunnableContextPropagationTest.java
@@ -16,6 +16,19 @@
package org.openecomp.sdc.logging.slf4j;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_EMPTY;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_EXCEPTION_FROM_INNER;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_INNER_RUN;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_NOT_COPIED;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_OUTER_RUN;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_POPULATED;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_PROPAGATED_TO_CHILD;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_REMAIN_EMPTY;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_REPLACED_WITH_STORED;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_RETAINED_IN_CURRENT;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_RETAINED_IN_PARENT;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.EXPECT_REVERTED_ON_EXCEPTION;
+import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.IS_SUITABLE_LOGBACK_VERSION;
import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.assertContextEmpty;
import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.assertContextFields;
import static org.openecomp.sdc.logging.slf4j.ContextPropagationTestHelper.putUniqueValues;
@@ -23,27 +36,30 @@ import static org.testng.Assert.assertTrue;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
-import org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField;
import org.openecomp.sdc.logging.spi.LoggingContextService;
import org.testng.annotations.Test;
/**
+ * Unit-testing logging context propagation to Runnable.
+ *
* @author evitaliy
* @since 08 Jan 18
*/
-public class RunnableContextPropagationTest extends BaseContextPropagationTest {
+@SuppressWarnings("DefaultAnnotationParam")
+public class RunnableContextPropagationTest {
+
+ private final LoggingContextService ctxService = new SLF4JLoggingServiceProvider();
- @Test(enabled = ENABLED, dataProvider = PROVIDER)
- public void contextNotCopiedToChildThreadByDefault(LoggingContextService ctx)
- throws InterruptedException {
+ @Test(enabled = IS_SUITABLE_LOGBACK_VERSION)
+ public void contextNotCopiedToChildThreadByDefault() throws InterruptedException {
- Map<ContextField, String> values = putUniqueValues(ctx);
+ Map<ContextField, String> values = putUniqueValues();
AtomicBoolean complete = new AtomicBoolean(false);
// create thread right away without copying context
Thread thread = new Thread(() -> {
- assertContextEmpty("Data unexpectedly copied to a child thread. " +
- "Are you using an old version of SLF4J diagnostic context implementation (e.g. logback)?");
+ assertContextEmpty("Data unexpectedly copied to a child thread. "
+ + "Are you using an old version of SLF4J diagnostic context implementation (e.g. logback)?");
complete.set(true);
});
@@ -54,15 +70,14 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
assertTrue(complete.get(), EXPECT_INNER_RUN);
}
- @Test(enabled = ENABLED, dataProvider = PROVIDER)
- public void contextCopiedWhenToRunnableCalled(LoggingContextService ctx)
- throws InterruptedException {
+ @Test(enabled = IS_SUITABLE_LOGBACK_VERSION)
+ public void contextCopiedWhenToRunnableCalled() throws InterruptedException {
- Map<ContextField, String> values = putUniqueValues(ctx);
+ Map<ContextField, String> values = putUniqueValues();
AtomicBoolean complete = new AtomicBoolean(false);
// pass the runnable to the context service first
- Thread thread = new Thread(ctx.copyToRunnable(() -> {
+ Thread thread = new Thread(ctxService.copyToRunnable(() -> {
assertContextFields(values, EXPECT_PROPAGATED_TO_CHILD);
complete.set(true);
}));
@@ -74,15 +89,14 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
assertTrue(complete.get(), EXPECT_INNER_RUN);
}
- @Test(enabled = ENABLED, dataProvider = PROVIDER)
- public void copiedContextRetainedEvenWhenAnotherPushed(LoggingContextService ctx)
- throws InterruptedException {
+ @Test(enabled = IS_SUITABLE_LOGBACK_VERSION)
+ public void copiedContextRetainedEvenWhenAnotherPushed() throws InterruptedException {
- Map<ContextField, String> innerValues = putUniqueValues(ctx);
+ Map<ContextField, String> innerValues = putUniqueValues();
AtomicBoolean innerComplete = new AtomicBoolean(false);
// should run with the context of main thread
- Runnable inner = ctx.copyToRunnable(() -> {
+ Runnable inner = ctxService.copyToRunnable(() -> {
assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
innerComplete.set(true);
});
@@ -90,7 +104,7 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
// pushes its context, but the inner must run with its own context
AtomicBoolean outerComplete = new AtomicBoolean(false);
Thread outer = new Thread(() -> {
- Map<ContextField, String> outerValues = putUniqueValues(ctx);
+ Map<ContextField, String> outerValues = putUniqueValues();
inner.run();
assertContextFields(outerValues, EXPECT_REPLACED_WITH_STORED);
outerComplete.set(true);
@@ -104,15 +118,14 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
}
- @Test(enabled = ENABLED, dataProvider = PROVIDER)
- public void contextRemainsEmptyWhenParentWasEmpty(LoggingContextService ctx)
- throws InterruptedException {
+ @Test(enabled = IS_SUITABLE_LOGBACK_VERSION)
+ public void contextRemainsEmptyWhenParentWasEmpty() throws InterruptedException {
- ctx.clear();
+ ctxService.clear();
assertContextEmpty(EXPECT_EMPTY);
final AtomicBoolean complete = new AtomicBoolean(false);
- Runnable runnable = ctx.copyToRunnable(() -> {
+ Runnable runnable = ctxService.copyToRunnable(() -> {
assertContextEmpty(EXPECT_EMPTY);
complete.set(true);
});
@@ -125,14 +138,13 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
assertTrue(complete.get(), EXPECT_INNER_RUN);
}
- @Test(enabled = ENABLED, dataProvider = PROVIDER)
- public void childThreadCleanedUpAfterRunnableRuns(LoggingContextService ctx)
- throws Exception {
+ @Test(enabled = IS_SUITABLE_LOGBACK_VERSION)
+ public void childThreadCleanedUpAfterRunnableRuns() throws Exception {
- Map<ContextField, String> innerValues = putUniqueValues(ctx);
+ Map<ContextField, String> innerValues = putUniqueValues();
AtomicBoolean innerComplete = new AtomicBoolean(false);
// should run with the context of main thread
- Runnable inner = ctx.copyToRunnable(() -> {
+ Runnable inner = ctxService.copyToRunnable(() -> {
assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
innerComplete.set(true);
});
@@ -154,15 +166,14 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
}
- @Test(enabled = ENABLED, dataProvider = PROVIDER)
- public void childThreadCleanedUpAfterException(LoggingContextService ctx)
- throws Exception {
+ @Test(enabled = IS_SUITABLE_LOGBACK_VERSION)
+ public void childThreadCleanedUpAfterException() throws Exception {
- Map<ContextField, String> innerValues = putUniqueValues(ctx);
+ Map<ContextField, String> innerValues = putUniqueValues();
// should run with the context of main thread
AtomicBoolean innerComplete = new AtomicBoolean(false);
- Runnable inner = ctx.copyToRunnable(() -> {
+ Runnable inner = ctxService.copyToRunnable(() -> {
assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
innerComplete.set(true);
throw new IllegalArgumentException();
@@ -173,7 +184,7 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
AtomicBoolean exceptionThrown = new AtomicBoolean(false);
Thread outer = new Thread(() -> {
- Map<ContextField, String> outerValues = putUniqueValues(ctx);
+ Map<ContextField, String> outerValues = putUniqueValues();
assertContextFields(outerValues, EXPECT_POPULATED);
try {
@@ -194,6 +205,4 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
assertTrue(exceptionThrown.get(), EXPECT_EXCEPTION_FROM_INNER);
}
-
-
} \ No newline at end of file