diff options
author | vempo <vitaliy.emporopulo@amdocs.com> | 2018-01-08 20:59:19 +0200 |
---|---|---|
committer | Vitaly Emporopulo <Vitaliy.Emporopulo@amdocs.com> | 2018-01-09 13:41:15 +0000 |
commit | 1c1edf2e7b1ddef504d8b075b2763e0b0d83a2aa (patch) | |
tree | 9860b1a7eae0962db44d61118bae24eea8dc8d8b /openecomp-be | |
parent | 6a96c39bf51c02fef0b35bba8b9e1430a18cbd2b (diff) |
Added logging context service, refactoring
Change-Id: Ib040d4579107b60c8da2c7a6da829f49c1cd8dd4
Issue-ID: SDC-772
Signed-off-by: vempo <vitaliy.emporopulo@amdocs.com>
Diffstat (limited to 'openecomp-be')
31 files changed, 1999 insertions, 1141 deletions
diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggerFactory.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggerFactory.java index 1be2fa21dc..b790a02042 100644 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggerFactory.java +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggerFactory.java @@ -4,9 +4,9 @@ * 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. @@ -16,245 +16,244 @@ package org.openecomp.sdc.logging.api; +import org.openecomp.sdc.logging.provider.LoggerCreationService; + +import java.util.Objects; /** * <a>Factory to hide a concrete, framework-specific implementation of logger creation.</a> * <p>The service used by this factory must implement {@link LoggerCreationService}. If no - * implementation has been configured or could not be instantiated, a <b>no-op logger</b> will be + * implementation has been configured or could be instantiated, a <b>no-op logger</b> will be * used, and <b>no events</b> will be logged. This is done to prevent recursion if attempts are * being made to log exceptions that resulted from logger initialization. </p> * * @author evitaliy - * @see BaseFactory - * @see LoggerCreationService * @since 13/09/2016. + * + * @see ServiceBinder + * @see LoggerCreationService */ -@SuppressWarnings("ThrowableInstanceNeverThrown") -public class LoggerFactory extends BaseFactory { - - private static final LoggerCreationService SERVICE; +public class LoggerFactory { - static { - LoggerCreationService service; + // use the no-op service to prevent recursion in case of an attempt to log an exception as a + // result of a logger initialization error + private static final LoggerCreationService SERVICE = ServiceBinder.getCreationServiceBinding().orElse( + new NoOpLoggerCreationService()); - try { - service = locateService(LoggerCreationService.class); - } catch (Exception ex) { - new RuntimeException("Failed to instantiate logger factory", ex).printStackTrace(); - // use the no-op service to prevent recursion in case of an attempt to log an exception as a - // result of a logger initialization error - service = new NoOpLoggerCreationService(); + private LoggerFactory() { + // prevent instantiation } - SERVICE = service; - } - - public static Logger getLogger(String clazzName) { - return SERVICE.getLogger(clazzName); - } - - public static Logger getLogger(Class<?> clazz) { - return SERVICE.getLogger(clazz); - } - - private static class NoOpLoggerCreationService implements LoggerCreationService { - private static final Logger NO_OP_LOGGER = new NoOpLogger(); - - private static class NoOpLogger implements Logger { - @Override - public String getName() { - return "No-Op Logger"; - } - - @Override - public boolean isMetricsEnabled() { - return false; - } - - @Override - public void metrics(String msg) { - //this is no_op_method - } - - @Override - public void metrics(String msg, Object arg) { - //this is no_op_method - } - - @Override - public void metrics(String msg, Object arg1, Object arg2) { - //this is no_op_method - } - - @Override - public void metrics(String msg, Object... arguments) { - //this is no_op_method - } - - @Override - public void metrics(String msg, Throwable t) { - //this is no_op_method - } - - @Override - public boolean isAuditEnabled() { - return false; - } - - @Override - public void audit(String msg) { - //this is no_op_method - } - - @Override - public void audit(String msg, Object arg) { - //this is no_op_method - } - - @Override - public void audit(String msg, Object arg1, Object arg2) { - //this is no_op_method - } - - @Override - public void audit(String msg, Object... arguments) { - //this is no_op_method - } - - @Override - public void audit(String msg, Throwable t) { - //this is no_op_method - } - - @Override - public boolean isDebugEnabled() { - return false; - } - - @Override - public void debug(String msg) { - //this is no_op_method - } - - @Override - public void debug(String msg, Object arg) { - //this is no_op_method - } - - @Override - public void debug(String msg, Object arg1, Object arg2) { - //this is no_op_method - } - - @Override - public void debug(String msg, Object... arguments) { - //this is no_op_method - } - - @Override - public void debug(String msg, Throwable t) { - //this is no_op_method - } - - @Override - public boolean isInfoEnabled() { - return false; - } - - @Override - public void info(String msg) { - //this is no_op_method - } - - @Override - public void info(String msg, Object arg) { - //this is no_op_method - } - - @Override - public void info(String msg, Object arg1, Object arg2) { - //this is no_op_method - } - - @Override - public void info(String msg, Object... arguments) { - //this is no_op_method - } - - @Override - public void info(String msg, Throwable t) { - //this is no_op_method - } - - @Override - public boolean isWarnEnabled() { - return false; - } - - @Override - public void warn(String msg) { - //this is no_op_method - } - - @Override - public void warn(String msg, Object arg) { - //this is no_op_method - } - - @Override - public void warn(String msg, Object... arguments) { - //this is no_op_method - } - - @Override - public void warn(String msg, Object arg1, Object arg2) { - //this is no_op_method - } - - @Override - public void warn(String msg, Throwable t) { - //this is no_op_method - } - - @Override - public boolean isErrorEnabled() { - return false; - } - - @Override - public void error(String msg) { - //this is no_op_method - } - - @Override - public void error(String msg, Object arg) { - //this is no_op_method - } - - @Override - public void error(String msg, Object arg1, Object arg2) { - //this is no_op_method - } - - @Override - public void error(String msg, Object... arguments) { - //this is no_op_method - } - - @Override - public void error(String msg, Throwable t) { - //this is no_op_method - } + public static Logger getLogger(String clazzName) { + return SERVICE.getLogger(clazzName); } - @Override - public Logger getLogger(String className) { - return NO_OP_LOGGER; + public static Logger getLogger(Class<?> clazz) { + return SERVICE.getLogger(clazz); } - @Override - public Logger getLogger(Class<?> clazz) { - return NO_OP_LOGGER; + private static class NoOpLoggerCreationService implements LoggerCreationService { + + private static final Logger NO_OP_LOGGER = new NoOpLogger(); + + private static class NoOpLogger implements Logger { + + @Override + public String getName() { + return "No-Op Logger"; + } + + @Override + public boolean isMetricsEnabled() { + return false; + } + + @Override + public void metrics(String msg) { + // no-op + } + + @Override + public void metrics(String msg, Object arg) { + // no-op + } + + @Override + public void metrics(String msg, Object arg1, Object arg2) { + // no-op + } + + @Override + public void metrics(String msg, Object... arguments) { + // no-op + } + + @Override + public void metrics(String msg, Throwable t) { + // no-op + } + + @Override + public boolean isAuditEnabled() { + return false; + } + + @Override + public void audit(String msg) { + // no-op + } + + @Override + public void audit(String msg, Object arg) { + // no-op + } + + @Override + public void audit(String msg, Object arg1, Object arg2) { + // no-op + } + + @Override + public void audit(String msg, Object... arguments) { + // no-op + } + + @Override + public void audit(String msg, Throwable t) { + // no-op + } + + @Override + public boolean isDebugEnabled() { + return false; + } + + @Override + public void debug(String msg) { + // no-op + } + + @Override + public void debug(String msg, Object arg) { + // no-op + } + + @Override + public void debug(String msg, Object arg1, Object arg2) { + // no-op + } + + @Override + public void debug(String msg, Object... arguments) { + // no-op + } + + @Override + public void debug(String msg, Throwable t) { + // no-op + } + + @Override + public boolean isInfoEnabled() { + return false; + } + + @Override + public void info(String msg) { + // no-op + } + + @Override + public void info(String msg, Object arg) { + // no-op + } + + @Override + public void info(String msg, Object arg1, Object arg2) { + // no-op + } + + @Override + public void info(String msg, Object... arguments) { + // no-op + } + + @Override + public void info(String msg, Throwable t) { + // no-op + } + + @Override + public boolean isWarnEnabled() { + return false; + } + + @Override + public void warn(String msg) { + // no-op + } + + @Override + public void warn(String msg, Object arg) { + // no-op + } + + @Override + public void warn(String msg, Object... arguments) { + // no-op + } + + @Override + public void warn(String msg, Object arg1, Object arg2) { + // no-op + } + + @Override + public void warn(String msg, Throwable t) { + // no-op + } + + @Override + public boolean isErrorEnabled() { + return false; + } + + @Override + public void error(String msg) { + // no-op + } + + @Override + public void error(String msg, Object arg) { + // no-op + } + + @Override + public void error(String msg, Object arg1, Object arg2) { + // no-op + } + + @Override + public void error(String msg, Object... arguments) { + // no-op + } + + @Override + public void error(String msg, Throwable t) { + // no-op + } + } + + @Override + public Logger getLogger(String className) { + Objects.requireNonNull(className, "Name cannot be null"); + return NO_OP_LOGGER; + } + + @Override + public Logger getLogger(Class<?> clazz) { + Objects.requireNonNull(clazz, "Class cannot be null"); + return NO_OP_LOGGER; + } } - } } 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 new file mode 100644 index 0000000000..542f709074 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggingContext.java @@ -0,0 +1,109 @@ +/* + * 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.api; + +import org.openecomp.sdc.logging.provider.LoggingContextService; + +import java.util.Objects; +import java.util.concurrent.Callable; + +/** + * <a>Factory to hide a concrete, framework-specific implementation of diagnostic context.</a> + * <p>The service used by this factory must implement {@link LoggingContextService}. If no + * implementation has been configured or could be instantiated, a <b>no-op context service</b> will be + * used, and <b>no context</b> will be stored or propagated. No errors will be generated, so that the application can + * still work (albeit without proper logging).</p> + * + * @author evitaliy + * @since 07/01/2018. + * + * @see ServiceBinder + * @see LoggingContextService + */ +public class LoggingContext { + + 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 String get(String key) { + return SERVICE.get(key); + } + + public static void remove(String key) { + SERVICE.remove(key); + } + + public static void clear() { + SERVICE.clear(); + } + + public static Runnable toRunnable(Runnable runnable) { + return SERVICE.toRunnable(runnable); + } + + public static <V> Callable<V> toCallable(Callable<V> callable) { + return SERVICE.toCallable(callable); + } + + 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 + } + + @Override + public String get(String key) { + Objects.requireNonNull(key, KEY_CANNOT_BE_NULL); + return null; + } + + @Override + public void remove(String key) { + Objects.requireNonNull(key, KEY_CANNOT_BE_NULL); + // no-op + } + + @Override + public void clear() { + // no-op + } + + @Override + public Runnable toRunnable(Runnable runnable) { + Objects.requireNonNull(runnable, "Runnable cannot be null"); + return runnable; + } + + @Override + public <V> Callable<V> toCallable(Callable<V> callable) { + Objects.requireNonNull(callable, "Callable cannot be null"); + return callable; + } + } +} diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ServiceBinder.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ServiceBinder.java new file mode 100644 index 0000000000..b16f3944e9 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/ServiceBinder.java @@ -0,0 +1,93 @@ +/* + * 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.api; + +import org.openecomp.sdc.logging.provider.LoggerCreationService; +import org.openecomp.sdc.logging.provider.LoggingContextService; +import org.openecomp.sdc.logging.provider.LoggingServiceProvider; + +import java.util.Iterator; +import java.util.Optional; +import java.util.ServiceLoader; + +/** + * <p>Binds to a concrete implementation of logging services.</p> + * + * <p>In order to use the factory, a particular (e.g. framework-specific) implementation of a service must be + * configured as described in + * <a href="http://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html">java.util.ServiceLoader</a>).</p> + * + * @author evitaliy + * @since 13/09/2016. + * + * @see ServiceLoader + */ + +// No advanced logging can be used here because we don't know +// which underlying implementation will be used +@SuppressWarnings({"UseOfSystemOutOrSystemErr", "squid:S106"}) +class ServiceBinder { + + private static final LoggingServiceProvider PROVIDER = lookupProvider(); + + private ServiceBinder () { + // prevent instantiation + } + + private static LoggingServiceProvider lookupProvider() { + + ServiceLoader<LoggingServiceProvider> loader = ServiceLoader.load(LoggingServiceProvider.class); + Iterator<LoggingServiceProvider> iterator = loader.iterator(); + + if (!iterator.hasNext()) { + System.err.printf("[ERROR] No provider configured for logging services %s. " + + "Default implementation will be used.\n", + LoggingServiceProvider.class.getName()); + return null; + } + + try { + + LoggingServiceProvider provider = iterator.next(); + if (!iterator.hasNext()) { + return provider; + } + + Logger logger = provider.getLogger(ServiceBinder.class); + if (logger.isWarnEnabled()) { + logger.warn("More than one provider for logging services {} found", + LoggingServiceProvider.class.getName()); + } + + return provider; + + } catch (Exception e) { + // don't fail if the provider cannot be instantiated + e.printStackTrace(System.err); + return null; + } + } + + static Optional<LoggingContextService> getContextServiceBinding() { + return Optional.ofNullable(PROVIDER); + } + + static Optional<LoggerCreationService> getCreationServiceBinding() { + return Optional.ofNullable(PROVIDER); + } +} + diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/context/TaskFactory.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/context/TaskFactory.java deleted file mode 100644 index 8621638460..0000000000 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/context/TaskFactory.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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.api.context; - -import org.openecomp.sdc.logging.api.BaseFactory; - -/** - * <p>Should be used to propagate a diagnostic context (for instance <a - * href="http://www.slf4j.org/manual.html#mdc">MDC</a>) to other threads.</p> - * <p>Applicable 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>).</p> - * <p>The service used by this factory must implement {@link ContextPropagationService}.</p> - * - * @author evitaliy - * @see ContextPropagationService - * @since 12/09/2016. - */ -@SuppressWarnings("ThrowableInstanceNeverThrown") -public class TaskFactory extends BaseFactory { - - private static final ContextPropagationService SERVICE; - private static final RuntimeException ERROR; - - static { - - ContextPropagationService service = null; - RuntimeException error = null; - - try { - service = locateService(ContextPropagationService.class); - } catch (Exception ex) { - error = new RuntimeException("Failed to instantiate task factory", ex); - } - - SERVICE = service; - ERROR = error; - } - - /** - * Modify a task so that a diagnostic context is propagated to the thread when the task runs. Done - * in a logging-framework specific way. - * - * @param task any Runnable that will run in a thread - * @return modified (wrapped) original task that runs the same business logic, but also takes care - * of copying the diagnostic context for logging - */ - public static Runnable create(Runnable task) { - - if (SERVICE == null) { - throw ERROR; - } - - return SERVICE.create(task); - } -} diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggerCreationService.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/provider/LoggerCreationService.java index 1d8eda255e..344d23688e 100644 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/LoggerCreationService.java +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/provider/LoggerCreationService.java @@ -14,7 +14,10 @@ * limitations under the License. */ -package org.openecomp.sdc.logging.api; +package org.openecomp.sdc.logging.provider; + +import org.openecomp.sdc.logging.api.Logger; +import org.openecomp.sdc.logging.api.LoggerFactory; /** * diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/provider/LoggingContextService.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/provider/LoggingContextService.java new file mode 100644 index 0000000000..8e725e7cc5 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/provider/LoggingContextService.java @@ -0,0 +1,70 @@ +/* + * 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.provider; + +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>). + * + * @author evitaliy + * @since 07/01/2018. + */ + +public interface LoggingContextService { + + /** + * Allows to store a key-value pair on thread context + */ + void put(String key, String value); + + /** + * 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); + + /** + * Removes a particular key from thread context + */ + void remove(String key); + + /** + * Clear logging thread context + */ + 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. + */ + Runnable toRunnable(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 + */ + <V> Callable<V> toCallable(Callable<V> callable); +} diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/provider/LoggingServiceProvider.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/provider/LoggingServiceProvider.java new file mode 100644 index 0000000000..baf99f0e55 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/provider/LoggingServiceProvider.java @@ -0,0 +1,30 @@ +/* + * 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.provider; + +/** + * <p>From the application code (consumer) perspective, logger creation (factory) and logging context are independent + * services. From the service provider perspective, however, these services are related and must be implemented together + * using the same underlying mechanism. Therefore, the service provider-facing interface combines the two services + * — to eliminate the chance that their implementations don't work well together.</p> + * + * @author EVITALIY + * @since 07 Jan 18 + */ +public interface LoggingServiceProvider extends LoggerCreationService, LoggingContextService { + // single provider must implement two separate consumer services +} diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggerFactoryTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggerFactoryTest.java index 4b3a1ba7c7..9fde4e5e6c 100644 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggerFactoryTest.java +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggerFactoryTest.java @@ -4,9 +4,9 @@ * 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,10 +19,8 @@ package org.openecomp.sdc.logging.api; import org.testng.annotations.Test; import java.lang.reflect.Field; -import java.util.ServiceLoader; import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; /** @@ -31,40 +29,48 @@ import static org.testng.Assert.assertNotNull; */ public class LoggerFactoryTest { - @Test - public void testNoOpLoggerService() throws Exception { + @Test + public void shouldHoldNoOpWhenNoBinding() throws Exception { + + // set up to access the private static field + Field factory = LoggerFactory.class.getDeclaredField("SERVICE"); + factory.setAccessible(true); + Object impl = factory.get(null); - assertFalse(ServiceLoader.load(LoggerCreationService.class).iterator().hasNext()); + assertEquals(impl.getClass().getName(), + "org.openecomp.sdc.logging.api.LoggerFactory$NoOpLoggerCreationService"); + } - LoggerFactory.getLogger(LoggerFactoryTest.class); - Field factory = LoggerFactory.class.getDeclaredField("SERVICE"); - factory.setAccessible(true); - Object impl = factory.get(null); - assertEquals("org.openecomp.sdc.logging.api.LoggerFactory$NoOpLoggerCreationService", - impl.getClass().getName()); - } + @Test + public void verifyNoOpLoggerWorksWhenGotByClass() { + Logger logger = LoggerFactory.getLogger(LoggerFactoryTest.class); + verifyLoggerWorks(logger); + } - @Test - public void testNoOpLoggerByClass() throws Exception { - Logger logger = LoggerFactory.getLogger(LoggerFactoryTest.class); - verifyLogger(logger); - } + @Test + public void verifyNoOpLoggerWorksWhenGotByName() { + Logger logger = LoggerFactory.getLogger(LoggerFactoryTest.class.getName()); + verifyLoggerWorks(logger); + } - @Test - public void testNoOpLoggerByName() throws Exception { - Logger logger = LoggerFactory.getLogger(LoggerFactoryTest.class.getName()); - verifyLogger(logger); - } + @Test(expectedExceptions = NullPointerException.class) + public void throwNpeWhenGetByNameWithNull() { + LoggerFactory.getLogger((String) null); + } - private void verifyLogger(Logger logger) { - assertNotNull(logger); + @Test(expectedExceptions = NullPointerException.class) + public void throwNpeWhenGetByClassWithNull() { + LoggerFactory.getLogger((Class<LoggerFactoryTest>) null); + } - // make sure no exceptions are thrown - logger.error(""); - logger.warn(""); - logger.info(""); - logger.debug(""); - logger.audit(""); - logger.metrics(""); - } + private void verifyLoggerWorks(Logger logger) { + assertNotNull(logger); + // make sure no exceptions are thrown + logger.error(""); + logger.warn(""); + logger.info(""); + logger.debug(""); + logger.audit(""); + logger.metrics(""); + } } 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 new file mode 100644 index 0000000000..7899eebd51 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/LoggingContextTest.java @@ -0,0 +1,101 @@ +/* + * 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.api; + +import org.testng.annotations.Test; + +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; + +/** + * @author EVITALIY + * @since 08 Jan 18 + */ +public class LoggingContextTest { + + @Test + public void shouldHoldNoOpWhenNoBinding() throws Exception { + Field factory = LoggingContext.class.getDeclaredField("SERVICE"); + factory.setAccessible(true); + Object impl = factory.get(null); + assertEquals(impl.getClass().getName(), + "org.openecomp.sdc.logging.api.LoggingContext$NoOpLoggingContextService"); + } + + @Test + public void putDoesNotHaveEffectWhenNoBinding() { + final String key = "Key"; + LoggingContext.put(key, "Dummy"); + assertNull(LoggingContext.get(key)); + } + + @Test(expectedExceptions = NullPointerException.class) + public void throwNpeWhenPutWithKeyNull() { + LoggingContext.put(null, "value"); + } + + @Test + public void getAlwaysReturnsNull() { + assertNull(LoggingContext.get("GetKey")); + } + + @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); + } + + @Test + public void clearDoesNotFail() { + LoggingContext.clear(); + } + + @Test + public void toRunnableReturnsSameInstance() { + Runnable test = () -> { /* do nothing */ }; + assertTrue(test == LoggingContext.toRunnable(test)); + } + + @Test(expectedExceptions = NullPointerException.class) + public void throwNpeWhenToRunnableWithNull() { + LoggingContext.toRunnable(null); + } + + @Test + public void toCallableReturnsSameInstance() { + Callable<String> test = () -> ""; + assertTrue(test == LoggingContext.toCallable(test)); + } + + @Test(expectedExceptions = NullPointerException.class) + public void throwNpeWhenToCallableWithNull() { + LoggingContext.toCallable(null); + } +}
\ No newline at end of file diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/context/ContextPropagationService.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/ServiceBinderTest.java index 7207ea7610..1a5c81d90d 100644 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/api/context/ContextPropagationService.java +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/ServiceBinderTest.java @@ -4,9 +4,9 @@ * 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. @@ -14,17 +14,25 @@ * limitations under the License. */ -package org.openecomp.sdc.logging.api.context; +package org.openecomp.sdc.logging.api; + +import org.testng.annotations.Test; + +import static org.testng.Assert.*; /** - * Should be used to implement a framework-specific mechanism of propagation of a diagnostic context to child threads. - * - * @author evitaliy - * @since 12/09/2016. + * @author EVITALIY + * @since 08 Jan 18 */ +public class ServiceBinderTest { -@FunctionalInterface -public interface ContextPropagationService { + @Test + public void makeSureNoContextServiceBinding() { + assertFalse(ServiceBinder.getContextServiceBinding().isPresent()); + } - Runnable create(Runnable task); -} + @Test + public void makeSureNoCreationServiceBinding() { + assertFalse(ServiceBinder.getCreationServiceBinding().isPresent()); + } +}
\ 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/context/TaskFactoryTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/context/TaskFactoryTest.java deleted file mode 100644 index f5c2187024..0000000000 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/api/context/TaskFactoryTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.openecomp.sdc.logging.api.context; - -import org.testng.annotations.Test; - -import java.util.ServiceLoader; - -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertTrue; - -/** - * @author evitaliy - * @since 14/09/2016. - */ -public class TaskFactoryTest { - - @Test(expectedExceptions = RuntimeException.class) - public void testNoImplementation() throws Exception { - - assertFalse(ServiceLoader.load(ContextPropagationService.class).iterator().hasNext()); - - try { - TaskFactory.create(() -> { - }); - } catch (RuntimeException e) { - Throwable cause = e.getCause(); - assertNotNull(cause); - assertTrue(cause.getMessage().contains(ContextPropagationService.class.getName())); - throw e; - } - } -}
\ No newline at end of file diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/SLF4JLoggerCreationService.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/SLF4JLoggerCreationService.java deleted file mode 100644 index bc896a91fc..0000000000 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/SLF4JLoggerCreationService.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * 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 org.openecomp.sdc.logging.api.Logger; -import org.openecomp.sdc.logging.api.LoggerCreationService; -import org.slf4j.LoggerFactory; - -/** - * @author evitaliy - * @since 13/09/2016. - */ -public class SLF4JLoggerCreationService implements LoggerCreationService { - - @Override - public Logger getLogger(String className) { - return new SLF4JWrapper(className); - } - - @Override - public Logger getLogger(Class<?> clazz) { - return new SLF4JWrapper(clazz); - } - - private class SLF4JWrapper implements Logger { - - private final org.slf4j.Logger logger; - - SLF4JWrapper(Class<?> clazz) { - logger = LoggerFactory.getLogger(clazz); - } - - SLF4JWrapper(String className) { - logger = LoggerFactory.getLogger(className); - } - - @Override - public String getName() { - return logger.getName(); - } - - @Override - public boolean isMetricsEnabled() { - return logger.isInfoEnabled(Markers.METRICS); - } - - @Override - public void metrics(String msg) { - logger.info(Markers.METRICS, msg); - } - - @Override - public void metrics(String msg, Object arg) { - logger.info(Markers.METRICS, msg, arg); - } - - @Override - public void metrics(String msg, Object arg1, Object arg2) { - logger.info(Markers.METRICS, msg, arg1, arg2); - } - - @Override - public void metrics(String msg, Object... arguments) { - logger.info(Markers.METRICS, msg, arguments); - } - - @Override - public void metrics(String msg, Throwable t) { - logger.info(Markers.METRICS, msg, t); - } - - @Override - public boolean isAuditEnabled() { - return logger.isInfoEnabled(Markers.AUDIT); - } - - @Override - public void audit(String msg) { - logger.info(Markers.AUDIT, msg); - } - - @Override - public void audit(String msg, Object arg) { - logger.info(Markers.AUDIT, msg, arg); - } - - @Override - public void audit(String msg, Object arg1, Object arg2) { - logger.info(Markers.AUDIT, msg, arg1, arg2); - } - - @Override - public void audit(String msg, Object... arguments) { - logger.info(Markers.AUDIT, msg, arguments); - } - - @Override - public void audit(String msg, Throwable t) { - logger.info(Markers.AUDIT, msg, t); - } - - @Override - public boolean isDebugEnabled() { - return logger.isDebugEnabled(); - } - - @Override - public void debug(String msg) { - logger.debug(msg); - } - - @Override - public void debug(String format, Object arg) { - logger.debug(format, arg); - } - - @Override - public void debug(String format, Object arg1, Object arg2) { - logger.debug(format, arg1, arg2); - } - - @Override - public void debug(String format, Object... arguments) { - logger.debug(format, arguments); - } - - @Override - public void debug(String msg, Throwable t) { - logger.debug(msg, t); - } - - @Override - public boolean isInfoEnabled() { - return logger.isInfoEnabled(); - } - - @Override - public void info(String msg) { - logger.info(msg); - } - - @Override - public void info(String format, Object arg) { - logger.info(format, arg); - } - - @Override - public void info(String format, Object arg1, Object arg2) { - logger.info(format, arg1, arg2); - } - - @Override - public void info(String format, Object... arguments) { - logger.info(format, arguments); - } - - @Override - public void info(String msg, Throwable t) { - logger.info(msg, t); - } - - @Override - public boolean isWarnEnabled() { - return logger.isWarnEnabled(); - } - - @Override - public void warn(String msg) { - logger.warn(msg); - } - - @Override - public void warn(String format, Object arg) { - logger.warn(format, arg); - } - - @Override - public void warn(String format, Object... arguments) { - logger.warn(format, arguments); - } - - @Override - public void warn(String format, Object arg1, Object arg2) { - logger.warn(format, arg1, arg2); - } - - @Override - public void warn(String msg, Throwable t) { - logger.warn(msg, t); - } - - @Override - public boolean isErrorEnabled() { - return logger.isErrorEnabled(); - } - - @Override - public void error(String msg) { - logger.error(msg); - } - - @Override - public void error(String format, Object arg) { - logger.error(format, arg); - } - - @Override - public void error(String format, Object arg1, Object arg2) { - logger.error(format, arg1, arg2); - } - - @Override - public void error(String format, Object... arguments) { - logger.error(format, arguments); - } - - @Override - public void error(String msg, Throwable t) { - logger.error(msg, t); - } - } -} diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/context/MDCPropagationService.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/context/MDCPropagationService.java deleted file mode 100644 index 131b8db263..0000000000 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/context/MDCPropagationService.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.context; - -import org.openecomp.sdc.logging.api.context.ContextPropagationService; -import org.slf4j.MDC; - -import java.util.Map; - -/** - * Propagates the <a href="http://www.slf4j.org/manual.html#mdc">SLF4J Mapped Diagnostic Context (MDC)</a> - * of a thread onto a runnable created by that thread, so that the context is available when the runnable is executed - * in a new thread. - * - * @author evitaliy - * @since 12/09/2016. - */ -public class MDCPropagationService implements ContextPropagationService { - - public Runnable create(Runnable task) { - return new MDCCopyingWrapper(task); - } - - private static class MDCCopyingWrapper implements Runnable { - - private final Runnable task; - private final Map<String, String> context; - - private MDCCopyingWrapper(Runnable task) { - this.task = task; - this.context = MDC.getCopyOfContextMap(); - } - - @Override - public void run() { - - Map<String, String> oldContext = MDC.getCopyOfContextMap(); - replaceMDC(this.context); - - try { - task.run(); - } finally { - replaceMDC(oldContext); - } - } - - private static void replaceMDC(Map<String, String> context) { - - if (context == null) { - MDC.clear(); - } else { - MDC.setContextMap(context); - } - } - } -} diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/logback/EventTypeDiscriminator.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/logback/EventTypeDiscriminator.java index 97fc2871de..b6f8cfa8ff 100644 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/logback/EventTypeDiscriminator.java +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/logback/EventTypeDiscriminator.java @@ -19,7 +19,7 @@ package org.openecomp.sdc.logging.logback; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.sift.AbstractDiscriminator; -import org.openecomp.sdc.logging.Markers; +import org.openecomp.sdc.logging.slf4j.Markers; import org.slf4j.Marker; /** 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 new file mode 100644 index 0000000000..a963542906 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/BaseMDCCopyingWrapper.java @@ -0,0 +1,53 @@ +/* + * 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 org.slf4j.MDC; + +import java.util.Map; + +/** + * @author EVITALIY + * @since 08 Jan 18 + */ +abstract class BaseMDCCopyingWrapper { + + private final Map<String, String> context; + + BaseMDCCopyingWrapper() { + this.context = MDC.getCopyOfContextMap(); + } + + final Map<String, String> replace() { + Map<String, String> old = MDC.getCopyOfContextMap(); + replaceMDC(this.context); + return old; + } + + final void revert(Map<String, String> old) { + replaceMDC(old); + } + + private static void replaceMDC(Map<String, String> context) { + + if (context == null) { + MDC.clear(); + } else { + MDC.setContextMap(context); + } + } +} 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 new file mode 100644 index 0000000000..9cb67dee4c --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCCallableWrapper.java @@ -0,0 +1,46 @@ +/* + * 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 java.util.Map; +import java.util.concurrent.Callable; + +/** + * @author EVITALIY + * @since 08 Jan 18 + */ +class MDCCallableWrapper<V> extends BaseMDCCopyingWrapper implements Callable<V> { + + private final Callable<V> task; + + MDCCallableWrapper(Callable<V> task) { + super(); + this.task = task; + } + + @Override + public V call() throws Exception { + + Map<String, String> oldContext = replace(); + + try { + return task.call(); + } finally { + revert(oldContext); + } + } +} 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 new file mode 100644 index 0000000000..f1a6986fec --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/MDCRunnableWrapper.java @@ -0,0 +1,45 @@ +/* + * 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 java.util.Map; + +/** + * @author EVITALIY + * @since 08 Jan 18 + */ +class MDCRunnableWrapper extends BaseMDCCopyingWrapper implements Runnable { + + private final Runnable task; + + MDCRunnableWrapper(Runnable task) { + super(); + this.task = task; + } + + @Override + public void run() { + + Map<String, String> oldContext = replace(); + + try { + task.run(); + } finally { + revert(oldContext); + } + } +} diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/Markers.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/Markers.java index 1416a9651f..7d2d846097 100644 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/Markers.java +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/Markers.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.openecomp.sdc.logging; +package org.openecomp.sdc.logging.slf4j; import org.slf4j.Marker; import org.slf4j.MarkerFactory; @@ -41,6 +41,10 @@ import org.slf4j.MarkerFactory; */ public class Markers { + private Markers() { + // prevent instantiation + } + public static final Marker AUDIT = MarkerFactory.getMarker("AUDIT"); public static final Marker METRICS = MarkerFactory.getMarker("METRICS"); } 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 new file mode 100644 index 0000000000..5d223450bd --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggerWrapper.java @@ -0,0 +1,222 @@ +/* + * 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 org.openecomp.sdc.logging.api.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author EVITALIY + * @since 08 Jan 18 + */ +class SLF4JLoggerWrapper implements Logger { + + private final org.slf4j.Logger logger; + + SLF4JLoggerWrapper(Class<?> clazz) { + logger = LoggerFactory.getLogger(clazz); + } + + SLF4JLoggerWrapper(String className) { + logger = LoggerFactory.getLogger(className); + } + + @Override + public String getName() { + return logger.getName(); + } + + @Override + public boolean isMetricsEnabled() { + return logger.isInfoEnabled(Markers.METRICS); + } + + @Override + public void metrics(String msg) { + logger.info(Markers.METRICS, msg); + } + + @Override + public void metrics(String msg, Object arg) { + logger.info(Markers.METRICS, msg, arg); + } + + @Override + public void metrics(String msg, Object arg1, Object arg2) { + logger.info(Markers.METRICS, msg, arg1, arg2); + } + + @Override + public void metrics(String msg, Object... arguments) { + logger.info(Markers.METRICS, msg, arguments); + } + + @Override + public void metrics(String msg, Throwable t) { + logger.info(Markers.METRICS, msg, t); + } + + @Override + public boolean isAuditEnabled() { + return logger.isInfoEnabled(Markers.AUDIT); + } + + @Override + public void audit(String msg) { + logger.info(Markers.AUDIT, msg); + } + + @Override + public void audit(String msg, Object arg) { + logger.info(Markers.AUDIT, msg, arg); + } + + @Override + public void audit(String msg, Object arg1, Object arg2) { + logger.info(Markers.AUDIT, msg, arg1, arg2); + } + + @Override + public void audit(String msg, Object... arguments) { + logger.info(Markers.AUDIT, msg, arguments); + } + + @Override + public void audit(String msg, Throwable t) { + logger.info(Markers.AUDIT, msg, t); + } + + @Override + public boolean isDebugEnabled() { + return logger.isDebugEnabled(); + } + + @Override + public void debug(String msg) { + logger.debug(msg); + } + + @Override + public void debug(String format, Object arg) { + logger.debug(format, arg); + } + + @Override + public void debug(String format, Object arg1, Object arg2) { + logger.debug(format, arg1, arg2); + } + + @Override + public void debug(String format, Object... arguments) { + logger.debug(format, arguments); + } + + @Override + public void debug(String msg, Throwable t) { + logger.debug(msg, t); + } + + @Override + public boolean isInfoEnabled() { + return logger.isInfoEnabled(); + } + + @Override + public void info(String msg) { + logger.info(msg); + } + + @Override + public void info(String format, Object arg) { + logger.info(format, arg); + } + + @Override + public void info(String format, Object arg1, Object arg2) { + logger.info(format, arg1, arg2); + } + + @Override + public void info(String format, Object... arguments) { + logger.info(format, arguments); + } + + @Override + public void info(String msg, Throwable t) { + logger.info(msg, t); + } + + @Override + public boolean isWarnEnabled() { + return logger.isWarnEnabled(); + } + + @Override + public void warn(String msg) { + logger.warn(msg); + } + + @Override + public void warn(String format, Object arg) { + logger.warn(format, arg); + } + + @Override + public void warn(String format, Object... arguments) { + logger.warn(format, arguments); + } + + @Override + public void warn(String format, Object arg1, Object arg2) { + logger.warn(format, arg1, arg2); + } + + @Override + public void warn(String msg, Throwable t) { + logger.warn(msg, t); + } + + @Override + public boolean isErrorEnabled() { + return logger.isErrorEnabled(); + } + + @Override + public void error(String msg) { + logger.error(msg); + } + + @Override + public void error(String format, Object arg) { + logger.error(format, arg); + } + + @Override + public void error(String format, Object arg1, Object arg2) { + logger.error(format, arg1, arg2); + } + + @Override + public void error(String format, Object... arguments) { + logger.error(format, arguments); + } + + @Override + public void error(String msg, Throwable t) { + logger.error(msg, t); + } +} 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 new file mode 100644 index 0000000000..015875bdc8 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/java/org/openecomp/sdc/logging/slf4j/SLF4JLoggingServiceProvider.java @@ -0,0 +1,85 @@ +/* + * 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 org.openecomp.sdc.logging.api.Logger; +import org.openecomp.sdc.logging.provider.LoggingServiceProvider; +import org.slf4j.MDC; + +import java.util.Objects; +import java.util.concurrent.Callable; + +/** + * @author evitaliy + * @since 13/09/2016. + */ +public class SLF4JLoggingServiceProvider implements LoggingServiceProvider { + + private static final String KEY_CANNOT_BE_NULL = "Key cannot be null"; + + @Override + public Logger getLogger(String className) { + Objects.requireNonNull(className, "Name cannot be null"); + return new SLF4JLoggerWrapper(className); + } + + @Override + public Logger getLogger(Class<?> clazz) { + Objects.requireNonNull(clazz, "Class cannot be null"); + return new SLF4JLoggerWrapper(clazz); + } + + @Override + public void put(String key, String value) { + Objects.requireNonNull(key, KEY_CANNOT_BE_NULL); + MDC.put(key, value); + } + + @Override + public String get(String key) { + Objects.requireNonNull(key, KEY_CANNOT_BE_NULL); + return MDC.get(key); + } + + @Override + public void remove(String key) { + Objects.requireNonNull(key, KEY_CANNOT_BE_NULL); + MDC.remove(key); + } + + @Override + public void clear() { + MDC.clear(); + } + + @Override + public Runnable toRunnable(Runnable runnable) { + Objects.requireNonNull(runnable, "Runnable cannot be null"); + return new MDCRunnableWrapper(runnable); + } + + @Override + public <V> Callable<V> toCallable(Callable<V> callable) { + Objects.requireNonNull(callable, "Runnable cannot be null"); + return new MDCCallableWrapper<>(callable); + } + + @Override + public String toString() { + return this.getClass().getName(); + } +} diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/resources/META-INF/services/org.openecomp.sdc.logging.provider.LoggingServiceProvider b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/resources/META-INF/services/org.openecomp.sdc.logging.provider.LoggingServiceProvider new file mode 100644 index 0000000000..7e438b7a49 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/main/resources/META-INF/services/org.openecomp.sdc.logging.provider.LoggingServiceProvider @@ -0,0 +1 @@ +org.openecomp.sdc.logging.slf4j.SLF4JLoggingServiceProvider
\ No newline at end of file diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/LoggerFactoryTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/LoggerFactoryTest.java deleted file mode 100644 index fe81a4626a..0000000000 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/LoggerFactoryTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.openecomp.sdc.logging; - -import org.openecomp.sdc.logging.api.LoggerFactory; -import org.testng.annotations.Test; - -import java.lang.reflect.Field; - -import static org.testng.Assert.assertEquals; - -/** - * @author evitaliy - * @since 12/09/2016. - */ -public class LoggerFactoryTest { - - @Test - public void testCreate() throws Exception { - // test that the service loader loads the right implementation - LoggerFactory.getLogger(LoggerFactoryTest.class); - Field factory = LoggerFactory.class.getDeclaredField("SERVICE"); - factory.setAccessible(true); - Object implementation = factory.get(null); - assertEquals(SLF4JLoggerCreationService.class, implementation.getClass()); - } -}
\ No newline at end of file diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/RoutingTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/RoutingTest.java index fd3f5909d4..adc1d8e71d 100644 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/RoutingTest.java +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/RoutingTest.java @@ -22,6 +22,7 @@ import ch.qos.logback.classic.sift.SiftingAppender; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.AppenderBase; import org.openecomp.sdc.logging.logback.EventTypeDiscriminator; +import org.openecomp.sdc.logging.slf4j.Markers; import org.slf4j.LoggerFactory; import org.testng.Assert; import org.testng.annotations.BeforeClass; @@ -48,7 +49,7 @@ public class RoutingTest { private static final String METRICS = "Metrics"; private Logger logger; - private Map<String, TestAppender> result = new ConcurrentHashMap<>(); + private final Map<String, TestAppender> result = new ConcurrentHashMap<>(); @BeforeClass public void setUp() { @@ -137,14 +138,14 @@ public class RoutingTest { */ private static class TestAppender extends AppenderBase<ILoggingEvent> { - private List<ILoggingEvent> events = Collections.synchronizedList(new ArrayList<>(10)); + private final List<ILoggingEvent> events = Collections.synchronizedList(new ArrayList<>(10)); @Override protected void append(ILoggingEvent event) { this.events.add(event); } - public boolean contains(Predicate<ILoggingEvent> predicate) { + boolean contains(Predicate<ILoggingEvent> predicate) { return events.stream().anyMatch(predicate); } } diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/context/MDCPropagationFactoryTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/context/MDCPropagationFactoryTest.java deleted file mode 100644 index 1fda9e85b3..0000000000 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/context/MDCPropagationFactoryTest.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * 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.context; - -import org.slf4j.MDC; -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 - * @since 12/09/2016. - */ -public class MDCPropagationFactoryTest { - - // Disable if an old version of MDC implementation is being used. - // MDCPropagationFactory should be used when MDC is not propagated to child threads. - // See https://jira.qos.ch/browse/LOGBACK-422 and https://jira.qos.ch/browse/LOGBACK-624 - private static final boolean ENABLED = false; - - @Test(enabled = ENABLED) - public void testNoPropagation() throws InterruptedException { - - String uuid = UUID.randomUUID().toString(); - AtomicBoolean complete = new AtomicBoolean(false); - MDC.put("data", uuid); - - Runnable runnable = () -> { - assertNull(MDC.get("data"), "Data unexpectedly copied to a child thread. " + - "Are you using an old version of MDC implementation (e.g. logback)?"); - complete.set(true); - }; - - Thread thread = new Thread(runnable); - thread.start(); - thread.join(); - - assertEquals(MDC.get("data"), uuid, "Expected data to be retained in this thread"); - assertTrue(complete.get(), "Expected the inner thread to run"); - } - - @Test(enabled = ENABLED) - public void testPropagation() throws InterruptedException { - - String uuid = UUID.randomUUID().toString(); - AtomicBoolean complete = new AtomicBoolean(false); - MDC.put("data", uuid); - - MDCPropagationService factory = new MDCPropagationService(); - Runnable runnable = factory.create(() -> { - assertEquals(MDC.get("data"), uuid, "Expected data to be propagated to the child thread's MDC"); - complete.set(true); - }); - - Thread thread = new Thread(runnable); - thread.start(); - - thread.join(); - - assertEquals(MDC.get("data"), uuid, "Expected data to be retained in this thread"); - assertTrue(complete.get(), "Expected the inner thread to run"); - } - - @Test(enabled = ENABLED) - public void testReplacement() throws InterruptedException { - - String innerUuid = UUID.randomUUID().toString(); - AtomicBoolean innerComplete = new AtomicBoolean(false); - AtomicBoolean outerComplete = new AtomicBoolean(false); - - MDC.put("data", innerUuid); - - MDCPropagationService factory = new MDCPropagationService(); - - // should run with the context of main thread - Runnable inner = factory.create(() -> { - assertEquals(MDC.get("data"), innerUuid, "Expected data to be propagated to the child thread's MDC"); - innerComplete.set(true); - }); - - // pushes its own context, but runs the inner runnable - Runnable outer = () -> { - String outerUuid = UUID.randomUUID().toString(); - MDC.put("data", outerUuid); - inner.run(); - assertEquals(MDC.get("data"), outerUuid, "Expected MDC data to be replaced with stored data"); - outerComplete.set(true); - }; - - - Thread thread = new Thread(outer); - thread.start(); - thread.join(); - - assertEquals(MDC.get("data"), innerUuid, "Expected data to be retained in this thread"); - assertTrue(outerComplete.get(), "Expected the outer thread to run"); - assertTrue(innerComplete.get(), "Expected the inner thread to run"); - } - - @Test(enabled = ENABLED) - public void testEmpty() throws InterruptedException { - - final AtomicBoolean complete = new AtomicBoolean(false); - - MDC.remove("data"); - assertNull(MDC.get("data"), "Expected MDC data to be empty"); - - MDCPropagationService factory = new MDCPropagationService(); - Runnable runnable = factory.create(() -> { - assertNull(MDC.get("data"), "Expected MDC data to be empty"); - complete.set(true); - }); - - Thread thread = new Thread(runnable); - thread.start(); - thread.join(); - - assertNull(MDC.get("data"), "Expected MDC data to be empty"); - assertTrue(complete.get(), "Expected the inner thread to run"); - } - - @Test(enabled = ENABLED) - public void testCleanup() throws Exception { - - String innerUuid = UUID.randomUUID().toString(); - AtomicBoolean innerComplete = new AtomicBoolean(false); - AtomicBoolean outerComplete = new AtomicBoolean(false); - - MDC.put("data", innerUuid); - - MDCPropagationService factory = new MDCPropagationService(); - - // should run with the context of main thread - Runnable inner = factory.create(() -> { - assertEquals(MDC.get("data"), innerUuid, "Expected data to be propagated to the child thread's MDC"); - innerComplete.set(true); - }); - - // pushes its own context, but runs the inner runnable - Runnable outer = () -> { - assertNull(MDC.get("data"), "Expected MDC data not to be copied to this thread"); - inner.run(); - assertNull(MDC.get("data"), "Expected MDC data to remain empty in this thread"); - outerComplete.set(true); - }; - - Thread thread = new Thread(outer); - thread.start(); - thread.join(); - - assertEquals(MDC.get("data"), innerUuid, "Expected MDC data to be retained in parent thread"); - assertTrue(outerComplete.get(), "Expected the outer thread to run"); - assertTrue(innerComplete.get(), "Expected the inner thread to run"); - } - - @Test(enabled = ENABLED) - public void testCleanupAfterError() throws Exception { - - String innerUuid = UUID.randomUUID().toString(); - AtomicBoolean innerComplete = new AtomicBoolean(false); - AtomicBoolean outerComplete = new AtomicBoolean(false); - AtomicBoolean exceptionThrown = new AtomicBoolean(false); - - MDC.put("data", innerUuid); - - MDCPropagationService factory = new MDCPropagationService(); - - // should run with the context of main thread - Runnable inner = factory.create(() -> { - assertEquals(MDC.get("data"), innerUuid, "Expected data to be propagated to the child thread's MDC"); - innerComplete.set(true); - throw new RuntimeException(); - }); - - // pushes its own context, but runs the inner runnable - Runnable outer = () -> { - - String outerUuid = UUID.randomUUID().toString(); - MDC.put("data", outerUuid); - assertEquals(MDC.get("data"), outerUuid, "Expected MDC data to be populated in this thread"); - - try { - inner.run(); - } catch (RuntimeException e) { - exceptionThrown.set(true); - } finally { - assertEquals(MDC.get("data"), outerUuid, "Expected MDC data to be reverted even in case of exception"); - outerComplete.set(true); - } - }; - - Thread thread = new Thread(outer); - thread.start(); - thread.join(); - - assertEquals(MDC.get("data"), innerUuid, "Expected MDC data to be retained in parent thread"); - assertTrue(outerComplete.get(), "Expected the outer thread to run"); - assertTrue(innerComplete.get(), "Expected the inner thread to run"); - assertTrue(exceptionThrown.get(), "Expected the inner class to throw exception"); - } - -} diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/context/TaskFactoryTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/context/TaskFactoryTest.java deleted file mode 100644 index dad60d44d5..0000000000 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/context/TaskFactoryTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.openecomp.sdc.logging.context; - -import org.openecomp.sdc.logging.api.context.TaskFactory; -import org.testng.annotations.Test; - -import java.lang.reflect.Field; - -import static org.testng.Assert.assertEquals; - -/** - * @author evitaliy - * @since 12/09/2016. - */ -public class TaskFactoryTest { - - @Test - public void testCreate() throws Exception { - // test that the service loader loads the right implementation - TaskFactory.create(() -> { - }); - Field factory = TaskFactory.class.getDeclaredField("SERVICE"); - factory.setAccessible(true); - Object implementation = factory.get(null); - assertEquals(MDCPropagationService.class, implementation.getClass()); - } -}
\ No newline at end of file diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/logback/EventTypeDiscriminatorTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/logback/EventTypeDiscriminatorTest.java index 9885fc32b8..050c583346 100644 --- a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/logback/EventTypeDiscriminatorTest.java +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/logback/EventTypeDiscriminatorTest.java @@ -4,9 +4,9 @@ * 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. @@ -18,7 +18,7 @@ package org.openecomp.sdc.logging.logback; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.spi.LoggingEvent; -import org.openecomp.sdc.logging.Markers; +import org.openecomp.sdc.logging.slf4j.Markers; import org.slf4j.MarkerFactory; import org.testng.annotations.Test; @@ -30,187 +30,187 @@ import static org.testng.Assert.assertEquals; */ public class EventTypeDiscriminatorTest { - private static final String DEBUG = "Debug"; - private static final String ERROR = "Error"; - - @Test - public void testGetDefaultDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - assertEquals(discriminator.getDiscriminatingValue(event), DEBUG); - } - - @Test - public void testGetErrorDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.ERROR); - assertEquals(discriminator.getDiscriminatingValue(event), ERROR); - } - - @Test - public void testGetWarnDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.WARN); - assertEquals(discriminator.getDiscriminatingValue(event), ERROR); - } - - @Test - public void testGetInfoDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.INFO); - assertEquals(discriminator.getDiscriminatingValue(event), ERROR); - } - - @Test - public void testGetTraceDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.TRACE); - assertEquals(discriminator.getDiscriminatingValue(event), DEBUG); - } - - @Test - public void testGetErrorWithAuditDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.ERROR); - event.setMarker(Markers.AUDIT); - assertEquals(discriminator.getDiscriminatingValue(event), ERROR); - } - - @Test - public void testGetErrorWithMetricsDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.ERROR); - event.setMarker(Markers.METRICS); - assertEquals(discriminator.getDiscriminatingValue(event), ERROR); - } - - @Test - public void testGetWarnWithAuditDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.WARN); - event.setMarker(Markers.AUDIT); - assertEquals(discriminator.getDiscriminatingValue(event), ERROR); - } - - @Test - public void testGetWarnWithMetricsDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.WARN); - event.setMarker(Markers.METRICS); - assertEquals(discriminator.getDiscriminatingValue(event), ERROR); - } - - @Test - public void testGetDebugWithAuditDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.DEBUG); - event.setMarker(Markers.AUDIT); - assertEquals(discriminator.getDiscriminatingValue(event), DEBUG); - } - - @Test - public void testGetDebugWithMetricsDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.DEBUG); - event.setMarker(Markers.METRICS); - assertEquals(discriminator.getDiscriminatingValue(event), DEBUG); - } - - @Test - public void testGetTraceWithAuditDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.TRACE); - event.setMarker(Markers.AUDIT); - assertEquals(discriminator.getDiscriminatingValue(event), DEBUG); - } - - @Test - public void testGetTraceWithMetricsDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.TRACE); - event.setMarker(Markers.METRICS); - assertEquals(discriminator.getDiscriminatingValue(event), DEBUG); - } - - @Test - public void testGetErrorWithMarkerDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.ERROR); - event.setMarker(MarkerFactory.getMarker("Dummy")); - assertEquals(discriminator.getDiscriminatingValue(event), ERROR); - } - - @Test - public void testGetWarnWithMarkerDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.WARN); - event.setMarker(MarkerFactory.getMarker("Dummy")); - assertEquals(discriminator.getDiscriminatingValue(event), ERROR); - } - - @Test - public void testGetDebugWithMarkerDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.DEBUG); - event.setMarker(MarkerFactory.getMarker("Dummy")); - assertEquals(discriminator.getDiscriminatingValue(event), DEBUG); - } - - @Test - public void testGetTraceWithMarkerDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.TRACE); - event.setMarker(MarkerFactory.getMarker("Dummy")); - assertEquals(discriminator.getDiscriminatingValue(event), DEBUG); - } - - @Test - public void testGetInfoWithMarkerDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.INFO); - event.setMarker(MarkerFactory.getMarker("Dummy")); - assertEquals(discriminator.getDiscriminatingValue(event), ERROR); - } - - @Test - public void testGetAuditDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.INFO); - event.setMarker(Markers.AUDIT); - assertEquals(discriminator.getDiscriminatingValue(event), "Audit"); - } - - @Test - public void testGetMetricsMarkerDiscriminatingValue() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - LoggingEvent event = new LoggingEvent(); - event.setLevel(Level.INFO); - event.setMarker(Markers.METRICS); - assertEquals(discriminator.getDiscriminatingValue(event), "Metrics"); - } - - @Test - public void testGetKey() throws Exception { - EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); - assertEquals("eventType", discriminator.getKey()); - } + private static final String DEBUG = "Debug"; + private static final String ERROR = "Error"; + + @Test + public void testGetDefaultDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + assertEquals(discriminator.getDiscriminatingValue(event), DEBUG); + } + + @Test + public void testGetErrorDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.ERROR); + assertEquals(discriminator.getDiscriminatingValue(event), ERROR); + } + + @Test + public void testGetWarnDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.WARN); + assertEquals(discriminator.getDiscriminatingValue(event), ERROR); + } + + @Test + public void testGetInfoDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.INFO); + assertEquals(discriminator.getDiscriminatingValue(event), ERROR); + } + + @Test + public void testGetTraceDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.TRACE); + assertEquals(discriminator.getDiscriminatingValue(event), DEBUG); + } + + @Test + public void testGetErrorWithAuditDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.ERROR); + event.setMarker(Markers.AUDIT); + assertEquals(discriminator.getDiscriminatingValue(event), ERROR); + } + + @Test + public void testGetErrorWithMetricsDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.ERROR); + event.setMarker(Markers.METRICS); + assertEquals(discriminator.getDiscriminatingValue(event), ERROR); + } + + @Test + public void testGetWarnWithAuditDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.WARN); + event.setMarker(Markers.AUDIT); + assertEquals(discriminator.getDiscriminatingValue(event), ERROR); + } + + @Test + public void testGetWarnWithMetricsDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.WARN); + event.setMarker(Markers.METRICS); + assertEquals(discriminator.getDiscriminatingValue(event), ERROR); + } + + @Test + public void testGetDebugWithAuditDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.DEBUG); + event.setMarker(Markers.AUDIT); + assertEquals(discriminator.getDiscriminatingValue(event), DEBUG); + } + + @Test + public void testGetDebugWithMetricsDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.DEBUG); + event.setMarker(Markers.METRICS); + assertEquals(discriminator.getDiscriminatingValue(event), DEBUG); + } + + @Test + public void testGetTraceWithAuditDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.TRACE); + event.setMarker(Markers.AUDIT); + assertEquals(discriminator.getDiscriminatingValue(event), DEBUG); + } + + @Test + public void testGetTraceWithMetricsDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.TRACE); + event.setMarker(Markers.METRICS); + assertEquals(discriminator.getDiscriminatingValue(event), DEBUG); + } + + @Test + public void testGetErrorWithMarkerDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.ERROR); + event.setMarker(MarkerFactory.getMarker("Dummy")); + assertEquals(discriminator.getDiscriminatingValue(event), ERROR); + } + + @Test + public void testGetWarnWithMarkerDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.WARN); + event.setMarker(MarkerFactory.getMarker("Dummy")); + assertEquals(discriminator.getDiscriminatingValue(event), ERROR); + } + + @Test + public void testGetDebugWithMarkerDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.DEBUG); + event.setMarker(MarkerFactory.getMarker("Dummy")); + assertEquals(discriminator.getDiscriminatingValue(event), DEBUG); + } + + @Test + public void testGetTraceWithMarkerDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.TRACE); + event.setMarker(MarkerFactory.getMarker("Dummy")); + assertEquals(discriminator.getDiscriminatingValue(event), DEBUG); + } + + @Test + public void testGetInfoWithMarkerDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.INFO); + event.setMarker(MarkerFactory.getMarker("Dummy")); + assertEquals(discriminator.getDiscriminatingValue(event), ERROR); + } + + @Test + public void testGetAuditDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.INFO); + event.setMarker(Markers.AUDIT); + assertEquals(discriminator.getDiscriminatingValue(event), "Audit"); + } + + @Test + public void testGetMetricsMarkerDiscriminatingValue() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + LoggingEvent event = new LoggingEvent(); + event.setLevel(Level.INFO); + event.setMarker(Markers.METRICS); + assertEquals(discriminator.getDiscriminatingValue(event), "Metrics"); + } + + @Test + public void testGetKey() { + EventTypeDiscriminator discriminator = new EventTypeDiscriminator(); + assertEquals("eventType", discriminator.getKey()); + } } 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 new file mode 100644 index 0000000000..a430de7d22 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/BaseContextPropagationTest.java @@ -0,0 +1,98 @@ +/* + * 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 org.openecomp.sdc.logging.api.LoggingContext; +import org.openecomp.sdc.logging.provider.LoggingContextService; +import org.testng.annotations.DataProvider; + +import java.util.concurrent.Callable; + +/** + * @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. + // 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"; + static final String EXPECT_REPLACED_WITH_STORED = "Expected context data to be replaced with stored data"; + static final String EXPECT_INNER_RUN = "Expected the inner thread to run"; + static final String EXPECT_OUTER_RUN = "Expected the outer thread to run"; + static final String EXPECT_NOT_COPIED = "Expected context data not to be copied to this thread"; + static final String EXPECT_RETAINED_IN_PARENT = "Expected context data to be retained in parent thread"; + static final String EXPECT_POPULATED = "Expected context data to be populated in this thread"; + static final String EXPECT_EMPTY = "Expected context data to be empty"; + static final String EXPECT_REMAIN_EMPTY = "Expected context data to remain empty in this thread"; + static final String EXPECT_REVERTED_ON_EXCEPTION = "Expected context data to be reverted even in case of exception"; + static final String EXPECT_EXCEPTION_FROM_INNER = "Expected the inner class to throw exception"; + + @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() } + }; + } + + private static class LoggingContextAdaptor implements LoggingContextService { + + @Override + public void put(String key, String value) { + LoggingContext.put(key, value); + } + + @Override + public String get(String key) { + return LoggingContext.get(key); + } + + @Override + public void remove(String key) { + LoggingContext.remove(key); + } + + @Override + public void clear() { + LoggingContext.clear(); + } + + @Override + public Runnable toRunnable(Runnable runnable) { + return LoggingContext.toRunnable(runnable); + } + + @Override + public <V> Callable<V> toCallable(Callable<V> callable) { + return LoggingContext.toCallable(callable); + } + + @Override + public String toString() { + return this.getClass().getName(); + } + } +} 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 new file mode 100644 index 0000000000..5fad3f70c5 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/CallableContextPropagationTest.java @@ -0,0 +1,188 @@ +/* + * 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 org.openecomp.sdc.logging.provider.LoggingContextService; +import org.testng.annotations.Test; + +import java.util.UUID; +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; + +/** + * @author EVITALIY + * @since 08 Jan 18 + */ +public class CallableContextPropagationTest extends BaseContextPropagationTest { + + @Test(enabled = ENABLED, dataProvider = PROVIDER) + public void testContextPropagated(LoggingContextService ctx) throws Exception { + + String uuid = UUID.randomUUID().toString(); + ctx.put(KEY, uuid); + + AtomicBoolean complete = new AtomicBoolean(false); + + // pass the callable to the context service first + execute(ctx.toCallable(() -> { + assertEquals(ctx.get(KEY), uuid, EXPECT_PROPAGATED_TO_CHILD); + complete.set(true); + return null; + })); + + assertEquals(ctx.get(KEY), uuid, 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); + + AtomicBoolean innerComplete = new AtomicBoolean(false); + + // should run with the context of main thread + Callable inner = ctx.toCallable(() -> { + assertEquals(ctx.get(KEY), innerRandom, EXPECT_PROPAGATED_TO_CHILD); + innerComplete.set(true); + return null; + }); + + // 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); + inner.call(); + assertEquals(ctx.get(KEY), outerUuid, EXPECT_REPLACED_WITH_STORED); + outerComplete.set(true); + return null; + }); + + assertEquals(ctx.get(KEY), innerRandom, EXPECT_RETAINED_IN_CURRENT); + assertTrue(outerComplete.get(), EXPECT_OUTER_RUN); + assertTrue(innerComplete.get(), EXPECT_INNER_RUN); + } + + @Test(enabled = ENABLED, dataProvider = PROVIDER) + public void testContextRemainsEmpty(LoggingContextService ctx) throws Exception { + + ctx.remove(KEY); + assertNull(ctx.get(KEY), EXPECT_EMPTY); + + final AtomicBoolean complete = new AtomicBoolean(false); + execute(ctx.toCallable(() -> { + assertNull(ctx.get(KEY), EXPECT_EMPTY); + complete.set(true); + return null; + })); + + assertNull(ctx.get(KEY), 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); + + AtomicBoolean innerComplete = new AtomicBoolean(false); + // should run with the context of main thread + Callable inner = ctx.toCallable((() -> { + assertEquals(ctx.get(KEY), innerRandom, EXPECT_PROPAGATED_TO_CHILD); + innerComplete.set(true); + return null; + })); + + // pushes its own context, but runs the inner + AtomicBoolean outerComplete = new AtomicBoolean(false); + execute(() -> { + assertNull(ctx.get(KEY), EXPECT_NOT_COPIED); + inner.call(); + assertNull(ctx.get(KEY), EXPECT_REMAIN_EMPTY); + outerComplete.set(true); + return null; + }); + + assertEquals(ctx.get(KEY), innerRandom, EXPECT_RETAINED_IN_PARENT); + assertTrue(outerComplete.get(), EXPECT_OUTER_RUN); + assertTrue(innerComplete.get(), EXPECT_INNER_RUN); + } + + @Test(enabled = ENABLED, dataProvider = PROVIDER) + public void testCleanupAfterError(LoggingContextService ctx) throws Exception { + + String innerRandom = UUID.randomUUID().toString(); + ctx.put(KEY, innerRandom); + + // should run with the context of main thread + AtomicBoolean innerComplete = new AtomicBoolean(false); + Callable inner = ctx.toCallable(() -> { + assertEquals(ctx.get(KEY), innerRandom, EXPECT_PROPAGATED_TO_CHILD); + innerComplete.set(true); + throw new IllegalArgumentException(); + }); + + // pushes its own context, but runs the inner callable + AtomicBoolean outerComplete = new AtomicBoolean(false); + AtomicBoolean exceptionThrown = new AtomicBoolean(false); + execute(() -> { + + String outerUuid = UUID.randomUUID().toString(); + ctx.put(KEY, outerUuid); + assertEquals(ctx.get(KEY), outerUuid, EXPECT_POPULATED); + + try { + inner.call(); + } catch (IllegalArgumentException e) { + exceptionThrown.set(true); + } finally { + assertEquals(ctx.get(KEY), outerUuid, EXPECT_REVERTED_ON_EXCEPTION); + outerComplete.set(true); + } + + return null; + }); + + assertEquals(ctx.get(KEY), innerRandom, EXPECT_RETAINED_IN_PARENT); + assertTrue(outerComplete.get(), EXPECT_OUTER_RUN); + assertTrue(innerComplete.get(), EXPECT_INNER_RUN); + assertTrue(exceptionThrown.get(), EXPECT_EXCEPTION_FROM_INNER); + } + + private void execute(Callable<Object> callable) throws Exception { + + ExecutorService executor = Executors.newSingleThreadExecutor(); + + try { + Future<Object> future = executor.submit(callable); + future.get(10, TimeUnit.SECONDS); + } finally { + executor.shutdown(); + } + } +}
\ No newline at end of file diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/LoggerFactoryTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/LoggerFactoryTest.java new file mode 100644 index 0000000000..e04af23a91 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/LoggerFactoryTest.java @@ -0,0 +1,56 @@ +/* + * 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 org.openecomp.sdc.logging.api.Logger; +import org.openecomp.sdc.logging.api.LoggerFactory; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * @author EVITALIY + * @since 08 Jan 18 + */ +public class LoggerFactoryTest { + + private static final String CLASS_NAME = LoggerFactoryTest.class.getName(); + + @Test + public void returnSlf4jLoggerWhenGetByClass() { + Logger logger = LoggerFactory.getLogger(LoggerFactoryTest.class); + assertEquals(logger.getClass(), SLF4JLoggerWrapper.class); + assertEquals(logger.getName(), CLASS_NAME); + } + + @Test + public void returnSlf4jLoggerWhenGetByName() { + Logger logger = LoggerFactory.getLogger(CLASS_NAME); + assertEquals(logger.getClass(), SLF4JLoggerWrapper.class); + assertEquals(logger.getName(), CLASS_NAME); + } + + @Test(expectedExceptions = NullPointerException.class) + public void throwNpeWhenGetByNameWithNull() { + LoggerFactory.getLogger((String) null); + } + + @Test(expectedExceptions = NullPointerException.class) + public void throwNpeWhenGetByClassWithNull() { + LoggerFactory.getLogger((Class<LoggerFactoryTest>) null); + } +} 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 new file mode 100644 index 0000000000..516a27f2cd --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/LoggingContextTest.java @@ -0,0 +1,112 @@ +/* + * 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 org.openecomp.sdc.logging.api.LoggingContext; +import org.slf4j.MDC; +import org.testng.annotations.Test; + +import java.util.UUID; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +/** + * @author evitaliy + * @since 12/09/2016. + */ +public class LoggingContextTest { + + @Test + public void returnMdcWrapperWhenToRunnableCalled() { + assertEquals(LoggingContext.toRunnable(() -> {}).getClass(), MDCRunnableWrapper.class); + } + + @Test(expectedExceptions = NullPointerException.class) + public void throwNpeWhenToRunnableWithNull() { + LoggingContext.toRunnable(null); + } + + @Test + public void returnMdcWrapperWhenToCallableCalled() { + assertEquals(LoggingContext.toCallable(() -> "").getClass(), MDCCallableWrapper.class); + } + + @Test(expectedExceptions = NullPointerException.class) + public void throwNpeWhenToCallableWithNull() { + LoggingContext.toCallable(null); + } + + @Test + public void clearContextWhenClearCalled() { + + String random = UUID.randomUUID().toString(); + + try { + LoggingContext.put(random, random); + LoggingContext.clear(); + assertNull(MDC.get(random)); + assertNull(LoggingContext.get(random)); + } finally { + MDC.remove(random); + } + } + + @Test + public void returnContextWhenGetCalled() { + + String random = UUID.randomUUID().toString(); + + try { + LoggingContext.put(random, random); + assertEquals(random, MDC.get(random)); + assertEquals(random, LoggingContext.get(random)); + } finally { + MDC.remove(random); + } + } + + @Test + public void removeContextWhenRemoveCalled() { + + String random = UUID.randomUUID().toString(); + + try { + LoggingContext.put(random, random); + LoggingContext.remove(random); + assertNull(MDC.get(random)); + assertNull(LoggingContext.get(random)); + } finally { + MDC.remove(random); + } + } + + @Test(expectedExceptions = NullPointerException.class) + public void throwNpeWhenPutWithKeyNull() { + LoggingContext.put(null, "---"); + } + + @Test(expectedExceptions = NullPointerException.class) + public void throwNpeWhenGetWithKeyNull() { + LoggingContext.get(null); + } + + @Test(expectedExceptions = NullPointerException.class) + public void throwNpeWhenRemoveWithKeyNull() { + LoggingContext.remove(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 new file mode 100644 index 0000000000..a617abd69c --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-core/src/test/java/org/openecomp/sdc/logging/slf4j/RunnableContextPropagationTest.java @@ -0,0 +1,209 @@ +/* + * 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 org.openecomp.sdc.logging.provider.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 + * @since 08 Jan 18 + */ +public class RunnableContextPropagationTest extends BaseContextPropagationTest { + + @Test(enabled = ENABLED, dataProvider = PROVIDER) + public void contextNotCopiedToChildThreadByDefault(LoggingContextService ctx) + throws InterruptedException { + + String random = UUID.randomUUID().toString(); + ctx.put(KEY, random); + + 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. " + + "Are you using an old version of SLF4J diagnostic context implementation (e.g. logback)?"); + complete.set(true); + }); + + thread.start(); + thread.join(); + + assertEquals(ctx.get(KEY), random, EXPECT_RETAINED_IN_CURRENT); + assertTrue(complete.get(), EXPECT_INNER_RUN); + } + + @Test(enabled = ENABLED, dataProvider = PROVIDER) + public void contextCopiedWhenToRunnableCalled(LoggingContextService ctx) + throws InterruptedException { + + String uuid = UUID.randomUUID().toString(); + ctx.put(KEY, uuid); + + AtomicBoolean complete = new AtomicBoolean(false); + + // pass the runnable to the context service first + Thread thread = new Thread(ctx.toRunnable(() -> { + assertEquals(ctx.get(KEY), uuid, EXPECT_PROPAGATED_TO_CHILD); + complete.set(true); + })); + + thread.start(); + thread.join(); + + assertEquals(ctx.get(KEY), uuid, EXPECT_RETAINED_IN_CURRENT); + assertTrue(complete.get(), EXPECT_INNER_RUN); + } + + @Test(enabled = ENABLED, dataProvider = PROVIDER) + public void copiedContextRetainedEvenWhenAnotherPushed(LoggingContextService ctx) + throws InterruptedException { + + String innerRandom = UUID.randomUUID().toString(); + ctx.put(KEY, innerRandom); + + AtomicBoolean innerComplete = new AtomicBoolean(false); + + // should run with the context of main thread + Runnable inner = ctx.toRunnable(() -> { + assertEquals(ctx.get(KEY), innerRandom, 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); + inner.run(); + assertEquals(ctx.get(KEY), outerUuid, EXPECT_REPLACED_WITH_STORED); + outerComplete.set(true); + }); + + outer.start(); + outer.join(); + + assertEquals(ctx.get(KEY), innerRandom, EXPECT_RETAINED_IN_CURRENT); + assertTrue(outerComplete.get(), EXPECT_OUTER_RUN); + assertTrue(innerComplete.get(), EXPECT_INNER_RUN); + } + + @Test(enabled = ENABLED, dataProvider = PROVIDER) + public void contextRemainsEmptyWhenParentWasEmpty(LoggingContextService ctx) + throws InterruptedException { + + ctx.remove(KEY); + assertNull(ctx.get(KEY), EXPECT_EMPTY); + + final AtomicBoolean complete = new AtomicBoolean(false); + Runnable runnable = ctx.toRunnable(() -> { + assertNull(ctx.get(KEY), EXPECT_EMPTY); + complete.set(true); + }); + + Thread thread = new Thread(runnable); + thread.start(); + thread.join(); + + assertNull(ctx.get(KEY), EXPECT_EMPTY); + assertTrue(complete.get(), EXPECT_INNER_RUN); + } + + @Test(enabled = ENABLED, dataProvider = PROVIDER) + public void childThreadCleanedUpAfterRunnableRuns(LoggingContextService ctx) + throws Exception { + + String innerRandom = UUID.randomUUID().toString(); + ctx.put(KEY, innerRandom); + + AtomicBoolean innerComplete = new AtomicBoolean(false); + // should run with the context of main thread + Runnable inner = ctx.toRunnable(() -> { + assertEquals(ctx.get(KEY), innerRandom, 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); + inner.run(); + assertNull(ctx.get(KEY), EXPECT_REMAIN_EMPTY); + outerComplete.set(true); + }); + + outer.start(); + outer.join(); + + assertEquals(ctx.get(KEY), innerRandom, EXPECT_RETAINED_IN_PARENT); + assertTrue(outerComplete.get(), EXPECT_OUTER_RUN); + assertTrue(innerComplete.get(), EXPECT_INNER_RUN); + } + + @Test(enabled = ENABLED, dataProvider = PROVIDER) + public void childThreadCleanedUpAfterException(LoggingContextService ctx) + throws Exception { + + String innerRandom = UUID.randomUUID().toString(); + ctx.put(KEY, innerRandom); + + // should run with the context of main thread + AtomicBoolean innerComplete = new AtomicBoolean(false); + Runnable inner = ctx.toRunnable(() -> { + assertEquals(ctx.get(KEY), innerRandom, EXPECT_PROPAGATED_TO_CHILD); + innerComplete.set(true); + throw new IllegalArgumentException(); + }); + + // pushes its own context, but runs the inner runnable + AtomicBoolean outerComplete = new AtomicBoolean(false); + 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); + + try { + inner.run(); + } catch (IllegalArgumentException e) { + exceptionThrown.set(true); + } finally { + assertEquals(ctx.get(KEY), outerUuid, EXPECT_REVERTED_ON_EXCEPTION); + outerComplete.set(true); + } + }); + + outer.start(); + outer.join(); + + assertEquals(ctx.get(KEY), innerRandom, EXPECT_RETAINED_IN_PARENT); + assertTrue(outerComplete.get(), EXPECT_OUTER_RUN); + assertTrue(innerComplete.get(), EXPECT_INNER_RUN); + assertTrue(exceptionThrown.get(), EXPECT_EXCEPTION_FROM_INNER); + } + + +}
\ No newline at end of file |