Java日志最佳实践强调可读性、可维护性、可观测性与性能平衡,须统一SLF4J门面、结构化JSON输出、MDC注入关键上下文、分级精准(ERROR/WARN/INFO/DEBUG)、禁用System.out、强制滚动策略、启用异步日志及敏感字段过滤。

Java 日志记录的企业级最佳实践,核心是可读性、可维护性、可观测性与性能平衡,不是堆砌日志,而是让每条日志在故障排查、审计追踪、容量分析中真正起作用。
统一日志框架 + SLF4J 门面规范
项目必须使用 SLF4J 作为日志门面,底层绑定 Logback(开发/测试)或 Log4j2(需异步高吞吐场景)。禁止直接调用 log4j、logback 或 JUL 的原生 API。
- 确保所有模块依赖一致:只引入
slf4j-api和一个 binding(如logback-classic),避免 binding 冲突导致 silent loss of logs - Maven 中排除传递依赖里的其他 binding(尤其注意 Spring Boot Starter 默认带 logback,引入 log4j2 时要 exclude)
- 自定义 Logger 命名:用当前类名(
LoggerFactory.getLogger(MyService.class)),不写字符串字面量
结构化日志 + 关键字段注入
企业系统需对接 ELK、Loki、Splunk 等平台,纯文本日志难以解析。Logback 推荐用 logstash-logback-encoder,Log4j2 用 JsonLayout,输出 JSON 格式。
- 必含字段:
timestamp、level、logger、traceId(集成 OpenTelemetry/Spring Cloud Sleuth)、spanId、service、host - 业务上下文通过 MDC(Mapped Diagnostic Context)注入:如用户ID(
MDC.put("uid", userId))、订单号(MDC.put("orderId", "ORD-123")),并在日志模板中引用(%X{uid}) - 避免在 MDC 中存敏感信息(密码、身份证号),若必须记录,需先脱敏(如
***1234)
分级合理 + 内容精准
ERROR 不等于“出错了就打”,INFO 不等于“每进一个方法都打”。日志级别应反映系统状态和运维意图:
-
ERROR:发生不可恢复异常、外部服务彻底不可用、数据已损坏、触发熔断等——需告警;必须包含异常堆栈(
logger.error("Failed to send email", e)) - WARN:非阻断但需关注的问题,如降级执行、重试后成功、配置缺失使用默认值——建议加监控指标(如 warn_count/sec)
- INFO:关键业务节点,如“订单创建成功”、“支付回调接收完成”,不含调试细节;禁止循环内打 INFO
- DEBUG:仅开发/预发开启,用于定位逻辑分支、参数流转;生产环境默认关闭(通过配置控制,而非注释掉)
日志输出与治理底线要求
再好的内容,输出失控也会反噬系统:
- 禁用
System.out.println和e.printStackTrace()—— 它们绕过日志框架,无法格式化、无法分级、无法路由 - 滚动策略强制配置:按天(
TimeBasedRollingPolicy)+ 大小限制(SizeAndTimeBasedRollingPolicy),单文件 ≤ 256MB,保留 ≤ 7 天 - 异步日志必开(Logback 使用
AsyncAppender,Log4j2 用AsyncLogger),避免 I/O 阻塞业务线程 - 敏感字段自动过滤:在 encoder 层或 AOP 切面中拦截日志内容,对 key 名称匹配(如
password、idCard)的值做掩码处理
不复杂但容易忽略:日志是系统的“黑匣子”,写的时候想着谁会看、怎么看、看什么,比写多少更重要。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











