Expose tracing context via log context service 63/44663/2
authorvempo <vitaliy.emporopulo@amdocs.com>
Wed, 25 Apr 2018 12:28:48 +0000 (15:28 +0300)
committerAvi Gaffa <avi.gaffa@amdocs.com>
Tue, 1 May 2018 07:29:07 +0000 (07:29 +0000)
Tracing context must be available to application code
when the application makes outbound calls.

Change-Id: Ica8e1f9d8e0bd6d37688a01a64c1fbedc126801c
Issue-ID: SDC-1264
Signed-off-by: vempo <vitaliy.emporopulo@amdocs.com>
openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ContextData.java
openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggingContext.java
openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggingContextService.java
openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCDelegate.java
openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/RequestContextProvider.java
openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggingServiceProvider.java
openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/LoggingContextTest.java
openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/RequestContextProviderTest.java

index 43f0143..6eb747f 100644 (file)
@@ -16,6 +16,8 @@
 
 package org.openecomp.sdc.logging.api;
 
+import java.util.Objects;
+
 /**
  * Builder to populate logging <i>context</i> data, i.e. data that should be available to any log writing event
  * throughout an application. This includes only data known at some point to the application (e.g. at an API call),
@@ -63,10 +65,31 @@ public class ContextData {
         return partnerName;
     }
 
+    @Override
+    public boolean equals(Object o) {
+
+        if (this == o) {
+            return true;
+        }
+
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        ContextData that = (ContextData) o;
+        return Objects.equals(requestId, that.requestId) && Objects.equals(serviceName, that.serviceName)
+                       && Objects.equals(partnerName, that.partnerName);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(requestId, serviceName, partnerName);
+    }
+
     @Override
     public String toString() {
         return "ContextData{responseCode=" + requestId + ", responseDescription=" + serviceName
-                + ", clientIpAddress=" + partnerName + '}';
+                       + ", clientIpAddress=" + partnerName + '}';
     }
 
     public static ContextDataBuilder builder() {
index 2dc4afd..c17149e 100644 (file)
@@ -36,8 +36,7 @@ import org.openecomp.sdc.logging.spi.LoggingContextService;
 public class LoggingContext {
 
     private static final LoggingContextService SERVICE =
-        ServiceBinder.getContextServiceBinding().orElse(
-            new NoOpLoggingContextService());
+            ServiceBinder.getContextServiceBinding().orElse(new NoOpLoggingContextService());
 
     private LoggingContext() {
         // prevent instantiation
@@ -47,6 +46,10 @@ public class LoggingContext {
         SERVICE.put(contextData);
     }
 
+    public static ContextData get() {
+        return SERVICE.get();
+    }
+
     public static void clear() {
         SERVICE.clear();
     }
@@ -61,11 +64,18 @@ public class LoggingContext {
 
     private static class NoOpLoggingContextService implements LoggingContextService {
 
+        private static final ContextData EMPTY_CONTEXT = ContextData.builder().build();
+
         @Override
         public void put(ContextData contextData) {
             Objects.requireNonNull(contextData, "Context data cannot be null");
         }
 
+        @Override
+        public ContextData get() {
+            return EMPTY_CONTEXT;
+        }
+
         @Override
         public void clear() {
             // no-op
index 8d719a2..026d3fa 100644 (file)
@@ -49,6 +49,27 @@ class MDCDelegate {
         return copy;
     }
 
+    /**
+     * Reads all context fields from MDC.
+     */
+    static Map<ContextField, String> get() {
+        return get(ContextField.values());
+    }
+
+    /**
+     * Reads selected fields from MDC.
+     */
+    static Map<ContextField, String> get(ContextField... fields) {
+
+        Map<ContextField, String> values = new EnumMap<>(ContextField.class);
+
+        for (ContextField key : fields) {
+            values.put(key, MDC.get(key.asKey()));
+        }
+
+        return values;
+    }
+
     /**
      * Entirely replaces the logging MDC context with the content of the argument. Logging keys that are not present in
      * the input map will be cleared from MDC.
index d79771c..40684cc 100644 (file)
@@ -30,10 +30,21 @@ class RequestContextProvider implements ContextProvider {
 
     private final ContextData data;
 
-    RequestContextProvider(ContextData contextData) {
+    private RequestContextProvider(ContextData contextData) {
         this.data = contextData;
     }
 
+    static RequestContextProvider from(ContextData contextData) {
+        return new RequestContextProvider(contextData);
+    }
+
+    static ContextData to(Map<ContextField, String> values) {
+        return ContextData.builder()
+                          .requestId(values.get(ContextField.REQUEST_ID))
+                          .serviceName(values.get(ContextField.SERVICE_NAME))
+                          .partnerName(values.get(ContextField.PARTNER_NAME)).build();
+    }
+
     @Override
     public Map<ContextField, String> values() {
 
index 1a5d6fa..9d4d507 100644 (file)
@@ -45,7 +45,12 @@ public class SLF4JLoggingServiceProvider implements LoggingServiceProvider {
     @Override
     public void put(ContextData contextData) {
         Objects.requireNonNull(contextData, "Context data cannot be null");
-        MDCDelegate.put(new RequestContextProvider(contextData), new GlobalContextProvider());
+        MDCDelegate.put(RequestContextProvider.from(contextData), new GlobalContextProvider());
+    }
+
+    @Override
+    public ContextData get() {
+        return RequestContextProvider.to(MDCDelegate.get());
     }
 
     @Override
index 47386d4..c2cef88 100644 (file)
@@ -42,7 +42,7 @@ public class LoggingContextTest {
 
     @Test
     public void returnMdcWrapperWhenToRunnableCalled() {
-        assertEquals(LoggingContext.copyToRunnable(() -> {}).getClass(), MDCRunnableWrapper.class);
+        assertEquals(LoggingContext.copyToRunnable(() -> { }).getClass(), MDCRunnableWrapper.class);
     }
 
     @Test(expectedExceptions = NullPointerException.class)
@@ -140,4 +140,32 @@ public class LoggingContextTest {
         LoggingContext.put(context);
         assertNotNull(MDC.get(ContextField.INSTANCE_ID.asKey()));
     }
+
+    @Test
+    public void contextReturnsServiceNameWhenPut() {
+
+        String random = UUID.randomUUID().toString();
+        ContextData context = ContextData.builder().serviceName(random).build();
+        LoggingContext.put(context);
+        assertEquals(context, LoggingContext.get());
+    }
+
+    @Test
+    public void contextReturnsRequestIdWhenPut() {
+
+        String random = UUID.randomUUID().toString();
+        ContextData context = ContextData.builder().requestId(random).build();
+        LoggingContext.put(context);
+        assertEquals(context, LoggingContext.get());
+    }
+
+    @Test
+    public void contextReturnsPartnerNameWhenPut() {
+
+        String random = UUID.randomUUID().toString();
+        ContextData context = ContextData.builder().partnerName(random).build();
+        LoggingContext.put(context);
+        assertEquals(context, LoggingContext.get());
+    }
+
 }
index fa7926a..a2d36ef 100644 (file)
 package org.openecomp.sdc.logging.slf4j;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 
+import java.util.HashMap;
 import org.openecomp.sdc.logging.api.ContextData;
 import org.testng.annotations.Test;
 
@@ -31,32 +33,67 @@ import org.testng.annotations.Test;
 public class RequestContextProviderTest {
 
     @Test
-    public void valuesEmptyWhenInputEmpty() {
-        RequestContextProvider provider = new RequestContextProvider(ContextData.builder().build());
+    public void valuesEmptyWhenInputDataEmpty() {
+        RequestContextProvider provider = RequestContextProvider.from(ContextData.builder().build());
         assertTrue(provider.values().isEmpty());
     }
 
     @Test
-    public void serviceNameReturnedWhenSupplied() {
+    public void serviceNameReturnedWhenSuppliedInData() {
         final String service = "supplied-service-name";
         RequestContextProvider provider =
-                new RequestContextProvider(ContextData.builder().serviceName(service).build());
+                RequestContextProvider.from(ContextData.builder().serviceName(service).build());
         assertEquals(provider.values().get(ContextField.SERVICE_NAME), service);
     }
 
     @Test
-    public void partnerNameReturnedWhenSupplied() {
+    public void partnerNameReturnedWhenSuppliedInData() {
         final String partner = "supplied-partner-name";
         RequestContextProvider provider =
-                new RequestContextProvider(ContextData.builder().partnerName(partner).build());
+                RequestContextProvider.from(ContextData.builder().partnerName(partner).build());
         assertEquals(provider.values().get(ContextField.PARTNER_NAME), partner);
     }
 
     @Test
-    public void requestIdReturnedWhenSupplied() {
+    public void requestIdReturnedWhenSuppliedInData() {
         final String request = "supplied-request-id";
         RequestContextProvider provider =
-                new RequestContextProvider(ContextData.builder().requestId(request).build());
+                RequestContextProvider.from(ContextData.builder().requestId(request).build());
         assertEquals(provider.values().get(ContextField.REQUEST_ID), request);
     }
+
+    @Test
+    public void dataEmptyWhenValuesEmpty() {
+        ContextData data = RequestContextProvider.to(new HashMap<>());
+        assertNull(data.getPartnerName());
+        assertNull(data.getRequestId());
+        assertNull(data.getServiceName());
+    }
+
+    @Test
+    public void serviceNameInDataWhenSuppliedInValues() {
+        final String service = "values-service-name";
+        HashMap<ContextField, String> values = new HashMap<>();
+        values.put(ContextField.SERVICE_NAME, service);
+        ContextData data = RequestContextProvider.to(values);
+        assertEquals(data.getServiceName(), service);
+    }
+
+    @Test
+    public void partnerNameInDataWhenSuppliedInValues() {
+        final String partner = "values-partner-name";
+        HashMap<ContextField, String> values = new HashMap<>();
+        values.put(ContextField.PARTNER_NAME, partner);
+        ContextData data = RequestContextProvider.to(values);
+        assertEquals(data.getPartnerName(), partner);
+    }
+
+    @Test
+    public void requestIdInDataWhenSuppliedInValues() {
+        final String request = "values-request-id";
+        HashMap<ContextField, String> values = new HashMap<>();
+        values.put(ContextField.REQUEST_ID, request);
+        ContextData data = RequestContextProvider.to(values);
+        assertEquals(data.getRequestId(), request);
+    }
 }