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.