一、Log4j2简介
Apache Log4j 2 是对Log4j的升级,它比其前身Log4j 1.x提供了重大改进,并参考了Logback中优秀的设计,同时修复了Logback架构中的一些问题。被誉为是目前最优秀的Java日志框架;企业中通常使用SLF4j门面+Log4j2来记录日志*、
异常处理:在logback中,Appender中的异常不会被应用感知到,但是在log4j2中,提供了一些异常处理机制。 性能提升:log4j2相较于log4j和logback都具有很明显的性能提升,在多线程方案中,异步记录器的吞吐量比Log4j 1.x和Logback高10倍
自动重载配置:参考了logback的设计,当然会提供自动刷新参数配置,最实用的就是我们在生产上可以动态的修改日志的级别而不需要重启应用
无垃圾机制:log4j2在大部分情况下,都可以使用其设计的一套无垃圾机制,避免频繁的日志收集导致的jvm gc。
支持自定义日志级别:可以在代码或配置中定义自定义日志级别。
二、Log4j2入门案例
目前市面上最主流的日志门面就是SLF4J,虽然Log4j2也是日志门面,但是它的日志实现功能非常强大,性能优越。所以大家一般还是将Log4j2看作是日志的实现,Slf4j + Log4j2应该是未来的大势所趋。不过在学习中我将使用纯Log4j2,后面介绍SLF4J + Log4j2
<!--Log4j2自带的日志门面-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.1</version>
</dependency>
<!--Log4j2具体的日志实现-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version>
</dependency>
@Test
public void demoA() {
//import org.apache.logging.log4j.LogManager; Log4j2的日志管理器
//import org.apache.logging.log4j.Logger; Log4j2的日志记录器
//通过日志管理器获取Logger对象
Logger logger = LogManager.getLogger(Log4j2Demo.class);
//打印日志
logger.fatal(" 严重错误,一般造成系统崩溃并终止运行");
logger.error(" 错误信息,不会影响系统运行"); //默认级别
logger.warn(" 警告信息,可能会发生问题");
logger.info(" 运行信息,数据连接,网络连接,IO操作等");
logger.debug(" 调试信息,一般在开发中使用,记录程序变量传递信息等等");
logger.trace(" 追踪信息,记录程序所有的流程信息");
}
//打印记录
//11:12:55.378 [main] FATAL cn.xw.Log4j2Demo - 严重错误,一般造成系统崩溃并终止运行
//11:12:55.384 [main] ERROR cn.xw.Log4j2Demo - 错误信息,不会影响系统运行
从上面案例来看,即使不指定Log4j2的配置文件也可以进行日志的打印(这一点就比Log4j 1.x好),带有默认的日志配置;
下面我将带大家详细说明配置文件,因为它才是重点,以上面的入门案例的Java来进行测试!!
<?xml version="1.0" encoding="UTF-8" ?>
<!--monitorInterval属性值(秒数)为一个非零值来让Log4j每隔指定的秒数来重新读取配置文件,可以用来动态应用Log4j配置-->
<Configuration status="debug" monitorInterval="30">
<!--用来自定义一些变量-->
<Properties>
<!--变量定义-->
<Property name="myPattern" value="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
<Property name="dir_url">d:/logs</Property>
</Properties>
<!--使用Appenders元素可以将日志事件数据写到各种目标位置-->
<Appenders>
<!-- 默认打印到控制台 -->
<Console name="ConsoleAppend" target="SYSTEM_OUT">
<!-- 默认打印格式 -->
<PatternLayout pattern="${myPattern}"/>
</Console>
<!-- 打印到日志文件上 -->
<File name="FileAppend" fileName="${dir_url}/fileLog.log" bufferedIO="true" immediateFlush="true">
<PatternLayout>
<pattern>${myPattern}</pattern>
</PatternLayout>
</File>
</Appenders>
<!--定义logger,只有定义了logger并引入的appender,appender才会生效-->
<Loggers>
<!-- 默认打印日志级别为 error -->
<Root level="INFO">
<AppenderRef ref="ConsoleAppend"/>
<AppenderRef ref="FileAppend"/>
</Root>
</Loggers>
</Configuration>
三、Log4j2常用标签
Configuration元素配置
Configuration元素可以使用以下属性:
advertiser:
可选的Advertiser插件名,用来通知个别FileAppender或SocketAppender的配置。目前唯一可用Advertiser名为"multicastdns"
dest:
err(将输出到stderr上)或一个文件路径或一个URL;
monitorInterval:
检查配置文件是否有更新的间隔秒数;
name:
配置的名称;
packages:
逗号分隔的用于搜索插件的包名列表。插件只会被每个类加载器加载一次,所以仅重新配置该项不会生效;
schema:
为类加载器定位XML Schema位置以验证配置。仅当strict属性设置为true时该属性才有效,如果不设置该属性,则不会验证Schema
shutdownHook:
设置当 JVM 关闭时 log4j 是否也自动关闭。默认是启用的,也可以设置该属性为 disable 来禁用该关闭钩子;
shutdownTimeout:
设置当 JVM 关闭后 Appender 和后台任务超时多少毫秒才关闭。默认为0,表示每个Appender使用其默认的超时,不等待后台任务。
这仅是个提示,而不能保证关闭进程不会花费更长的时间。将该值设置过小可能增加日志事件在还未输出到最终位置之前就丢失的风险。
如果 shutdownHook 属性未设置,那么将不会使用该属性;
status:
应该打印到控制台的内部 Log4j 日志事件的级别,可设置的值有 trace、debug、info、warn、error 和 fatal,Log4j 将会打
印出内部初始化等事件的详细信息(在发现配置文件之后)。设置该属性为 trace 是查找 Log4j 故障的第一手工具。也可以通过设
置 log4j2.debug 系统属性来输出 Log4j 内部日志,包括配置文件加载前的内部日志(从 log4j 2.9 开始)
strict:
使用严格的 XML 格式, JSON 格式的配置文件不支持该属性
verbose:
加载插件时是否显示诊断信息
Appenders元素配置
Log4j使用Appender将日志事件数据写到各种目标位置(目前可以为控制台、文件、多种数据库 API、远程套接字服务器、Apache Flume、JMS、远程 UNIX Syslog daemon)。
在大多数情况下,Appender将格式化事件的责任委托给Layout。一些Appender包装其它Appender,以便它们可以修改LogEvent、处理Appender中的失败、根据高级筛选条件将事件路由到下级Appender,或者提供不直接格式化事件的类似功能。
Appender可以通过特定的Appender插件名或appender元素(带有指定Appender插件名的type属性)来配置。另外每个Appender都必须要有一个name属性,用来指定一个去别区其它Appender的唯一标识,该标识的值在Logger中通过AppenderRef来引用,从而将该Appender配置到该 Logger 中。
每个Appender都必须实现Appender接口,多数Appender都扩展自AbstractAppender,该抽象类添加了Lifecycle和Filterable支持。Lifecycle可以对日志组件在配置加载后进行初始化和在关闭时进行清理等操作。Filterable可以让日志组件绑定用于处理日志事件的过滤器。代表不同目标位置的各种Appender也具有其功能所需的其他属性和子元素。这里选择常用的Appender加以介绍。
ConsoleAppender控制台输出
ConsoleAppender会将输出写入System.out(默认目标位置)或 System.err 中。必须提供一个 Layout 来格式化LogEvent
参数名(类型):介绍说明
filter(Filter):
指定一个过滤器来决定是否将日志事件传递给Appender处理。可以指定为一个CompositeFilter来使用多个过滤器。
layout(Layout):
指定格式化LogEvent的Layout。如果没有指定Layout,则默认使用 %m%n 格式。
follow(boolean):
在配置好之后,是否可以通过System.setOut或System.setErr来重新指定输出位置为System.out或System.err。
不能在 Windows 下用于Jansi,也不能和direct属性一起使用。
direct(boolean):
绕开java.lang.System.out/.err直接写入java.io.FileDescriptor。当输出重定向到文件或其他目标时可以
节约10倍的性能消耗。不能在Windows下用于 Jansi,也性不能和 follow 属性一起使用。在多线程应用中,
输出不会遵循 java.lang.System.setOut()/.setErr() ,而是可能会和其他输出纠缠在一起输出到
java.lang.System.out/.err。该属性是 2.6.2 版本新增的,目前仅在Linux和Windows下的Oracle JVM环境中测试过。
name(String):
必选的 Appender 的名称,表示区别于其他Appender的唯一标识。
ignoreExceptions(boolean):
默认为 true,表示当输出事件时出现的异常将会被内部记录而忽略。 当设置为 false 时,则会将异常传播给调用者。
当将该Appender包装成FailoverAppender时,必须设置为 false。
target(String):
SYSTEM_OUT 或 SYSTEM_ERR。默认为 SYSTEM_OUT。
<?xml version="1.0" encoding="UTF-8" ?>
<Configuration status="error" monitorInterval="30">
<Properties>
<Property name="myPattern" value="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Properties>
<Appenders>
<Console name="ConsoleAppend" target="SYSTEM_ERR">
<PatternLayout pattern="${myPattern}"/>
</Console>
</Appenders>
<Loggers>
<Root level="WARN">
<AppenderRef ref="ConsoleAppend"/>
</Root>
</Loggers>
</Configuration>
<!--日志输出-->
16:42:41.556 [main] FATAL cn.xw.Log4j2Demo - 严重错误,一般造成系统崩溃并终止运行
16:42:41.559 [main] ERROR cn.xw.Log4j2Demo - 错误信息,不会影响系统运行
16:42:41.559 [main] WARN cn.xw.Log4j2Demo - 警告信息,可能会发生问题
RollingFileAppender文件输出
RollingFileAppender是一个OutputStreamAppender,可以根据TriggeringPolicy和RolloverPolicy将文件切割归档,通过RollingFileManager(扩展了OutputStreamManager)来实际执行文件I / O并执行归档。参数如下:
触发器
TriggeringPolicy
TriggeringPolicy是控制日志文件归档的触发条件。总共有四种类型的TriggeringPolicy,可以组合(CompositeTriggeringPolicy)多种触发策略来控制归档,标签为,如果配置了多种策略,则只要有一种策略返回true,就返回true。
<Policies>
<!-- <CronTriggeringPolicy schedule="0 0 * * * ?"/> -->
<OnStartupTriggeringPolicy minSize="2" />
<SizeBasedTriggeringPolicy size="20 MB" />
<TimeBasedTriggeringPolicy />
</Policies>
四种类型如下:
OnStartupTriggeringPolicy
如果日志文件的时间比JVM的启动时间早,或者达到minSize的值,则会触发归档。
minSize:触发文件归档的最小值,默认为1。
SizeBasedTriggeringPolicy
当文件达到指定大小后,触发归档。大小可以通过size指定,单位为KB、MB、GB。与TimeBasedTriggeringPolicy配合使用时,filePattern中必须包含%i,否则文件每次归档时都会覆盖当前文件,因为TimeBasedTriggeringPolicy不会让文件名中的时间戳改变。如果不使用TimeBasedTriggeringPolicy,则SizeBasedTriggeringPolicy会让时间戳改变。
注意,配置的size,实际生成的文件并不严格按照此大小,一般回略大于配置的size
例如配置10kb
TimeBasedTriggeringPolicy
当前时间与当前日志文件时间不匹配时,TimeBasedTriggeringPolicy会触发归档。参数如下:
CronTriggeringPolicy
基于cron表达式触发归档。此策略由计时器控制,并且与处理日志事件异步,因此上一个或下一个时间段的日志事件可能会出现在当前日志文件的开头或结尾。filePattern属性应包含一个时间戳,否则目标文件将在每次归档时被覆盖。参数如下
例如
<Policies>
<OnStartupTriggeringPolicy/>
<!-- TimeBasedTriggeringPolicy :时间滚动策略,默认0点小时产生新的文件,interval="2" : 自定义文件滚动时间间隔,每隔2小时产生新文件, modulate="true" :
产生文件是否以0点偏移时间,即2点,4点,6点,8点-->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<!-- SizeBasedTriggeringPolicy :文件大小滚动策略-->
<SizeBasedTriggeringPolicy size="${fileSize}"/>
</Policies>
除了时间归档外,每次重启服务器也会触归档,不过归档的明明规则
RolloverPolicy
用来控制文件归档方式,目前有两种类型如下:
DefaultRolloverStrategy
通过接收filePattern属性中日期/时间模式(%d)和整数(%i)来控制归档方式。如果存在日期/时间模式,则将在归档时使用当前时间替换filePattern中配置的日期/时间部分,如果模式包含整数,则它将在每次归档时递增。如果归档时在模式中同时包含日期/时间和整数,则整数将递增,直到日期/时间部分也将被替换。如果文件模式以“ .gz”,“.zip”,“.bz2”,“.deflate”,“.pack200”或“ .xz”结尾,则将使用与后缀匹配的压缩方案来压缩文件。 bzip2, Deflate, Pack200 and XZ格式要求有Apache Commons Compress组件,另外xz格式还要求有XZ for Java组件。
DefaultRolloverStrategy参数如下:
fileIndex设值不同,则文件归档及新文件创建及计数器递增方法都不同,计数器递增有三种方式,如下:
- 方式一:fileIndex值为max
假设将DefaultRolloverStrategy的min属性设置为1,将max属性设置为3,fileName是“ foo.log”,filePattern是“ foo-%i.log”,归档规则如下:
- 方式二:fileIndex值为min
假设将DefaultRolloverStrategy的min属性设置为1,将max属性设置为3,fileName是“ foo.log”,filePattern是“ foo-%i.log”,归档规则如下:
- 方式三:fileIndex值为nomax
nomax为2.8新增属性,设置为nomax时,将忽略DefaultRolloverStrategy的最大值和最小值,每次归档生成的新文件相对于前一个文件编号加1,没有最大文件数限制。
DirectWriteRolloverStrategy
将日志事件直接写入由filePattern表示的文件。使用此策略文件不会执行重命名。如果是基于大小的触发策略,将在指定的时间段内写入多个文件,它们从1开始编号,并不断递增直到发生基于时间归档。
注意:如果filePattern的后缀表示应该进行压缩,则在关闭应用程序时不会压缩当前文件。此外,如果时间更改使得filePattern不再与当前文件匹配,则启动时也不会对其进行压缩。
DirectWriteRolloverStrategy模式参数如下:
归档保留策略
DefaultRolloverStrategy模式下,Log4j-2.5引入了Delete(删除)操作(标签为),与 max属性所提供的功能相比,Log4j-2.5使用户可以更好地控制在归档时删除哪些文件。删除操作使用户可以配置一个或多个条件,以选择要相对于基本目录删除的文件。
Filter
CompositeFilter
虽然只能配置一个Filter,但可以通过Filters元素表示一个CompositeFilter(组合过滤器) ,该元素不接收任何参数,Filters元素允许包含任意多个Filter子元素。
ThresholdFilter(常用)
该Filter是使用最多的过滤器,主要属性如下:
level(String)
匹配的可用的日志级别,可以为 OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE 、ALL 之一
onMatch(String)
当日志级别匹配时匹配时执行的过滤动作,可以为 ACCEPT、DENY、NEUTRAL 之一,默认为 NEUTRAL
onMismatch(String)
当日志级别不匹配时执行的过滤动作,可以为 ACCEPT、DENY、NEUTRAL 之一,默认为 DENY
如果不指定,则会有默认值
ThresholdFilter
@PluginFactory
public static ThresholdFilter createFilter(
@PluginAttribute("level") final Level level,
@PluginAttribute("onMatch") final Result match,
@PluginAttribute("onMismatch") final Result mismatch) {
final Level actualLevel = level == null ? Level.ERROR : level;
final Result onMatch = match == null ? Result.NEUTRAL : match;
final Result onMismatch = mismatch == null ? Result.DENY : mismatch;
return new ThresholdFilter(actualLevel, onMatch, onMismatch);
}
AbstractFilter
protected AbstractFilter(final Result onMatch, final Result onMismatch) {
this.onMatch = onMatch == null ? Result.NEUTRAL : onMatch;
this.onMismatch = onMismatch == null ? Result.DENY : onMismatch;
}
如何分开记录info,warn,error日志
目的是
info.log
只会记录info信息
error.log
只会记录error信息
Filters决定日志事件能否被输出。
onMatch
onMismatch
onMatch:表示匹配该级别及以上(>=) onMismatch:表示匹配该级别以下 (<)
过滤条件有三个值(onMatch、onMismatch属性的值):
ACCEPT(接受)
DENY(拒绝)
NEUTRAL(中立/流传) 流转到下一过滤器
如: level=“warn” onMatch=“DENY” onMismatch=“ACCEPT” 含义:大于warn级别的拒绝,小于warn级别的接受
只输出info
<Filters>
<!-- >= WARN级别的,拒绝!-->
<ThresholdFilter level="warn" onMatch="DENY" onMismatch="ACCEPT"/>
</Filters>
只输出warn
<Filters>
<ThresholdFilter level="warn" onMatch="NEUTRAL" onMismatch="DENY"/>
<ThresholdFilter level="error" onMatch="DENY" onMismatch="ACCEPT"/>
</Filters>
只输出error级别以上的日志
<Filters>
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
RegexFilter
<Filters>
<RegexFilter regex=".* test .*" onMatch="NEUTRAL" onMismatch="DENY"/>
</Filters>
TimeFilter
<Filters>
<!-- 只允许在每天的 8点~8点半 之间输出日志 -->
<TimeFilter start="08:00:00" end="08:30:00" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
整合实例
分别为info,warn,error三个级别记录日志
<?xml version="1.0" encoding="UTF-8"?>
<!--设置log4j2的自身log级别为info-->
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,
当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<!--packages: 插件扫描的基础包 -->
<Configuration status="info" packages="com.yiyouliao" monitorInterval="30">
<properties>
<Property name="pattern">%highlight{%d{HH:mm:ss.SSS} [%-5level] [%logger{36}.%M:%L] - %msg%n}{FATAL=red,
ERROR=red,
WARN=yellow,
INFO=cyan, DEBUG=green, TRACE=blue}
</Property>
<Property name="fileSize">5MB</Property>
<Property name="deleteInterval">7d</Property>
<Property name="policyInterval">1</Property>
</properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${pattern}"/>
</Console>
<RollingFile name="InfoFile" fileName="${sys:log_dir}/info.log"
filePattern="${sys:log_dir}/$${date:yyyy-MM-dd}/info-%d{yyyy-MM-dd-HH}-%i.log.gz">
<ThresholdFilter level="warn" onMatch="DENY" onMismatch="ACCEPT"/>
<PatternLayout pattern="${pattern}"/>
<Policies>
<OnStartupTriggeringPolicy/>
<!-- TimeBasedTriggeringPolicy :时间滚动策略,默认0点小时产生新的文件,interval="2" : 自定义文件滚动时间间隔,每隔2小时产生新文件, modulate="true" :
产生文件是否以0点偏移时间,即2点,4点,6点,8点-->
<TimeBasedTriggeringPolicy interval="${policyInterval}" modulate="true"/>
<!-- SizeBasedTriggeringPolicy :文件大小滚动策略-->
<SizeBasedTriggeringPolicy size="${fileSize}"/>
</Policies>
<DefaultRolloverStrategy>
<Delete basePath="${sys:log_dir}">
<IfFileName glob="*">
<IfLastModified age="${deleteInterval}">
<IfAny>
<!--logDir下文件总大小超过50M,进行删除-->
<IfAccumulatedFileSize exceeds="180M"/>
<!--logDir下文件总数量超过10,进行删除-->
<IfAccumulatedFileCount exceeds="10"/>
</IfAny>
</IfLastModified>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="WarnFile" fileName="${sys:log_dir}/warn.log"
filePattern="${sys:log_dir}/$${date:yyyy-MM-dd}/warn-%d{yyyy-MM-dd-HH}-%i.log.gz">
<Filters>
<ThresholdFilter level="warn" onMatch="NEUTRAL" onMismatch="DENY"/>
<ThresholdFilter level="error" onMatch="DENY" onMismatch="ACCEPT"/>
</Filters>
<PatternLayout pattern="${pattern}"/>
<Policies>
<OnStartupTriggeringPolicy/>
<!-- TimeBasedTriggeringPolicy :时间滚动策略,默认0点小时产生新的文件,interval="2" : 自定义文件滚动时间间隔,每隔2小时产生新文件, modulate="true" :
产生文件是否以0点偏移时间,即2点,4点,6点,8点-->
<TimeBasedTriggeringPolicy interval="${policyInterval}" modulate="true"/>
<!-- SizeBasedTriggeringPolicy :文件大小滚动策略-->
<SizeBasedTriggeringPolicy size="${fileSize}"/>
</Policies>
<DefaultRolloverStrategy>
<Delete basePath="${sys:log_dir}">
<IfFileName glob="*">
<IfLastModified age="${deleteInterval}">
<IfAny>
<!--logDir下文件总大小超过50M,进行删除-->
<IfAccumulatedFileSize exceeds="180M"/>
<!--logDir下文件总数量超过10,进行删除-->
<IfAccumulatedFileCount exceeds="10"/>
</IfAny>
</IfLastModified>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="ErrorFile" fileName="${sys:log_dir}/error.log"
filePattern="${sys:log_dir}/$${date:yyyy-MM-dd}/error-%d{yyyy-MM-dd-HH}-%i.log.gz">
<!-- <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>-->
<PatternLayout pattern="${pattern}"/>
<Filters>
<ThresholdFilter level="error"/>
</Filters>
<Policies>
<OnStartupTriggeringPolicy/>
<!-- TimeBasedTriggeringPolicy :时间滚动策略,默认0点小时产生新的文件,interval="2" : 自定义文件滚动时间间隔,每隔2小时产生新文件, modulate="true" :
产生文件是否以0点偏移时间,即2点,4点,6点,8点-->
<TimeBasedTriggeringPolicy interval="${policyInterval}" modulate="true"/>
<!-- SizeBasedTriggeringPolicy :文件大小滚动策略-->
<SizeBasedTriggeringPolicy size="${fileSize}"/>
</Policies>
<DefaultRolloverStrategy>
<!--此配置都将删除与“.log.gz”匹配且早于 30 天的文件,但保留最新的 100 GB 或最新的 10 个文件(以先到者为准) -->
<Delete basePath="${sys:log_dir}">
<IfFileName glob="*"/>
<IfLastModified age="${deleteInterval}">
<IfAny>
<!--logDir下文件总大小超过50M,进行删除-->
<IfAccumulatedFileSize exceeds="30 G"/>
<!--logDir下文件总数量超过10,进行删除-->
<IfAccumulatedFileCount exceeds="10"/>
</IfAny>
</IfLastModified>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
<AppenderRef ref="InfoFile"/>
<AppenderRef ref="WarnFile"/>
<AppenderRef ref="ErrorFile"/>
</Root>
</Loggers>
</Configuration>