From be1000d64424f7c0fc3a4226ae554eb141ddb53a Mon Sep 17 00:00:00 2001 From: Evgenii Novozhilov Date: Fri, 10 Jan 2025 14:54:05 +0200 Subject: [PATCH] testFramework: prevent log records multiplication in console When idea.test.logs.echo.debug.to.stdout is enabled and some loggers have FINE or lower level allowed then some records might get multiplicated in the output -- see comment in the code. This was caused by too many handlers assigned to loggers and this change reduces the amount of them. GitOrigin-RevId: 903f52a3f1b01f02303a15b2c633892e13240a89 --- .../testFramework/TestLoggerFactory.java | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/platform/testFramework/core/src/com/intellij/testFramework/TestLoggerFactory.java b/platform/testFramework/core/src/com/intellij/testFramework/TestLoggerFactory.java index ff1288034c73..48e11a92aa0d 100644 --- a/platform/testFramework/core/src/com/intellij/testFramework/TestLoggerFactory.java +++ b/platform/testFramework/core/src/com/intellij/testFramework/TestLoggerFactory.java @@ -9,7 +9,6 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.LineTokenizer; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ExceptionUtil; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.ApiStatus.Internal; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -81,22 +80,7 @@ public final class TestLoggerFactory implements Logger.Factory { myInitialized = true; } - java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger(category); - if (myEchoDebugToStdout) { - configureLogToStdoutIfDebug(julLogger); - } - return new TestLogger(julLogger, this); - } - - /** - * If the logger has the "FINE" level, add a LogToStdoutJulHandler that streams its log records - * to STDOUT with a timestamp relative to the test start time. - */ - private static void configureLogToStdoutIfDebug(@NotNull java.util.logging.Logger julLogger) { - if (julLogger.isLoggable(Level.FINE) && - ContainerUtil.findInstance(julLogger.getHandlers(), LogToStdoutJulHandler.class) == null) { - julLogger.addHandler(new LogToStdoutJulHandler()); - } + return new TestLogger(java.util.logging.Logger.getLogger(category), this); } public static int getRethrowErrorNumber() { @@ -124,6 +108,11 @@ public final class TestLoggerFactory implements Logger.Factory { Path logFile = logDir.resolve(LOG_FILE_NAME); JulLogger.clearHandlers(); JulLogger.configureLogFileAndConsole(logFile, false, true, false, null, null, null); + + if (myEchoDebugToStdout) { + addConsoleAppenderForDebugRecords(); + } + System.out.printf("Test log file: %s%n", logFile); if (Files.exists(logFile) && Files.size(logFile) >= LOG_SIZE_LIMIT) { @@ -138,6 +127,13 @@ public final class TestLoggerFactory implements Logger.Factory { } } + private static void addConsoleAppenderForDebugRecords() { + java.util.logging.Logger rootLogger = java.util.logging.Logger.getLogger(""); + + // just add a single console appender instead of multiple handlers, but for the root logger + rootLogger.addHandler(new LogToStdoutJulHandler(Level.FINE)); + } + public static @NotNull Path getTestLogDir() { String property = System.getProperty(PROPERTY_LOG_PATH); return property == null ? Path.of(PathManager.getSystemPath(), LOG_DIR) : Path.of(property).normalize(); @@ -546,9 +542,13 @@ public final class TestLoggerFactory implements Logger.Factory { private static class LogToStdoutJulHandler extends StreamHandler { private boolean initialized; - LogToStdoutJulHandler() { + LogToStdoutJulHandler(Level level) { super(System.out, new WithTimeSinceTestStartedJulFormatter()); + + // we'd like to capture all records with level or finer than the level + // so we set level to all and do actual level filtering with the filter setLevel(Level.ALL); + setFilter(record -> record.getLevel().intValue() <= level.intValue()); } @Override