Also, note that each event has to be individually filtered so processing a 
batch probably won’t work properly.

Ralph

> On Jan 9, 2018, at 8:04 AM, Ralph Goers <[email protected]> wrote:
> 
> 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] 
>> <mailto:[email protected]>> wrote:
>> 
>> On 2018-01-09 14:46, Apache <[email protected] 
>> <mailto:[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