Log4j

​ Log4j是Apache的- -个开放源代码项目,通过使用Log4j,可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器等;也可以控制每- - 条日志的输出格式;通过定义每一条日志信息的级别,能够更加细致地控制日志的生成过程。这些可以通过一一个配置文件来灵活地进行配置,而不需要修改应用的代码。

一句话: 以什么样的格式,按照日志的优先级,将日志输出到哪?

  • 目的地[ appender ]
  • 布局[ layout ]
  • 控制单元[ logger ]
  • 级别[ level ]

1. 常见Appender, 前3个常用

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 (把日志用JDBC记录到数据库中)

2. 常见Layout

  • 布局就是指输出信息的格試。在Log4j中称作Layout

org.apache.log4j.HTMLLayout (以HTML表格形式布局),

org.apache.log4j.PatternLayout (可以灵活地指定布局模式),

org.apache.log4j.SimpleLayout ( 包含日志信息的级别和信息字符串),

org.apache.log4j.TTCCLayout (包含日志产生的时间、线程、类别等等信息)

常用Patternlayout

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
%m输出代码中指定的消息
%p输出优先级,即DEBUG,INFO, WARN,ERROR, FATAL
%r输出自应用启动到输出该log信息耗费的毫秒数
%c输出所属的类目,通常就是所在类的全名.
%t输出产生该日志事件的线程名
%n输出一个回车换行符,Windows平台为"\r\n",Unix平台为"\n"
%d输出日志时间点的日期或时间,默认格式为IS08601,也可以在其后指定格式,
%r - 程序启动到现在的毫秒数
%t - 当前线程名
%l - 输出日志事件的发生位置, 同 %F%L%C%M
%F - java 源文件名
%L - java 源码行数
%C - java 类名,%C{1} 输出最后一个元素
%M - java 方法名
比如: %d{yyyy-MM-dd HH:mm:ss,SSS},输出类似: 2015-12-20 18:35:51,768

个人喜欢的日志输出格式

%d{yyyy-MM-dd HH:mm:ss,SSS} %5p (method:%l) - %m%n

3. 案例

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.zzxx.dao;

import org.apache.log4j.Logger;
public class UserDao {
public static final Logger logger = Logger.getLogger(UserDao.class);

public static void main(String[] args) {
logger.debug("hello----debug");
logger.info("hello----info");
logger.warn("hello----warn");
logger.error("hello----error");
}
}

lo4j.properties

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


# 每日滚动更新一个日志文件 File 输出为文件
log4j.appender.zzxx.File=org.apache.log4j.DailyRollingFileAppender
# 日志输出的位置
log4j.appender.zzxx.File.file=d:\\log4j\\log4j.log
# 每日滚动更新一个日志文件的后缀
log4j.appender.zzxx.File.DatePattern=.yyyy-MM-dd
# layout日志输出的样式 布局 PatternLayout自定义
log4j.appender.zzxx.File.layout=org.apache.log4j.PatternLayout
# 自定义输出的 layout %d 表示date %5p:p是优先级 %5为5位置INFO不够也会默认一个空格 对其 %C 包名+类名 %M 类中的某个方法 %m:message %n:回车
log4j.appender.zzxx.File.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p (%C:%M) - %m%n

# Console 输出控制台
log4j.appender.zzxx.Console=org.apache.log4j.ConsoleAppender
# layout日志输出的样式 布局 PatternLayout自定义
log4j.appender.zzxx.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.zzxx.Console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p (%C:%M) - %m%n

# Logger控制单元 如果没有指定 默认 rootLogger debug默认 debug 级别 zzxx.File 输出到文件 zzxx.Console输出到控制台
log4j.rootLogger=debug,zzxx.File,zzxx.Console

修改logger1

1
2
log4j.rootLogger=error,zzxx.File,zzxx.Console
log4j.logger.com.zzxx=debug,zzxx.File,zzxx.Console

修改logger2

1
2
log4j.rootLogger=debug,zzxx.File,zzxx.Console
log4j.logger.com.zzxx=error,zzxx.File,zzxx.Console

修改logger3

1
2
3
log4j.rootLogger=error,zzxx.File,zzxx.Console
log4j.logger.com.zzxx=info,zzxx.File,zzxx.Console
log4j.logger.com.zzxx.dao=debug,zzxx.File,zzxx.Console

image-20220225215609930

修改logger4

1
2
3
log4j.rootLogger=error,zzxx.File,zzxx.Console
log4j.logger.com.zzxx=warn,zzxx.File,zzxx.Console
log4j.logger.com.zzxx.dao=info,zzxx.File,zzxx.Console

修改logger5

1
2
3
log4j.rootLogger=error,zzxx.File
log4j.logger.com.zzxx=warn,zzxx.Console
log4j.logger.com.zzxx.dao=info,zzxx.File,zzxx.Console

结论

级别取精确,输出为各自

我们打印的是 com.zzxx.dao.UserDao 这个类下的,级别取精确是 com.zzxx.dao> com.zzxx > root(默认)

输出为各自 各自配置的输出到哪里,如果都配置了控制台,都会输出到控制台。

4. Appender、Layout、 Logger三者之 间的关系

  • 每个appender后面必然需要跟随layout,指定自己的风格样式
  • 每个Logger都可以指定一- 个级别,同时引用多个Appender
  • 每个Appender也同时可以被多个Logger引用

log4j.xmI优先于log4j.properties

5. 常用的几个log配置

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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//log4j/log4j Configuration//EN" "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

<!-- 日志输出到控制台 -->
<appender name="log.console" class="org.apache.log4j.ConsoleAppender">
<!-- 日志输出格式 -->
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} %5p (method:%l) - %m%n"/>
</layout>

<!--过滤器设置输出的级别-->
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<!-- 设置日志输出的最小级别 -->
<param name="levelMin" value="INFO"/>
<!-- 设置日志输出的最大级别 -->
<param name="levelMax" value="ERROR"/>
<param name="AcceptOnMatch" value="true"/>
</filter>
</appender>


<!-- 输出日志到文件 -->
<!-- 日志输出到文件,可以配置多久产生一个新的日志信息文件 -->
<appender name="log.file" class="org.apache.log4j.DailyRollingFileAppender">
<!-- 文件文件全路径名 -->
<param name="File" value="/data/logs/dailyRollingAppender.log"/>
<param name="Append" value="true" />
<!-- 设置日志备份频率,默认:为每天一个日志文件 -->
<param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />
<!--每分钟一个备份-->
<!--<param name="DatePattern" value="'.'yyyy-MM-dd-HH-mm'.log'" />-->

<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} %5p (method:%l) - %m%n"/>
</layout>
</appender>

<!--
1. 指定logger的设置,additivity是否遵循缺省的继承机制(停止日志的传播机制)
2. 当additivity="false"时,root中的配置就失灵了,不遵循缺省的继承机制
3. 代码中使用Logger.getLogger("logTest")获得此输出器,且不会使用根输出器
-->
<logger name="com.zzxx" additivity="false">
<level value ="INFO"/>
<appender-ref ref="log.console"/>
<appender-ref ref="log.file"/>
</logger>

<logger name="com.zzxx.dao" additivity="false">
<level value ="DEBUG"/>
<appender-ref ref="log.console"/>
<appender-ref ref="log.file"/>
</logger>
<!-- 根logger的设置,若代码中未找到指定的logger,则会根据继承机制,使用根logger-->
<root>
<level value="debug"/>
<appender-ref ref="log.console"/>
<appender-ref ref="log.file"/>
</root>

</log4j:configuration>
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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration>

<!-- 将日志信息输出到控制台 -->
<appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
<!-- 设置日志输出的样式 -->
<layout class="org.apache.log4j.PatternLayout">
<!-- 设置日志输出的格式 -->
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%-5p] [method:%l]%n%m%n%n" />
</layout>
<!--过滤器设置输出的级别-->
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<!-- 设置日志输出的最小级别 -->
<param name="levelMin" value="WARN" />
<!-- 设置日志输出的最大级别 -->
<param name="levelMax" value="ERROR" />
<!-- 设置日志输出的xxx,默认是false -->
<param name="AcceptOnMatch" value="true" />
</filter>
</appender>

<!-- 将日志信息输出到文件,但是当文件的大小达到某个阈值的时候,日志文件会自动回滚 -->
<appender name="RollingFileAppender" class="org.apache.log4j.RollingFileAppender">
<!-- 设置日志信息输出文件全路径名 -->
<param name="File" value="D:/log4j/RollingFileAppender.log" />
<!-- 设置是否在重新启动服务时,在原有日志的基础添加新日志 -->
<param name="Append" value="true" />
<!-- 设置保存备份回滚日志的最大个数 -->
<param name="MaxBackupIndex" value="10" />
<!-- 设置当日志文件达到此阈值的时候自动回滚,单位可以是KB,MB,GB,默认单位是KB -->
<param name="MaxFileSize" value="100MB" />
<!-- 设置日志输出的样式 -->
<layout class="org.apache.log4j.PatternLayout">
<!-- 设置日志输出的格式 -->
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%-5p] [method:%l]%n%m%n%n" />
</layout>
</appender>

<!-- 将日志信息输出到文件,可以配置多久产生一个新的日志信息文件 -->
<appender name="DailyRollingFileAppender" class="org.apache.log4j.DailyRollingFileAppender">
<!-- 设置日志信息输出文件全路径名 -->
<param name="File" value="D:/log4j/DailyRollingFileAppender.log" />
<!-- 设置日志每天回滚一次,即产生一个新的日志文件 -->
<param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />
<!-- 设置日志输出的样式 -->
<layout class="org.apache.log4j.PatternLayout">
<!-- 设置日志输出的格式 -->
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%-5p] [method:%l]%n%m%n%n" />
</layout>
</appender>


<!--
注意:
1:当additivity="false"时,root中的配置就失灵了,不遵循缺省的继承机制
2:logger中的name非常重要,它代表记录器的包的形式,有一定的包含关系,试验表明
2-1:当定义的logger的name同名时,只有最后的那一个才能正确的打印日志
2-2:当对应的logger含有包含关系时,比如:name=test.log4j.test8 和 name=test.log4j.test8.UseLog4j,则2-1的情况是一样的
2-3:logger的name表示所有的包含在此名的所有记录器都遵循同样的配置,name的值中的包含关系是指记录器的名称哟!注意啦!
3:logger中定义的level和appender中的filter定义的level的区间取交集
4:如果appender中的filter定义的 levelMin > levelMax ,则打印不出日志信息
-->

<!-- 指定logger的设置,additivity指示是否遵循缺省的继承机制-->
<logger name="test.log4j.test8.UseLog4j" additivity="false">
<level value ="WARN"/>
<appender-ref ref="DailyRollingFileAppender"/>
</logger>

<!--指定logger的设置,additivity指示是否遵循缺省的继承机制 -->
<logger name="test.log4j.test8.UseLog4j_" additivity="false">
<level value ="ERROR"/>
<appender-ref ref="RollingFileAppender"/>
</logger>

<!-- 根logger的设置-->
<root>
<level value ="INFO"/>
<appender-ref ref="ConsoleAppender"/>
<appender-ref ref="DailyRollingFileAppender"/>
</root>

</log4j:configuration>
  • logback.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
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="/tmp/logs" />
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/yida-sync.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>100MB</MaxFileSize>
</triggeringPolicy>
</appender>

<!-- 日志输出级别 -->
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>

<logger name="com.actionsoft" level="debug"/>
</configuration>