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 <[email protected]> wrote: > 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]> > -- Matt Sicker <[email protected]>
