使用log4j将错误日志记录到stderr,将调试信息和信息日志记录到stdout

63

我希望在我正在开发的应用程序中添加日志记录,使用Apache log4j。目前,我希望将所有级别为INFO及以下(TRACE,DEBUG)的日志消息重定向到标准输出(stdout),并将所有其他来自WARN及以上(ERROR,FATAL)的日志消息重定向到标准错误(stderr)。

...
logger.info("Processing at some point"); // must be written to stdout
logger.debug("Point x was processed"); // must be written to stdout
logger.warn("Incorrect point config"); // must be written only to stderr
logger.error("Exception occurred at point x"); // must be written only to stderr

那么我的log4j.properties文件应该是什么样的呢?目前它看起来是这样的:

log4j.rootLogger=DEBUG, stdout, stderr

# configure stdout
# set the conversion pattern of stdout
# Print the date in ISO 8601 format
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Threshold = DEBUG
log4j.appender.stdout.Target   = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %-5p %d [%t][%F:%L] : %m%n

# configure stderr
# set the conversion pattern of stdout
# Print the date in ISO 8601 format
log4j.appender.stderr = org.apache.log4j.ConsoleAppender
log4j.appender.stderr.Threshold = WARN
log4j.appender.stderr.Target   = System.err
log4j.appender.stderr.layout = org.apache.log4j.PatternLayout
log4j.appender.stderr.layout.ConversionPattern = %-5p %d [%t][%F:%L] : %m%n

上述配置的问题在于, logger.error() ... 的输出也会出现在标准输出(stdout)中。
6个回答

54
以下是以属性文件格式解决的方法。关键是正确定义过滤器。在此处查看Log4j属性信息
修改后的原始尝试,以过滤WARN和ERROR:
log4j.rootLogger=TRACE, stdout, stderr

# configure stdout
# set the conversion pattern of stdout
# Print the date in ISO 8601 format
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Threshold = TRACE
log4j.appender.stdout.Target   = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %-5p %d [%t][%F:%L] : %m%n
log4j.appender.stdout.filter.filter1=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.stdout.filter.filter1.levelMin=TRACE
log4j.appender.stdout.filter.filter1.levelMax=INFO

# configure stderr
# set the conversion pattern of stdout
# Print the date in ISO 8601 format
log4j.appender.stderr = org.apache.log4j.ConsoleAppender
log4j.appender.stderr.Threshold = WARN
log4j.appender.stderr.Target   = System.err
log4j.appender.stderr.layout = org.apache.log4j.PatternLayout
log4j.appender.stderr.layout.ConversionPattern = %-5p %d [%t][%F:%L] : %m%n

2
你确定过滤器可以这样应用到第一个appender吗?我尝试使用.properties文件没有成功。 - John Strickler
1
这个解决方案对我有效,也许应该将其标记为解决方案,而不是由John B提供的答案。 - Stefan
为什么这个解决方案对一些人有效,而对另一些人无效?(对我来说不起作用,过滤器没有应用。) - Meera
4
找到答案了:看起来在1.2.16和1.2.17版本中支持在属性文件中使用,但在这之前的版本不支持(https://dev59.com/am865IYBdhLWcg3wnP2a)。 - Meera

12

根据Jon Skeet之前在这篇帖子中的内容:

不幸的是,没有“最大”阈值,所以无论何时您收到调试信息,都会收到警告信息。在我看来,这有点麻烦。


注:原文中的"IMO"表示"In My Opinion",翻译为“在我看来”。

谢谢您的快速回复。是否有办法对附加器(例如stdout附加器)进行子类化,以便在日志级别高于INFO时将其拒绝?过滤器方面怎么样:设置一个stdout过滤器,只接受TRACE、DEBUG、INFO级别的日志? - Elvis
当然可以。您可以创建自己的appender并在配置文件中指向它。 - John B
1
这是一个(xml配置文件中的)例子:https://dev59.com/NW445IYBdhLWcg3wgqnT,那么这个和下面的代码是一样的吗? log4j.appender.stdout.Filter = org.apache.varia.LevelRangeFilter log4j.appender.stdout.Filter.LevelMax = INFO log4j.appender.stdout.Filter.LevelMin = TRACE? 如果是的话,在我的情况下好像不起作用。Log4j会抛出一个警告信息,告诉我无法设置过滤器... - Elvis

11
  1. 不再使用.properties配置文件,而是需要使用.xml配置文件。
  2. 在.xml配置文件中,添加一个名为"filter"的元素,类型为"org.apache.log4j.varia.LevelRangeFilter",并设置其参数LevelMaxLevelMin

例如下面的.xml配置文件定义了两个追加器:stdout、stderr。stdout将所有级别小于或等于INFO的日志输出到标准输出,而stderr则将所有级别大于INFO的日志输出到标准错误。

<?xml version="1.0" encoding="UTF-8"?>
<!--
    Document    : log4j.xml
    Created on  : 13 Δεκέμβριος 2011, 3:55 μμ
    Author      : elitex
    Description : Purpose of the document follows.
-->
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration>
    <appender name="stderr" class="org.apache.log4j.ConsoleAppender">
        <param name="threshold" value="warn" />
        <param name="target" value="System.err"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-5p %d [%t][%F:%L] : %m%n" />
        </layout>
    </appender>
    <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
        <param name="threshold" value="debug" />
        <param name="target" value="System.out"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-5p %d [%t][%F:%L] : %m%n" />
        </layout>
        <filter class="org.apache.log4j.varia.LevelRangeFilter">
            <param name="LevelMin" value="debug" />
            <param name="LevelMax" value="info" />
        </filter>
    </appender>
    <root>
        <priority value="debug"></priority>
        <appender-ref ref="stderr" />
        <appender-ref ref="stdout" />
    </root>
</log4j:configuration>

更多信息请参见:http://www.laliluna.de/articles/posts/log4j-tutorial.html

(该网页内容与IT技术有关,可供参考)

6

以下是使用log4j2中的ThresholdFilter标记的另一个示例。

<Console name="ConsoleERR" target="SYSTEM_ERR">
    <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level - %msg%n"/>
    <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
</Console>

请查看文档

2
这是一个可以完全满足你要求的logback配置文件:
```xml

请保留HTML标签

```
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true" scan="true" scanPeriod="30 seconds">

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <target>System.out</target>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder>
            <pattern>
                %-4relative [%thread] %-5level %logger - %msg%n
            </pattern>
        </encoder>
    </appender>

    <appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender">
        <target>System.err</target>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>WARN</level>
        </filter>
        <encoder>
            <pattern>
                %-4relative [%thread] %-5level %logger - %msg%n
            </pattern>
        </encoder>
    </appender>

    <root level="${LOGBACK_ROOT_LEVEL:-INFO}">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="STDERR" />
    </root>

</configuration>

不好意思,这也会过滤跟踪和调试信息。 - Thirdman

0

将其更改为NEUTRAL并添加DEBUG过滤器应该可以捕获DEBUG。还有另一个内置的过滤器,需要janino依赖项:

    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">      
        <evaluator> 
            <expression>
                   <![CDATA[ level > INFO ]]>
            </expression>
        </evaluator>
        <OnMatch>DENY</OnMatch>
        <OnMismatch>NEUTRAL</OnMismatch>
    </filter>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接