目录标题
-
- 一、配置文件
- (一)动态刷新配置——monitorInterval
- (二)Configuration的status属性
- (三)日志级别——通过属性level指定
- (四)Logger与Root标签
- (五)Log4j2.xml 对大小写不敏感
- (六)Logger 的additivity属性
- (七)appender-ref的ref属性
- 二、appender
- (一)Console
- (二)RollingRandomAccessFile
- (三)RollingFile
- 三、Patterns
- 四、Java 使用Log4j2
- (一)导入pom依赖
- (二)配置Log4j2.xml
- (三)使用日志
- (四)加载指定路径下的配置文件
- 五、比较完整的log4j2.xml配置
- 六、参考
一、配置文件
常用配置选项
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="WARN" monitorInterval="30" >
<!--配置常量-->
<properties></properties>
<!--扩展、插件(可选项)-->
<Appenders></Appenders>
<Loggers></Loggers>
</configuration>
(一)动态刷新配置——monitorInterval
monitorInterval:从文件配置时,Log4j 能够自动检测对配置文件的更改并重新配置自身。如果在配置元素上指定了 monitorInterval 属性并将其设置为非零值,则在下次评估和/或记录日志事件时将检查该文件,并且自上次检查以来已经过去了 monitorInterval。下面的示例显示了如何配置该属性,以便仅在经过至少 30 秒后才检查配置文件的更改。最小间隔为 5 秒
。
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="error" monitorInterval="30">
</configuration>
(二)Configuration的status属性
Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出。
status 属性的有效值为“trace”、“debug”、“info”、“warn”、“error”和“fatal”。以下配置将状态属性设置为调试。
<configuration status="error" monitorInterval="30">
</configuration>
(三)日志级别——通过属性level指定
日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出。对于Loggers中level的定义同样适用。
例子:
<Logger name="myLog" level="trace" additivity="false">
<appender-ref ref="console"/>
</Logger>
public static void main(String[] args) {
Logger logger = LogManager.getLogger("mylog");
logger.trace("trace level");
logger.debug("debug level");
logger.info("info level");
logger.warn("warn level");
logger.error("error level");
logger.fatal("fatal level");
}
(四)Logger与Root标签
可以简单的将Root认为默认的日志输出控制,并且这个默认的输出是不会被覆盖的
。也就是当你输出日志的时候只要日志级别比Root指定的低那么一定会输出。
<Loggers>
<Logger name="myLog" level="trace" additivity="false">
<appender-ref ref="console"/>
</Logger>
<Root level="info">
<AppenderRef ref="Console" />
</Root>
</Loggers>
例子:
- 只配置Root
<Loggers>
<Root level="info">
<AppenderRef ref="Console" />
</Root>
</Loggers>
public class Log4j2Test {
private static final Logger logger = LogManager.getLogger();
@Test
public void test(){
logger.trace("trace level");
logger.debug("debug level");
logger.info("info level");
logger.warn("warn level");
logger.error("error level");
logger.fatal("fatal level");
}
}
输出:
- 增加一个Logger 配置名字为myLog
注意:name的值随意,一般为类路径。name的值可以重复,但是重复的name只有一个会生效
。
<Loggers>
<Logger name="myLog" level="trace">
<appender-ref ref="console"/>
</Logger>
<Root level="info">
<AppenderRef ref="Console" />
</Root>
</Loggers>
public class Log4j2Test {
private static final Logger logger = LogManager.getLogger("myLog");
@Test
public void test(){
logger.trace("trace level");
logger.debug("debug level");
logger.info("info level");
logger.warn("warn level");
logger.error("error level");
logger.fatal("fatal level");
}
}
输出:你会发现每条日志都重复输出了。这是因为Root和Logger叠加在一起了,并且还是以日志级别高的为准。那么我们可以避免叠加吗?当然可以,Logger 的additivity属性就可以做到。
(五)Log4j2.xml 对大小写不敏感
注意:Log4j2对大小写不敏感,AppenderRef == appender-ref。configuration ==Configuration
(六)Logger 的additivity属性
Logger 的additivity属性默认为true也就是可以叠加的。如果我们不想要日志叠加输出,那么可以将值设置为false。
<Loggers>
<Logger name="myLog" level="trace" additivity="false">
<appender-ref ref="console"/>
<appender-ref ref="brokerLog-appender"/>
</Logger>
<Root level="info">
<AppenderRef ref="Console" />
</Root>
</Loggers>
(七)appender-ref的ref属性
<Loggers>
<Logger name="myLog" level="trace" additivity="false">
<!-- 将日志输出到console -->
<appender-ref ref="console"/>
<!-- 将日志输出到brokerLog-appender-->
<appender-ref ref="brokerLog-appender"/>
</Logger>
<Root level="info">
<AppenderRef ref="Console" />
</Root>
</Loggers>
注意:ref的值为appenders标签里面定义的appender(扩展、插件)的name的值。
二、appender
(一)Console
参数名 | 类型 | 描述 |
---|---|---|
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 。 |
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%m%n"/>
</Console>
</Appenders>
(二)RollingRandomAccessFile
RollingRandomAccessFile 有一下属性
参数名 | 类型 | 描述 |
---|---|---|
append | boolean | 当为 true(默认)时,日志记录将会添加到文件末尾。设置为 false 时,日志记录写入文件之前会清空文件。 |
bufferedIO | boolean | 当为 true(默认)时,日志记录将会写入一个缓冲区,当缓冲区满或设置了 immediateFlush ,日志记录才会写入磁盘中。 该属性不能使用文件锁。缓冲 I/O 能够显著提高性能,即使启用了immediateFlush 。 |
bufferSize | int | 当 bufferedIO 为 true 时,该属性用来设置缓冲区的大小,默认为 8192 字节。 |
createOnDemand | boolean | Appender 是按需(on-demand)创建文件的。仅当日志事件通过所有过滤器并到达 Appender 时,该 Appender 才会创建文件。默认为 false。 |
filter | Filter | 指定一个过滤器来决定是否将日志事件传递给 Appender 处理。可以指定为一个 CompositeFilter 来使用多个过滤器。 |
fileName | String | 设置写入日志记录的文件名。如果该文件或其父目录不存在,则会自动创建。 |
filePattern | String | 归档日志文件的文件名模式(pattern)。该模式依赖于所用的 RolloverPolicy 。DefaultRolloverPolicy 可以接受兼容 SimpleDateFormat 的日期/时间或表示一个整数的计数器的 %i 。该模式也支持运行时插入值(interpolation),故任何 Lookup(比如 DateLookup)都可以包含该模式。 |
immediateFlush | boolean | 当为 true(默认)时,每次写入都会跟随一次 flush 。这将保证数据写入磁盘,但会影响性能。仅当使用异步 Logger 的 Appender 时设置每次写入都进行 flush 才有用。异步的 Logger 和 Appender 会在一批次的日志事件末尾自动 flush ,即使该属性设置为 false ,这种方式也可以保证数据写入磁盘,但是更有效率。 |
layout | Layout | 指定格式化 LogEvent 的 Layout 。如果没有指定 Layout ,则默认使用 %m%n 格式。 |
name | String | 必选的 Appender 的名称,表示区别于其他 Appender 的唯一标识。 |
policy | TriggeringPolicy | 设置确定是否创建文件的规则(policy)。 |
strategy | RolloverStrategy | 设置确定归档文件的文件名和位置的策略(strategy)。 |
ignoreExceptions | boolean | 默认为 true ,表示当输出事件时出现的异常将会被内部记录而忽略。 当设置为 false 时,则会将异常传播给调用者。当将该 Appender 包装成 FailoverAppender 时,必须设置为 false 。 |
filePermissions | String | 设置每当创建文件时所用的 POSIX 格式的文件属性权限。底层文件系统应该支持 POSIX 格式的文件属性视图。比如: rw——- 或 rw-rw-rw- 等。 |
fileOwner | String | 指定每次创建文件的属主。由于权限原因,可能不允许更改文件属主,这时会抛出 IOException 。仅当有效的目标用户 ID 和文件的用户 ID 相同,或目标用户 ID 具有修改文件属主的权限(如果 _POSIX_CHOWN_RESTRICTED 在日志文件路径下有效)时才会处理。底层文件系统应该支持 owner 文件属性视图。 |
fileGroup | String | 指定每次创建文件的属组。底层文件系统应该支持 POSIX 格式的文件属性视图。 |
<appenders>
<!-- 这个会打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingRandomAccessFile name="error-appender" fileName="${user.dir}/jmqttlogs/error.log"
<!--将fileName日志文件的内容按照时间间隔复制到filePattern日志文件中。注意:通过 %d{yyyy-MM-dd}里面的日期格式可以控制多久生成一个日期文件-->
filePattern="${user.dir}/jmqttlogs/error.log.%d{yyyy-MM-dd}"
<!-- fileName是否追加写-->
append="true">
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout
pattern="${pattern}"
charset="UTF-8"/>
<Policies>
<!-- 指定时间的颗粒度,比如:interval="1",就是每1(分、小时、天)产生一个filePattern日志文件 -->
<TimeBasedTriggeringPolicy interval="1" />
<SizeBasedTriggeringPolicy size="10 MB" />
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了10 -->
<DefaultRolloverStrategy max="20">
<!-- 每10天删除一个日志文件-->
<Delete basePath="${user.dir}" maxDepth="1">
<IfFileName glob="*/common-error.log.*"/>
<IfLastModified age="10d"/>
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
</appenders>
注意:
- TimeBasedTriggeringPolicy 这个配置需要和filePattern结合使用,注意filePattern中配置的文件重命名规则是${FILE_NAME}-%d{yyyy-MM-dd HH-mm}-%i,最小的时间粒度是mm,即分钟,TimeBasedTriggeringPolicy指定的size是1,结合起来就是每1分钟生成一个新文件。如果改成%d{yyyy-MM-dd HH},最小粒度为小时,则每一个小时生成一个文件。
- filePattern定义的是每天生成一个日志文件,但是如果一天内的日志文件体积已经超过50M,就从新生成,两个条件满足一个即可。
- filePattern 日志文件与 fileName 日志文件
- fileName 指定当前日志文件的位置和文件名称
- filePattern 指定当发生Rolling时,文件的转移和重命名规则
(三)RollingFile
RollingFile 与RollingRandomAccessFile功能类似。
<RollingFile name="error-appender" fileName="${user.dir}/jmqttlogs/error.log"
filePattern="${user.dir}/jmqttlogs/error.log.%d{yyyy-MM-dd}"
append="true">
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout
pattern="${pattern}"
charset="UTF-8"/>
<TimeBasedTriggeringPolicy/>
<DefaultRolloverStrategy>
<Delete basePath="${user.dir}" maxDepth="1">
<IfFileName glob="*/common-error.log.*"/>
<IfLastModified age="10d"/>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
三、Patterns
######### 常见参数 #########
//
%c{参数} 或 %logger{参数} ##输出日志名称
%C{参数} 或 %class{参数 ##输出类型
%d{参数}{时区te{参数}{时区} ##输出时间
%F|%file ##输出文件名
highlight{pattern}{style} ##高亮显示
%l ##输出错误的完整位置
%L ##输出错误行号
%m 或 %msg 或 %message ##输出错误信息
%M 或 %method ##输出方法名
%n ##输出换行符
%level{参数1}{参数2}{参数3} ##输出日志的级别
%t 或 %thread ##创建logging事件的线程名
*/
######### 特殊符号 ############
#有些特殊符号不能直接打印,需要使用实体名称或者编号
//
& —— & 或者 &
< —— < 或者 <
> —— > 或者 >
“ —— " 或者 "
‘ —— ' 或者 '
*/
######## pattern对齐修饰 ##########
// 对齐修饰,可以指定信息的输出格式,如是否左对齐,是否留空格等。
## 编写格式为在任何pattern和%之间加入一个小数,可以是正数,也可以是负数。
## 整数表示右对齐,负数表示左对齐;
## 整数位表示输出信息的最小n个字符,如果输出信息不够n个字符,将用空格补齐;
## 小数位表示输出信息的最大字符数,如果超过n个字符,则只保留最后n个字符的信息
## (注意:保留的是后20个字符,而不是前20个字符)
*/
#示例如下
//
%20 —— 右对齐,不足20个字符则在信息前面用空格补足,超过20个字符则保留原信息
%-20 —— 左对齐,不足20个字符则在信息后面用空格补足,超过20个字符则保留原信息
%.30 —— 如果信息超过30个字符,则只保留最后30个字符
%20.30 —— 右对齐,不足20个字符则在信息前面用空格补足,超过30个字符则只保留最后30个字符
%-20.30 —— 左对齐,不足20个字符则在信息后面用空格补足,超过30个字符则只保留最后30个字符
四、Java 使用Log4j2
(一)导入pom依赖
<dependencies>
<!--日志门面slf4j-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!---->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j2.version}</version>
</dependency>
<!--日志实现 log4j2-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j2.version}</version>
</dependency>
<!--日志门面 log4j-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<!--<scope>test</scope>-->
</dependency>
</dependencies>
(二)配置Log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="WARN" monitorInterval="5">
<properties>
<!-- 配置常量,用于宏设置属性 -->
<property name="user.dir" value="./" />
<property name="level" value="INFO"/>
<property name="pattern" value="%d [%X{traceId}/%X{loginUserID}/%X{remoteAddr}/%X{clientId} - %X{requestURIWithQueryString}] %-5p %c{2} - %m%n"/>
</properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${pattern}" />
</Console>
<!--这个会打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档
将fileName日志文件的内容按照时间间隔复制到filePattern日志文件中。注意:通过 %d{yyyy-MM-dd}里面的日期格式可以控制多久生成一个日期文件
append="true" fileName是否追加写
-->
<RollingRandomAccessFile name="rolling-appender"
fileName="${user.dir}/logs/rolling.log"
filePattern="${user.dir}/logs/rolling.log.%d{yyyy-MM-dd hh-mm}"
append="true">
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout
pattern="${pattern}"
charset="UTF-8"/>
<!-- 指定时间的颗粒度,比如:interval="1",就是每1(分、小时、天)产生一个filePattern日志文件 -->
<Policies>
<TimeBasedTriggeringPolicy interval="10" />
<SizeBasedTriggeringPolicy size="10 MB" />
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 -->
<DefaultRolloverStrategy max="20">
<!-- 每10天删除一个日志文件-->
<Delete basePath="${user.dir}" maxDepth="1">
<IfFileName glob="*/rolling.log.*"/>
<IfLastModified age="2m"/>
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile >
</Appenders>
<Loggers>
<Logger name="myLog" level="${level}" additivity="false">
<!--同时将日志输出到控制台和日志文件-->
<AppenderRef ref="Console" />
<AppenderRef ref="rolling-appender"/>
</Logger>
<Root level="${level}">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</configuration>
(三)使用日志
package com.lihua;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.junit.Test;
/**
* @author hs
* @date 2021/11/18 14:41
*/
public class Log4j2Test {
private static final Logger logger = LogManager.getLogger("myLog");
@Test
public void test(){
for (int i = 0; i <2 ; i++) {
logger.trace("trace level");
logger.debug("debug level");
logger.info("info level");
logger.warn("warn level");
logger.error("error level");
logger.fatal("fatal level");
}
}
}
当然你也可以结合lombok 插件的@Slf4j注解使用
package com.lihua;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.junit.Test;
/**
* @author hs
* @date 2021/11/18 14:41
*/
@Slf4j
public class Log4j2Test {
@Test
public void test1(){
log.trace("trace level");
log.debug("debug level");
log.info("info level");
log.warn("warn level");
log.error("error level");
}
}
(四)加载指定路径下的配置文件
注意:log4j2.xml文件如果在resources的根目录下是会主动加载log4j2.xml配置文件的,当log4j2.xml所在目录发生变化后,可能会出错。
五、比较完整的log4j2.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,可设置一个非零的间隔秒数来检测配置变更 -->
<Configuration status="WARN" monitorInterval="60">
<!-- 自定义一些变量 -->
<Properties>
<!-- 变量定义 -->
<Property name="log_base_dir">/app_data/logs/my_app</Property>
<!-- Appender在将日志数据写入目标位置之前,一般会将日志数据通过Layout进行格式化。PatternLayout可以使用与C语言printf函数类似
的转换模式来指定输出格式。常见的配置如下:
- %d{yyyy-MM-dd HH:mm:ss.SSS} : 日志生成时间,输出格式为“年-月-日 时:分:秒.毫秒”
- %p : 日志输出格式
- %c : logger的名称
- %m : 日志内容,即 logger.info("message")
- %n : 换行符
- %T : 线程号
- %L : 日志输出所在行数
- %M : 日志输出所在方法名 -->
<Property name="log_pattern">[%d{yyyy-MM-dd HH:mm:ss.SSS}][%-5p][%T][%c.%M:%L] %msg%xEx%n</Property>
<!-- 单个日志文件最大大小,单位可以是KB, MB or GB -->
<Property name="max_single_file_size">1MB</Property>
</Properties>
<!-- 使用Appenders元素可以将日志事件数据写到各种目标位置(目前可以为控制台、文件、多种数据库API、远程套接字服务器、Apache Flume、
JMS、远程UNIX Syslog daemon),其内的每个Appender都必须要有一个name属性作为唯一标识,该标识的值在Logger中通过AppenderRef来引
用,从而将该Appender配置到该Logger中 -->
<Appenders>
<!-- Console Appender常用于将日志输出到System.out,一般用在开发环境 -->
<Console name="Console" target="SYSTEM_OUT">
<!-- 只接受程序中DEBUG级别的日志进行处理-->
<ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
<!-- 在大多数情况下,Appender将格式化LogEvent的责任委托给Layout -->
<PatternLayout pattern="${log_pattern}"/>
</Console>
<!-- RollingFile Appender会将日志输出到fileName属性指定的文件中,且需要指定TriggeringPolicy和RolloverStrategy。其中
TriggeringPolicy决定是否生成新的日志文件,RolloverStrategy决定如何生成新的日志文件。如果没有配置RolloverStrategy,则会
使用DefaultRolloverStrategy。从2.5开始,可以在DefaultRolloverStrategy中配置一个自定义的删除动作。从2.8开始,如果没有指定
文件名,则会使用DirectWriteRolloverStrategy来代替DefaultRolloverStrategy -->
<!-- 这个RollingFile Appender会打印出所有的DEBUG及以下级别(DEBUG、INFO、ERROR、FATAL、OFF)的信息 -->
<RollingFile name="DebugLogRollingFile" fileName="${log_base_dir}/my_app_debug.log"
filePattern="${log_base_dir}/$${date:yyyy_MM_dd}/my_app_debug_%d{yyyy_MM_dd_HH}_%i.log.gz">
<ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${log_pattern}" charset="UTF-8"/>
<!-- Policies表示一个CompositeTriggeringPolicy,可以组合多个TriggeringPolicy,只要内部的任意一个TriggeringPolicy
满足触发条件,都会滚动日志 -->
<Policies>
<!-- TimeBasedTriggeringPolicy用于按时间滚动日志。只要filePattern属性值中的日期/时间模式(pattern)不再应用于当
前文件时就进行日志滚动。这种规则通过interval和modulate属性来配置。interval属性指定一个整数,用于基于日期/时间模式中
的最小的时间单位数滚动一次。例如,filePattern值为/app_data/logs/my_app/$${date:yyyy_MM_dd}/my_app_%d{yyyy_
MM_dd_HH}_%i.log,这里使用小时作为最小的时间单位时,假如interval参数值为4,则表示每4小时滚动一次。默认值为1。
modulate表示是否调整interval属性值以便下次滚动发生在interval边界处。如果时间最小单位为小时,当前时间为早上3点,间隔
为4小时,则第一次滚动将发生在早上4点时(而不是早上7点),后续滚动将发生在早上8点、中午12点、下午4点等时刻 -->
<TimeBasedTriggeringPolicy interval="1" modulate="false"/>
<!-- SizeBasedTriggeringPolicy用于按文件大小滚动日志。每当日志文件超过size指定的大小(一般不超过几十MB,否则使用软
件打开导出的日志时很不方便),则这size大小的日志会自动存入按filePattern属性指定建立的文件夹下面并进行压缩存档 -->
<SizeBasedTriggeringPolicy size="${max_single_file_size}"/>
</Policies>
<!-- DefaultRolloverStrategy可以同时接受RollingFileAppender中filePattern属性值中日期/时间和整数计数器(%i)的
pattern,当日期/时间满足条件时,则会使用当前的日期/时间生成新的日志文件,如果filePattern属性值中含有一个整数计数器%i,则
在每次滚动时该整数都会增加,如果filePattern属性值中同时包含了日期/时间和整数计数器(%i),计数器会在日期/时间不变时而满足
其他滚动触发条件时(文件大小)开始自增,直到日期/时间发生变化时,计数器会重新自增。以.gz、.zip、.bz2、deflate、pack200
或xz结尾的filePattern值,会在日志文件归档时以后缀对应的格式进行压缩。min属性指定计数器的最小值,默认为1。max属性指定计数
器的最大值,一旦计数器达到了最大值,最早的归档将会在每次滚动时被删除,默认值为7。fileIndex属性如果设置为max(默认),则具
有更大索引的文件比具有更小索引的文件内容更新,如果设置为min,文件将重命名且计数器将遵循Fixed Window策略,这两种情况均有可
能导致批量的文件重命名,自2.8版本开始,如果fileIndex属性设置为nomax,则min和max属性值都将会被忽略,文件编号将每次递增1,
每次滚动都会递增到更大的值,且没有最大文件编号的限制 -->
<!--<DefaultRolloverStrategy max="100" min="1" fileIndex = "nomax"/>-->
<DefaultRolloverStrategy fileIndex="nomax">
<!-- Log4j 2.5引入了删除动作(Delete元素)。在滚动删除旧的日志文件时,相比使用DefaultRolloverStrategy的max属
性,该功能可以让用户拥有更多的删除控制。删除动作可以让用户配置若干个条件来删除相对于基准目录的文件。该功能可以删除非日
志文件,使用时一定要小心。可以通过testMode属性来测试配置是否会错删文件。basePath属性值用于指定删除文件的基准目录,必
须显式指定。maxDepth属性指定扫描目录的最大层级,0表示仅能访问基准目录(安全限制不能访问的情况除外),
Integer.MAX_VALUE值表示可以访问所有层级。默认值为1,表示仅扫描基准目录下的文件。testMode属性值如果设置为true,文件
不会实际删除,而是在status logger打印一条INFO级别的消息,可以使用该功能来测试是否会错删目标文件,默认为false。-->
<!-- 这里的Delete元素配置了每次滚动都会删除基准目录下匹配“*/my_app_debug_*.log.gz”日志文件,只要9分钟以前的日志文
件总大小超过2MB,或9分钟以前的日志文件文件总数超过2个就按时间顺序删除较早的日志文件。该元素可以防止日志文件所在分区的
磁盘空间被占满。特别需要注意的是,只有在发生日志滚动时才会尝试进行删除,否则即使满足了删除条件,但如果没有新的滚动日志
生成的话也不会发生删除操作。 -->
<Delete basePath="${log_base_dir}" maxDepth="2">
<!-- Delete元素里可以指定若干个PathCondition类型的元素。如果指定了不止一个条件,则这些条件都需要在删除之前接受
某个路径。这些条件可以嵌套,只有外部条件接受某个路径之后,其内部条件才会决定是否接受该路径。如果这些条件没有嵌套,
则它们的执行顺序是任意的。这些条件也可以通过使用IfAll, IfAny和IfNot等组合条件进行AND、OR和NOT等逻辑运算。用户
也可以创建自定义条件或使用内置条件:
- IfFileName:接受匹配正则表达式或glob的文件路径;
- IfLastModified:接受比指定时段早或一样早的文件;
- IfAccumulatedFileCount:在遍历文件树时文件总数超过文件数上限后接受路径;
- IfAccumulatedFileSize:在遍历文件树时文件总大小超过上限后接受路径;
- IfAll:如果所有内嵌条件都接受了某个路径才会接受该路径,相当于AND逻辑,其内嵌条件的执行顺序是任意的;
- IfAny:如果任意一个内嵌条件接受了某个目录就接受该目录,相当于OR逻辑,其内嵌条件的执行顺序是任意的;
- IfNot:如果内嵌条件不接受某个路径就接收该路径,相当于NOT逻辑。-->
<!-- IfFileName可以通过glob(使用受限的模式语言,比正则更简单)或regex属性(正则)来匹配相对路径(相对于Delete
的basePath属性指定的基准目录)-->
<!-- 当外部的条件满足时才会计算内部的条件,内部的同级条件的计算顺序是任意的。 -->
<IfFileName glob="*/my_app_debug_*.log.gz">
<!-- IfLastModified可以通过age属性值来指定接受最后修改时间为指定时间或早于指定时间的路径,该属性的值可参考
org.apache.logging.log4j.core.appender.rolling.action.Duration.parse(CharSequence text)方法的文档 -->
<!-- 这里的IfLastModified指定删除达到或超过60天内的文件 -->
<IfLastModified age="9m">
<!-- 这里的IfAny内嵌了两个PathCondition,表示满足任意一个条件即可 -->
<IfAny>
<!-- IfAccumulatedFileSize可通过exceeds属性值指定一个文件总大小上限值。如果文件数超过了该上限值
则删除文件 -->
<IfAccumulatedFileSize exceeds="2MB"/>
<!-- IfAccumulatedFileCount可通过exceeds属性值指定一个文件总数上限值。如果文件数超过了该上限值
则删除文件 -->
<IfAccumulatedFileCount exceeds="2"/>
</IfAny>
</IfLastModified>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="InfoLogRollingFile" fileName="${log_base_dir}/my_app_info.log"
filePattern="${log_base_dir}/$${date:yyyy_MM_dd}/my_app_info_%d{yyyy_MM_dd_HH}_%i.log.gz">
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${log_pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="${max_single_file_size}"/>
</Policies>
<DefaultRolloverStrategy fileIndex="nomax">
<Delete basePath="${log_base_dir}" maxDepth="2">
<IfFileName glob="*/my_app_info_*.log.gz">
<!-- 这里表示匹配“*/my_app_info_*.log.gz”模式的日志文件的删除策略如下:
- 只要日志文件总数量超过5个就删除按时间顺序最早的日志文件
- 只要日志文件总大小超过10MB就会删除按时间顺序最早的日志文件
- 只要日志文件最近修改时间为9分钟前或更早就会删除按时间顺序最早的日志文件 -->
<IfAny>
<IfAccumulatedFileSize exceeds="8MB"/>
<IfAccumulatedFileCount exceeds="5"/>
<IfLastModified age="9m"/>
</IfAny>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="WarnLogRollingFile" fileName="${log_base_dir}/my_app_warn.log"
filePattern="${log_base_dir}/$${date:yyyy_MM_dd}/my_app_warn_%d{yyyy_MM_dd_HH}_%i.log.gz">
<ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${log_pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="${max_single_file_size}"/>
</Policies>
<DefaultRolloverStrategy fileIndex="nomax">
<Delete basePath="${log_base_dir}" maxDepth="2">
<IfFileName glob="*/my_app_warn_*.log.gz">
<IfAny>
<IfAccumulatedFileSize exceeds="3GB"/>
<IfAccumulatedFileCount exceeds="3000"/>
<IfLastModified age="30d"/>
</IfAny>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="ErrorLogRollingFile" fileName="${log_base_dir}/my_app_error.log"
filePattern="${log_base_dir}/$${date:yyyy_MM_dd}/my_app_error_%d{yyyy_MM_dd_HH}_%i.log.gz">
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${log_pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="${max_single_file_size}"/>
</Policies>
<DefaultRolloverStrategy fileIndex="nomax">
<Delete basePath="${log_base_dir}" maxDepth="2">
<IfFileName glob="*/my_app_error_*.log.gz">
<IfAny>
<IfAccumulatedFileSize exceeds="3GB"/>
<IfAccumulatedFileCount exceeds="3000"/>
<IfLastModified age="30d"/>
</IfAny>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<!-- 记录druid的SQL语句 -->
<RollingFile name="DruidSqlRollingFile" fileName="${log_base_dir}/druid.log"
filePattern="${log_base_dir}/$${date:yyyy_MM_dd}/druid_%d{yyyy_MM_dd_HH}_%i.log.gz">
<PatternLayout pattern="${log_pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="${max_single_file_size}"/>
</Policies>
<DefaultRolloverStrategy fileIndex="nomax">
<Delete basePath="${log_base_dir}" maxDepth="2" testMode="true">
<IfFileName glob="*/druid_*.log.gz">
<IfAny>
<IfAccumulatedFileSize exceeds="3GB"/>
<IfAccumulatedFileCount exceeds="3000"/>
<IfLastModified age="30d"/>
</IfAny>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<!--定义logger,只有定义了logger并引入的appender,appender才会生效-->
<Loggers>
<!-- 当Logger在配置文件中声明时,就创建了一个LoggerConfig对象,两者一一对应,LoggerConfig包含一些Filter、这些
Filters用于过滤传递给任意Appender的LogEvent,它还包含一些Appender的引用。Logger本身执行无指向的动作,它仅含有一
个与LoggerConfig关联的名称(通过name属性指定),root Logger具有固定的默认名称,其他Logger需要指定各自的name属性
值。LoggerConfig会被分配一个日志级别,通过level属性来指定。内建的日志级别按优先级从高到底排序有:OFF > FATAL >
ERROR > WARN > INFO > DEBUG > TRACE > ALL,Log4j 2 也支持自定义的日志级别。
-->
<Root level="ALL">
<AppenderRef ref="Console"/>
<AppenderRef ref="InfoLogRollingFile"/>
<AppenderRef ref="WarnLogRollingFile"/>
<AppenderRef ref="DebugLogRollingFile"/>
<AppenderRef ref="ErrorLogRollingFile"/>
</Root>
<!-- 每个LoggerConfig的日志级别如果没有显式配置,则会继承其父级LoggerConfig的日志级别,而root LoggerConfig如果没
有配置日志级别,则会为其分配一个默认的ERROR级别 -->
<!-- 某个Logger所允许的每条日志打印请求都会传递给其LoggerConfig中的所有Appender,也会传递给该LoggerConfig的parent
LoggerConfig中的Appender,这种现象称为相加性(Additivity)。也就是说,Appender会从LoggerConfig的继承中继承相加性。这种特
性可以用来汇整某几个logger的输出,可以在声明Logger的配置文件中设置additivity="false"来禁用这种叠加继承 -->
<!--记录druid-sql的记录-->
<Logger name="druid.sql.Statement" level="debug" additivity="false">
<appender-ref ref="DruidSqlRollingFile"/>
</Logger>
<!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
<Logger name="org.springframework" level="INFO"/>
<Logger name="org.mybatis" level="INFO"/>
<!--log4j2 自带过滤日志-->
<Logger name="org.apache.catalina.startup.DigesterFactory" level="error"/>
<Logger name="org.apache.catalina.util.LifecycleBase" level="error"/>
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="warn"/>
<Logger name="org.apache.sshd.common.util.SecurityUtils" level="warn"/>
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="warn"/>
<Logger name="org.crsh.plugin" level="warn"/>
<Logger name="org.crsh.ssh" level="warn"/>
<Logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="error"/>
<Logger name="org.hibernate.validator.internal.util.Version" level="warn"/>
<Logger name="org.springframework.boot.actuate.autoconfigure.CrshAutoConfiguration" level="warn"/>
<Logger name="org.springframework.boot.actuate.endpoint.jmx" level="warn"/>
<Logger name="org.thymeleaf" level="warn"/>
</Loggers>
</Configuration>