Repository: logging-log4j2 Updated Branches: refs/heads/master 9be7f31d9 -> d0b97aa94
LOG4J2-1221 Added async logger Timeout wait strategy and made this the default. Prevents deadlock that may occur on Solaris. Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/f9a4b707 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/f9a4b707 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/f9a4b707 Branch: refs/heads/master Commit: f9a4b7078b04e6bfadc26ccc31ed05ae0c0acb12 Parents: 9be7f31 Author: rpopma <[email protected]> Authored: Wed Jan 13 23:58:49 2016 +0900 Committer: rpopma <[email protected]> Committed: Wed Jan 13 23:58:49 2016 +0900 ---------------------------------------------------------------------- .../logging/log4j/core/async/DisruptorUtil.java | 27 +++++++++++++------- src/changes/changes.xml | 4 +++ src/site/xdoc/manual/async.xml | 16 +++++++++--- 3 files changed, 34 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f9a4b707/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java index 917710f..a610b95 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java @@ -20,18 +20,14 @@ package org.apache.logging.log4j.core.async; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import com.lmax.disruptor.*; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.util.Integers; import org.apache.logging.log4j.status.StatusLogger; import org.apache.logging.log4j.util.PropertiesUtil; -import com.lmax.disruptor.BlockingWaitStrategy; -import com.lmax.disruptor.ExceptionHandler; -import com.lmax.disruptor.SleepingWaitStrategy; -import com.lmax.disruptor.WaitStrategy; -import com.lmax.disruptor.YieldingWaitStrategy; - /** * Utility methods for getting Disruptor related configuration. */ @@ -43,7 +39,19 @@ final class DisruptorUtil { private DisruptorUtil() { } + static long getTimeout(final String propertyName, final long defaultTimeout) { + return PropertiesUtil.getProperties().getLongProperty(propertyName, defaultTimeout); + } + static WaitStrategy createWaitStrategy(final String propertyName) { + final String key = propertyName.startsWith("AsyncLogger.") + ? "AsyncLogger.Timeout" + : "AsyncLoggerConfig.Timeout"; + final long timeout = DisruptorUtil.getTimeout(key, 10L); + return createWaitStrategy(propertyName, timeout); + } + + static WaitStrategy createWaitStrategy(final String propertyName, final long timeoutMs) { final String strategy = PropertiesUtil.getProperties().getStringProperty(propertyName); if (strategy != null) { LOGGER.trace("property {}={}", propertyName, strategy); @@ -53,9 +61,11 @@ final class DisruptorUtil { return new YieldingWaitStrategy(); } else if ("Block".equalsIgnoreCase(strategy)) { return new BlockingWaitStrategy(); + } else if ("Timeout".equalsIgnoreCase(strategy)) { + return new TimeoutBlockingWaitStrategy(timeoutMs, TimeUnit.MILLISECONDS); } } - return new BlockingWaitStrategy(); + return new TimeoutBlockingWaitStrategy(timeoutMs, TimeUnit.MILLISECONDS); } static int calculateRingBufferSize(final String propertyName) { @@ -95,7 +105,7 @@ final class DisruptorUtil { /** * Returns the thread ID of the background appender thread. This allows us to detect Logger.log() calls initiated * from the appender thread, which may cause deadlock when the RingBuffer is full. (LOG4J2-471) - * + * * @param executor runs the appender thread * @return the thread ID of the background appender thread */ @@ -114,5 +124,4 @@ final class DisruptorUtil { throw new IllegalStateException(msg, ex); } } - } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f9a4b707/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index bf4d0d9..3bf73f7 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -24,6 +24,10 @@ </properties> <body> <release version="2.5.1" date="201Y-MM-DD" description="GA Release 2.5.1"> + <action issue="LOG4J2-1221" dev="rpopma" type="add" due-to="Michael Barker"> + Added async logger Timeout wait strategy and made this the default wait strategy for async loggers. + This prevents a rare deadlock that may occur on Solaris. + </action> <action issue="LOG4J2-1080" dev="rpopma" type="add"> Added option to discard events below a certain log level if the async logger ring buffer or async appender queue remaining capacity falls below a certain ratio. http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f9a4b707/src/site/xdoc/manual/async.xml ---------------------------------------------------------------------- diff --git a/src/site/xdoc/manual/async.xml b/src/site/xdoc/manual/async.xml index 0f6a754..911c27a 100644 --- a/src/site/xdoc/manual/async.xml +++ b/src/site/xdoc/manual/async.xml @@ -207,15 +207,19 @@ <tr> <td>AsyncLogger.WaitStrategy</td> <td> - <tt>Block</tt> + <tt>Timeout</tt> </td> <td> - Valid values: Block, Sleep, Yield. + Valid values: Block, Timeout, Sleep, Yield. <br /> <tt>Block</tt> is a strategy that uses a lock and condition variable for the I/O thread waiting for log events. Block can be used when throughput and low-latency are not as important as CPU resource. Recommended for resource constrained/virtualised environments. <br /> + <tt>Timeout</tt> is a variation of the <tt>Block</tt> strategy that will periodically + wake up from the lock condition await() call. This ensures that if a notification is missed somehow + the consumer thread is not stuck but will recover with a small latency delay (default 10ms). + <br /> <tt>Sleep</tt> is a strategy that initially spins, then uses a Thread.yield(), and eventually parks for the minimum number of nanos the OS and JVM will allow while the I/O thread is waiting for log events. Sleep is a good compromise between performance @@ -364,15 +368,19 @@ <tr> <td>AsyncLoggerConfig.WaitStrategy</td> <td> - <tt>Block</tt> + <tt>Timeout</tt> </td> <td> - Valid values: Block, Sleep, Yield. + Valid values: Block, Timeout, Sleep, Yield. <br /> <tt>Block</tt> is a strategy that uses a lock and condition variable for the I/O thread waiting for log events. Block can be used when throughput and low-latency are not as important as CPU resource. Recommended for resource constrained/virtualised environments. <br /> + <tt>Timeout</tt> is a variation of the <tt>Block</tt> strategy that will periodically + wake up from the lock condition await() call. This ensures that if a notification is missed somehow + the consumer thread is not stuck but will recover with a small latency delay (default 10ms). + <br /> <tt>Sleep</tt> is a strategy that initially spins, then uses a Thread.yield(), and eventually parks for the minimum number of nanos the OS and JVM will allow while the I/O thread is waiting for log events. Sleep is a good compromise between performance
