You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2016/05/02 23:31:40 UTC
logging-log4j2 git commit: [LOG4J2-621] Pattern to drop first N
package parts. Closes #28 https://github.com/apache/logging-log4j2/pull/28
Repository: logging-log4j2
Updated Branches:
refs/heads/master ad5073c05 -> 23b2b3670
[LOG4J2-621] Pattern to drop first N package parts. Closes #28
https://github.com/apache/logging-log4j2/pull/28
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/23b2b367
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/23b2b367
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/23b2b367
Branch: refs/heads/master
Commit: 23b2b3670d70e4494b2dc6c1929e6eb36ac0db2d
Parents: ad5073c
Author: ggregory <gg...@apache.org>
Authored: Mon May 2 14:31:35 2016 -0700
Committer: ggregory <gg...@apache.org>
Committed: Mon May 2 14:31:35 2016 -0700
----------------------------------------------------------------------
.../log4j/core/pattern/NameAbbreviator.java | 77 ++++++-
.../log4j/core/layout/PatternLayoutTest.java | 202 +++++++++++++++++++
src/changes/changes.xml | 3 +
src/site/xdoc/manual/layouts.xml.vm | 34 +++-
4 files changed, 304 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/23b2b367/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/NameAbbreviator.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/NameAbbreviator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/NameAbbreviator.java
index 1271ad5..a59cc5f 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/NameAbbreviator.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/NameAbbreviator.java
@@ -52,18 +52,31 @@ public abstract class NameAbbreviator {
return DEFAULT;
}
+ boolean isNegativeNumber;
+ final String number;
+
+ // check if number is a negative number
+ if (trimmed.length() > 1 && trimmed.charAt(0) == '-') {
+ isNegativeNumber = true;
+ number = trimmed.substring(1);
+ } else {
+ isNegativeNumber = false;
+ number = trimmed;
+ }
+
int i = 0;
- while (i < trimmed.length() && trimmed.charAt(i) >= '0'
- && trimmed.charAt(i) <= '9') {
+ while (i < number.length() && number.charAt(i) >= '0'
+ && number.charAt(i) <= '9') {
i++;
}
//
// if all blanks and digits
//
- if (i == trimmed.length()) {
- return new MaxElementAbbreviator(Integer.parseInt(trimmed));
+ if (i == number.length()) {
+ return new MaxElementAbbreviator(Integer.parseInt(number),
+ isNegativeNumber? MaxElementAbbreviator.Strategy.DROP : MaxElementAbbreviator.Strategy.RETAIN);
}
final ArrayList<PatternAbbreviatorFragment> fragments = new ArrayList<>(5);
@@ -156,18 +169,45 @@ public abstract class NameAbbreviator {
* Abbreviator that drops starting path elements.
*/
private static class MaxElementAbbreviator extends NameAbbreviator {
+
+ /**
+ * <p>When the name is reduced in length by cutting parts, there can be two ways to do it.</p>
+ * 1. Remove a given number of parts starting from front - called DROP <br/>
+ * 2. Retain a given number of parts starting from the end - called RETAIN
+ */
+ private enum Strategy {
+ DROP,
+ RETAIN
+ };
+
/**
* Maximum number of path elements to output.
*/
private final int count;
/**
+ * Strategy used for cutting down the size of the name
+ */
+ private final Strategy strategy;
+
+ /**
* Create new instance.
*
- * @param count maximum number of path elements to output.
+ * @param count maximum number of path elements to drop or output.
+ * @param strategy drop or retain
*/
- public MaxElementAbbreviator(final int count) {
- this.count = count < 1 ? 1 : count;
+ public MaxElementAbbreviator(final int count, final Strategy strategy) {
+ final int minCount = getMinCount(strategy);
+ this.count = count < minCount ? minCount : count;
+ this.strategy = strategy;
+ }
+
+ private int getMinCount(final Strategy strategy) {
+ if (Strategy.DROP == strategy) {
+ return 0;
+ } else { // Strategy.RETAIN
+ return 1;
+ }
}
/**
@@ -179,7 +219,30 @@ public abstract class NameAbbreviator {
*/
@Override
public void abbreviate(final String original, final StringBuilder destination) {
+ if (Strategy.DROP == strategy) {
+ abbreviateForDrop(original, destination);
+ } else { // Strategy.RETAIN
+ abbreviateForRetain(original, destination);
+ }
+ }
+
+ private void abbreviateForDrop(String original, StringBuilder destination) {
+ // If a path does not contain enough path elements to drop, none will be dropped.
+ int start = 0;
+ int nextStart = 0;
+ for (int i = 0; i < count; i++) {
+ nextStart = original.indexOf('.', start);
+ if (nextStart == -1) {
+ destination.append(original);
+ return;
+ } else {
+ start = nextStart + 1;
+ }
+ }
+ destination.append(original, start, original.length());
+ }
+ private void abbreviateForRetain(String original, StringBuilder destination) {
// We subtract 1 from 'len' when assigning to 'end' to avoid out of
// bounds exception in return r.substring(end+1, len). This can happen if
// precision is 1 and the category name ends with a dot.
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/23b2b367/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java
index 988b42b..6f58ebc 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java
@@ -398,4 +398,206 @@ public class PatternLayoutTest {
.withConfiguration(ctx.getConfiguration()).withCharset(StandardCharsets.UTF_8).build();
assertEquals(StandardCharsets.UTF_8, layout.getCharset());
}
+
+ @Test
+ public void testLoggerNameTruncationByRetainingPartsFromEnd() throws Exception {
+ {
+ final PatternLayout layout = PatternLayout.newBuilder().withPattern("%c{1} %m")
+ .withConfiguration(ctx.getConfiguration()).build();
+ final LogEvent event1 = Log4jLogEvent.newBuilder()
+ .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger")
+ .setLevel(Level.INFO)
+ .setMessage(new SimpleMessage("Hello, world 1!")).build();
+ final String result1 = layout.toSerializable(event1);
+ assertEquals(this.getClass().getName().substring(this.getClass().getName().lastIndexOf(".") + 1) + " Hello, world 1!", new String(result1));
+ }
+ {
+ final PatternLayout layout = PatternLayout.newBuilder().withPattern("%c{2} %m")
+ .withConfiguration(ctx.getConfiguration()).build();
+ final LogEvent event1 = Log4jLogEvent.newBuilder()
+ .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger")
+ .setLevel(Level.INFO)
+ .setMessage(new SimpleMessage("Hello, world 1!")).build();
+ final String result1 = layout.toSerializable(event1);
+ String name = this.getClass().getName().substring(0, this.getClass().getName().lastIndexOf("."));
+ name = name.substring(0, name.lastIndexOf("."));
+ assertEquals(this.getClass().getName().substring(name.length() + 1) + " Hello, world 1!", new String(result1));
+ }
+ {
+ final PatternLayout layout = PatternLayout.newBuilder().withPattern("%c{20} %m")
+ .withConfiguration(ctx.getConfiguration()).build();
+ final LogEvent event1 = Log4jLogEvent.newBuilder()
+ .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger")
+ .setLevel(Level.INFO)
+ .setMessage(new SimpleMessage("Hello, world 1!")).build();
+ final String result1 = layout.toSerializable(event1);
+ assertEquals(this.getClass().getName() + " Hello, world 1!", new String(result1));
+ }
+ }
+
+ @Test
+ public void testCallersFqcnTruncationByRetainingPartsFromEnd() throws Exception {
+ {
+ final PatternLayout layout = PatternLayout.newBuilder().withPattern("%C{1} %m")
+ .withConfiguration(ctx.getConfiguration()).build();
+ final LogEvent event1 = Log4jLogEvent.newBuilder()
+ .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger")
+ .setLevel(Level.INFO)
+ .setMessage(new SimpleMessage("Hello, world 1!"))
+ .setSource(new StackTraceElement(this.getClass().getName(), "testCallersFqcnTruncationByRetainingPartsFromEnd", this.getClass().getCanonicalName() + ".java", 440))
+ .build();
+ final String result1 = layout.toSerializable(event1);
+ assertEquals(this.getClass().getName().substring(this.getClass().getName().lastIndexOf(".") + 1) + " Hello, world 1!", new String(result1));
+ }
+ {
+ final PatternLayout layout = PatternLayout.newBuilder().withPattern("%C{2} %m")
+ .withConfiguration(ctx.getConfiguration()).build();
+ final LogEvent event1 = Log4jLogEvent.newBuilder()
+ .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger")
+ .setLevel(Level.INFO)
+ .setMessage(new SimpleMessage("Hello, world 1!"))
+ .setSource(new StackTraceElement(this.getClass().getName(), "testCallersFqcnTruncationByRetainingPartsFromEnd", this.getClass().getCanonicalName() + ".java", 440))
+ .build();
+ final String result1 = layout.toSerializable(event1);
+ String name = this.getClass().getName().substring(0, this.getClass().getName().lastIndexOf("."));
+ name = name.substring(0, name.lastIndexOf("."));
+ assertEquals(this.getClass().getName().substring(name.length() + 1) + " Hello, world 1!", new String(result1));
+ }
+ {
+ final PatternLayout layout = PatternLayout.newBuilder().withPattern("%C{20} %m")
+ .withConfiguration(ctx.getConfiguration()).build();
+ final LogEvent event1 = Log4jLogEvent.newBuilder()
+ .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger")
+ .setLevel(Level.INFO)
+ .setMessage(new SimpleMessage("Hello, world 1!"))
+ .setSource(new StackTraceElement(this.getClass().getName(), "testCallersFqcnTruncationByRetainingPartsFromEnd", this.getClass().getCanonicalName() + ".java", 440))
+ .build();
+ final String result1 = layout.toSerializable(event1);
+ assertEquals(this.getClass().getName() + " Hello, world 1!", new String(result1));
+ }
+ {
+ final PatternLayout layout = PatternLayout.newBuilder().withPattern("%class{1} %m")
+ .withConfiguration(ctx.getConfiguration()).build();
+ final LogEvent event1 = Log4jLogEvent.newBuilder()
+ .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger")
+ .setLevel(Level.INFO)
+ .setMessage(new SimpleMessage("Hello, world 1!"))
+ .setSource(new StackTraceElement(this.getClass().getName(), "testCallersFqcnTruncationByRetainingPartsFromEnd", this.getClass().getCanonicalName() + ".java", 440))
+ .build();
+ final String result1 = layout.toSerializable(event1);
+ assertEquals(this.getClass().getName().substring(this.getClass().getName().lastIndexOf(".") + 1) + " Hello, world 1!", new String(result1));
+ }
+ }
+
+ @Test
+ public void testLoggerNameTruncationByDroppingPartsFromFront() throws Exception {
+ {
+ final PatternLayout layout = PatternLayout.newBuilder().withPattern("%c{-1} %m")
+ .withConfiguration(ctx.getConfiguration()).build();
+ final LogEvent event1 = Log4jLogEvent.newBuilder()
+ .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger")
+ .setLevel(Level.INFO)
+ .setMessage(new SimpleMessage("Hello, world 1!")).build();
+ final String result1 = layout.toSerializable(event1);
+ String name = this.getClass().getName().substring(this.getClass().getName().indexOf(".") + 1);
+ assertEquals(name + " Hello, world 1!", new String(result1));
+ }
+ {
+ final PatternLayout layout = PatternLayout.newBuilder().withPattern("%c{-3} %m")
+ .withConfiguration(ctx.getConfiguration()).build();
+ final LogEvent event1 = Log4jLogEvent.newBuilder()
+ .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger")
+ .setLevel(Level.INFO)
+ .setMessage(new SimpleMessage("Hello, world 1!")).build();
+ final String result1 = layout.toSerializable(event1);
+ String name = this.getClass().getName().substring(this.getClass().getName().indexOf(".") + 1);
+ name = name.substring(name.indexOf(".") + 1);
+ name = name.substring(name.indexOf(".") + 1);
+ assertEquals(name + " Hello, world 1!", new String(result1));
+ }
+ {
+ final PatternLayout layout = PatternLayout.newBuilder().withPattern("%logger{-3} %m")
+ .withConfiguration(ctx.getConfiguration()).build();
+ final LogEvent event1 = Log4jLogEvent.newBuilder()
+ .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger")
+ .setLevel(Level.INFO)
+ .setMessage(new SimpleMessage("Hello, world 1!")).build();
+ final String result1 = layout.toSerializable(event1);
+ String name = this.getClass().getName().substring(this.getClass().getName().indexOf(".") + 1);
+ name = name.substring(name.indexOf(".") + 1);
+ name = name.substring(name.indexOf(".") + 1);
+ assertEquals(name + " Hello, world 1!", new String(result1));
+ }
+ {
+ final PatternLayout layout = PatternLayout.newBuilder().withPattern("%c{-20} %m")
+ .withConfiguration(ctx.getConfiguration()).build();
+ final LogEvent event1 = Log4jLogEvent.newBuilder()
+ .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger")
+ .setLevel(Level.INFO)
+ .setMessage(new SimpleMessage("Hello, world 1!")).build();
+ final String result1 = layout.toSerializable(event1);
+ assertEquals(this.getClass().getName() + " Hello, world 1!", new String(result1));
+ }
+
+ }
+
+ @Test
+ public void testCallersFqcnTruncationByDroppingPartsFromFront() throws Exception {
+ {
+ final PatternLayout layout = PatternLayout.newBuilder().withPattern("%C{-1} %m")
+ .withConfiguration(ctx.getConfiguration()).build();
+ final LogEvent event1 = Log4jLogEvent.newBuilder()
+ .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger")
+ .setLevel(Level.INFO)
+ .setMessage(new SimpleMessage("Hello, world 1!"))
+ .setSource(new StackTraceElement(this.getClass().getName(), "testCallersFqcnTruncationByDroppingPartsFromFront", this.getClass().getCanonicalName() + ".java", 546))
+ .build();
+ final String result1 = layout.toSerializable(event1);
+ String name = this.getClass().getName().substring(this.getClass().getName().indexOf(".") + 1);
+ assertEquals(name + " Hello, world 1!", new String(result1));
+ }
+ {
+ final PatternLayout layout = PatternLayout.newBuilder().withPattern("%C{-3} %m")
+ .withConfiguration(ctx.getConfiguration()).build();
+ final LogEvent event1 = Log4jLogEvent.newBuilder()
+ .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger")
+ .setLevel(Level.INFO)
+ .setMessage(new SimpleMessage("Hello, world 1!"))
+ .setSource(new StackTraceElement(this.getClass().getName(), "testCallersFqcnTruncationByDroppingPartsFromFront", this.getClass().getCanonicalName() + ".java", 546))
+ .build();
+ final String result1 = layout.toSerializable(event1);
+ String name = this.getClass().getName().substring(this.getClass().getName().indexOf(".") + 1);
+ name = name.substring(name.indexOf(".") + 1);
+ name = name.substring(name.indexOf(".") + 1);
+ assertEquals(name + " Hello, world 1!", new String(result1));
+ }
+ {
+ final PatternLayout layout = PatternLayout.newBuilder().withPattern("%class{-3} %m")
+ .withConfiguration(ctx.getConfiguration()).build();
+ final LogEvent event1 = Log4jLogEvent.newBuilder()
+ .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger")
+ .setLevel(Level.INFO)
+ .setMessage(new SimpleMessage("Hello, world 1!"))
+ .setSource(new StackTraceElement(this.getClass().getName(), "testCallersFqcnTruncationByDroppingPartsFromFront", this.getClass().getCanonicalName() + ".java", 546))
+ .build();
+ final String result1 = layout.toSerializable(event1);
+ String name = this.getClass().getName().substring(this.getClass().getName().indexOf(".") + 1);
+ name = name.substring(name.indexOf(".") + 1);
+ name = name.substring(name.indexOf(".") + 1);
+ assertEquals(name + " Hello, world 1!", new String(result1));
+ }
+ {
+ final PatternLayout layout = PatternLayout.newBuilder().withPattern("%C{-20} %m")
+ .withConfiguration(ctx.getConfiguration()).build();
+ final LogEvent event1 = Log4jLogEvent.newBuilder()
+ .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger")
+ .setLevel(Level.INFO)
+ .setMessage(new SimpleMessage("Hello, world 1!"))
+ .setSource(new StackTraceElement(this.getClass().getName(), "testCallersFqcnTruncationByDroppingPartsFromFront", this.getClass().getCanonicalName() + ".java", 546))
+ .build();
+ final String result1 = layout.toSerializable(event1);
+ assertEquals(this.getClass().getName() + " Hello, world 1!", new String(result1));
+ }
+
+ }
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/23b2b367/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 7d77dc9..77e687d 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -24,6 +24,9 @@
</properties>
<body>
<release version="2.6" date="2016-MM-DD" description="GA Release 2.6">
+ <action issue="LOG4J2-621" dev="ggregory" type="add" due-to="Lee Theobald, Kamal Mettananda, Gary Gregory">
+ Pattern to drop first N package parts.
+ </action>
<action issue="LOG4J2-494" dev="rgoers" type="add" due-to="Philipp Knobel">
Support merging configurations to for a composite configuration.
</action>
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/23b2b367/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 e94e5e7..1a33b76 100644
--- a/src/site/xdoc/manual/layouts.xml.vm
+++ b/src/site/xdoc/manual/layouts.xml.vm
@@ -520,11 +520,15 @@ WARN [main]: Message 2</pre>
specifier can be optionally followed by <em>precision specifier</em>, which consists of a
decimal integer, or a pattern starting with a decimal integer.
</p>
- <p>If a precision specifier is given and it is an integer value, then only the corresponding number
- of right most components of the logger name will be printed. If the precision contains
- other non-integer characters then the name will be abbreviated based on the pattern. If the
- precision integer is less than one the right-most token will still be printed in full.
- By default the logger name is printed in full.
+ <p>When the precision specifier is an integer value, it reduces the size of the logger name.
+ If the number is positive, the layout prints the corresponding number of rightmost logger
+ name components. If negative, the layout removes the corresponding number of leftmost logger
+ name components.
+ </p>
+ <p>
+ If the precision contains any non-integer characters, then the layout abbreviates the name
+ based on the pattern. If the precision integer is less than one, the layout still prints
+ the right-most token in full. By default, the layout prints the logger name in full.
</p>
<table>
<tr>
@@ -543,6 +547,26 @@ WARN [main]: Message 2</pre>
<td>commons.Foo</td>
</tr>
<tr>
+ <td>%c{10}</td>
+ <td>org.apache.${break}commons.Foo</td>
+ <td>org.apache.${break}commons.Foo</td>
+ </tr>
+ <tr>
+ <td>%c{-1}</td>
+ <td>org.apache.${break}commons.Foo</td>
+ <td>apache.${break}commons.Foo</td>
+ </tr>
+ <tr>
+ <td>%c{-2}</td>
+ <td>org.apache.${break}commons.Foo</td>
+ <td>${break}commons.Foo</td>
+ </tr>
+ <tr>
+ <td>%c{-10}</td>
+ <td>org.apache.${break}commons.Foo</td>
+ <td>org.apache.${break}commons.Foo</td>
+ </tr>
+ <tr>
<td>%c{1.}</td>
<td>org.apache.${break}commons.Foo</td>
<td>o.a.c.Foo</td>