diff options
Diffstat (limited to 'common/openecomp-logging-lib/openecomp-logging-api')
10 files changed, 620 insertions, 0 deletions
diff --git a/common/openecomp-logging-lib/openecomp-logging-api/pom.xml b/common/openecomp-logging-lib/openecomp-logging-api/pom.xml new file mode 100644 index 0000000000..96129557f4 --- /dev/null +++ b/common/openecomp-logging-lib/openecomp-logging-api/pom.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <name>openecomp-configuration-management-test</name> + <groupId>org.openecomp.sdc.common</groupId> + <artifactId>openecomp-logging-api</artifactId> + + <parent> + <artifactId>openecomp-logging-lib</artifactId> + <groupId>org.openecomp.sdc.common</groupId> + <version>1.1.0-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + +</project> diff --git a/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/BaseFactory.java b/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/BaseFactory.java new file mode 100644 index 0000000000..14943805cc --- /dev/null +++ b/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/BaseFactory.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.core.logging.api; + +import java.util.Iterator; +import java.util.ServiceLoader; + +/** + * Contains common functionality for factories used in the logging framework. <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> + * + * @see java.util.ServiceLoader + */ +public class BaseFactory { + + protected static <T> T locateService(Class<T> clazz) throws Exception { + + T service; + ServiceLoader<T> loader = ServiceLoader.load(clazz); + Iterator<T> iterator = loader.iterator(); + if (iterator.hasNext()) { + + service = iterator.next(); + if (iterator.hasNext()) { + System.err.println(String.format("Warning! Configured more than one implementation of %s", + clazz.getName())); + } + + return service; + } + + throw new IllegalArgumentException( + (String.format("No implementations configured for %s", clazz.getName()))); + } +} diff --git a/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/Logger.java b/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/Logger.java new file mode 100644 index 0000000000..0fe3d8f230 --- /dev/null +++ b/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/Logger.java @@ -0,0 +1,103 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.core.logging.api; + +/** + * <p>This interface defines logging as specified by OPENECOMP logging requirements.</p> <p>Formatted + * messages must follow the <a href="http://www.slf4j.org/api/org/slf4j/helpers/MessageFormatter.html>SLF4J + * format</a>.</p> + */ +public interface Logger { + + String getName(); + + boolean isMetricsEnabled(); + + void metrics(String msg); + + void metrics(String msg, Object arg); + + void metrics(String msg, Object arg1, Object arg2); + + void metrics(String msg, Object... arguments); + + void metrics(String msg, Throwable throwable); + + boolean isAuditEnabled(); + + void audit(String msg); + + void audit(String msg, Object arg); + + void audit(String msg, Object arg1, Object arg2); + + void audit(String msg, Object... arguments); + + void audit(String msg, Throwable throwable); + + boolean isDebugEnabled(); + + void debug(String msg); + + void debug(String msg, Object arg); + + void debug(String msg, Object arg1, Object arg2); + + void debug(String msg, Object... arguments); + + void debug(String msg, Throwable throwable); + + boolean isInfoEnabled(); + + void info(String msg); + + void info(String msg, Object arg); + + void info(String msg, Object arg1, Object arg2); + + void info(String msg, Object... arguments); + + void info(String msg, Throwable throwable); + + boolean isWarnEnabled(); + + void warn(String msg); + + void warn(String msg, Object arg); + + void warn(String msg, Object... arguments); + + void warn(String msg, Object arg1, Object arg2); + + void warn(String msg, Throwable throwable); + + boolean isErrorEnabled(); + + void error(String msg); + + void error(String msg, Object arg); + + void error(String msg, Object arg1, Object arg2); + + void error(String msg, Object... arguments); + + void error(String msg, Throwable throwable); +} diff --git a/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/LoggerCreationService.java b/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/LoggerCreationService.java new file mode 100644 index 0000000000..298f8f0267 --- /dev/null +++ b/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/LoggerCreationService.java @@ -0,0 +1,11 @@ +package org.openecomp.core.logging.api; + +/** + * Implements a framework-specific logging, to be used by {@link LoggerFactory}. + */ +public interface LoggerCreationService { + + Logger getLogger(String className); + + Logger getLogger(Class<?> clazz); +} diff --git a/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/LoggerFactory.java b/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/LoggerFactory.java new file mode 100644 index 0000000000..e6f4aa3707 --- /dev/null +++ b/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/LoggerFactory.java @@ -0,0 +1,232 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.core.logging.api; + +/** + * <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 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> + * + * @see BaseFactory + * @see LoggerCreationService + */ +@SuppressWarnings("ThrowableInstanceNeverThrown") +public class LoggerFactory extends BaseFactory { + + private static final LoggerCreationService SERVICE; + + static { + + LoggerCreationService service; + + try { + service = locateService(LoggerCreationService.class); + } catch (Throwable throwable) { + new RuntimeException("Failed to instantiate logger factory", throwable).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(); + } + + 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 Logger() { + + @Override + public String getName() { + return "No-Op Logger"; + } + + @Override + public boolean isMetricsEnabled() { + return false; + } + + @Override + public void metrics(String msg) { + } + + @Override + public void metrics(String msg, Object arg) { + } + + @Override + public void metrics(String msg, Object arg1, Object arg2) { + } + + @Override + public void metrics(String msg, Object... arguments) { + } + + @Override + public void metrics(String msg, Throwable throwable) { + } + + @Override + public boolean isAuditEnabled() { + return false; + } + + @Override + public void audit(String msg) { + } + + @Override + public void audit(String msg, Object arg) { + } + + @Override + public void audit(String msg, Object arg1, Object arg2) { + } + + @Override + public void audit(String msg, Object... arguments) { + } + + @Override + public void audit(String msg, Throwable throwable) { + } + + @Override + public boolean isDebugEnabled() { + return false; + } + + @Override + public void debug(String msg) { + } + + @Override + public void debug(String msg, Object arg) { + } + + @Override + public void debug(String msg, Object arg1, Object arg2) { + } + + @Override + public void debug(String msg, Object... arguments) { + } + + @Override + public void debug(String msg, Throwable throwable) { + } + + @Override + public boolean isInfoEnabled() { + return false; + } + + @Override + public void info(String msg) { + } + + @Override + public void info(String msg, Object arg) { + } + + @Override + public void info(String msg, Object arg1, Object arg2) { + } + + @Override + public void info(String msg, Object... arguments) { + } + + @Override + public void info(String msg, Throwable throwable) { + } + + @Override + public boolean isWarnEnabled() { + return false; + } + + @Override + public void warn(String msg) { + } + + @Override + public void warn(String msg, Object arg) { + } + + @Override + public void warn(String msg, Object... arguments) { + } + + @Override + public void warn(String msg, Object arg1, Object arg2) { + } + + @Override + public void warn(String msg, Throwable throwable) { + } + + @Override + public boolean isErrorEnabled() { + return false; + } + + @Override + public void error(String msg) { + } + + @Override + public void error(String msg, Object arg) { + } + + @Override + public void error(String msg, Object arg1, Object arg2) { + } + + @Override + public void error(String msg, Object... arguments) { + } + + @Override + public void error(String msg, Throwable throwable) { + } + }; + + @Override + public Logger getLogger(String className) { + return NO_OP_LOGGER; + } + + @Override + public Logger getLogger(Class<?> clazz) { + return NO_OP_LOGGER; + } + } +} diff --git a/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/annotations/Metrics.java b/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/annotations/Metrics.java new file mode 100644 index 0000000000..1588bcafc0 --- /dev/null +++ b/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/annotations/Metrics.java @@ -0,0 +1,15 @@ +package org.openecomp.core.logging.api.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates a method whose execution time should be measured and logged as required for OPENECOMP + * metrics. + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Metrics { +} diff --git a/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/context/ContextPropagationService.java b/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/context/ContextPropagationService.java new file mode 100644 index 0000000000..8e9c2dfa28 --- /dev/null +++ b/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/context/ContextPropagationService.java @@ -0,0 +1,10 @@ +package org.openecomp.core.logging.api.context; + +/** + * Should be used to implement a framework-specific mechanism of propagation of a diagnostic context + * to child threads. + */ +public interface ContextPropagationService { + + Runnable create(Runnable task); +} diff --git a/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/context/TaskFactory.java b/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/context/TaskFactory.java new file mode 100644 index 0000000000..b358a77573 --- /dev/null +++ b/common/openecomp-logging-lib/openecomp-logging-api/src/main/java/org/openecomp/core/logging/api/context/TaskFactory.java @@ -0,0 +1,73 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.core.logging.api.context; + +import org.openecomp.core.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> + * + * @see ContextPropagationService + */ +@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 (Throwable throwable) { + error = new RuntimeException("Failed to instantiate task factory", throwable); + } + + 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/common/openecomp-logging-lib/openecomp-logging-api/src/test/java/org/openecomp/core/logging/api/LoggerFactoryTest.java b/common/openecomp-logging-lib/openecomp-logging-api/src/test/java/org/openecomp/core/logging/api/LoggerFactoryTest.java new file mode 100644 index 0000000000..7158db7ab4 --- /dev/null +++ b/common/openecomp-logging-lib/openecomp-logging-api/src/test/java/org/openecomp/core/logging/api/LoggerFactoryTest.java @@ -0,0 +1,74 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.core.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; + +/** + * @author evitaliy + * @since 14/09/2016. + */ +public class LoggerFactoryTest { + + @Test + public void testNoOpLoggerService() throws Exception { + + assertFalse(ServiceLoader.load(LoggerCreationService.class).iterator().hasNext()); + + LoggerFactory.getLogger(LoggerFactoryTest.class); + Field factory = LoggerFactory.class.getDeclaredField("SERVICE"); + factory.setAccessible(true); + Object impl = factory.get(null); + assertEquals("org.openecomp.core.logging.api.LoggerFactory$NoOpLoggerCreationService", + impl.getClass().getName()); + } + + @Test + public void testNoOpLoggerByClass() throws Exception { + Logger logger = LoggerFactory.getLogger(LoggerFactoryTest.class); + verifyLogger(logger); + } + + @Test + public void testNoOpLoggerByName() throws Exception { + Logger logger = LoggerFactory.getLogger(LoggerFactoryTest.class.getName()); + verifyLogger(logger); + } + + private void verifyLogger(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/common/openecomp-logging-lib/openecomp-logging-api/src/test/java/org/openecomp/core/logging/api/context/TaskFactoryTest.java b/common/openecomp-logging-lib/openecomp-logging-api/src/test/java/org/openecomp/core/logging/api/context/TaskFactoryTest.java new file mode 100644 index 0000000000..111a30de1a --- /dev/null +++ b/common/openecomp-logging-lib/openecomp-logging-api/src/test/java/org/openecomp/core/logging/api/context/TaskFactoryTest.java @@ -0,0 +1,30 @@ +package org.openecomp.core.logging.api.context; + +import org.testng.annotations.Test; + +import java.util.ServiceLoader; + +import static org.testng.Assert.*; + +/** + * @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 |