The actual code in the AsyncAppender does:

public void append(final LogEvent logEvent) {
    if (!isStarted()) {
        throw new IllegalStateException("AsyncAppender " + getName() + " is not 
active");
    }
    final Log4jLogEvent memento = Log4jLogEvent.createMemento(logEvent, 
includeLocation);
    InternalAsyncUtil.makeMessageImmutable(logEvent.getMessage());
    if (!transfer(memento)) {
        if (blocking) {
            if (AbstractLogger.getRecursionDepth() > 1) { // LOG4J2-1518, 
LOG4J2-2031
                // If queue is full AND we are in a recursive call, call 
appender directly to prevent deadlock
                final Message message = 
AsyncQueueFullMessageUtil.transform(logEvent.getMessage());
                logMessageInCurrentThread(new 
Log4jLogEvent.Builder(logEvent).setMessage(message).build());
            } else {
                // delegate to the event router (which may discard, enqueue and 
block, or log in current thread)
                final EventRoute route = 
asyncQueueFullPolicy.getRoute(thread.getId(), memento.getLevel());
                route.logMessage(this, memento);
            }
        } else {
            error("Appender " + getName() + " is unable to write primary 
appenders. queue is full");
            logToErrorAppenderIfNecessary(false, memento);
        }
    }
}
And then the run method for the thread does:
while (!queue.isEmpty()) {
    try {
        final LogEvent event = queue.take();
        if (event instanceof Log4jLogEvent) {
            final Log4jLogEvent logEvent = (Log4jLogEvent) event;
            logEvent.setEndOfBatch(queue.isEmpty());
            callAppenders(logEvent);
            count++;
        } else {
            ignored++;
            LOGGER.trace("Ignoring event of class {}", 
event.getClass().getName());
        }
    } catch (final InterruptedException ex) {
        // May have been interrupted to shut down.
        // Here we ignore interrupts and try to process all remaining events.
    }
}
As you can see it doesn’t handle batches.

Ralph




> On Jan 9, 2018, at 7:27 AM, Jochen Wiedmann <[email protected]> wrote:
> 
> On 2018-01-09 14:46, Apache <[email protected]> wrote:
>> The Logging api only allows you to log a single event at a time so it 
>> doesn?019t make sense for an appender to have a method that accepts multiple 
>> events since it can?019t happen. That said, appenders can queue the events 
>> and send them downstream in batches. I believe some of the appenders do that 
>> now.
> 
>> 
>> Is there some use case I am not aware of where this method could be called?
> 
> As I wrote, the use case would be performance, assuming that the
> Appender can process a bunch of messages just as quickly as a single
> message. (Think of the JMSAppender using a BatchMessage, rather than a
> TextMessage, or ObjectMessage.)
> 
> My trivial guess would be, that the AsyncAppender somewhere has code
> like the following:
> 
>  private void pushToSyncAppender(LogEvent[] events) {
>    final Appender appender = this.syncAppender;
>    for (LogEvent ev : events) {
>      appender.append(ev);
>    }
>  }
> 
> which could be changed to
> 
>  private void pushToSyncAppender(LogEvent[] events) {
>    final Appender appender = this.syncAppender;
>    if (appender instanceof BatchableAppender) {
>      ((BatchableAppender) appender).append(events);
>    } else {
>      for (LogEvent ev : events) {
>        appender.append(ev);
>      }
>    }
>  }
> 
> I have to admit, though, that I don't detect right now, where the
> AsyncAppender is actually pushing to the synchronous appender.
> 
> Jochen
> 

Reply via email to