You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by mi...@apache.org on 2016/08/03 11:34:02 UTC

[12/28] logging-log4j2 git commit: LOG4J2-1341 (GC) HighlightConverter and StyleConverter are now GC-free.

LOG4J2-1341 (GC) HighlightConverter and StyleConverter are now GC-free.

This closes GitHub pull request #34 (https://github.com/apache/logging-log4j2/pull/34).


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/c4af088d
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/c4af088d
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/c4af088d

Branch: refs/heads/LOG4J-1181
Commit: c4af088d7d0a181f4e9b84f401bd56f2e1342797
Parents: 8529086
Author: rpopma <rp...@apache.org>
Authored: Sun Jul 31 14:43:14 2016 +0900
Committer: rpopma <rp...@apache.org>
Committed: Sun Jul 31 14:43:14 2016 +0900

----------------------------------------------------------------------
 .../log4j/core/pattern/HighlightConverter.java  | 37 ++++++----
 .../log4j/core/pattern/StyleConverter.java      | 24 ++++--
 .../core/pattern/HighlightConverterTest.java    | 78 ++++++++++++++++++++
 log4j-core/src/test/resources/gcFreeLogging.xml | 10 +--
 .../resources/gcFreeMixedSyncAsyncLogging.xml   | 10 +--
 log4j-core/src/test/resources/log4j-style.xml   |  4 +-
 src/changes/changes.xml                         |  5 +-
 src/site/xdoc/manual/garbagefree.xml            | 10 ++-
 8 files changed, 143 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c4af088d/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java
index 0e2f63d..c0ab673 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java
@@ -34,14 +34,14 @@ import org.apache.logging.log4j.util.Strings;
  * <p>
  * For example:
  * </p>
- * 
+ *
  * <pre>
  * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}
  * </pre>
  * <p>
  * You can define custom colors for each Level:
  * </p>
- * 
+ *
  * <pre>
  * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}{FATAL=red, ERROR=red, WARN=yellow, INFO=green, DEBUG=cyan,
  * TRACE=black}
@@ -49,9 +49,9 @@ import org.apache.logging.log4j.util.Strings;
  * <p>
  * You can use a predefined style:
  * </p>
- * 
+ *
  * <pre>
- * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}{STYLE=Log4j}
+ * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}{STYLE=DEFAULT}
  * </pre>
  * <p>
  * The available predefined styles are:
@@ -108,7 +108,7 @@ public final class HighlightConverter extends LogEventPatternConverter implement
      * <p>
      * The format of the option string in {@code option[1]} is:
      * </p>
-     * 
+     *
      * <pre>
      * Level1=Value, Level2=Value, ...
      * </pre>
@@ -193,6 +193,8 @@ public final class HighlightConverter extends LogEventPatternConverter implement
 
     private final boolean noAnsi;
 
+    private final String defaultStyle;
+
     /**
      * Construct the converter.
      *
@@ -205,6 +207,7 @@ public final class HighlightConverter extends LogEventPatternConverter implement
         super("style", "style");
         this.patternFormatters = patternFormatters;
         this.levelStyles = levelStyles;
+        this.defaultStyle = AnsiEscape.getDefaultStyle();
         this.noAnsi = noAnsi;
     }
 
@@ -213,17 +216,25 @@ public final class HighlightConverter extends LogEventPatternConverter implement
      */
     @Override
     public void format(final LogEvent event, final StringBuilder toAppendTo) {
-        final StringBuilder buf = new StringBuilder();
-        for (final PatternFormatter formatter : patternFormatters) {
-            formatter.format(event, buf);
+        final int start = toAppendTo.length();
+        int end = 0;
+        if (!noAnsi) { // use ANSI: set prefix
+            toAppendTo.append(levelStyles.get(event.getLevel()));
+            end = toAppendTo.length();
+        }
+
+        //noinspection ForLoopReplaceableByForEach
+        for (int i = 0, size = patternFormatters.size(); i <  size; i++) {
+            patternFormatters.get(i).format(event, toAppendTo);
         }
 
-        if (buf.length() > 0) {
-            if (noAnsi) {
-                toAppendTo.append(buf.toString());
+        // if we use ANSI we need to add the postfix or erase the unnecessary prefix
+        final boolean empty = toAppendTo.length() == end;
+        if (!noAnsi) {
+            if (empty) {
+                toAppendTo.setLength(start); // erase prefix
             } else {
-                toAppendTo.append(levelStyles.get(event.getLevel())).append(buf.toString()).
-                    append(AnsiEscape.getDefaultStyle());
+                toAppendTo.append(defaultStyle); // add postfix
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c4af088d/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java
index 202d771..0d8c730 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java
@@ -94,17 +94,25 @@ public final class StyleConverter extends LogEventPatternConverter implements An
      */
     @Override
     public void format(final LogEvent event, final StringBuilder toAppendTo) {
-        final StringBuilder buf = new StringBuilder();
-        for (final PatternFormatter formatter : patternFormatters) {
-            formatter.format(event, buf);
+        int start = 0;
+        int end = 0;
+        if (!noAnsi) { // use ANSI: set prefix
+            start = toAppendTo.length();
+            toAppendTo.append(style);
+            end = toAppendTo.length();
+        }
+
+        //noinspection ForLoopReplaceableByForEach
+        for (int i = 0, size = patternFormatters.size(); i <  size; i++) {
+            patternFormatters.get(i).format(event, toAppendTo);
         }
 
-        if (buf.length() > 0) {
-            if (noAnsi) {
-                // faster to test and do this than setting style and defaultStyle to empty strings.
-                toAppendTo.append(buf.toString());
+        // if we use ANSI we need to add the postfix or erase the unnecessary prefix
+        if (!noAnsi) {
+            if (toAppendTo.length() == end) {
+                toAppendTo.setLength(start); // erase prefix
             } else {
-                toAppendTo.append(style).append(buf.toString()).append(defaultStyle);
+                toAppendTo.append(defaultStyle); // add postfix
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c4af088d/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java
new file mode 100644
index 0000000..6051f85
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java
@@ -0,0 +1,78 @@
+package org.apache.logging.log4j.core.pattern;/*
+ * 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.
+ */
+
+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.SimpleMessage;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests the HighlightConverter.
+ */
+public class HighlightConverterTest {
+
+    @Test
+    public void testAnsiEmpty() {
+        final String[] options = {"", PatternParser.NO_CONSOLE_NO_ANSI + "=false"};
+        final HighlightConverter converter = HighlightConverter.newInstance(null, options);
+
+        final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
+                new SimpleMessage("message in a bottle")).build();
+        final StringBuilder buffer = new StringBuilder();
+        converter.format(event, buffer);
+        assertEquals("", buffer.toString());
+    }
+
+    @Test
+    public void testAnsiNonEmpty() {
+        final String[] options = {"%-5level: %msg", PatternParser.NO_CONSOLE_NO_ANSI + "=false"};
+        final HighlightConverter converter = HighlightConverter.newInstance(null, options);
+
+        final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
+                new SimpleMessage("message in a bottle")).build();
+        final StringBuilder buffer = new StringBuilder();
+        converter.format(event, buffer);
+        assertEquals("\u001B[32mINFO : message in a bottle\u001B[m", buffer.toString());
+    }
+
+    @Test
+    public void testNoAnsiEmpty() {
+        final String[] options = {"", PatternParser.NO_CONSOLE_NO_ANSI + "=true"};
+        final HighlightConverter converter = HighlightConverter.newInstance(null, options);
+
+        final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
+                new SimpleMessage("message in a bottle")).build();
+        final StringBuilder buffer = new StringBuilder();
+        converter.format(event, buffer);
+        assertEquals("", buffer.toString());
+    }
+
+    @Test
+    public void testNoAnsiNonEmpty() {
+        final String[] options = {"%-5level: %msg", PatternParser.NO_CONSOLE_NO_ANSI + "=true"};
+        final HighlightConverter converter = HighlightConverter.newInstance(null, options);
+
+        final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
+                new SimpleMessage("message in a bottle")).build();
+        final StringBuilder buffer = new StringBuilder();
+        converter.format(event, buffer);
+        assertEquals("INFO : message in a bottle", buffer.toString());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c4af088d/log4j-core/src/test/resources/gcFreeLogging.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/gcFreeLogging.xml b/log4j-core/src/test/resources/gcFreeLogging.xml
index f90d754..8893466 100644
--- a/log4j-core/src/test/resources/gcFreeLogging.xml
+++ b/log4j-core/src/test/resources/gcFreeLogging.xml
@@ -6,13 +6,13 @@
     </Console>
     <File name="File" fileName="target/gcfreefile.log" bufferedIO="false">
       <PatternLayout>
-        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
+        <Pattern>%highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %m%n}</Pattern>
       </PatternLayout>
     </File>
     <RollingFile name="RollingFile" fileName="target/gcfreeRollingFile.log"
         filePattern="target/gcfree-%d{MM-dd-yy-HH-mm-ss}.log.gz">
       <PatternLayout>
-        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
+        <Pattern>%highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %m%n}</Pattern>
       </PatternLayout>
       <Policies>
         <SizeBasedTriggeringPolicy size="50M" />
@@ -20,7 +20,7 @@
     </RollingFile>
     <RandomAccessFile name="RandomAccessFile" fileName="target/gcfreeRAF.log" immediateFlush="false" append="false">
       <PatternLayout>
-        <Pattern>%d %p %c{1.} [%t] %X{aKey} %m %ex%n</Pattern>
+        <Pattern>%highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %X{aKey} %m %ex%n}</Pattern>
       </PatternLayout>
     </RandomAccessFile>
     <RollingRandomAccessFile name="RollingRandomAccessFile"
@@ -28,7 +28,7 @@
         filePattern="target/afterRollover-%i.log" append="false"
         immediateFlush="false">
       <PatternLayout>
-        <Pattern>%d %p %c{1.} [%t] %X{aKey} %m %location %ex%n</Pattern>
+        <Pattern>%highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %X{aKey} %m %location %ex%n}</Pattern>
       </PatternLayout>
       <Policies>
         <SizeBasedTriggeringPolicy size="50 M"/>
@@ -38,7 +38,7 @@
         fileName="target/gcfreemmap.log"
         immediateFlush="false" append="false">
       <PatternLayout>
-        <Pattern>%d %p %c{1.} [%t] %X{aKey} %m%ex%n</Pattern>
+        <Pattern>%highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %X{aKey} %m%ex%n}</Pattern>
       </PatternLayout>
     </MemoryMappedFile>
     <RandomAccessFile name="RandomAccessFileGelf" fileName="target/gcfree.json" immediateFlush="false" append="false">

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c4af088d/log4j-core/src/test/resources/gcFreeMixedSyncAsyncLogging.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/gcFreeMixedSyncAsyncLogging.xml b/log4j-core/src/test/resources/gcFreeMixedSyncAsyncLogging.xml
index e4c0000..50bff57 100644
--- a/log4j-core/src/test/resources/gcFreeMixedSyncAsyncLogging.xml
+++ b/log4j-core/src/test/resources/gcFreeMixedSyncAsyncLogging.xml
@@ -6,13 +6,13 @@
     </Console>
     <File name="File" fileName="target/gcfreefileMixed.log" bufferedIO="false">
       <PatternLayout>
-        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
+        <Pattern>%highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %m%n}</Pattern>
       </PatternLayout>
     </File>
     <RollingFile name="RollingFile" fileName="target/gcfreeRollingFileMixed.log"
         filePattern="target/gcfree-%d{MM-dd-yy-HH-mm-ss}.log.gz">
       <PatternLayout>
-        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
+        <Pattern>%highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %m%n}</Pattern>
       </PatternLayout>
       <Policies>
         <SizeBasedTriggeringPolicy size="50M" />
@@ -20,7 +20,7 @@
     </RollingFile>
     <RandomAccessFile name="RandomAccessFile" fileName="target/gcfreeRAFMixed.log" immediateFlush="false" append="false">
       <PatternLayout>
-        <Pattern>%d %p %c{1.} [%t] %X{aKey} %m %ex%n</Pattern>
+        <Pattern>%highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %X{aKey} %m %ex%n}</Pattern>
       </PatternLayout>
     </RandomAccessFile>
     <RollingRandomAccessFile name="RollingRandomAccessFile"
@@ -28,7 +28,7 @@
         filePattern="target/afterRollover-%i.log" append="false"
         immediateFlush="false">
       <PatternLayout>
-        <Pattern>%d %p %c{1.} [%t] %X{aKey} %m %location %ex%n</Pattern>
+        <Pattern>%highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %X{aKey} %m %location %ex%n}</Pattern>
       </PatternLayout>
       <Policies>
         <SizeBasedTriggeringPolicy size="50 M"/>
@@ -38,7 +38,7 @@
         fileName="target/gcfreemmapMixed.log"
         immediateFlush="false" append="false">
       <PatternLayout>
-        <Pattern>%d %p %c{1.} [%t] %X{aKey} %m%ex%n</Pattern>
+        <Pattern>%highlight{%style{%d}{bright,cyan} %p %c{1.} [%t] %X{aKey} %m%ex%n}</Pattern>
       </PatternLayout>
     </MemoryMappedFile>
     <RandomAccessFile name="RandomAccessFileGelf" fileName="target/gcfreeMixed.json" immediateFlush="false" append="false">

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c4af088d/log4j-core/src/test/resources/log4j-style.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-style.xml b/log4j-core/src/test/resources/log4j-style.xml
index 9b18b37..6acf873 100644
--- a/log4j-core/src/test/resources/log4j-style.xml
+++ b/log4j-core/src/test/resources/log4j-style.xml
@@ -20,7 +20,7 @@
   <Appenders>
     <List name="List">
        <PatternLayout>
-         <Pattern>%d %highlight{%p} %style{%logger}{bright,cyan} %C{1.} %msg%n</Pattern>
+         <Pattern>%d %highlight{%p} %style{%logger}{bright,cyan}%style{}{bright,cyan} %C{1.} %msg%n</Pattern>
       </PatternLayout>
     </List>
   </Appenders>
@@ -31,4 +31,4 @@
     </Root>
   </Loggers>
 
-</Configuration>
\ No newline at end of file
+</Configuration>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c4af088d/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 8ec3453..25d4b07 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -23,7 +23,10 @@
     <title>Changes</title>
   </properties>
   <body>
-    <release version="2.7.0" date="2016-MM-DD" description="GA Release 2.7.0">
+    <release version="2.7" date="2016-MM-DD" description="GA Release 2.7.0">
+      <action issue="LOG4J2-1341" dev="rpopma" type="fix" due-to="Richard Zschech">
+        (GC) HighlightConverter and StyleConverter are now GC-free.
+      </action>
       <action issue="LOG4J2-1467" dev="rpopma, ggregory" type="fix" due-to="Ralf, Gary Gregory">
         [OSGi] Missing import package.
       </action>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c4af088d/src/site/xdoc/manual/garbagefree.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/garbagefree.xml b/src/site/xdoc/manual/garbagefree.xml
index 58ca1d0..46499d5 100644
--- a/src/site/xdoc/manual/garbagefree.xml
+++ b/src/site/xdoc/manual/garbagefree.xml
@@ -234,6 +234,14 @@
               </td>
             </tr>
             <tr>
+              <td>%highlight{pattern}{style}</td>
+              <td>Adds ANSI colors (unless nested pattern is not garbage free)</td>
+            </tr>
+            <tr>
+              <td>style{pattern}{ANSI style}</td>
+              <td>Style the message (unless nested pattern is not garbage free)</td>
+            </tr>
+            <tr>
               <td>%m, %msg, %message</td>
               <td>Log message (unless message text contains '${')</td>
             </tr>
@@ -501,4 +509,4 @@ public void garbageFree() {
       </subsection>
     </section>
   </body>
-</document>
\ No newline at end of file
+</document>