log4j2.xml配置文件元素解析
配置文件展示
《 monitorInterval="30"作用:30秒进行一次扫描该配置文件,重新加载一次,不需要重启项目》
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="erro" monitorInterval="30">
<Properties>
<!-- 配置日志文件输出目录此处定义了变量,后面就可以使用${LOG_HOME}进行引用了 -->
<Property name="LOG_HOME"> /ccx</Property>
</Properties>
<Appenders>
<!-- 输出值控制台 -->
<Console name="Console" target="SYSTEM_OUT">
<!-- 格式化日志 -->
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"
charset="UTF-8" />
</Console>
<!-- 输出到文件中 采用这个可以将日志写到多个文件中,可以自定义日志分包、日志文件数量控制等。因此建议使用这个 -->
<RollingRandomAccessFile name="File"
fileName="E:/logs/app.log" filePattern="E:/logs/$${date:HH}/%d{HH}.app.%i.log"
immediateFlush="true">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"
charset="UTF-8" />
<Policies>
<!-- 每 5s 翻滚一次 其实就是每过5s就新建一个日志文件,如果filepattern的"E:/logs/$${date:HH}/%d{HH}.app 如果不清楚可以参照下面关于policies解释
这部分相同,则进行增加i 1 2 3 4 5增加 -->
<CronTriggeringPolicy schedule="0/5 * * * * ?" />
<!-- 指单个文件最大的大小,超过这个容量就进行重新建立日志文件。 必须配合上面i使用单位 KB,MB,GB -->
<SizeBasedTriggeringPolicy size="10 MB" />
</Policies>
<!-- 控制文件数量,根据日志名称的i值,最大到10,之后就进行覆盖,默认情况下是7 -->
<DefaultRolloverStrategy max="10" />
<Filters>
<!-- 注意:配置起来比较乱,建议使用的时候单个使用,并将最后的onMismatch="DENY"这样就可以 了,做到拦截。同时LevelRangeFilter的日志输出范围为LevelRangeFilter范围与logger设置的level的交集。 -->
<!-- 只允许在每天的 8点~8点半 之间输出日志 -->
<TimeFilter start="08:00:00" end="17:29:30" onMatch="ACCEPT"
onMismatch="NEUTRAL" />
<!-- 从大到小:error, warn, info, debug, trace -->
<LevelRangeFilter minLevel="error" maxLevel="info"
onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<Logger name="AsyncFileLogger" level="trace" additivity="false">
<AppenderRef ref="Console" />
</Logger>
<!-- 以下定义两个logger,name如果是包名,那么就 com.haiyang是com.haiyang.controller的父logger,同时root是所有logger的父logger
此时通过在代码中Logger logger = (Logger) LogManager.getLogger(getClass().getName());如果该方法类在com.haiyang这个包内,
就会调用该包的方法。Logger logger = (Logger) LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);调用的是root的logger
Logger logger = (Logger) LogManager.getLogger("AsyncFileLogger");可以调用上面的那个日志定义
additivity属性作用:是否集成父类(父类也进行执行),默认是true。
<Logger name="com.haiyang.controller"
level="trace"> <AppenderRef ref="Console" /> </Logger>
<Logger name="com.haiyang"
level="trace"> <AppenderRef ref="Console" /> </Logger> -->
<Root level="erro">
<AppenderRef ref="File" />
</Root>
</Loggers>
</Configuration>
log4j2配置文件整体结构
- Appdenders部分
- Appender
- Filter
- Layout
- Policies
- Strategy
- Appender
- Loggers部分
- Logger
- Root
对于Appender的理解
作用:简单说Appender就是一个管道,定义了日志内容的去向(保存位置)。
配置一个或者多个Filter ,Filter的过滤机制和Servlet的Filter有些差别,下文会进行说明。(注意只是在文件输出的时候才配置 ,因为输入值控制台配置该属性没意义。)
配置Layout 来控制日志信息的输出格式。
配置Policies 以控制日志何时(When)进行滚动。通俗的解释就是控制日志如何区分。如多长时间进行新建一个文件夹存放日志,同一文件夹下多长时间生成一个log日志文件,统一名称日志文件最多存放几个,超出之后按照最新的覆盖最先的。(注意只是在文件输出的时候才配置 ,因为输入值控制台配置该属性没意义。)
配置Strategy 以控制日志如何(How)进行滚动。(这个没有做过多的了解)
对于Logger的理解
简单说Logger就是一个路由器,指定类、包中的日志信息流向哪个管道,以及控制他们的流量(日志级别) .通俗的解释就是,定义哪个名称、包下日志应当采用哪种Appender进行输出。
Appender标签的实现类
其实这些标签都是类名或者类名去掉后缀。
Appender的常用的实现类有:
其实Appender相当于是一个接口,在实际使用过程中,都是使用它的实现类,常用的是以下三个实现类。分别对应控制台输出 单文件输出 多文件输出。注意:括号内的名称为在log4j2.xml文件中的标签名。
- ConsoleAppender(Console)
- FileAppender(File)、RandomAccessFileAppender(RandomAccessFile)
- RollingFileAppender(RollingFile)、RollingRandomAccessFileAppender(RollingRandomAccessFile)
标签详解及可包含字标签元素
Console
该实现类会把日志输出到控制台中。
它有两种输出方式:
- SYSTEM_OUT(System.out) // 默认的配置
- SYSTEM_ERR(System.err)
两种输出方式区别,其实就相当于调用system.out与调用system.err的区别,后置在控制台输出的为红色字体。
如果不配置,默认使用SYSTEM_OUT进行输出。括号中是调用的方法。
代码如下:
<Appenders>
<!-- 在log4j2.xml文件中配置 采用Console标签即可。-->
<Console name="Console" target="SYSTEM_OUT">
<!-- 格式化日志 -->
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" charset="UTF-8"/>
</Console>
</Appenders>
File、 RandomAccessFile
相同点:写入日志信息到文件(单个文件中)
不同点:使用的I/O实现类不同,前者使用FileOutputStream,后者使用RandomAccessFile。
官方文档说是在bufferedIO=true(默认是true)的情况下后者比前者性能提升20% ~ 200%,不明觉厉,就用后者吧。
通俗点解释就是:改组是输出在单个日志文件中。平时采用后者居多.
代码示例:
<Appenders>
<RandomAccessFile name="File" fileName="logs/app.log" immediateFlush="false">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" charset="UTF-8"/>
</RandomAccessFile>
</Appenders>
属性解释:
filename:来指定文件位置,文件或目录不存在则会自动创建。通常情况下指定准确的位置,如果不指定盘符,默认位置是开发软件所在home目录。具体的不确定,因此建议改为准确的盘符位置,如文章开头所示例那样。
immediateFlush:是否每次写入都要立刻刷新到硬盘中。默认true,如果使用默认值可能会影响性能。
RollingFile 、 RollingRandomAccessFile
可以进行多个日志文件输出。(重点掌握)
这一对之间的区别与上一对之间的区别是一样的。平时也是采用RollingRandomAccessFile
上一对的实现类不能进行日志滚动,所谓日志滚动就是当达到设定的条件后,日志文件进行切分。
比如:工程师想让系统中的日志按日进行切分,并且按月归档。
这时候这一对的作用就体现出来了。
示例代码:
<Appenders>
<RollingRandomAccessFile name="File" fileName="logs/app.log"
filePattern="logs/$${date:hh-mm}/%d{hh-mm-ss}.app.%i.log" >
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" charset="UTF-8"/>
<Policies>
<!-- 每 5s 翻滚一次 -->
<CronTriggeringPolicy schedule="0/5 * * * * ?" />
<SizeBasedTriggeringPolicy size="10 MB"/>
</Policies>
<DefaultRolloverStrategy max="10" />
</RollingRandomAccessFile>
</Appenders>
-注意 filePattern这个属性,参照上面示例代码,是定义日志名称的作用,后面的%i的作用,是配合如下policies与DefaultRolloverStrategy使用的。如下配置的fileOattern名称为logs目录下,以分钟为文件夹区分,时分秒为文件名,如果这样设计,那么下面policies属性设5s属性及DefaultRolloverStrategy属性将失去作用,因为文件名不会重复。但是如果使用logs/$${date:hh}/%d{hh}.app.%i.log这样命名,就好很多,因为以小时为文件名,这样文件重名的概率就比较大,从而就使用上i的属性编号。日志文件展示如下图:
只有上图因为17.app同名,因此此时DefaultRolloverStrategy才能起上作用。一直到创建日志10次之后 会把旧的日志内容覆盖。
Filters
Filters决定日志事件能否被输出。过滤条件有三个值:ACCEPT(接受),DENY(拒绝),NEUTRAL(中立)。
常用的Filter实现类有:
- LevelRangeFilter 控制输出日志级别范围
- TimeFilter 控制日志按照何种日期进行输出
- ThresholdFilter 平时使用比较少
使用代码如下:
<Appenders>
<Console name="Console">
<!--
设置 onMismatch="NEUTRAL" 可以让日志经过后续的过滤器
最后一个过滤器建议设置 onMismatch="DENY", 不然日志就输出了。
-->
<Filters>
<!-- 从大到小:error, warn, info, debug, trace -->
<LevelRangeFilter minLevel="error" maxLevel="info" onMatch="ACCEPT" onMismatch="NEUTRAL" />
<!-- 只允许在每天的 8点~8点半 之间输出日志 -->
<TimeFilter start="08:00:00" end="08:30:00" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" charset="UTF-8"/>
</Console>
</Appenders>
注意:配置起来比较乱,建议使用的时候单个使用,并将最后的onMismatch="DENY"这样就可以 了,做到拦截。同时LevelRangeFilter的日志输出范围为LevelRangeFilter范围与logger设置的level的交集。
Policy & Strategy
上文也说了,Policy是用来控制日志文件何时(When)进行滚动的;Strategy是用来控制日志文件如何(How)进行滚动的。
如果配置的是RollingFile或RollingRandomAccessFile,则必须配置一个Policy。
如果想按月归档,按日切分日志,然后
Policy常用的实现类:
- SizeBasedTriggeringPolicy
- CronTriggeringPolicy
- TimeBasedTriggeringPolicy
SizeBasedTriggeringPolicy
根据日志文件的大小进行滚动。
单位有:KB,MB,GB
CronTriggeringPolicy
使用Cron表达式进行日志滚动,很灵活。
TimeBasedTriggeringPolicy
这个滚动策略依赖于filePattern中配置的最具体的时间单位,根据最具体的时间单位进行滚动。
这种方式比较简洁。CronTriggeringPolicy策略更强大。
简单示例:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration name="baseConf" status="warn" monitorInterval="30">
<Appenders>
<RollingRandomAccessFile name="File" fileName="logs/app.log"
filePattern="logs/$${date:hh-mm}/%d{hh-mm-ss}.app.%i.log" >
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" charset="UTF-8"/>
<Policies>
<!-- 每 5s 翻滚一次 -->
<!--<CronTriggeringPolicy schedule="0/5 * * * * ?" />-->
<!--
filePattern中最具体的时间单位是 秒。
这里用 TimeBasedTriggeringPolicy 替换 CronTriggeringPolicy
注意:modulate属性是指从启动时间开始算5秒,还是从0秒开始算5秒,运行一下就明白了。
modulate: true(默认值) // 会从启动时间开始算 5秒
modulate: false // 从 0秒开始算
-->
<TimeBasedTriggeringPolicy interval="5" modulate="true"/>
<SizeBasedTriggeringPolicy size="10 MB"/>
</Policies>
<DefaultRolloverStrategy max="10" />
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>
Strategy常用的实现类
- DefaultRolloverStrategy
- DirectWriteRolloverStrategy
这两个Strategy都是控制如何进行日志滚动的,至于他们的区别我还是不太明白,大佬解释一下吧。平时大部分用DefaultRolloverStrategy就可以了。
Logger
Logger部分就比较简单了,分为两个Logger:
- Root(必须配置)
- Logger
简单示例:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration name="baseConf" status="warn" monitorInterval="30">
<Appenders>
<Console name="Console">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</Console>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="Console"/>
<Filters>
<LevelRangeFilter minLevel="error" maxLevel="info" onMatch="ACCEPT" onMismatch="DENY" />
</Filters>
</Root>
</Loggers>
</Configuration>
注意:Logger中也可以加过滤器的哟~
较重要的问题: 日志重复打印
这时候我们需要使用一个Logger的属性来解决,那就是additivity,其默认值为true,需要配置为false。参照上面的示例代码。
<Logger name="AsyncFileLogger" level="trace" additivity="false">
<AppenderRef ref="Console" />
</Logger>
总结:
其实使用logger日志,只需关系日志怎么使用,日志输出位置即可。关于该文章目的就是为了了解log4j2.xml文件的配置方式。以下有几种经验。
1.在使用过程中会查看别人配置文件 遇到如下图不知道$${jndi:logging/context-name}是什么意思,此时解决方法就是,在log日志中,将这个变量输出,看一下到底是什么,就知道是什么值了。同样,有时候会在filename等属性中也会遇到类似这种不知道的值,解决方案也如此。
2.在配置文件中自己定义属性。并在配置文件中进行引用。
3.关于注意 大写HH为24小时制,hh为12小时制,这与java日期格式一致。
4.关于控制jar包及框架日志情况,只需要开启包名即可 如下代码spring框架日志。
<Loggers>
<!--
限制Spring框架日志的输出级别,其它框架类似配置
或者使用 AppenderRef 标签,将其输出到指定文件中,记得加上 additivity="false"
-->
<logger name="org.springframework" level="warn"/>
<Root level="info">
<AppenderRef ref="File1"/>
</Root>
</Loggers>
5.关于lookups的知识,个人觉得不要进行太纠结,钻死牛角。及日志输出格式问题,能显示出来即可,不需要死记硬背,会用即可。
lookups参考资料:
https://blog.csdn.net/ghsau/article/details/52334762