Skip to content

Commit

Permalink
Fix StatusLogger log level filtering when debug mode is enabled (#2337
Browse files Browse the repository at this point in the history
  • Loading branch information
vy committed Mar 1, 2024
1 parent 3060ab1 commit c542041
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,19 @@

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 {
Expand Down Expand Up @@ -104,4 +111,79 @@ void invalid_level_should_cause_fallback_to_defaults() throws Exception {
// 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());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,8 @@ private void notifyListeners(final StatusData statusData) {
}

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);
}
}
Expand Down Expand Up @@ -963,8 +964,20 @@ public boolean isEnabled(final Level level, final Marker marker, final Message m
}

@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);
}
}
8 changes: 8 additions & 0 deletions src/changelog/.2.x.x/fix_StatusLogger_debug_mode.xml
Original file line number Diff line number Diff line change
@@ -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>

0 comments on commit c542041

Please sign in to comment.