rootlogger 和 logger的关系

文章介绍了日志框架如log4j、logback中的logger配置,包括logger的name如何关联代码中的logger对象,以及如何通过logger的name形成树形结构。这种结构允许子logger继承父logger的属性,如日志级别和appender,便于管理和控制日志输出。配置文件中的logger标签需对应实际存在的logger,并提供了如何批量配置日志级别的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

你是不是经常看到日志框架(log4j、log4j2、logback等)配置文件中有类似配置,但是始终搞不清楚啥意思?

    <root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    </root>
    
    <logger name="xxxx" level="DEBUG">
        <appender-ref ref="FILE" />
    </logger>

    <logger name="yyyy" level="DEBUG" />

1,首先搞清楚这里的logger指的是什么?

就是咱们在java代码中创建的logger对象,如下:

Logger log = LoggerFactory.getLogger(App.class);

logger的name有两种指定方式,源码如下:

推荐使用传入当前类型的方式(使用全限定名作为logger的name),因为这种方式能使所有的logger形成一棵树,当然自己传入字符串作为logger的name也可以形成一棵树,只不过相对麻烦,具体看下面说明。

2. logger之间是怎么形成一棵树的

通过logger的name。

假设在com.aa包中有A1.class和A2.class, 在com.bb包中有B1.class和B2.class,在com.aa.user包中AUser.class。

A1.class中创建logger:

Logger logger = LoggerFactory.getLogger(A1.class);

A2.class中创建logger:

Logger logger = LoggerFactory.getLogger(A2.class);

B1.class中创建logger:

Logger logger = LoggerFactory.getLogger(B1.class);

B2.class中创建logger:

Logger logger = LoggerFactory.getLogger(B2.class);

AUser.class中创建logger:

Logger logger = LoggerFactory.getLogger(AUser.class);

那么这几个logger就通过name形成了一定关系,简图如下(蓝色的是目录,绿色的logger):

形成树之后有什么好处?

因为子节点会继承父节点的属性值(如日志级别、appender、日志格式等),所以可以方便批量的控制和管理logger,而root logger相当于树根,可用来做默认配置,比如rootlogger的日志级别设置为INFO,那么下面所有logger的日志级别都是INFO,除非针对某个logger设定它自己的级别,举几个例子如下:

1.设定com.aa包及其子包下的所有logger的日志级别为INFO,使用配置如下:

<logger name="com.aa" level="INFO" />

2.设定com.aa.user包及其子包下的所有logger的日志级别为ERROR,使用配置如下:

<logger name="com.aa.user" level="ERROR" />

3.设定com.bb包及其子包下的所有logger的日志级别为DEBUG,使用配置如下:

<logger name="com.bb" level="DEBUG" />

4.设定所有日志只输出到控制台,但com.bb包及其子包下的所有logger不光要输出到控制台,还要输出到log文件中:

    <!--所有的logger都只输出到控制台-->
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>
    
    <!--com.bb包及其子包下的所有logger,不仅要输出到控制台,还要输出到log文件-->
    <logger name="com.bb" level="DEBUG">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="myfile" /> 
    </logger>

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder charset="UTF-8">
            <!-- 输出日志记录格式 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="myfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 输出文件路径+文件名 -->
            <fileNamePattern>${CATALINA_BASE}/collie.%d{yyyyMMdd}.log</fileNamePattern>
            <!-- 保存30天的日志 -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder charset="UTF-8">
            <!-- 输出日志记录格式 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

3.总结

① 配置文件中logger标签的name并不是瞎写的,而是要在代码中确实存在的,否则没有任何效果

② 用类型作为logger的name,本质就是使用类的全限定名作为name,它本身就具有树形结构,所以创建logger时推荐使用类型作为入参,自己传入的字符串很难形成树形结构且不好维护

③ logger之间形成树,且子会继承父的属性,如果不想继承,可增加additivity="false"属性,如下:

<logger name="org.example" level="INFO" additivity="false" />

④ 所有日志框架的基本套路: 有 logger、appender、日志格式 三大组件

logger就是在代码中通过LoggerFactory.getLogger创建的对象,我们用它来输出日志,

每个logger都可以通过setXXX方法来设置其日志输出级别、日志输出目的地appender(一般日志格式的配置是在appender内的),

但是如果每个logger都设置一遍这些参数就太繁琐了,所以日志框架的设计者就让这些logger形成一颗树,咱们在配置文件中只需对树上的某些节点进行配置日志级别、appender等就可以了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值