Just FYI, if you make a plugin builder, you don't need to make a plugin
factory as well. The builder is used first if available followed by the
factory method. Classes that have both are mainly for backwards
compatibility.

---------- Forwarded message ----------
From: <[email protected]>
Date: 26 May 2016 at 10:12
Subject: logging-log4j2 git commit: FastConsoleAppender
To: [email protected]


Repository: logging-log4j2
Updated Branches:
  refs/heads/LOG4J2-1395 [created] 06c554689


FastConsoleAppender


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

Branch: refs/heads/LOG4J2-1395
Commit: 06c55468948efdce95a591801d5f9e2ffdb69dd4
Parents: e012269
Author: Mikael Ståldal <[email protected]>
Authored: Thu May 26 17:12:33 2016 +0200
Committer: Mikael Ståldal <[email protected]>
Committed: Thu May 26 17:12:33 2016 +0200

----------------------------------------------------------------------
 .../core/appender/FastConsoleAppender.java      | 227 +++++++++++++++++++
 .../jmh/Log4j2AppenderComparisonBenchmark.java  |  18 ++
 .../resources/log4j2-appenderComparison.xml     |   6 +
 3 files changed, 251 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/06c55468/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FastConsoleAppender.java
----------------------------------------------------------------------
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FastConsoleAppender.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FastConsoleAppender.java
new file mode 100644
index 0000000..a7cd905
--- /dev/null
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FastConsoleAppender.java
@@ -0,0 +1,227 @@
+/*
+ * 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.appender;
+
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import
org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
+import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.apache.logging.log4j.core.util.CloseShieldOutputStream;
+
+/**
+ * Appends log events to <code>System.out</code> or
<code>System.err</code> using a layout specified by the user. The
+ * default target is <code>System.out</code>.
+ */
+@Plugin(name = "FastConsole", category = "Core", elementType = "appender",
printObject = true)
+public final class FastConsoleAppender extends
AbstractOutputStreamAppender<OutputStreamManager> {
+
+    private static ConsoleManagerFactory factory = new
ConsoleManagerFactory();
+    private static final Target DEFAULT_TARGET = Target.SYSTEM_OUT;
+    private static final AtomicInteger COUNT = new AtomicInteger();
+
+    private final Target target;
+
+    /**
+     * Enumeration of console destinations.
+     */
+    public enum Target {
+        /** Standard output. */
+        SYSTEM_OUT,
+        /** Standard error output. */
+        SYSTEM_ERR
+    }
+
+    private FastConsoleAppender(final String name, final Layout<? extends
Serializable> layout, final Filter filter,
+                                final OutputStreamManager manager, final
boolean ignoreExceptions, Target target) {
+        super(name, layout, filter, ignoreExceptions, true, manager);
+        this.target = target;
+    }
+
+    /**
+     * Creates a Console Appender.
+     *
+     * @param layout The layout to use (required).
+     * @param filter The Filter or null.
+     * @param target The target (SYSTEM_OUT or SYSTEM_ERR). The default is
SYSTEM_OUT.
+     * @param name The name of the Appender (required).
+     * @param ignoreExceptions If {@code "true"} (default) exceptions
encountered when appending events are logged; otherwise they
+     *            are propagated to the caller.
+     * @return The ConsoleAppender.
+     */
+    @PluginFactory
+    public static FastConsoleAppender createAppender(
+            // @formatter:off
+            @PluginElement("Layout") Layout<? extends Serializable> layout,
+            @PluginElement("Filter") final Filter filter,
+            @PluginAttribute(value = "target") Target target,
+            @PluginAttribute("name") final String name,
+            @PluginAttribute(value = "ignoreExceptions", defaultBoolean =
true) final boolean ignoreExceptions) {
+            // @formatter:on
+        if (name == null) {
+            LOGGER.error("No name provided for ConsoleAppender");
+            return null;
+        }
+        if (layout == null) {
+            layout = PatternLayout.createDefaultLayout();
+        }
+        target = target == null ? Target.SYSTEM_OUT : target;
+        return new FastConsoleAppender(name, layout, filter,
getManager(target, layout), ignoreExceptions, target);
+    }
+
+    public static FastConsoleAppender createDefaultAppenderForLayout(final
Layout<? extends Serializable> layout) {
+        // this method cannot use the builder class without introducing an
infinite loop due to DefaultConfiguration
+        return new FastConsoleAppender("DefaultConsole-" +
COUNT.incrementAndGet(), layout, null,
+                getDefaultManager(DEFAULT_TARGET, layout), true,
DEFAULT_TARGET);
+    }
+
+    @PluginBuilderFactory
+    public static Builder newBuilder() {
+        return new Builder();
+    }
+
+    /**
+     * Builds ConsoleAppender instances.
+     */
+    public static class Builder implements
org.apache.logging.log4j.core.util.Builder<FastConsoleAppender> {
+
+        @PluginElement("Layout")
+        @Required
+        private Layout<? extends Serializable> layout =
PatternLayout.createDefaultLayout();
+
+        @PluginElement("Filter")
+        private Filter filter;
+
+        @PluginBuilderAttribute
+        @Required
+        private Target target = DEFAULT_TARGET;
+
+        @PluginBuilderAttribute
+        @Required
+        private String name;
+
+        @PluginBuilderAttribute
+        private boolean ignoreExceptions = true;
+
+        public Builder setLayout(final Layout<? extends Serializable>
aLayout) {
+            this.layout = aLayout;
+            return this;
+        }
+
+        public Builder setFilter(final Filter aFilter) {
+            this.filter = aFilter;
+            return this;
+        }
+
+        public Builder setTarget(final Target aTarget) {
+            this.target = aTarget;
+            return this;
+        }
+
+        public Builder setName(final String aName) {
+            this.name = aName;
+            return this;
+        }
+
+        public Builder setIgnoreExceptions(final boolean
shouldIgnoreExceptions) {
+            this.ignoreExceptions = shouldIgnoreExceptions;
+            return this;
+        }
+
+        @Override
+        public FastConsoleAppender build() {
+            return new FastConsoleAppender(name, layout, filter,
getManager(target, layout), ignoreExceptions, target);
+        }
+    }
+
+    private static OutputStreamManager getDefaultManager(final Target
target, final Layout<? extends Serializable> layout) {
+        final OutputStream os = getOutputStream(target);
+
+        // LOG4J2-1176 DefaultConfiguration should not share
OutputStreamManager instances to avoid memory leaks.
+        final String managerName = target.name() + '-' + COUNT.get();
+        return OutputStreamManager.getManager(managerName, new
FactoryData(os, managerName, layout), factory);
+    }
+
+    private static OutputStreamManager getManager(final Target target,
final Layout<? extends Serializable> layout) {
+        final OutputStream os = getOutputStream(target);
+        final String managerName = target.name();
+        return OutputStreamManager.getManager(managerName, new
FactoryData(os, managerName, layout), factory);
+    }
+
+    private static OutputStream getOutputStream(final Target target) {
+        OutputStream outputStream = target == Target.SYSTEM_OUT
+            ? new FileOutputStream(FileDescriptor.out)
+            : new FileOutputStream(FileDescriptor.err);
+        return new CloseShieldOutputStream(outputStream);
+    }
+
+    /**
+     * Data to pass to factory method.
+     */
+    private static class FactoryData {
+        private final OutputStream os;
+        private final String name;
+        private final Layout<? extends Serializable> layout;
+
+        /**
+         * Constructor.
+         *
+         * @param os The OutputStream.
+         * @param type The name of the target.
+         * @param layout A Serializable layout
+         */
+        public FactoryData(final OutputStream os, final String type, final
Layout<? extends Serializable> layout) {
+            this.os = os;
+            this.name = type;
+            this.layout = layout;
+        }
+    }
+
+    /**
+     * Factory to create the Appender.
+     */
+    private static class ConsoleManagerFactory implements
ManagerFactory<OutputStreamManager, FactoryData> {
+
+        /**
+         * Create an OutputStreamManager.
+         *
+         * @param name The name of the entity to manage.
+         * @param data The data required to create the entity.
+         * @return The OutputStreamManager
+         */
+        @Override
+        public OutputStreamManager createManager(final String name, final
FactoryData data) {
+            return new OutputStreamManager(data.os, data.name,
data.layout, true);
+        }
+    }
+
+    public Target getTarget() {
+        return target;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/06c55468/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/Log4j2AppenderComparisonBenchmark.java
----------------------------------------------------------------------
diff --git
a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/Log4j2AppenderComparisonBenchmark.java
b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/Log4j2AppenderComparisonBenchmark.java
index 0527709..a4ea02e 100644
---
a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/Log4j2AppenderComparisonBenchmark.java
+++
b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/Log4j2AppenderComparisonBenchmark.java
@@ -57,12 +57,14 @@ public class Log4j2AppenderComparisonBenchmark {
     private Logger rafLogger;
     private Logger mmapLogger;
     private Logger consoleLogger;
+    private Logger fastConsoleLogger;
     private Logger noopLogger;
     private Logger rewriteLogger;
     private Appender fileAppender;
     private Appender rafAppender;
     private Appender mmapAppender;
     private Appender consoleAppender;
+    private Appender fastConsoleAppender;
     private Appender noopAppender;
     private Appender rewriteAppender;

@@ -102,6 +104,7 @@ public class Log4j2AppenderComparisonBenchmark {
         rafLogger = LogManager.getLogger("RAFLogger");
         mmapLogger = LogManager.getLogger("MMapLogger");
         consoleLogger = LogManager.getLogger("ConsoleLogger");
+        fastConsoleLogger = LogManager.getLogger("FastConsoleLogger");
         noopLogger = LogManager.getLogger("NoopLogger");
         rewriteLogger = LogManager.getLogger("RewriteLogger");

@@ -109,6 +112,7 @@ public class Log4j2AppenderComparisonBenchmark {
         rafAppender = ((org.apache.logging.log4j.core.Logger)
rafLogger).getAppenders().get("RandomAccessFile");
         mmapAppender = ((org.apache.logging.log4j.core.Logger)
mmapLogger).getAppenders().get("MemoryMappedFile");
         consoleAppender = ((org.apache.logging.log4j.core.Logger)
consoleLogger).getAppenders().get("Console");
+        fastConsoleAppender = ((org.apache.logging.log4j.core.Logger)
fastConsoleLogger).getAppenders().get("FastConsole");
         noopAppender = ((org.apache.logging.log4j.core.Logger)
noopLogger).getAppenders().get("NoOp");
         rewriteAppender = ((org.apache.logging.log4j.core.Logger)
rewriteLogger).getAppenders().get("Rewrite");
     }
@@ -218,4 +222,18 @@ public class Log4j2AppenderComparisonBenchmark {
     public void appenderConsole() {
         consoleAppender.append(EVENT);
     }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void end2endFastConsole() {
+        fastConsoleLogger.debug(MESSAGE);
+    }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void appenderFastConsole() {
+        fastConsoleAppender.append(EVENT);
+    }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/06c55468/log4j-perf/src/main/resources/log4j2-appenderComparison.xml
----------------------------------------------------------------------
diff --git a/log4j-perf/src/main/resources/log4j2-appenderComparison.xml
b/log4j-perf/src/main/resources/log4j2-appenderComparison.xml
index 741a225..8ad6327 100644
--- a/log4j-perf/src/main/resources/log4j2-appenderComparison.xml
+++ b/log4j-perf/src/main/resources/log4j2-appenderComparison.xml
@@ -21,6 +21,9 @@
         <Console name="Console" target="SYSTEM_OUT">
             <PatternLayout pattern="%d %p [%t] %c{1} %X{transactionId} -
%m%n"/>
         </Console>
+        <FastConsole name="FastConsole" target="SYSTEM_OUT">
+            <PatternLayout pattern="%d %p [%t] %c{1} %X{transactionId} -
%m%n"/>
+        </FastConsole>
         <File name="File" fileName="target/testlog4j2.log"
immediateFlush="false">
             <PatternLayout pattern="%d %p [%t] %c{1} %X{transactionId} -
%m%n"/>
         </File>
@@ -55,6 +58,9 @@
         <Logger name="ConsoleLogger" level="debug" additivity="false">
             <AppenderRef ref="Console"/>
         </Logger>
+        <Logger name="FastConsoleLogger" level="debug" additivity="false">
+            <AppenderRef ref="FastConsole"/>
+        </Logger>
         <Logger name="NoopLogger" level="debug" additivity="false">
             <AppenderRef ref="NoOp"/>
         </Logger>




-- 
Matt Sicker <[email protected]>

Reply via email to