什么是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。
系统选择配置的文件的优先级如下:

  1. classpath下的名为log4j2-test.json或者log4j-test.jsn文件
  2. classpath下名为log4j2-test.xml的文件
  3. classpath下名为log4j2.json或者log4j2.jsn的文件
  4. 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日志");