Sure. I can't believe I forgot to document that better.

On 26 May 2016 at 12:06, Ralph Goers <[email protected]> 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 <[email protected]> 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 <[email protected]> wrote:
>
>> Which one of builder and factory is preferred?
>>
>> On Thu, May 26, 2016 at 5:22 PM, Matt Sicker <[email protected]> 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: <[email protected]>
>>> Date: 26 May 2016 at 10:12
>>> Subject: logging-log4j2 git commit: FastConsoleAppender
>>> To: [email protected]
>>>
>>>
>>> Repository: logging-log4j2
>>> Updated Branches:
>>>   refs/heads/LOG4J2-1395 [created] 06c554689
>>>
>>>
>>> FastConsoleAppender
>>>
>>>
>>> Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
>>> Commit:
>>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/06c55468
>>> Tree:
>>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/06c55468
>>> Diff:
>>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/06c55468
>>>
>>> Branch: refs/heads/LOG4J2-1395
>>> Commit: 06c55468948efdce95a591801d5f9e2ffdb69dd4
>>> Parents: e012269
>>> Author: Mikael Ståldal <[email protected]>
>>> Authored: Thu May 26 17:12:33 2016 +0200
>>> Committer: Mikael Ståldal <[email protected]>
>>> Committed: Thu May 26 17:12:33 2016 +0200
>>>
>>> ----------------------------------------------------------------------
>>>  .../core/appender/FastConsoleAppender.java      | 227
>>> +++++++++++++++++++
>>>  .../jmh/Log4j2AppenderComparisonBenchmark.java  |  18 ++
>>>  .../resources/log4j2-appenderComparison.xml     |   6 +
>>>  3 files changed, 251 insertions(+)
>>> ----------------------------------------------------------------------
>>>
>>>
>>>
>>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/06c55468/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FastConsoleAppender.java
>>> ----------------------------------------------------------------------
>>> diff --git
>>> a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FastConsoleAppender.java
>>> b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FastConsoleAppender.java
>>> new file mode 100644
>>> index 0000000..a7cd905
>>> --- /dev/null
>>> +++
>>> b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FastConsoleAppender.java
>>> @@ -0,0 +1,227 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one or more
>>> + * contributor license agreements. See the NOTICE file distributed with
>>> + * this work for additional information regarding copyright ownership.
>>> + * The ASF licenses this file to You under the Apache license, Version
>>> 2.0
>>> + * (the "License"); you may not use this file except in compliance with
>>> + * the License. You may obtain a copy of the License at
>>> + *
>>> + *      http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * Unless required by applicable law or agreed to in writing, software
>>> + * distributed under the License is distributed on an "AS IS" BASIS,
>>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>>> implied.
>>> + * See the license for the specific language governing permissions and
>>> + * limitations under the license.
>>> + */
>>> +package org.apache.logging.log4j.core.appender;
>>> +
>>> +import java.io.FileDescriptor;
>>> +import java.io.FileOutputStream;
>>> +import java.io.OutputStream;
>>> +import java.io.Serializable;
>>> +import java.util.concurrent.atomic.AtomicInteger;
>>> +
>>> +import org.apache.logging.log4j.core.Filter;
>>> +import org.apache.logging.log4j.core.Layout;
>>> +import org.apache.logging.log4j.core.config.plugins.Plugin;
>>> +import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
>>> +import
>>> org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
>>> +import
>>> org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
>>> +import org.apache.logging.log4j.core.config.plugins.PluginElement;
>>> +import org.apache.logging.log4j.core.config.plugins.PluginFactory;
>>> +import
>>> org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
>>> +import org.apache.logging.log4j.core.layout.PatternLayout;
>>> +import org.apache.logging.log4j.core.util.CloseShieldOutputStream;
>>> +
>>> +/**
>>> + * Appends log events to <code>System.out</code> or
>>> <code>System.err</code> using a layout specified by the user. The
>>> + * default target is <code>System.out</code>.
>>> + */
>>> +@Plugin(name = "FastConsole", category = "Core", elementType =
>>> "appender", printObject = true)
>>> +public final class FastConsoleAppender extends
>>> AbstractOutputStreamAppender<OutputStreamManager> {
>>> +
>>> +    private static ConsoleManagerFactory factory = new
>>> ConsoleManagerFactory();
>>> +    private static final Target DEFAULT_TARGET = Target.SYSTEM_OUT;
>>> +    private static final AtomicInteger COUNT = new AtomicInteger();
>>> +
>>> +    private final Target target;
>>> +
>>> +    /**
>>> +     * Enumeration of console destinations.
>>> +     */
>>> +    public enum Target {
>>> +        /** Standard output. */
>>> +        SYSTEM_OUT,
>>> +        /** Standard error output. */
>>> +        SYSTEM_ERR
>>> +    }
>>> +
>>> +    private FastConsoleAppender(final String name, final Layout<?
>>> extends Serializable> layout, final Filter filter,
>>> +                                final OutputStreamManager manager,
>>> final boolean ignoreExceptions, Target target) {
>>> +        super(name, layout, filter, ignoreExceptions, true, manager);
>>> +        this.target = target;
>>> +    }
>>> +
>>> +    /**
>>> +     * Creates a Console Appender.
>>> +     *
>>> +     * @param layout The layout to use (required).
>>> +     * @param filter The Filter or null.
>>> +     * @param target The target (SYSTEM_OUT or SYSTEM_ERR). The default
>>> is SYSTEM_OUT.
>>> +     * @param name The name of the Appender (required).
>>> +     * @param ignoreExceptions If {@code "true"} (default) exceptions
>>> encountered when appending events are logged; otherwise they
>>> +     *            are propagated to the caller.
>>> +     * @return The ConsoleAppender.
>>> +     */
>>> +    @PluginFactory
>>> +    public static FastConsoleAppender createAppender(
>>> +            // @formatter:off
>>> +            @PluginElement("Layout") Layout<? extends Serializable>
>>> layout,
>>> +            @PluginElement("Filter") final Filter filter,
>>> +            @PluginAttribute(value = "target") Target target,
>>> +            @PluginAttribute("name") final String name,
>>> +            @PluginAttribute(value = "ignoreExceptions", defaultBoolean
>>> = true) final boolean ignoreExceptions) {
>>> +            // @formatter:on
>>> +        if (name == null) {
>>> +            LOGGER.error("No name provided for ConsoleAppender");
>>> +            return null;
>>> +        }
>>> +        if (layout == null) {
>>> +            layout = PatternLayout.createDefaultLayout();
>>> +        }
>>> +        target = target == null ? Target.SYSTEM_OUT : target;
>>> +        return new FastConsoleAppender(name, layout, filter,
>>> getManager(target, layout), ignoreExceptions, target);
>>> +    }
>>> +
>>> +    public static FastConsoleAppender
>>> createDefaultAppenderForLayout(final Layout<? extends Serializable> layout)
>>> {
>>> +        // this method cannot use the builder class without introducing
>>> an infinite loop due to DefaultConfiguration
>>> +        return new FastConsoleAppender("DefaultConsole-" +
>>> COUNT.incrementAndGet(), layout, null,
>>> +                getDefaultManager(DEFAULT_TARGET, layout), true,
>>> DEFAULT_TARGET);
>>> +    }
>>> +
>>> +    @PluginBuilderFactory
>>> +    public static Builder newBuilder() {
>>> +        return new Builder();
>>> +    }
>>> +
>>> +    /**
>>> +     * Builds ConsoleAppender instances.
>>> +     */
>>> +    public static class Builder implements
>>> org.apache.logging.log4j.core.util.Builder<FastConsoleAppender> {
>>> +
>>> +        @PluginElement("Layout")
>>> +        @Required
>>> +        private Layout<? extends Serializable> layout =
>>> PatternLayout.createDefaultLayout();
>>> +
>>> +        @PluginElement("Filter")
>>> +        private Filter filter;
>>> +
>>> +        @PluginBuilderAttribute
>>> +        @Required
>>> +        private Target target = DEFAULT_TARGET;
>>> +
>>> +        @PluginBuilderAttribute
>>> +        @Required
>>> +        private String name;
>>> +
>>> +        @PluginBuilderAttribute
>>> +        private boolean ignoreExceptions = true;
>>> +
>>> +        public Builder setLayout(final Layout<? extends Serializable>
>>> aLayout) {
>>> +            this.layout = aLayout;
>>> +            return this;
>>> +        }
>>> +
>>> +        public Builder setFilter(final Filter aFilter) {
>>> +            this.filter = aFilter;
>>> +            return this;
>>> +        }
>>> +
>>> +        public Builder setTarget(final Target aTarget) {
>>> +            this.target = aTarget;
>>> +            return this;
>>> +        }
>>> +
>>> +        public Builder setName(final String aName) {
>>> +            this.name = aName;
>>> +            return this;
>>> +        }
>>> +
>>> +        public Builder setIgnoreExceptions(final boolean
>>> shouldIgnoreExceptions) {
>>> +            this.ignoreExceptions = shouldIgnoreExceptions;
>>> +            return this;
>>> +        }
>>> +
>>> +        @Override
>>> +        public FastConsoleAppender build() {
>>> +            return new FastConsoleAppender(name, layout, filter,
>>> getManager(target, layout), ignoreExceptions, target);
>>> +        }
>>> +    }
>>> +
>>> +    private static OutputStreamManager getDefaultManager(final Target
>>> target, final Layout<? extends Serializable> layout) {
>>> +        final OutputStream os = getOutputStream(target);
>>> +
>>> +        // LOG4J2-1176 DefaultConfiguration should not share
>>> OutputStreamManager instances to avoid memory leaks.
>>> +        final String managerName = target.name() + '-' + COUNT.get();
>>> +        return OutputStreamManager.getManager(managerName, new
>>> FactoryData(os, managerName, layout), factory);
>>> +    }
>>> +
>>> +    private static OutputStreamManager getManager(final Target target,
>>> final Layout<? extends Serializable> layout) {
>>> +        final OutputStream os = getOutputStream(target);
>>> +        final String managerName = target.name();
>>> +        return OutputStreamManager.getManager(managerName, new
>>> FactoryData(os, managerName, layout), factory);
>>> +    }
>>> +
>>> +    private static OutputStream getOutputStream(final Target target) {
>>> +        OutputStream outputStream = target == Target.SYSTEM_OUT
>>> +            ? new FileOutputStream(FileDescriptor.out)
>>> +            : new FileOutputStream(FileDescriptor.err);
>>> +        return new CloseShieldOutputStream(outputStream);
>>> +    }
>>> +
>>> +    /**
>>> +     * Data to pass to factory method.
>>> +     */
>>> +    private static class FactoryData {
>>> +        private final OutputStream os;
>>> +        private final String name;
>>> +        private final Layout<? extends Serializable> layout;
>>> +
>>> +        /**
>>> +         * Constructor.
>>> +         *
>>> +         * @param os The OutputStream.
>>> +         * @param type The name of the target.
>>> +         * @param layout A Serializable layout
>>> +         */
>>> +        public FactoryData(final OutputStream os, final String type,
>>> final Layout<? extends Serializable> layout) {
>>> +            this.os = os;
>>> +            this.name = type;
>>> +            this.layout = layout;
>>> +        }
>>> +    }
>>> +
>>> +    /**
>>> +     * Factory to create the Appender.
>>> +     */
>>> +    private static class ConsoleManagerFactory implements
>>> ManagerFactory<OutputStreamManager, FactoryData> {
>>> +
>>> +        /**
>>> +         * Create an OutputStreamManager.
>>> +         *
>>> +         * @param name The name of the entity to manage.
>>> +         * @param data The data required to create the entity.
>>> +         * @return The OutputStreamManager
>>> +         */
>>> +        @Override
>>> +        public OutputStreamManager createManager(final String name,
>>> final FactoryData data) {
>>> +            return new OutputStreamManager(data.os, data.name,
>>> data.layout, true);
>>> +        }
>>> +    }
>>> +
>>> +    public Target getTarget() {
>>> +        return target;
>>> +    }
>>> +
>>> +}
>>>
>>>
>>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/06c55468/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/Log4j2AppenderComparisonBenchmark.java
>>> ----------------------------------------------------------------------
>>> diff --git
>>> a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/Log4j2AppenderComparisonBenchmark.java
>>> b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/Log4j2AppenderComparisonBenchmark.java
>>> index 0527709..a4ea02e 100644
>>> ---
>>> a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/Log4j2AppenderComparisonBenchmark.java
>>> +++
>>> b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/Log4j2AppenderComparisonBenchmark.java
>>> @@ -57,12 +57,14 @@ public class Log4j2AppenderComparisonBenchmark {
>>>      private Logger rafLogger;
>>>      private Logger mmapLogger;
>>>      private Logger consoleLogger;
>>> +    private Logger fastConsoleLogger;
>>>      private Logger noopLogger;
>>>      private Logger rewriteLogger;
>>>      private Appender fileAppender;
>>>      private Appender rafAppender;
>>>      private Appender mmapAppender;
>>>      private Appender consoleAppender;
>>> +    private Appender fastConsoleAppender;
>>>      private Appender noopAppender;
>>>      private Appender rewriteAppender;
>>>
>>> @@ -102,6 +104,7 @@ public class Log4j2AppenderComparisonBenchmark {
>>>          rafLogger = LogManager.getLogger("RAFLogger");
>>>          mmapLogger = LogManager.getLogger("MMapLogger");
>>>          consoleLogger = LogManager.getLogger("ConsoleLogger");
>>> +        fastConsoleLogger = LogManager.getLogger("FastConsoleLogger");
>>>          noopLogger = LogManager.getLogger("NoopLogger");
>>>          rewriteLogger = LogManager.getLogger("RewriteLogger");
>>>
>>> @@ -109,6 +112,7 @@ public class Log4j2AppenderComparisonBenchmark {
>>>          rafAppender = ((org.apache.logging.log4j.core.Logger)
>>> rafLogger).getAppenders().get("RandomAccessFile");
>>>          mmapAppender = ((org.apache.logging.log4j.core.Logger)
>>> mmapLogger).getAppenders().get("MemoryMappedFile");
>>>          consoleAppender = ((org.apache.logging.log4j.core.Logger)
>>> consoleLogger).getAppenders().get("Console");
>>> +        fastConsoleAppender = ((org.apache.logging.log4j.core.Logger)
>>> fastConsoleLogger).getAppenders().get("FastConsole");
>>>          noopAppender = ((org.apache.logging.log4j.core.Logger)
>>> noopLogger).getAppenders().get("NoOp");
>>>          rewriteAppender = ((org.apache.logging.log4j.core.Logger)
>>> rewriteLogger).getAppenders().get("Rewrite");
>>>      }
>>> @@ -218,4 +222,18 @@ public class Log4j2AppenderComparisonBenchmark {
>>>      public void appenderConsole() {
>>>          consoleAppender.append(EVENT);
>>>      }
>>> +
>>> +    @BenchmarkMode(Mode.Throughput)
>>> +    @OutputTimeUnit(TimeUnit.SECONDS)
>>> +    @Benchmark
>>> +    public void end2endFastConsole() {
>>> +        fastConsoleLogger.debug(MESSAGE);
>>> +    }
>>> +
>>> +    @BenchmarkMode(Mode.Throughput)
>>> +    @OutputTimeUnit(TimeUnit.SECONDS)
>>> +    @Benchmark
>>> +    public void appenderFastConsole() {
>>> +        fastConsoleAppender.append(EVENT);
>>> +    }
>>>  }
>>>
>>>
>>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/06c55468/log4j-perf/src/main/resources/log4j2-appenderComparison.xml
>>> ----------------------------------------------------------------------
>>> diff --git a/log4j-perf/src/main/resources/log4j2-appenderComparison.xml
>>> b/log4j-perf/src/main/resources/log4j2-appenderComparison.xml
>>> index 741a225..8ad6327 100644
>>> --- a/log4j-perf/src/main/resources/log4j2-appenderComparison.xml
>>> +++ b/log4j-perf/src/main/resources/log4j2-appenderComparison.xml
>>> @@ -21,6 +21,9 @@
>>>          <Console name="Console" target="SYSTEM_OUT">
>>>              <PatternLayout pattern="%d %p [%t] %c{1} %X{transactionId}
>>> - %m%n"/>
>>>          </Console>
>>> +        <FastConsole name="FastConsole" target="SYSTEM_OUT">
>>> +            <PatternLayout pattern="%d %p [%t] %c{1} %X{transactionId}
>>> - %m%n"/>
>>> +        </FastConsole>
>>>          <File name="File" fileName="target/testlog4j2.log"
>>> immediateFlush="false">
>>>              <PatternLayout pattern="%d %p [%t] %c{1} %X{transactionId}
>>> - %m%n"/>
>>>          </File>
>>> @@ -55,6 +58,9 @@
>>>          <Logger name="ConsoleLogger" level="debug" additivity="false">
>>>              <AppenderRef ref="Console"/>
>>>          </Logger>
>>> +        <Logger name="FastConsoleLogger" level="debug"
>>> additivity="false">
>>> +            <AppenderRef ref="FastConsole"/>
>>> +        </Logger>
>>>          <Logger name="NoopLogger" level="debug" additivity="false">
>>>              <AppenderRef ref="NoOp"/>
>>>          </Logger>
>>>
>>>
>>>
>>>
>>> --
>>> Matt Sicker <[email protected]>
>>>
>>
>>
>>
>> --
>> [image: MagineTV]
>>
>> *Mikael Ståldal*
>> Senior software developer
>>
>> *Magine TV*
>> [email protected]
>> 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 <[email protected]>
>
>
>


-- 
Matt Sicker <[email protected]>

Reply via email to