Log4j 为每个 appender 设置不同的日志记录级别

Posted

技术标签:

【中文标题】Log4j 为每个 appender 设置不同的日志记录级别【英文标题】:Log4j set a different logging level for each appender 【发布时间】:2018-07-10 13:15:52 【问题描述】:

我正在使用Log4j 2 来记录我的应用程序的事件。但是我遇到了以下问题。

目前所有日志消息都被写入两个不同的附加程序。一个具有RollingFile 类型,而另一个具有Console 类型。

我想要的是 RollingFile appender 记录 INFO 级别或更高级别(ERROR、FATAL)的消息,以及 Console appender 记录 ERROR 级别或更高级别(FATAL)的消息。

在我的 log4j2.xml 文件中,我似乎只能声明整个记录器(包括其所有附加程序)的日志记录级别。这是我的 log4j2.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="30">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout>
                <Pattern>%d %level %msg%n</Pattern>
            </PatternLayout>
        </Console>
        
        <RollingFile name="Log" fileName="log/Log.log" filePattern="log/Log-%dyyyy-MM-dd-%i.log" append="false">
            <PatternLayout>
                <Pattern>%d %level %msg%n</Pattern>
            </PatternLayout>
            <Policies>
                <SizeBasedTriggeringPolicy size="1 MB" />
            </Policies>
            <DefaultRolloverStrategy max="10"/>
        </RollingFile>
    </Appenders>

    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console" />
            <AppenderRef ref="Log" />
        </Root>
    </Loggers>
</Configuration>

有没有一种简单的方法可以做到这一点?我搜索了 log4j 文档,但找不到我要找的东西(也许我错过了?)。如果可能的话,我真的希望该解决方案适用于任何附加程序的类型;不特定于 RollingFile 和 Console。

编辑

我看到很多问题,要求将某个级别的消息写入文件,同时将不同级别的消息写入不同的文件。就我而言,我需要将具有一定级别 HIGHER 的消息写入不同的文件。例如,在我提供级别为 ERROR 或 FATAL 的消息的情况下,将同时写入 RollingFile 和控制台,而级别为 INFO 的消息将仅写入 RollingFile。

【问题讨论】:

Different level of logs in different log files的可能重复 我真的不这么认为。在您提供的问题中,它是关于将 ONLY 信息消息写入文件,并将 ONLY 错误消息写入另一个文件。就我而言,我想将某个级别或 HIGHER 的消息写入单独的文件。 【参考方案1】:

要限制 log4j2 中特定附加程序的日志记录级别,您应该使用附加程序的 ThresholdFilter 元素。

在您的情况下,log4j2.xml 文件将如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="30">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout>
                <Pattern>%d %level %msg%n</Pattern>
            </PatternLayout>
        </Console>
    
        <RollingFile name="Log" fileName="log/Log.log" filePattern="log/Log-%dyyyy-MM-dd-%i.log" append="false">
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout>
                <Pattern>%d %level %msg%n</Pattern>
            </PatternLayout>
            <Policies>
                <SizeBasedTriggeringPolicy size="1 MB" />
            </Policies>
            <DefaultRolloverStrategy max="10"/>
        </RollingFile>
    </Appenders>

    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console" />
            <AppenderRef ref="Log" />
        </Root>
    </Loggers>
</Configuration>

这是一个简单的测试:

public class Log4jTest 
    private static final Logger logger = LogManager.getLogger(Log4jTest.class);

    public static void main(String[] args) 
        logger.debug("Debug");
        logger.info("Info");
        logger.warn("Warning");
        logger.error("Error");
        logger.fatal("Fatal");
    

控制台输出:

2020-02-25 12:33:50,587 ERROR Error
2020-02-25 12:33:50,589 FATAL Fatal

Log.log 内容:

2020-02-25 12:33:50,585 INFO Info
2020-02-25 12:33:50,587 WARN Warning
2020-02-25 12:33:50,587 ERROR Error
2020-02-25 12:33:50,589 FATAL Fatal

在 log4j 的第一个版本中,它是 appender 的 Threshold 属性。关于如何在 log4j see the answer on question 中解决同样的问题。

借助过滤器,Log4j2 允许将输出配置到特定的附加程序,比 log4j 更灵活。

【讨论】:

@Said,我认为这与你无关,这个问题是 2 年前提出的。我只是在寻找类似问题的解决方案,发现您的问题没有得到解答。我在这里发布了对我有用的解决方案。【参考方案2】:

这应该可以解决问题。

<Loggers>
    <Root level="debug" additivity="false">
        <AppenderRef ref="Console"/>
    </Root>
    <Logger name="com.project.package" level="info" additivity="false">
        <AppenderRef ref="Log" />
    </Logger>
</Loggers>

或者,您可以这样做 - Different level of logs in different log files

顺便说一句,这在 Log4j2 文档中得到了很好的解释。见-https://logging.apache.org/log4j/2.x/manual/configuration.html

【讨论】:

这到底是什么意思?如果我有 3 个附加程序怎么办?那我该怎么办? 您可以拥有任意数量的“附加器”。 'additivity' 属性和 'name' 属性将帮助您控制是否希望这些日志记录在所有 'appenders' 中。 查看我分享的链接中 Logj2 文档中的“可加性”部分。 那不能解决我的问题。从文档中,一般方法是使用 LogManager.getLogger() 来获取与每个类对应的记录器。你不是建议我为我的应用程序中的每个包都这样做是吗? :) 我相信这确实是你应该做的。替代品 - softwareengineering.stackexchange.com/questions/287896/… 不是很好! :)

以上是关于Log4j 为每个 appender 设置不同的日志记录级别的主要内容,如果未能解决你的问题,请参考以下文章

log4j输出日志到不同文件

log4j输出文件位置

在log4j中,怎样将一个filter设置进appender中去

log4j使用总结

Log4j Append属性指定是否追加内容

Log4j Append属性指定是否追加内容