如何更好的掌控日志输出-Log4j <logger>配置项介绍

本文介绍如何通过Log4j的配置文件精确控制不同组件和类的日志输出级别,以便于开发过程中更高效地定位问题。

【转自】http://tobato.iteye.com/blog/152573

 

经常看见开发Web应用的时候,有人被控制台输出的大量日志 弄得眼花缭乱,启动一个应用,控制台打出
N多没用的日志 。那么,如何控制最大限度log4j的配置文件输出需要的调试信息呢?

Log4j的Logger组件配置可以帮助我们屏蔽不必要的日志 输出,尤其在项目应用了大量第三方组件的时候,
通过控制Logger组件可以控制输出某一个组件的日志 级别,帮助我们更好的进行调试。

注意:控制的粒度到类一级。也就是说,可以控制某一个类的日志 如何输出。
限制:虽然不可以控制到方法一级,但是基本上也够用了。

假设我们现在的类命名空间在 com.foo 下面
我们有2个包
package com.foo.cartoon
package com.foo.common

这2个包下面分别有自己的类文件
在package com.foo.cartoon包下有
com.foo.cartoon.Cat;

在package com.foo.common包下有
com.foo.common.Omia;

使用如下的配置文件:

Java代码 复制代码
  1. <?xml version= "1.0"  encoding= "UTF-8"  ?>  
  2. <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >  
  3.   
  4. <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" >  
  5.   
  6.     <appender name="CONSOLE"   class = "org.apache.log4j.ConsoleAppender" >  
  7.         <layout class = "org.apache.log4j.PatternLayout" >  
  8.             <param name="ConversionPattern"   
  9.                 value="%p [%t] %c{1}.%M(%L) | %m%n" />  
  10.         </layout>  
  11.     </appender>  
  12.   
  13.     <logger name="com.foo" >  
  14.         <level value="INFO" />  
  15.     </logger>  
  16.   
  17.     <logger name="com.foo.common" >  
  18.         <level value="DEBUG" />  
  19.     </logger>       
  20.         
  21.     <root>  
  22.         <level value="WARN" />  
  23.         <appender-ref ref="CONSOLE" />  
  24.     </root>  
  25.   
  26. </log4j:configuration>  
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern"
                value="%p [%t] %c{1}.%M(%L) | %m%n"/>
        </layout>
    </appender>

    <logger name="com.foo">
        <level value="INFO"/>
    </logger>

    <logger name="com.foo.common">
        <level value="DEBUG"/>
    </logger>     
      
    <root>
        <level value="WARN"/>
        <appender-ref ref="CONSOLE"/>
    </root>

</log4j:configuration>



那么 针对所有日志 (<root>项配置) 都使用WARN级别输出
com.foo 路径下的Class 都使用INFO 级别输出
com.foo.common 路径下的Class 都使用DEBUG 级别输出

---------------

假如想要控制com.foo.common.Omia这一个类的日志 输出级别
只需要使用如下配置
<logger name="com.foo.common.Omia">
<level value="DEBUG"/>
</logger>

---------------

如果项目中使用了第三方组件,那么可以用这样的方式控制日志

<logger name="org.apache.struts2 ">
<level value="DEBUG"/>
</logger>

<logger name="org.springframework">
<level value="INFO"/>
</logger>

这样就可以让struts2日志 按Debug级别输出,让Spring的日志 按Info级别输出

<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- 日志存放路径 --> <property name="log.path" value="/home/ruoyi/logs" /> <!-- 日志输出格式 --> <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" /> <!-- 控制台输出 --> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>${log.pattern}</pattern> </encoder> </appender> <!-- 系统日志输出 --> <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${log.path}/sys-info.log</file> <!-- 循环政策:基于时间创建日志文件 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 日志文件名格式 --> <fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- 日志最大的历史 60天 --> <maxHistory>60</maxHistory> </rollingPolicy> <encoder> <pattern>${log.pattern}</pattern> </encoder> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <!-- 过滤的级别 --> <level>INFO</level> <!-- 匹配时的操作:接收(记录) --> <onMatch>ACCEPT</onMatch> <!-- 不匹配时的操作:拒绝(不记录) --> <onMismatch>DENY</onMismatch> </filter> </appender> <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${log.path}/sys-error.log</file> <!-- 循环政策:基于时间创建日志文件 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 日志文件名格式 --> <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- 日志最大的历史 60天 --> <maxHistory>60</maxHistory> </rollingPolicy> <encoder> <pattern>${log.pattern}</pattern> </encoder> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <!-- 过滤的级别 --> <level>ERROR</level> <!-- 匹配时的操作:接收(记录) --> <onMatch>ACCEPT</onMatch> <!-- 不匹配时的操作:拒绝(不记录) --> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- 用户访问日志输出 --> <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${log.path}/sys-user.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 按天回滚 daily --> <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- 日志最大的历史 60天 --> <maxHistory>60</maxHistory> </rollingPolicy> <encoder> <pattern>${log.pattern}</pattern> </encoder> </appender> <!-- 系统模块日志级别控制 --> <logger name="com.ruoyi" level="info" /> <!-- Spring日志级别控制 --> <logger name="org.springframework" level="warn" /> <root level="info"> <appender-ref ref="console" /> </root> <!--系统操作日志--> <root level="info"> <appender-ref ref="file_info" /> <appender-ref ref="file_error" /> </root> <!--系统用户操作日志--> <logger name="sys-user" level="info"> <appender-ref ref="sys-user"/> </logger> </configuration> 解释下这个日志 会产生什么效果
最新发布
07-01
<think>我们有一个logback配置文件,需要解释其中各个appender和logger的作用,以及该配置会产生什么样的日志输出效果。配置文件内容如下(来自引用[3]):```<configuration><appender name="FILE" class="ch.qos.logback.core.FileAppender"><file>myApp.log</file><encoder><pattern>%date %level [%thread] %logger{10}[%file:%line]%msg%n</pattern></encoder></appender><appendername="STDOUT"class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%msg%n</pattern></encoder></appender><loggername="chapters.configuration"><appender-refref="FILE"/></logger><rootlevel="debug"><appender-ref ref="STDOUT" /></root></configuration> ```根据引用内容,我们逐步解析:1.**Appender(输出源)**:定义日志输出的目的地。每个appender有一个名称和一个类,类决定了输出到哪里(如文件、控制台等)。-`FILE` appender:使用`FileAppender`,将日志写入文件`myApp.log`。其`encoder`定义了输出格式:日期、日志级别、线程名、logger名(缩写为10个字符)、文件名和行号、日志消息,最后换行(%n)[^3][^4]。-`STDOUT` appender:使用`ConsoleAppender`,将日志输出到控制台。其`encoder`只输出日志消息本身(%msg)和换行(%n)[^3]。2. **Logger日志记录器)**:负责捕获日志信息,并决定是否传递到appender。每个logger可以设置级别和关联的appender。-名为`chapters.configuration`的logger:它关联了`FILE` appender(通过`<appender-ref ref="FILE"/>`)。这意味着所有由该logger(或其子logger)处理的日志事件,只要级别满足,就会发送到`FILE` appender。注意,这个logger没有设置级别,所以它会继承根logger的级别(即debug)[^2][^3]。-logger(`<root>`):级别为debug,关联了`STDOUT`appender。根logger是所有logger的祖先,所以所有日志事件最终都会到达根logger(除非中间某个logger设置了`additivity=false`)[^2]。3. **日志传递规则(Additivity)**:默认情况下,logger的additivity为true,即日志事件除了被当前logger处理外,还会传递给父logger。在这个配置中:-对于`chapters.configuration`这个logger,由于没有设置`additivity`,所以默认为true。因此,一条日志事件会先被这个logger处理(发送到`FILE`appender),然后传递给根logger(发送到`STDOUT` appender)[^2]。-注意:同一个日志事件可能会被多个appender处理,即同时输出到文件和控制台。4.**产生的日志输出效果**:-所有日志事件(因为根logger级别为debug,所以所有debug及以上级别的日志都会记录)都会输出到控制台(通过`STDOUT` appender),但控制台只输出消息本身(%msg)[^3]。-同时,对于`chapters.configuration`这个logger(以及其下的子logger,比如`chapters.configuration.Foo`)产生的日志事件,除了会输出到控制台(因为传递到根logger)外,还会以更详细的格式输出到文件`myApp.log`中(格式为:日期级别[线程] [logger名缩写][文件名:行号]消息)[^3]。-对于其他logger(比如名为`com.example`的logger)产生的日志事件,由于没有专门配置,所以只由根logger处理,即只输出到控制台(不会输出到文件)[^2][^3]。总结:该配置实现了将特定包(`chapters.configuration`)下的日志详细记录到文件,同时所有日志(包括该包下的日志)都以简略形式输出到控制台。注意:由于`chapters.configuration`这个logger的additivity默认为true,所以它的日志会同时出现在文件和终端。如果希望避免重复输出(比如不想让`chapters.configuration`的日志在控制台出现两次:一次是详细格式到文件,一次是简略格式到控制台),通常需要在该logger上设置`additivity="false"`,这样就不会传递给根logger了。但本配置没有设置,所以会有重复(但格式不同:文件是详细格式,控制台是简略格式)。因此,具体效果:-控制台:所有日志(包括`chapters.configuration`的日志)都只显示消息内容(%msg)。-文件`myApp.log`:只有`chapters.configuration`及其子logger日志,显示详细格式(包括日期、级别等)。引用说明:[^1]:Logger的基本概念和级别[^2]: logger的层级和additivity的作用[^3]:具体的配置示例[^4]: encoder和layout的作用</think>### Logback配置文件解析 以下配置来自引用[3],我将逐层解析其作用机制和日志输出效果: ```xml <configuration> <!-- 文件型Appender --> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>myApp.log</file> <encoder> <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern> </encoder> </appender> <!-- 控制台Appender --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%msg%n</pattern> </encoder> </appender> <!-- 特定Logger --> <logger name="chapters.configuration"> <appender-ref ref="FILE" /> </logger> <!--Logger --> <root level="debug"> <appender-ref ref="STDOUT" /> </root> </configuration> ``` --- ### 一、Appender组件解析 Appender定义日志输出目的地和格式: 1. **FILE Appender** - **作用**:将日志写入文件`myApp.log` - **输出格式**: ```text %date %level [%thread] %logger{10} [%file:%line] %msg%n ``` - `%date`:时间戳 - `%level`:日志级别(DEBUG/INFO等) - `%thread`:线程名 - `%logger{10}`:Logger名称(缩写至10字符) - `%file:%line`:源代码文件名和行号 - `%msg`:日志内容 - `%n`:换行符 *示例输出*: `2023-10-01 10:30 INFO [main] c.c.MyClass [MyClass.java:42] 用户登录成功` 2. **STDOUT Appender** - **作用**:将日志输出到控制台 - **输出格式**: ```text %msg%n ``` -输出原始日志内容(无元数据) *示例输出*: `用户登录成功` --- ### 二、Logger组件解析 Logger控制日志采集范围和传递规则(引用[2]层级传递机制): 1. **特定Logger** ```xml <logger name="chapters.configuration"> <appender-ref ref="FILE" /> </logger> ``` - **作用**:捕获`chapters.configuration`包及其子包的所有类日志 - **关键特性**: - 默认`additivity=true`(未显式声明),日志会继续传递给父Logger - 关联`FILE` Appender,日志会写入文件 *示例*:`chapters.configuration.MyClass`的日志会出现在文件中 2. **根Logger** ```xml <root level="debug"> <appender-ref ref="STDOUT" /> </root> ``` - **作用**:捕获所有未被特定Logger处理的日志 - **关键特性**: - 日志级别`debug`:收集DEBUG及以上级别日志 - 关联`STDOUT` Appender:输出到控制台 *示例*:`com.other.package`的日志输出到控制台 --- ### 三、日志输出效果 #### 场景模拟 假设存在两个类: - `chapters.configuration.UserService`(匹配特定Logger- `com.utils.StringUtil`(不匹配特定Logger) | 日志来源 | 文件`myApp.log` | 控制台输出 | |------------------------------|------------------------------|-------------------| | `UserService.login()` | ✅ 带完整元数据的详细日志 | ✅ 仅纯消息文本 | | `StringUtil.validateEmail()` | ❌ 不出现 | ✅ 仅纯消息文本 | #### 传递流程(引用[2]机制) 1. `UserService`日志- 被`chapters.configuration` Logger捕获 → 写入文件 - 因`additivity=true` → 继续传递给根Logger输出到控制台 2. `StringUtil`日志- 无匹配Logger → 直接由根Logger处理 → 仅输出到控制台 --- ### 四、设计目的总结 1. **日志分离** - 核心模块日志(如`chapters.configuration`)保留完整上下文存入文件 - 其他日志输出简化消息到控制台,避免干扰 2. **资源优化** - 文件日志包含元数据便于后期分析 - 控制台日志精简,减少I/O开销 3. **灵活扩展** - 新增Logger可快速扩展新模块的日志策略 - 通过`additivity=false`可阻断日志传递(本例未使用) > 此配置典型适用于:核心业务模块需要持久化详细日志,辅助模块只需控制台监控的场景[^3][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值