From 8f429bd30146ed064f37440312548d5fcde20a9b Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Mon, 2 Jan 2017 16:55:57 +0100 Subject: SONAR-8567 Improve logging API to accept a lambda as argument --- .../main/java/org/sonar/api/utils/log/Logger.java | 37 ++++++++++++++- .../org/sonar/api/utils/log/LogTesterTest.java | 53 ++++++++++++++++++++++ 2 files changed, 89 insertions(+), 1 deletion(-) (limited to 'sonar-plugin-api') diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/Logger.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/Logger.java index 36665b990a6..3fd95e6ec55 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/Logger.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/log/Logger.java @@ -19,6 +19,7 @@ */ package org.sonar.api.utils.log; +import java.util.function.Supplier; import javax.annotation.Nullable; /** @@ -59,6 +60,23 @@ public interface Logger { */ void trace(String msg); + /** + * Logs a TRACE message, which is only to be constructed if the logging level + * is such that the message will actually be logged. + *

+ * TRACE messages must + * be valuable for diagnosing production problems. They must not be used for development debugging. + * They can significantly slow down performances. The standard use-case is logging of + * SQL and Elasticsearch requests. + * @param msgSupplier A function, which when called, produces the desired log message + * @since 6.3 + */ + default void trace(Supplier msgSupplier) { + if (isTraceEnabled()) { + trace(msgSupplier.get()); + } + } + /** * Logs an TRACE parameterized message according to the specified format and argument. Example: * trace("Value is {}", value) @@ -99,11 +117,28 @@ public interface Logger { boolean isDebugEnabled(); /** - * Logs a DEBUG message. Debug messages must + * Logs a DEBUG message. + *

+ * DEBUG messages must * be valuable for diagnosing production problems. They must not be used for development debugging. */ void debug(String msg); + /** + * Logs a DEBUG message which is only to be constructed if the logging level + * is such that the message will actually be logged. + *

+ * DEBUG messages must + * be valuable for diagnosing production problems. They must not be used for development debugging. + * @param msgSupplier A function, which when called, produces the desired log message + * @since 6.3 + */ + default void debug(Supplier msgSupplier) { + if (isDebugEnabled()) { + debug(msgSupplier.get()); + } + } + /** * Logs an DEBUG parameterized message according to the specified format and argument. Example: * debug("Value is {}", value) diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/utils/log/LogTesterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/log/LogTesterTest.java index 0521837bc3b..e94f797ac44 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/utils/log/LogTesterTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/utils/log/LogTesterTest.java @@ -19,6 +19,7 @@ */ package org.sonar.api.utils.log; +import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -63,4 +64,56 @@ public class LogTesterTest { underTest.after(); assertThat(LogInterceptors.get()).isSameAs(NullInterceptor.NULL_INSTANCE); } + + @Test + public void use_suppliers() throws Throwable { + // when LogTester is used, then info logs are enabled by default + underTest.before(); + AtomicBoolean touchedTrace = new AtomicBoolean(); + AtomicBoolean touchedDebug = new AtomicBoolean(); + Loggers.get("logger1").trace(() -> { + touchedTrace.set(true); + return "a trace information"; + }); + Loggers.get("logger1").debug(() -> { + touchedDebug.set(true); + return "a debug information"; + }); + + assertThat(underTest.logs()).isEmpty(); + assertThat(touchedTrace.get()).isFalse(); + assertThat(touchedDebug.get()).isFalse(); + + // change level to DEBUG + underTest.setLevel(LoggerLevel.DEBUG); + Loggers.get("logger1").trace(() -> { + touchedTrace.set(true); + return "a trace information"; + }); + Loggers.get("logger1").debug(() -> { + touchedDebug.set(true); + return "a debug information"; + }); + + assertThat(underTest.logs()).containsOnly("a debug information"); + assertThat(touchedTrace.get()).isFalse(); + assertThat(touchedDebug.get()).isTrue(); + touchedDebug.set(false); + underTest.logs().clear(); + + // change level to TRACE + underTest.setLevel(LoggerLevel.TRACE); + Loggers.get("logger1").trace(() -> { + touchedTrace.set(true); + return "a trace information"; + }); + Loggers.get("logger1").debug(() -> { + touchedDebug.set(true); + return "a debug information"; + }); + + assertThat(underTest.logs()).containsExactly("a trace information", "a debug information"); + assertThat(touchedTrace.get()).isTrue(); + assertThat(touchedDebug.get()).isTrue(); + } } -- cgit v1.2.3