Skip to content

Commit 1ab36ca

Browse files
committed
Set the default minLevel/maxLevel of LevelRangeFilter to OFF/ALL (#1503)
1 parent 1930672 commit 1ab36ca

File tree

3 files changed

+161
-50
lines changed

3 files changed

+161
-50
lines changed

log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/LevelRangeFilterTest.java

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,41 +17,77 @@
1717
package org.apache.logging.log4j.core.filter;
1818

1919
import org.apache.logging.log4j.Level;
20-
import org.apache.logging.log4j.core.Filter;
20+
import org.apache.logging.log4j.core.Filter.Result;
2121
import org.apache.logging.log4j.core.LogEvent;
2222
import org.apache.logging.log4j.core.impl.Log4jLogEvent;
2323
import org.apache.logging.log4j.message.SimpleMessage;
24+
import org.assertj.core.api.SoftAssertions;
2425
import org.junit.jupiter.api.Test;
26+
import org.junit.jupiter.params.ParameterizedTest;
27+
import org.junit.jupiter.params.provider.MethodSource;
2528

26-
import static org.junit.jupiter.api.Assertions.*;
29+
import static org.apache.logging.log4j.core.filter.LevelRangeFilter.createFilter;
30+
import static org.assertj.core.api.Assertions.assertThat;
2731

28-
public class LevelRangeFilterTest {
32+
class LevelRangeFilterTest {
2933

3034
@Test
31-
public void testLevels() {
32-
final LevelRangeFilter filter = LevelRangeFilter.createFilter(Level.ERROR, Level.INFO, null, null);
33-
filter.start();
34-
assertTrue(filter.isStarted());
35-
assertSame(Filter.Result.DENY, filter.filter(null, Level.DEBUG, null, (Object) null, (Throwable) null));
36-
assertSame(Filter.Result.NEUTRAL, filter.filter(null, Level.ERROR, null, (Object) null, (Throwable) null));
37-
LogEvent event = Log4jLogEvent.newBuilder() //
38-
.setLevel(Level.DEBUG) //
39-
.setMessage(new SimpleMessage("Test")) //
40-
.build();
41-
assertSame(Filter.Result.DENY, filter.filter(event));
42-
event = Log4jLogEvent.newBuilder() //
43-
.setLevel(Level.ERROR) //
44-
.setMessage(new SimpleMessage("Test")) //
45-
.build();
46-
assertSame(Filter.Result.NEUTRAL, filter.filter(event));
35+
void verify_constants() {
36+
assertThat(LevelRangeFilter.DEFAULT_MIN_LEVEL).isEqualTo(Level.OFF);
37+
assertThat(LevelRangeFilter.DEFAULT_MAX_LEVEL).isEqualTo(Level.ALL);
38+
assertThat(LevelRangeFilter.DEFAULT_ON_MATCH).isEqualTo(Result.NEUTRAL);
39+
assertThat(LevelRangeFilter.DEFAULT_ON_MISMATCH).isEqualTo(Result.DENY);
40+
}
41+
42+
@Test
43+
void verify_defaults() {
44+
final LevelRangeFilter filter = createFilter(null, null, null, null);
45+
assertThat(filter.getMinLevel()).isEqualTo(Level.OFF);
46+
assertThat(filter.getMaxLevel()).isEqualTo(Level.ALL);
47+
assertThat(filter.getOnMatch()).isEqualTo(Result.NEUTRAL);
48+
assertThat(filter.getOnMismatch()).isEqualTo(Result.DENY);
49+
}
50+
51+
@ParameterizedTest
52+
@MethodSource("org.apache.logging.log4j.Level#values")
53+
void default_should_match_all_levels(final Level level) {
54+
final LevelRangeFilter filter = createFilter(null, null, null, null);
55+
assertThat(filter.filter(createEvent(level))).isEqualTo(LevelRangeFilter.DEFAULT_ON_MATCH);
4756
}
4857

4958
@Test
50-
public void testMinimumOnlyLevel() {
51-
final LevelRangeFilter filter = LevelRangeFilter.createFilter(Level.ERROR, null, null, null);
52-
filter.start();
53-
assertTrue(filter.isStarted());
54-
assertSame(Filter.Result.NEUTRAL, filter.filter(null, Level.ERROR, null, (Object) null, (Throwable) null));
59+
void overriding_defaults_should_be_effective() {
60+
61+
// Choose a configuration
62+
final Level minLevel = Level.ERROR;
63+
final Level maxLevel = Level.WARN;
64+
final Result onMatch = Result.ACCEPT;
65+
final Result onMismatch = Result.NEUTRAL;
66+
67+
// Verify we deviate from the defaults
68+
assertThat(minLevel).isNotEqualTo(LevelRangeFilter.DEFAULT_MIN_LEVEL);
69+
assertThat(maxLevel).isNotEqualTo(LevelRangeFilter.DEFAULT_MAX_LEVEL);
70+
assertThat(onMatch).isNotEqualTo(LevelRangeFilter.DEFAULT_ON_MATCH);
71+
assertThat(onMismatch).isNotEqualTo(LevelRangeFilter.DEFAULT_ON_MISMATCH);
72+
73+
// Verify the filtering
74+
final LevelRangeFilter filter = createFilter(minLevel, maxLevel, onMatch, onMismatch);
75+
final SoftAssertions assertions = new SoftAssertions();
76+
for (final Level level : Level.values()) {
77+
final Result expectedResult = level.isInRange(minLevel, maxLevel) ? onMatch : onMismatch;
78+
assertions.assertThat(filter.filter(createEvent(level))).isEqualTo(expectedResult);
79+
}
80+
assertions.assertAll();
81+
82+
}
83+
84+
private static LogEvent createEvent(final Level level) {
85+
final SimpleMessage message = new SimpleMessage("test message at level " + level);
86+
return Log4jLogEvent
87+
.newBuilder()
88+
.setLevel(level)
89+
.setMessage(message)
90+
.build();
5591
}
5692

5793
}

log4j-core/src/main/java/org/apache/logging/log4j/core/filter/LevelRangeFilter.java

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,12 @@
2929
import org.apache.logging.log4j.util.PerformanceSensitive;
3030

3131
/**
32-
* This filter returns the {@code onMatch} result if the level in the {@code LogEvent} is in the range of the configured
33-
* min and max levels, otherwise it returns {@code onMismatch} value . For example, if the filter is configured with
34-
* {@link Level#ERROR} and {@link Level#INFO} and the LogEvent contains {@link Level#WARN} then the onMatch value will
35-
* be returned since {@link Level#WARN WARN} events are in between {@link Level#ERROR ERROR} and {@link Level#INFO
36-
* INFO}.
32+
* This filter returns the {@link #onMatch} result if the level of the {@link LogEvent} is in the range of the configured {@link #minLevel} and {@link #maxLevel} values, otherwise it returns the {@link #onMismatch} result.
33+
* The default values for {@link #minLevel} and {@link #maxLevel} are set to {@link Level#OFF} and {@link Level#ALL}, respectively.
34+
* The default values for {@link #onMatch} and {@link #onMismatch} are set to {@link Result#NEUTRAL} and {@link Result#DENY}, respectively.
3735
* <p>
38-
* The default Levels are both {@link Level#ERROR ERROR}.
36+
* The levels get compared by their associated integral values; {@link Level#OFF} has an integral value of 0, {@link Level#FATAL} 100, {@link Level#ERROR} 200, and so on.
37+
* For example, if the filter is configured with {@link #maxLevel} set to {@link Level#INFO}, the filter will return {@link #onMismatch} result for {@link LogEvent}s of level with higher integral values; {@link Level#DEBUG}, {@link Level#TRACE}, etc.
3938
* </p>
4039
*/
4140
@Configurable(elementType = Filter.ELEMENT_TYPE, printObject = true)
@@ -44,33 +43,49 @@
4443
public final class LevelRangeFilter extends AbstractFilter {
4544

4645
/**
47-
* Creates a ThresholdFilter.
46+
* The default minimum level threshold.
47+
*/
48+
public static final Level DEFAULT_MIN_LEVEL = Level.OFF;
49+
50+
/**
51+
* THe default maximum level threshold.
52+
*/
53+
public static final Level DEFAULT_MAX_LEVEL = Level.ALL;
54+
55+
/**
56+
* The default result on a match.
57+
*/
58+
public static final Result DEFAULT_ON_MATCH = Result.NEUTRAL;
59+
60+
/**
61+
* The default result on a mismatch.
62+
*/
63+
public static final Result DEFAULT_ON_MISMATCH = Result.DENY;
64+
65+
/**
66+
* Creates an instance with the provided properties.
4867
*
49-
* @param minLevel
50-
* The minimum log Level.
51-
* @param maxLevel
52-
* The maximum log Level.
53-
* @param match
54-
* The action to take on a match.
55-
* @param mismatch
56-
* The action to take on a mismatch.
57-
* @return The created ThresholdFilter.
68+
* @param minLevel the minimum level threshold
69+
* @param maxLevel the maximum level threshold
70+
* @param onMatch the result to return on a match
71+
* @param onMismatch the result to return on a mismatch
72+
* @return a new instance
5873
*/
59-
// TODO Consider refactoring to use AbstractFilter.AbstractFilterBuilder
6074
@PluginFactory
6175
public static LevelRangeFilter createFilter(
6276
// @formatter:off
6377
@PluginAttribute final Level minLevel,
6478
@PluginAttribute final Level maxLevel,
65-
@PluginAttribute final Result match,
66-
@PluginAttribute final Result mismatch) {
79+
@PluginAttribute final Result onMatch,
80+
@PluginAttribute final Result onMismatch) {
6781
// @formatter:on
68-
final Level actualMinLevel = minLevel == null ? Level.ERROR : minLevel;
69-
final Level actualMaxLevel = maxLevel == null ? Level.ERROR : maxLevel;
70-
final Result onMatch = match == null ? Result.NEUTRAL : match;
71-
final Result onMismatch = mismatch == null ? Result.DENY : mismatch;
72-
return new LevelRangeFilter(actualMinLevel, actualMaxLevel, onMatch, onMismatch);
82+
final Level effectiveMinLevel = minLevel == null ? DEFAULT_MIN_LEVEL : minLevel;
83+
final Level effectiveMaxLevel = maxLevel == null ? DEFAULT_MAX_LEVEL : maxLevel;
84+
final Result effectiveOnMatch = onMatch == null ? DEFAULT_ON_MATCH : onMatch;
85+
final Result effectiveOnMismatch = onMismatch == null ? DEFAULT_ON_MISMATCH : onMismatch;
86+
return new LevelRangeFilter(effectiveMinLevel, effectiveMaxLevel, effectiveOnMatch, effectiveOnMismatch);
7387
}
88+
7489
private final Level maxLevel;
7590

7691
private final Level minLevel;
@@ -82,7 +97,7 @@ private LevelRangeFilter(final Level minLevel, final Level maxLevel, final Resul
8297
}
8398

8499
private Result filter(final Level level) {
85-
return level.isInRange(this.minLevel, this.maxLevel) ? onMatch : onMismatch;
100+
return level.isInRange(minLevel, maxLevel) ? onMatch : onMismatch;
86101
}
87102

88103
@Override
@@ -177,13 +192,23 @@ public Result filter(final Logger logger, final Level level, final Marker marker
177192
return filter(level);
178193
}
179194

195+
/**
196+
* @return the minimum level threshold
197+
*/
180198
public Level getMinLevel() {
181199
return minLevel;
182200
}
183201

202+
/**
203+
* @return the maximum level threshold
204+
*/
205+
public Level getMaxLevel() {
206+
return maxLevel;
207+
}
208+
184209
@Override
185210
public String toString() {
186-
return minLevel.toString();
211+
return String.format("[%s,%s]", minLevel, maxLevel);
187212
}
188213

189214
}

src/site/asciidoc/manual/filters.adoc

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
////
1717
= Filters
1818
Ralph Goers <[email protected]>
19+
Volkan Yazıcı <[email protected]>
1920
2021
++++
2122
<link rel="stylesheet" type="text/css" href="../css/tables.css">
@@ -224,6 +225,55 @@ Here is a sample configuration containing the DynamicThresholdFilter:
224225
</Configuration>
225226
----
226227
228+
[#LevelRangeFilter]
229+
== LevelRangeFilter
230+
231+
`LevelRangeFilter` allows filtering against a level range, where levels get compared by their associated integral values; `OFF` has an integral value of 0, `FATAL` 100, `ERROR` 200, and so on.
232+
233+
.`LevelRangeFilter` parameters
234+
[cols="1m,1m,4"]
235+
|===
236+
|Parameter Name |Type |Description
237+
238+
|minLevel
239+
|Level
240+
|the minimum level threshold (defaults to `OFF`, which has an integral value of 0)
241+
242+
|maxLevel
243+
|Level
244+
|the maximum level threshold (defaults to `ALL`, which has an integral value of `Integer.MAX_VALUE`)
245+
246+
|onMatch
247+
|Filter.Result
248+
|the result to return on a match, where allowed values are `ACCEPT`, `DENY`, or `NEUTRAL` (default)
249+
250+
|onMismatch
251+
|Filter.Result
252+
|the result to return on a mismatch, where allowed values are `ACCEPT`, `DENY` (default), or `NEUTRAL`
253+
|===
254+
255+
In the following example configuration, a `LevelRangeFilter` is configured with `maxLevel` set to `INFO`.
256+
The filter will return `onMismatch` result (i.e., `DENY`, the default) for log events of level with higher integral values than `INFO`; i.e., `DEBUG`, `TRACE`, etc.
257+
258+
.Example configuration using `LevelRangeFilter`
259+
[source,xml]
260+
----
261+
<?xml version="1.0" encoding="UTF-8"?>
262+
<Configuration status="WARN" name="MyApp">
263+
<Appenders>
264+
<Console name="STDOUT">
265+
<LevelRangeFilter maxLevel="INFO"/>
266+
<PatternLayout pattern="%d %p %c{1.} [%t] %m%n"/>
267+
</Console>
268+
</Appenders>
269+
<Loggers>
270+
<Root level="ERROR">
271+
<AppenderRef ref="STDOUT"/>
272+
</Root>
273+
</Loggers>
274+
</Configuration>
275+
----
276+
227277
[#MapFilter]
228278
== MapFilter
229279

0 commit comments

Comments
 (0)