Skip to content

Commit aa0e35d

Browse files
committed
Fix StatusLogger log level filtering when debug mode is enabled (#2337)
1 parent 3060ab1 commit aa0e35d

File tree

3 files changed

+107
-4
lines changed

3 files changed

+107
-4
lines changed

log4j-api-test/src/test/java/org/apache/logging/log4j/status/StatusLoggerLevelTest.java

+82
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,19 @@
1818

1919
import static org.apache.logging.log4j.status.StatusLogger.DEFAULT_FALLBACK_LISTENER_LEVEL;
2020
import static org.assertj.core.api.Assertions.assertThat;
21+
import static org.mockito.ArgumentMatchers.any;
2122
import static org.mockito.Mockito.mock;
23+
import static org.mockito.Mockito.times;
24+
import static org.mockito.Mockito.verify;
2225
import static org.mockito.Mockito.when;
2326

27+
import java.util.Arrays;
2428
import java.util.Properties;
2529
import org.apache.logging.log4j.Level;
30+
import org.apache.logging.log4j.message.ParameterizedNoReferenceMessageFactory;
2631
import org.junit.jupiter.api.Test;
32+
import org.junit.jupiter.params.ParameterizedTest;
33+
import org.junit.jupiter.params.provider.ValueSource;
2734
import uk.org.webcompere.systemstubs.SystemStubs;
2835

2936
class StatusLoggerLevelTest {
@@ -104,4 +111,79 @@ void invalid_level_should_cause_fallback_to_defaults() throws Exception {
104111
// Verify the level
105112
assertThat(statusLoggerConfig.fallbackListenerLevel).isEqualTo(DEFAULT_FALLBACK_LISTENER_LEVEL);
106113
}
114+
115+
@ParameterizedTest
116+
@ValueSource(booleans = {true, false})
117+
void debug_mode_should_override_log_filtering(final boolean debugEnabled) {
118+
119+
// Create a logger with debug enabled
120+
final StatusLogger.Config loggerConfig = new StatusLogger.Config(debugEnabled, 0, null);
121+
final Level loggerLevel = Level.ERROR;
122+
final StatusConsoleListener fallbackListener = mock(StatusConsoleListener.class);
123+
when(fallbackListener.getStatusLevel()).thenReturn(loggerLevel);
124+
final StatusLogger logger = new StatusLogger(
125+
StatusLoggerLevelTest.class.getSimpleName(),
126+
ParameterizedNoReferenceMessageFactory.INSTANCE,
127+
loggerConfig,
128+
fallbackListener);
129+
130+
// Log at all levels
131+
final Level[] levels = Level.values();
132+
for (final Level level : levels) {
133+
logger.log(level, "test for level `{}`", level);
134+
}
135+
136+
// Calculate the number of expected messages
137+
final int expectedMessageCount;
138+
if (debugEnabled) {
139+
expectedMessageCount = levels.length;
140+
} else {
141+
expectedMessageCount = (int) Arrays.stream(levels)
142+
.filter(loggerLevel::isLessSpecificThan)
143+
.count();
144+
}
145+
146+
// Verify the fallback listener invocation
147+
assertThat(expectedMessageCount).isGreaterThan(0);
148+
verify(fallbackListener, times(expectedMessageCount)).log(any());
149+
}
150+
151+
@ParameterizedTest
152+
@ValueSource(booleans = {true, false})
153+
void debug_mode_should_override_listener_filtering(final boolean debugEnabled) {
154+
155+
// Create a logger with debug enabled
156+
final StatusLogger.Config loggerConfig = new StatusLogger.Config(debugEnabled, 0, null);
157+
final StatusLogger logger = new StatusLogger(
158+
StatusLoggerLevelTest.class.getSimpleName(),
159+
ParameterizedNoReferenceMessageFactory.INSTANCE,
160+
loggerConfig,
161+
new StatusConsoleListener(Level.ERROR));
162+
163+
// Register a listener
164+
final Level listenerLevel = Level.INFO;
165+
final StatusListener listener = mock(StatusListener.class);
166+
when(listener.getStatusLevel()).thenReturn(listenerLevel);
167+
logger.registerListener(listener);
168+
169+
// Log at all levels
170+
final Level[] levels = Level.values();
171+
for (final Level level : levels) {
172+
logger.log(level, "test for level `{}`", level);
173+
}
174+
175+
// Calculate the number of expected messages
176+
final int expectedMessageCount;
177+
if (debugEnabled) {
178+
expectedMessageCount = levels.length;
179+
} else {
180+
expectedMessageCount = (int) Arrays.stream(levels)
181+
.filter(listenerLevel::isLessSpecificThan)
182+
.count();
183+
}
184+
185+
// Verify the listener invocation
186+
assertThat(expectedMessageCount).isGreaterThan(0);
187+
verify(listener, times(expectedMessageCount)).log(any());
188+
}
107189
}

log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java

+17-4
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,8 @@ private void notifyListeners(final StatusData statusData) {
768768
}
769769

770770
private void notifyListener(final StatusListener listener, final StatusData statusData) {
771-
if (config.debugEnabled || listener.getStatusLevel().isLessSpecificThan(statusData.getLevel())) {
771+
final boolean levelEnabled = isLevelEnabled(listener.getStatusLevel(), statusData.getLevel());
772+
if (levelEnabled) {
772773
listener.log(statusData);
773774
}
774775
}
@@ -963,8 +964,20 @@ public boolean isEnabled(final Level level, final Marker marker, final Message m
963964
}
964965

965966
@Override
966-
public boolean isEnabled(final Level level, final Marker marker) {
967-
requireNonNull(level, "level");
968-
return getLevel().isLessSpecificThan(level);
967+
public boolean isEnabled(final Level messageLevel, final Marker marker) {
968+
requireNonNull(messageLevel, "messageLevel");
969+
final Level loggerLevel = getLevel();
970+
return isLevelEnabled(loggerLevel, messageLevel);
971+
}
972+
973+
/**
974+
* Checks if the message level is allowed for the filtering level (e.g., of logger, of listener) by taking debug mode into account.
975+
*
976+
* @param filteringLevel the level (e.g., of logger, of listener) to filter messages
977+
* @param messageLevel the level of the message
978+
* @return {@code true}, if the sink level is less specific than the message level; {@code false}, otherwise
979+
*/
980+
private boolean isLevelEnabled(final Level filteringLevel, final Level messageLevel) {
981+
return config.debugEnabled || filteringLevel.isLessSpecificThan(messageLevel);
969982
}
970983
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xmlns="http://logging.apache.org/log4j/changelog"
4+
xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.3.xsd"
5+
type="fixed">
6+
<issue id="2337" link="https://github.com/apache/logging-log4j2/issues/2337"/>
7+
<description format="asciidoc">Fix `StatusLogger` log level filtering when debug mode is enabled</description>
8+
</entry>

0 commit comments

Comments
 (0)