From 0258442c39183fdd7e4812054d095cafdcab420d Mon Sep 17 00:00:00 2001 From: vempo Date: Wed, 25 Apr 2018 15:28:48 +0300 Subject: Expose tracing context via log context service 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 --- .../org/openecomp/sdc/logging/api/ContextData.java | 25 +++++++++- .../openecomp/sdc/logging/api/LoggingContext.java | 14 +++++- .../sdc/logging/spi/LoggingContextService.java | 5 ++ .../openecomp/sdc/logging/slf4j/MDCDelegate.java | 21 +++++++++ .../sdc/logging/slf4j/RequestContextProvider.java | 13 +++++- .../logging/slf4j/SLF4JLoggingServiceProvider.java | 7 ++- .../sdc/logging/slf4j/LoggingContextTest.java | 30 +++++++++++- .../logging/slf4j/RequestContextProviderTest.java | 53 ++++++++++++++++++---- 8 files changed, 154 insertions(+), 14 deletions(-) (limited to 'openecomp-be') diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ContextData.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ContextData.java index 43f0143774..6eb747f9d9 100644 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ContextData.java +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ContextData.java @@ -16,6 +16,8 @@ package org.openecomp.sdc.logging.api; +import java.util.Objects; + /** * Builder to populate logging context 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() { 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 2dc4afdf58..c17149e98e 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 @@ -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 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 b90ce63982..37e212ac54 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 @@ -39,6 +39,11 @@ public interface LoggingContextService { */ void put(ContextData contextData); + /** + * Return logging context's data. + */ + ContextData get(); + /** * Clear logging thread context. */ diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCDelegate.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCDelegate.java index 8d719a2da8..026d3fa99b 100644 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCDelegate.java +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCDelegate.java @@ -49,6 +49,27 @@ class MDCDelegate { return copy; } + /** + * Reads all context fields from MDC. + */ + static Map get() { + return get(ContextField.values()); + } + + /** + * Reads selected fields from MDC. + */ + static Map get(ContextField... fields) { + + Map 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. diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/RequestContextProvider.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/RequestContextProvider.java index d79771c1c5..40684cc132 100644 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/RequestContextProvider.java +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/RequestContextProvider.java @@ -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 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 values() { 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 1a5d6facc2..9d4d507ac5 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 @@ -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 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 47386d4cf3..c2cef88899 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 @@ -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()); + } + } diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/RequestContextProviderTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/RequestContextProviderTest.java index fa7926acef..a2d36ef085 100644 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/RequestContextProviderTest.java +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/RequestContextProviderTest.java @@ -17,8 +17,10 @@ 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 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 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 values = new HashMap<>(); + values.put(ContextField.REQUEST_ID, request); + ContextData data = RequestContextProvider.to(values); + assertEquals(data.getRequestId(), request); + } } -- cgit 1.2.3-korg