[LOG4J2-1146] Add %notEmpty to PatternLayout to avoid output of patterns where all variables are empty.
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/d41f343c Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/d41f343c Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/d41f343c Branch: refs/heads/LOG4J2-1136 Commit: d41f343c47bdb64c96ec9148857b529cf4da687b Parents: b902020 Author: ggregory <[email protected]> Authored: Fri Oct 2 11:54:39 2015 -0700 Committer: Ralph Goers <[email protected]> Committed: Sat Oct 3 23:08:06 2015 -0700 ---------------------------------------------------------------------- .../core/pattern/LiteralPatternConverter.java | 6 ++ .../core/pattern/LogEventPatternConverter.java | 4 + .../VariablesNotEmptyReplacementConverter.java | 91 ++++++++++++++++++++ ...riablesNotEmptyReplacementConverterTest.java | 78 +++++++++++++++++ src/changes/changes.xml | 3 + src/site/xdoc/manual/layouts.xml.vm | 17 ++++ 6 files changed, 199 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d41f343c/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LiteralPatternConverter.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LiteralPatternConverter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LiteralPatternConverter.java index 2722bff..0751bca 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LiteralPatternConverter.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LiteralPatternConverter.java @@ -79,7 +79,13 @@ public final class LiteralPatternConverter extends LogEventPatternConverter impl } @Override + public boolean isVariable() { + return false; + } + + @Override public String toString() { return "LiteralPatternConverter[literal=" + literal + ", config=" + config + ", substitute=" + substitute + "]"; } + } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d41f343c/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LogEventPatternConverter.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LogEventPatternConverter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LogEventPatternConverter.java index d42f300..84cee32 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LogEventPatternConverter.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LogEventPatternConverter.java @@ -64,4 +64,8 @@ public abstract class LogEventPatternConverter extends AbstractPatternConverter public boolean handlesThrowable() { return false; } + + public boolean isVariable() { + return true; + } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d41f343c/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/VariablesNotEmptyReplacementConverter.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/VariablesNotEmptyReplacementConverter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/VariablesNotEmptyReplacementConverter.java new file mode 100644 index 0000000..ea16266 --- /dev/null +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/VariablesNotEmptyReplacementConverter.java @@ -0,0 +1,91 @@ +/* + * 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.logging.log4j.core.pattern; + +import java.util.List; + +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.config.Configuration; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.layout.PatternLayout; + +/** + * VariablesNotEmpty pattern converter. + */ +@Plugin(name = "notEmpty", category = PatternConverter.CATEGORY) +@ConverterKeys({ "notEmpty", "varsNotEmpty", "variablesNotEmpty", }) +public final class VariablesNotEmptyReplacementConverter extends LogEventPatternConverter { + + /** + * Gets an instance of the class. + * + * @param config + * The current Configuration. + * @param options + * pattern options, may be null. + * @return instance of class. + */ + public static VariablesNotEmptyReplacementConverter newInstance(final Configuration config, + final String[] options) { + if (options.length != 1) { + LOGGER.error("Incorrect number of options on varsNotEmpty. Expected 1 received " + options.length); + return null; + } + if (options[0] == null) { + LOGGER.error("No pattern supplied on varsNotEmpty"); + return null; + } + final PatternParser parser = PatternLayout.createPatternParser(config); + final List<PatternFormatter> formatters = parser.parse(options[0]); + return new VariablesNotEmptyReplacementConverter(formatters); + } + + private final List<PatternFormatter> formatters; + + /** + * Construct the converter. + * + * @param formatters + * The PatternFormatters to generate the text to manipulate. + */ + private VariablesNotEmptyReplacementConverter(final List<PatternFormatter> formatters) { + super("notEmpty", "notEmpty"); + this.formatters = formatters; + } + + /** + * {@inheritDoc} + */ + @Override + public void format(final LogEvent event, final StringBuilder toAppendTo) { + final StringBuilder buf = new StringBuilder(); + int emptyVars = 0; + int vars = 0; + for (final PatternFormatter formatter : formatters) { + int start = buf.length(); + formatter.format(event, buf); + final boolean isVariable = formatter.getConverter().isVariable(); + vars += isVariable ? 1 : 0; + if (isVariable && buf.length() - start == 0) { + emptyVars++; + } + } + if (vars > 0 && emptyVars != vars) { + toAppendTo.append(buf.toString()); + } + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d41f343c/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/VariablesNotEmptyReplacementConverterTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/VariablesNotEmptyReplacementConverterTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/VariablesNotEmptyReplacementConverterTest.java new file mode 100644 index 0000000..15be1ea --- /dev/null +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/VariablesNotEmptyReplacementConverterTest.java @@ -0,0 +1,78 @@ +/* + * 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.logging.log4j.core.pattern; + +import static org.junit.Assert.assertEquals; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.impl.Log4jLogEvent; +import org.apache.logging.log4j.message.SimpleMessage; +import org.apache.logging.log4j.util.Strings; +import org.junit.Test; + +/** + * + */ +public class VariablesNotEmptyReplacementConverterTest { + + @Test + public void testMarkerReplacement() { + testReplacement("%marker", Strings.EMPTY); + } + + @Test + public void testMultipleMarkerReplacementEmpty() { + testReplacement("<%marker>Foo</%marker>", Strings.EMPTY); + } + + @Test + public void testMultipleMarkerReplacementSomeEmpty() { + testReplacement("<%marker>%msg</%marker>", "[<>This is a test</>]"); + } + + @Test + public void testMultipleMarkerReplacement() { + testReplacement("<%level>%msg</%level>", "[<DEBUG>This is a test</DEBUG>]"); + } + + @Test + public void testMarkerSimpleNameReplacement() { + testReplacement("%markerSimpleName", Strings.EMPTY); + } + + @Test + public void testLoggerNameReplacement() { + testReplacement("%logger", "[" + VariablesNotEmptyReplacementConverterTest.class.getName() + "]"); + } + + private void testReplacement(String tag, String expectedValue) { + final LogEvent event = Log4jLogEvent.newBuilder() // + .setLoggerName(VariablesNotEmptyReplacementConverterTest.class.getName()) // + .setLevel(Level.DEBUG) // + .setMessage(new SimpleMessage("This is a test")) // + .build(); + final StringBuilder sb = new StringBuilder(); + final LoggerContext ctx = LoggerContext.getContext(); + final String[] options = new String[] { "[" + tag + "]" }; + final VariablesNotEmptyReplacementConverter converter = VariablesNotEmptyReplacementConverter + .newInstance(ctx.getConfiguration(), options); + converter.format(event, sb); + assertEquals(expectedValue, sb.toString()); + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d41f343c/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index cd86147..0fa5c6e 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -33,6 +33,9 @@ <action issue="LOG4J2-1147" dev="ggregory" type="add"> Add %equalsIgnoreCase to PatternLayout to test and replace patterns with strings. </action> + <action issue="LOG4J2-1146" dev="ggregory" type="add"> + Add %notEmpty to PatternLayout to avoid output of patterns where all variables are empty. + </action> <action issue="LOG4J2-1020" dev="mikes" type="fix"> Possibility to set shutdown timeout on AsyncAppender </action> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d41f343c/src/site/xdoc/manual/layouts.xml.vm ---------------------------------------------------------------------- diff --git a/src/site/xdoc/manual/layouts.xml.vm b/src/site/xdoc/manual/layouts.xml.vm index e1c0e12..ee1270a 100644 --- a/src/site/xdoc/manual/layouts.xml.vm +++ b/src/site/xdoc/manual/layouts.xml.vm @@ -995,6 +995,23 @@ WARN [main]: Message 2</pre> </tr> <tr> <td align="center"> + <a name="VariablesNotEmpty" /> + <b>variablesNotEmpty</b>{pattern}<br /> + <b>varsNotEmpty</b>{pattern}<br /> + <b>notEmpty</b>{pattern} + </td> + <td> + <p> + Outputs the result of evaluating the pattern if and only if all variables in the pattern are not empty. + </p> + <p> + For example: + <pre>%notEmpty{[%marker]}</pre> + </p> + </td> + </tr> + <tr> + <td align="center"> <b>p</b>|<b>level</b>{<em>level</em>=<em>label</em>, <em>level</em>=<em>label</em>, ...} <b>p</b>|<b>level</b>{length=<em>n</em>} <b>p</b>|<b>level</b>{lowerCase=<em>true</em>|<em>false</em>}
