2
votes

I'm trying to set up log4j2 to log all the messages to rolling files using async loggers.

In addition, I am using custom appender that I've added which enables me to capture all messages to a buffer. This appender is used for debug purposes. It starts collecting messages when a special debug request reaches the server, it captures all the messages, it is then instructed to stop collecting messages and the captured messages are returned as a response.

This custom appender obviously cannot be added to an async logger since then I will not be able to return the debug messages in the response (since the messages will be sent to the appender on a different thread).

The question is how to configure log4j to run only this custom appender in sync and the rest in async mode.

I cat set the root logger to async and add references to all the file loggers and add another sync logger for the custom appender, but then the sync logger requires a name and will only log messages that come from loggers that inherit that name. That's not good enough since I want to capture all messages in the system.

I can also create a sync logger and use async appenders but then I lose the ability to use the disruptor library for async logging which looks promising.

Is there a way to create another logger that will capture all events? Any other ideas?

Here's my log4j2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration packages="lqm.common.utils">
  <Appenders>
    <Console name="STDOUT" target="SYSTEM_OUT">
      <PatternLayout pattern="%d [%t] %-5p %c - %m%n"/>
    </Console>
     <RollingFile name="async_E" fileName="/var/log/ep/error.log" filePattern="/var/log/ep/error.log.%d{yyyy-MM-dd-HH}">
      <PatternLayout pattern="%d [%t] %-5p %c [%X{username}] - %m%n"/>
      <Policies>
        <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
      </Policies>
    </RollingFile>
    <RollingFile name="async_P" fileName="/var/log/ep/ep-async.log" filePattern="/var/log/ep/ep-async.log.%d{yyyy-MM-dd-HH}">
      <PatternLayout pattern="%d [%t] %-5p %c [%X{username}] - %m%n"/>
      <Policies>
        <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
      </Policies>
    </RollingFile> 
    <StringAppender name="imMem">
      <PatternLayout pattern="%d [%t] %-5p %c [%X{username}] - %m%n"/>
    </StringAppender>
  </Appenders>
  <Loggers>
    <Logger name="lqm" level="trace">
        <AppenderRef ref="imMem" />
    </Logger>
   <asyncRoot level="info">
      <AppenderRef ref="STDOUT"/>
      <AppenderRef ref="async_E" level="warn"/>
      <AppenderRef ref="async_P" />
    </asyncRoot>
  </Loggers>
 </Configuration>
1
Can you paste the log4j.xml you have till now?Andy Dufresne

1 Answers

1
votes

I think you already have most of it worked out. The way I see it you have three options:

  1. Create a sync root, and make all appenders except the in-memory appender asynchronous.
  2. Use the config you have now, with an async root and a single named sync logger. Additivity means that the named logger will receive all events. This option assumes that all components are in the "lqm" namespace.
  3. The last option that I see is to make all loggers async, and change the receiver of the in-memory captured log message in such a way that it can handle asynchronous callbacks. The way your question is phrased it seems like you have already rejected this option, but you don't say why. However, this option may need significant redesign and is probably the most complex. Also, if the number of log events is small enough that you are able to store them all in memory, then the performance of async appenders (option 1) is probably sufficient...