You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ck...@apache.org on 2018/07/27 03:59:04 UTC

[1/6] logging-log4j2 git commit: [LOG4J2-2391] release note

Repository: logging-log4j2
Updated Branches:
  refs/heads/master 7fb3f8e22 -> 29831fe75


[LOG4J2-2391] release note


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

Branch: refs/heads/master
Commit: 29831fe755deed933295596ded11c09a4885afac
Parents: 044e7ad
Author: Carter Kozak <ck...@apache.org>
Authored: Thu Jul 26 23:50:30 2018 -0400
Committer: Carter Kozak <ck...@apache.org>
Committed: Thu Jul 26 23:57:59 2018 -0400

----------------------------------------------------------------------
 src/changes/changes.xml | 6 ++++++
 1 file changed, 6 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/29831fe7/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index b637344..6d239e0 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -224,6 +224,12 @@
       <action issue="LOG4J2-2387" dev="ggregory" type="update">
         Update optional Apache Commons DBCP from 2.4.0 to 2.5.0.
       </action>
+      <action issue="LOG4J2-2391" dev="ckozak" type="update">
+        Improve exception logging performance. ThrowableProxy construction uses a more faster
+        method to discover the current stack trace. ThrowablePatternConverter and
+        ExtendedThrowablePatternConverter default configurations no longer allocate
+        an additional buffer for stack trace contents.
+      </action>
     </release>
     <release version="2.11.1" date="2018-MM-DD" description="GA Release 2.11.1">
       <action issue="LOG4J2-2389" dev="rgoers" type="fix" due-to="Liu Wen">


[5/6] logging-log4j2 git commit: [LOG4J2-2391] StackLocator initializes PrivateSecurityManager

Posted by ck...@apache.org.
[LOG4J2-2391] StackLocator initializes PrivateSecurityManager

Regression introduced here, removing StackLocator.SECURITY_MANAGER
initialization: 55b9fd20907994a5115e28674d03ddb215e149b4


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

Branch: refs/heads/master
Commit: 044e7addb2043ad629fc02d14ef29429e75ac0d0
Parents: 5eb02a1
Author: Carter Kozak <ck...@apache.org>
Authored: Thu Jul 26 22:27:32 2018 -0400
Committer: Carter Kozak <ck...@apache.org>
Committed: Thu Jul 26 23:57:59 2018 -0400

----------------------------------------------------------------------
 .../org/apache/logging/log4j/util/StackLocator.java  | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/044e7add/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocator.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocator.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocator.java
index 3dfcd9b..fa7df44 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocator.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocator.java
@@ -46,7 +46,7 @@ import java.util.Stack;
  */
 public final class StackLocator {
 
-    private static PrivateSecurityManager SECURITY_MANAGER;
+    private static final PrivateSecurityManager SECURITY_MANAGER;
 
     // Checkstyle Suppress: the lower-case 'u' ticks off CheckStyle...
     // CHECKSTYLE:OFF
@@ -82,6 +82,19 @@ public final class StackLocator {
             java7u25CompensationOffset = -1;
         }
 
+        PrivateSecurityManager psm;
+        try {
+            final SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                sm.checkPermission(new RuntimePermission("createSecurityManager"));
+            }
+            psm = new PrivateSecurityManager();
+        } catch (final SecurityException ignored) {
+            psm = null;
+        }
+
+        SECURITY_MANAGER = psm;
+
         GET_CALLER_CLASS = getCallerClass;
         JDK_7u25_OFFSET = java7u25CompensationOffset;
 


[6/6] logging-log4j2 git commit: ExtendedThrowablePatternConverter writes to the layout buffer

Posted by ck...@apache.org.
ExtendedThrowablePatternConverter writes to the layout buffer

ExtendedThrowablePatternConverter no longer constructs a String
of the full stack trace, instead appending to the layout
StringBuilder.


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

Branch: refs/heads/master
Commit: ea0aef03c1375f2bf4940f349728b503ba91e1ca
Parents: 6ec8f2c
Author: Carter Kozak <ck...@apache.org>
Authored: Wed Jul 25 19:06:06 2018 -0400
Committer: Carter Kozak <ck...@apache.org>
Committed: Thu Jul 26 23:57:59 2018 -0400

----------------------------------------------------------------------
 .../logging/log4j/core/impl/ThrowableProxy.java      | 15 ++++++++++++++-
 .../pattern/ExtendedThrowablePatternConverter.java   |  6 ++----
 2 files changed, 16 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ea0aef03/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
index 111ff71..73d7faf 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
@@ -505,6 +505,20 @@ public class ThrowableProxy implements Serializable {
      */
     public String getExtendedStackTraceAsString(final List<String> ignorePackages, final TextRenderer textRenderer, final String suffix, final String lineSeparator) {
         final StringBuilder sb = new StringBuilder(1024);
+        formatExtendedStackTraceTo(sb, ignorePackages, textRenderer, suffix, lineSeparator);
+        return sb.toString();
+    }
+
+    /**
+     * Formats the stack trace including packaging information.
+     *
+     * @param sb Destination.
+     * @param ignorePackages List of packages to be ignored in the trace.
+     * @param textRenderer The message renderer.
+     * @param suffix Append this to the end of each stack frame.
+     * @param lineSeparator The end-of-line separator.
+     */
+    public void formatExtendedStackTraceTo(final StringBuilder sb, final List<String> ignorePackages, final TextRenderer textRenderer, final String suffix, final String lineSeparator) {
         textRenderer.render(name, sb, "Name");
         textRenderer.render(": ", sb, "NameMessageSeparator");
         textRenderer.render(this.message, sb, "Message");
@@ -514,7 +528,6 @@ public class ThrowableProxy implements Serializable {
         this.formatElements(sb, Strings.EMPTY, 0, causedTrace, this.extendedStackTrace, ignorePackages, textRenderer, suffix, lineSeparator);
         this.formatSuppressed(sb, TAB, this.suppressedProxies, ignorePackages, textRenderer, suffix, lineSeparator);
         this.formatCause(sb, Strings.EMPTY, this.causeProxy, ignorePackages, textRenderer, suffix, lineSeparator);
-        return sb.toString();
     }
 
     public String getLocalizedMessage() {

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ea0aef03/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
index 3196758..8ec9b7d 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
@@ -20,7 +20,6 @@ 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.impl.ThrowableProxy;
-import org.apache.logging.log4j.util.Strings;
 
 /**
  * Outputs the Throwable portion of the LoggingEvent as a full stack trace
@@ -68,13 +67,12 @@ public final class ExtendedThrowablePatternConverter extends ThrowablePatternCon
                 super.format(event, toAppendTo);
                 return;
             }
-            final String extStackTrace = proxy.getExtendedStackTraceAsString(options.getIgnorePackages(),
-                    options.getTextRenderer(), getSuffix(event), options.getSeparator());
             final int len = toAppendTo.length();
             if (len > 0 && !Character.isWhitespace(toAppendTo.charAt(len - 1))) {
                 toAppendTo.append(' ');
             }
-            toAppendTo.append(extStackTrace);
+            proxy.formatExtendedStackTraceTo(toAppendTo, options.getIgnorePackages(),
+                    options.getTextRenderer(), getSuffix(event), options.getSeparator());
         }
     }
 


[2/6] logging-log4j2 git commit: ThrowableProxy cleanup

Posted by ck...@apache.org.
ThrowableProxy cleanup

Removed a few  unnecessary parameters and operations.


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

Branch: refs/heads/master
Commit: 5eb02a1a892506a85267f578bace8a71ec108289
Parents: ea0aef0
Author: Carter Kozak <ck...@apache.org>
Authored: Wed Jul 25 19:23:11 2018 -0400
Committer: Carter Kozak <ck...@apache.org>
Committed: Thu Jul 26 23:57:59 2018 -0400

----------------------------------------------------------------------
 .../logging/log4j/core/impl/ThrowableProxy.java      | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/5eb02a1a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
index 73d7faf..42ed186 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
@@ -657,8 +657,7 @@ public class ThrowableProxy implements Serializable {
      * @param exact             True if the class was obtained via Reflection.getCallerClass.
      * @return The CacheEntry.
      */
-    private CacheEntry toCacheEntry(final StackTraceElement stackTraceElement, final Class<?> callerClass,
-                                    final boolean exact) {
+    private CacheEntry toCacheEntry(final Class<?> callerClass, final boolean exact) {
         String location = "?";
         String version = "?";
         ClassLoader lastLoader = null;
@@ -734,7 +733,7 @@ public class ThrowableProxy implements Serializable {
             // present as those methods have returned.
             ExtendedClassInfo extClassInfo;
             if (clazz != null && className.equals(clazz.getName())) {
-                final CacheEntry entry = this.toCacheEntry(stackTraceElement, clazz, true);
+                final CacheEntry entry = this.toCacheEntry(clazz, true);
                 extClassInfo = entry.element;
                 lastLoader = entry.loader;
                 stack.pop();
@@ -748,8 +747,7 @@ public class ThrowableProxy implements Serializable {
                         lastLoader = entry.loader;
                     }
                 } else {
-                    final CacheEntry entry = this.toCacheEntry(stackTraceElement,
-                        this.loadClass(lastLoader, className), false);
+                    final CacheEntry entry = this.toCacheEntry(this.loadClass(lastLoader, className), false);
                     extClassInfo = entry.element;
                     map.put(className, entry);
                     if (entry.loader != null) {
@@ -771,17 +769,16 @@ public class ThrowableProxy implements Serializable {
     private ThrowableProxy[] toSuppressedProxies(final Throwable thrown, Set<Throwable> suppressedVisited) {
         try {
             final Throwable[] suppressed = thrown.getSuppressed();
-            if (suppressed == null) {
+            if (suppressed == null || suppressed.length == 0) {
                 return EMPTY_THROWABLE_PROXY_ARRAY;
             }
             final List<ThrowableProxy> proxies = new ArrayList<>(suppressed.length);
             if (suppressedVisited == null) {
-                suppressedVisited = new HashSet<>(proxies.size());
+                suppressedVisited = new HashSet<>(suppressed.length);
             }
             for (int i = 0; i < suppressed.length; i++) {
                 final Throwable candidate = suppressed[i];
-                if (!suppressedVisited.contains(candidate)) {
-                    suppressedVisited.add(candidate);
+                if (suppressedVisited.add(candidate)) {
                     proxies.add(new ThrowableProxy(candidate, suppressedVisited));
                 }
             }


[3/6] logging-log4j2 git commit: [LOG4J2-2391] Benchmarks for logging to disk with a Throwable

Posted by ck...@apache.org.
[LOG4J2-2391] Benchmarks for logging to disk with a Throwable

Initial results (re-ordered fastest to slowest):

Benchmark                                                Mode  Cnt       Score       Error  Units
FileAppenderThrowableBenchmark.logbackFile              thrpt    3  135260.838 ± 15790.010  ops/s
FileAppenderThrowableBenchmark.log4j2SimpleThrowable    thrpt    3   87385.712 ±  8082.803  ops/s
FileAppenderThrowableBenchmark.log4j1                   thrpt    3   60359.485 ± 10122.858  ops/s
FileAppenderThrowableBenchmark.julFile                  thrpt    3   52134.431 ±  1302.365  ops/s
FileAppenderThrowableBenchmark.log4j2ExtendedThrowable  thrpt    3   15348.378 ±  1301.501  ops/s


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

Branch: refs/heads/master
Commit: d7c0c829edf7bff7ab9cdff183b1cc658cc853b2
Parents: 7fb3f8e
Author: Carter Kozak <ck...@apache.org>
Authored: Tue Jul 24 17:59:00 2018 -0400
Committer: Carter Kozak <ck...@apache.org>
Committed: Thu Jul 26 23:57:59 2018 -0400

----------------------------------------------------------------------
 .../jmh/FileAppenderThrowableBenchmark.java     | 144 +++++++++++++++++++
 .../resources/log4j12-perf-file-throwable.xml   |  31 ++++
 .../resources/log4j2-perf-file-throwable.xml    |  40 ++++++
 .../resources/logback-perf-file-throwable.xml   |  30 ++++
 4 files changed, 245 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d7c0c829/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderThrowableBenchmark.java
----------------------------------------------------------------------
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderThrowableBenchmark.java b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderThrowableBenchmark.java
new file mode 100644
index 0000000..6f02c01
--- /dev/null
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderThrowableBenchmark.java
@@ -0,0 +1,144 @@
+/*
+ * 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.perf.jmh;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Threads;
+import org.openjdk.jmh.annotations.Warmup;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.FileHandler;
+import java.util.logging.Level;
+
+/**
+ * Benchmarks Log4j 2, Log4j 1, Logback and JUL using the ERROR level which is enabled for this test.
+ * The configuration for each writes to disk.
+ */
+// HOW TO RUN THIS TEST
+// java -jar target/benchmarks.jar ".*FileAppenderThrowableBenchmark.*" -f 1 -i 10 -wi 20 -bm sample -tu ns
+@State(Scope.Thread)
+@Threads(1)
+@Fork(1)
+@Warmup(iterations = 3, time = 3)
+@Measurement(iterations = 3, time = 3)
+public class FileAppenderThrowableBenchmark {
+
+    private static final Throwable THROWABLE = getThrowable();
+
+    private static Throwable getThrowable() {
+        return new IllegalStateException("Test Throwable");
+    }
+
+    private FileHandler julFileHandler;
+    Logger log4j2ExtendedThrowable;
+    Logger log4j2SimpleThrowable;
+    org.slf4j.Logger slf4jLogger;
+    org.apache.log4j.Logger log4j1Logger;
+    java.util.logging.Logger julLogger;
+
+    @Setup
+    public void setUp() throws Exception {
+        deleteLogFiles();
+        System.setProperty("log4j2.is.webapp", "false");
+        System.setProperty("log4j.configurationFile", "log4j2-perf-file-throwable.xml");
+        System.setProperty("log4j.configuration", "log4j12-perf-file-throwable.xml");
+        System.setProperty("logback.configurationFile", "logback-perf-file-throwable.xml");
+
+        log4j2ExtendedThrowable = LogManager.getLogger("RAFExtendedException");
+        log4j2SimpleThrowable = LogManager.getLogger("RAFSimpleException");
+        slf4jLogger = LoggerFactory.getLogger(getClass());
+        log4j1Logger = org.apache.log4j.Logger.getLogger(getClass());
+
+        julFileHandler = new FileHandler("target/testJulLog.log");
+        julLogger = java.util.logging.Logger.getLogger(getClass().getName());
+        julLogger.setUseParentHandlers(false);
+        julLogger.addHandler(julFileHandler);
+        julLogger.setLevel(Level.ALL);
+    }
+
+    @TearDown
+    public void tearDown() {
+        System.clearProperty("log4j2.is.webapp");
+        System.clearProperty("log4j.configurationFile");
+        System.clearProperty("log4j.configuration");
+        System.clearProperty("logback.configurationFile");
+        deleteLogFiles();
+    }
+
+    private void deleteLogFiles() {
+        final File logbackFile = new File("target/testlogback.log");
+        logbackFile.delete();
+        final File log4jFile = new File ("target/testlog4j.log");
+        log4jFile.delete();
+        final File log4jRandomFile = new File ("target/extended-exception.log");
+        log4jRandomFile.delete();
+        final File log4j2File = new File ("target/simple-exception.log");
+        log4j2File.delete();
+        final File julFile = new File("target/testJulLog.log");
+        julFile.delete();
+    }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void log4j1() {
+        log4j1Logger.error("Caught an exception", THROWABLE);
+    }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void log4j2SimpleThrowable() {
+        log4j2SimpleThrowable.error("Caught an exception", THROWABLE);
+    }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void log4j2ExtendedThrowable() {
+        log4j2ExtendedThrowable.error("Caught an exception", THROWABLE);
+    }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void logbackFile() {
+        slf4jLogger.error("Caught an exception", THROWABLE);
+    }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void julFile() {
+        // must specify sourceClass or JUL will look it up by walking the stack trace!
+        julLogger.logp(Level.SEVERE, getClass().getName(), "param1JulFile", "Caught an exception", THROWABLE);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d7c0c829/log4j-perf/src/main/resources/log4j12-perf-file-throwable.xml
----------------------------------------------------------------------
diff --git a/log4j-perf/src/main/resources/log4j12-perf-file-throwable.xml b/log4j-perf/src/main/resources/log4j12-perf-file-throwable.xml
new file mode 100644
index 0000000..172e2f2
--- /dev/null
+++ b/log4j-perf/src/main/resources/log4j12-perf-file-throwable.xml
@@ -0,0 +1,31 @@
+<!--
+ 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.
+
+-->
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
+    <appender name="TestLogfile" class="org.apache.log4j.FileAppender">
+        <param name="File" value="target/testlog4j.log"/>
+        <param name="immediateFlush" value="false"/>
+        <layout class="org.apache.log4j.PatternLayout">
+            <param name="ConversionPattern" value="%m%n"/>
+        </layout>
+    </appender>
+    <root>
+        <level value="debug"/>
+        <appender-ref ref="TestLogfile"/>
+    </root>
+</log4j:configuration>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d7c0c829/log4j-perf/src/main/resources/log4j2-perf-file-throwable.xml
----------------------------------------------------------------------
diff --git a/log4j-perf/src/main/resources/log4j2-perf-file-throwable.xml b/log4j-perf/src/main/resources/log4j2-perf-file-throwable.xml
new file mode 100644
index 0000000..3a4d9a4
--- /dev/null
+++ b/log4j-perf/src/main/resources/log4j2-perf-file-throwable.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+
+-->
+<Configuration name="FileAppenderThrowableBenchmark" status="error">
+    <Appenders>
+        <RandomAccessFile name="RAFExtendedException" fileName="target/extended-exception.log" immediateFlush="false">
+            <PatternLayout>
+                <Pattern>%m%xEx</Pattern>
+            </PatternLayout>
+        </RandomAccessFile>
+        <RandomAccessFile name="RAFSimpleException" fileName="target/simple-exception.log" immediateFlush="false">
+            <PatternLayout>
+                <Pattern>%m%ex</Pattern>
+            </PatternLayout>
+        </RandomAccessFile>
+    </Appenders>
+    <Loggers>
+        <Logger name="RAFExtendedException" level="debug" additivity="false">
+            <AppenderRef ref="RAFExtendedException"/>
+        </Logger>
+        <Logger name="RAFSimpleException" level="debug" additivity="false">
+            <AppenderRef ref="RAFSimpleException"/>
+        </Logger>
+    </Loggers>
+</Configuration>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d7c0c829/log4j-perf/src/main/resources/logback-perf-file-throwable.xml
----------------------------------------------------------------------
diff --git a/log4j-perf/src/main/resources/logback-perf-file-throwable.xml b/log4j-perf/src/main/resources/logback-perf-file-throwable.xml
new file mode 100644
index 0000000..25b0b28
--- /dev/null
+++ b/log4j-perf/src/main/resources/logback-perf-file-throwable.xml
@@ -0,0 +1,30 @@
+<!--
+ 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.
+
+-->
+<configuration>
+    <appender name="TestLogfile" class="ch.qos.logback.core.FileAppender">
+        <file>target/testlogback.log</file>
+        <immediateFlush>false</immediateFlush>
+        <encoder>
+            <Pattern>%m%n</Pattern>
+        </encoder>
+    </appender>
+
+    <root level="debug">
+        <appender-ref ref="TestLogfile" />
+    </root>
+</configuration>
\ No newline at end of file


[4/6] logging-log4j2 git commit: [LOG4J2-2391] Improve ThrowablePatternConverter performance

Posted by ck...@apache.org.
[LOG4J2-2391] Improve ThrowablePatternConverter performance

This does not provide any benefit for
ExtendedThrowablePatternConverter.

Updated Benchmarks:

Benchmark                                                Mode  Cnt       Score       Error  Units
FileAppenderThrowableBenchmark.julFile                  thrpt    3   42411.701 ±  9740.338  ops/s
FileAppenderThrowableBenchmark.log4j1                   thrpt    3   58608.053 ±  9127.229  ops/s
FileAppenderThrowableBenchmark.log4j2ExtendedThrowable  thrpt    3   15443.610 ±  3942.549  ops/s
FileAppenderThrowableBenchmark.log4j2SimpleThrowable    thrpt    3  114443.966 ± 29211.657  ops/s
FileAppenderThrowableBenchmark.logbackFile              thrpt    3  135646.780 ± 16794.353  ops/s


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

Branch: refs/heads/master
Commit: 6ec8f2cd445efbaa4432ce9d1789abc0e52a4dab
Parents: d7c0c82
Author: Carter Kozak <ck...@apache.org>
Authored: Tue Jul 24 18:25:35 2018 -0400
Committer: Carter Kozak <ck...@apache.org>
Committed: Thu Jul 26 23:57:59 2018 -0400

----------------------------------------------------------------------
 .../core/pattern/ThrowablePatternConverter.java | 46 ++++++++++----------
 1 file changed, 23 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/6ec8f2cd/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
index eadb3f3..7b9679c 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
@@ -27,6 +27,7 @@ import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.impl.ThrowableFormatOptions;
 import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.apache.logging.log4j.core.util.StringBuilderWriter;
 import org.apache.logging.log4j.util.Strings;
 
 
@@ -44,6 +45,8 @@ public class ThrowablePatternConverter extends LogEventPatternConverter {
      */
     protected final List<PatternFormatter> formatters;
     private String rawOption;
+    private final boolean subShortOption;
+    private final boolean nonStandardLineSeparator;
 
     /**
      * Options.
@@ -87,7 +90,13 @@ public class ThrowablePatternConverter extends LogEventPatternConverter {
         } else {
             this.formatters = Collections.emptyList();
         }
-
+        subShortOption = ThrowableFormatOptions.MESSAGE.equalsIgnoreCase(rawOption) ||
+                ThrowableFormatOptions.LOCALIZED_MESSAGE.equalsIgnoreCase(rawOption) ||
+                ThrowableFormatOptions.FILE_NAME.equalsIgnoreCase(rawOption) ||
+                ThrowableFormatOptions.LINE_NUMBER.equalsIgnoreCase(rawOption) ||
+                ThrowableFormatOptions.METHOD_NAME.equalsIgnoreCase(rawOption) ||
+                ThrowableFormatOptions.CLASS_NAME.equalsIgnoreCase(rawOption);
+        nonStandardLineSeparator = !Strings.LINE_SEPARATOR.equals(this.options.getSeparator());
     }
 
     /**
@@ -109,7 +118,7 @@ public class ThrowablePatternConverter extends LogEventPatternConverter {
     public void format(final LogEvent event, final StringBuilder buffer) {
         final Throwable t = event.getThrown();
 
-        if (isSubShortOption()) {
+        if (subShortOption) {
             formatSubShortOption(t, getSuffix(event), buffer);
         }
         else if (t != null && options.anyLines()) {
@@ -117,15 +126,6 @@ public class ThrowablePatternConverter extends LogEventPatternConverter {
         }
     }
 
-    private boolean isSubShortOption() {
-        return ThrowableFormatOptions.MESSAGE.equalsIgnoreCase(rawOption) ||
-                ThrowableFormatOptions.LOCALIZED_MESSAGE.equalsIgnoreCase(rawOption) ||
-                ThrowableFormatOptions.FILE_NAME.equalsIgnoreCase(rawOption) ||
-                ThrowableFormatOptions.LINE_NUMBER.equalsIgnoreCase(rawOption) ||
-                ThrowableFormatOptions.METHOD_NAME.equalsIgnoreCase(rawOption) ||
-                ThrowableFormatOptions.CLASS_NAME.equalsIgnoreCase(rawOption);
-    }
-
     private void formatSubShortOption(final Throwable t, final String suffix, final StringBuilder buffer) {
         StackTraceElement[] trace;
         StackTraceElement throwingMethod = null;
@@ -174,32 +174,29 @@ public class ThrowablePatternConverter extends LogEventPatternConverter {
     }
 
     private void formatOption(final Throwable throwable, final String suffix, final StringBuilder buffer) {
-        final StringWriter w = new StringWriter();
-
-        throwable.printStackTrace(new PrintWriter(w));
         final int len = buffer.length();
         if (len > 0 && !Character.isWhitespace(buffer.charAt(len - 1))) {
             buffer.append(' ');
         }
-        if (!options.allLines() || !Strings.LINE_SEPARATOR.equals(options.getSeparator()) || Strings.isNotBlank(suffix)) {
-            final StringBuilder sb = new StringBuilder();
+        if (!options.allLines() || nonStandardLineSeparator || Strings.isNotBlank(suffix)) {
+            final StringWriter w = new StringWriter();
+            throwable.printStackTrace(new PrintWriter(w));
+
             final String[] array = w.toString().split(Strings.LINE_SEPARATOR);
             final int limit = options.minLines(array.length) - 1;
             final boolean suffixNotBlank = Strings.isNotBlank(suffix);
             for (int i = 0; i <= limit; ++i) {
-                sb.append(array[i]);
+                buffer.append(array[i]);
                 if (suffixNotBlank) {
-                    sb.append(' ');
-                    sb.append(suffix);
+                    buffer.append(' ');
+                    buffer.append(suffix);
                 }
                 if (i < limit) {
-                    sb.append(options.getSeparator());
+                    buffer.append(options.getSeparator());
                 }
             }
-            buffer.append(sb.toString());
-
         } else {
-            buffer.append(w.toString());
+            throwable.printStackTrace(new PrintWriter(new StringBuilderWriter(buffer)));
         }
     }
 
@@ -214,6 +211,9 @@ public class ThrowablePatternConverter extends LogEventPatternConverter {
     }
 
     protected String getSuffix(final LogEvent event) {
+        if (formatters.isEmpty()) {
+            return Strings.EMPTY;
+        }
         //noinspection ForLoopReplaceableByForEach
         final StringBuilder toAppendTo = new StringBuilder();
         for (int i = 0, size = formatters.size(); i <  size; i++) {