log4j2的简单学习:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
package
com.book.web.controller;
import
org.slf4j.Logger;
import
org.slf4j.LoggerFactory;
//import org.apache.commons.logging.Log;
//import org.apache.commons.logging.LogFactory;
//import org.apache.logging.log4j.LogManager;
//import org.apache.logging.log4j.Logger;
/**
* log4j2测试
* @author liweihan
*
*/
public
class
TestLog4j2Log {
/**
1.
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.5</version>
</dependency>
如果是web环境可以加入:因为会提示:
Log4j appears to be running in a Servlet environment,
but there's no log4j-web module available.
If you want better web container support,
please add the log4j-web JAR to your web archive or server lib directory.
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.2</version>
</dependency>
2.
log4j2与log4j1发生了很大的变化,不兼容。
log4j1仅仅作为一个实际的日志框架,
slf4j、commons-logging作为门面,统一各种日志框架的混乱格局,
现在log4j2也想跳出来充当门面了,也想统一大家了!!
3.log4j2分成2个部分:
log4j-api: 作为日志接口层,用于统一底层日志系统
log4j-core : 作为上述日志接口的实现,是一个实际的日志框架
4.log4j 2.x版本不再支持像1.x中的.properties后缀的文件配置方式,
2.x版本配置文件后缀名只能为”.xml”,”.json”或者”.jsn”。
log4j2默认会在classpath目录下寻找:
<1.>log4j2-test.json 或者log4j2-test.jsn的文件
<2.>log4j2-test.xml的文件.
<3.>log4j2.json 或者log4j2.jsn的文件.
<4.>log4j2.xml的文件.
如果都没有找到,则会按默认配置输出,也就是输出到控制台
5.和log4j1是不同的。此时Logger是log4j-api中定义的接口,而log4j1中的Logger则是类
6.如果要log4j2与commons-logging集成,还需要引入jar包:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jcl</artifactId>
<version>2.2</version>
</dependency>
commons-logging
log4j-api (log4j2的API包)
log4j-core (log4j2的API实现包)
log4j-jcl (log4j2与commons-logging的集成包)
private static Log logger = LogFactory.getLog(TestLog4j2Log.class);
使用commons-logging的Log接口和LogFactory来进行编写,看不到log4j2的影子。
但是这时候含有上述几个jar包,log4j2就与commons-logging集成了起来。
common-logging貌似不支持占位符!
7.如果log4j2与slf4j集成,还需要引入jar包:
<!-- log4j2与slf4j集成 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.5</version>
</dependency>
log4j-slf4j-impl : 用于log4j2与slf4j集成
获取logger的方式:
private static Logger logger=LoggerFactory.getLogger(Log4j2Slf4jTest.class);
*/
// private static final Logger logger = LogManager.getLogger(TestLog4j2Log.class);
// private static Log logger = LogFactory.getLog(TestLog4j2Log.class);
private
static
Logger logger = LoggerFactory.getLogger(TestLog4j2Log.
class
);
public
static
void
main(String[] args) {
if
(logger.isTraceEnabled()) {
logger.trace(
" ===== log4j2 trace meassge"
);
}
if
(logger.isDebugEnabled()) {
logger.debug(
" ===== log4j2 debug message"
);
logger.debug(
" ------ test log4j2:{},{}"
,
"Hello "
,
"HANCHo"
);
}
if
(logger.isInfoEnabled()) {
logger.info(
" ===== log4j2 info message"
);
}
if
(logger.isErrorEnabled()) {
logger.error(
" ===== log4j2 error message "
);
}
//
Object[] params = {
"HAN"
,
1
,
"CHAO"
};
logger.info(
" ===== test:{}, 加班 {} 天, {}要回家了!"
,params);
}
}
|
配置文件:log4j2.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
Configuration
status
=
"info"
monitorInterval
=
"300"
>
<
Properties
>
<
Property
name
=
"log.pattern"
>
<!--%d %-5p [%t] %C{2} (%F:%L) - %m%n-->
%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n
</
Property
>
</
Properties
>
<
Appenders
>
<!-- 控制台 -->
<
Console
name
=
"Console"
target
=
"SYSTEM_OUT"
>
<
ThresholdFilter
level
=
"debug"
/>
<
PatternLayout
pattern
=
"${log.pattern}"
/>
<!-- 本地测试可以用这个
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
-->
<!--
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %class{36} %L %M - %msg%n"/>
-->
<!--
%d{yyyy-MM-dd HH:mm:ss, SSS} : 日志生产时间
%p : 日志输出格式
%c : logger的名称
%m : 日志内容,即 logger.info("message")
%n : 换行符
%C : Java类名
%L : 日志输出所在行数
%M : 日志输出所在方法名
hostName : 本地机器名
hostAddress : 本地ip地址
-->
</
Console
>
<!-- 文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用
append为TRUE表示消息增加到指定文件中,false表示消息覆盖指定的文件内容,默认值是true -->
<
File
name
=
"log"
fileName
=
"./logs/test.log"
append
=
"false"
>
<
PatternLayout
pattern
=
"%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"
/>
</
File
>
<!-- 打印所有的日志到stdout.log文件 -->
<
RollingFile
name
=
"Stdout"
fileName
=
"./logs/stdout.log"
filePattern
=
"./logs/stdout.log.%d{yyyy-MM-dd}-%i"
>
<
PatternLayout
pattern
=
"%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{36} %L %M - %msg%xEx%n"
/>
<
Policies
>
<!-- 基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour。
modulate=true用来调整时间:比如现在是早上3am,interval是4,
那么第一次滚动是在4am,接着是8am,12am...而不是7am.
-->
<!-- 时间触发,一天一个日志 -->
<
TimeBasedTriggeringPolicy
interval
=
"24"
modulate
=
"true"
/>
<!-- 大小触发,达到50M的时候进行分割 -->
<
SizeBasedTriggeringPolicy
size
=
"50 MB"
/>
</
Policies
>
<!-- 用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的 -->
<!-- DefaultRolloverStrategy属性如不设置,
则默认为最多同一文件夹下7个文件,这里设置了20 -->
<
DefaultRolloverStrategy
max
=
"30"
/>
</
RollingFile
>
<!-- 只打印error以及以上级别的日志到stderr.log -->
<
RollingFile
name
=
"Error"
fileName
=
"./logs/stderr.log"
filePattern
=
"./logs/stderr.log.%d{yyyy-MM-dd}-%i"
>
<!-- 控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
<
ThresholdFilter
level
=
"error"
onMatch
=
"ACCEPT"
onMismatch
=
"DENY"
/>
<
PatternLayout
pattern
=
"%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{36} %L %M - %msg%xEx%n"
/>
<
Policies
>
<!-- 时间触发,一天一个日志 -->
<
TimeBasedTriggeringPolicy
interval
=
"24"
modulate
=
"true"
/>
<!-- 大小触发,达到50M的时候进行分割 -->
<
SizeBasedTriggeringPolicy
size
=
"50 MB"
/>
</
Policies
>
<!-- 用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的 -->
<
DefaultRolloverStrategy
max
=
"30"
/>
</
RollingFile
>
</
Appenders
>
<
Loggers
>
<!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
<
Logger
name
=
"org.mybatis"
level
=
"INFO"
></
Logger
>
<
Logger
name
=
"org.springframework"
level
=
"INFO"
></
Logger
>
<
Root
level
=
"debug"
>
<
Appender-ref
ref
=
"Stdout"
/>
<
Appender-ref
ref
=
"Console"
/>
<
Appender-ref
ref
=
"Error"
/>
<!-- just for test temp -->
<
Appender-ref
ref
=
"log"
/>
</
Root
>
</
Loggers
>
</
Configuration
>
|
1
|
===============================================================================
|
一、Configuration
有两个属性:status和monitorinterval,有两个子节点:Appenders和Loggers(表明可以定义多个Appender和Logger).
status : 用来指定log4j本身的打印日志的级别.
monitorinterval : 用于指定log4j自动重新配置的监测间隔时间,单位是s,最小是5s.
二、Appenders节点
常见的有三种子节点:Console、RollingFile、File.
1.Console: Console节点用来定义输出到控制台的Appender.
name:指定Appender的名字.
target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT.
PatternLayout:输出格式,不设置默认为:%m%n.
2.File: File节点用来定义输出到指定位置的文件的Appender.
name:指定Appender的名字.
fileName:指定输出日志的目的文件带全路径的文件名.
PatternLayout:输出格式,不设置默认为:%m%n.
3.RollingFile: RollingFile节点用来定义超过指定大小自动删除旧的创建新的的Appender.
name:指定Appender的名字.
fileName:指定输出日志的目的文件带全路径的文件名.
PatternLayout:输出格式,不设置默认为:%m%n.
filePattern:指定新建日志文件的名称格式.
Policies:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志.
TimeBasedTriggeringPolicy:Policies子节点,基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour。modulate=true用来调整时间:比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am…而不是7am.
SizeBasedTriggeringPolicy:Policies子节点,基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小.
DefaultRolloverStrategy:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max)
三、Loggers节点
常见子节点的有两种:Root和Logger.
1.Root:
Root节点用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出
level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
AppenderRef:Root的子节点,用来指定该日志输出到哪个Appender.
2.Logger:
Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。
level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
name:用来指定该Logger所适用的类或者类所在的包全路径,继承自Root节点.
AppenderRef:Logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root.如果指定了,那么会在指定的这个Appender和Root的Appender中都会输出,此时我们可以设置Logger的additivity=”false”只在自定义的Appender中进行输出。
四、关于日志level
共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
All:最低等级的,用于打开所有日志记录.
Trace:是追踪,就是程序推进以下,你就可以写个trace输出,所以trace应该会特别多,不过没关系,我们可以设置最低日志级别不让他输出.
Debug:指出细粒度信息事件对调试应用程序是非常有帮助的.
Info:消息在粗粒度级别上突出强调应用程序的运行过程.
Warn:输出警告及warn以下级别的日志.
Error:输出错误信息日志.
Fatal:输出每个严重的错误事件将会导致应用程序的退出的日志.
OFF:最高等级的,用于关闭所有日志记录.
程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少
五、参考
log4j2:
http://blog.csdn.net/vergilgeekopen/article/details/61417342
http://www.cnblogs.com/hanfight/p/5721855.html
性能对比:
https://my.oschina.net/OutOfMemory/blog/789267
http://blog.csdn.net/yjh1271845364/article/details/70888262
其他日志系统了解:
http://blog.csdn.net/xudan1010/article/details/52890102
http://www.cnblogs.com/Leo_wl/p/3417215.html
https://my.oschina.net/pingpangkuangmo/blog/406618
六、遇到的一个问题
日志突然不打印了。查看日志,发现log4j2本身的日志显示:在加载log4j2.xml文件时发生错误。
log4j2使用自己默认的log4j2的配置,只能打印error日志。
默认配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
Configuration
status
=
"WARN"
>
<
Appenders
>
<
Console
name
=
"Console"
target
=
"SYSTEM_OUT"
>
<
PatternLayout
pattern
=
"%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"
/>
</
Console
>
</
Appenders
>
<
Loggers
>
<
Root
level
=
"error"
>
<
AppenderRef
ref
=
"Console"
/>
</
Root
>
</
Loggers
>
</
Configuration
>
|
分析原因:
本文转自韩立伟 51CTO博客,原文链接:http://blog.51cto.com/hanchaohan/1954000,如需转载请自行联系原作者