Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>