Log4j2 实战指南:Java 功能最强的日志框架

Log4j2 中文实战指南:log4j-api/log4j-core 依赖、log4j2.xml 配置结构(Appenders/Loggers)、PatternLayout 占位符、JsonLayout/JsonTemplateLayout JSON 输出、异步 Logger 与 garbage-free 性能模式、ThreadContext 上下文注入,以及观测云 DataKit 采集落地方案。

最佳实践
Log4j2 实战指南:Java 功能最强的日志框架技术指南封面

Log4j2 是 Apache 对 Log4j 1 的全面重写,模块化架构、LMAX Disruptor 异步、garbage-free 模式,是 Java 生态功能与性能上限最高的日志框架。本文从依赖配置讲到生产调优,并给出观测云平台的接入方案。

核心要点速览

  • 两个依赖起步log4j-api(API)+ log4j-core(实现);业务代码建议面向 SLF4J 门面。
  • log4j2.xml 两段式:Appenders 定义去向与格式,Loggers 定义级别与路由。
  • 性能双武器:全异步 Logger(Disruptor)+ garbage-free 模式,高吞吐场景碾压同行。
  • 生产落地:JsonTemplateLayout 输出 stdout,观测云 DataKit 采集,监控器告警。

依赖与最小配置

<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-api</artifactId>
  <version>2.24.0</version>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.24.0</version>
</dependency>
<!-- 业务代码面向 SLF4J:再加 log4j-slf4j2-impl 桥接 -->

src/main/resources/log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{ISO8601} %-5level [%t] %logger{36} - %msg %ex%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="info">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>

代码:

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

private static final Logger log = LogManager.getLogger(OrderService.class);

log.info("订单创建成功 orderId={}", order.getId());
log.error("扣款失败", ex);   // 异常作为参数,自动带堆栈

级别:TRACE → DEBUG → INFO → WARN → ERROR → FATAL

PatternLayout 常用占位符

占位符 含义
%d{ISO8601} ISO-8601 时间
%-5level 级别
%logger{36} logger 名(缩写至 36 字符)
%msg / %m 消息
%ex / %throwable 异常堆栈
%X{key} ThreadContext(MDC)值

JSON 输出:JsonLayout 与 JsonTemplateLayout

jackson-databind 依赖后用 JsonLayout 一行切换 JSON;生产更推荐 JsonTemplateLayout(依赖 log4j-layout-template-json),用模板文件精确控制输出结构:

<Console name="JsonConsole" target="SYSTEM_OUT">
  <JsonTemplateLayout eventTemplateUri="classpath:EcsLayout.json"/>
</Console>

内置的 EcsLayout.json 模板直接输出 Elastic Common Schema 规范字段(@timestamplog.levellog.logger);也可复制模板改名定制——比如把 @timestamp 改成 timelog.level 改成 status,对齐团队字段契约。

上下文注入:ThreadContext

ThreadContext.put("trace_id", traceId);
ThreadContext.put("user_id", userId);
try {
    log.info("订单处理完成");
} finally {
    ThreadContext.clearAll();
}

ThreadContext(MDC 的 Log4j2 叫法)中的键值随每条日志输出,JSON 模板中可直接引用。接入观测云 APM Java 探针后 trace_id 自动写入,实现日志与链路双向跳转。

性能调优:异步与 garbage-free

# log4j2.component.properties 或系统属性
log4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
log4j2.enableThreadlocals=true
log4j2.garbagefreeThreadContextMap=true
  • 全异步 Logger:基于 LMAX Disruptor,日志写入不占用业务线程,吞吐提升一个量级;也可只对部分 logger 用 <AsyncLogger> 标签选择性开启;
  • Garbage-free:复用 ThreadLocal 缓冲区,日志路径几乎零分配,GC 压力显著下降。

注意:异步模式崩溃时内存队列中的日志会丢——审计级日志保持同步,或依赖 DataKit 从 stdout 采集兜底。

观测云落地:Log4j2 日志采集与分析

  1. 应用侧:JsonTemplateLayout 输出 stdout(容器)或 RollingFile(主机内建轮转)。字段命名对齐契约。
  2. DataKit 采集:容器 stdout 自动采集;主机 conf.d/log/logging.conf 文件采集,source: java-appservice 标识服务。JSON 自动解析为字段。
  3. Pipeline 标准化log.level 映射标准 status(ERROR/FATAL → error),@timestamp 解析为 time
  4. 检索告警:日志查看器按 status/service/trace_id 过滤,聚类分析归纳异常;监控器对 ERROR/FATAL 阈值告警,通知对象发钉钉/企业微信/飞书。
  5. 链路关联:APM 探针注入 trace_id,错误日志一键跳转调用链。
  6. 成本控制:多索引按级别拆保留,历史数据转发归档对象存储。

常见问题(FAQ)

log4j2.xml 改了要重启吗?

<Configuration monitorInterval="30"> 开启定时检查,改文件 30 秒内自动重载,无需重启。

Spring Boot 项目怎么换成 Log4j2?

排除 spring-boot-starter-logging(Logback),引入 spring-boot-starter-log4j2,放 log4j2.xml 即可。SLF4J 门面保证业务代码零改动。

RollingFile 的轮转策略怎么配?

<TimeBasedTriggeringPolicy interval="1"/>(按天)或 <SizeBasedTriggeringPolicy size="100MB"/>,配合 <DefaultRolloverStrategy max="30"/> 控制历史文件数量。云原生部署建议直接 stdout,轮转交给采集层。

日志里 %X{} 是空的?

ThreadContext 的 put 必须发生在日志调用之前且同一线程。异步线程池场景注意上下文传递(用 TaskDecorator 或 Log4j2 的上下文数据提供器)。

系列阅读


获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台