什么是log4j2
log4j是Apache提供的一个日志实现,是一个基于Java的日志记录工具,有log4j1跟log4j2两个版本。log4j2是log4j的升级版本。log4j2支持log4j1.2,slf4j、commons loggin和java.util.loggin API。
本文使用log4j2+slf4j进行配置。slf4j不是一个真正的日志实现,而是一个抽象层,相当于一个统一的接口,它允许你在后台使用任意一个日志类库。我们使用slf4j提供的接口进行日志记录的编程,当我们需要更换具体的日志实现时,可以不改日志代码,只要加入相应的jar包跟配置就可以实现切换。例如从logback到log4j2的切换,只需将logback相关jiar包改为log4j2相关jar包即可。
需要引入的jar包
在maven配置文件中加入以下依赖jar包
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.6.2</version>
</dependency>
<dependency> <!-- 桥接:告诉Slf4j使用Log4j2 -->
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId> <!-- 桥接:log4j1使用Log4j2 也支持其他实现到log4j的桥接,引入不同的jar包即可-->
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.12</version>
</dependency>
<!-- 使用异步写日志功能 必须引入此包-->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.6</version>
</dependency>
xml方式log4j配置
可以通过以下四种方式配置log4j2
- 通过一个格式为xml或json的配置文件
- 以编程方式,通过创建一个ConfigurationFactory工厂和Configuration实现
- 以编程方式,通过api暴露在配置界面添加组件的博人方式
- 以编程方式,通过调用Logger内部类上的方法
配置文件优先级及存放位置
log4j2不在支持log2j1中的.properties后缀的文件配置方式。log4j2版本配置文件后缀只能为xml、json或jsn。
系统选择配置的文件的优先级如下:
- classpath下的名为log4j2-test.json或者log4j-test.jsn文件
- classpath下名为log4j2-test.xml的文件
- classpath下名为log4j2.json或者log4j2.jsn的文件
- classpath下名为log4j2.xml的文件
我们一般默认使用log4j2.xml进行命名。如果本地测试,可以先把log4j2-test.xml放到classpath,而正式环境使用log4j2.xml,则在打包部署的时候不要打包log4j2-test.xml
首先先来看一个例子
<?xml version="1.0" encoding="UTF-8"?>
<!-- status : 这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,会看到log4j2内部各种详细输出 ,默认OFF
monitorInterval : Log4j能够自动检测修改配置文件和重新配置本身, 设置间隔秒数。
%d{yyyy-MM-dd HH:mm:ss, SSS} : 日志生产时间
%p : 日志输出格式
%c : logger的名称
%m : 日志内容,即 logger.info("message")
%n : 换行符
%C : Java类名
%L : 日志输出所在行数
%M : 日志输出所在方法名
hostName : 本地机器名 hostAddress : 本地ip地址 -->
<Configuration status="debug" strict="true">
<properties>
<property name="LOG_HOME">${sys:catalina.home}/logs/</property>
</properties>
<Appenders>
<!--这个输出控制台的配置 -->
<Console name="Console" target="SYSTEM_OUT">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/>
<!-- 输出日志的格式 -->
<PatternLayout pattern="%d{DEFAULT} %c{1} %p [%t] %m%n"/>
</Console>
<!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定是否清空-->
<File name="log" fileName="${LOG_HOME}/log/test.log" append="false">
<!-- 输出的日志格式 -->
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
</File>
<!--这个会打印出所有的信息 每个小时自动按年月日时进行压缩 -->
<RollingFile name="appLog"
fileName="${LOG_HOME}info/info.log"
filePattern="${LOG_HOME}info/info.log.%d{yyyy-MM-dd-HH}.log.gz"
append="true"
>
<!-- 日志打印格式-->
<PatternLayout pattern="%d{DEFAULT} | %c{1} | %p | [%t] | %m%n"/>
<Policies>
<!-- 此处是按时间进行压缩 根据filePattern中的时间格式 每隔一个单位进行压缩-->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
</RollingFile>
<Async name="asyncAppLog">
<AppenderRef ref="appLog"/>
</Async>
<!-- error日志格式 -->
<!--配置多个Rollingfile地址,还需要在root下添加appender-ref ref="asyncErrorLog"/> 只显示error级别的信息 -->
<RollingFile name="errorLog" fileName="${LOG_HOME}error/error.log"
filePattern="${LOG_HOME}error/error.log.%d{yyyy-MM-dd}.log.gz">
<!-- 日志打印格式-->
<PatternLayout pattern="%d{DEFAULT} | %c{10} | %p | [%t] | %m%n"/>
<Policies>
<!-- 日志压缩触发条件 -->
<!-- 每次日志超过size配置的大小,按filePattern的配置的格式进行压缩>
<SizeBasedTriggeringPolicy size="250 MB"/>
<!-- 此处是按时间进行压缩 根据filePattern中的时间格式 每隔一个单位进行压缩 此处是按天压缩-->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
</RollingFile>
<Async name="asyncErrorLog">
<AppenderRef ref="errorLog"/>
</Async>
</Appenders>
<!--定义logger,只有定义了logger并引入的appender,appender才会生效 -->
<Loggers>
<!-- 配置日志的根节点,建立一个默认的root的logger,需要在root的level中指定输出的级别 -->
<Root level="info">
<AppenderRef ref="asyncAppLog"/>
</Root>
<AsyncLogger name="logger.error" level="info" additivity="false">
<AppenderRef ref="asyncErrorLog"/>
</AsyncLogger>
</Loggers>
</Configuration>
log4j配置文件详解
logs4j配置
- Configuration节点中有两个属性:status和monitorInterval。
- status表示log4j自己的日志打印级别,如果设置为TRACE,可以看到控制台输出log4j本身的日志信息。
- monitorInterval表示每隔多少秒自动检测配置文件的更改,单位是秒,最小的时间间隔是5秒。
- Configuration有两个子节点Appenders和Loggers
- Appenders节点,常见的有三种子节点:Console、RollingFile、File。
- Console节点用来定义输出到控制台的Appender
- name:指定Appender的名字
- target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT
- PatternLayout : 输出格式,不设置默认为%m%n.
- File节点用来定义输出到指定位置的文件的Appender
- name:指定Appender的名字
- fileName :指定输出日志的目的文件带全路径的文件名
- PatternLayout : 输出格式,不设置默认为:%m%n.
- RollingFile节点用来定义超过指定大小自动删除旧的创建新的的Appender
- name:指定Appender的名字
- fileName : 指定输出日志的目的文件带全路径的文件名
- PatternLayout : RollingFile子节点,输出格式,不设置默认为%m%n.
- filePattern:指定新建日志文件的名称格式
- Policies:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志
- TimeBasedTriggeringPolicy:Policies子节点,基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1hour。modulate=true用来调整时间。比如现在是早上3点,interval是4没那么第一次滚动是在早上4点,接着是8am,12am..而不是7am
- SizeBasedTriggeringPolicy:Policies子节点,基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小。
- DefaultRolloverStrategy:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max)
- Loggers节点,常见的有两种:Root和Logger
- Root节点用来指定项目的根日志,如果没有单独指定Logger,那么久会默认使用该Root日志输出
- level:日志输出级别,共有8个级别,按照从低到高:ALL-Trace-Debug-Info-Warn-Error-Fatal-OFF
- name:Root的子节点,用来指定该日志输出到哪个Appender
- Logger节点 用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等
- level:日志输出级别,共有8个级别,按照从低到高:ALL-Trace-Debug-Info-Warn-Error-Fatal-OFF
- name: 用来指定该Logger所适用的类或类做在的包路径,继承自Root节点
- AppenderRef : logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root。如果指定了,那么会在指定的Appender和Root的Appender中都会输出,此时我们可以设置Logger的additivity=”false”只在自定义的Appender中进行输出。
- 关于日志level
- 共有8个级别,按照从低到高ALL-Trace-Debug-Info-Warn-Error-Fatal-OFF
- ALL:最低等级,用于打开所有日志记录
- Trace:是追踪,就是程序推进以下,你就可以写个trace输出,所以trace应该会特别多,不过没关系,我们可以设置最低日志级别不让他输出
- Debug:指出细粒度信息事件对调试应用程序是非常有帮助的
- Info:消息在粗粒度级别上突出强调用用程序的运行过程
- Warn:输出警告及warn以下级别的日志
- Error:输出错误信息日志
- Fatal:输出每个严重的错误事件将会导致应用程序退出的日志
- OFF:最高等级,用于关闭所有的日志记录
程序会打印高于或等于所设置级别的日志,设置级别的日志越高,打印出来的日志就越少
PatternLayou格式设置
%d{yyyy-MM-dd HH:mm:ss.SSS}:表示输出的日期格式
%t:表示当前线程名称
%-5level:输出日志级别,-5表示左对齐并且固定输出5个字符
%l:输出语句所在的包名、类名、函数名、行数
%msg:输出日志的内容
%n:换行
%F 输出所在的类文件名
%L 输出行号
%M 输出所在方法名
java 中使用
private final static Logger LOGGER = LoggerFactory.getLogger(clazz);
private static final Logger ERROR_LOG = LoggerFactory.getLogger("logger.error");
private static final Logger TEST_LOG = LoggerFactory.getLogger("logger.test");
LOGGER.info("info日志");
ERROR_LOG.error("error日志");
TEST_LOG.error("test日志");