Log4j 是 Apache 的一个开源项目,通过使用 Log4j,我们可以控制日志输出的目标、日志的级别、日志的格式等操作。
日志作用
- 记录系统运行过程中的重要运行信息
1)付费信息
2)消费信息
3)道具掉落信息 - 记录系统运行过程中的异常信息
1)服务器运行宕机
2)程序抛出异常
log4j.properties 中的内容
log4j.properties
文件共包括3种信息:
记录器:日志使用的记录级别和输出源名称
日志级别和日志开关
# 日志级别 FATAL(致命) ERROR(错误) WARN(警告) INFO(信息) DEBUG(调试)TRACE(堆栈) # 日志开关 ALL(所有级别日志都打印) OFF(关闭日志)
输出源名称
输出源是自己定义的一个名称,用来分类输出日志
输出源:日志记录的方式(控制台记录、文件记录、数据库记录…),每一个输出源要指定一个输出源名称
常见的输出源:org.apache.log4j.ConsoleAppender(控制台) org.apache.log4j.FileAppender(文件) org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件) org.apache.log4j.RollingFileAppender(文件大于配置的时候产生一个新的文件) org.apache.log4j.jdbc.JDBCAppender(数据库持久化日志) org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
布局:日志的样式(日志记录的时间、级别、信息…)
org.apache.log4j.HTMLLayout(以HTML表格形式布局) org.apache.log4j.PatternLayout(可以灵活地指定布局模式) org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串) org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等信息)
例子:
# 记录器:定义当前日志使用的记录级别和输出源名称
# info:日志级别,只能指定一个
# yz:输出源的名称。输出源的名称可以是多个,用逗号隔开
log4j.rootLogger=info,yz
# 输出源:日志采用哪种方式记录(控制台记录、文件记录、数据库记录)
log4j.appender.yz=org.apache.log4j.ConsoleAppender
# 输出目标,一般可以不用配置
# log4j.appender.yz.Target=System.out
# 布局类型
log4j.appender.yz.layout=org.apache.log4j.PatternLayout
# 布局:日志记录的内容包括哪些(记录时间、记录类型、记录级别...)
# %d:日期;%p:日志事件的优先级;%c:类名;%L:行号;%m:logger.info/debug 中输出的消息;%n:换行;
# 这些可用的符号均在 PatternLayout 中定义
log4j.appender.yz.layout.ConversionPattern=%d %p %c:%L - %m%n
多日志配置
注意:养成良好的习惯,不要将注释与配置项放在同一行!
# 定义了 debug 级别,控制台输出器 A2,文件追加器 files,日常追加器 everyday 和数据库追加器 DATABASE
log4j.rootLogger=debug,A2,files,everyday,DATABASE
log4j.appender.A2=org.apache.log4j.ConsoleAppender
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
# for file
log4j.appender.files=org.apache.log4j.RollingFileAppender
log4j.appender.files.layout=org.apache.log4j.PatternLayout
log4j.appender.files.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
# true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true
log4j.appender.files.Append = true
# 指定日志信息的最低输出级别,默认为DEBUG
# log4j.appender.files.Threshold = ERROR
# 指定日志目录及日志文件
log4j.appender.files.File=logger.log
log4j.appender.files.MaxFileSize=1KB
# for file every day
log4j.appender.everyday=org.apache.log4j.DailyRollingFileAppender
log4j.appender.everyday.layout=org.apache.log4j.PatternLayout
# true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true
log4j.appender.everyday.Append = true
# 指定日志信息的最低输出级别,默认为DEBUG
# log4j.appender.everyday.Threshold = ERROR
# 指定日志目录及日志文件
log4j.appender.everyday.File=myloggers.log
log4j.appender.everyday.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.everyday.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
log4j.appender.everyday.MaxFileSize=1KB
# for database
log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
# 指定日志信息的最低输出级别,默认为DEBUG
# log4j.appender.DATABASE.Threshold = ERROR
#log4j.appender.DATABASE.BufferSize=10
log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
log4j.appender.DATABASE.URL=jjdbc:mysql://127.0.0.1:3306/test
log4j.appender.DATABASE.user=root
log4j.appender.DATABASE.password=root
# className:类名;methodName:方法名;message:日志信息
# '%c','%M','%m':对应 PatternLayout 中定义的格式
log4j.appender.DATABASE.sql=INSERT INTO tbl_log (className,methodName,message) VALUES ('%c','%M','%m')
# 日志分包记录,格式:log4j.category.包名=日志级别
log4j.category.com.p7.dao=error
log4j.category.com.p7.pay=debug
Log4j 配置中的坑
日志级别的优先级配置
log4j.appender.Console.Threshold > log4j.category.包名 > log4j.rootLogger
,Threshold
最优先,其次log4j.category
,最后是rootLogger
的优先级。
在log4j.category
分包设置日志级别当中,子包的日志级别会覆盖父包的日志级别。# 父包下的所有类的日志级别为debug log4j.category.com.p7.log=debug # 子包下的所有类的日志级别为 log4j.category.com.p7.log.impl=info
log4j.appender.输出源名称.Threshold = ERROR
这个配置项是可以覆盖log4j.rootLogger
和log4j.category.com.p7.log
分包的日志级别# 定义LOG输出级别 log4j.rootLogger=all,Console # 定义日志输出目的地为控制台 log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.Target=System.out log4j.appender.Console.Threshold = error # 可以灵活地指定日志输出格式,下面一行是指定具体的格式 log4j.appender.Console.layout = org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=[%c] - %m%n # 此处分包设置日志级别 log4j.category.com.p7.log=debug log4j.category.com.p7.log.impl=info
Java 中使用 Log4j
- 创建一个
Maven
项目 引入
log4j
需要的依赖<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.7</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.7</version> </dependency>
配置
log4j.properties
文件,放在src/main/resources
下log4j.rootLogger=DEBUG,Console log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.Target=System.out log4j.appender.Console.layout = org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=[%p] [%d{yyyy-MM-dd HH:mm:ss}][%c]%m%n
测试(默认配置文件)
// 这里使用 org.slf4j 下的类,而不是 org.apache.log4j 下的类,为什么呢? // 大家可以导入org.apache.log4j 下的类试一下 import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TestLog4j { // log4j默认会加载classpath下的配置文件 private static Logger logger = LoggerFactory.getLogger(TestLog4j.class); public static void main(String[] args) { // 带有参数 logger.info("This is args:{}", 123); // 记录debug级别的信息 logger.debug("This is debug message."); // 记录info级别的信息 logger.info("This is info message."); // 记录error级别的信息 logger.error("This is error message."); } }
指定配置文件
- 通过JVM传参指定配置文件
java -Dlog4j.configuration=file:/E:/workspace/edu-parent/edu-log4j/src/main/resources/conf/log4j.properties/log4j.properties
- 通过
PropertyConfigurator.configure(arg)
指定配置文件
public class TestLog4j { static { // 指定全路径 // PropertyConfigurator.configure("E:\\workspace\\edu-parent\\edu-log4j\\src\\main\\resources\\conf\\log4j.properties"); // 使用org.apache.log4j.helpers.Loader提供的方式,从classpath读取配置文件 // PropertyConfigurator.configure(Loader.getResource("conf/log4j.properties")); // 通过classloader从classpath获取配置文件内容 PropertyConfigurator.configure(TestLog4j.class.getClassLoader().getResourceAsStream("conf/log4j.properties")); } private static Logger logger = LoggerFactory.getLogger(TestLog4j.class); public static void main(String[] args) { // 带有参数 logger.info("This is args:{}", 123); // 记录debug级别的信息 logger.debug("This is debug message."); // 记录info级别的信息 logger.info("This is info message."); // 记录error级别的信息 logger.error("This is error message."); } }
- 通过JVM传参指定配置文件
遇到的一些问题
log4j
的警告,这些警告是因为log4j
默认加载的配置文件的路径是classpath
下,但是你可能将配置文件放在了单独的文件夹下,例如在/src/main/resources
下新建config
文件夹,并将配置文件放在此文件夹下,log4j
找不到就会有这个警告,并且你的日志也不会被打印出来。
这个警告不管是否是spring
项目,只要log4j
没有找到配置文件就会出现。
可以指定配置文件的路径避免这个警告,参考上文提供的方式。
log4j:WARN No appenders could be found for logger (com.p7.framework.dbrouter.TestDynamicDataSource).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.