You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by pk...@apache.org on 2022/06/13 09:07:05 UTC
[logging-log4j2] branch release-2.x updated: [LOG4J2-3534] Fix LevelRangeFilterBuilder to align with log4j1's behavior (#924)
This is an automated email from the ASF dual-hosted git repository.
pkarwasz pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/release-2.x by this push:
new c2d049d947 [LOG4J2-3534] Fix LevelRangeFilterBuilder to align with log4j1's behavior (#924)
c2d049d947 is described below
commit c2d049d947da1f650862437df036fea470ff2869
Author: Yohei Ueki <yu...@users.noreply.github.com>
AuthorDate: Mon Jun 13 18:06:57 2022 +0900
[LOG4J2-3534] Fix LevelRangeFilterBuilder to align with log4j1's behavior (#924)
The current `LevelRangeFilterBuilder` does not take into account the inversion of the level scale between Log4j 1 and Log4j 2: a minimal Log4j 1 level corresponds to a maximal Log4j 2 level and vice versa.
---
.../builders/filter/LevelRangeFilterBuilder.java | 21 +-
.../filter/LevelRangeFilterBuilderTest.java | 211 +++++++++++++++++++++
.../config/AbstractLog4j1ConfigurationTest.java | 29 +++
.../log4j/config/PropertiesConfigurationTest.java | 41 +++-
.../apache/log4j/config/XmlConfigurationTest.java | 5 +
.../src/test/resources/LOG4J2-3326.properties | 49 ++---
.../log4j-LevelRangeFilter.properties} | 46 ++---
.../config-1.2/log4j-LevelRangeFilter.xml | 32 ++++
.../log4j/core/filter/LevelRangeFilter.java | 4 +
src/changes/changes.xml | 3 +
10 files changed, 384 insertions(+), 57 deletions(-)
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/LevelRangeFilterBuilder.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/LevelRangeFilterBuilder.java
index ca103fe2cb..615b4a0a73 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/LevelRangeFilterBuilder.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/LevelRangeFilterBuilder.java
@@ -35,7 +35,10 @@ import org.apache.logging.log4j.core.filter.LevelRangeFilter;
import org.w3c.dom.Element;
/**
- * Build a Level match failter.
+ * Build a Level range filter.
+ * In this class, order of {@link Level} is log4j1 way, i.e.,
+ * {@link Level#ALL} and {@link Level#OFF} have minimum and maximum order, respectively.
+ * (see: LOG4J2-2315)
*/
@Plugin(name = "org.apache.log4j.varia.LevelRangeFilter", category = CATEGORY)
public class LevelRangeFilterBuilder extends AbstractBuilder<Filter> implements FilterBuilder {
@@ -63,7 +66,7 @@ public class LevelRangeFilterBuilder extends AbstractBuilder<Filter> implements
levelMax.set(getValueAttribute(currentElement));
break;
case LEVEL_MIN:
- levelMax.set(getValueAttribute(currentElement));
+ levelMin.set(getValueAttribute(currentElement));
break;
case ACCEPT_ON_MATCH:
acceptOnMatch.set(getBooleanValueAttribute(currentElement));
@@ -83,19 +86,23 @@ public class LevelRangeFilterBuilder extends AbstractBuilder<Filter> implements
}
private Filter createFilter(String levelMax, String levelMin, boolean acceptOnMatch) {
- Level max = Level.FATAL;
- Level min = Level.TRACE;
+ Level max = Level.OFF;
+ Level min = Level.ALL;
if (levelMax != null) {
- max = OptionConverter.toLevel(levelMax, org.apache.log4j.Level.FATAL).getVersion2Level();
+ max = OptionConverter.toLevel(levelMax, org.apache.log4j.Level.OFF).getVersion2Level();
}
if (levelMin != null) {
- min = OptionConverter.toLevel(levelMin, org.apache.log4j.Level.DEBUG).getVersion2Level();
+ min = OptionConverter.toLevel(levelMin, org.apache.log4j.Level.ALL).getVersion2Level();
}
org.apache.logging.log4j.core.Filter.Result onMatch = acceptOnMatch
? org.apache.logging.log4j.core.Filter.Result.ACCEPT
: org.apache.logging.log4j.core.Filter.Result.NEUTRAL;
- return FilterWrapper.adapt(LevelRangeFilter.createFilter(min, max, onMatch,
+ // XXX: LOG4J2-2315
+ // log4j1 order: ALL < TRACE < DEBUG < ... < FATAL < OFF
+ // log4j2 order: ALL > TRACE > DEBUG > ... > FATAL > OFF
+ // So we create as LevelRangeFilter.createFilter(minLevel=max, maxLevel=min, ...)
+ return FilterWrapper.adapt(LevelRangeFilter.createFilter(max, min, onMatch,
org.apache.logging.log4j.core.Filter.Result.DENY));
}
}
diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/builders/filter/LevelRangeFilterBuilderTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/builders/filter/LevelRangeFilterBuilderTest.java
new file mode 100644
index 0000000000..327ea823c2
--- /dev/null
+++ b/log4j-1.2-api/src/test/java/org/apache/log4j/builders/filter/LevelRangeFilterBuilderTest.java
@@ -0,0 +1,211 @@
+/*
+ * 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.
+ */
+package org.apache.log4j.builders.filter;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.io.StringReader;
+import java.util.Properties;
+import java.util.stream.Stream;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.log4j.bridge.FilterWrapper;
+import org.apache.log4j.spi.Filter;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Filter.Result;
+import org.apache.logging.log4j.core.filter.LevelRangeFilter;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
+import org.junit.jupiter.params.provider.ArgumentsSource;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+
+public class LevelRangeFilterBuilderTest {
+
+ @ParameterizedTest
+ @ArgumentsSource(TestLevelRangeFilterBuilderProvider.class)
+ public void testAcceptOnMatchTrue(TestLevelRangeFilterBuilder builder) throws Exception {
+ LevelRangeFilter levelRangeFilter = builder.build(Level.INFO, Level.ERROR, true);
+
+ assertResult(Result.DENY, levelRangeFilter, Level.ALL);
+ assertResult(Result.DENY, levelRangeFilter, Level.DEBUG);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.INFO);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.WARN);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.ERROR);
+ assertResult(Result.DENY, levelRangeFilter, Level.FATAL);
+ assertResult(Result.DENY, levelRangeFilter, Level.OFF);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(TestLevelRangeFilterBuilderProvider.class)
+ public void testAcceptOnMatchFalse(TestLevelRangeFilterBuilder builder) throws Exception {
+ LevelRangeFilter levelRangeFilter = builder.build(Level.INFO, Level.ERROR, false);
+
+ assertResult(Result.DENY, levelRangeFilter, Level.ALL);
+ assertResult(Result.DENY, levelRangeFilter, Level.DEBUG);
+ assertResult(Result.NEUTRAL, levelRangeFilter, Level.INFO);
+ assertResult(Result.NEUTRAL, levelRangeFilter, Level.WARN);
+ assertResult(Result.NEUTRAL, levelRangeFilter, Level.ERROR);
+ assertResult(Result.DENY, levelRangeFilter, Level.FATAL);
+ assertResult(Result.DENY, levelRangeFilter, Level.OFF);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(TestLevelRangeFilterBuilderProvider.class)
+ public void testAcceptOnMatchNull(TestLevelRangeFilterBuilder builder) throws Exception {
+ LevelRangeFilter levelRangeFilter = builder.build(Level.INFO, Level.ERROR, null);
+
+ assertResult(Result.DENY, levelRangeFilter, Level.ALL);
+ assertResult(Result.DENY, levelRangeFilter, Level.DEBUG);
+ assertResult(Result.NEUTRAL, levelRangeFilter, Level.INFO);
+ assertResult(Result.NEUTRAL, levelRangeFilter, Level.WARN);
+ assertResult(Result.NEUTRAL, levelRangeFilter, Level.ERROR);
+ assertResult(Result.DENY, levelRangeFilter, Level.FATAL);
+ assertResult(Result.DENY, levelRangeFilter, Level.OFF);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(TestLevelRangeFilterBuilderProvider.class)
+ public void testMinLevelNull(TestLevelRangeFilterBuilder builder) throws Exception {
+ LevelRangeFilter levelRangeFilter = builder.build(null, Level.ERROR, true);
+
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.ALL);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.DEBUG);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.INFO);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.WARN);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.ERROR);
+ assertResult(Result.DENY, levelRangeFilter, Level.FATAL);
+ assertResult(Result.DENY, levelRangeFilter, Level.OFF);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(TestLevelRangeFilterBuilderProvider.class)
+ public void testMaxLevelNull(TestLevelRangeFilterBuilder builder) throws Exception {
+ LevelRangeFilter levelRangeFilter = builder.build(Level.INFO, null, true);
+
+ assertResult(Result.DENY, levelRangeFilter, Level.ALL);
+ assertResult(Result.DENY, levelRangeFilter, Level.DEBUG);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.INFO);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.WARN);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.ERROR);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.FATAL);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.OFF);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(TestLevelRangeFilterBuilderProvider.class)
+ public void testMinMaxLevelSame(TestLevelRangeFilterBuilder builder) throws Exception {
+ LevelRangeFilter levelRangeFilter = builder.build(Level.INFO, Level.INFO, true);
+
+ assertResult(Result.DENY, levelRangeFilter, Level.ALL);
+ assertResult(Result.DENY, levelRangeFilter, Level.DEBUG);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.INFO);
+ assertResult(Result.DENY, levelRangeFilter, Level.WARN);
+ assertResult(Result.DENY, levelRangeFilter, Level.ERROR);
+ assertResult(Result.DENY, levelRangeFilter, Level.FATAL);
+ assertResult(Result.DENY, levelRangeFilter, Level.OFF);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(TestLevelRangeFilterBuilderProvider.class)
+ public void testMinMaxLevelNull(TestLevelRangeFilterBuilder builder) throws Exception {
+ LevelRangeFilter levelRangeFilter = builder.build(null, null, true);
+
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.ALL);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.DEBUG);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.INFO);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.WARN);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.ERROR);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.FATAL);
+ assertResult(Result.ACCEPT, levelRangeFilter, Level.OFF);
+ }
+
+ private static void assertResult(Result expected, LevelRangeFilter filter, Level level) {
+ assertSame(expected, filter.filter(null, level, null, (Object) null, null));
+ }
+
+ private static class TestLevelRangeFilterBuilderProvider implements ArgumentsProvider {
+
+ @Override
+ public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) {
+ return Stream.of(
+ Arguments.of(new TestLevelRangeFilterFromXmlBuilder()),
+ Arguments.of(new TestLevelRangeFilterFromPropertyBuilder())
+ );
+ }
+ }
+
+ private interface TestLevelRangeFilterBuilder {
+
+ LevelRangeFilter build(Level levelMin, Level levelMax, Boolean acceptOnMatch) throws Exception;
+ }
+
+ private static class TestLevelRangeFilterFromXmlBuilder implements TestLevelRangeFilterBuilder {
+
+ @Override
+ public LevelRangeFilter build(Level levelMin, Level levelMax, Boolean acceptOnMatch) throws Exception {
+ LevelRangeFilterBuilder builder = new LevelRangeFilterBuilder();
+ Filter filter = builder.parse(generateTestXml(levelMin, levelMax, acceptOnMatch), null);
+ org.apache.logging.log4j.core.Filter wrappedFilter = ((FilterWrapper) filter).getFilter();
+ return (LevelRangeFilter) wrappedFilter;
+ }
+
+ private static Element generateTestXml(Level levelMin, Level levelMax, Boolean acceptOnMatch) throws Exception {
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("<filter class=\"org.apache.log4j.varia.LevelRangeFilter\">\n");
+ if (levelMin != null) {
+ sb.append(String.format("<param name=\"LevelMin\" value=\"%s\"/>\n", levelMin));
+ }
+ if (levelMax != null) {
+ sb.append(String.format("<param name=\"LevelMax\" value=\"%s\"/>\n", levelMax));
+ }
+ if (acceptOnMatch != null) {
+ sb.append(String.format("<param name=\"AcceptOnMatch\" value=\"%b\"/>\n", acceptOnMatch));
+ }
+ sb.append("</filter>");
+
+ return DocumentBuilderFactory.newInstance().newDocumentBuilder()
+ .parse(new InputSource(new StringReader(sb.toString())))
+ .getDocumentElement();
+ }
+ }
+
+ private static class TestLevelRangeFilterFromPropertyBuilder implements TestLevelRangeFilterBuilder {
+
+ @Override
+ public LevelRangeFilter build(Level levelMin, Level levelMax, Boolean acceptOnMatch) {
+ Properties properties = new Properties();
+ if (levelMin != null) {
+ properties.setProperty("foobar.levelMin", levelMin.name());
+ }
+ if (levelMax != null) {
+ properties.setProperty("foobar.levelMax", levelMax.name());
+ }
+ if (acceptOnMatch != null) {
+ properties.setProperty("foobar.acceptOnMatch", acceptOnMatch.toString());
+ }
+ LevelRangeFilterBuilder builder = new LevelRangeFilterBuilder("foobar", properties);
+ Filter filter = builder.parse(null);
+ org.apache.logging.log4j.core.Filter wrappedFilter = ((FilterWrapper) filter).getFilter();
+ return (LevelRangeFilter) wrappedFilter;
+ }
+ }
+}
diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java
index 34fdb03d5b..566d768a61 100644
--- a/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java
+++ b/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java
@@ -611,4 +611,33 @@ public abstract class AbstractLog4j1ConfigurationTest {
assertEquals(11, defaultRolloverStrategy.getMinIndex());
assertEquals(20, defaultRolloverStrategy.getMaxIndex());
}
+
+ protected void testLevelRangeFilter() throws Exception {
+ try (final LoggerContext ctx = configure("config-1.2/log4j-LevelRangeFilter")) {
+ final Configuration config = ctx.getConfiguration();
+ final Logger logger = LogManager.getLogger(PropertiesConfigurationTest.class);
+ // List appender
+ final Appender appender = config.getAppender("LIST");
+ assertNotNull(appender);
+ final ListAppender legacyAppender = (ListAppender) ((Adapter) appender).getAppender();
+ // deny
+ logger.trace("TRACE");
+ assertEquals(0, legacyAppender.getEvents().size());
+ // deny
+ logger.debug("DEBUG");
+ assertEquals(0, legacyAppender.getEvents().size());
+ // accept
+ logger.info("INFO");
+ assertEquals(1, legacyAppender.getEvents().size());
+ // accept
+ logger.warn("WARN");
+ assertEquals(2, legacyAppender.getEvents().size());
+ // accept
+ logger.error("ERROR");
+ assertEquals(3, legacyAppender.getEvents().size());
+ // deny
+ logger.fatal("FATAL");
+ assertEquals(3, legacyAppender.getEvents().size());
+ }
+ }
}
diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationTest.java
index 219848abba..98ce9dfbc7 100644
--- a/log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationTest.java
+++ b/log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationTest.java
@@ -125,10 +125,38 @@ public class PropertiesConfigurationTest extends AbstractLog4j1ConfigurationTest
final Filterable filterable = (Filterable) appender;
final CompositeFilter filter = (CompositeFilter) filterable.getFilter();
final org.apache.logging.log4j.core.Filter[] filters = filter.getFiltersArray();
- final LevelRangeFilter customFilterReal = (LevelRangeFilter) filters[0];
- assertEquals(Level.ALL, customFilterReal.getMinLevel());
- final LevelRangeFilter defaultFilter = (LevelRangeFilter) filters[1];
- assertEquals(Level.TRACE, defaultFilter.getMinLevel());
+ final LevelRangeFilter filter1 = (LevelRangeFilter) filters[0];
+ // XXX: LOG4J2-2315
+ assertEquals(Level.OFF, filter1.getMinLevel());
+ assertEquals(Level.ALL, filter1.getMaxLevel());
+ final LevelRangeFilter filter2 = (LevelRangeFilter) filters[1];
+ assertEquals(Level.ERROR, filter2.getMinLevel());
+ assertEquals(Level.INFO, filter2.getMaxLevel());
+ final LevelRangeFilter filter3 = (LevelRangeFilter) filters[2];
+ assertEquals(Level.OFF, filter3.getMinLevel());
+ assertEquals(Level.ALL, filter3.getMaxLevel());
+
+ final ListAppender legacyAppender = (ListAppender) ((AppenderAdapter.Adapter) appender).getAppender();
+ final Logger logger = LogManager.getLogger(PropertiesConfigurationTest.class);
+
+ // deny
+ logger.trace("TRACE");
+ assertEquals(0, legacyAppender.getEvents().size());
+ // deny
+ logger.debug("DEBUG");
+ assertEquals(0, legacyAppender.getEvents().size());
+ // accept
+ logger.info("INFO");
+ assertEquals(1, legacyAppender.getEvents().size());
+ // accept
+ logger.warn("WARN");
+ assertEquals(2, legacyAppender.getEvents().size());
+ // accept
+ logger.error("ERROR");
+ assertEquals(3, legacyAppender.getEvents().size());
+ // deny
+ logger.fatal("FATAL");
+ assertEquals(3, legacyAppender.getEvents().size());
}
}
@@ -326,4 +354,9 @@ public class PropertiesConfigurationTest extends AbstractLog4j1ConfigurationTest
}
}
+ @Override
+ @Test
+ public void testLevelRangeFilter() throws Exception {
+ super.testLevelRangeFilter();
+ }
}
diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.java
index bec639f202..f314e1bee2 100644
--- a/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.java
+++ b/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.java
@@ -202,4 +202,9 @@ public class XmlConfigurationTest extends AbstractLog4j1ConfigurationTest {
}
}
+ @Override
+ @Test
+ public void testLevelRangeFilter() throws Exception {
+ super.testLevelRangeFilter();
+ }
}
diff --git a/log4j-1.2-api/src/test/resources/LOG4J2-3326.properties b/log4j-1.2-api/src/test/resources/LOG4J2-3326.properties
index e21d0d394c..492aba876b 100644
--- a/log4j-1.2-api/src/test/resources/LOG4J2-3326.properties
+++ b/log4j-1.2-api/src/test/resources/LOG4J2-3326.properties
@@ -1,23 +1,26 @@
-#
-# 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.
-#
-
-log4j.appender.CUSTOM=org.apache.log4j.CustomNoopAppender
-log4j.appender.CUSTOM.filter.1=org.apache.log4j.varia.LevelRangeFilter
-log4j.appender.CUSTOM.filter.1.levelMin=ALL
-log4j.appender.CUSTOM.filter.2=org.apache.log4j.varia.LevelRangeFilter
-
-log4j.rootLogger=trace, CUSTOM
+#
+# 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.
+#
+
+log4j.appender.CUSTOM=org.apache.log4j.ListAppender
+log4j.appender.CUSTOM.filter.1=org.apache.log4j.varia.LevelRangeFilter
+log4j.appender.CUSTOM.filter.1.levelMin=ALL
+log4j.appender.CUSTOM.filter.2=org.apache.log4j.varia.LevelRangeFilter
+log4j.appender.CUSTOM.filter.2.levelMin=INFO
+log4j.appender.CUSTOM.filter.2.levelMax=ERROR
+log4j.appender.CUSTOM.filter.3=org.apache.log4j.varia.LevelRangeFilter
+
+log4j.rootLogger=trace, CUSTOM
diff --git a/log4j-1.2-api/src/test/resources/LOG4J2-3326.properties b/log4j-1.2-api/src/test/resources/config-1.2/log4j-LevelRangeFilter.properties
similarity index 73%
copy from log4j-1.2-api/src/test/resources/LOG4J2-3326.properties
copy to log4j-1.2-api/src/test/resources/config-1.2/log4j-LevelRangeFilter.properties
index e21d0d394c..1ba8c5bcb1 100644
--- a/log4j-1.2-api/src/test/resources/LOG4J2-3326.properties
+++ b/log4j-1.2-api/src/test/resources/config-1.2/log4j-LevelRangeFilter.properties
@@ -1,23 +1,23 @@
-#
-# 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.
-#
-
-log4j.appender.CUSTOM=org.apache.log4j.CustomNoopAppender
-log4j.appender.CUSTOM.filter.1=org.apache.log4j.varia.LevelRangeFilter
-log4j.appender.CUSTOM.filter.1.levelMin=ALL
-log4j.appender.CUSTOM.filter.2=org.apache.log4j.varia.LevelRangeFilter
-
-log4j.rootLogger=trace, CUSTOM
+#
+# 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.
+#
+
+log4j.appender.LIST = org.apache.log4j.ListAppender
+log4j.appender.LIST.filter.1 = org.apache.log4j.varia.LevelRangeFilter
+log4j.appender.LIST.filter.1.LevelMin = INFO
+log4j.appender.LIST.filter.1.LevelMax = ERROR
+log4j.appender.LIST.filter.1.AcceptOnMatch = false
+log4j.rootLogger = debug, LIST
diff --git a/log4j-1.2-api/src/test/resources/config-1.2/log4j-LevelRangeFilter.xml b/log4j-1.2-api/src/test/resources/config-1.2/log4j-LevelRangeFilter.xml
new file mode 100644
index 0000000000..87db868e32
--- /dev/null
+++ b/log4j-1.2-api/src/test/resources/config-1.2/log4j-LevelRangeFilter.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="LIST" class="org.apache.log4j.ListAppender">
+ <filter class="org.apache.log4j.varia.LevelRangeFilter">
+ <param name="levelMin" value="INFO"/>
+ <param name="levelMax" value="ERROR"/>
+ <param name="AcceptOnMatch" value="false"/>
+ </filter>
+ </appender>
+
+ <root>
+ <priority value="debug"/>
+ <appender-ref ref="LIST"/>
+ </root>
+</log4j:configuration>
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 0e79b8508f..18b6d0be5c 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
@@ -180,6 +180,10 @@ public final class LevelRangeFilter extends AbstractFilter {
return minLevel;
}
+ public Level getMaxLevel() {
+ return maxLevel;
+ }
+
@Override
public String toString() {
return minLevel.toString();
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 943729ec6e..2533905c85 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -30,6 +30,9 @@
- "remove" - Removed
-->
<release version="2.18.0" date="2022-MM-DD" description="GA Release 2.18.0">
+ <action issue="LOG4J2-3534" dev="yueki1993" type="fix">
+ Fix LevelRangeFilterBuilder to align with log4j1's behavior.
+ </action>
<action issue="LOG4J2-3527" dev="rgoers" type="fix">
Don't use Paths.get() to avoid circular file systems.
</action>