文章目录
- 引言
- 什么是Log4J
- Log4J三大组件
- Log4J日志级别
- Log4J基本使用
- 自定义配置文件
- Appender示例
- FileAppender
- DailyRollingFileAppender
- RollingFileAppender
- JDBCAppender
- 自定义Logger
引言
Java 日志框架 JUL
在这篇文章中已经向大家介绍了我们为什么要使用日志文件、常见的日志框架、日志框架的发展历程、还向大家介绍了一个Java原生的一个日志框架JUL。我们在说日志文件的发展历程的时候提到Log4J2是现在最优秀的Java日志框架,Log4J当前已经停止维护,不建议使用。但是Log4是Log4J2的前身,Log4J2是在Log4J的基础上做的改进。
知其然并知其所以然 今天我们来聊一下另外一个日志框架Log4J。
什么是Log4J
Log4J是Apache开源项目,通过使用Log4J,我们可以控制日志信息输送的目的地是控制台、文件、数据库等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。
Log4J三大组件
Loggers(日志记录器)
Loggers
(日志记录器):负责收集处理日志记录,获取logger
实例可通过类名或者全限定名获取,并且对于名称具有继承机制。
从log4J 1.2以来,Logger
类取代了Category
类,Logger
类可以视作Category
类的别名。
在Log4J中包含一个特殊的logger
为rootlogger
,它是所有logger
的根,其他logger
会直接或间接的继承该rootlogger
,可使用Logger.getLogger()
获取。
Appender(输出端)
Appender 用来指定日志输出到哪个地方,可以同时指定日志的输出目的地。Log4j 常用的输出目的地有以下几种。
输出端 类型 | 作用 |
---|---|
ConsoleAppender | 将日志输出到控制台 |
FileAppender | 将日志输出到文件中 |
DailyRollingFileAppender | 将日志输出到一个日志文件,并且每天输出到一个新的文件 |
RollingFileAppender | 将日志信息输出到一个日志文件,并且指定文件的尺寸,当文件大 小达到指定尺寸时,会自动把文件改名,同时产生一个新的文件 |
JDBCAppender | 把日志信息保存到数据库中 |
Layout(日志格式化器)
用于控制日志输出内容的格式,通过使用不同的Layout类型来指定各种需要的格式。
格式化器类型 | 作用 |
---|---|
HTMLLayout | 格式化日志输出为HTML表格形式 |
SimpleLayout | 简单的日志输出格式化,打印的日志格式为(info - message) |
PatternLayout | 最强大的格式化期,可以根据自定义格式输出日志,如果没有指定转换格式,就是用默认的转换格式 |
Log4J日志级别
Log4J 在 org.apache.log4j.Level 类中定义了OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL七种日志级别:
级别 | 含义 |
---|---|
OFF | 最高日志级别,关闭左右日志 |
FATAL | 将会导致应用程序退出的错误 |
ERROR | 发生错误事件,但仍不影响系统的继续运行 |
WARN | 警告,即潜在的错误情形 |
INFO | 一般和在粗粒度级别上,强调应用程序的运行全程 |
DEBUG | 一般用于细粒度级别上,对调试应用程序非常有帮助 |
ALL | 最低等级,打开所有日志记录 |
一般只使用4个级别,优先级从高到低为 ERROR > WARN > INFO > DEBUG
Log4J基本使用
我们知道Log4J是Apache开源项目,那么我们在使用时,需要引入Jar包。
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
我们这里先不使用配置文件,直接使用BasicConfigurator.configure() 初始化系统配置,如果我们不使用配置文件又不使用BasicConfigurator.configure() 初始化系统配置将会报错。
public class LogTest {
public static void main(String[] args) {
//初始化系统配置,不需要配置文件
BasicConfigurator.configure();
//获取logger实例,注意这里的Logger是Log4j的
Logger logger = Logger.getLogger(LogTest.class);
//打印不同的日志等级
logger.fatal("fatal");
logger.error("error");
logger.warn("warn");
logger.info("info");
logger.debug("debug");
logger.trace("trace");
}
}
当通过调用方法进行配置时,logger
实例的父属性rootlogger
的appender
为ConsoleAppender
(formatter
为SimpleFormatter
),logger
实例的日志等级为DEBUG
。所以trace
等级的日志并不会输出。
自定义配置文件
将自定义配置文件log4j.properties
放置到resource
目录下
#rootLogger配置 第一个参数为日志等级,第二个参数为appender
log4j.rootLogger = trace,console
#console只是作为指定appender的别名
log4j.appender.console = org.apache.log4j.ConsoleAppender
#设置ConsoleAppender的layout为SimpleLayout
log4j.appender.console.layout = org.apache.log4j.SimpleLayout
public class LogTest {
public static void main(String[] args) {
//获取logger实例
Logger logger = Logger.getLogger(LogTest.class);
//打印6个不同的日志等级
logger.fatal("fatal");
logger.error("error");
logger.warn("warn");
logger.info("info");
logger.debug("debug");
logger.trace("trace");
}
}
当通过配置文件进行配置时,所有级别都输出了。
# 设置rootlogger日志等级为trace、指定appender为下面定义的ConsoleAppender
log4j.rootLogger = trace,console
# 指定ConsoleAppender设置别名为console
log4j.appender.console = org.apache.log4j.ConsoleAppender
# 指定ConsoleAppender的layout设置为PatternLayout
log4j.appender.console.layout = org.apache.log4j.PatternLayout
# 设置该layout的自定义格式(解析时会调用)
log4j.appender.console.layout.ConversionPattern= [%-5p]%r %l %d{yyyy-MM-dd HH:mm:ss:SSS} %m%n
专对于
PatternLayout
类中的pattern
自定义格式说明
# 占位符相关含义
%p: 输出优先级,及 DEBUG、INFO 等
%m: 输出代码中指定的日志信息
%n: 换行符(Windows平台的换行符为 "\n",Unix 平台为 "\n")
%r: 输出自应用启动到输出该 log 信息耗费的毫秒数
%d: 输出服务器当前时间,默认为 ISO8601,也可以指定格式,如:%d{yyyy-MM-dd HH:mm:ss:SSS} => 年月日 时分秒毫秒
%l: 输出日志时间发生的位置,包括类名、线程、及在代码中的行数。如:Test.main(Test.java:10)
# %l即可表示下方四个修饰符
%c: 输出打印语句所属的类的全名
%t: 输出产生该日志的线程全名
%F: 输出日志消息产生时所在的文件名称
%L: 输出代码中的行号
%%: 输出一个 "%" 字符
# 可在例如%m之间加入修饰符来控制最小宽度、最大宽度和文本的对其方式
%5c: 输出category名称,最小宽度是5,category<5,默认的情况下右对齐
%-5c: 输出category名称,最小宽度是5,category<5,"-"号指定左对齐,会有空格
%.5c: 输出category名称,最大宽度是5,category>5,就会将左边多出的字符截掉,<5不会有空格
%20.30c: category名称<20补空格,并且右对齐,>30字符,就从左边交远销出的字符截掉
public class LogTest {
public static void main(String[] args) {
//开启LogLog的debug模式
LogLog.setInternalDebugging(true);
//获取logger实例
Logger logger = Logger.getLogger(LogTest.class);
//打印不同的日志等级
logger.fatal("fatal");
logger.error("error");
logger.warn("warn");
logger.info("info");
logger.debug("debug");
logger.trace("trace");
}
}
Appender示例
FileAppender
FileAppender
:用于输出到文件,其有两个实现类,DailyRollingFileAppender
提供了轮询功能(可根据指定时间点添加文件)、RollingFileAppender
提供了根据文件大小拆分的功能。
log4j.rootLogger = trace,file
# FileAppender
# file为名称 其中属性file:文件路径 encoding:编码
log4j.appender.file = org.apache.log4j.FileAppender
log4j.appender.file.file = C:/Users/93997/Desktop/projectexers/logs/log.txt
log4j.appender.file.encoding = UTF-8
# 设置自定义布局(自定义输出格式)
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern= [%-5p]%r %l %d{yyyy-MM-dd HH:mm:ss:SSS} %m%n
public class LogTest {
public static void main(String[] args) {
//开启LogLog的debug模式
LogLog.setInternalDebugging(true);
//获取logger实例
Logger logger = Logger.getLogger(LogTest.class);
//打印不同的日志等级
logger.fatal("fatal");
logger.error("error");
logger.warn("warn");
logger.info("info");
logger.debug("debug");
logger.trace("trace");
}
}
DailyRollingFileAppender
轮询功能(根据指定是每小时,还是每天输出log日志)
# 日志等级为trace,指定appender为下面以roll作为别名的
log4j.rootLogger = trace,roll
# DailyRollingFileAppender 轮询
log4j.appender.roll = org.apache.log4j.DailyRollingFileAppender
log4j.appender.roll.file = /logs/log4j.log
log4j.appender.roll.encoding = UTF-8
# datePattern指的是根据分钟来进行轮询 可设置年月日时分秒毫秒如右: '.'yyyy-MM-dd-HH-mm-ss-SSS
log4j.appender.roll.datePattern = '.'yyyy-MM-dd-HH-mm
# 设置自定义布局(自定义输出格式)
log4j.appender.roll.layout = org.apache.log4j.PatternLayout
log4j.appender.roll.layout.ConversionPattern= [%-5p]%r %l %d{yyyy-MM-dd HH:mm:ss:SSS} %m%n
public class LogTest {
public static void main(String[] args) {
//开启LogLog的debug模式
LogLog.setInternalDebugging(true);
//获取logger实例
Logger logger = Logger.getLogger(LogTest.class);
//打印不同的日志等级
logger.fatal("fatal");
logger.error("error");
logger.warn("warn");
logger.info("info");
logger.debug("debug");
logger.trace("trace");
}
}
RollingFileAppender
按照指定文件大小进行拆分,拆分最大的文件数量可指定。
# 日志等级为trace,指定appender为下面以rollfile作为别名的
log4j.rootLogger = trace,rollfile
# RollingFileAppender 分段
log4j.appender.rollfile = org.apache.log4j.RollingFileAppender
log4j.appender.rollfile.file = /logs/log4j.log
log4j.appender.rollfile.encoding = UTF-8
# 设置单个文件最大容量(KB、MB、GB,其他单位默认传为10MB+1)以及最大文件个数
log4j.appender.rollfile.maxFileSize = 1MB
log4j.appender.rollfile.maxBackupIndex = 5
# 设置自定义布局(自定义输出格式)
log4j.appender.rollfile.layout = org.apache.log4j.PatternLayout
log4j.appender.rollfile.layout.ConversionPattern= [%-5p]%r %l %d{yyyy-MM-dd HH:mm:ss:SSS} %m%n
public class LogTest {
public static void main(String[] args) {
//开启LogLog的debug模式
LogLog.setInternalDebugging(true);
//获取logger实例
Logger logger = Logger.getLogger(LogTest.class);
for (int i = 0; i < 1000000; i++) {
//打印不同的日志等级
logger.fatal("fatal");
logger.error("error");
logger.warn("warn");
logger.info("info");
logger.debug("debug");
logger.trace("trace");
}
}
JDBCAppender
创建log表
CREATE TABLE `log` (
`log_id` int(11) NOT NULL AUTO_INCREMENT,
`project_name` varchar(255) DEFAULT NULL COMMENT '目项名',
`create_date` varchar(255) DEFAULT NULL COMMENT '创建时间',
`level` varchar(255) DEFAULT NULL COMMENT '优先级',
`category` varchar(255) DEFAULT NULL COMMENT '所在类的全名',
`file_name` varchar(255) DEFAULT NULL COMMENT '输出日志消息产生时所在的文件名称 ',
`thread_name` varchar(255) DEFAULT NULL COMMENT '日志事件的线程名',
`line` varchar(255) DEFAULT NULL COMMENT '号行',
`all_category` varchar(255) DEFAULT NULL COMMENT '日志事件的发生位置',
`message` varchar(4000) DEFAULT NULL COMMENT '输出代码中指定的消息',
PRIMARY KEY (`log_id`)
);
引入mysql驱动
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
配置连接信息
# rootlogger的日志等级是trace,appender为JDBCAppender,logDB是下面指定的别名
log4j.rootLogger = trace,logDB
# JDBCAppender 存储到数据库中
log4j.appender.logDB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.logDB.layout=org.apache.log4j.PatternLayout
log4j.appender.logDB.Driver=com.mysql.jdbc.Driver
log4j.appender.logDB.URL=jdbc:mysql://localhost:3306/test
log4j.appender.logDB.User=root
log4j.appender.logDB.Password=123456
log4j.appender.logDB.Sql=INSERT INTO log(project_name,create_date,level,category,file_name,thread_name,line,all_category,message) values('changlu','%d{yyyy-MM-ddHH:mm:ss}','%p','%c','%F','%t','%L','%l','%m')
public static void main(String[] args) {
//开启LogLog的debug模式
LogLog.setInternalDebugging(true);
//获取logger实例
Logger logger = Logger.getLogger(LogTest.class);
for (int i = 0; i < 1000000; i++) {
//打印不同的日志等级
logger.fatal("fatal");
logger.error("error");
logger.warn("warn");
logger.info("info");
logger.debug("debug");
logger.trace("trace");
}
}
自定义Logger
通过使用自定义Logger能够将第三方包下调用的类以及自己定义的类进行日志区分,对于自己的类的日志信息输出到文件中,而对于第三方包的类输出到屏幕上。
# rootLogger日志等级为trace,输出到屏幕上
log4j.rootLogger = trace,console
# 设置两个自定义logger
# xu.enbei(自己创建的包)自定义logger,日志等级为info,输出到文件
log4j.logger.xu.enbei = info,file
# 设置org.apache(第三方包)作为一个自定义logger,日志等级为error
log4j.logger.org.apache = err
# console
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern= [%-5p]%r %l %d{yyyy-MM-dd HH:mm:ss:SSS} %m%n
# FileAppender
# file:文件路径 encoding:编码
log4j.appender.file = org.apache.log4j.FileAppender
log4j.appender.file.file = C:/Users/93997/Desktop/projectexers/logs/log.log
log4j.appender.file.encoding = UTF-8
# 设置自定义布局(自定义输出格式)
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern= [%-5p]%r %l %d{yyyy-MM-dd HH:mm:ss:SSS} %m%n
public class LogTest {
public static void main(String[] args) {
//开启LogLog的debug模式
LogLog.setInternalDebugging(true);
//自己包下类的自定义logger实例
//getLogger()参数为xu.enbei包下的类,所以获取到配置文件中xu.enbei的logger实例
//logger实例与rootLogger的日志等级都为INFO,本身实例输出到文件,rootLogger输出到窗口
Logger logger = Logger.getLogger(LogTest.class);
System.out.println(logger.getName());
//打印不同的日志等级
logger.fatal("fatal");
logger.error("error");
logger.warn("warn");
logger.info("info");
logger.debug("debug");
logger.trace("trace")
// org.Apache包下的自定义logger实例,只输出到屏幕(本身实例没有设置logger)
// 本身实例与rootLogger日志等级为error
Logger logger1 = Logger.getLogger(Logger.class);
System.out.println(logger1.getName());
logger1.fatal("fatal logger1");
logger1.error("error logger1");
logger1.warn("warn logger1");
logger1.info("info logger1");
logger1.debug("debug logger1");
logger1.trace("trace logger1");
}
}