A asyncRoot
configuration corresponding mating disruptor class is AsyncLoggerConfigDisruptor
with Log4jContextSelector
the configuration globally asynchronous boot parameters corresponding mating disruptor class is AsyncLoggerDisruptor
. The following analysis isAsyncLoggerConfigDisruptor
disruptor components needed to create and start implementation
AsyncLoggerConfigDisruptor.start
The method used to create and start the disruptor
instance
created disruptor needs EventFactory
, ringBuffer的大小
, ThreadFactory
, ProducerType
, 等待策略waitStrategy
after you create needs to be set ExceptionHandler
, set EventHandler
.
Posted translator (production) event.
EventFactory
Whether sub-variable ( mutable
field) corresponding to two different scenarios EventFactory.
Immutable factory logic is:
@Override
public Log4jEventWrapper newInstance() {
return new Log4jEventWrapper();
}
Variable factory logic:
public Log4jEventWrapper newInstance() {
return new Log4jEventWrapper(new MutableLogEvent());
}
We will be in Log4jEventWrapper
the constructor passed MutableLogEvent
instance.
ringBuffer size
Is a AsyncLoggerConfig.RingBufferSize
calculated configuration values.
This value is not less than the minimum configuration item 128 , the default value is set two conditions: if the ENABLE_THREADLOCALS enabled (optimization of a configuration item GC), the default value 4 * 1024
, otherwise it is 256 * 1024
.
This configuration is designated by the System properties, there are also different versions of the name of the case are inconsistent configuration, log4j2.asyncLoggerRingBufferSize (AsyncLogger.RingBufferSize). Details can be found here
ThreadFactory
The main thread is custom name:
thread name format is: "AsyncLoggerConfig-" + FACTORY_NUMBER (increment) + "-" + threadFactoryName + "-" + THREAD_NUMBER ( increment)
Default practical example is: Log4j2-TF-1-AsyncLoggerConfig - 1, with some differences above, the above analysis wrong? ?
ProducerType
Multi-producer
Holding policy waitStrategy
The default is 10ms of TimeoutBlockingWaitStrategy. Support configurable SleepingWaitStrategy
, YieldingWaitStrategy
, BlockingWaitStrategy
, BusySpinWaitStrategy
, TimeoutBlockingWaitStrategy
.
This configuration is designated by the System properties, there are also different versions, inconsistent configuration item name case, log4j2.asyncLoggerWaitStrategy (AsyncLogger.WaitStrategy).
ExceptionHandler
You can configure, configuration item name is AsyncLoggerConfig.ExceptionHandler, the default is to use AsyncLoggerConfigDefaultExceptionHandler, print: AsyncLogger error handling event seq = ..., value = ..., and played an exception stack.
EventHandler
As used herein, the Log4jEventWrapperHandler RingBufferLogEventHandler, is disruptor of SequenceReportingEventHandler achieved.
/**
* EventHandler performs the work in a separate thread.
*/
private static class Log4jEventWrapperHandler implements SequenceReportingEventHandler<Log4jEventWrapper> {
private static final int NOTIFY_PROGRESS_THRESHOLD = 50;
private Sequence sequenceCallback;
private int counter;
@Override
public void setSequenceCallback(final Sequence sequenceCallback) {
this.sequenceCallback = sequenceCallback;
}
@Override
public void onEvent(final Log4jEventWrapper event, final long sequence, final boolean endOfBatch)
throws Exception {
event.event.setEndOfBatch(endOfBatch);
event.loggerConfig.asyncCallAppenders(event.event);
event.clear();
notifyIntermediateProgress(sequence);
}
/**
* Notify the BatchEventProcessor that the sequence has progressed. Without this callback the sequence would not
* be progressed until the batch has completely finished.
*/
private void notifyIntermediateProgress(final long sequence) {
if (++counter > NOTIFY_PROGRESS_THRESHOLD) {
sequenceCallback.set(sequence);
counter = 0;
}
}
}
event.loggerConfig.asyncCallAppenders (event.event); this will trigger output log
translator
With EventFactory
the same points mutable
is variable or two cases.
Immutable:
private static final EventTranslatorTwoArg<Log4jEventWrapper, LogEvent, AsyncLoggerConfig> TRANSLATOR =
new EventTranslatorTwoArg<Log4jEventWrapper, LogEvent, AsyncLoggerConfig>() {
@Override
public void translateTo(final Log4jEventWrapper ringBufferElement, final long sequence,
final LogEvent logEvent, final AsyncLoggerConfig loggerConfig) {
ringBufferElement.event = logEvent;
ringBufferElement.loggerConfig = loggerConfig;
}
};
variable:
/**
* Object responsible for passing on data to a RingBuffer event with a MutableLogEvent.
*/
private static final EventTranslatorTwoArg<Log4jEventWrapper, LogEvent, AsyncLoggerConfig> MUTABLE_TRANSLATOR =
new EventTranslatorTwoArg<Log4jEventWrapper, LogEvent, AsyncLoggerConfig>() {
@Override
public void translateTo(final Log4jEventWrapper ringBufferElement, final long sequence,
final LogEvent logEvent, final AsyncLoggerConfig loggerConfig) {
((MutableLogEvent) ringBufferElement.event).initFrom(logEvent);
ringBufferElement.loggerConfig = loggerConfig;
}
};
It is done a thing to the event ringBufferElement element assignment or initialization.
TryEnqueue into the event queue of logical analysis
- prepareEvent
- ensureImmutable: LogEvent create a snapshot, passed in the original LogEvent will continue to be modified in the application thread, so here you want to create a snapshot
- Log4jLogEvent.makeMessageImmutable: formatted message. Because it is asynchronous log messages for the required format to format here, because otherwise it will change the object referenced values lead to inaccurate log
- tryPublishEvent
- Release event object to disruptor queue
The event processing queue
Look at the press call stack:
Daemon Thread [Log4j2-TF-1-AsyncLoggerConfig--1] (Suspended (breakpoint at line 37 in PatternFormatter))
PatternFormatter.format(LogEvent, StringBuilder) line: 37
PatternLayout$PatternSerializer.toSerializable(LogEvent, StringBuilder) line: 334
PatternLayout.toText(AbstractStringLayout$Serializer2, LogEvent, StringBuilder) line: 233
PatternLayout.encode(LogEvent, ByteBufferDestination) line: 218
PatternLayout.encode(Object, ByteBufferDestination) line: 58
ConsoleAppender(AbstractOutputStreamAppender<M>).directEncodeEvent(LogEvent) line: 177
ConsoleAppender(AbstractOutputStreamAppender<M>).tryAppend(LogEvent) line: 170
ConsoleAppender(AbstractOutputStreamAppender<M>).append(LogEvent) line: 161
AppenderControl.tryCallAppender(LogEvent) line: 156
AppenderControl.callAppender0(LogEvent) line: 129
AppenderControl.callAppenderPreventRecursion(LogEvent) line: 120
AppenderControl.callAppender(LogEvent) line: 84
AsyncLoggerConfig(LoggerConfig).callAppenders(LogEvent) line: 448
AsyncLoggerConfig.asyncCallAppenders(LogEvent) line: 129
AsyncLoggerConfigDisruptor$Log4jEventWrapperHandler.onEvent(AsyncLoggerConfigDisruptor$Log4jEventWrapper, long, boolean) line: 111
AsyncLoggerConfigDisruptor$Log4jEventWrapperHandler.onEvent(Object, long, boolean) line: 97
BatchEventProcessor<T>.run() line: 129
Log4jThread(Thread).run() line: 748
Log4jEventWrapperHandler.onEvent 111 lines are event.loggerConfig.asyncCallAppenders (event.event), see above EventHandler, where a real log write is completed.