Log4j2是Log4j的升级版,相比其前身Log4j 1.x提供了显著的改进,并提供了在Logback中提供的许多改进,同时修复了Logback体系结构中的一些固有问题。
Log4j2的内容很多,本文主要介绍其简单实用方法;文中所使用到的软件版本:Java 1.8.0_191、log4j 2.12.1。
1、配置
1.1、加载配置
Log4j2能够在初始化期间自动查找配置文件进行配置;按照优先级查找配置文件直到找到,优先级如下:
1、查找系统属性log4j.configurationFile对应的配置文件
2、在classpath下查找log4j2-test.properties
3、在classpath下查找log4j2-test.yaml或者log4j2-test.yml
4、在classpath下查找log4j2-test.json或者log4j2-test.jsn
5、在classpath下查找log4j2-test.xml
6、在classpath下查找log4j2.yaml或者log4j2.yml
7、在classpath下查找log4j2.json或者log4j2.jsn
8、在classpath下查找log4j2.xml
9、如果上面的步骤都找不到配置文件,则使用默认的配置,日志会输出到控制台。
1.2、自动更新配置
如果配置是从配置文件加载的,通过设置monitorInterval(单位为秒)参数,可以让log4j2自动检查文件的变化情况,如果变化了则从新加载配置。检查文件是否变化的时机为记录日志时且距离上次检查时间超过monitorInterval。
...
2、Appenders
2.1、ConsoleAppender
输出日志到控制台,有如下常用参数:
filter 过滤器
layout 布局器
name 输出目的地名称
target SYSTEM_OUT或SYSTEM_ERR;默认为SYSTEM_OUT。
2.2、FileAppender
输出日志到文件,有如下常用参数:
filter 过滤器
fileName 文件名称
layout 布局器
name 输出目的地名称
2.3、RollingFileAppender
滚动输出日志到文件,通过一定的策略来生成历史日志文件,并保留固定数量的最新历史文件;有如下常用参数:
filter 过滤器
fileName 文件名称
filePattern 历史日志文件名称生成策略,支持日期格式配置:$${date:yyyy-MM}、%d{MM-dd-yyyy};序号配置:%i
layout 布局器
name 输出目的地名称
policy 历史日志文件生成策略
DefaultRolloverStrategy 默认策略
2.3.1、policy
有如下策略:
OnStartupTriggeringPolicy,启动的时候就生成历史日志文件,其参数:
minSize 日志文件大于该值,启动时会生成历史日志文件;默认为1,防止空的日志文件生成历史日志文件
SizeBasedTriggeringPolicy,日志文件达到多大时就会生成历史日志文件,其参数:
size 日志文件大小
TimeBasedTriggeringPolicy,根据时间间隔来生成历史日志文件,其参数:
interval 生成新的历史日志文件的时间间隔,单位为小时,默认为1
modulate 是否应调整间隔,如间隔为4小时,当前时间为3点,则生成历史日志文件的时间点为4点、8点...
maxRandomDelay 随机延迟生成历史日志文件的最大秒数,默认为0;如果服务器上有多个应用程序且配置的滚动日志文件时间端一样,则此设置非常有用,可以将负载分散到不同时间。
SizeBasedTriggeringPolicy和TimeBasedTriggeringPolicy如果一起使用,则filePattern中需指定%i,否则会覆盖原有历史日志文件,因为SizeBasedTriggeringPolicy策略起作用时不会改变文件名中的时间戳。
2.3.2、DefaultRolloverStrategy
有如下常用参数:
max 最大历史日志文件个数
还有其他好多Appender,如JDBCAppender、JMS Appender、JPAAppender、KafkaAppender等等,这里就不一一介绍,可以参考官网文档:https://logging.apache.org/log4j/2.x/manual/appenders.html
3、Layouts
log4j2提供了多种layout,如HTML Layout、JSON Layout、Pattern Layout、XML Layout等等,这里着重介绍Pattern Layout。
Log4J2通过参数来格式化日志信息,这与log4j 1.x很类似:
d{pattern}、date{pattern} 输出日志记录事件的日期,可以在其后指定格式;如:%d{dd MMM yyyy HH:mm:ss,SSS},输出类似:02 Nov 2012 14:34:02,781
p|level{level=label, level=label, ...}、p|level{length=n}、p|level{lowerCase=true|false} 输出日志记录事件的优先级,如:%level{WARN=W, INFO=I,length=2}
t、tn、thread、threadName 输出生成日志记录事件的线程的名称
T、id、threadId 输出生成日志记录事件的线程的id
c{precision}、logger{precision} 输出日志记录事件的类别;后面可以给出精度,如类别为"org.apache.commons.Foo";%c{1}将输出"Foo",%c{1.}将输出"o.a.c.Foo"
C{precision}、class{precision} 输出发出日志记录请求的调用方的完全限定类名称;后面可以给出精度,与c{precision}类似。
M、method 输出发出日志记录请求的方法名称。该操作代价较高,可能会影响性,小心使用。
F、file 输出发出日志记录请求的文件名。该操作代价较高,可能会影响性,小心使用。
L、line 输出发出日志记录请求的文件行号。该操作代价较高,可能会影响性,小心使用。
m{nolookups}{ansi}、msg{nolookups}{ansi}、message{nolookups}{ansi} 输出应用程序提供的消息
n 输出与平台相关的行分隔符,Windows平台为\r\n,Unix平台为\n
x、NDC 输出与生成日志记录事件的线程关联的NDC(嵌套诊断上下文)
X{key[,key2...]}、mdc{key[,key2...]}、MDC{key[,key2...]} 用于输出与生成日志记录事件的线程关联的MDC(映射诊断上下文)。通常用于多个客户端连接同一台服务器,方便服务器区分是哪个客户端访问留下来的日志。如%X{5}将记录代号为5的客户端的日志
默认情况下,相关信息会全部输出;可以借助格式修改器,更改最小字段宽度、最大字段宽度和对齐方向。格式修改器放置在百分比符号和转换字符之间。
%20c 如果类别名称少于20个字符,则用空格左垫。
%-20c 如果类别名称少于20个字符,则用空格右垫。
%.30c 如果类别名称长于30个字符,则从左开始截取掉多余的字符。
%20.30c 如果类别名称少于20个字符,则用空格左垫;如果类别名称长于30个字符,则从左开始截取掉多余的字符。
%-20.30c 如果类别名称少于20个字符,则用空格右垫;如果类别名称长于30个字符,则从左开始截取掉多余的字符。
更多相关说明参见 https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout
4、Lookups
lookup的主要功能就是提供另外一种方式以添加某些特殊的值到日志中。
4.1、Date Lookup
获取当前日期的值,使用SimpleDateFormat验证格式是否有效;如获取当前日期月份:$${date:yyyy-MM}
4.2、Environment Lookup
获取环境变量的值;如获取$PATH变量的值:$${env:PATH}
4.3、Java Lookup
获取Java环境信息相关的值;如获取java运行时:${java:runtime}
4.4、System Properties Lookup
获取系统属性相关的值;如获取系统文件编码:${sys:file.encoding}
还有其他好多Lookup,如Context Map Lookup、Jndi Lookup、Spring Boot Lookup等等,这里就不一一介绍,可以参考官网文档:https://logging.apache.org/log4j/2.x/manual/lookups.html。
5、Filters
Filters用来确定日志是否被输出。过滤器包含两个基本参数,onMatch:配置过滤器时执行的动作,onMismatch:不配置过滤器时执行的动作;这两个参数的值可以为: ACCEPT、DENY 或NEUTRAL。ACCEPT表示输出日志;DENY表示不输出日志;NEUTRAL一般用于多个过滤器中,表示执行下一个过滤器。
在多个过滤器一起使用时,如果一个过滤器配置为onMatch="ACCEPT",并且日志消息满足onMatch,则输出该日志消息并忽略后面的过滤器;如果一个过滤器配置为onMatch="DENY",并且日志消息满足onMatch,则不输出该日志消息并忽略后面的过滤器;如果一个过滤器配置为onMatch="NEUTRAL",并且日志消息满足onMatch,则继续执行后面的过滤器。
5.1、RegexFilter
通过java正则表达式来与日志消息来比较,判断是否过滤。
5.2、ThresholdFilter
通过日志级别来判断是否过滤
5.3、TimeFilter
通过时间来判断是否过滤
5.4、CompositeFilter
组合过滤器,通过组合其他的过滤器来组成一个过滤链。
还有其他各种Filter,如BurstFilter、MarkerFilter等等,这里就不一一介绍,可以参考官网文档:https://logging.apache.org/log4j/2.x/manual/filters.html。
6、实际使用
6.1、配置文件log4j2.xml
该文件放到src/log4j2.xml或src/main/resources(spring boot工程)下即可。
xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN" strict="true" monitorInterval="30"> <Appenders> <Console name="STDOUT"> <PatternLayout pattern="%d %p [%t] %C.%M[%F:%L] -> %m%n" /> <Filters> <RegexFilter regex="This.*" onMatch="NEUTRAL" onMismatch="DENY"/> <ThresholdFilter level="INFO" onMatch="NEUTRAL" onMismatch="DENY"/> <TimeFilter start="05:00:00" end="17:30:00" onMatch="NEUTRAL" onMismatch="DENY"/> Filters> Console> <File name="File" fileName="D:\temp\a.log"> <PatternLayout pattern="%d %-p [%t] %C.%M[%F:%L] -> %m%n" /> File> <File name="lookupTest" fileName="D:\temp\lookup.log"> <PatternLayout pattern="$${date:yyyy-MM} $${env:PATH} ${java:runtime} ${sys:file.encoding} %d -> %m%n" /> File> <RollingFile name="RollingFile" fileName="D:\temp\b.log" filePattern="D:\temp\$${date:yyyy-MM}\b-%d{MM-dd-yyyy}-%i.log"> <PatternLayout pattern="%d %-p [%t] %C.%M[%F:%L] -> %m%n" /> <Policies> <OnStartupTriggeringPolicy /> <SizeBasedTriggeringPolicy size="200KB" /> <TimeBasedTriggeringPolicy /> Policies> <DefaultRolloverStrategy max="5"/> RollingFile> Appenders> <Loggers> <Root level="info"> <AppenderRef ref="STDOUT" /> <AppenderRef ref="File" /> <AppenderRef ref="lookupTest" /> <AppenderRef ref="RollingFile" /> Root> Loggers> Configuration>
6.2、代码例子
package com.inspur.demo.log; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** * log4j2使用示例 */ public class Log4j2Case { private static Logger logger = LogManager.getLogger(Log4j2Case.class); public static void main(String[] args) throws Exception { logger.debug("This is debug message."); logger.warn(logger.getClass()); for (int i = 0; i < 100; i++) { logger.info("This is info message:" + i); } } }
运行代码可以看到控制台及相关的文件中生成了日志消息。