You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by vy...@apache.org on 2024/03/01 13:04:53 UTC

(logging-log4j2) 01/01: Fix `StatusLogger` log level filtering when debug mode is enabled (#2337)

This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch 2.x-StatusLogger-debug-fix
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit aa0e35d755f3143717394e4ff283a76a264dcf44
Author: Volkan Yazıcı <vo...@yazi.ci>
AuthorDate: Fri Mar 1 14:05:00 2024 +0100

    Fix `StatusLogger` log level filtering when debug mode is enabled (#2337)
---
 .../log4j/status/StatusLoggerLevelTest.java        | 82 ++++++++++++++++++++++
 .../apache/logging/log4j/status/StatusLogger.java  | 21 ++++--
 .../.2.x.x/fix_StatusLogger_debug_mode.xml         |  8 +++
 3 files changed, 107 insertions(+), 4 deletions(-)

diff --git a/log4j-api-test/src/test/java/org/apache/logging/log4j/status/StatusLoggerLevelTest.java b/log4j-api-test/src/test/java/org/apache/logging/log4j/status/StatusLoggerLevelTest.java
index 3d58cf454a..9aa6ad9db7 100644
--- a/log4j-api-test/src/test/java/org/apache/logging/log4j/status/StatusLoggerLevelTest.java
+++ b/log4j-api-test/src/test/java/org/apache/logging/log4j/status/StatusLoggerLevelTest.java
@@ -18,12 +18,19 @@ package org.apache.logging.log4j.status;
 
 import static org.apache.logging.log4j.status.StatusLogger.DEFAULT_FALLBACK_LISTENER_LEVEL;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import java.util.Arrays;
 import java.util.Properties;
 import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.message.ParameterizedNoReferenceMessageFactory;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 import uk.org.webcompere.systemstubs.SystemStubs;
 
 class StatusLoggerLevelTest {
@@ -104,4 +111,79 @@ class StatusLoggerLevelTest {
         // Verify the level
         assertThat(statusLoggerConfig.fallbackListenerLevel).isEqualTo(DEFAULT_FALLBACK_LISTENER_LEVEL);
     }
+
+    @ParameterizedTest
+    @ValueSource(booleans = {true, false})
+    void debug_mode_should_override_log_filtering(final boolean debugEnabled) {
+
+        // Create a logger with debug enabled
+        final StatusLogger.Config loggerConfig = new StatusLogger.Config(debugEnabled, 0, null);
+        final Level loggerLevel = Level.ERROR;
+        final StatusConsoleListener fallbackListener = mock(StatusConsoleListener.class);
+        when(fallbackListener.getStatusLevel()).thenReturn(loggerLevel);
+        final StatusLogger logger = new StatusLogger(
+                StatusLoggerLevelTest.class.getSimpleName(),
+                ParameterizedNoReferenceMessageFactory.INSTANCE,
+                loggerConfig,
+                fallbackListener);
+
+        // Log at all levels
+        final Level[] levels = Level.values();
+        for (final Level level : levels) {
+            logger.log(level, "test for level `{}`", level);
+        }
+
+        // Calculate the number of expected messages
+        final int expectedMessageCount;
+        if (debugEnabled) {
+            expectedMessageCount = levels.length;
+        } else {
+            expectedMessageCount = (int) Arrays.stream(levels)
+                    .filter(loggerLevel::isLessSpecificThan)
+                    .count();
+        }
+
+        // Verify the fallback listener invocation
+        assertThat(expectedMessageCount).isGreaterThan(0);
+        verify(fallbackListener, times(expectedMessageCount)).log(any());
+    }
+
+    @ParameterizedTest
+    @ValueSource(booleans = {true, false})
+    void debug_mode_should_override_listener_filtering(final boolean debugEnabled) {
+
+        // Create a logger with debug enabled
+        final StatusLogger.Config loggerConfig = new StatusLogger.Config(debugEnabled, 0, null);
+        final StatusLogger logger = new StatusLogger(
+                StatusLoggerLevelTest.class.getSimpleName(),
+                ParameterizedNoReferenceMessageFactory.INSTANCE,
+                loggerConfig,
+                new StatusConsoleListener(Level.ERROR));
+
+        // Register a listener
+        final Level listenerLevel = Level.INFO;
+        final StatusListener listener = mock(StatusListener.class);
+        when(listener.getStatusLevel()).thenReturn(listenerLevel);
+        logger.registerListener(listener);
+
+        // Log at all levels
+        final Level[] levels = Level.values();
+        for (final Level level : levels) {
+            logger.log(level, "test for level `{}`", level);
+        }
+
+        // Calculate the number of expected messages
+        final int expectedMessageCount;
+        if (debugEnabled) {
+            expectedMessageCount = levels.length;
+        } else {
+            expectedMessageCount = (int) Arrays.stream(levels)
+                    .filter(listenerLevel::isLessSpecificThan)
+                    .count();
+        }
+
+        // Verify the listener invocation
+        assertThat(expectedMessageCount).isGreaterThan(0);
+        verify(listener, times(expectedMessageCount)).log(any());
+    }
 }
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java b/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
index bdebc1150a..56d9ef9862 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
@@ -768,7 +768,8 @@ public class StatusLogger extends AbstractLogger {
     }
 
     private void notifyListener(final StatusListener listener, final StatusData statusData) {
-        if (config.debugEnabled || listener.getStatusLevel().isLessSpecificThan(statusData.getLevel())) {
+        final boolean levelEnabled = isLevelEnabled(listener.getStatusLevel(), statusData.getLevel());
+        if (levelEnabled) {
             listener.log(statusData);
         }
     }
@@ -963,8 +964,20 @@ public class StatusLogger extends AbstractLogger {
     }
 
     @Override
-    public boolean isEnabled(final Level level, final Marker marker) {
-        requireNonNull(level, "level");
-        return getLevel().isLessSpecificThan(level);
+    public boolean isEnabled(final Level messageLevel, final Marker marker) {
+        requireNonNull(messageLevel, "messageLevel");
+        final Level loggerLevel = getLevel();
+        return isLevelEnabled(loggerLevel, messageLevel);
+    }
+
+    /**
+     * Checks if the message level is allowed for the filtering level (e.g., of logger, of listener) by taking debug mode into account.
+     *
+     * @param filteringLevel the level (e.g., of logger, of listener) to filter messages
+     * @param messageLevel the level of the message
+     * @return {@code true}, if the sink level is less specific than the message level; {@code false}, otherwise
+     */
+    private boolean isLevelEnabled(final Level filteringLevel, final Level messageLevel) {
+        return config.debugEnabled || filteringLevel.isLessSpecificThan(messageLevel);
     }
 }
diff --git a/src/changelog/.2.x.x/fix_StatusLogger_debug_mode.xml b/src/changelog/.2.x.x/fix_StatusLogger_debug_mode.xml
new file mode 100644
index 0000000000..0eafe16cbc
--- /dev/null
+++ b/src/changelog/.2.x.x/fix_StatusLogger_debug_mode.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns="http://logging.apache.org/log4j/changelog"
+       xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.3.xsd"
+       type="fixed">
+  <issue id="2337" link="https://github.com/apache/logging-log4j2/issues/2337"/>
+  <description format="asciidoc">Fix `StatusLogger` log level filtering when debug mode is enabled</description>
+</entry>