From 6eceb46537df31756446760484ad1925a997205a Mon Sep 17 00:00:00 2001 From: vempo Date: Fri, 23 Mar 2018 23:10:30 +0300 Subject: Logging refactoring and global context Implemented global context (instance ID, host address). Refactored the logging context API for clarity and separation of concerns. Added unit tests. Fixed Javadoc. Change-Id: I6e29b7b3613aebf23112dc017490ad2828e0fb91 Issue-ID: SDC-772 Signed-off-by: vempo --- .../org/openecomp/sdc/logging/api/AuditData.java | 34 +++--- .../org/openecomp/sdc/logging/api/ContextData.java | 128 +++++++++++++++++++++ .../openecomp/sdc/logging/api/LoggingContext.java | 29 +---- .../sdc/logging/spi/LoggingContextService.java | 12 +- .../openecomp/sdc/logging/api/ContextDataTest.java | 54 +++++++++ .../sdc/logging/api/LoggingContextTest.java | 18 +-- 6 files changed, 217 insertions(+), 58 deletions(-) create mode 100644 openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ContextData.java create mode 100644 openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/ContextDataTest.java (limited to 'openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src') diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/AuditData.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/AuditData.java index fdef45a57f..ecf795b2d5 100644 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/AuditData.java +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/AuditData.java @@ -27,8 +27,9 @@ package org.openecomp.sdc.logging.api; */ public class AuditData { - // A concrete implementation interface was chosen over an interface to enable to gracefully - // add new fields without affecting client code + // A concrete implementation interface was chosen over an interface to enable to gracefully add new fields without + // affecting client code. Also, the builder can be implemented differently if needed, without affecting client code. + // For instance, it may delegate the population and instantiation to a service provider. private final long startTime; private final long endTime; @@ -37,7 +38,7 @@ public class AuditData { private final String responseDescription; private final String clientIpAddress; - AuditData(final AuditDataBuilder builder) { + private AuditData(final AuditDataBuilder builder) { this.startTime = builder.startTime; this.endTime = builder.endTime; this.statusCode = builder.statusCode; @@ -47,7 +48,7 @@ public class AuditData { } /** - * Begin timestamp of an API invocation + * Begin timestamp of an API invocation. * * @return timestamp */ @@ -56,7 +57,7 @@ public class AuditData { } /** - * End timestamp of an API invocation + * End timestamp of an API invocation. * * @return timestamp */ @@ -65,7 +66,7 @@ public class AuditData { } /** - * Result status of an API invocation + * Result status of an API invocation. * * @return protocol and application agnostic status code */ @@ -74,7 +75,7 @@ public class AuditData { } /** - * Application/protocol specific response status of an API invocation + * Application/protocol specific response status of an API invocation. * * @return response code */ @@ -83,7 +84,7 @@ public class AuditData { } /** - * Application/protocol specific response in a human-friendly way + * Application/protocol specific response in a human-friendly way. * * @return human-friendly response description */ @@ -92,7 +93,7 @@ public class AuditData { } /** - * IP address of the invoking client when available + * IP address of the invoking client when available. * * @return IP address */ @@ -102,15 +103,18 @@ public class AuditData { @Override public String toString() { - return "AuditData{startTime=" + startTime + ", endTime=" + endTime + ", statusCode=" + statusCode + - ", responseCode='" + responseCode + ", responseDescription=" + responseDescription + ", clientIpAddress=" - + clientIpAddress + '}'; + return "AuditData{startTime=" + startTime + ", endTime=" + endTime + ", statusCode=" + statusCode + + ", responseCode=" + responseCode + ", responseDescription=" + responseDescription + + ", clientIpAddress=" + clientIpAddress + '}'; } public static AuditDataBuilder builder() { return new AuditDataBuilder(); } + /** + * Fluent API for building audit data. + */ public static class AuditDataBuilder { private long startTime; @@ -123,7 +127,7 @@ public class AuditData { AuditDataBuilder() { /* package-private default constructor to hide the public one */ } /** - * Begin timestamp of an activity being audited + * Begin timestamp of an activity being audited. * * @param startTime local timestamp, usually received from {@link System#currentTimeMillis()} * @return this builder for fluent API @@ -134,7 +138,7 @@ public class AuditData { } /** - * End timestamp of an activity being audited + * End timestamp of an activity being audited. * * @param endTime local timestamp, usually received from {@link System#currentTimeMillis()} * @return this builder for fluent API @@ -191,7 +195,7 @@ public class AuditData { } /** - * Create an instance of {@link AuditData} + * Create an instance of {@link AuditData}. * * @return a populated instance of audit data */ diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ContextData.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ContextData.java new file mode 100644 index 0000000000..ea777d5907 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ContextData.java @@ -0,0 +1,128 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdc.logging.api; + +/** + * Builder to populate logging context data. This includes only data known to an application, and not otherwise + * available to the logging framework. + * + * @author evitaliy + * @since Mar 22, 2018 + */ +public class ContextData { + + private final String requestId; + private final String serviceName; + private final String partnerName; + + private ContextData(final ContextDataBuilder builder) { + this.requestId = builder.requestId; + this.serviceName = builder.serviceName; + this.partnerName = builder.partnerName; + } + + /** + * Uniques request ID received from a calling peer, or created. + * + * @return unique identifier of a request + */ + public String getRequestId() { + return requestId; + } + + /** + * Service, in the context of which logs will be written. + * + * @return a string that identifies an exposed service + */ + public String getServiceName() { + return serviceName; + } + + /** + * Identifies a peer (if any). + * + * @return identification of a calling partner + */ + public String getPartnerName() { + return partnerName; + } + + @Override + public String toString() { + return "ContextData{responseCode=" + requestId + ", responseDescription=" + serviceName + + ", clientIpAddress=" + partnerName + '}'; + } + + public static ContextDataBuilder builder() { + return new ContextDataBuilder(); + } + + /** + * Fluent API for building context data. + */ + public static class ContextDataBuilder { + + private String requestId; + private String serviceName; + private String partnerName; + + ContextDataBuilder() { /* package-private default constructor to hide the public one */ } + + /** + * Unique request ID, most likely propagated via an HTTP header. + * + * @param requestId generated or propagated request ID. + * @return this builder for fluent API + */ + public ContextDataBuilder requestId(final String requestId) { + this.requestId = requestId; + return this; + } + + /** + * Name of a invoked API, by which it can be identified in the application. + * + * @param serviceName human-friendly service identifier + * @return this builder for fluent API + */ + public ContextDataBuilder serviceName(final String serviceName) { + this.serviceName = serviceName; + return this; + } + + /** + * Identifier of a peer calling a service {@link #serviceName(String)}). + * + * @param partnerName an string that is received from a calling peer and can identify it + * @return this builder for fluent API + */ + public ContextDataBuilder partnerName(final String partnerName) { + this.partnerName = partnerName; + return this; + } + + /** + * Create an instance of {@link ContextData}. + * + * @return a populated instance of audit data + */ + public ContextData build() { + return new ContextData(this); + } + } +} diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggingContext.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggingContext.java index 879d9cf098..2dc4afdf58 100644 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggingContext.java +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggingContext.java @@ -16,10 +16,9 @@ package org.openecomp.sdc.logging.api; -import org.openecomp.sdc.logging.spi.LoggingContextService; - import java.util.Objects; import java.util.concurrent.Callable; +import org.openecomp.sdc.logging.spi.LoggingContextService; /** *

Factory to hide a concrete, framework-specific implementation of diagnostic context.

@@ -44,16 +43,8 @@ public class LoggingContext { // prevent instantiation } - public static void putRequestId(String requestId) { - SERVICE.putRequestId(requestId); - } - - public static void putServiceName(String serviceName) { - SERVICE.putServiceName(serviceName); - } - - public static void putPartnerName(String partnerName) { - SERVICE.putPartnerName(partnerName); + public static void put(ContextData contextData) { + SERVICE.put(contextData); } public static void clear() { @@ -71,18 +62,8 @@ public class LoggingContext { private static class NoOpLoggingContextService implements LoggingContextService { @Override - public void putRequestId(String requestId) { - Objects.requireNonNull(requestId, "Request ID cannot be null"); - } - - @Override - public void putServiceName(String serviceName) { - Objects.requireNonNull(serviceName, "Service name cannot be null"); - } - - @Override - public void putPartnerName(String partnerName) { - Objects.requireNonNull(partnerName, "Partner name cannot be null"); + public void put(ContextData contextData) { + Objects.requireNonNull(contextData, "Context data cannot be null"); } @Override diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggingContextService.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggingContextService.java index 07b93c1468..b90ce63982 100644 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggingContextService.java +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/spi/LoggingContextService.java @@ -17,6 +17,7 @@ package org.openecomp.sdc.logging.spi; import java.util.concurrent.Callable; +import org.openecomp.sdc.logging.api.ContextData; /** * Should be used to implement a framework-specific mechanism of managing a per-thread diagnostic context (for instance @@ -33,14 +34,13 @@ import java.util.concurrent.Callable; public interface LoggingContextService { - void putRequestId(String requestId); - - void putServiceName(String serviceName); - - void putPartnerName(String partnerName); + /** + * Put logging data on the context. + */ + void put(ContextData contextData); /** - * Clear logging thread context + * Clear logging thread context. */ void clear(); diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/ContextDataTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/ContextDataTest.java new file mode 100644 index 0000000000..8a173b452a --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/ContextDataTest.java @@ -0,0 +1,54 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdc.logging.api; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +import org.testng.annotations.Test; + +/** + * Unit-testing context data builder. + * + * @author evitaliy + * @since 04 Mar 18 + */ +public class ContextDataTest { + + @Test + public void allPropertiesReadWhenPopulated() { + + final String serviceName = "running-service"; + final String partnerName = "remote-partner"; + final String requestId = "123412341234"; + + ContextData data = ContextData.builder() + .serviceName(serviceName).partnerName(partnerName).requestId(requestId).build(); + + assertEquals(data.getRequestId(), requestId); + assertEquals(data.getServiceName(), serviceName); + assertEquals(data.getPartnerName(), partnerName); + } + + @Test + public void allPropertiesEmptyWhenUnpopulated() { + ContextData data = ContextData.builder().build(); + assertNull(data.getRequestId()); + assertNull(data.getServiceName()); + assertNull(data.getPartnerName()); + } +} \ No newline at end of file diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggingContextTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggingContextTest.java index bfc53a3146..3e7bbe14e0 100644 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggingContextTest.java +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggingContextTest.java @@ -24,7 +24,9 @@ import java.util.concurrent.Callable; import org.testng.annotations.Test; /** - * @author EVITALIY + * Unit-testing default context service implementation. + * + * @author evitaliy * @since 08 Jan 18 */ public class LoggingContextTest { @@ -39,18 +41,8 @@ public class LoggingContextTest { } @Test(expectedExceptions = NullPointerException.class) - public void throwNpeWhenPartnerNameIsNull() { - LoggingContext.putPartnerName(null); - } - - @Test(expectedExceptions = NullPointerException.class) - public void throwNpeWhenServiceNameIsNull() { - LoggingContext.putServiceName(null); - } - - @Test(expectedExceptions = NullPointerException.class) - public void throwNpeWhenRequestIdIsNull() { - LoggingContext.putRequestId(null); + public void throwNpeWhenContextIsNull() { + LoggingContext.put(null); } @Test -- cgit 1.2.3-korg