Class AsyncLogger

All Implemented Interfaces:
com.lmax.disruptor.EventTranslatorVararg<RingBufferLogEvent>, Serializable, Logger, ExtendedLogger, LocationAwareLogger, Supplier<LoggerConfig>

public class AsyncLogger extends Logger implements com.lmax.disruptor.EventTranslatorVararg<RingBufferLogEvent>
AsyncLogger is a logger designed for high throughput and low latency logging. It does not perform any I/O in the calling (application) thread, but instead hands off the work to another thread as soon as possible. The actual logging is performed in the background thread. It uses LMAX Disruptor for inter-thread communication.

To use AsyncLogger, specify the System property -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector before you obtain a Logger, and all Loggers returned by LogManager.getLogger will be AsyncLoggers.

Note that for performance reasons, this logger does not include source location by default. You need to specify includeLocation="true" in the configuration or any %class, %location or %line conversion patterns in your log4j.xml configuration will produce either a "?" character or no output at all.

For best performance, use AsyncLogger with the RandomAccessFileAppender or RollingRandomAccessFileAppender, with immediateFlush=false. These appenders have built-in support for the batching mechanism used by the Disruptor library, and they will flush to disk at the end of each batch. This means that even with immediateFlush=false, there will never be any items left in the buffer; all log events will all be written to disk in a very efficient manner.

See Also:
  • Field Details

  • Constructor Details

    • AsyncLogger

      public AsyncLogger(LoggerContext context, String name, MessageFactory messageFactory, AsyncLoggerDisruptor loggerDisruptor)
      Constructs an AsyncLogger with the specified context, name and message factory.
      Parameters:
      context - context of this logger
      name - name of this logger
      messageFactory - message factory of this logger
      loggerDisruptor - helper class that logging can be delegated to. This object owns the Disruptor.
  • Method Details

    • updateConfiguration

      protected void updateConfiguration(Configuration newConfig)
      Description copied from class: Logger
      Associates this Logger with a new Configuration. This method is not exposed through the public API.

      There are two ways this could be used to guarantee all threads are aware of changes to config.

      1. Synchronize this method. Accessors don't need to be synchronized as Java will treat all variables within a synchronized block as volatile.
      2. Declare the variable volatile. Option 2 is used here as the performance cost is very low and it does a better job at documenting how it is used.
      Overrides:
      updateConfiguration in class Logger
      Parameters:
      newConfig - The new Configuration.
    • getNanoClock

      NanoClock getNanoClock()
    • getCachedTranslator

      private RingBufferLogEventTranslator getCachedTranslator()
    • logMessage

      public void logMessage(String fqcn, Level level, Marker marker, Message message, Throwable thrown)
      Description copied from interface: ExtendedLogger
      Logs a message at the specified level. It is the responsibility of the caller to ensure the specified level is enabled.
      Specified by:
      logMessage in interface ExtendedLogger
      Overrides:
      logMessage in class Logger
      Parameters:
      fqcn - The fully qualified class name of the logger entry point, used to determine the caller class and method when location information needs to be logged.
      level - The logging Level to check.
      marker - A Marker or null.
      message - The Message.
      thrown - the exception to log, including its stack trace.
    • log

      public void log(Level level, Marker marker, String fqcn, StackTraceElement location, Message message, Throwable throwable)
      Overrides:
      log in class Logger
    • getTranslatorType

      private AsyncLogger.TranslatorType getTranslatorType()
    • isReused

      private boolean isReused(Message message)
    • logWithThreadLocalTranslator

      private void logWithThreadLocalTranslator(String fqcn, Level level, Marker marker, Message message, Throwable thrown)
      Enqueues the specified log event data for logging in a background thread.

      This re-uses a RingBufferLogEventTranslator instance cached in a ThreadLocal to avoid creating unnecessary objects with each event.

      Parameters:
      fqcn - fully qualified name of the caller
      level - level at which the caller wants to log the message
      marker - message marker
      message - the log message
      thrown - a Throwable or null
    • logWithThreadLocalTranslator

      private void logWithThreadLocalTranslator(String fqcn, StackTraceElement location, Level level, Marker marker, Message message, Throwable thrown)
      Enqueues the specified log event data for logging in a background thread.

      This re-uses a RingBufferLogEventTranslator instance cached in a ThreadLocal to avoid creating unnecessary objects with each event.

      Parameters:
      fqcn - fully qualified name of the caller
      location - the Location of the caller.
      level - level at which the caller wants to log the message
      marker - message marker
      message - the log message
      thrown - a Throwable or null
    • publish

      private void publish(RingBufferLogEventTranslator translator)
    • handleRingBufferFull

      private void handleRingBufferFull(RingBufferLogEventTranslator translator)
    • initTranslator

      private void initTranslator(RingBufferLogEventTranslator translator, String fqcn, StackTraceElement location, Level level, Marker marker, Message message, Throwable thrown)
    • initTranslator

      private void initTranslator(RingBufferLogEventTranslator translator, String fqcn, Level level, Marker marker, Message message, Throwable thrown)
    • initTranslatorThreadValues

      private void initTranslatorThreadValues(RingBufferLogEventTranslator translator)
    • calcLocationIfRequested

      private StackTraceElement calcLocationIfRequested(String fqcn)
      Returns the caller location if requested, null otherwise.
      Parameters:
      fqcn - fully qualified caller name.
      Returns:
      the caller location if requested, null otherwise.
    • logWithVarargTranslator

      private void logWithVarargTranslator(String fqcn, Level level, Marker marker, Message message, Throwable thrown)
      Enqueues the specified log event data for logging in a background thread.

      This creates a new varargs Object array for each invocation, but does not store any non-JDK classes in a ThreadLocal to avoid memory leaks in web applications (see LOG4J2-1172).

      Parameters:
      fqcn - fully qualified name of the caller
      level - level at which the caller wants to log the message
      marker - message marker
      message - the log message
      thrown - a Throwable or null
    • logWithVarargTranslator

      private void logWithVarargTranslator(String fqcn, StackTraceElement location, Level level, Marker marker, Message message, Throwable thrown)
      Enqueues the specified log event data for logging in a background thread.

      This creates a new varargs Object array for each invocation, but does not store any non-JDK classes in a ThreadLocal to avoid memory leaks in web applications (see LOG4J2-1172).

      Parameters:
      fqcn - fully qualified name of the caller
      location - location of the caller.
      level - level at which the caller wants to log the message
      marker - message marker
      message - the log message
      thrown - a Throwable or null
    • translateTo

      public void translateTo(RingBufferLogEvent event, long sequence, Object... args)
      Specified by:
      translateTo in interface com.lmax.disruptor.EventTranslatorVararg<RingBufferLogEvent>
    • logMessageInCurrentThread

      void logMessageInCurrentThread(String fqcn, Level level, Marker marker, Message message, Throwable thrown)
      LOG4J2-471: prevent deadlock when RingBuffer is full and object being logged calls Logger.log() from its toString() method
      Parameters:
      fqcn - fully qualified caller name
      level - log level
      marker - optional marker
      message - log message
      thrown - optional exception
    • handleRingBufferFull

      private void handleRingBufferFull(StackTraceElement location, String fqcn, Level level, Marker marker, Message msg, Throwable thrown)
    • actualAsyncLog

      public void actualAsyncLog(RingBufferLogEvent event)
      This method is called by the EventHandler that processes the RingBufferLogEvent in a separate thread. Merges the contents of the configuration map into the contextData, after replacing any variables in the property values with the StrSubstitutor-supplied actual values.
      Parameters:
      event - the event to log
    • onPropertiesPresent

      private void onPropertiesPresent(RingBufferLogEvent event, List<Property> properties)
    • getContextData

      private static StringMap getContextData(RingBufferLogEvent event)
    • getAsyncLoggerDisruptor

      AsyncLoggerDisruptor getAsyncLoggerDisruptor()