Log4j2 how to redirect ERROR log events on stderr
When containerizing an application, a common need is to redirect the logs to standard outputs. Most of the time you put everything on stdout but it is actually quite doable to put errors on stderr and other logs only on stdout. Except the fact it respects the aim of these outputs, it also enables to filter more easily the output when working with microservices, to monitor only important events when you rely on a ton of services and also to use different priorities for each of the outputs (errors being high priority). You can see it as getting two messaging queues instead of one.
The trick to do that with Log4j2 is to start by creating two console appenders (one for stdout and one for stderr) and then to filter log events going to each of the appender through a filter based on the level (a.k.a. ThresholdFilter). Once done, you just register both appenders as root logger (or for specific loggers id desired).
Here is a sample log4j2.xml configuration doing that, ready to put in your docker container:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Properties>
<Property name="pattern">[%d{yyyy-MM-dd HH:mm:ss.SSS}][%highlight{%-5level}][%t][%logger] %msg%n</Property>
</Properties>
<Appenders>
<Console name="stdout" target="SYSTEM_OUT"> <!-- 1 -->
<PatternLayout pattern="${pattern}"/>
<ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="ACCEPT"/> <!-- 3 -->
</Console>
<Console name="stderr" target="SYSTEM_ERR"> <!-- 2 -->
<PatternLayout pattern="${pattern}"/>
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> <!-- 3 -->
</Console>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="stdout"/> <!-- 4 -->
<AppenderRef ref="stderr"/> <!-- 4 -->
</Root>
</Loggers>
</Configuration>
- The stdout appender which will take all messages < ERROR level,
- The stderr appender which will take all messages at ERROR level,
- The filters enabling to activate the distribution of the message depending the error level to the right appender. Note that both filters are reversed, enabling to keep all messages in the overall system (stdout filter + stderr filter = all messages),
- Both appender are registered on the root logger to ensure we don't miss any message.
With this simple trick, the process will dispatch error messages on stderr and other messages on stdout and docker logging driver will poll messages properly on both outputs giving you even more power in your monitoring infrastructure :).
From the same author:
In the same category: