You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by vy...@apache.org on 2023/06/05 20:04:38 UTC

[logging-log4j2] branch LevelRangeFilter-defaults created (now 0a097b4ffb)

This is an automated email from the ASF dual-hosted git repository.

vy pushed a change to branch LevelRangeFilter-defaults
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


      at 0a097b4ffb Set the default `minLevel` and `maxLevel` of `LevelRangeFilter` to `OFF` and `ALL`, respectively

This branch includes the following new commits:

     new 0a097b4ffb Set the default `minLevel` and `maxLevel` of `LevelRangeFilter` to `OFF` and `ALL`, respectively

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[logging-log4j2] 01/01: Set the default `minLevel` and `maxLevel` of `LevelRangeFilter` to `OFF` and `ALL`, respectively

Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch LevelRangeFilter-defaults
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 0a097b4ffb2234d16dddec3a59ca90f3238b476a
Author: Volkan Yazıcı <vo...@yazi.ci>
AuthorDate: Mon Jun 5 22:04:23 2023 +0200

    Set the default `minLevel` and `maxLevel` of `LevelRangeFilter` to `OFF` and `ALL`, respectively
---
 .../log4j/core/filter/LevelRangeFilterTest.java    | 84 +++++++++++++++-------
 .../log4j/core/filter/LevelRangeFilter.java        | 73 ++++++++++++-------
 .../1503_change_defaults_for_LevelRangeFilter.xml  | 25 +++++++
 src/site/xdoc/manual/filters.xml                   | 54 ++++++++++++++
 4 files changed, 186 insertions(+), 50 deletions(-)

diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/LevelRangeFilterTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/LevelRangeFilterTest.java
index 622503147f..7eab683c69 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/LevelRangeFilterTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/LevelRangeFilterTest.java
@@ -17,41 +17,77 @@
 package org.apache.logging.log4j.core.filter;
 
 import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.Filter.Result;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.message.SimpleMessage;
+import org.assertj.core.api.SoftAssertions;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
 
-import static org.junit.jupiter.api.Assertions.*;
+import static org.apache.logging.log4j.core.filter.LevelRangeFilter.createFilter;
+import static org.assertj.core.api.Assertions.assertThat;
 
-public class LevelRangeFilterTest {
+class LevelRangeFilterTest {
 
     @Test
-    public void testLevels() {
-        final LevelRangeFilter filter = LevelRangeFilter.createFilter(Level.ERROR, Level.INFO, null, null);
-        filter.start();
-        assertTrue(filter.isStarted());
-        assertSame(Filter.Result.DENY, filter.filter(null, Level.DEBUG, null, (Object) null, (Throwable) null));
-        assertSame(Filter.Result.NEUTRAL, filter.filter(null, Level.ERROR, null, (Object) null, (Throwable) null));
-        LogEvent event = Log4jLogEvent.newBuilder() //
-                .setLevel(Level.DEBUG) //
-                .setMessage(new SimpleMessage("Test")) //
-                .build();
-        assertSame(Filter.Result.DENY, filter.filter(event));
-        event = Log4jLogEvent.newBuilder() //
-                .setLevel(Level.ERROR) //
-                .setMessage(new SimpleMessage("Test")) //
-                .build();
-        assertSame(Filter.Result.NEUTRAL, filter.filter(event));
+    void verify_constants() {
+        assertThat(LevelRangeFilter.DEFAULT_MIN_LEVEL).isEqualTo(Level.OFF);
+        assertThat(LevelRangeFilter.DEFAULT_MAX_LEVEL).isEqualTo(Level.ALL);
+        assertThat(LevelRangeFilter.DEFAULT_ON_MATCH).isEqualTo(Result.NEUTRAL);
+        assertThat(LevelRangeFilter.DEFAULT_ON_MISMATCH).isEqualTo(Result.DENY);
+    }
+
+    @Test
+    void verify_defaults() {
+        final LevelRangeFilter filter = createFilter(null, null, null, null);
+        assertThat(filter.getMinLevel()).isEqualTo(Level.OFF);
+        assertThat(filter.getMaxLevel()).isEqualTo(Level.ALL);
+        assertThat(filter.getOnMatch()).isEqualTo(Result.NEUTRAL);
+        assertThat(filter.getOnMismatch()).isEqualTo(Result.DENY);
+    }
+
+    @ParameterizedTest
+    @MethodSource("org.apache.logging.log4j.Level#values")
+    void default_should_match_all_levels(final Level level) {
+        final LevelRangeFilter filter = createFilter(null, null, null, null);
+        assertThat(filter.filter(createEvent(level))).isEqualTo(LevelRangeFilter.DEFAULT_ON_MATCH);
     }
 
     @Test
-    public void testMinimumOnlyLevel() {
-        final LevelRangeFilter filter = LevelRangeFilter.createFilter(Level.ERROR, null, null, null);
-        filter.start();
-        assertTrue(filter.isStarted());
-        assertSame(Filter.Result.NEUTRAL, filter.filter(null, Level.ERROR, null, (Object) null, (Throwable) null));
+    void overriding_defaults_should_be_effective() {
+
+        // Choose a configuration
+        final Level minLevel = Level.ERROR;
+        final Level maxLevel = Level.WARN;
+        final Result onMatch = Result.ACCEPT;
+        final Result onMismatch = Result.NEUTRAL;
+
+        // Verify we deviate from the defaults
+        assertThat(minLevel).isNotEqualTo(LevelRangeFilter.DEFAULT_MIN_LEVEL);
+        assertThat(maxLevel).isNotEqualTo(LevelRangeFilter.DEFAULT_MAX_LEVEL);
+        assertThat(onMatch).isNotEqualTo(LevelRangeFilter.DEFAULT_ON_MATCH);
+        assertThat(onMismatch).isNotEqualTo(LevelRangeFilter.DEFAULT_ON_MISMATCH);
+
+        // Verify the filtering
+        final LevelRangeFilter filter = createFilter(minLevel, maxLevel, onMatch, onMismatch);
+        final SoftAssertions assertions = new SoftAssertions();
+        for (final Level level : Level.values()) {
+            final Result expectedResult = level.isInRange(minLevel, maxLevel) ? onMatch : onMismatch;
+            assertions.assertThat(filter.filter(createEvent(level))).isEqualTo(expectedResult);
+        }
+        assertions.assertAll();
+
+    }
+
+    private static LogEvent createEvent(final Level level) {
+        final SimpleMessage message = new SimpleMessage("test message at level " + level);
+        return Log4jLogEvent
+                .newBuilder()
+                .setLevel(level)
+                .setMessage(message)
+                .build();
     }
 
 }
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/LevelRangeFilter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/LevelRangeFilter.java
index 3f5194ce87..6207717ee0 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/LevelRangeFilter.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/LevelRangeFilter.java
@@ -29,13 +29,12 @@ import org.apache.logging.log4j.message.Message;
 import org.apache.logging.log4j.util.PerformanceSensitive;
 
 /**
- * This filter returns the {@code onMatch} result if the level in the {@code LogEvent} is in the range of the configured
- * min and max levels, otherwise it returns {@code onMismatch} value . For example, if the filter is configured with
- * {@link Level#ERROR} and {@link Level#INFO} and the LogEvent contains {@link Level#WARN} then the onMatch value will
- * be returned since {@link Level#WARN WARN} events are in between {@link Level#ERROR ERROR} and {@link Level#INFO
- * INFO}.
+ * 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.
+ * The default values for {@link #minLevel} and {@link #maxLevel} are set to {@link Level#OFF} and {@link Level#ALL}, respectively.
+ * The default values for {@link #onMatch} and {@link #onMismatch} are set to {@link Result#NEUTRAL} and {@link Result#DENY}, respectively.
  * <p>
- * The default Levels are both {@link Level#ERROR ERROR}.
+ * 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.
+ * 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.
  * </p>
  */
 @Plugin(name = "LevelRangeFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
@@ -43,33 +42,49 @@ import org.apache.logging.log4j.util.PerformanceSensitive;
 public final class LevelRangeFilter extends AbstractFilter {
 
     /**
-     * Creates a ThresholdFilter.
+     * The default minimum level threshold.
+     */
+    public static final Level DEFAULT_MIN_LEVEL = Level.OFF;
+
+    /**
+     * THe default maximum level threshold.
+     */
+    public static final Level DEFAULT_MAX_LEVEL = Level.ALL;
+
+    /**
+     * The default result on a match.
+     */
+    public static final Result DEFAULT_ON_MATCH = Result.NEUTRAL;
+
+    /**
+     * The default result on a mismatch.
+     */
+    public static final Result DEFAULT_ON_MISMATCH = Result.DENY;
+
+    /**
+     * Creates an instance with the provided properties.
      *
-     * @param minLevel
-     *            The minimum log Level.
-     * @param maxLevel
-     *            The maximum log Level.
-     * @param match
-     *            The action to take on a match.
-     * @param mismatch
-     *            The action to take on a mismatch.
-     * @return The created ThresholdFilter.
+     * @param minLevel the minimum level threshold
+     * @param maxLevel the maximum level threshold
+     * @param onMatch the result to return on a match
+     * @param onMismatch the result to return on a mismatch
+     * @return a new instance
      */
-    // TODO Consider refactoring to use AbstractFilter.AbstractFilterBuilder
     @PluginFactory
     public static LevelRangeFilter createFilter(
             // @formatter:off
             @PluginAttribute("minLevel") final Level minLevel,
             @PluginAttribute("maxLevel") final Level maxLevel,
-            @PluginAttribute("onMatch") final Result match,
-            @PluginAttribute("onMismatch") final Result mismatch) {
+            @PluginAttribute("onMatch") final Result onMatch,
+            @PluginAttribute("onMismatch") final Result onMismatch) {
             // @formatter:on
-        final Level actualMinLevel = minLevel == null ? Level.ERROR : minLevel;
-        final Level actualMaxLevel = maxLevel == null ? Level.ERROR : maxLevel;
-        final Result onMatch = match == null ? Result.NEUTRAL : match;
-        final Result onMismatch = mismatch == null ? Result.DENY : mismatch;
-        return new LevelRangeFilter(actualMinLevel, actualMaxLevel, onMatch, onMismatch);
+        final Level effectiveMinLevel = minLevel == null ? DEFAULT_MIN_LEVEL : minLevel;
+        final Level effectiveMaxLevel = maxLevel == null ? DEFAULT_MAX_LEVEL : maxLevel;
+        final Result effectiveOnMatch = onMatch == null ? DEFAULT_ON_MATCH : onMatch;
+        final Result effectiveOnMismatch = onMismatch == null ? DEFAULT_ON_MISMATCH : onMismatch;
+        return new LevelRangeFilter(effectiveMinLevel, effectiveMaxLevel, effectiveOnMatch, effectiveOnMismatch);
     }
+
     private final Level maxLevel;
 
     private final Level minLevel;
@@ -81,7 +96,7 @@ public final class LevelRangeFilter extends AbstractFilter {
     }
 
     private Result filter(final Level level) {
-        return level.isInRange(this.minLevel, this.maxLevel) ? onMatch : onMismatch;
+        return level.isInRange(minLevel, maxLevel) ? onMatch : onMismatch;
     }
 
     @Override
@@ -176,17 +191,23 @@ public final class LevelRangeFilter extends AbstractFilter {
         return filter(level);
     }
 
+    /**
+     * @return the minimum level threshold
+     */
     public Level getMinLevel() {
         return minLevel;
     }
 
+    /**
+     * @return the maximum level threshold
+     */
     public Level getMaxLevel() {
         return maxLevel;
     }
 
     @Override
     public String toString() {
-        return minLevel.toString();
+        return String.format("[%s,%s]", minLevel, maxLevel);
     }
 
 }
diff --git a/src/changelog/.2.x.x/1503_change_defaults_for_LevelRangeFilter.xml b/src/changelog/.2.x.x/1503_change_defaults_for_LevelRangeFilter.xml
new file mode 100644
index 0000000000..f08212ca6c
--- /dev/null
+++ b/src/changelog/.2.x.x/1503_change_defaults_for_LevelRangeFilter.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to you under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<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.1.xsd"
+       type="changed">
+  <issue id="1503" link="https://github.com/apache/logging-log4j2/pulls/1503"/>
+  <author id="vy"/>
+  <description format="asciidoc">Set the default `minLevel` and `maxLevel` of `LevelRangeFilter` to `OFF` and `ALL`, respectively</description>
+</entry>
diff --git a/src/site/xdoc/manual/filters.xml b/src/site/xdoc/manual/filters.xml
index c066e414c1..2947b993bc 100644
--- a/src/site/xdoc/manual/filters.xml
+++ b/src/site/xdoc/manual/filters.xml
@@ -235,6 +235,60 @@
   </Loggers>
 </Configuration>]]></pre>
         </subsection>
+
+        <a name="LevelRangeFilter"/>
+        <subsection name="LevelRangeFilter">
+          <p>
+            <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.
+          </p>
+          <table>
+            <caption align="top">Map Filter Parameters</caption>
+            <tr>
+              <th>Parameter Name</th>
+              <th>Type</th>
+              <th>Description</th>
+            </tr>
+            <tr>
+              <td><code>minLevel</code></td>
+              <td><code>Level</code></td>
+              <td>the minimum level threshold (defaults to <code>OFF</code>, which has an integral value of 0)</td>
+            </tr>
+            <tr>
+              <td><code>maxLevel</code></td>
+              <td><code>Level</code></td>
+              <td>the maximum level threshold (defaults to <code>ALL</code>, which has an integral value of <code>Integer.MAX_VALUE</code>)</td>
+            </tr>
+            <tr>
+              <td><code>onMatch</code></td>
+              <td><code>Filter.Result</code></td>
+              <td>the result to return on a match, where allowed values are <code>ACCEPT</code>, <code>DENY</code> or <code>NEUTRAL</code> (default)</td>
+            </tr>
+            <tr>
+              <td><code>onMismatch</code></td>
+              <td><code>Filter.Result</code></td>
+              <td>the result to return on a mismatch, where allowed values are <code>ACCEPT</code>, <code>DENY</code> (default) or <code>NEUTRAL</code></td>
+            </tr>
+          </table>
+          <p>
+            In the following example configuration, a <code>LevelRangeFilter</code> is configured with <code>maxLevel</code> set to <code>INFO</code>.
+            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.
+          </p>
+          <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="WARN" name="MyApp">
+  <Appenders>
+    <Console name="STDOUT">
+      <LevelRangeFilter maxLevel="INFO"/>
+      <PatternLayout pattern="%d %p %c{1.} [%t] %m%n"/>
+    </Console>
+  </Appenders>
+  <Loggers>
+    <Root level="ERROR">
+      <AppenderRef ref="STDOUT"/>
+    </Root>
+  </Loggers>
+</Configuration>]]></pre>
+        </subsection>
+
         <a name="MapFilter"/>
         <subsection name="MapFilter">
           <p>