Skip to content

Commit 0a097b4

Browse files
committed
Set the default minLevel and maxLevel of LevelRangeFilter to OFF and ALL, respectively
1 parent 3f5da0a commit 0a097b4

File tree

4 files changed

+186
-50
lines changed

4 files changed

+186
-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: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -29,47 +29,62 @@
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
@Plugin(name = "LevelRangeFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
4241
@PerformanceSensitive("allocation")
4342
public final class LevelRangeFilter extends AbstractFilter {
4443

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

7590
private final Level minLevel;
@@ -81,7 +96,7 @@ private LevelRangeFilter(final Level minLevel, final Level maxLevel, final Resul
8196
}
8297

8398
private Result filter(final Level level) {
84-
return level.isInRange(this.minLevel, this.maxLevel) ? onMatch : onMismatch;
99+
return level.isInRange(minLevel, maxLevel) ? onMatch : onMismatch;
85100
}
86101

87102
@Override
@@ -176,17 +191,23 @@ public Result filter(final Logger logger, final Level level, final Marker marker
176191
return filter(level);
177192
}
178193

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

201+
/**
202+
* @return the maximum level threshold
203+
*/
183204
public Level getMaxLevel() {
184205
return maxLevel;
185206
}
186207

187208
@Override
188209
public String toString() {
189-
return minLevel.toString();
210+
return String.format("[%s,%s]", minLevel, maxLevel);
190211
}
191212

192213
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Licensed to the Apache Software Foundation (ASF) under one or more
4+
~ contributor license agreements. See the NOTICE file distributed with
5+
~ this work for additional information regarding copyright ownership.
6+
~ The ASF licenses this file to you under the Apache License, Version 2.0
7+
~ (the "License"); you may not use this file except in compliance with
8+
~ the License. You may obtain a copy of the License at
9+
~
10+
~ http://www.apache.org/licenses/LICENSE-2.0
11+
~
12+
~ Unless required by applicable law or agreed to in writing, software
13+
~ distributed under the License is distributed on an "AS IS" BASIS,
14+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
~ See the License for the specific language governing permissions and
16+
~ limitations under the License.
17+
-->
18+
<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19+
xmlns="http://logging.apache.org/log4j/changelog"
20+
xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.1.xsd"
21+
type="changed">
22+
<issue id="1503" link="https://github.com/apache/logging-log4j2/pulls/1503"/>
23+
<author id="vy"/>
24+
<description format="asciidoc">Set the default `minLevel` and `maxLevel` of `LevelRangeFilter` to `OFF` and `ALL`, respectively</description>
25+
</entry>

src/site/xdoc/manual/filters.xml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,60 @@
235235
</Loggers>
236236
</Configuration>]]></pre>
237237
</subsection>
238+
239+
<a name="LevelRangeFilter"/>
240+
<subsection name="LevelRangeFilter">
241+
<p>
242+
<code>LevelRangeFilter</code> allows filtering against a level range, where levels get compared by their associated integral values; <code>OFF</code> has an integral value of 0, <code>FATAL</code> 100, <code>ERROR</code> 200, and so on.
243+
</p>
244+
<table>
245+
<caption align="top">Map Filter Parameters</caption>
246+
<tr>
247+
<th>Parameter Name</th>
248+
<th>Type</th>
249+
<th>Description</th>
250+
</tr>
251+
<tr>
252+
<td><code>minLevel</code></td>
253+
<td><code>Level</code></td>
254+
<td>the minimum level threshold (defaults to <code>OFF</code>, which has an integral value of 0)</td>
255+
</tr>
256+
<tr>
257+
<td><code>maxLevel</code></td>
258+
<td><code>Level</code></td>
259+
<td>the maximum level threshold (defaults to <code>ALL</code>, which has an integral value of <code>Integer.MAX_VALUE</code>)</td>
260+
</tr>
261+
<tr>
262+
<td><code>onMatch</code></td>
263+
<td><code>Filter.Result</code></td>
264+
<td>the result to return on a match, where allowed values are <code>ACCEPT</code>, <code>DENY</code> or <code>NEUTRAL</code> (default)</td>
265+
</tr>
266+
<tr>
267+
<td><code>onMismatch</code></td>
268+
<td><code>Filter.Result</code></td>
269+
<td>the result to return on a mismatch, where allowed values are <code>ACCEPT</code>, <code>DENY</code> (default) or <code>NEUTRAL</code></td>
270+
</tr>
271+
</table>
272+
<p>
273+
In the following example configuration, a <code>LevelRangeFilter</code> is configured with <code>maxLevel</code> set to <code>INFO</code>.
274+
The filter will return <code>onMismatch</code> result (i.e., <code>DENY</code>, the default) for log events of level with higher integral values than <code>INFO</code>; i.e., <code>DEBUG</code>, <code>TRACE</code>, etc.
275+
</p>
276+
<pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
277+
<Configuration status="WARN" name="MyApp">
278+
<Appenders>
279+
<Console name="STDOUT">
280+
<LevelRangeFilter maxLevel="INFO"/>
281+
<PatternLayout pattern="%d %p %c{1.} [%t] %m%n"/>
282+
</Console>
283+
</Appenders>
284+
<Loggers>
285+
<Root level="ERROR">
286+
<AppenderRef ref="STDOUT"/>
287+
</Root>
288+
</Loggers>
289+
</Configuration>]]></pre>
290+
</subsection>
291+
238292
<a name="MapFilter"/>
239293
<subsection name="MapFilter">
240294
<p>

0 commit comments

Comments
 (0)