summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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