log4j 详解

安装

log4j 官网下载相应的 jar 包: 点击直达

或使用 maven 坐标:

1
2
3
4
5
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>

快速开始

首先需要在项目 src 目录下创建文件 log4j.properties :

1
2
3
4
5
6
7
8
log4j.rootLogger = debug, stdout

log4j.appender.stdout = org.apache.log4j.ConsoleAppender

log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern = %c %d{ABSOLUTE} %5p %c{1}:%L - %m%n

输出日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import org.apache.log4j.Logger;

public class Test {
private static Logger logger = Logger.getLogger(Test.class);

public static void main(String[] args) {
// 记录debug级别的信息
logger.debug("This is debug message.");
// 记录info级别的信息
logger.info("This is info message.");
// 记录error级别的信息
logger.error("This is error message.");
}
}

打印结果:

im.zhaojun.Test 19:31:42,793 DEBUG Test:13 - This is debug message.
im.zhaojun.Test 19:31:42,798  INFO Test:15 - This is info message.
im.zhaojun.Test 19:31:42,798 ERROR Test:17 - This is error message.

log4j 配置

Appender

输出方式也称之为输出目的地,Log4j 自带的 appender 类有:

1
2
3
4
5
6
org.apache.log4j.ConsoleAppender(控制台),  
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
org.apache.log4j.jdbc.JDBCAppender(输出到数据库)

配置方式如下:

1
log4j.appender.appenderName=org.apache.log4j.ConsoleAppender

Level

日志信息的优先级从高到低有 OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL,但只建议使用 ERROR、WARN、INFO、DEBUG 四种级别。

Root Level

可以在 log4j.properties 中来配置 Root Level,语法为:

1
log4j.rootLogger = [ level ], appenderName, appenderName, …

[level] 中可填写 info, debug 等级别,它表示所有 appender 的最低输出级别,如填写 info,则所有 appender 中低于 info 级别的日志将不会生效。

Appender Level

每个 Appender 也可以配置 Level,不过这里称为 Threshold :

1
log4j.appender.appenderName.Threshold = [level]

其中 appenderName 为自定义的 appender 名称,[level] 为当前 appender 的最低输出级别。

Logger Level

在程序中通过 logger.setLevel() 来设置当前 Logger 对象输出的最低 Level。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Test {
private static Logger logger = Logger.getLogger(Test.class);

public static void main(String[] args) {
// 设置只输出 INFO 及以上级别的信息
logger.setLevel(Level.INFO);

// 记录debug级别的信息, (这里不会输出)
logger.debug("This is debug message.");
// 记录info级别的信息
logger.info("This is info message.");
// 记录error级别的信息
logger.error("This is error message.");
}
}

不推荐使用,在 Appender 中会配置更加直观。

Level 相互关系

三种 Level 的关系为:Root Level > Appender Level > Logger Level

它们之间可理解为父子关系,父级别会限制子级别的输出内容,

Layout

Log4j 自带的 layout 有:

1
2
3
4
org.apache.log4j.HTMLLayout(以HTML表格形式布局),  
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

配置方式如下:

1
log4j.appender.appenderName.layout=org.apache.log4j.PatternLayout

Logger 实例

Logger类提供了多种方法来处理日志,它提供了两个静态方法获得一个 Logger 对象:

  • public static Logger getRootLogger();
  • public static Logger getLogger(String name);

第一个返回应用程序实例根记录器并没有名字。

第二种方法通过记录器的名称获得。记录器名称是可以传递任何字符串,通常是类或包的名称 ,用于区分不同类的输出,可以在 Layout 中通过 %c 来获取。(也可传入 Class 类型,会自动调用其 getName 方法取得字符串)。

Logger类有专门用于打印日志信息下面的方法如下。

# 方法及描述
1 public void debug(Object message) 这种方法打印使用 Level.DEBUG 消息级别
2 public void error(Object message) 这种方法打印使用 Level.ERROR 消息级别
3 public void fatal(Object message); 这种方法打印使用 Level.FATAL 消息级别
4 public void info(Object message); 这种方法打印使用 Level.INFO 消息级别
5 public void warn(Object message); 这种方法打印使用 Level.WARN 消息级别
6 public void trace(Object message); 这种方法打印使用Level.TRACE消息级别

日志格式化

PatternLayout

最为常用的便是 org.apache.log4j.PatternLayout,它采用类似 C 语言中的 printf 函数的打印格式格式化日志信息。

%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL  
%r 输出自应用启动到输出该log信息耗费的毫秒数  
%c 输出所属的类目,通常就是所在类的全名  
%t 输出产生该日志事件的线程名  
%n 输出一个回车换行符,Windows平台为"rn",Unix平台为"n"  
%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921  
%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)
参数 描述 实例
c Logger 的名字, 即 Logger.getLogger(String name) 创建实例时的 name 值。
允许使用 %c{数字} 输出部分的名字(从右边往左边数)。见实例
%c 将输出 com.log4j.Log4jTest
%c{1}将输出Log4jTest
%c{2}将输出log4j.Log4jTest
%c{3}将输出com.log4j.Log4jTest
C 输出 Logger 所在类的名称。 %C 将输出com.log4j.Log4jTest
%C{1}将输出Log4jTest
%C{2}将输出log4j.Log4jTest
%C{3}将输出com.log4j.Log4jTest
d 输出日期。允许使用%d{yyyy-MM-dd HH:mm:ss}格式化日期。 %d将输出2018-07-28 22:24:25,353
%d{yyyy-MM-dd}将输出2018-07-28
%d{ABSOLUTE}将输出22:24:25,353
F 输出所在的类文件名称 %F将输出Log4jTest.java
l 输出语句所在的行数,包括类名,方法名,文件名,行数等 %l将输出com.log4j.test.Log4jTest.main(Log4jTest.java:50)
L 输出语句所在的行数,只输出数字 %L将输出 50
m 输出日志 输出日志,即log.info(“”), log.debug(“”)的内容
M 输出方法名 %M 将输出main
n 换行符,Windows下输出\r\n,Linux下输出\n 含行
p 输出日志级别(prioriry) DEBUG,INFO,ERROR,FITAL等
r 输出从程序启动到输出该日志之间的时间间隔,单位毫秒 %r将输出300
t 输出当前的线程名称 %t将输出main,Thread-0,Thread-1等
% %%用来输出百分号

需要避免 “C”, “F”, “L”, “M” 等位置信息的记录,原因详见:http://logging.apache.org/log4j/2.x/manual/layouts.html#LocationInformation

Log4j 能输出形形色色的参数, 但参数内容的长度可能不同。如 %C 输出类名,有的类名很长,有的类名很短,会导致日志比较凌乱。为了解决该问题,Log4j允许设置输出内容的长度等,不够的会用空格补上。

设置的方法是在 % 与参数符号间添加数字, 例如 %20p, %-20p等。正数表示右对齐,负数表示左对齐,数字表示最小宽度,不足时用空格补齐。还可以设置最大宽度,如果超出,则截取,方法是用小数点+数字设置,例如 %.30p

%p 为例,所有的调整格式见表:

格式 对齐方式 最小宽度 最大宽度 描述 实例
[%10p] 右对齐 10 正数右对齐,最小宽度 [ ERROR]
[%-10p] 左对齐 10 负数左对齐,最小宽度 [ERROR ]
[%.4p] 4 最大宽度 [RROR]
[%10.20p] 右对齐 10 20 正数右对齐,最大最小宽度 [ ERROR]

日志目的地

控制台

文件

要写日志信息到一个文件中,必须使用 org.apache.log4j.FileAppender。配置参数:

属性 描述
immediateFlush 标志的默认设置为true,这意味着输出流的文件被刷新,在每个追加操作
encoding 它可以使用任何字符编码。默认情况下是特定于平台的编码方案
threshold 这个 appender 阈值级别
File 日志文件的路径,如 d:/test.log
append 默认设置为true,这意味着记录的信息被附加到同一文件的末尾
bufferedIO 此标志表示是否需要写入缓存启用。默认设置为false
bufferSize 如果 bufferedI/O 启用,这表示缓冲区的大小,默认设置为8KB

数据库

log4j API 提供 org.apache.log4j.jdbc.JDBCAppender 对象,它能够将日志信息在指定的数据库,配置参数:

Property 描述
bufferSize 设置缓冲区的大小。默认大小为1
driver 设置驱动程序类为指定的字符串。如果没有指定驱动程序类,默认为sun.jdbc.odbc.JdbcOdbcDriver
layout 设置要使用的布局。默认布局是org.apache.log4j.PatternLayout
password Sets the database password.
sql 指定SQL语句在每次记录事件发生的时间执行。这可能是INSERT,UPDATE或DELETE
URL 设置JDBC URL
user 设置数据库用户名

开始使用基于JDBC日志,要创建在哪里保存日志信息的表。下面是创建日志表的SQL语句:

1
2
3
4
5
6
7
8
CREATE TABLE `logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`),
`date` datetime NOT NULL,
`logger` varchar(50) NOT NULL,
`level` varchar(10) NOT NULL,
`message` varchar(1000) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

以下是将用于将消息记录到一个日志表中的示例配置文件 log4j.properties的JDBCAppender

1
2
3
4
5
6
7
8
9
10
11
log4j.rootLogger = DEBUG, DB

log4j.appender.DB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DB.URL=jdbc:mysql://localhost/dbname
log4j.appender.DB.driver=com.mysql.jdbc.Driver
log4j.appender.DB.user=root
log4j.appender.DB.password=root

log4j.appender.DB.sql=INSERT INTO logs(`date`, `logger`, `level`, `message`)VALUES('%d{yyyy-MM-dd HH:mm:ss}','%C','%p','%m')

log4j.appender.DB.layout=org.apache.log4j.PatternLayout

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
mysql> select * from logs;
+---------------------+-----------------+-------+---------------------------+----+
| date | logger | level | message | id |
+---------------------+-----------------+-------+---------------------------+----+
| 2018-07-28 23:25:40 | im.zhaojun.Test | INFO | This is info message.你好 | 1 |
| 2018-07-28 23:25:40 | im.zhaojun.Test | ERROR | This is error message. | 2 |
| 2018-07-28 23:25:40 | im.zhaojun.Test | INFO | This is info message.你好 | 3 |
| 2018-07-28 23:25:40 | im.zhaojun.Test | ERROR | This is error message. | 4 |
| 2018-07-28 23:25:40 | im.zhaojun.Test | INFO | This is info message.你好 | 5 |
| 2018-07-28 23:25:41 | im.zhaojun.Test | ERROR | This is error message. | 6 |
+---------------------+-----------------+-------+---------------------------+----+
4 rows in set (0.03 sec)