首页 > 解决方案 > log4j2中不同appender的不同级别(包括自定义级别)

问题描述

我想将我的 2 个类中的特殊消息记录到 DB 中,还想在控制台上写入我的所有程序日志。为了实现这一点,我为 JDBC appender 定义了一个 intLevel=50 的自定义级别(managerLogsLevel),但我不能'不要设置 log4j2.xml 来完成我的确切目的。这是我的 xml 文件:

<CustomLevels>

    <CustomLevel name="managerLogsLevel" intLevel="50" />

</CustomLevels>

<Appenders>
    <Console name="Console" target="SYSTEM_OUT">
        <PatternLayout pattern="%d{yyyy-MMM-dd hh:mm:ss a } %level %c - %m %n" />
    </Console>
    <JDBC name="MySQLDatabase" tableName="phonebook_finalproject.eventlog">
        <ConnectionFactory class="ir.maktabsharif.core.base.ConnectionFactory"
            method="getConnection" />
        <Column name="time" isEventTimestamp="true" />
        <Column name="name" pattern="%logger" />
        <Column name="level" pattern="%level" />
        <Column name="description" pattern="%m" />
    </JDBC>
</Appenders>

<Loggers>

    <Root level="info" additivity="false">
        <AppenderRef ref="Console" level="info" />
    </Root>

    <Logger name="org.hibernate" level="warn" />

    <Logger name="ir.maktabsharif.api" level="managerLogsLevel" >
        <AppenderRef ref="MySQLDatabase" level="managerLogsLevel" />
        <AppenderRef ref="Console" level="info" />
    </Logger>

</Loggers>

标签: javalog4j2

解决方案


正如我在评论中提到的,我不认为自定义日志级别是您的用例的最佳解决方案:

我想将我的两个班级中的特殊消息记录到数据库中,并且还想在控制台上写入我的所有程序日志

我在评论中提出了两种不同的解决方案,但我想提供更完整的答案以及一些示例。请注意,这些示例不会将消息发送到数据库,但您可以根据需要修改附加程序。这些示例只是为了说明您可以使用的一些一般技术。

下面的第一个 java 类将使用Marker/MarkerFilter方法:

package example;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;

public class SomeClass {

    private static final Logger LOG = LogManager.getLogger();
    private static final Marker SPECIAL_MESSAGE = MarkerManager.getMarker("SPECIAL_MESSAGE");   

    public static void main(String[] args){

        if(LOG.isDebugEnabled())
            LOG.debug("This is some debug!");
        LOG.info("Here's some info!");
        //To log a special kind of message use the same logger but include the marker
        LOG.info(SPECIAL_MESSAGE, "Something special goes here");
        LOG.error("Some error happened!");
    }
}

下一个类(如下)将使用“特殊记录器”方法:

package example;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class SomeClass2 {

    private static final Logger LOG = LogManager.getLogger();
    private static final Logger SPECIAL_LOG = LogManager.getLogger("SPECIAL_LOGGER");   

    public static void main(String[] args){

        if(LOG.isDebugEnabled())
            LOG.debug("This is some debug!");
        LOG.info("Here's some info!");
        //To log a special kind of message use the special logger
        SPECIAL_LOG.info("Something special goes here");
        LOG.error("Some error happened!");
    }
}

这是包含两种方法配置的 log4j2.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>

        <File name="SpecialAppender" fileName="logs/special.log" immediateFlush="false"
            append="false">
            <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
            <MarkerFilter marker="SPECIAL_MESSAGE" onMatch="ACCEPT" onMismatch="DENY"/>
        </File>

        <File name="SpecialAppenderNoFilter" fileName="logs/specialNoFilter.log" immediateFlush="false"
            append="false">
            <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </File>
    </Appenders>

    <Loggers>
        <Root level="debug">
            <AppenderRef ref="Console" />
        </Root>

        <!-- This logger uses the MarkerFilter method -->
        <Logger name="example.SomeClass" level="debug">
            <AppenderRef ref="SpecialAppender" />
        </Logger>

        <!-- The following logger is used for the "special logger" method -->

        <Logger name="SPECIAL_LOGGER" level="info">
            <AppenderRef ref="SpecialAppenderNoFilter" />
        </Logger>
    </Loggers>
</Configuration>

这两种方法非常相似,但也有区别:

  1. Marker解决方案要求您创建一个Marker对象,而记录器解决方案需要第二个Logger对象。
  2. 解决方案的输出Marker仍然为您提供了一个有意义的记录器名称,而记录器解决方案需要一个通用的记录器名称,它不会为您提供有关消息生成位置的任何线索。
  3. Marker解决方案MarkerFilter在配置文件中需要一个,而记录器解决方案在配置中需要一个专用Logger的。

正如我在评论中提到的,另一个考虑因素是在必要时将您的日志记录策略迁移到另一个日志记录框架是多么容易。如果您要迁移到的Marker框架不支持标记概念,则解决方案可能会更加困难。看来slf4j 确实支持标记,因此如果您移动到具有 slf4j 绑定的框架,那么标记很有可能仍然有效。


推荐阅读