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 >> >
