This is an automated email from the ASF dual-hosted git repository. mattsicker pushed a commit to branch LOG4J2-3341 in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 8776e4837c2753dd68909fbf9039bf381fcc7fcf Author: Matt Sicker <[email protected]> AuthorDate: Thu Jan 27 22:27:05 2022 -0600 [LOG4J2-3341] Support logger level and appender refs shorthand This adds a properties format feature where the property names "rootLogger" and "logger.<key>" can be set to a level and one or more appender refs. Signed-off-by: Matt Sicker <[email protected]> --- .../properties/PropertiesConfigurationBuilder.java | 28 ++++++++++++++++------ .../properties/PropertiesConfigurationTest.java | 24 +++++++++++++++++++ .../resources/LoggerLevelAppenderTest.properties | 25 +++++++++++++++++++ .../RootLoggerLevelAppenderTest.properties | 22 +++++++++++++++++ 4 files changed, 92 insertions(+), 7 deletions(-) diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationBuilder.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationBuilder.java index 45a783d..803e7da 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationBuilder.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationBuilder.java @@ -17,10 +17,6 @@ package org.apache.logging.log4j.core.config.properties; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.TimeUnit; - import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.LoggerContext; @@ -45,6 +41,10 @@ import org.apache.logging.log4j.core.util.Builder; import org.apache.logging.log4j.util.PropertiesUtil; import org.apache.logging.log4j.util.Strings; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + /** * Helper builder for parsing properties files into a PropertiesConfiguration. * @@ -170,17 +170,20 @@ public class PropertiesConfigurationBuilder extends ConfigurationBuilderFactory } } } else { - final Map<String, Properties> loggers = PropertiesUtil - .partitionOnCommonPrefixes(PropertiesUtil.extractSubset(rootProperties, "logger")); + final Properties context = PropertiesUtil.extractSubset(rootProperties, "logger"); + final Map<String, Properties> loggers = PropertiesUtil.partitionOnCommonPrefixes(context); for (final Map.Entry<String, Properties> entry : loggers.entrySet()) { final String name = entry.getKey().trim(); if (!name.equals(LoggerConfig.ROOT)) { - builder.add(createLogger(name, entry.getValue())); + final Properties loggerProps = entry.getValue(); + useSyntheticLevelAndAppenderRefs(name, loggerProps, context); + builder.add(createLogger(name, loggerProps)); } } } final Properties props = PropertiesUtil.extractSubset(rootProperties, "rootLogger"); + useSyntheticLevelAndAppenderRefs("rootLogger", props, rootProperties); if (props.size() > 0) { builder.add(createRootLogger(props)); } @@ -190,6 +193,17 @@ public class PropertiesConfigurationBuilder extends ConfigurationBuilderFactory return builder.build(false); } + private static void useSyntheticLevelAndAppenderRefs(final String propertyName, final Properties loggerProps, final Properties context) { + final String propertyValue = (String) context.remove(propertyName); + if (propertyValue != null) { + final String[] parts = propertyValue.split(","); + loggerProps.setProperty("level", parts[0]); + for (int i = 1; i < parts.length; i++) { + loggerProps.setProperty("appenderRef.$" + i + ".ref", parts[i]); + } + } + } + private ScriptComponentBuilder createScript(final Properties properties) { final String name = (String) properties.remove("name"); final String language = (String) properties.remove("language"); diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationTest.java index 1a75512..ec6fcd5 100644 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationTest.java +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationTest.java @@ -22,12 +22,17 @@ import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Filter; import org.apache.logging.log4j.core.LifeCycle; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.LoggerConfig; import org.apache.logging.log4j.core.filter.ThresholdFilter; import org.apache.logging.log4j.junit.LoggerContextSource; +import org.apache.logging.log4j.junit.Named; +import org.apache.logging.log4j.test.appender.ListAppender; import org.junit.jupiter.api.Test; +import java.util.List; import java.util.Map; import static org.hamcrest.MatcherAssert.assertThat; @@ -106,4 +111,23 @@ class PropertiesConfigurationTest { logger.debug("Welcome to Log4j!"); } + + @Test + @LoggerContextSource("RootLoggerLevelAppenderTest.properties") + void testRootLoggerLevelAppender(final LoggerContext context, @Named final ListAppender app) { + context.getRootLogger().info("Hello world!"); + final List<LogEvent> events = app.getEvents(); + assertEquals(1, events.size()); + assertEquals("Hello world!", events.get(0).getMessage().getFormattedMessage()); + } + + @Test + @LoggerContextSource("LoggerLevelAppenderTest.properties") + void testLoggerLevelAppender(final LoggerContext context, @Named final ListAppender first, @Named final ListAppender second) { + context.getLogger(getClass()).atInfo().log("message"); + final List<LogEvent> firstEvents = first.getEvents(); + final List<LogEvent> secondEvents = second.getEvents(); + assertEquals(firstEvents, secondEvents); + assertEquals(1, firstEvents.size()); + } } diff --git a/log4j-core/src/test/resources/LoggerLevelAppenderTest.properties b/log4j-core/src/test/resources/LoggerLevelAppenderTest.properties new file mode 100644 index 0000000..a267694 --- /dev/null +++ b/log4j-core/src/test/resources/LoggerLevelAppenderTest.properties @@ -0,0 +1,25 @@ +# +# 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. +# + +status = all +name = LoggerLevelAppenderTest +logger.0.name = org.apache.logging.log4j.core.config.properties +logger.0 = INFO,first,second +appender.0.name = first +appender.0.type = List +appender.1.name = second +appender.1.type = List diff --git a/log4j-core/src/test/resources/RootLoggerLevelAppenderTest.properties b/log4j-core/src/test/resources/RootLoggerLevelAppenderTest.properties new file mode 100644 index 0000000..c40ceed --- /dev/null +++ b/log4j-core/src/test/resources/RootLoggerLevelAppenderTest.properties @@ -0,0 +1,22 @@ +# +# 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. +# + +status = off +name = RootLoggerLevelAppenderTest +rootLogger = INFO,app +appender.0.name = app +appender.0.type = List
