java日志框架问题探究

本文探讨了log4j配置中的关键问题,包括配置文件命名、类或包的日志配置、additivity属性的作用、appender的Threshold与rootLogger level的区别,以及log4j迁移到logback的步骤。实验结果显示,log4j.properties文件名不可更改,additivity属性影响子Logger的输出源,Threshold用于过滤日志级别,迁移log4j至logback涉及jar包、配置文件和logger类的替换。

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

主要参考资料:

(推荐)java日志框架知识:https://www.cnblogs.com/gavanwanggw/p/7305218.html

log4j配置详解:https://blog.youkuaiyun.com/sinat_30185177/article/details/73550377

包或类的日志配置:https://www.cnblogs.com/yidaxia/p/5820036.html

Log4j迁移到Logback:https://blog.youkuaiyun.com/abc86319253/article/details/48731297


这里,以log4j为例,主要探究以下几个问题:

1、更改配置文件名字(log4j.properties),是否可以正常读取配置文件?
2、如何为单独一个类或者一个包配置日志?
3、additivity属性有什么作用?
4、appender的"Threshold = ERROR "和rootLogger的level有什么区别,同时配置会有什么效果?
5、如何实现不同日志系统的桥接?

 

一、环境配置:

引入jar包(log4j-1.2.17.jar)后,创建配置文件(log4j.properties)如下:

### \u8BBE\u7F6E###
log4j.rootLogger = info,stdout,D,E

### \u8F93\u51FA\u4FE1\u606F\u5230\u63A7\u5236\u62AC ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### \u8F93\u51FADEBUG \u7EA7\u522B\u4EE5\u4E0A\u7684\u65E5\u5FD7\u5230=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG 
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### \u8F93\u51FAERROR \u7EA7\u522B\u4EE5\u4E0A\u7684\u65E5\u5FD7\u5230=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E\://logs/error.log 
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern =%-d{yyyy-MM-dd HH\:mm\:ss}  [ %t\:%r ] - [ %p ]  %m%n

创建测试类进行测试:

 

二、探究结果:

  • 问题一

测试结果:文件名修改后,日志打印无法正常进行,文件名必须为log4j.properties。

  • 问题二

要给某一个包或者类配置日志,只需加上类似如下配置即可:(配置logger,指定包名或者类名,additivity属性等)

#com.thunisoft.crj.test.ClassLog\u5305\u4E0B\u914D\u7F6E\u7684\u65E5\u5FD7
log4j.logger.com.thunisoft.crj.test.ClassLog=DEBUG, message
log4j.additivity.com.thunisoft.crj.test.ClassLog=false
log4j.appender.message=org.apache.log4j.RollingFileAppender
log4j.appender.message.File=E\://logs/message.log 
log4j.appender.message.Append=true
log4j.appender.message.MaxFileSize=1GB
log4j.appender.message.MaxBackupIndex=5
log4j.appender.message.layout=org.apache.log4j.PatternLayout
log4j.appender.message.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%-5p][%c{1}] [%t] - %m%n
log4j.appender.message.encoding=UTF-8
  • 问题三:

关于additivity:

additivity是 子Logger 是否继承 父Logger 的 输出源(appender) 的标志位。详细说,默认情况下 子Logger 会继承 父Logger 的appender(additivity=true),也就是说 子Logger 会在 父Logger 的appender里输出。若是additivity设为false,则 子Logger 仅仅会在自己的appender里输出。而不会在 父Logger 的appender里输出。 

 

换句话说,在子logger(这里指是message)中配置additivity=false,不会在父logger(这里指是rootLogger,包括stdout,D,E)中的appender输出,只会在自己的appender中输出。

  • 问题四:

关于Threshold:(使用场景:比如把一些报错ERROR日志单独存到指定文件)

Threshold属性可以指定日志level 

Log4j根据日志信息的重要程度从大到小,分OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL

比如我们指定某个appender的Threshold为WARN,那这个appender输出的日志信息就是WARN级别以及WARN以上的级别; 

假如我们指定的是ERROR,那这个就输出ERROR或者FATAL日志信息;

当然这里有个提前  rootLogger里配置的level比如小于Threshold层级  否则无效 还是按照总的rootLogger里的level来输出,一般我们实际实用的话 rootLogger里配置DEBUG,然后某个文件专门存储ERRO日志,就配置下Threshold为ERROR,这个就是我们的最佳实践,不要乱七八糟瞎配置;

关于这一点,在上面的配置试验中就可以看出:由于D这个appender配置的“Threshold=DEBUG”级别小于rootLogger中配置的INFO,因此,按照info的级别输出。而E这个appender配置的“Threshold=ERROR”级别大于rootLogger中配置的INFO,则输出对应的日志级别以error为准。

  • 问题五:

由于logback日志组件性能比log4j好,项目中我们更多的是使用logback。为此,如果之前使用log4j,则需要将log4j迁移到logback(只要三步):
1,引入需要的jar包(是maven则加入对应的依赖)

或者

                <!-- logback日志配置开始 -->
                <dependency>
                        <groupId>ch.qos.logback</groupId>
                        <artifactId>logback-core</artifactId>
                        <version>1.1.2</version>
                </dependency>
                <dependency>
                        <groupId>ch.qos.logback</groupId>
                        <artifactId>logback-access</artifactId>
                        <version>1.1.2</version>
                </dependency>
                <dependency>
                        <groupId>ch.qos.logback</groupId>
                        <artifactId>logback-classic</artifactId>
                        <version>1.1.2</version>
                </dependency>
                <dependency>
                        <groupId>org.slf4j</groupId>
                        <artifactId>log4j-over-slf4j</artifactId>
                        <version>1.7.7</version>
                </dependency>
               <!-- logback日志配置结束 -->

2,在src目录下创建logback.xml文件

项目之前的使用log4j.properties可以用http://logback.qos.ch/translator/转换到等价的logback配置文件。PS:转换后的配置文件,pattern参数需要修改。
如log4j的pattern配置 %-d{yyyy-MM-dd HH:mm:ss,SSS} [%c:%L]-[%p] %m%n 在logback里面不在起效。
我把它调整为 %date [%level] [%thread] %logger{80} [%file : %line] %msg%n
另外按日期产生日志文件策略的pattern也需要修改(具体查看下文的logback.xml配置文件)。

参考:https://blog.youkuaiyun.com/chenminghe271/article/details/38682493

转化后: 

<?xml version="1.0" encoding="UTF-8"?>

<!-- For assistance related to logback-translator or configuration  -->
<!-- files in general, please contact the logback user mailing list -->
<!-- at http://www.qos.ch/mailman/listinfo/logback-user             -->
<!--                                                                -->
<!-- For professional support please see                            -->
<!--    http://www.qos.ch/shop/products/professionalSupport         -->
<!--                                                                -->
<configuration>
  <appender name="message" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!--See also http://logback.qos.ch/manual/appenders.html#RollingFileAppender-->
    <encoding>UTF-8</encoding>
    <Append>true</Append>
    <File>E://logs/message.log</File>
    <encoder>
      <pattern>%date [%level] [%thread] %logger{80} [%file : %line] %msg%n</pattern>
    </encoder>
    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
      <maxIndex>5</maxIndex>
      <FileNamePattern>E://logs/message.log .%i</FileNamePattern>
    </rollingPolicy>
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
      <MaxFileSize>1GB</MaxFileSize>
    </triggeringPolicy>
  </appender>
  <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
    <Target>System.out</Target>
    <encoder>
      <pattern>%date [%level] [%thread] %logger{80} [%file : %line] %msg%n</pattern>
    </encoder>
  </appender>
  <appender name="D" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!--See http://logback.qos.ch/manual/appenders.html#RollingFileAppender-->
    <!--and http://logback.qos.ch/manual/appenders.html#TimeBasedRollingPolicy-->
    <!--for further documentation-->
    <Append>true</Append>
    <File>E://logs/log.log</File>
    <encoder>
      <pattern>%date [%level] [%thread] %logger{80} [%file : %line] %msg%n</pattern>
    </encoder>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>DEBUG</level>
    </filter>
  </appender>
  <appender name="E" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!--See http://logback.qos.ch/manual/appenders.html#RollingFileAppender-->
    <!--and http://logback.qos.ch/manual/appenders.html#TimeBasedRollingPolicy-->
    <!--for further documentation-->
    <Append>true</Append>
    <File>E://logs/error.log</File>
    <encoder>
      <pattern>%date [%level] [%thread] %logger{80} [%file : %line] %msg%n</pattern>
    </encoder>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>ERROR</level>
    </filter>
  </appender>
  <logger name="com.thunisoft.crj.test.ClassLog" additivity="false" level="DEBUG">
    <appender-ref ref="message"/>
  </logger>
  <root level="INFO">
    <appender-ref ref="stdout"/>
    <appender-ref ref="D"/>
    <appender-ref ref="E"/>
  </root>
</configuration>

3,把打印日志类使用的logger类替换为SLF4J的logger类(注意是LoggerFactory)

 

桥接完成! 


结束和声明

以上纯属个人观点和体会,相关的资料和观点来自网络的朋友们!
希望这篇文章能对你有所帮助! 
欢迎大家来一起讨论分享干货,或者批评指正! 
更加热切盼望各路大神前辈给些指导和建议!
转载请注明出处!或者联系我!(chenruijia_java@163.com)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值