本文主要目的是理清log4j.properties的结构,以及对于一些常见配置场景的说明。
#logger level and appender
log4j.rootLogger=info,console,file
#append to console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d %p - %m%n
#append to file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=${MyProject.root}WEB-INF/logs/web.log
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=10000
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %p - %m%n
#children log
log4j.logger.tect.luoyu.merchant.mapper=debug
log4j.logger.org.apache.shiro=debug
基本配置
以上是一个精简的log4j配置文件,首先说明下一下log4j.rootLogger,这个属性可以看成是对整个配置文件的一种声明,之后配置的细节要么是在补充说明这个属性,要么是在扩展这个属性。其值的标准配置格式为:log4j.rootLogger = [ level ] , appenderName1, appenderName2, …配置文件中实际值info,console,file。info的意思是指定日志输出级别为info级别。console和file则是自己定义的appender的名字。但是appender到底是什么呢?要怎么理解这个appender?
我们知道log4j日志框架的作用就是能让我们进行细粒度的日志管理。 appender的概念我们可以把每一个appender看成是一套日志镜像,这套镜像的输出格式可以被随意定制。定义多少个appender就有多少个镜像。为什么我们需要多套镜像呢?最简单的实际情况,开发时我们需要日志打印在控制台,而项目上线后,我们需要日志存放到文件系统,用于我们运维。这不就是2套镜像么?
理解了appender的概念后,我们回到配置文件本身。每个appender中,都有2个基本配置:输出目的地和输出格式(此配置文件里为便于理解,只做了基本配置)。
先以红色字体的console(appender的名字定义为console)这个appender的配置为例,第一个需要配置的是日志输出目的地,即控制台还是文件系统,其配置格式为:log4j.appender.appenderName = className
log4j.appender.console=org.apache.log4j.ConsoleAppender
注: console是appender的名字,ConsoleAppender是指定输出到控制台
然后就是日志输出格式,其配置格式为:log4j.appender.appenderName.layout
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d %p - %m%n
注:表示console这个appender输出日志的格式为灵活指定布局格式,ConversionPattern指定了具体的输出格式
再来看看蓝色字体的file(appender的名字定义为file)这个appender的配置。log4j.appender.file=org.apache.log4j.RollingFileAppender
注:指定file appender的输出目的地为RollingFileAppender,RollingFileAppender表示文件到达指定大小时,产生一个新的日志文件
log4j.appender.file.File=${MyProject.root}WEB-INF/logs/web.log
注:指定日志输出路径
log4j.appender.file.MaxFileSize=1MB
注:指定日志文件的大小
log4j.appender.file.MaxBackupIndex=10000
注:指定日志文件的最大个数,超过该个数会自动删除最旧的
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %p - %m%n
注:同colole,表示file这个appender输出日志的格式为灵活指定布局格式,ConversionPattern指定了具体的输出格式
进阶配置场景1:配置指定模块日志输出级别
到这里,相信对log4j的配置有了基本了解。接下来说一说一些更精细的配置。先来说说上述配置文件中最后2行的意思。刚才已经说明过,log4j.rootLogger = info,console,file,将所有的日志的输出格式配置info,info级别是不显示debug信息的,而我们开发的时候显然是需要debug信息的,那要怎么办呢?最简单粗暴的方法当然是,直接把输出级别改为debug?但是,那真的是我们想要的吗?我们现在开发会整合各种框架,就比如spring+mybatis+shiro吧,程序中时时刻刻都在和spring容器做交互,如果日志级别直接改成debug,会发生什么呢?大量spring的日志就会被打出来,日志太多有成了影响我们开发效率的问题。那我们自然就想到是不是可以开启某个具体模块的debug。是的,log4j是允许指定具体java包下面的输出级别,格式为:log4j.logger.包名 = [level],appender1, appender2...,上述示例配置文件中的最后2行
log4j.logger.tect.luoyu.merchant.mapper=debug
注:开启mybatis的打印
log4j.logger.org.apache.shiro=debug
注:开始shiro的打印
看到log4j.logger.包名 = [level],appender1, appender2...这个配置有没有觉得跟上面配置log4j.rootLogger一样?没错实际上log4j.logger.包名是log4j.rootLogger的子类,在rootLogger里配置的appender会自动应用于log4j.logger.包名,这也是为什么上述配置没有再额外配置appender的原因,也就是说我们刚才已经配置了在控制台打印的console这个appender和file appender,在增加log4j.logger.tect.luoyu.merchant.mapper和log4j.logger.org.apache.shiro=debug
这2个子类配置的时候,他们打印的debug信息也会继承log4j.rootLogger的console和file的配置。
进阶配置场景2:子logger不继承父logger的appender
这个是上一个配置情况的更进一步配置,上面的配置中,说我们把mybatis和shiro的相关debug信息打印到了全局日志输出中(父logger的appender)。但有时我们也会遇到这样的需求是,我们希望把mybatis或者shiro的debug信息单独输出到某个指定文件,并且不输出到全局日志(父logger的appender)中。这种情况下我们需要用到的配置属性是:log4j.additivity,以shiro为例,我们需要把下面这一行
log4j.logger.org.apache.shiro=debug
改为:
log4j.logger.mobileLogger=debug,shiroLogger
log4j.additivity. shiroLogger =false
log4j.appender. shiroLogger =org.apache.log4j.DailyRollingFileAppender
log4j.appender. shiroLogger.layout=org.apache.log4j.PatternLayout
log4j.appender. shiroLogger.layout.ConversionPattern=%m%n
log4j.appender. shiroLogger.file=shiroLog.log
进阶配置场景3:为某个特定appender指定输出级别
需要用到的属性是log4j.appender.appenderName.Threshold = [Level],直接上配置用例:
### set log levels ###
log4j.rootLogger = debug ,stdout,D,E
### 输出到控制台 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n
### 输出到日志文件 ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = logs/log.log
log4j.appender.D.Threshold = DEBUG ## 输出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
### 保存异常信息到单独文件 ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File = logs/error.log ## 异常日志文件名
log4j.appender.E.Threshold = ERROR ## 只输出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
进阶配置场景4:自定义logger
上述配置如果还不能完全满足你的要求,你希望把error信息就只输出到error.log,而不是error及error级以上。那log4j提供的基本配置就无法完全满足你的要求了,需要在代码级别做更进一步的配置:自定义logger。本文不做详细解释,只给出参考示例:
log4j.properties
log4j.rootLogger=debug,stdout
#Console appender
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
#infofile
log4j.logger.infofile = info,infofile
log4j.appender.infofile =org.apache.log4j.DailyRollingFileAppender
log4j.appender.infofile.layout=org.apache.log4j.PatternLayout
log4j.appender.infofile.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.infofile.File=info.log
log4j.appender.infofile.DatePattern='.'yyyy-MM-dd'.log'
#errorfile
log4j.logger.errorfile = error,errorfile
log4j.appender.errorfile =org.apache.log4j.DailyRollingFileAppender
log4j.appender.errorfile.layout=org.apache.log4j.PatternLayout
log4j.appender.errorfile.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.errorfile.File=error.log
log4j.appender.errorfile.DatePattern='.'yyyy-MM-dd'.log'
java代码
public class Log4jDemo { static Logger infoLogger = Logger.getLogger("infofile"); static Logger errorLogger = Logger.getLogger("errorfile"); public static void main(String[] args) { try { infoLogger.info("run division.."); int result = 7/0; } catch(ArithmeticException e) { errorLogger.error("Can not divide by zero"); } } }
常用基本配置属性速查
日志输出级别
输出目的地:
org.apache.log4j.ConsoleAppender(控制台)
org.apache.log4j.FileAppender(文件)
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
org.apache.log4j.net.SMTPAppender (发送日志到指定邮件)
org.apache.log4j.jdbc.JDBCAppender (应用于数据库)
日志布局(Layout)
org.apache.log4j.HTMLLayout(以HTML表格形式布局)
org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等信息)