public final class ActiveAsynchronousAppender extends AppenderSkeleton implements Appender, AppenderAttachable, OptionHandler
LoggingEvent
s asynchronously. It acts solely as
an event dispatcher, and must therefore be attached to one or more child
appenders in order to do useful work.
The appender buffers events into the tail of a queue (on an application thread). The appender's dispatch thread takes events from the head of the queue, and dispatches them to all the appenders that are attached to this appender.
It is the user's responsibility to close appenders, typically at the end of the application lifecycle. If this is done, instances of this appender make best efforts to dispatch all buffered events. Upon a dirty shutdown (e.g. Ctrl+C, no shutdown hooks) then no guarantees can be made.
This appender has an optional dependency upon the SourceForge backport-util-concurrent concurrency JAR. To use backport-util-concurrent, ensure the JAR is in your application's CLASSPATH, and set UseConcurrentBackport to true.
The appender's event buffer is configured with the BufferSize parameter (default 32). If the buffer is full, then application threads are blocked from appending new events until the dispatch thread has had a chance to dispatch one or more events. When the buffer is no longer full, application threads are notified, and are able to start appending events once more.
Optimally tuning the size of the appender's event buffer for maximum application throughput depends upon several factors. Any or all of the following factors are likely to affect throughput:
LoggingEventQueue
When using Java 5 or above there is the option to use the non-blocking CAS
implementation of the LoggingEventQueue
, configured by setting
UseCAS parameter to true. This implementation offers the
highest throughput of the various provided implementations of
LoggingEventQueue
though there is a cost in terms of higher CPU
usage; it is recommended to use this where high throughput is a hard
requirement and the application is doing a relatively large amount of
logging. NB This cannot be used in conjunction with the
UseConcurrentBackport parameter.
It is possible to attach separate instances of this appender to one another to achieve multi-threaded dispatch. For example, assume a requirement for two child appenders that each perform relatively expensive operations such as messaging and file IO. For this case, one could set up a graph of appenders such that the parent asynchronous appender, A, has two child asynchronous appenders attached, B and C. Let's say B in turn has a child file IO appender attached, and C has a child messaging appender attached. This will result in fast dispatch from A to both B and C via A's dispatch thread. B's dispatch thread will be dedicated to logging to file IO, and C's dispatch thread will be dedicated to logging via messaging.
RuntimeException
s are caught by the dispatch thread. For this case
the appender can be configured either to continue dispatching events
asynchronously, or to fail back to synchronous logging. By default the
appender fails back to synchronous logging, since this is the default
behaviour of the standard Log4J AsyncAppender
. To configure the
appender to continue asynchronous dispatch, set the FailToSync flag
to false.
A restriction of this appender is that attached appenders must be named. A
call to addAppender(Appender)
wherein the parameter is not a named
appender will result in a failure to attach.
AsyncAppender
closed, errorHandler, headFilter, layout, name, tailFilter, threshold
Constructor and Description |
---|
ActiveAsynchronousAppender() |
Modifier and Type | Method and Description |
---|---|
void |
activateOptions() |
void |
addAppender(Appender newAppender) |
protected void |
append(LoggingEvent event)
Forwards
LoggingEvent s to the dispatcher, which in turn delegates
append operations to the attached appenders. |
void |
close()
Closes all attached appenders.
|
(package private) boolean |
compareAndSetClosed(boolean expect,
boolean update) |
void |
doAppend(LoggingEvent event)
Minimally-synchronized override of
AppenderSkeleton.doAppend(LoggingEvent) . |
Enumeration |
getAllAppenders() |
Appender |
getAppender(String name) |
int |
getBufferSize()
Gets the current buffer size.
|
boolean |
getFailToSync() |
boolean |
getLocationInfo() |
boolean |
getUseCAS() |
boolean |
getUseConcurrentBackport() |
boolean |
isAttached(Appender appender) |
(package private) boolean |
isClosed() |
void |
removeAllAppenders() |
void |
removeAppender(Appender appender) |
void |
removeAppender(String name) |
boolean |
requiresLayout() |
void |
setBufferSize(int size) |
void |
setFailToSync(boolean flag) |
void |
setLocationInfo(boolean flag) |
void |
setName(String name) |
void |
setUseCAS(boolean flag) |
void |
setUseConcurrentBackport(boolean flag) |
addFilter, clearFilters, finalize, getErrorHandler, getFilter, getFirstFilter, getLayout, getName, getThreshold, isAsSevereAsThreshold, setErrorHandler, setLayout, setThreshold
clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
addFilter, clearFilters, getErrorHandler, getFilter, getLayout, getName, setErrorHandler, setLayout
public final void activateOptions()
activateOptions
in interface OptionHandler
activateOptions
in class AppenderSkeleton
AppenderSkeleton.activateOptions()
public final void addAppender(Appender newAppender)
addAppender
in interface AppenderAttachable
AppenderAttachable.addAppender(org.apache.log4j.Appender)
public final void close()
close
in interface Appender
Appender.close()
public final void doAppend(LoggingEvent event)
AppenderSkeleton.doAppend(LoggingEvent)
.doAppend
in interface Appender
doAppend
in class AppenderSkeleton
AppenderSkeleton.doAppend(org.apache.log4j.spi.LoggingEvent)
public final Enumeration getAllAppenders()
getAllAppenders
in interface AppenderAttachable
AppenderAttachable.getAllAppenders()
public final Appender getAppender(String name)
getAppender
in interface AppenderAttachable
AppenderAttachable.getAppender(java.lang.String)
public final int getBufferSize()
public final boolean getFailToSync()
public final boolean getUseConcurrentBackport()
public final boolean getUseCAS()
public final boolean getLocationInfo()
AsyncAppender.getLocationInfo()
public final boolean isAttached(Appender appender)
isAttached
in interface AppenderAttachable
AppenderAttachable.isAttached(org.apache.log4j.Appender)
public final void removeAllAppenders()
removeAllAppenders
in interface AppenderAttachable
AppenderAttachable.removeAllAppenders()
public final void removeAppender(Appender appender)
removeAppender
in interface AppenderAttachable
AppenderAttachable.removeAppender(org.apache.log4j.Appender)
public final void removeAppender(String name)
removeAppender
in interface AppenderAttachable
AppenderAttachable.removeAppender(java.lang.String)
public final boolean requiresLayout()
requiresLayout
in interface Appender
Appender.requiresLayout()
public final void setBufferSize(int size)
size
- buffer size, must be positive.AsyncAppender.setBufferSize(int)
public final void setFailToSync(boolean flag)
flag
- true if the asynchronous appender should fail-over to synchronous
logging in the event that an attempt to append a LoggingEvent
fails due to a RuntimeException
.public final void setName(String name)
setName
in interface Appender
setName
in class AppenderSkeleton
public final void setLocationInfo(boolean flag)
flag
- true if location information should be extracted.AsyncAppender.setLocationInfo(boolean)
public final void setUseConcurrentBackport(boolean flag)
public final void setUseCAS(boolean flag)
final boolean isClosed()
final boolean compareAndSetClosed(boolean expect, boolean update)
expect
- The expected value.update
- The replacement value.protected final void append(LoggingEvent event)
LoggingEvent
s to the dispatcher, which in turn delegates
append operations to the attached appenders.append
in class AppenderSkeleton
AppenderSkeleton.append(org.apache.log4j.spi.LoggingEvent)