You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by Matt Sicker <bo...@gmail.com> on 2016/05/26 15:22:14 UTC

Fwd: logging-log4j2 git commit: FastConsoleAppender

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: <mi...@apache.org>
Date: 26 May 2016 at 10:12
Subject: logging-log4j2 git commit: FastConsoleAppender
To: commits@logging.apache.org


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 <mi...@magine.com>
Authored: Thu May 26 17:12:33 2016 +0200
Committer: Mikael Ståldal <mi...@magine.com>
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 <bo...@gmail.com>

Re: logging-log4j2 git commit: FastConsoleAppender

Posted by Matt Sicker <bo...@gmail.com>.
Added documentation to the "Extending Log4j" page. Let me know if you have
any more questions about it.

On 26 May 2016 at 16:23, Matt Sicker <bo...@gmail.com> wrote:

> Is there any place the factory method version is documented? I could add
> the info there. Otherwise, I'll have to figure out an appropriate place for
> it (perhaps in the manual).
>
> On 26 May 2016 at 13:35, Matt Sicker <bo...@gmail.com> wrote:
>
>> Sure. I can't believe I forgot to document that better.
>>
>> On 26 May 2016 at 12:06, Ralph Goers <ra...@dslextreme.com> wrote:
>>
>>> Can you provide documentation on using the builder?  I tried to
>>> implement something a few months ago using a builder and couldn’t quite
>>> figure it all out so I went back to using a factory.
>>>
>>> Ralph
>>>
>>> On May 26, 2016, at 8:31 AM, Matt Sicker <bo...@gmail.com> wrote:
>>>
>>> I prefer builders when you have more than 2 arguments to the factory.
>>> This is based on Item 2 from Effective Java (prefer builders for
>>> constructors that take a lot of arguments).
>>>
>>> On 26 May 2016 at 10:24, Mikael Ståldal <mi...@magine.com>
>>> wrote:
>>>
>>>> Which one of builder and factory is preferred?
>>>>
>>>> On Thu, May 26, 2016 at 5:22 PM, Matt Sicker <bo...@gmail.com> wrote:
>>>>
>>>>> 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: <mi...@apache.org>
>>>>> Date: 26 May 2016 at 10:12
>>>>> Subject: logging-log4j2 git commit: FastConsoleAppender
>>>>> To: commits@logging.apache.org
>>>>>
>>>>>
>>>>> 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 <mi...@magine.com>
>>>>> Authored: Thu May 26 17:12:33 2016 +0200
>>>>> Committer: Mikael Ståldal <mi...@magine.com>
>>>>> 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 <bo...@gmail.com>
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> [image: MagineTV]
>>>>
>>>> *Mikael Ståldal*
>>>> Senior software developer
>>>>
>>>> *Magine TV*
>>>> mikael.staldal@magine.com
>>>> Grev Turegatan 3  | 114 46 Stockholm, Sweden  |   www.magine.com
>>>> <http://www.magine.com/>
>>>>
>>>> Privileged and/or Confidential Information may be contained in this
>>>> message. If you are not the addressee indicated in this message
>>>> (or responsible for delivery of the message to such a person), you may
>>>> not copy or deliver this message to anyone. In such case,
>>>> you should destroy this message and kindly notify the sender by reply
>>>> email.
>>>>
>>>
>>>
>>>
>>> --
>>> Matt Sicker <bo...@gmail.com>
>>>
>>>
>>>
>>
>>
>> --
>> Matt Sicker <bo...@gmail.com>
>>
>
>
>
> --
> Matt Sicker <bo...@gmail.com>
>



-- 
Matt Sicker <bo...@gmail.com>

Re: logging-log4j2 git commit: FastConsoleAppender

Posted by Matt Sicker <bo...@gmail.com>.
Is there any place the factory method version is documented? I could add
the info there. Otherwise, I'll have to figure out an appropriate place for
it (perhaps in the manual).

On 26 May 2016 at 13:35, Matt Sicker <bo...@gmail.com> wrote:

> Sure. I can't believe I forgot to document that better.
>
> On 26 May 2016 at 12:06, Ralph Goers <ra...@dslextreme.com> wrote:
>
>> Can you provide documentation on using the builder?  I tried to implement
>> something a few months ago using a builder and couldn’t quite figure it all
>> out so I went back to using a factory.
>>
>> Ralph
>>
>> On May 26, 2016, at 8:31 AM, Matt Sicker <bo...@gmail.com> wrote:
>>
>> I prefer builders when you have more than 2 arguments to the factory.
>> This is based on Item 2 from Effective Java (prefer builders for
>> constructors that take a lot of arguments).
>>
>> On 26 May 2016 at 10:24, Mikael Ståldal <mi...@magine.com>
>> wrote:
>>
>>> Which one of builder and factory is preferred?
>>>
>>> On Thu, May 26, 2016 at 5:22 PM, Matt Sicker <bo...@gmail.com> wrote:
>>>
>>>> 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: <mi...@apache.org>
>>>> Date: 26 May 2016 at 10:12
>>>> Subject: logging-log4j2 git commit: FastConsoleAppender
>>>> To: commits@logging.apache.org
>>>>
>>>>
>>>> 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 <mi...@magine.com>
>>>> Authored: Thu May 26 17:12:33 2016 +0200
>>>> Committer: Mikael Ståldal <mi...@magine.com>
>>>> 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 <bo...@gmail.com>
>>>>
>>>
>>>
>>>
>>> --
>>> [image: MagineTV]
>>>
>>> *Mikael Ståldal*
>>> Senior software developer
>>>
>>> *Magine TV*
>>> mikael.staldal@magine.com
>>> Grev Turegatan 3  | 114 46 Stockholm, Sweden  |   www.magine.com
>>> <http://www.magine.com/>
>>>
>>> Privileged and/or Confidential Information may be contained in this
>>> message. If you are not the addressee indicated in this message
>>> (or responsible for delivery of the message to such a person), you may
>>> not copy or deliver this message to anyone. In such case,
>>> you should destroy this message and kindly notify the sender by reply
>>> email.
>>>
>>
>>
>>
>> --
>> Matt Sicker <bo...@gmail.com>
>>
>>
>>
>
>
> --
> Matt Sicker <bo...@gmail.com>
>



-- 
Matt Sicker <bo...@gmail.com>

Re: logging-log4j2 git commit: FastConsoleAppender

Posted by Matt Sicker <bo...@gmail.com>.
Sure. I can't believe I forgot to document that better.

On 26 May 2016 at 12:06, Ralph Goers <ra...@dslextreme.com> wrote:

> Can you provide documentation on using the builder?  I tried to implement
> something a few months ago using a builder and couldn’t quite figure it all
> out so I went back to using a factory.
>
> Ralph
>
> On May 26, 2016, at 8:31 AM, Matt Sicker <bo...@gmail.com> wrote:
>
> I prefer builders when you have more than 2 arguments to the factory. This
> is based on Item 2 from Effective Java (prefer builders for constructors
> that take a lot of arguments).
>
> On 26 May 2016 at 10:24, Mikael Ståldal <mi...@magine.com> wrote:
>
>> Which one of builder and factory is preferred?
>>
>> On Thu, May 26, 2016 at 5:22 PM, Matt Sicker <bo...@gmail.com> wrote:
>>
>>> 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: <mi...@apache.org>
>>> Date: 26 May 2016 at 10:12
>>> Subject: logging-log4j2 git commit: FastConsoleAppender
>>> To: commits@logging.apache.org
>>>
>>>
>>> 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 <mi...@magine.com>
>>> Authored: Thu May 26 17:12:33 2016 +0200
>>> Committer: Mikael Ståldal <mi...@magine.com>
>>> 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 <bo...@gmail.com>
>>>
>>
>>
>>
>> --
>> [image: MagineTV]
>>
>> *Mikael Ståldal*
>> Senior software developer
>>
>> *Magine TV*
>> mikael.staldal@magine.com
>> Grev Turegatan 3  | 114 46 Stockholm, Sweden  |   www.magine.com
>> <http://www.magine.com/>
>>
>> Privileged and/or Confidential Information may be contained in this
>> message. If you are not the addressee indicated in this message
>> (or responsible for delivery of the message to such a person), you may
>> not copy or deliver this message to anyone. In such case,
>> you should destroy this message and kindly notify the sender by reply
>> email.
>>
>
>
>
> --
> Matt Sicker <bo...@gmail.com>
>
>
>


-- 
Matt Sicker <bo...@gmail.com>

Re: logging-log4j2 git commit: FastConsoleAppender

Posted by Ralph Goers <ra...@dslextreme.com>.
Can you provide documentation on using the builder?  I tried to implement something a few months ago using a builder and couldn’t quite figure it all out so I went back to using a factory.

Ralph

> On May 26, 2016, at 8:31 AM, Matt Sicker <bo...@gmail.com> wrote:
> 
> I prefer builders when you have more than 2 arguments to the factory. This is based on Item 2 from Effective Java (prefer builders for constructors that take a lot of arguments).
> 
> On 26 May 2016 at 10:24, Mikael Ståldal <mikael.staldal@magine.com <ma...@magine.com>> wrote:
> Which one of builder and factory is preferred?
> 
> On Thu, May 26, 2016 at 5:22 PM, Matt Sicker <boards@gmail.com <ma...@gmail.com>> wrote:
> 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: <mikes@apache.org <ma...@apache.org>>
> Date: 26 May 2016 at 10:12
> Subject: logging-log4j2 git commit: FastConsoleAppender
> To: commits@logging.apache.org <ma...@logging.apache.org>
> 
> 
> Repository: logging-log4j2
> Updated Branches:
>   refs/heads/LOG4J2-1395 [created] 06c554689
> 
> 
> FastConsoleAppender
> 
> 
> Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo <http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo>
> Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/06c55468 <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 <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 <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 <mikael.staldal@magine.com <ma...@magine.com>>
> Authored: Thu May 26 17:12:33 2016 +0200
> Committer: Mikael Ståldal <mikael.staldal@magine.com <ma...@magine.com>>
> 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 <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 <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 <http://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 <http://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 <http://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 <http://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 <http://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 <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 <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 <boards@gmail.com <ma...@gmail.com>>
> 
> 
> 
> -- 
>  
> 
> Mikael Ståldal
> Senior software developer 
> 
> Magine TV
> mikael.staldal@magine.com <ma...@magine.com>    
> Grev Turegatan 3  | 114 46 Stockholm, Sweden  |   www.magine.com  <http://www.magine.com/>
> 
> Privileged and/or Confidential Information may be contained in this message. If you are not the addressee indicated in this message
> (or responsible for delivery of the message to such a person), you may not copy or deliver this message to anyone. In such case, 
> you should destroy this message and kindly notify the sender by reply email.   
> 
> 
> 
> -- 
> Matt Sicker <boards@gmail.com <ma...@gmail.com>>


Re: logging-log4j2 git commit: FastConsoleAppender

Posted by Matt Sicker <bo...@gmail.com>.
I prefer builders when you have more than 2 arguments to the factory. This
is based on Item 2 from Effective Java (prefer builders for constructors
that take a lot of arguments).

On 26 May 2016 at 10:24, Mikael Ståldal <mi...@magine.com> wrote:

> Which one of builder and factory is preferred?
>
> On Thu, May 26, 2016 at 5:22 PM, Matt Sicker <bo...@gmail.com> wrote:
>
>> 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: <mi...@apache.org>
>> Date: 26 May 2016 at 10:12
>> Subject: logging-log4j2 git commit: FastConsoleAppender
>> To: commits@logging.apache.org
>>
>>
>> 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 <mi...@magine.com>
>> Authored: Thu May 26 17:12:33 2016 +0200
>> Committer: Mikael Ståldal <mi...@magine.com>
>> 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 <bo...@gmail.com>
>>
>
>
>
> --
> [image: MagineTV]
>
> *Mikael Ståldal*
> Senior software developer
>
> *Magine TV*
> mikael.staldal@magine.com
> Grev Turegatan 3  | 114 46 Stockholm, Sweden  |   www.magine.com
>
> Privileged and/or Confidential Information may be contained in this
> message. If you are not the addressee indicated in this message
> (or responsible for delivery of the message to such a person), you may not
> copy or deliver this message to anyone. In such case,
> you should destroy this message and kindly notify the sender by reply
> email.
>



-- 
Matt Sicker <bo...@gmail.com>

Re: logging-log4j2 git commit: FastConsoleAppender

Posted by Mikael Ståldal <mi...@magine.com>.
Which one of builder and factory is preferred?

On Thu, May 26, 2016 at 5:22 PM, Matt Sicker <bo...@gmail.com> wrote:

> 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: <mi...@apache.org>
> Date: 26 May 2016 at 10:12
> Subject: logging-log4j2 git commit: FastConsoleAppender
> To: commits@logging.apache.org
>
>
> 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 <mi...@magine.com>
> Authored: Thu May 26 17:12:33 2016 +0200
> Committer: Mikael Ståldal <mi...@magine.com>
> 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 <bo...@gmail.com>
>



-- 
[image: MagineTV]

*Mikael Ståldal*
Senior software developer

*Magine TV*
mikael.staldal@magine.com
Grev Turegatan 3  | 114 46 Stockholm, Sweden  |   www.magine.com

Privileged and/or Confidential Information may be contained in this
message. If you are not the addressee indicated in this message
(or responsible for delivery of the message to such a person), you may not
copy or deliver this message to anyone. In such case,
you should destroy this message and kindly notify the sender by reply
email.