Log4j 似乎已经被淘汰了为什么还要写这篇文章?
log4j、log4j2、logback 从基础思想上三者的实现是一致的,无非就是输出内容到文件,且看配置文件也都大同小异(logger、appender、layout),无非后两者比前者具有更多的高级功能,此块可以单独拎出讲。所以如果想了解本质,从最开始的版本开始会比较好下手。
简单体验
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
测试类:
public static void main(String[] args) {
Logger logger = Logger.getLogger(Log4jTest.class);
logger.debug("log4j debug");
logger.info("log4j info");
logger.error("log4j error");
}
输出到控制台:log4j.properties
# 定义一个名为 csAppender 的日志附加器
log4j.appender.csAppender=org.apache.log4j.ConsoleAppender
log4j.appender.csAppender.Threshold=INFO
log4j.appender.csAppender.Target=System.out
log4j.appender.csAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.csAppender.layout.ConversionPattern=[%d] [%t] [%c.%M:%L] [%-5p]: %m%n
# 配置根日志级别为 debug,并设置输出器为刚定义的 csAppender
log4j.rootLogger=debug,csAppender
输出到文件:log4j.properties
# 定义一个名为 fileAppender 的日志附加器
log4j.appender.fileAppender=org.apache.log4j.DailyRollingFileAppender
log4j.appender.fileAppender.Threshold=INFO
log4j.appender.fileAppender.File=D://data//usr//local//logs//home//log4j-log.log
log4j.appender.fileAppender.DatePattern = '.'yyyy-MM-dd'.log'
log4j.appender.fileAppender.Encoding=UTF-8
log4j.appender.fileAppender.Append=true
log4j.appender.fileAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.fileAppender.layout.ConversionPattern=[%d] [%t] [%-5p] [%c.%M:%L]: %m%n
# 配置根日志级别为 debug,并设置输出器为刚定义的 fileAppender
log4j.rootLogger=debug,fileAppender
上面示例配置中的 root 日志实例分别使用 csAppender(控制台)、fileAppender(文件)附加器将日志内容输出到目的地。当然也可以同时输出。log4j 官网并没有对配置进行说明,但在 org.apache.log4j.PropertyConfigurator#doConfigure
方法注释上可看到完整的说明。
第一步需要配置根 Logger 格式如下:
log4j.rootLogger = [level] , appenderName1, appenderName2, …
-
level 设定日志记录的最低级别,可设的值有 OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的级别,比如在这里设定了INFO级别,则应用程序中所有DEBUG级别的日志信息将不会被打印出来。
-
appenderName
就是指定日志信息要输出到哪里。可以同时指定多个输出目的地,用逗号隔开。 例如:log4j.rootLogger=INFO,A1,B2,C3
第二步配置日志信息输出目的地(appender)格式如下:
# For appender named
log4j.appender.appenderName=fully.qualified.name.of.appender.class
# Set appender specific options.
log4j.appender.appenderName.option1=value1
...
log4j.appender.appenderName.optionN=valueN
三大组件
Log4j has three main components: loggers, appenders and layouts. These three types of components work together to enable developers to log messages according to message type and level, and to control at runtime how these messages are formatted and where they are reported.
Log4j 有三个主要的组件:Loggers(记录器),Appenders (输出源)和 Layouts(布局)。这里可简单理解为日志类别,日志要输出的地方和日志以何种形式输出。综合使用这三个组件可以轻松地记录信息的类型和级别,并可以在运行时控制日志输出的样式和位置。
Logger
Loggers 组件在此系统中被分为五个级别:DEBUG、INFO、WARN、ERROR和FATAL。这五个级别是有顺序的,DEBUG < INFO < WARN < ERROR < FATAL,分别用来指定这条日志信息的重要程度。Log4j 有一个规则:只输出级别不低于设定级别的日志信息。假设 Loggers 级别设定为 INFO,则 INFO、WARN、ERROR 和 FATAL 级别的日志信息都会输出,而级别比 INFO 低的 DEBUG 则不会输出。
定义 logger
Log4J 中总是存在一个 rootLogger,即使没有显示配置也是存在的,并且默认输出级别为 DEBUG。其它的 logger 都继承自这个 rootLogger(如果其他logger未单独定义其输出级别)。
其次,Log4J 中的层次(Hierarchy)是用 ‘.’ 来分隔的,如 log4j.logger.com.example.test
,并不是说 log4j.logger 后面一定是具体的包名乃至类名,这个名称可以自定义,我们甚至可以定义一个log4j.logger.A.B.C,如下例所示,建立了 3 个 logger 实例,它们分别是 A
、A.B
、A.B.C
## log4j.properties
log4j.logger.A.B.C = ERROR,appenderName
## 在代码中获取名为 A.B 的日志对象
Logger logger = Logger.getLogger("A.B")
当获取不到当前需要的 logger 时,查找动作会传递,直到 root 节点仍没找到对应名字的 logger,就返回 root logger 实例。
Appender
Each enabled logging request for a given logger will be forwarded to all the appenders in that logger as well as the appenders higher in the hierarchy
log4j 官网这句话的意思是,logger 对象可以继承,且 appender 是可以累加的。当调用层次较低的 logger 对象输出日志时,log4j 会把该请求输出到当前所有附加在此 logger 上的所有 appender。
假设存在如下配置文件:
log4j.rootLogger=DEBUG,consoleAppender
log4j.logger.com=DEBUG,consoleAppender
log4j.logger.com.A.B=INFO,consoleAppender
log4j.logger.com.X=INFO,consoleAppender
## ... 省略 consoleAppender 配置
则 log4j 日志容器中存在如下图示实例关系:
对于名为 A.B 的 logger 输出的日志会往控制台输出三次,原因是 A.B 继承 A 的以及A 的父 logger 的所有 appender,这种继承关系仅仅是把父 logger 的 appender 添加到自己的 appender 列表中,父 logger 的输出 level 不会影响子 logger 的输出。
log4j.rootLogger=DEBUG,consoleAppender
log4j.logger.A=DEBUG,consoleAppender
log4j.logger.A.B=INFO,consoleAppender
log4j.additivity.A.B=false
名为 A.B 的 logger 日志仅会输出到自己的 appender 中,不会继承任何父 logger 的 appender。
若想对输出到 appender 中的日志级别进行限制的话,就需要用到 threshold 来控制。
log4j.threshold=ERROR
用来控制所有的 appender,即输出到所有appender的日志,不管原来是什么级别的,都不能低于threshold所规定的级别。
log4j.appender.Console.threshold=ERROR
用来控制指定的 appender 的输出级别。
Log4j 日志系统还提供许多强大的功能,比如允许把日志输出到不同的地方,如控制台(Console)、文件(Files)等,可以根据天数或者文件大小产生新的文件,可以以流的形式发送到其它地方等等。
控制台(console)
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
日志文件(logFile)
log4j.appender.logFile=org.apache.log4j.FileAppender
log4j.appender.logFile.Threshold=DEBUG
log4j.appender.logFile.ImmediateFlush=true
log4j.appender.logFile.Append=true
log4j.appender.logFile.File=D:/logs/log.log4j
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
回滚文件(rollingFile)
- Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG
- ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。
- Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true。
- File=D:/logs/logging.log4j:指定消息输出到logging.log4j文件中。
- MaxFileSize=100KB:后缀可以是KB, MB 或者GB。在日志文件到达该大小时,将会自动滚动,即将原来的内容移到logging.log4j.1文件中。
- MaxBackupIndex=2:指定可以产生的滚动文件的最大数,例如,设为2则可以产生logging.log4j.1,logging.log4j.2两个滚动文件和一个logging.log4j文件。
log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.Threshold=DEBUG
log4j.appender.rollingFile.ImmediateFlush=true
log4j.appender.rollingFile.Append=true
log4j.appender.rollingFile.File=D:/logs/log.log4j
log4j.appender.rollingFile.MaxFileSize=200KB
log4j.appender.rollingFile.MaxBackupIndex=50
log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout
定期回滚日志文件(dailyFile)
DatePattern='.'yyyy-MM
:即每月产生一个新的日志文件。当前月的日志文件名为 logging.log4j,前一个月的日志文件名为 logging.log4j.yyyy-MM。另外,也可以指定按周、天、时、分等来滚动日志文件,对应的格式如下:
- yyyy-MM:每月
- yyyy-ww:每周
- yyyy-MM-dd:每天
- yyyy-MM-dd-a:每天两次
- yyyy-MM-dd-HH:每小时
- yyyy-MM-dd-HH-mm:每分钟
log4j.appender.dailyFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyFile.Threshold=DEBUG
log4j.appender.dailyFile.ImmediateFlush=true
log4j.appender.dailyFile.Append=true
log4j.appender.dailyFile.File=D:/logs/log.log4j
log4j.appender.dailyFile.DatePattern='.'yyyy-MM-dd
log4j.appender.dailyFile.layout=org.apache.log4j.PatternLayout
应用于 socket
log4j.appender.socket=org.apache.log4j.RollingFileAppender
log4j.appender.socket.RemoteHost=localhost
log4j.appender.socket.Port=5001
log4j.appender.socket.LocationInfo=true
发送日志到指定邮件
log4j.appender.mail=org.apache.log4j.net.SMTPAppender
log4j.appender.mail.Threshold=FATAL
log4j.appender.mail.BufferSize=10
log4j.appender.mail.From = xxx@mail.com
log4j.appender.mail.SMTPHost=mail.com
log4j.appender.mail.Subject=Log4J Message
log4j.appender.mail.To= xxx@mail.com
log4j.appender.mail.layout=org.apache.log4j.PatternLayout
应用于数据库
log4j.appender.database=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.database.URL=jdbc:mysql://localhost:3306/test
log4j.appender.database.driver=com.mysql.jdbc.Driver
log4j.appender.database.user=root
log4j.appender.database.password=
log4j.appender.database.sql=INSERT INTO LOG4J (Message) VALUES('=[%-5p] %d(%r) --> [%t] %l: %m %x %n')
log4j.appender.database.layout=org.apache.log4j.PatternLayout
Layout
有时用户希望根据自己的喜好格式化自己的日志输出,Log4j 可以在 Appenders 的后面附加Layouts来完成这个功能。Layouts 提供四种日志输出样式,如根据HTML样式、自由指定样式、包含日志级别与信息的样式和包含日志时间、线程、类别等信息的样式。常使用的类如下:
- org.apache.log4j.HTMLLayout(以HTML表格形式布局)
- org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
- org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
- org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等信息)
格式化符号说明
%p:输出日志信息的优先级,即DEBUG,INFO,WARN,ERROR,FATAL。
%d:输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,如:%d{yyyy/MM/dd HH:mm:ss,SSS}。
%r:输出自应用程序启动到输出该log信息耗费的毫秒数。
%t:输出产生该日志事件的线程名。
%l:输出日志事件的发生位置,相当于%c.%M(%F:%L)的组合,包括类全名、方法、文件名以及在代码中的行数。例如:test.TestLog4j.main(TestLog4j.java:10)。
%c:输出日志信息所属的类目,通常就是所在类的全名。
%M:输出产生日志信息的方法名。
%F:输出日志消息产生时所在的文件名称。
%L::输出代码中的行号。
%m::输出代码中指定的具体日志信息。
%n:输出一个回车换行符,Windows平台为"rn",Unix平台为"n"。
%x:输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
%%:输出一个"%"字符。 另外,还可以在%与格式字符之间加上修饰符来控制其最小长度、最大长度、和文本的对齐方式。如: 1) c:指定输出category的名称,最小的长度是20,如果category的名称长度小于20的话,默认的情况下右对齐。 2)%-20c:"-"号表示左对齐。 3)%.30c:指定输出category的名称,最大的长度是30,如果category的名称长度大于30的话,就会将左边多出的字符截掉,但小于30的话也不会补空格。
实战分析
定义两个 appender 分别输出到控制台和文件,针对名为 com.fingard.rh.rhf.ryb.manager.UnifiedServiceManager
日志输出级别调成 ERROR,且禁用 appender 继承,只在当前 logger 的 appender 中输出。在类 UnifiedServiceManager
中若是使用如下方式获取 logger 则日志只有在 ERROR 级别及以上会输出
Logger logger1 = Logger.getLogger(UnifiedServiceManager.class)
分析 Logger getLogger(Class clazz)
源码可知,默认使用类全路径作为 loggerName 传入。故获取到的 logger1 即为配置文件中指定名为 com.fingard.rh.rhf.ryb.manager.UnifiedServiceManager
的日志对象。
使用技巧
在 .properties 配置文件中定义变量
LOG_HOME=D://data//usr//local//logs//home1
log4j.rootLogger=debug,fileAppender
# ...
log4j.appender.fileAppender.File=${LOG_HOME}//log4j-log.log
差不多是隐藏功能了…
log4j 不同模块输出到不同的文件
不同模块:以包名为 loggerName 定义多个 logger 实例
不同文件:定义多个 fileAppender,并与对应的 loggerName 的 logger 实例关联
参考:www.cnblogs.com/0201zcr/p/5…
日志输出动态改变路径
参考
- logging.apache.org/log4j/1.2/m…
- org.apache.log4j.PropertyConfigurator#doConfigure
今天的文章Log4j 笔记分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/16234.html