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
>
> 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]>

Reply via email to