0
点赞
收藏
分享

微信扫一扫

Log4j将不同Package的日志输出到不同的文件的方法

小磊z 2023-02-07 阅读 74


随着项目规模的越来越大,会不断的引入新的模块,不同的模块都会打印自己的日志,最后就造成日志根本没法查看,比如我自己的项目中,就存在以下这些日志:

  1. 接收外界消息的日志、对外发送消息的日志;
  2. 后台常驻线程的处理日志;
  3. 外部接口访问的参数、返回结果等接口日志;
  4. Service访问数据库产生的SQL日志;

这其中,消息日志和后台线程的日志数据量非常庞大,如果所有日志打印在一个文件中,使用tail -f log.log文件,会发现日志在快速的滚动,根本无法查看甚至定位某一个具体的SQL或者Service访问日志。

解决方法就是可以将不同的日志加以分类输出,这样相互的日志不影响,尤其重要的接口访问日志,能够很方便的定位和排查问题。

步骤1:在log4j.properties中配置

先贴一下我自己所有的log4j.properties配置:

log4j . rootLogger = INFO , console , file

log4j . appender . console = net . czt . log . AsyncConsoleAppender
log4j . appender . console . layout = org . apache . log4j . PatternLayout
log4j . appender . console . layout . ConversionPattern = % d [ % t ] % - 5p crazyant - web % - 17c { 2 } ( % 13F : % L ) % X { USER_ID } | % X { USER_IP } | % X { SERVER_ADDRESS } | % X { SERVER_NAME } | % X { REQUEST_URI } | % X { SESSION_ID } - % m % n
log4j . appender . console . bufferSize = 10000
log4j . appender . console . encoding = UTF - 8

log4j . appender . file = org . apache . log4j . RollingFileAppender
log4j . appender . file . file = / home / work / apache - tomcat - 6.0.39 / logs / crazyant . log
log4j . appender . file . MaxBackupIndex = 5
log4j . appender . file . MaxFileSize = 1GB
log4j . appender . file . layout = org . apache . log4j . PatternLayout
log4j . appender . file . layout . ConversionPattern = [ % - 5p ] crazyant - web % d { yyyy - MM - dd HH : mm : ss , SSS } % X { USER_ID } | % X { USER_IP } | % X { SERVER_ADDRESS } | % X { SERVER_NAME } | % X { REQUEST_URI } | % X { SESSION_ID } method : % l % n % m % n
log4j . appender . file . bufferSize = 10000
log4j . appender . file . encoding = UTF - 8

log4j . logger . net . czt . crazyant . msg = DEBUG , message
log4j . additivity . net . czt . crazyant . msg = false
log4j . appender . message = org . apache . log4j . RollingFileAppender
log4j . appender . message . File = / home / work / apache - tomcat - 6.0.39 / logs / crazyant_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

log4j . logger . net . czt . crazyant . async . service = DEBUG , async
log4j . additivity . net . czt . crazyant . async . service = false
log4j . appender . async = org . apache . log4j . RollingFileAppender
log4j . appender . async . File = / home / work / apache - tomcat - 6.0.39 / logs / crazyant_async . log
log4j . appender . async . Append = true
log4j . appender . async . MaxFileSize = 1GB
log4j . appender . async . MaxBackupIndex = 5
log4j . appender . async . layout = org . apache . log4j . PatternLayout
log4j . appender . async . layout . ConversionPattern = % d { yyyy - MM - dd HH : mm : ss } [ % - 5p ] [ % c { 1 } ] [ % t ] - % m % n
log4j . appender . async . encoding = UTF - 8

log4j . logger . net . czt . orm . mybatis . SqlMonitorManager = DEBUG , showsql
log4j . additivity . net . czt . orm . mybatis . SqlMonitorManager = false
log4j . logger . net . czt . transaction . interceptor . SmartTransactionInterceptor = DEBUG , showsql
log4j . additivity . net . czt . transaction . interceptor . SmartTransactionInterceptor = false
log4j . appender . showsql = org . apache . log4j . RollingFileAppender
log4j . appender . showsql . File = / home / work / apache - tomcat - 6.0.39 / logs / crazyant_sql . log
log4j . appender . showsql . Append = true
log4j . appender . showsql . MaxFileSize = 1GB
log4j . appender . showsql . MaxBackupIndex = 5
log4j . appender . showsql . layout = org . apache . log4j . PatternLayout
log4j . appender . showsql . layout . ConversionPattern = % d { yyyy - MM - dd HH : mm : ss } [ % - 5p ] [ % c { 1 } ] [ % t ] - % m % n
log4j . appender . showsql . encoding = UTF - 8

log4j . logger . net . czt . crazyant . service = DEBUG , service
log4j . additivity . net . czt . crazyant . service = false
log4j . appender . service = org . apache . log4j . RollingFileAppender
log4j . appender . service . File = / home / work / apache - tomcat - 6.0.39 / logs / crazyant_service . log
log4j . appender . service . Append = true
log4j . appender . service . MaxFileSize = 1GB
log4j . appender . service . MaxBackupIndex = 5
log4j . appender . service . layout = org . apache . log4j . PatternLayout
log4j . appender . service . layout . ConversionPattern = % d { yyyy - MM - dd HH : mm : ss } [ % - 5p ] [ % c { 1 } ] [ % t ] - % m % n
log4j . appender . service . encoding = UTF - 8





 

在配置文件的下方,可以方便的看到,我将message(消息)、async(后端线程)、showsql(数据库日志)、service(接口调用)分别输出到了不同的日志文件。

其中的一些解释:

log4j.rootLogger=INFO, console, file

log4j有一个rootLogger和普通Logger的概念,默认情况下我们只需要一个rootLogger,就是所有的日志只会输出到这一个日志文件中。

 

看一下普通Logger的配置(以接口日志service为例):

  • log4j.logger.net.czt.crazyant.service=DEBUG, service
  • 这句中的”net.czt.crazyant.service”,表示该普通logger日志配置生效的package的完全路径
  • 其中色service,表示该普通logger的名字
  • log4j.additivity.net.czt.crazyant.service=false
  • 其中的”net.czt.crazyant.service”,和上面的相同,表示该配置项针对的package
  • 该句配置的意思,是不要将该package的日志输出到rootLogger日志中,只输出到自己配置的日志就行了;
  • log4j.appender.service=org.apache.log4j.RollingFileAppender,以及该配置段下面的配置项
  • 这里的”service”字符串,和上面的第一个配置项的”service”相同,表示对该普通Logger的配置;
  • 下方的配置项和rootLogger相同,表示每天输出文件、编码UTF8、分片规则、每行的输出模式等等

我自己遇到的问题,是上面的log4j.properties配置好以后,发现各个日志文件创建了,但是里面都没有内容,这是为啥呢?来看下面第二个注意的地方;

步骤2、输出日志时需要设定日志对象对应的具体Class

什么意思呢?上面的配置项中,有一个”net.czt.crazyant.service”的package字符串,那么我们自己想一下,log4j是怎样将不同package中的logger日志输出到不同文件呢,想一下会有两种方法:

  1. 采用intercepter或者aop的方式,log4j自己检测日志输出,检测到日志产生于哪个package,就将其输出到对应文件中;
  2. 由用户传一个Class参数,log4j获取该Class对应的Package,以此为准,来定位不同的日志文件;

看一下代码,显然log4j用的是后一种简单直接的方式:







Java

import                   org         .         apache         .         commons         .         logging         .         Log         ;

import org . apache . commons . logging . LogFactory ;



public class MyClassImpl implements MyClass {

/**

* loger

*/

private static final Log logger = LogFactory . getLog ( MyClassImpl . class ) ;



/**

* my func

*/

public void myfunc ( ) {

logger . info ( "call method myfunc." ) ;

}

}




在logger = LogFactory.getLog(MyClassImpl.class)中,传入了使用该logger的Class参数,而该Class被反射取到的package地址,就是log4j用来输出日志的package地址。

这种做法也有强大的地方,方便逻辑上的日志归类,比如很多代码不属于一个package,但是它们逻辑上属于一起的,举个例子,消息的处理不只是接口调用Service这个package,可能还会调用发送msg的操作,如果想把msg的package中一些日志也输出到Service,那么在这个msg的logger初始化的时候,传入一个Serivice的Class就行了。

或者对于某一类的所有日志来说,它们所有的logger对象,都来自封装好的单个对象实例即可,而这个单个对象实例传入的参数只有一个,用于标识这个逻辑归类即可。

总结

在Log4j.properties中,支持package或者具体class的日志单独输出,但是也需要代码中logger初始化的时候,能和日志配置中的package对应上。

 


举报

相关推荐

0 条评论