You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rp...@apache.org on 2016/03/04 15:23:21 UTC
[43/50] [abbrv] logging-log4j2 git commit: LOG4J2-1217 -
PatternLayout option to limit length of text.
LOG4J2-1217 - PatternLayout option to limit length of text.
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/df0270af
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/df0270af
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/df0270af
Branch: refs/heads/LOG4J2-1278-gc-free-logger
Commit: df0270af2ec4f4ad64474a778f5d9b2731d4cce9
Parents: ee4573b
Author: Matt Sicker <bo...@gmail.com>
Authored: Wed Mar 2 22:32:31 2016 -0600
Committer: Matt Sicker <bo...@gmail.com>
Committed: Wed Mar 2 22:32:31 2016 -0600
----------------------------------------------------------------------
.../log4j/core/pattern/MaxLengthConverter.java | 103 +++++++++++++++++++
.../core/pattern/MaxLengthConverterTest.java | 73 +++++++++++++
src/changes/changes.xml | 3 +
src/site/xdoc/manual/layouts.xml.vm | 38 +++++++
4 files changed, 217 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df0270af/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/MaxLengthConverter.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/MaxLengthConverter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/MaxLengthConverter.java
new file mode 100644
index 0000000..ca053f2
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/MaxLengthConverter.java
@@ -0,0 +1,103 @@
+/*
+ * 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.appender.AbstractAppender;
+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;
+
+/**
+ * Max length pattern converter. Limit contained text to a maximum length.
+ * On invalid length the default value 100 is used (and an error message is logged).
+ * If max length is greater than 20, an abbreviated text will get ellipsis ("...") appended.
+ * Example usage (for email subject):
+ * {@code "%maxLen{[AppName, ${hostName}, ${web:contextPath}] %p: %c{1} - %m%notEmpty{ =>%ex{short}}}{160}"}
+ *
+ * @author Thies Wellpott
+ */
+@Plugin(name = "maxLength", category = PatternConverter.CATEGORY)
+@ConverterKeys({"maxLength", "maxLen"})
+public final class MaxLengthConverter extends LogEventPatternConverter {
+
+ /**
+ * Gets an instance of the class.
+ *
+ * @param config The current Configuration.
+ * @param options pattern options, an array of two elements: pattern, max length (defaults to 100 on invalid value).
+ * @return instance of class.
+ */
+ public static MaxLengthConverter newInstance(final Configuration config, final String[] options) {
+ if (options.length != 2) {
+ LOGGER.error("Incorrect number of options on maxLength: expected 2 received {}: {}", options.length,
+ options);
+ return null;
+ }
+ if (options[0] == null) {
+ LOGGER.error("No pattern supplied on maxLength");
+ return null;
+ }
+ if (options[1] == null) {
+ LOGGER.error("No length supplied on maxLength");
+ return null;
+ }
+ final PatternParser parser = PatternLayout.createPatternParser(config);
+ final List<PatternFormatter> formatters = parser.parse(options[0]);
+ return new MaxLengthConverter(formatters, AbstractAppender.parseInt(options[1], 100));
+ }
+
+
+ private final List<PatternFormatter> formatters;
+ private final int maxLength;
+
+ /**
+ * Construct the converter.
+ *
+ * @param formatters The PatternFormatters to generate the text to manipulate.
+ * @param maxLength The max. length of the resulting string. Ellipsis ("...") is appended on shorted string, if greater than 20.
+ */
+ private MaxLengthConverter(final List<PatternFormatter> formatters, final int maxLength) {
+ super("MaxLength", "maxLength");
+ this.maxLength = maxLength;
+ this.formatters = formatters;
+ LOGGER.trace("new MaxLengthConverter with {}", maxLength);
+ }
+
+
+ @Override
+ public void format(final LogEvent event, final StringBuilder toAppendTo) {
+ final StringBuilder buf = new StringBuilder();
+ for (final PatternFormatter formatter : formatters) {
+ formatter.format(event, buf);
+ if (buf.length() > maxLength) { // stop early
+ break;
+ }
+ }
+ if (buf.length() > maxLength) {
+ buf.setLength(maxLength);
+ if (maxLength > 20) { // only append ellipses if length is not very short
+ buf.append("...");
+ }
+ }
+ toAppendTo.append(buf);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df0270af/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/MaxLengthConverterTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/MaxLengthConverterTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/MaxLengthConverterTest.java
new file mode 100644
index 0000000..e379915
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/MaxLengthConverterTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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 org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.SimpleMessage;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ */
+public class MaxLengthConverterTest {
+
+ private static MaxLengthConverter converter = MaxLengthConverter.newInstance(null, new String[]{"%m", "10"});
+
+ @Test
+ public void testUnderMaxLength() throws Exception {
+ final Message message = new SimpleMessage("0123456789");
+ final LogEvent event = Log4jLogEvent.newBuilder()
+ .setLoggerName("MyLogger")
+ .setLevel(Level.DEBUG)
+ .setMessage(message)
+ .build();
+ final StringBuilder sb = new StringBuilder();
+ converter.format(event, sb);
+ assertEquals("0123456789", sb.toString());
+ }
+
+ @Test
+ public void testOverMaxLength() throws Exception {
+ final Message message = new SimpleMessage("01234567890123456789");
+ final LogEvent event = Log4jLogEvent.newBuilder()
+ .setLoggerName("MyLogger")
+ .setLevel(Level.DEBUG)
+ .setMessage(message)
+ .build();
+ final StringBuilder sb = new StringBuilder();
+ converter.format(event, sb);
+ assertEquals("0123456789", sb.toString());
+ }
+ @Test
+ public void testOverMaxLength21WithEllipsis() throws Exception {
+ final Message message = new SimpleMessage("012345678901234567890123456789");
+ final LogEvent event = Log4jLogEvent.newBuilder()
+ .setLoggerName("MyLogger")
+ .setLevel(Level.DEBUG)
+ .setMessage(message)
+ .build();
+ final StringBuilder sb = new StringBuilder();
+ MaxLengthConverter.newInstance(null, new String[]{"%m", "21"}).format(event, sb);
+ assertEquals("012345678901234567890...", sb.toString());
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df0270af/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index aa6581c..5066c0a 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -190,6 +190,9 @@
<action issue="LOG4J2-1306" dev="mattsicker" type="update">
JeroMqAppender should use ShutdownCallbackRegistry instead of runtime hooks.
</action>
+ <action issue="LOG4J2-1217" dev="mattsicker" type="add" due-to="Thies Wellpott">
+ PatternLayout option to limit length of text.
+ </action>
</release>
<release version="2.5" date="2015-12-06" description="GA Release 2.5">
<action issue="LOG4J2-324" dev="rpopma" type="fix">
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df0270af/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 fa602e4..d193380 100644
--- a/src/site/xdoc/manual/layouts.xml.vm
+++ b/src/site/xdoc/manual/layouts.xml.vm
@@ -910,6 +910,7 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternMap"/>
<b>K</b>{key}<br />
<b>map</b>{key}<br />
<b>MAP</b>{key}
@@ -957,6 +958,7 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternMessage"/>
<b>m</b><br />
<b>msg</b><br />
<b>message</b>
@@ -977,18 +979,40 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternMarker"/>
<b>marker</b>
</td>
<td>The full name of the marker, including parents, if one is present.</td>
</tr>
<tr>
<td align="center">
+ <a name="PatternMarkerSimpleName"/>
<b>markerSimpleName</b>
</td>
<td>The simple name of the marker (not including parents), if one is present.</td>
</tr>
<tr>
<td align="center">
+ <a name="PatternMaxLength"/>
+ <b>maxLen</b><br/>
+ <b>maxLength</b>
+ </td>
+ <td>
+ <p>
+ Outputs the result of evaluating the pattern and truncating the result. If the length is greater
+ than 20, then the output will contain a trailing ellipsis. If the provided length is invalid, a
+ default value of 100 is used.
+ </p>
+ <p>
+ Example syntax: <code>%maxLen{%p: %c{1} - %m%notEmpty{ =>%ex{short}}}{160}</code> will be limited to
+ 160 characters with a trailing ellipsis. Another example: <code>%maxLen{%m}{20}</code> will be
+ limited to 20 characters and no trailing ellipsis.
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td align="center">
+ <a name="PatternNewLine"/>
<b>n</b>
</td>
<td>
@@ -1029,6 +1053,7 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternLevel"/>
<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>}
@@ -1065,6 +1090,7 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternRelative"/>
<b>r</b><br />
<b>relative</b>
</td>
@@ -1074,6 +1100,7 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternReplace"/>
<b>replace</b>{pattern}{regex}{substitution}
</td>
<td>
@@ -1089,6 +1116,7 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternException"/>
<b>rEx</b>["none"|"short"|"full"|depth],[filters(packages)}<br />
<b>rException</b>["none"|"short"|"full"|depth],[filters(packages)}<br />
<b>rThrowable</b>["none"|"short"|"full"|depth],[filters(packages)}
@@ -1109,6 +1137,7 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternSequenceNumber"/>
<b>sn</b><br />
<b>sequenceNumber</b>
</td>
@@ -1118,6 +1147,7 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternStyle"/>
<b>style</b>{pattern}{ANSI style}
</td>
<td>
@@ -1239,6 +1269,7 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternThreadId"/>
<b>T</b><br />
<b>tid</b><br />
<b>threadId</b>
@@ -1247,6 +1278,7 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternThreadName"/>
<b>t</b><br />
<b>thread</b><br />
<b>threadName</b>
@@ -1255,6 +1287,7 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternThreadPriority"/>
<b>tp</b><br />
<b>threadPriority</b>
</td>
@@ -1262,6 +1295,7 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternNDC"/>
<b>x</b><br />
<b>NDC</b>
</td>
@@ -1271,6 +1305,7 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternMDC"/>
<b>X</b>{key[,key2...]}<br />
<b>mdc</b>{key[,key2...]}<br />
<b>MDC</b>{key[,key2...]}
@@ -1300,6 +1335,7 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternUUID"/>
<b>u</b>{"RANDOM" | "TIME"}<br />
<b>uuid</b>
</td>
@@ -1314,6 +1350,7 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternExtendedException"/>
<b>xEx</b>{"none"|"short"|"full"|depth],[filters(packages)}<br />
<b>xException</b>["none"|"short"|"full"|depth],[filters(packages)}<br />
<b>xThrowable</b>["none"|"short"|"full"|depth],[filters(packages)}
@@ -1338,6 +1375,7 @@ WARN [main]: Message 2</pre>
</tr>
<tr>
<td align="center">
+ <a name="PatternPercentLiteral"/>
<b>%</b>
</td>
<td>The sequence %% outputs a single percent sign.