Repository: logging-log4j2 Updated Branches: refs/heads/master 2ed5d3789 -> e94c9a46e
[LOG4J2-926] Truncate from the end of text format modifier. Also change next version to 2.2 in changes.xml since this is a new minor feature. Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/e94c9a46 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/e94c9a46 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/e94c9a46 Branch: refs/heads/master Commit: e94c9a46ed60527422442d0e5d7230dacab25e98 Parents: 2ed5d37 Author: Gary Gregory <[email protected]> Authored: Mon Mar 9 14:49:50 2015 -0700 Committer: Gary Gregory <[email protected]> Committed: Mon Mar 9 14:49:50 2015 -0700 ---------------------------------------------------------------------- .../log4j/core/pattern/FormattingInfo.java | 27 ++++++++-- .../log4j/core/pattern/PatternParser.java | 32 ++++++----- .../log4j/core/pattern/FormattingInfoTest.java | 57 ++++++++++++++++++++ .../log4j/core/pattern/PatternParserTest.java | 37 ++++++++++++- src/changes/changes.xml | 5 +- src/site/xdoc/manual/layouts.xml.vm | 15 ++++++ 6 files changed, 156 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e94c9a46/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FormattingInfo.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FormattingInfo.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FormattingInfo.java index 950a7d5..d252bd6 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FormattingInfo.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FormattingInfo.java @@ -29,7 +29,7 @@ public final class FormattingInfo { /** * Default instance. */ - private static final FormattingInfo DEFAULT = new FormattingInfo(false, 0, Integer.MAX_VALUE); + private static final FormattingInfo DEFAULT = new FormattingInfo(false, 0, Integer.MAX_VALUE, true); /** * Minimum length. @@ -47,6 +47,11 @@ public final class FormattingInfo { private final boolean leftAlign; /** + * Left vs. right-hand side truncation. + */ + private final boolean leftTruncate; + + /** * Creates new instance. * * @param leftAlign @@ -56,10 +61,11 @@ public final class FormattingInfo { * @param maxLength * maximum length. */ - public FormattingInfo(final boolean leftAlign, final int minLength, final int maxLength) { + public FormattingInfo(final boolean leftAlign, final int minLength, final int maxLength, final boolean leftTruncate) { this.leftAlign = leftAlign; this.minLength = minLength; this.maxLength = maxLength; + this.leftTruncate = leftTruncate; } /** @@ -81,6 +87,15 @@ public final class FormattingInfo { } /** + * Determine if left truncated. + * + * @return true if left truncated. + */ + public boolean isLeftTruncate() { + return leftTruncate; + } + + /** * Get minimum length. * * @return minimum length. @@ -110,7 +125,11 @@ public final class FormattingInfo { final int rawLength = buffer.length() - fieldStart; if (rawLength > maxLength) { - buffer.delete(fieldStart, buffer.length() - maxLength); + if (leftTruncate) { + buffer.delete(fieldStart, buffer.length() - maxLength); + } else { + buffer.delete(fieldStart + maxLength, fieldStart + buffer.length()); + } } else if (rawLength < minLength) { if (leftAlign) { final int fieldEnd = buffer.length(); @@ -146,6 +165,8 @@ public final class FormattingInfo { sb.append(maxLength); sb.append(", minLength="); sb.append(minLength); + sb.append(", leftTruncate="); + sb.append(leftTruncate); sb.append(']'); return sb.toString(); } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e94c9a46/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java index c0a7b9e..b8b4db3 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java @@ -362,7 +362,7 @@ public final class PatternParser { switch (c) { case '-': formattingInfo = new FormattingInfo(true, formattingInfo.getMinLength(), - formattingInfo.getMaxLength()); + formattingInfo.getMaxLength(), formattingInfo.isLeftTruncate()); break; case '.': @@ -373,7 +373,7 @@ public final class PatternParser { if (c >= '0' && c <= '9') { formattingInfo = new FormattingInfo(formattingInfo.isLeftAligned(), c - '0', - formattingInfo.getMaxLength()); + formattingInfo.getMaxLength(), formattingInfo.isLeftTruncate()); state = ParserState.MIN_STATE; } else { i = finalizeConverter(c, pattern, i, currentLiteral, formattingInfo, converterRules, @@ -394,7 +394,7 @@ public final class PatternParser { if (c >= '0' && c <= '9') { // Multiply the existing value and add the value of the number just encountered. formattingInfo = new FormattingInfo(formattingInfo.isLeftAligned(), formattingInfo.getMinLength() - * DECIMAL + c - '0', formattingInfo.getMaxLength()); + * DECIMAL + c - '0', formattingInfo.getMaxLength(), formattingInfo.isLeftTruncate()); } else if (c == '.') { state = ParserState.DOT_STATE; } else { @@ -409,16 +409,24 @@ public final class PatternParser { case DOT_STATE: currentLiteral.append(c); - - if (c >= '0' && c <= '9') { + switch (c) { + case '-': formattingInfo = new FormattingInfo(formattingInfo.isLeftAligned(), formattingInfo.getMinLength(), - c - '0'); - state = ParserState.MAX_STATE; - } else { - LOGGER.error("Error occurred in position " + i + ".\n Was expecting digit, instead got char \"" + c - + "\"."); + formattingInfo.getMaxLength(),false); + break; - state = ParserState.LITERAL_STATE; + default: + + if (c >= '0' && c <= '9') { + formattingInfo = new FormattingInfo(formattingInfo.isLeftAligned(), formattingInfo.getMinLength(), + c - '0', formattingInfo.isLeftTruncate()); + state = ParserState.MAX_STATE; + } else { + LOGGER.error("Error occurred in position " + i + ".\n Was expecting digit, instead got char \"" + c + + "\"."); + + state = ParserState.LITERAL_STATE; + } } break; @@ -429,7 +437,7 @@ public final class PatternParser { if (c >= '0' && c <= '9') { // Multiply the existing value and add the value of the number just encountered. formattingInfo = new FormattingInfo(formattingInfo.isLeftAligned(), formattingInfo.getMinLength(), - formattingInfo.getMaxLength() * DECIMAL + c - '0'); + formattingInfo.getMaxLength() * DECIMAL + c - '0', formattingInfo.isLeftTruncate()); } else { i = finalizeConverter(c, pattern, i, currentLiteral, formattingInfo, converterRules, patternConverters, formattingInfos, noConsoleNoAnsi, convertBackslashes); http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e94c9a46/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/FormattingInfoTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/FormattingInfoTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/FormattingInfoTest.java new file mode 100644 index 0000000..e2f9621 --- /dev/null +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/FormattingInfoTest.java @@ -0,0 +1,57 @@ +/* + * 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.junit.Test; + +/** + * Testing FormattingInfo. + */ +public class FormattingInfoTest { + + @Test + public void testFormatTruncateFromBeginning() { + StringBuilder message = new StringBuilder("Hello, world"); + + FormattingInfo formattingInfo = new FormattingInfo(false, 0, 5, true); + formattingInfo.format(0, message); + + assertEquals("world", message.toString()); + } + + @Test + public void testFormatTruncateFromEnd() { + StringBuilder message = new StringBuilder("Hello, world"); + + FormattingInfo formattingInfo = new FormattingInfo(false, 0, 5, false); + formattingInfo.format(0, message); + + assertEquals("Hello", message.toString()); + } + + @Test + public void testFormatTruncateFromEndGivenFieldStart() { + StringBuilder message = new StringBuilder("2015-03-09 11:49:28,295; INFO org.apache.logging.log4j.PatternParserTest"); + + FormattingInfo formattingInfo = new FormattingInfo(false, 0, 5, false); + formattingInfo.format(31, message); + + assertEquals("2015-03-09 11:49:28,295; INFO org.a", message.toString()); + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e94c9a46/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java index 075bb19..9bd118b 100644 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java @@ -54,6 +54,8 @@ public class PatternParserTest { private static String badPattern = "[%d{yyyyMMdd HH:mm:ss,SSS] %-5p [%c{10}] - %m%n"; private static String customPattern = "[%d{yyyyMMdd HH:mm:ss,SSS}] %-5p [%-25.25c{1}:%-4L] - %m%n"; + private static String patternTruncateFromEnd = "%d; %-5p %5.-5c %m%n"; + private static String patternTruncateFromBeginning = "%d; %-5p %5.5c %m%n"; private static String nestedPatternHighlight = "%highlight{%d{dd MMM yyyy HH:mm:ss,SSS}{GMT+0} [%t] %-5level: %msg%n%throwable}"; @@ -102,9 +104,42 @@ public class PatternParserTest { formatter.format(event, buf); } final String str = buf.toString(); - final String expected = "INFO [PatternParserTest :95 ] - Hello, world" + Constants.LINE_SEPARATOR; + final String expected = "INFO [PatternParserTest :97 ] - Hello, world" + Constants.LINE_SEPARATOR; assertTrue("Expected to end with: " + expected + ". Actual: " + str, str.endsWith(expected)); } + + @Test + public void testPatternTruncateFromBeginning() { + final List<PatternFormatter> formatters = parser.parse(patternTruncateFromBeginning); + assertNotNull(formatters); + final LogEvent event = new Log4jLogEvent("org.apache.logging.log4j.PatternParserTest", null, + Logger.class.getName(), Level.INFO, new SimpleMessage("Hello, world"), null, + null, null, "Thread1", null, System.currentTimeMillis()); + final StringBuilder buf = new StringBuilder(); + for (final PatternFormatter formatter : formatters) { + formatter.format(event, buf); + } + final String str = buf.toString(); + final String expected = "INFO rTest Hello, world" + Constants.LINE_SEPARATOR; + assertTrue("Expected to end with: " + expected + ". Actual: " + str, str.endsWith(expected)); + } + + @Test + public void testPatternTruncateFromEnd() { + final List<PatternFormatter> formatters = parser.parse(patternTruncateFromEnd); + assertNotNull(formatters); + final LogEvent event = new Log4jLogEvent("org.apache.logging.log4j.PatternParserTest", null, + Logger.class.getName(), Level.INFO, new SimpleMessage("Hello, world"), null, + null, null, "Thread1", null, System.currentTimeMillis()); + final StringBuilder buf = new StringBuilder(); + for (final PatternFormatter formatter : formatters) { + formatter.format(event, buf); + } + final String str = buf.toString(); + final String expected = "INFO org.a Hello, world" + Constants.LINE_SEPARATOR; + assertTrue("Expected to end with: " + expected + ". Actual: " + str, str.endsWith(expected)); + } + @Test public void testBadPattern() { http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e94c9a46/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 25b9d1d..ff407ba 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -23,7 +23,10 @@ <title>Changes</title> </properties> <body> - <release version="2.2.1" date="2015-0?-??" description="GA Release 2.2.1"> + <release version="2.2" date="2015-0?-??" description="GA Release 2.2"> + <action issue="LOG4J2-926" dev="ggregory" type="add" due-to="David Ohana"> + Truncate from the end of text format modifier. + </action> <action issue="LOG4J2-966" dev="ggregory" type="fix" due-to="Gary Gregory"> KeyStoreConfiguration.createKeyStoreConfiguration() ignores keyManagerFactoryAlgorithm. </action> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e94c9a46/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 dd4683a..cedf18e 100644 --- a/src/site/xdoc/manual/layouts.xml.vm +++ b/src/site/xdoc/manual/layouts.xml.vm @@ -1147,6 +1147,11 @@ WARN [main]: Message 2</pre> are dropped. This behavior deviates from the printf function in C where truncation is done from the end. </p> + <p>Truncation from the end is possible by appending a minus character + right after the period. In that case, if the maximum field width + is eight and the data item is ten characters long, then the last + two characters of the data item are dropped. + </p> <p>Below are various format modifier examples for the category conversion specifier. </p> @@ -1205,6 +1210,16 @@ WARN [main]: Message 2</pre> then truncate from the beginning. </td> </tr> + <tr> + <td align="center">%-20.-30c</td> + <td align="center">true</td> + <td align="center">20</td> + <td align="center">30</td> + <td>Right pad with spaces if the category name is shorter than 20 + characters. However, if category name is longer than 30 characters, + then truncate from the end. + </td> + </tr> <caption align="top">Pattern Converters</caption> </table> <h4>ANSI Styling on Windows</h4>
