aboutsummaryrefslogtreecommitdiffstats
path: root/openecomp-be
diff options
context:
space:
mode:
Diffstat (limited to 'openecomp-be')
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggingContext.java48
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggingContextService.java48
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggingContextTest.java37
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/GlobalLoggingContext.java185
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/BaseMDCCopyingWrapper.java52
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCCallableWrapper.java3
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCRunnableWrapper.java3
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapper.java60
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggingServiceProvider.java46
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/BaseContextPropagationTest.java27
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/CallableContextPropagationTest.java71
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/ContextPropagationTestHelper.java67
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/LoggingContextTest.java83
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/RunnableContextPropagationTest.java80
-rw-r--r--openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapperTest.java40
15 files changed, 571 insertions, 279 deletions
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 f827fec50f..879d9cf098 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
@@ -1,5 +1,5 @@
/*
- * Copyright © 2016-2017 European Support Limited
+ * Copyright © 2016-2018 European Support Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,37 +22,38 @@ import java.util.Objects;
import java.util.concurrent.Callable;
/**
- * <a>Factory to hide a concrete, framework-specific implementation of diagnostic context.</a>
- * <p>The service used by this factory must implement {@link LoggingContextService}. If no
- * implementation has been configured or could be instantiated, a <b>no-op context service</b> will be
- * used, and <b>no context</b> will be stored or propagated. No errors will be generated, so that the application can
- * still work (albeit without proper logging).</p>
+ * <p>Factory to hide a concrete, framework-specific implementation of diagnostic context.</p>
*
- * @author evitaliy
- * @since 07/01/2018.
+ * <p>The service used by this factory must implement {@link LoggingContextService}. If no implementation has been
+ * configured or could be instantiated, a <b>no-op context service</b> will be used, and <b>no context</b> will be
+ * stored or propagated. No errors will be generated, so that the application can still work (albeit without proper
+ * logging).</p>
*
+ * @author evitaliy
* @see ServiceBinder
* @see LoggingContextService
+ * @since 07 Jan 2018
*/
public class LoggingContext {
- private static final LoggingContextService SERVICE = ServiceBinder.getContextServiceBinding().orElse(
+ private static final LoggingContextService SERVICE =
+ ServiceBinder.getContextServiceBinding().orElse(
new NoOpLoggingContextService());
private LoggingContext() {
// prevent instantiation
}
- public static void put(String key, String value) {
- SERVICE.put(key, value);
+ public static void putRequestId(String requestId) {
+ SERVICE.putRequestId(requestId);
}
- public static String get(String key) {
- return SERVICE.get(key);
+ public static void putServiceName(String serviceName) {
+ SERVICE.putServiceName(serviceName);
}
- public static void remove(String key) {
- SERVICE.remove(key);
+ public static void putPartnerName(String partnerName) {
+ SERVICE.putPartnerName(partnerName);
}
public static void clear() {
@@ -69,24 +70,19 @@ public class LoggingContext {
private static class NoOpLoggingContextService implements LoggingContextService {
- private static final String KEY_CANNOT_BE_NULL = "Key cannot be null";
-
@Override
- public void put(String key, String value) {
- Objects.requireNonNull(key, KEY_CANNOT_BE_NULL);
- // no-op
+ public void putRequestId(String requestId) {
+ Objects.requireNonNull(requestId, "Request ID cannot be null");
}
@Override
- public String get(String key) {
- Objects.requireNonNull(key, KEY_CANNOT_BE_NULL);
- return null;
+ public void putServiceName(String serviceName) {
+ Objects.requireNonNull(serviceName, "Service name cannot be null");
}
@Override
- public void remove(String key) {
- Objects.requireNonNull(key, KEY_CANNOT_BE_NULL);
- // no-op
+ public void putPartnerName(String partnerName) {
+ Objects.requireNonNull(partnerName, "Partner name 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 7aed0fc7dc..07b93c1468 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
@@ -1,12 +1,12 @@
/*
- * Copyright © 2016-2017 European Support Limited
+ * Copyright © 2016-2018 European Support Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -19,37 +19,25 @@ package org.openecomp.sdc.logging.spi;
import java.util.concurrent.Callable;
/**
- * Should be used to implement a framework-specific mechanism of managing a per-thread diagnostic context
- * (for instance <a href="http://www.slf4j.org/manual.html#mdc">MDC</a>), and propagating it to child threads if needed.
- * Context propagation should be used when creating a child thread directly, or submitting tasks for potentially
- * postponed execution via an
- * <a href="http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html">Executor</a> (including any of
- * the
- * <a href="http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html">executor services</a>
- * and <a href="http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.html">ForkJoinPool</a>).
+ * Should be used to implement a framework-specific mechanism of managing a per-thread diagnostic context (for instance
+ * <a href="http://www.slf4j.org/manual.html#mdc">MDC</a>), and propagating it to child threads if needed. Context
+ * propagation should be used when creating a child thread directly, or submitting tasks for potentially postponed
+ * execution via an <a href="http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html">Executor</a>
+ * (including any of the <a href="http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html">
+ * executor services</a> and <a href="http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.html">
+ * ForkJoinPool</a>).
*
* @author evitaliy
- * @since 07/01/2018.
+ * @since 07 Jan 2018
*/
public interface LoggingContextService {
- /**
- * Allows to store a key-value pair on thread context
- */
- void put(String key, String value);
+ void putRequestId(String requestId);
- /**
- * Returns the value associated with a key stored on thread context
- *
- * @return value or <code>null</code> if the key does not exits
- */
- String get(String key);
+ void putServiceName(String serviceName);
- /**
- * Removes a particular key from thread context
- */
- void remove(String key);
+ void putPartnerName(String partnerName);
/**
* Clear logging thread context
@@ -57,14 +45,14 @@ public interface LoggingContextService {
void clear();
/**
- * Copies logging context of current thread onto a {@link Runnable}, so that the context is available
- * when this {@link Runnable} runs in another thread.
+ * Copies logging context of current thread onto a {@link Runnable}, so that the context is available when this
+ * {@link Runnable} runs in another thread.
*/
Runnable copyToRunnable(Runnable runnable);
/**
- * Copies logging context of current thread onto a {@link Callable}, so that the context is available
- * when this {@link Callable} runs in another thread
+ * Copies logging context of current thread onto a {@link Callable}, so that the context is available when this
+ * {@link Callable} runs in another thread
*/
<V> Callable<V> copyToCallable(Callable<V> callable);
}
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 79252cde0b..bfc53a3146 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
@@ -16,14 +16,12 @@
package org.openecomp.sdc.logging.api;
-import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
import java.lang.reflect.Field;
import java.util.concurrent.Callable;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
+import org.testng.annotations.Test;
/**
* @author EVITALIY
@@ -40,36 +38,19 @@ public class LoggingContextTest {
"org.openecomp.sdc.logging.api.LoggingContext$NoOpLoggingContextService");
}
- @Test
- public void putDoesNotHaveEffectWhenNoBinding() {
- final String key = "Key";
- LoggingContext.put(key, "Dummy");
- assertNull(LoggingContext.get(key));
- }
-
@Test(expectedExceptions = NullPointerException.class)
- public void throwNpeWhenPutWithKeyNull() {
- LoggingContext.put(null, "value");
- }
-
- @Test
- public void getAlwaysReturnsNull() {
- assertNull(LoggingContext.get("GetKey"));
+ public void throwNpeWhenPartnerNameIsNull() {
+ LoggingContext.putPartnerName(null);
}
@Test(expectedExceptions = NullPointerException.class)
- public void throwNpeWhenGetWithKeyNull() {
- LoggingContext.get(null);
- }
-
- @Test
- public void removeDoesNotFail() {
- LoggingContext.remove("RemoveKey");
+ public void throwNpeWhenServiceNameIsNull() {
+ LoggingContext.putServiceName(null);
}
@Test(expectedExceptions = NullPointerException.class)
- public void throwNpWhenRemoveWithKeyNull() {
- LoggingContext.remove(null);
+ public void throwNpeWhenRequestIdIsNull() {
+ LoggingContext.putRequestId(null);
}
@Test
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
new file mode 100644
index 0000000000..95dc52c85c
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/GlobalLoggingContext.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openecomp.sdc.logging;
+
+import java.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;
+import java.util.prefs.Preferences;
+
+/**
+ * Collect information the is required for logging, but should not concern the business code of an application. For
+ * example, host name and IP address.
+ *
+ * @author evitaliy
+ * @since 04 Mar 2018
+ */
+@SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace", "squid:S106", "squid:S1148"})
+public class GlobalLoggingContext {
+
+ 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 String APPLICATION_ID;
+
+ 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;
+ }
+
+ /**
+ * A unique ID of the logging entity. Is useful to distinguish between different nodes of the same application. It
+ * is assumed, that the node can be re-started, in which case the unique ID must be retained.
+ *
+ * @return unique logging entity ID
+ */
+ public static String getInstanceId() {
+ return INSTANCE_ID;
+ }
+
+ /**
+ * Local host address as returned by Java runtime. A value of host address will be cached for the interval specified
+ * in {@link HostAddressCache#REFRESH_TIME}
+ *
+ * @return local host address, may be null if could not be read for some reason
+ */
+ public static InetAddress getHostAddress() {
+ return HOST_ADDRESS.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
+ final Preferences preferences = Preferences.userRoot();
+ String existingId = preferences.get(key, null);
+ if (existingId != null) {
+ return existingId;
+ }
+
+ String newId = UUID.randomUUID().toString();
+ preferences.put(key, newId);
+ preferences.flush();
+ return newId;
+
+ } catch (BackingStoreException e) {
+ e.printStackTrace();
+ // don't fail if there's a problem to use the store for some unexpected reason
+ return UUID.randomUUID().toString();
+ }
+ }
+
+ private static 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;
+
+ private final AtomicLong lastUpdated = new AtomicLong(0L);
+ private InetAddress hostAddress;
+
+ public InetAddress get() {
+
+ long current = System.currentTimeMillis();
+ if (current - lastUpdated.get() > REFRESH_TIME) {
+
+ synchronized (this) {
+
+ try {
+ // set now to register the attempt even if failed
+ lastUpdated.set(current);
+ hostAddress = InetAddress.getLocalHost();
+ } catch (UnknownHostException e) {
+ e.printStackTrace(); // can't really use logging
+ hostAddress = null;
+ }
+ }
+ }
+
+ return hostAddress;
+ }
+ }
+}
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/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
index a963542906..d667ff769c 100644
--- 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
@@ -16,38 +16,58 @@
package org.openecomp.sdc.logging.slf4j;
-import org.slf4j.MDC;
-
+import java.util.EnumMap;
import java.util.Map;
+import org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField;
+import org.slf4j.MDC;
/**
- * @author EVITALIY
- * @since 08 Jan 18
+ * 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<String, String> context;
+ private final Map<ContextField, String> context;
BaseMDCCopyingWrapper() {
- this.context = MDC.getCopyOfContextMap();
+ this.context = fromMdc();
}
- final Map<String, String> replace() {
- Map<String, String> old = MDC.getCopyOfContextMap();
- replaceMDC(this.context);
+ final Map<ContextField, String> replace() {
+ Map<ContextField, String> old = fromMdc();
+ toMdc(this.context);
return old;
}
- final void revert(Map<String, String> old) {
- replaceMDC(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 replaceMDC(Map<String, String> context) {
+ private static void toMdc(Map<ContextField, String> context) {
- if (context == null) {
- MDC.clear();
- } else {
- MDC.setContextMap(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/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 9cb67dee4c..07d0f935f7 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,6 +18,7 @@ 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
@@ -35,7 +36,7 @@ class MDCCallableWrapper<V> extends BaseMDCCopyingWrapper implements Callable<V>
@Override
public V call() throws Exception {
- Map<String, String> oldContext = replace();
+ Map<ContextField, String> oldContext = replace();
try {
return task.call();
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 f1a6986fec..e1b8f1e5c5 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,6 +17,7 @@
package org.openecomp.sdc.logging.slf4j;
import java.util.Map;
+import org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField;
/**
* @author EVITALIY
@@ -34,7 +35,7 @@ class MDCRunnableWrapper extends BaseMDCCopyingWrapper implements Runnable {
@Override
public void run() {
- Map<String, String> oldContext = replace();
+ Map<ContextField, String> oldContext = replace();
try {
task.run();
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapper.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapper.java
index a8ada8777f..783dac4ed4 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapper.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapper.java
@@ -16,6 +16,14 @@
package org.openecomp.sdc.logging.slf4j;
+import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.BEGIN_TIMESTAMP;
+import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.CLIENT_IP_ADDRESS;
+import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.ELAPSED_TIME;
+import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.END_TIMESTAMP;
+import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.RESPONSE_CODE;
+import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.RESPONSE_DESCRIPTION;
+import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.STATUS_CODE;
+
import java.text.Format;
import java.text.SimpleDateFormat;
import org.openecomp.sdc.logging.api.AuditData;
@@ -24,28 +32,36 @@ import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
/**
- * @author EVITALIY
+ * @author evitaliy
* @since 08 Jan 18
*/
class SLF4JLoggerWrapper implements Logger {
//The specified format presents time in UTC formatted per ISO 8601, as required by ONAP logging guidelines
-
private static final String DATE_TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
+
private static final String PREFIX = "";
- static final String BEGIN_TIMESTAMP = PREFIX + "BeginTimestamp";
- static final String END_TIMESTAMP = PREFIX + "EndTimestamp";
- static final String ELAPSED_TIME = PREFIX + "ElapsedTime";
- static final String STATUS_CODE = PREFIX + "StatusCode";
- static final String RESPONSE_CODE = PREFIX + "ResponseCode";
- static final String RESPONSE_DESCRIPTION = PREFIX + "ResponseDescription";
- static final String CLIENT_IP_ADDRESS = PREFIX + "ClientIpAddress";
+ enum AuditField {
+
+ BEGIN_TIMESTAMP(PREFIX + "BeginTimestamp"),
+ END_TIMESTAMP(PREFIX + "EndTimestamp"),
+ ELAPSED_TIME(PREFIX + "ElapsedTime"),
+ STATUS_CODE(PREFIX + "StatusCode"),
+ RESPONSE_CODE(PREFIX + "ResponseCode"),
+ RESPONSE_DESCRIPTION(PREFIX + "ResponseDescription"),
+ CLIENT_IP_ADDRESS(PREFIX + "ClientIpAddress");
+
+ private final String key;
- private static final String[] ALL_MDC_FIELDS = {
- BEGIN_TIMESTAMP, END_TIMESTAMP, ELAPSED_TIME, STATUS_CODE,
- RESPONSE_CODE, RESPONSE_DESCRIPTION, CLIENT_IP_ADDRESS
- };
+ AuditField(String key) {
+ this.key = key;
+ }
+
+ public String asKey() {
+ return key;
+ }
+ }
private final org.slf4j.Logger logger;
@@ -110,19 +126,19 @@ class SLF4JLoggerWrapper implements Logger {
}
putTimes(data);
- putIfNotNull(RESPONSE_CODE, data.getResponseCode());
- putIfNotNull(RESPONSE_DESCRIPTION, data.getResponseDescription());
- putIfNotNull(CLIENT_IP_ADDRESS, data.getClientIpAddress());
+ putIfNotNull(RESPONSE_CODE.key, data.getResponseCode());
+ putIfNotNull(RESPONSE_DESCRIPTION.key, data.getResponseDescription());
+ putIfNotNull(CLIENT_IP_ADDRESS.key, data.getClientIpAddress());
if (data.getStatusCode() != null) {
- MDC.put(STATUS_CODE, data.getStatusCode().name());
+ MDC.put(STATUS_CODE.key, data.getStatusCode().name());
}
try {
logger.info(Markers.AUDIT, "");
} finally {
- for (String k : ALL_MDC_FIELDS) {
- MDC.remove(k);
+ for (AuditField f : AuditField.values()) {
+ MDC.remove(f.key);
}
}
}
@@ -136,9 +152,9 @@ class SLF4JLoggerWrapper implements Logger {
private void putTimes(AuditData data) {
// SimpleDateFormat is not thread-safe and cannot be a constant
Format dateTimeFormat = new SimpleDateFormat(DATE_TIME_PATTERN);
- MDC.put(BEGIN_TIMESTAMP, dateTimeFormat.format(data.getStartTime()));
- MDC.put(END_TIMESTAMP, dateTimeFormat.format(data.getEndTime()));
- MDC.put(ELAPSED_TIME, String.valueOf(data.getEndTime() - data.getStartTime()));
+ MDC.put(BEGIN_TIMESTAMP.key, dateTimeFormat.format(data.getStartTime()));
+ MDC.put(END_TIMESTAMP.key, dateTimeFormat.format(data.getEndTime()));
+ MDC.put(ELAPSED_TIME.key, String.valueOf(data.getEndTime() - data.getStartTime()));
}
@Override
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 fbda93cf61..6f69aae1b6 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,6 +16,10 @@
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.Logger;
@@ -24,11 +28,26 @@ import org.slf4j.MDC;
/**
* @author evitaliy
- * @since 13/09/2016.
+ * @since 13 Sep 2016
*/
public class SLF4JLoggingServiceProvider implements LoggingServiceProvider {
- private static final String KEY_CANNOT_BE_NULL = "Key cannot be null";
+ 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) {
@@ -43,26 +62,29 @@ public class SLF4JLoggingServiceProvider implements LoggingServiceProvider {
}
@Override
- public void put(String key, String value) {
- Objects.requireNonNull(key, KEY_CANNOT_BE_NULL);
- MDC.put(key, value);
+ public void putRequestId(String requestId) {
+ put(REQUEST_ID.key, requestId);
}
@Override
- public String get(String key) {
- Objects.requireNonNull(key, KEY_CANNOT_BE_NULL);
- return MDC.get(key);
+ public void putServiceName(String serviceName) {
+ put(SERVICE_NAME.key, serviceName);
}
@Override
- public void remove(String key) {
- Objects.requireNonNull(key, KEY_CANNOT_BE_NULL);
- MDC.remove(key);
+ public void putPartnerName(String partnerName) {
+ put(PARTNER_NAME.key, partnerName);
}
@Override
public void clear() {
- MDC.clear();
+ for (ContextField s : ContextField.values()) {
+ MDC.remove(s.key);
+ }
+ }
+
+ private void put(String key, String value) {
+ MDC.put(key, Objects.requireNonNull(value, key));
}
@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
index 636ff94a39..52a794f937 100644
--- 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
@@ -1,5 +1,5 @@
/*
- * Copyright © 2016-2017 European Support Limited
+ * Copyright © 2016-2018 European Support Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,18 +23,17 @@ import org.testng.annotations.DataProvider;
import java.util.concurrent.Callable;
/**
- * @author EVITALIY
+ * @author evitaliy
* @since 08 Jan 18
*/
public abstract class BaseContextPropagationTest {
- // Disable if an old version of ctx implementation is being used.
- // ctxPropagationFactory should be used when ctx is not propagated to child threads.
+ // 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 KEY = "test-data";
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";
@@ -52,27 +51,27 @@ public abstract class BaseContextPropagationTest {
@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() }
+ return new Object[][]{
+ {new SLF4JLoggingServiceProvider()},
+ {new LoggingContextAdaptor()}
};
}
private static class LoggingContextAdaptor implements LoggingContextService {
@Override
- public void put(String key, String value) {
- LoggingContext.put(key, value);
+ public void putRequestId(String requestId) {
+ LoggingContext.putRequestId(requestId);
}
@Override
- public String get(String key) {
- return LoggingContext.get(key);
+ public void putServiceName(String serviceName) {
+ LoggingContext.putServiceName(serviceName);
}
@Override
- public void remove(String key) {
- LoggingContext.remove(key);
+ public void putPartnerName(String partnerName) {
+ LoggingContext.putPartnerName(partnerName);
}
@Override
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 0c8de97e1a..58d52bfa0f 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,23 +16,24 @@
package org.openecomp.sdc.logging.slf4j;
-import org.openecomp.sdc.logging.spi.LoggingContextService;
-import org.testng.annotations.Test;
+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;
+import static org.testng.Assert.assertTrue;
-import java.util.UUID;
+import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
+import org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField;
+import org.openecomp.sdc.logging.spi.LoggingContextService;
+import org.testng.annotations.Test;
/**
- * @author EVITALIY
+ * @author evitaliy
* @since 08 Jan 18
*/
public class CallableContextPropagationTest extends BaseContextPropagationTest {
@@ -40,33 +41,29 @@ public class CallableContextPropagationTest extends BaseContextPropagationTest {
@Test(enabled = ENABLED, dataProvider = PROVIDER)
public void testContextPropagated(LoggingContextService ctx) throws Exception {
- String uuid = UUID.randomUUID().toString();
- ctx.put(KEY, uuid);
-
+ Map<ContextField, String> values = putUniqueValues(ctx);
AtomicBoolean complete = new AtomicBoolean(false);
// pass the callable to the context service first
execute(ctx.copyToCallable(() -> {
- assertEquals(ctx.get(KEY), uuid, EXPECT_PROPAGATED_TO_CHILD);
+ assertContextFields(values, EXPECT_PROPAGATED_TO_CHILD);
complete.set(true);
return null;
}));
- assertEquals(ctx.get(KEY), uuid, EXPECT_RETAINED_IN_CURRENT);
+ assertContextFields(values, EXPECT_RETAINED_IN_CURRENT);
assertTrue(complete.get(), EXPECT_INNER_RUN);
}
@Test(enabled = ENABLED, dataProvider = PROVIDER)
public void testContextReplacement(LoggingContextService ctx) throws Exception {
- String innerRandom = UUID.randomUUID().toString();
- ctx.put(KEY, innerRandom);
-
+ Map<ContextField, String> innerValues = putUniqueValues(ctx);
AtomicBoolean innerComplete = new AtomicBoolean(false);
// should run with the context of main thread
Callable inner = ctx.copyToCallable(() -> {
- assertEquals(ctx.get(KEY), innerRandom, EXPECT_PROPAGATED_TO_CHILD);
+ assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
innerComplete.set(true);
return null;
});
@@ -74,15 +71,14 @@ public class CallableContextPropagationTest extends BaseContextPropagationTest {
// pushes its own context, but the inner must run with its own context
AtomicBoolean outerComplete = new AtomicBoolean(false);
execute(() -> {
- String outerUuid = UUID.randomUUID().toString();
- ctx.put(KEY, outerUuid);
+ Map<ContextField, String> outerValues = putUniqueValues(ctx);
inner.call();
- assertEquals(ctx.get(KEY), outerUuid, EXPECT_REPLACED_WITH_STORED);
+ assertContextFields(outerValues, EXPECT_REPLACED_WITH_STORED);
outerComplete.set(true);
return null;
});
- assertEquals(ctx.get(KEY), innerRandom, EXPECT_RETAINED_IN_CURRENT);
+ assertContextFields(innerValues, EXPECT_RETAINED_IN_CURRENT);
assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
}
@@ -90,30 +86,29 @@ public class CallableContextPropagationTest extends BaseContextPropagationTest {
@Test(enabled = ENABLED, dataProvider = PROVIDER)
public void testContextRemainsEmpty(LoggingContextService ctx) throws Exception {
- ctx.remove(KEY);
- assertNull(ctx.get(KEY), EXPECT_EMPTY);
+ ctx.clear();
+ assertContextEmpty(EXPECT_EMPTY);
final AtomicBoolean complete = new AtomicBoolean(false);
execute(ctx.copyToCallable(() -> {
- assertNull(ctx.get(KEY), EXPECT_EMPTY);
+ assertContextEmpty(EXPECT_EMPTY);
complete.set(true);
return null;
}));
- assertNull(ctx.get(KEY), EXPECT_EMPTY);
+ assertContextEmpty(EXPECT_EMPTY);
assertTrue(complete.get(), EXPECT_INNER_RUN);
}
@Test(enabled = ENABLED, dataProvider = PROVIDER)
public void testContextCleanedUp(LoggingContextService ctx) throws Exception {
- String innerRandom = UUID.randomUUID().toString();
- ctx.put(KEY, innerRandom);
+ Map<ContextField, String> innerValues = putUniqueValues(ctx);
AtomicBoolean innerComplete = new AtomicBoolean(false);
// should run with the context of main thread
Callable inner = ctx.copyToCallable((() -> {
- assertEquals(ctx.get(KEY), innerRandom, EXPECT_PROPAGATED_TO_CHILD);
+ assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
innerComplete.set(true);
return null;
}));
@@ -121,14 +116,14 @@ public class CallableContextPropagationTest extends BaseContextPropagationTest {
// pushes its own context, but runs the inner
AtomicBoolean outerComplete = new AtomicBoolean(false);
execute(() -> {
- assertNull(ctx.get(KEY), EXPECT_NOT_COPIED);
+ assertContextEmpty(EXPECT_NOT_COPIED);
inner.call();
- assertNull(ctx.get(KEY), EXPECT_REMAIN_EMPTY);
+ assertContextEmpty(EXPECT_REMAIN_EMPTY);
outerComplete.set(true);
return null;
});
- assertEquals(ctx.get(KEY), innerRandom, EXPECT_RETAINED_IN_PARENT);
+ assertContextFields(innerValues, EXPECT_RETAINED_IN_PARENT);
assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
}
@@ -136,13 +131,12 @@ public class CallableContextPropagationTest extends BaseContextPropagationTest {
@Test(enabled = ENABLED, dataProvider = PROVIDER)
public void testCleanupAfterError(LoggingContextService ctx) throws Exception {
- String innerRandom = UUID.randomUUID().toString();
- ctx.put(KEY, innerRandom);
+ Map<ContextField, String> innerValues = putUniqueValues(ctx);
// should run with the context of main thread
AtomicBoolean innerComplete = new AtomicBoolean(false);
Callable inner = ctx.copyToCallable(() -> {
- assertEquals(ctx.get(KEY), innerRandom, EXPECT_PROPAGATED_TO_CHILD);
+ assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
innerComplete.set(true);
throw new IllegalArgumentException();
});
@@ -152,23 +146,22 @@ public class CallableContextPropagationTest extends BaseContextPropagationTest {
AtomicBoolean exceptionThrown = new AtomicBoolean(false);
execute(() -> {
- String outerUuid = UUID.randomUUID().toString();
- ctx.put(KEY, outerUuid);
- assertEquals(ctx.get(KEY), outerUuid, EXPECT_POPULATED);
+ Map<ContextField, String> outerValues = putUniqueValues(ctx);
+ assertContextFields(outerValues, EXPECT_POPULATED);
try {
inner.call();
} catch (IllegalArgumentException e) {
exceptionThrown.set(true);
} finally {
- assertEquals(ctx.get(KEY), outerUuid, EXPECT_REVERTED_ON_EXCEPTION);
+ assertContextFields(outerValues, EXPECT_REVERTED_ON_EXCEPTION);
outerComplete.set(true);
}
return null;
});
- assertEquals(ctx.get(KEY), innerRandom, EXPECT_RETAINED_IN_PARENT);
+ assertContextFields(innerValues, EXPECT_RETAINED_IN_PARENT);
assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
assertTrue(exceptionThrown.get(), EXPECT_EXCEPTION_FROM_INNER);
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
new file mode 100644
index 0000000000..5112d37ac5
--- /dev/null
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/ContextPropagationTestHelper.java
@@ -0,0 +1,67 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+
+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));
+
+ static Map<ContextField, String> putUniqueValues(LoggingContextService ctx) {
+
+ Map<ContextField, String> values = new EnumMap<>(ContextField.class);
+
+ String service = UUID.randomUUID().toString();
+ ctx.putServiceName(service);
+ values.put(ContextField.SERVICE_NAME, service);
+
+ String partner = UUID.randomUUID().toString();
+ ctx.putPartnerName(partner);
+ values.put(ContextField.PARTNER_NAME, partner);
+
+ String request = UUID.randomUUID().toString();
+ ctx.putRequestId(request);
+ values.put(ContextField.REQUEST_ID, request);
+
+ return values;
+ }
+
+ static void assertContextFields(Map<ContextField, String> values, String error) {
+
+ for (ContextField f : ContextField.values()) {
+ assertEquals(MDC.get(f.asKey()), values.get(f), error);
+ }
+ }
+
+ static void assertContextEmpty(String error) {
+ assertContextFields(EMPTY_CONTEXT, error);
+ }
+}
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 e93c114193..430d4d4c54 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
@@ -17,6 +17,7 @@
package org.openecomp.sdc.logging.slf4j;
import org.openecomp.sdc.logging.api.LoggingContext;
+import org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField;
import org.slf4j.MDC;
import org.testng.annotations.Test;
@@ -27,7 +28,7 @@ import static org.testng.Assert.assertNull;
/**
* @author evitaliy
- * @since 12/09/2016.
+ * @since 12 Sep 2016
*/
public class LoggingContextTest {
@@ -52,61 +53,93 @@ public class LoggingContextTest {
}
@Test
- public void clearContextWhenClearCalled() {
+ public void keysClearedWhenContextCleared() {
- String random = UUID.randomUUID().toString();
+ String value = UUID.randomUUID().toString();
try {
- LoggingContext.put(random, random);
+ LoggingContext.putPartnerName(value);
+ LoggingContext.putServiceName(value);
+ LoggingContext.putRequestId(value);
LoggingContext.clear();
- assertNull(MDC.get(random));
- assertNull(LoggingContext.get(random));
+
+ for (ContextField field : ContextField.values()) {
+ assertNull(MDC.get(field.asKey()));
+ }
+
} finally {
- MDC.remove(random);
+ MDC.clear();
}
}
@Test
- public void returnContextWhenGetCalled() {
+ public void unrelatedKeysRemainWhenContextCleared() {
- String random = UUID.randomUUID().toString();
+ String randomValue = UUID.randomUUID().toString();
+ String randomKey = "Key-" + randomValue;
try {
- LoggingContext.put(random, random);
- assertEquals(random, MDC.get(random));
- assertEquals(random, LoggingContext.get(random));
+
+ MDC.put(randomKey, randomValue);
+ LoggingContext.clear();
+ assertEquals(MDC.get(randomKey), randomValue);
+
} finally {
- MDC.remove(random);
+ MDC.clear();
}
}
@Test
- public void removeContextWhenRemoveCalled() {
+ public void contextHasServiceNameWhenPut() {
String random = UUID.randomUUID().toString();
try {
- LoggingContext.put(random, random);
- LoggingContext.remove(random);
- assertNull(MDC.get(random));
- assertNull(LoggingContext.get(random));
+ LoggingContext.putServiceName(random);
+ assertEquals(random, MDC.get(ContextField.SERVICE_NAME.asKey()));
} finally {
- MDC.remove(random);
+ MDC.clear();
}
}
@Test(expectedExceptions = NullPointerException.class)
- public void throwNpeWhenPutWithKeyNull() {
- LoggingContext.put(null, "---");
+ public void throwNpeWhenServiceNameNull() {
+ LoggingContext.putServiceName(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 throwNpeWhenGetWithKeyNull() {
- LoggingContext.get(null);
+ public void throwNpeWhenRequestIdNull() {
+ LoggingContext.putRequestId(null);
+ }
+
+ @Test
+ public void contextHasPartnerNameWhenPut() {
+
+ String random = UUID.randomUUID().toString();
+
+ try {
+ LoggingContext.putPartnerName(random);
+ assertEquals(random, MDC.get(ContextField.PARTNER_NAME.asKey()));
+ } finally {
+ MDC.clear();
+ }
}
@Test(expectedExceptions = NullPointerException.class)
- public void throwNpeWhenRemoveWithKeyNull() {
- LoggingContext.remove(null);
+ public void throwNpeWhenPartnerNameNull() {
+ LoggingContext.putPartnerName(null);
}
}
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 90d6cda52a..fcd1a56252 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,18 +16,19 @@
package org.openecomp.sdc.logging.slf4j;
-import org.openecomp.sdc.logging.spi.LoggingContextService;
-import org.testng.annotations.Test;
+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;
+import static org.testng.Assert.assertTrue;
-import java.util.UUID;
+import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
+import org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField;
+import org.openecomp.sdc.logging.spi.LoggingContextService;
+import org.testng.annotations.Test;
/**
- * @author EVITALIY
+ * @author evitaliy
* @since 08 Jan 18
*/
public class RunnableContextPropagationTest extends BaseContextPropagationTest {
@@ -36,14 +37,12 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
public void contextNotCopiedToChildThreadByDefault(LoggingContextService ctx)
throws InterruptedException {
- String random = UUID.randomUUID().toString();
- ctx.put(KEY, random);
-
+ Map<ContextField, String> values = putUniqueValues(ctx);
AtomicBoolean complete = new AtomicBoolean(false);
// create thread right away without copying context
Thread thread = new Thread(() -> {
- assertNull(ctx.get(KEY), "Data unexpectedly copied to a child thread. " +
+ 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);
});
@@ -51,7 +50,7 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
thread.start();
thread.join();
- assertEquals(ctx.get(KEY), random, EXPECT_RETAINED_IN_CURRENT);
+ assertContextFields(values, EXPECT_RETAINED_IN_CURRENT);
assertTrue(complete.get(), EXPECT_INNER_RUN);
}
@@ -59,21 +58,19 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
public void contextCopiedWhenToRunnableCalled(LoggingContextService ctx)
throws InterruptedException {
- String uuid = UUID.randomUUID().toString();
- ctx.put(KEY, uuid);
-
+ Map<ContextField, String> values = putUniqueValues(ctx);
AtomicBoolean complete = new AtomicBoolean(false);
// pass the runnable to the context service first
Thread thread = new Thread(ctx.copyToRunnable(() -> {
- assertEquals(ctx.get(KEY), uuid, EXPECT_PROPAGATED_TO_CHILD);
+ assertContextFields(values, EXPECT_PROPAGATED_TO_CHILD);
complete.set(true);
}));
thread.start();
thread.join();
- assertEquals(ctx.get(KEY), uuid, EXPECT_RETAINED_IN_CURRENT);
+ assertContextFields(values, EXPECT_RETAINED_IN_CURRENT);
assertTrue(complete.get(), EXPECT_INNER_RUN);
}
@@ -81,31 +78,28 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
public void copiedContextRetainedEvenWhenAnotherPushed(LoggingContextService ctx)
throws InterruptedException {
- String innerRandom = UUID.randomUUID().toString();
- ctx.put(KEY, innerRandom);
-
+ Map<ContextField, String> innerValues = putUniqueValues(ctx);
AtomicBoolean innerComplete = new AtomicBoolean(false);
// should run with the context of main thread
Runnable inner = ctx.copyToRunnable(() -> {
- assertEquals(ctx.get(KEY), innerRandom, EXPECT_PROPAGATED_TO_CHILD);
+ assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
innerComplete.set(true);
});
// pushes its context, but the inner must run with its own context
AtomicBoolean outerComplete = new AtomicBoolean(false);
Thread outer = new Thread(() -> {
- String outerUuid = UUID.randomUUID().toString();
- ctx.put(KEY, outerUuid);
+ Map<ContextField, String> outerValues = putUniqueValues(ctx);
inner.run();
- assertEquals(ctx.get(KEY), outerUuid, EXPECT_REPLACED_WITH_STORED);
+ assertContextFields(outerValues, EXPECT_REPLACED_WITH_STORED);
outerComplete.set(true);
});
outer.start();
outer.join();
- assertEquals(ctx.get(KEY), innerRandom, EXPECT_RETAINED_IN_CURRENT);
+ assertContextFields(innerValues, EXPECT_RETAINED_IN_CURRENT);
assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
}
@@ -114,12 +108,12 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
public void contextRemainsEmptyWhenParentWasEmpty(LoggingContextService ctx)
throws InterruptedException {
- ctx.remove(KEY);
- assertNull(ctx.get(KEY), EXPECT_EMPTY);
+ ctx.clear();
+ assertContextEmpty(EXPECT_EMPTY);
final AtomicBoolean complete = new AtomicBoolean(false);
Runnable runnable = ctx.copyToRunnable(() -> {
- assertNull(ctx.get(KEY), EXPECT_EMPTY);
+ assertContextEmpty(EXPECT_EMPTY);
complete.set(true);
});
@@ -127,7 +121,7 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
thread.start();
thread.join();
- assertNull(ctx.get(KEY), EXPECT_EMPTY);
+ assertContextEmpty(EXPECT_EMPTY);
assertTrue(complete.get(), EXPECT_INNER_RUN);
}
@@ -135,29 +129,27 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
public void childThreadCleanedUpAfterRunnableRuns(LoggingContextService ctx)
throws Exception {
- String innerRandom = UUID.randomUUID().toString();
- ctx.put(KEY, innerRandom);
-
+ Map<ContextField, String> innerValues = putUniqueValues(ctx);
AtomicBoolean innerComplete = new AtomicBoolean(false);
// should run with the context of main thread
Runnable inner = ctx.copyToRunnable(() -> {
- assertEquals(ctx.get(KEY), innerRandom, EXPECT_PROPAGATED_TO_CHILD);
+ assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
innerComplete.set(true);
});
// pushes its own context, but runs the inner
AtomicBoolean outerComplete = new AtomicBoolean(false);
Thread outer = new Thread(() -> {
- assertNull(ctx.get(KEY), EXPECT_NOT_COPIED);
+ assertContextEmpty(EXPECT_NOT_COPIED);
inner.run();
- assertNull(ctx.get(KEY), EXPECT_REMAIN_EMPTY);
+ assertContextEmpty(EXPECT_REMAIN_EMPTY);
outerComplete.set(true);
});
outer.start();
outer.join();
- assertEquals(ctx.get(KEY), innerRandom, EXPECT_RETAINED_IN_PARENT);
+ assertContextFields(innerValues, EXPECT_RETAINED_IN_PARENT);
assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
}
@@ -166,13 +158,12 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
public void childThreadCleanedUpAfterException(LoggingContextService ctx)
throws Exception {
- String innerRandom = UUID.randomUUID().toString();
- ctx.put(KEY, innerRandom);
+ Map<ContextField, String> innerValues = putUniqueValues(ctx);
// should run with the context of main thread
AtomicBoolean innerComplete = new AtomicBoolean(false);
Runnable inner = ctx.copyToRunnable(() -> {
- assertEquals(ctx.get(KEY), innerRandom, EXPECT_PROPAGATED_TO_CHILD);
+ assertContextFields(innerValues, EXPECT_PROPAGATED_TO_CHILD);
innerComplete.set(true);
throw new IllegalArgumentException();
});
@@ -182,16 +173,15 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
AtomicBoolean exceptionThrown = new AtomicBoolean(false);
Thread outer = new Thread(() -> {
- String outerUuid = UUID.randomUUID().toString();
- ctx.put(KEY, outerUuid);
- assertEquals(ctx.get(KEY), outerUuid, EXPECT_POPULATED);
+ Map<ContextField, String> outerValues = putUniqueValues(ctx);
+ assertContextFields(outerValues, EXPECT_POPULATED);
try {
inner.run();
} catch (IllegalArgumentException e) {
exceptionThrown.set(true);
} finally {
- assertEquals(ctx.get(KEY), outerUuid, EXPECT_REVERTED_ON_EXCEPTION);
+ assertContextFields(outerValues, EXPECT_REVERTED_ON_EXCEPTION);
outerComplete.set(true);
}
});
@@ -199,7 +189,7 @@ public class RunnableContextPropagationTest extends BaseContextPropagationTest {
outer.start();
outer.join();
- assertEquals(ctx.get(KEY), innerRandom, EXPECT_RETAINED_IN_PARENT);
+ assertContextFields(innerValues, EXPECT_RETAINED_IN_PARENT);
assertTrue(outerComplete.get(), EXPECT_OUTER_RUN);
assertTrue(innerComplete.get(), EXPECT_INNER_RUN);
assertTrue(exceptionThrown.get(), EXPECT_EXCEPTION_FROM_INNER);
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapperTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapperTest.java
index a4a5e5c72c..9093f7d066 100644
--- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapperTest.java
+++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapperTest.java
@@ -16,13 +16,13 @@
package org.openecomp.sdc.logging.slf4j;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.BEGIN_TIMESTAMP;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.CLIENT_IP_ADDRESS;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.ELAPSED_TIME;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.END_TIMESTAMP;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.RESPONSE_CODE;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.RESPONSE_DESCRIPTION;
-import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.STATUS_CODE;
+import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.BEGIN_TIMESTAMP;
+import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.CLIENT_IP_ADDRESS;
+import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.ELAPSED_TIME;
+import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.END_TIMESTAMP;
+import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.RESPONSE_CODE;
+import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.RESPONSE_DESCRIPTION;
+import static org.openecomp.sdc.logging.slf4j.SLF4JLoggerWrapper.AuditField.STATUS_CODE;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
@@ -39,7 +39,7 @@ import org.slf4j.MDC;
import org.testng.annotations.Test;
/**
- * @author EVITALIY
+ * @author evitaliy
* @since 05 Mar 18
*/
public class SLF4JLoggerWrapperTest {
@@ -54,7 +54,7 @@ public class SLF4JLoggerWrapperTest {
SpyLogger spy = createSpy();
long start = System.currentTimeMillis();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().startTime(start).build());
- assertNotNull(spy.mdc().get(BEGIN_TIMESTAMP));
+ assertNotNull(spy.mdc().get(BEGIN_TIMESTAMP.asKey()));
}
@Test
@@ -62,7 +62,7 @@ public class SLF4JLoggerWrapperTest {
SpyLogger spy = createSpy();
long end = System.currentTimeMillis();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().endTime(end).build());
- assertNotNull(spy.mdc().get(END_TIMESTAMP));
+ assertNotNull(spy.mdc().get(END_TIMESTAMP.asKey()));
}
@Test
@@ -71,21 +71,21 @@ public class SLF4JLoggerWrapperTest {
long start = System.currentTimeMillis();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder()
.startTime(start).endTime(start).build());
- assertNotNull(spy.mdc().get(ELAPSED_TIME));
+ assertNotNull(spy.mdc().get(ELAPSED_TIME.asKey()));
}
@Test
public void statusCodeAvailableWhenPassed() {
SpyLogger spy = createSpy();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().statusCode(StatusCode.COMPLETE).build());
- assertEquals(spy.mdc().get(STATUS_CODE), StatusCode.COMPLETE.name());
+ assertEquals(spy.mdc().get(STATUS_CODE.asKey()), StatusCode.COMPLETE.name());
}
@Test
public void statusCodeEmptyWhenNotPassed() {
SpyLogger spy = createSpy();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().build());
- assertNull(spy.mdc().get(STATUS_CODE));
+ assertNull(spy.mdc().get(STATUS_CODE.asKey()));
}
@Test
@@ -93,14 +93,14 @@ public class SLF4JLoggerWrapperTest {
final String responseCode = "SpyResponse";
SpyLogger spy = createSpy();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().responseCode(responseCode).build());
- assertEquals(spy.mdc().get(RESPONSE_CODE), responseCode);
+ assertEquals(spy.mdc().get(RESPONSE_CODE.asKey()), responseCode);
}
@Test
public void responseCodeEmptyWhenNotPassed() {
SpyLogger spy = createSpy();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().build());
- assertNull(spy.mdc().get(RESPONSE_CODE));
+ assertNull(spy.mdc().get(RESPONSE_CODE.asKey()));
}
@Test
@@ -108,14 +108,14 @@ public class SLF4JLoggerWrapperTest {
final String responseDescription = "SpyDescription";
SpyLogger spy = createSpy();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().responseDescription(responseDescription).build());
- assertEquals(spy.mdc().get(RESPONSE_DESCRIPTION), responseDescription);
+ assertEquals(spy.mdc().get(RESPONSE_DESCRIPTION.asKey()), responseDescription);
}
@Test
public void responseDescriptionEmptyWhenNotPassed() {
SpyLogger spy = createSpy();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().build());
- assertNull(spy.mdc().get(RESPONSE_DESCRIPTION));
+ assertNull(spy.mdc().get(RESPONSE_DESCRIPTION.asKey()));
}
@Test
@@ -123,14 +123,14 @@ public class SLF4JLoggerWrapperTest {
final String ipAddress = "10.56.20.20";
SpyLogger spy = createSpy();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().clientIpAddress(ipAddress).build());
- assertEquals(spy.mdc().get(CLIENT_IP_ADDRESS), ipAddress);
+ assertEquals(spy.mdc().get(CLIENT_IP_ADDRESS.asKey()), ipAddress);
}
@Test
public void clientIpAddressEmptyWhenNotPassed() {
SpyLogger spy = createSpy();
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().build());
- assertNull(spy.mdc().get(CLIENT_IP_ADDRESS));
+ assertNull(spy.mdc().get(CLIENT_IP_ADDRESS.asKey()));
}
@Test
@@ -140,7 +140,7 @@ public class SLF4JLoggerWrapperTest {
long start = System.currentTimeMillis();
long end = start + diff;
new SLF4JLoggerWrapper(spy).audit(AuditData.builder().startTime(start).endTime(end).build());
- assertEquals(spy.mdc().get(ELAPSED_TIME), Long.toString(diff));
+ assertEquals(spy.mdc().get(ELAPSED_TIME.asKey()), Long.toString(diff));
}
interface SpyLogger extends Logger {