log4j2 配置详解小结

发布时间 2023-11-20 11:27:56作者: 进击的davis

日志框架 log4j2 功能强大,了解配置信息对于我们使用 log4j2很有必要,今天学习下相关的配置。

Configuration

定义整个配置文件的根元素,整个配置信息都在这个标签内,下面是一个case[6]:

<?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>

在这个标签元素可以使用以下属性:

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:
   加载插件时是否显示诊断信息

Properties

通常用来定义一些变量,做到尽量复用,在 xml 后面中可能会重复用到某些属性信息,如上面的case。

Appenders

定义日志输出器的集合,在这个标签内部,我们可以通过指定 Appender 进而重定向日志到指定位置,如输出到 控制台、文件、网络传输、数据库、syslog、kafka等,每个 Appender 可以设置自己的输出方式与格式。

Appender

根据输出目标位置的不同,有不同的 Appender

以下是目前 log4j2 支持的目标位置:

image.png

这里主要学习下我们常用的输出到控制台,文件,以及涉及到日志滚动的文件输出。

Appender-Console

官方:https://logging.apache.org/log4j/2.x/manual/appenders.html#ConsoleAppender

下面是输出到控制台的case:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

Appender-File

官方:https://logging.apache.org/log4j/2.x/manual/appenders.html#FileAppender

Appender-RollingFile

官方:https://logging.apache.org/log4j/2.x/manual/appenders.html#RollingFileAppender

下面是输出到带日志滚动的case:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info">
    <Appenders>
        <RollingFile name="RollingFile" fileName="/path/to/logs/myapp.log"
                     filePattern="/path/to/logs/myapp-%d{yyyy-MM-dd}-%i.log.gz">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
            <DefaultRolloverStrategy max="10"/>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="RollingFile"/>
        </Root>
    </Loggers>
</Configuration>

常用的滚动策略是基于时间和日志大小,上面的日志滚动策略:

  • 基于时间的策略,结合filePattern的最小单位,本例中的单位是yyyy-MM-dd,所以最小单位是,即按照 day 作为滚动的时间单位,因为 interval=1,即每天滚动一次,结合 modulate 参数为 true 时,指明以 interval 为参数滚动
  • 基于日志大小的额滚动策略,设定的大小为 100MB,即如果单个日志达到 100MB,也会触发滚动策略

在元素 DefaultRolloverStrategy 中设置为10,即最大保留10个文件。

关于 RollingFile 策略设置:Log4j2中RollingFile的文件滚动更新机制 

Logger

定义 Logger 对象,可以有自己的日志级别Appenders过滤器等属性,内部通过子元素 AppenderRef 引用一个或多个 Appender,将他们附加到 Logger 上。

Root

定义 Root Logger 对象,也是所有 Logger 的父级 Logger,级别通常设置为最低级别,从而将所有日志消息传递到其他 Logger 或 Appender,Root元素通过子元素 AppenderRef 来引若干个 Appenders,将它们附加到 Root Logger 上。

Filter

定义一个或多个过滤器,用于控制哪些日志消息被记录和输出。过滤器可以根据下面几个方面进行过滤:

  • 日志级别
  • 消息内容
  • 时间戳等条件

Status

应该打印到控制台的内部 Log4j 日志事件的级别,可设置的值有 trace、debug、info、warn、error 和 fatal,Log4j 将会打
印出内部初始化等事件的详细信息(在发现配置文件之后)。设置该属性为 trace 是查找 Log4j 故障的第一手工具。也可以通过设
置 log4j2.debug 系统属性来输出 Log4j 内部日志,包括配置文件加载前的内部日志(从 log4j 2.9 开始)

Policies

Layouts

官方:https://logging.apache.org/log4j/2.x/manual/layouts.html

JsonLayout

PatternLayout

首先看个case,如不熟练 log4j2 的使用,请参考上篇分享-Java log4j2 使用小结-quick start
log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
    <Appenders>
        <Console name="console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} pid:%pid tid:%tid %r %-5p [%t] %C{2} (%F:%L) - %m%n"/>
        </Console>
        <File name="file" fileName="logs/app.log">
            <PatternLayout pattern="%d %-5p %r [%t] %C{2} (%F:%L) - %m%n"/>
        </File>
    </Appenders>
    <Loggers>
        <Root level="debug">
            <AppenderRef ref="console"/>
            <AppenderRef ref="file"/>
        </Root>
    </Loggers>
</Configuration>

main

package org.example;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class MyHelloWorld {
    private static Logger logger = LogManager.getLogger(MyHelloWorld.class);

    public static void main(String[] args) {
        logger.debug("这是 DEBUG 日志");
        logger.info("这是 INFO 日志");
        logger.error("这是 ERROR 日志");
        logger.fatal("这是 FATAL 日志");
    }
}

console输出

2023-11-17 10:25:49.519 pid:19608 tid:1 595 DEBUG [main] example.MyHelloWorld (MyHelloWorld.java:10) - 这是 DEBUG 日志
2023-11-17 10:25:49.522 pid:19608 tid:1 598 INFO  [main] example.MyHelloWorld (MyHelloWorld.java:11) - 这是 INFO 日志
2023-11-17 10:25:49.523 pid:19608 tid:1 599 ERROR [main] example.MyHelloWorld (MyHelloWorld.java:12) - 这是 ERROR 日志
2023-11-17 10:25:49.523 pid:19608 tid:1 599 FATAL [main] example.MyHelloWorld (MyHelloWorld.java:13) - 这是 FATAL 日志

这里说下 console 中的 patternLayout:

// pattern
"%d{yyyy-MM-dd HH:mm:ss.SSS} pid:%pid tid:%tid %r %-5p [%t] %C{2} (%F:%L) - %m%n"
  • %d{yyyy-MM-dd HH:mm:ss.SSS},日期时间,形如 2023-11-17 10:25:49.519
  • %pid,打印进程id
  • %tid,打印线程id
  • %r,输出从JVM启动到创建日志事件所经过的毫秒数
  • %-5p,“-” 表示左对齐,5 表示占位空间,p 表示日志级别
  • %t,当前线程
  • %C{2},日志记录器,显示到2级,如果后面没有限定数值,表示全输出
  • %F,当前文件名
  • %L,日志打印所在行号
  • %m,打印输入的message
  • %n,日志结束换行

举个通用的例子,我们在项目中通常比较重要的打印日志应该包含下面几个方面:

  • 时间
  • 日志级别
  • 进程、线程号
  • 当前源码所在文件
  • 记录行所在方法
  • 日志打印行号
  • 记录的message

其他信息根据项目需要灵活添加删减。

下面是来自官网的一些格式内容摘要,如有进一步需求,请点击下方的链接获取。

c{precision}/logger{precision}

该项属性主要输出项目的层级结构,看看官网的case就清楚了:

image.png

C{precision}/class{precision}

输出发出日志记录请求的调用方的完全限定类名,参考上一个的配置。

d{pattern}/date{pattern}

输出日志事件的时间信息,根据pattern输出对应的格式,常用pattern:

image.png

也可以使用定制的日期格式:

image.png

F/file

输出打印日志的文件名信息。

highlight{pattern}{style}

根据当前事件的日志记录级别将ANSI颜色添加到所包含模式的结果中。

L/line

输出打印日志的行号。

m{ansi}/msg{ansi}/message{ansi}

根据给定的message输出到应用日志。

M/method

输出打印日志对应的方法信息。

n

日志结束符号。

pid{[defaultValue]}/processId{[defaultValue]}

输出当前进程的 pid。

T/tid/threadId

输出当前线程的线程 thread ID。

t/tn/thread/threadName

输出当前线程的线程名。

p|level{level=label,...}/p|level{length=n}/p|level{lowerCase=true|false}

输出日志级别,默认输出如:DEBUG/INFO/WARN等,也可以根据 level和label定制输出,如 DEBUG=Debug,一般默认就可以。

r/relative

输出时间信息,从 JVM 启动到日志事件创建这段时间的时间跨度,毫秒级别。

%

该部分主要从占位数及左右对齐,数字代表占位字符数,默认右对齐,左对齐需要加“-”,如果字符数超过限定,会出现截断,如:

  • %20m,对于输出的message信息,右对齐,最大长度为20个字符
  • %-20m,左对齐,最多20个字符长度
  • %20.30m,右对齐,字符数在20-30内
  • %.30m,右对齐,字符数在0-30内

根据情况输出字符数,对齐情况。

官方:

参考: