log4j2配置

Log4j2 配置详解:从基础到实战的完整指南

Log4j2 作为主流的日志实现框架,以其高性能、灵活的配置和丰富的功能(如异步日志、动态配置)被广泛应用。其配置文件通过 XML、JSON 或 YAML 定义日志的输出目的地、格式、滚动策略等。本文基于 XML 配置格式,详细解析 Log4j2 的配置结构与核心功能。

Log4j2 配置文件基本结构

Log4j2 配置文件的根元素为<Configuration>,包含两大核心子元素:<Appenders>(日志输出目的地)和<Loggers>(日志器,控制日志流向)。基本结构如下:

<?xml version="1.0" encoding="UTF-8"?>
<!-- status:Log4j2自身日志级别(如WARN,避免过多内部日志);monitorInterval:自动检测配置文件变更的间隔(秒) -->
<Configuration status="WARN" monitorInterval="30">
    <!-- 日志输出目的地集合 -->
    <Appenders>
        <!-- 具体的Appender(如控制台、文件、滚动文件等) -->
        <Appender name="控制台" ...>
            <!-- 过滤器(可选) -->
            <Filters>...</Filters>
            <!-- 日志格式(必填) -->
            <PatternLayout .../>
            <!-- 滚动策略(仅滚动文件Appender需要) -->
            <Policies>...</Policies>
            <!-- 滚动规则(仅滚动文件Appender需要) -->
            <DefaultRolloverStrategy .../>
        </Appender>
    </Appenders>

    <!-- 日志器集合 -->
    <Loggers>
        <!-- 特定类/包的日志器 -->
        <Logger name="com.example" level="INFO" additivity="false">
            <AppenderRef ref="控制台"/> <!-- 关联Appender -->
        </Logger>
        <!-- 根日志器(默认日志器) -->
        <Root level="INFO">
            <AppenderRef ref="控制台"/>
        </Root>
    </Loggers>
</Configuration>

Appenders:日志输出目的地

<Appenders>定义日志的输出位置(如控制台、文件),每个<Appender>需指定name(唯一标识)和具体类型(如ConsoleFileRollingFile)。

1. Console:输出到控制台

最基础的 Appender,用于将日志输出到控制台(SYSTEM_OUTSYSTEM_ERR)。

<Console name="stdout" target="SYSTEM_OUT"> <!-- target默认SYSTEM_OUT,可选SYSTEM_ERR(错误流) -->
    <!-- 日志格式 -->
    <PatternLayout 
        charset="UTF-8"  <!-- 字符编码 -->
        pattern="[%-5p %d{yyyy-MM-dd HH:mm:ss.SSS}] %l [%m]%n"  <!-- 格式模板 -->
    />
</Console>
  • pattern常用占位符(后续 Layout 通用):
    • %d{格式}:日志时间(如%d{yyyy-MM-dd HH:mm:ss.SSS});
    • %p:日志级别(如 INFO、WARN,%-5p表示左对齐占 5 位);
    • %l:日志发生位置(类名、方法名、行号,如com.example.Test.main(Test.java:10));
    • %m:日志消息;
    • %n:换行符;
    • %t:线程名;
    • %X{key}:MDC 中的键值(如%X{traceId}输出追踪 ID)。

2. File:输出到固定文件

将日志输出到指定文件,不支持日志滚动(文件大小会无限增长,适合临时调试)。

<File 
    name="fileLog" 
    fileName="logs/app.log"  <!-- 文件路径相对路径基于项目根目录绝对路径如D:/logs/app.log-->
    append="true"  <!-- 是否追加(false则每次启动清空文件,默认true) -->
>
    <PatternLayout charset="UTF-8" pattern="[%-5p %d{HH:mm:ss.SSS}] %m%n"/>
</File>

3. RollingFile:支持日志滚动(生产环境首选)

RollingFile是生产环境最常用的 Appender,支持按时间、大小分割日志文件(避免单文件过大),并自动清理旧日志。

<RollingFile 
    name="rollingLog" 
    fileName="logs/app.log"  <!-- 当前日志文件路径 -->
    filePattern="logs/archive/app-%d{yyyyMMdd}-%i.log.bz2"  <!-- 滚动后文件命名格式(%i为序号,bz2表示压缩) -->
>
    <!-- 日志格式 -->
    <PatternLayout charset="UTF-8" pattern="[%-5p %d{yyyy-MM-dd HH:mm:ss.SSS}] %l [%m]%n"/>

    <!-- 日志滚动触发策略(满足任一条件即滚动) -->
    <Policies>
        <!-- 时间触发:按天滚动(依赖filePattern中的%d{yyyyMMdd}) -->
        <TimeBasedTriggeringPolicy 
            interval="1"  <!-- 滚动间隔单位与filePattern的时间粒度一致此处1表示1天-->
            modulate="true"  <!-- 是否对齐到自然时间(如每天0点滚动,而非启动后24小时) -->
        />
        <!-- 大小触发:单个文件超过100MB则滚动 -->
        <SizeBasedTriggeringPolicy size="100 MB"/>
        <!-- 定时触发:按Cron表达式滚动(如每天凌晨2点) -->
        <CronTriggeringPolicy schedule="0 0 2 * * ?"/>
    </Policies>

    <!-- 滚动规则(文件数量控制与旧日志删除) -->
    <DefaultRolloverStrategy max="30">  <!-- 同一目录下最大滚动文件数(超过则删除最旧的) -->
        <!-- 自动删除7天前的日志 -->
        <Delete basePath="logs/archive/" maxDepth="1">  <!-- basePath:日志存档目录;maxDepth:递归深度 -->
            <IfFileName glob="app-*.log.bz2"/>  <!-- 匹配文件名 -->
            <IfLastModified age="7d"/>  <!-- 保留7天内的日志(d=天,h=小时,m=分钟) -->
        </Delete>
    </DefaultRolloverStrategy>
</RollingFile>
  • filePattern说明
    格式中的%d{yyyyMMdd}决定时间滚动粒度(如yyyyMM表示按月,yyyyMMddHH表示按小时);%i用于同一时间粒度内多次滚动(如 1 天内文件超过大小,生成app-20240520-1.logapp-20240520-2.log)。

4. Filter:日志过滤机制

Filter用于控制哪些日志能通过 Appender 输出,常用ThresholdFilter(按级别过滤)和LevelRangeFilter(按级别范围过滤)。

<RollingFile name="errorLog" ...>
    <!-- 只输出ERROR及以上级别日志 -->
    <ThresholdFilter 
        level="ERROR"  <!-- 阈值级别 -->
        onMatch="ACCEPT"  <!-- 匹配时接受 -->
        onMismatch="DENY"  <!-- 不匹配时拒绝 -->
    />
    <!-- 其他配置... -->
</RollingFile>
  • 过滤逻辑:
    • ACCEPT:接受日志,后续 Filter 不再执行;
    • DENY:拒绝日志,后续 Filter 不再执行;
    • NEUTRAL:中立(交给后续 Filter 判断)。

Loggers:日志器(控制日志流向)

<Loggers>包含多个<Logger>和一个<Root>(根日志器),用于指定不同类 / 包的日志级别和输出目的地。

1. Logger:特定类 / 包的日志器

针对指定类或包配置日志行为,优先级高于Root

<Logger 
    name="com.example.service"  <!-- 类或包名"com.example"表示该包下所有类-->
    level="DEBUG"  <!-- 日志级别(TRACE < DEBUG < INFO < WARN < ERROR < FATAL) -->
    additivity="false"  <!-- 是否继承Root的Appender(false=不继承,避免重复输出) -->
>
    <AppenderRef ref="rollingLog"/>  <!-- 关联的Appender -->
</Logger>
  • level作用:只输出该级别及以上的日志(如level="INFO"则不输出 DEBUG 和 TRACE)。

2. Root:根日志器

所有未被特定<Logger>匹配的类 / 包,将使用Root的配置(默认日志器)。

<Root level="INFO">  <!-- 全局默认级别 -->
    <AppenderRef ref="stdout"/>  <!-- 输出到控制台 -->
    <AppenderRef ref="rollingLog"/>  <!-- 同时输出到滚动文件 -->
</Root>

3. 避免日志重复输出

Loggeradditivity="true"(默认)时,日志会同时输出到Logger关联的 Appender 和Root关联的 Appender,导致重复。解决方式:

  • Logger设置additivity="false"
  • 确保LoggerRoot的 Appender 不重复。

完整配置示例(生产环境参考)

<?xml version="1.0" encoding="UTF-8"?>
<!-- 自动检测配置变更(30秒),Log4j2自身日志级别为WARN -->
<Configuration status="WARN" monitorInterval="30">
    <Appenders>
        <!-- 控制台输出(INFO及以上) -->
        <Console name="Console" target="SYSTEM_OUT">
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout charset="UTF-8" pattern="[%-5p %d{yyyy-MM-dd HH:mm:ss.SSS} %t] %l %m%n"/>
        </Console>

        <!-- 滚动文件:INFO级别日志 -->
        <RollingFile name="InfoLog" 
            fileName="logs/info.log" 
            filePattern="logs/archive/info-%d{yyyyMMdd}-%i.log.gz">
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout charset="UTF-8" pattern="[%-5p %d{yyyy-MM-dd HH:mm:ss.SSS} %t %X{traceId}] %l %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <SizeBasedTriggeringPolicy size="50MB"/>
            </Policies>
            <DefaultRolloverStrategy max="30">
                <Delete basePath="logs/archive/" maxDepth="1">
                    <IfFileName glob="info-*.log.gz"/>
                    <IfLastModified age="15d"/> <!-- 保留15天日志 -->
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>

        <!-- 滚动文件:ERROR级别日志 -->
        <RollingFile name="ErrorLog" 
            fileName="logs/error.log" 
            filePattern="logs/archive/error-%d{yyyyMMdd}-%i.log.gz">
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout charset="UTF-8" pattern="[%-5p %d{yyyy-MM-dd HH:mm:ss.SSS} %t %X{traceId}] %l %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <SizeBasedTriggeringPolicy size="10MB"/> <!-- 错误日志量少,阈值设小 -->
            </Policies>
            <DefaultRolloverStrategy max="30">
                <Delete basePath="logs/archive/" maxDepth="1">
                    <IfFileName glob="error-*.log.gz"/>
                    <IfLastModified age="30d"/> <!-- 错误日志保留30天 -->
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>
    </Appenders>

    <Loggers>
        <!-- 第三方框架日志控制(如Spring、MyBatis,避免DEBUG级别的冗余日志) -->
        <Logger name="org.springframework" level="INFO" additivity="false">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="InfoLog"/>
        </Logger>
        <Logger name="org.mybatis" level="INFO" additivity="false">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="InfoLog"/>
        </Logger>

        <!-- 应用核心包日志(DEBUG级别,便于调试) -->
        <Logger name="com.example" level="DEBUG" additivity="false">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="InfoLog"/>
            <AppenderRef ref="ErrorLog"/>
        </Logger>

        <!-- 根日志器(默认INFO级别) -->
        <Root level="INFO">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="InfoLog"/>
            <AppenderRef ref="ErrorLog"/>
        </Root>
    </Loggers>
</Configuration>

关键配置要点总结

  1. 日志级别控制
    生产环境建议Root级别设为INFO,避免DEBUG/TRACE的冗余日志;特定包(如业务层)可设为DEBUG便于调试。
  2. 日志滚动策略
    • 结合TimeBasedTriggeringPolicy(按时间归档)和SizeBasedTriggeringPolicy(避免单文件过大);
    • 通过DefaultRolloverStrategyDelete自动清理旧日志,防止磁盘占满。
  3. 日志格式设计
    包含时间、级别、线程名、位置、消息,分布式系统需加入%X{traceId}实现链路追踪。
  4. 性能优化
    • 日志文件使用压缩(如.gz.bz2)减少磁盘占用;
    • 高并发场景启用 Log4j2 异步日志(需额外配置AsyncAppender)。
  5. 避免重复输出
    为自定义Logger设置additivity="false",避免同时输出到LoggerRoot的 Appender