Changed logging context API

Issue-ID: SDC-772
Change-Id: I9dce63f3a1bb7df067cf06a96158afa7d799319e
Signed-off-by: olegb <olegb@amdocs.com>
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 f827fec..879d9cf 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.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>
+ *
+ * <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
- * @since 07/01/2018.
- *
  * @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 @@
 
     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 7aed0fc..07b93c1 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 @@
 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 @@
     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 79252cd..bfc53a3 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 @@
                 "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 throwNpeWhenPartnerNameIsNull() {
+        LoggingContext.putPartnerName(null);
     }
 
     @Test(expectedExceptions = NullPointerException.class)
-    public void throwNpeWhenPutWithKeyNull() {
-        LoggingContext.put(null, "value");
-    }
-
-    @Test
-    public void getAlwaysReturnsNull() {
-        assertNull(LoggingContext.get("GetKey"));
+    public void throwNpeWhenServiceNameIsNull() {
+        LoggingContext.putServiceName(null);
     }
 
     @Test(expectedExceptions = NullPointerException.class)
-    public void throwNpeWhenGetWithKeyNull() {
-        LoggingContext.get(null);
-    }
-
-    @Test
-    public void removeDoesNotFail() {
-        LoggingContext.remove("RemoveKey");
-    }
-
-    @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 0000000..95dc52c
--- /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 a963542..d667ff7 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 java.util.EnumMap;
+import java.util.Map;
+import org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField;
 import org.slf4j.MDC;
 
-import java.util.Map;
-
 /**
- * @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 static void replaceMDC(Map<String, String> context) {
+    private Map<ContextField, String> fromMdc() {
 
-        if (context == null) {
-            MDC.clear();
-        } else {
-            MDC.setContextMap(context);
+        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/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 9cb67de..07d0f93 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 @@
 
 import java.util.Map;
 import java.util.concurrent.Callable;
+import org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider.ContextField;
 
 /**
  * @author EVITALIY
@@ -35,7 +36,7 @@
     @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 f1a6986..e1b8f1e 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 @@
     @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 a8ada87..783dac4 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.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 {
 
-    private static final String[] ALL_MDC_FIELDS = {
-        BEGIN_TIMESTAMP, END_TIMESTAMP, ELAPSED_TIME, STATUS_CODE,
-        RESPONSE_CODE, RESPONSE_DESCRIPTION, CLIENT_IP_ADDRESS
-    };
+        BEGIN_TIMESTAMP(PREFIX + "BeginTimestamp"),
+        END_TIMESTAMP(PREFIX + "EndTimestamp"),
+        ELAPSED_TIME(PREFIX + "ElapsedTime"),
+        STATUS_CODE(PREFIX + "StatusCode"),
+        RESPONSE_CODE(PREFIX + "ResponseCode"),
+        RESPONSE_DESCRIPTION(PREFIX + "ResponseDescription"),
+        CLIENT_IP_ADDRESS(PREFIX + "ClientIpAddress");
+
+        private final String key;
+
+        AuditField(String key) {
+            this.key = key;
+        }
+
+        public String asKey() {
+            return key;
+        }
+    }
 
     private final org.slf4j.Logger logger;
 
@@ -110,19 +126,19 @@
         }
 
         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 @@
     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 fbda93c..6f69aae 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 @@
 
 /**
  * @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 @@
     }
 
     @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 636ff94..52a794f 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 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 @@
     @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 0c8de97..58d52bf 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 @@
     @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 @@
         // 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 @@
     @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 @@
         // 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 @@
     @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 @@
         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 0000000..5112d37
--- /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 e93c114..430d4d4 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 @@
 
 /**
  * @author evitaliy
- * @since 12/09/2016.
+ * @since 12 Sep 2016
  */
 public class LoggingContextTest {
 
@@ -52,61 +53,93 @@
     }
 
     @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 90d6cda..fcd1a56 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 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.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;
 
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-
 /**
- * @author EVITALIY
+ * @author evitaliy
  * @since 08 Jan 18
  */
 public class RunnableContextPropagationTest extends BaseContextPropagationTest {
@@ -36,14 +37,12 @@
     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 @@
         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 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 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 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 @@
         thread.start();
         thread.join();
 
-        assertNull(ctx.get(KEY), EXPECT_EMPTY);
+        assertContextEmpty(EXPECT_EMPTY);
         assertTrue(complete.get(), EXPECT_INNER_RUN);
     }
 
@@ -135,29 +129,27 @@
     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 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 @@
         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 @@
         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 a4a5e5c..9093f7d 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.testng.annotations.Test;
 
 /**
- * @author EVITALIY
+ * @author evitaliy
  * @since 05 Mar 18
  */
 public class SLF4JLoggerWrapperTest {
@@ -54,7 +54,7 @@
         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 @@
         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 @@
         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 @@
         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 @@
         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 @@
         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 @@
         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 {