direct paramter to ConsoleAppender
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/50d0bf16 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/50d0bf16 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/50d0bf16 Branch: refs/heads/master Commit: 50d0bf16861503e41954c74be9db869308b3a3e2 Parents: c0366fd Author: Mikael Ståldal <mikael.stal...@magine.com> Authored: Mon May 30 16:34:19 2016 +0200 Committer: Mikael Ståldal <mikael.stal...@magine.com> Committed: Mon May 30 16:34:19 2016 +0200 ---------------------------------------------------------------------- .../log4j/core/appender/ConsoleAppender.java | 56 +++-- .../core/appender/FastConsoleAppender.java | 227 ------------------- .../core/appender/ConsoleAppenderTest.java | 14 +- .../jmh/Log4j2AppenderComparisonBenchmark.java | 16 +- .../resources/log4j2-appenderComparison.xml | 8 +- 5 files changed, 57 insertions(+), 264 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/50d0bf16/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java index 4e1e87c..64a3a5b 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java @@ -16,6 +16,8 @@ */ package org.apache.logging.log4j.core.appender; +import java.io.FileDescriptor; +import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; @@ -80,12 +82,12 @@ public final class ConsoleAppender extends AbstractOutputStreamAppender<OutputSt * @param layout The layout to use (required). * @param filter The Filter or null. * @param targetStr The target ("SYSTEM_OUT" or "SYSTEM_ERR"). The default is "SYSTEM_OUT". - * @param follow If true will follow changes to the underlying output stream. * @param name The name of the Appender (required). + * @param follow If true will follow changes to the underlying output stream. * @param ignore If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise they * are propagated to the caller. * @return The ConsoleAppender. - * @deprecated Use {@link #createAppender(Layout, Filter, Target, String, boolean, boolean)}. + * @deprecated Use {@link #createAppender(Layout, Filter, Target, String, boolean, boolean, boolean)}. */ @Deprecated public static ConsoleAppender createAppender(Layout<? extends Serializable> layout, @@ -104,7 +106,7 @@ public final class ConsoleAppender extends AbstractOutputStreamAppender<OutputSt final boolean isFollow = Boolean.parseBoolean(follow); final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true); final Target target = targetStr == null ? DEFAULT_TARGET : Target.valueOf(targetStr); - return new ConsoleAppender(name, layout, filter, getManager(target, isFollow, layout), ignoreExceptions, target); + return new ConsoleAppender(name, layout, filter, getManager(target, isFollow, false, layout), ignoreExceptions, target); } /** @@ -113,8 +115,10 @@ public final class ConsoleAppender extends AbstractOutputStreamAppender<OutputSt * @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 follow If true will follow changes to the underlying output stream. * @param name The name of the Appender (required). + * @param follow If true will follow changes to the underlying output stream. + * @param direct If true will write directly to {@link java.io.FileDescriptor} and bypass + * {@link System#out}/{@link System#err}. * @param ignoreExceptions If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise they * are propagated to the caller. * @return The ConsoleAppender. @@ -127,6 +131,7 @@ public final class ConsoleAppender extends AbstractOutputStreamAppender<OutputSt @PluginAttribute(value = "target") Target target, @PluginAttribute("name") final String name, @PluginAttribute(value = "follow", defaultBoolean = false) final boolean follow, + @PluginAttribute(value = "direct", defaultBoolean = false) final boolean direct, @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) final boolean ignoreExceptions) { // @formatter:on if (name == null) { @@ -137,13 +142,17 @@ public final class ConsoleAppender extends AbstractOutputStreamAppender<OutputSt layout = PatternLayout.createDefaultLayout(); } target = target == null ? Target.SYSTEM_OUT : target; - return new ConsoleAppender(name, layout, filter, getManager(target, follow, layout), ignoreExceptions, target); + if (follow && direct) { + LOGGER.error("Cannot use both follow and direct on ConsoleAppender"); + return null; + } + return new ConsoleAppender(name, layout, filter, getManager(target, follow, direct, layout), ignoreExceptions, target); } public static ConsoleAppender createDefaultAppenderForLayout(final Layout<? extends Serializable> layout) { // this method cannot use the builder class without introducing an infinite loop due to DefaultConfiguration return new ConsoleAppender("DefaultConsole-" + COUNT.incrementAndGet(), layout, null, - getDefaultManager(DEFAULT_TARGET, false, layout), true, DEFAULT_TARGET); + getDefaultManager(DEFAULT_TARGET, false, false, layout), true, DEFAULT_TARGET); } @PluginBuilderFactory @@ -175,6 +184,9 @@ public final class ConsoleAppender extends AbstractOutputStreamAppender<OutputSt private boolean follow = false; @PluginBuilderAttribute + private boolean direct = false; + + @PluginBuilderAttribute private boolean ignoreExceptions = true; public Builder setLayout(final Layout<? extends Serializable> aLayout) { @@ -202,6 +214,11 @@ public final class ConsoleAppender extends AbstractOutputStreamAppender<OutputSt return this; } + public Builder setDirect(final boolean shouldDirect) { + this.direct = shouldDirect; + return this; + } + public Builder setIgnoreExceptions(final boolean shouldIgnoreExceptions) { this.ignoreExceptions = shouldIgnoreExceptions; return this; @@ -209,34 +226,39 @@ public final class ConsoleAppender extends AbstractOutputStreamAppender<OutputSt @Override public ConsoleAppender build() { - return new ConsoleAppender(name, layout, filter, getManager(target, follow, layout), ignoreExceptions, target); + if (follow && direct) { + throw new IllegalArgumentException("Cannot use both follow and direct on ConsoleAppender"); + } + return new ConsoleAppender(name, layout, filter, getManager(target, follow, direct, layout), ignoreExceptions, target); } } - private static OutputStreamManager getDefaultManager(final Target target, final boolean follow, + private static OutputStreamManager getDefaultManager(final Target target, final boolean follow, final boolean direct, final Layout<? extends Serializable> layout) { - final OutputStream os = getOutputStream(follow, target); + final OutputStream os = getOutputStream(follow, direct, target); // LOG4J2-1176 DefaultConfiguration should not share OutputStreamManager instances to avoid memory leaks. - final String managerName = target.name() + '.' + follow + "-" + COUNT.get(); + final String managerName = target.name() + '.' + follow + '.' + direct + "-" + COUNT.get(); return OutputStreamManager.getManager(managerName, new FactoryData(os, managerName, layout), factory); } - private static OutputStreamManager getManager(final Target target, final boolean follow, + private static OutputStreamManager getManager(final Target target, final boolean follow, final boolean direct, final Layout<? extends Serializable> layout) { - final OutputStream os = getOutputStream(follow, target); - final String managerName = target.name() + '.' + follow; + final OutputStream os = getOutputStream(follow, direct, target); + final String managerName = target.name() + '.' + follow + '.' + direct; return OutputStreamManager.getManager(managerName, new FactoryData(os, managerName, layout), factory); } - private static OutputStream getOutputStream(final boolean follow, final Target target) { + private static OutputStream getOutputStream(final boolean follow, final boolean direct, final Target target) { final String enc = Charset.defaultCharset().name(); - OutputStream outputStream = null; + OutputStream outputStream; try { // @formatter:off outputStream = target == Target.SYSTEM_OUT ? - follow ? new PrintStream(new SystemOutStream(), true, enc) : System.out : - follow ? new PrintStream(new SystemErrStream(), true, enc) : System.err; + direct ? new FileOutputStream(FileDescriptor.out) : + (follow ? new PrintStream(new SystemOutStream(), true, enc) : System.out) : + direct ? new FileOutputStream(FileDescriptor.err) : + (follow ? new PrintStream(new SystemErrStream(), true, enc) : System.err); // @formatter:on outputStream = new CloseShieldOutputStream(outputStream); } catch (final UnsupportedEncodingException ex) { // should never happen http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/50d0bf16/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 deleted file mode 100644 index a7cd905..0000000 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/FastConsoleAppender.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * 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/50d0bf16/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java index 65b3e2e..78ca50e 100644 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java @@ -16,13 +16,6 @@ */ package org.apache.logging.log4j.core.appender; -import static org.easymock.EasyMock.anyInt; -import static org.easymock.EasyMock.anyObject; -import static org.easymock.EasyMock.expectLastCall; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - import java.io.ByteArrayOutputStream; import java.io.PrintStream; @@ -41,6 +34,11 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import static org.easymock.EasyMock.anyInt; +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.expectLastCall; +import static org.junit.Assert.*; + /** * @@ -100,7 +98,7 @@ public class ConsoleAppenderTest { mocks.replayAll(); systemSetter.systemSet(psMock); final Layout<String> layout = PatternLayout.createLayout(null, null, null, null, null, false, false, null, null); - final ConsoleAppender app = ConsoleAppender.createAppender(layout, null, targetName, "Console", false, + final ConsoleAppender app = ConsoleAppender.createAppender(layout, null, targetName, "Console", false, false, false); app.start(); assertTrue("Appender did not start", app.isStarted()); http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/50d0bf16/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 a4ea02e..6d5e8b2 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,14 +57,14 @@ public class Log4j2AppenderComparisonBenchmark { private Logger rafLogger; private Logger mmapLogger; private Logger consoleLogger; - private Logger fastConsoleLogger; + private Logger directConsoleLogger; private Logger noopLogger; private Logger rewriteLogger; private Appender fileAppender; private Appender rafAppender; private Appender mmapAppender; private Appender consoleAppender; - private Appender fastConsoleAppender; + private Appender directConsoleAppender; private Appender noopAppender; private Appender rewriteAppender; @@ -104,7 +104,7 @@ public class Log4j2AppenderComparisonBenchmark { rafLogger = LogManager.getLogger("RAFLogger"); mmapLogger = LogManager.getLogger("MMapLogger"); consoleLogger = LogManager.getLogger("ConsoleLogger"); - fastConsoleLogger = LogManager.getLogger("FastConsoleLogger"); + directConsoleLogger = LogManager.getLogger("DirectConsoleLogger"); noopLogger = LogManager.getLogger("NoopLogger"); rewriteLogger = LogManager.getLogger("RewriteLogger"); @@ -112,7 +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"); + directConsoleAppender = ((org.apache.logging.log4j.core.Logger) directConsoleLogger).getAppenders().get("DirectConsole"); noopAppender = ((org.apache.logging.log4j.core.Logger) noopLogger).getAppenders().get("NoOp"); rewriteAppender = ((org.apache.logging.log4j.core.Logger) rewriteLogger).getAppenders().get("Rewrite"); } @@ -226,14 +226,14 @@ public class Log4j2AppenderComparisonBenchmark { @BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.SECONDS) @Benchmark - public void end2endFastConsole() { - fastConsoleLogger.debug(MESSAGE); + public void end2endDirectConsole() { + directConsoleLogger.debug(MESSAGE); } @BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.SECONDS) @Benchmark - public void appenderFastConsole() { - fastConsoleAppender.append(EVENT); + public void appenderDirectConsole() { + directConsoleAppender.append(EVENT); } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/50d0bf16/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 8ad6327..70ce369 100644 --- a/log4j-perf/src/main/resources/log4j2-appenderComparison.xml +++ b/log4j-perf/src/main/resources/log4j2-appenderComparison.xml @@ -21,9 +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"> + <Console name="DirectConsole" target="SYSTEM_OUT" direct="true"> <PatternLayout pattern="%d %p [%t] %c{1} %X{transactionId} - %m%n"/> - </FastConsole> + </Console> <File name="File" fileName="target/testlog4j2.log" immediateFlush="false"> <PatternLayout pattern="%d %p [%t] %c{1} %X{transactionId} - %m%n"/> </File> @@ -58,8 +58,8 @@ <Logger name="ConsoleLogger" level="debug" additivity="false"> <AppenderRef ref="Console"/> </Logger> - <Logger name="FastConsoleLogger" level="debug" additivity="false"> - <AppenderRef ref="FastConsole"/> + <Logger name="DirectConsoleLogger" level="debug" additivity="false"> + <AppenderRef ref="DirectConsole"/> </Logger> <Logger name="NoopLogger" level="debug" additivity="false"> <AppenderRef ref="NoOp"/>