slf4j

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SLF4J - Quick Reference

SLF4J - 快速参考

When to Use This Skill

何时使用此技能

  • Standard logging API for Java
  • Integration with Logback, Log4j2
  • Java logging best practices
Deep Knowledge: Use
mcp__documentation__fetch_docs
with technology:
slf4j
for comprehensive documentation.
  • Java 标准日志 API
  • 与 Logback、Log4j2 集成
  • Java 日志最佳实践
深度知识:调用
mcp__documentation__fetch_docs
并指定技术栈为
slf4j
可获取完整文档。

Essential Patterns

核心使用范式

Logger Declaration

声明 Logger

java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class UserService {
    private static final Logger log = LoggerFactory.getLogger(UserService.class);

    // Or with Lombok
    // @Slf4j on class
}
java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class UserService {
    private static final Logger log = LoggerFactory.getLogger(UserService.class);

    // 配合 Lombok 可以简化为在类上标注 @Slf4j
}

Logging Levels

日志级别

java
log.trace("Detailed debug info: {}", details);
log.debug("Debug info for development");
log.info("Normal operation: user {} logged in", userId);
log.warn("Potential problem: {} retries remaining", retries);
log.error("Error occurred: {}", message, exception);
java
log.trace("Detailed debug info: {}", details);
log.debug("Debug info for development");
log.info("Normal operation: user {} logged in", userId);
log.warn("Potential problem: {} retries remaining", retries);
log.error("Error occurred: {}", message, exception);

Parameterized Logging

参数化日志

java
// Good - lazy evaluation
log.debug("Processing order {} for user {}", orderId, userId);

// Avoid - always evaluates
log.debug("Processing order " + orderId + " for user " + userId);

// Multiple parameters
log.info("User {} performed {} on resource {}", userId, action, resourceId);
java
// 推荐写法 - 懒加载计算
log.debug("Processing order {} for user {}", orderId, userId);

// 不推荐写法 - 会立即执行字符串拼接
log.debug("Processing order " + orderId + " for user " + userId);

// 多参数示例
log.info("User {} performed {} on resource {}", userId, action, resourceId);

Exception Logging

异常日志记录

java
try {
    processOrder(order);
} catch (OrderException e) {
    // Exception is always last parameter
    log.error("Failed to process order {}: {}", order.getId(), e.getMessage(), e);
}
java
try {
    processOrder(order);
} catch (OrderException e) {
    // 异常对象必须放在最后一个参数位置
    log.error("Failed to process order {}: {}", order.getId(), e.getMessage(), e);
}

MDC (Mapped Diagnostic Context)

MDC(映射诊断上下文)

java
import org.slf4j.MDC;

// Set context
MDC.put("requestId", requestId);
MDC.put("userId", userId);

try {
    // All logs in this scope will include requestId and userId
    log.info("Processing request");
} finally {
    MDC.clear();
}
java
import org.slf4j.MDC;

// 设置上下文信息
MDC.put("requestId", requestId);
MDC.put("userId", userId);

try {
    // 该作用域内的所有日志都会自动携带 requestId 和 userId
    log.info("Processing request");
} finally {
    MDC.clear();
}

Conditional Logging

条件日志

java
if (log.isDebugEnabled()) {
    log.debug("Expensive computation result: {}", expensiveMethod());
}

// Better with lambdas (SLF4J 2.0+)
log.atDebug().log(() -> "Result: " + expensiveMethod());
java
if (log.isDebugEnabled()) {
    log.debug("Expensive computation result: {}", expensiveMethod());
}

// SLF4J 2.0+ 更优雅的 Lambda 写法
log.atDebug().log(() -> "Result: " + expensiveMethod());

Fluent API (SLF4J 2.0+)

流式 API(SLF4J 2.0+)

java
log.atInfo()
   .addKeyValue("orderId", orderId)
   .addKeyValue("amount", amount)
   .log("Order processed successfully");
java
log.atInfo()
   .addKeyValue("orderId", orderId)
   .addKeyValue("amount", amount)
   .log("Order processed successfully");

When NOT to Use This Skill

何时不使用此技能

  • Logging framework configuration: Use
    logback
    or Log4j2 skills for XML/config
  • Performance tuning: Configuration-level optimization is in implementation skills
  • Transport/appender setup: That's implementation-specific (Logback/Log4j2)
  • Non-Java projects: Use language-appropriate logging APIs
  • Direct implementation usage: Always code to SLF4J API, not Logback/Log4j2 directly
  • 日志框架配置:Logback/Log4j2 的 XML/配置文件修改请使用对应的专项技能
  • 性能调优:配置层面的优化属于日志实现框架的能力范畴
  • 传输/追加器配置:该部分是 Logback/Log4j2 等实现框架的独有功能
  • 非 Java 项目:请使用对应语言适配的日志 API
  • 直接调用实现类:编码时应当始终面向 SLF4J API 开发,不要直接依赖 Logback/Log4j2 的实现类

Anti-Patterns

反模式

Anti-PatternWhy It's BadSolution
String concatenation in logsAlways evaluated, performance hitUse parameterized logging:
log.info("User {}", id)
Logging without level check for expensive opsWastes CPU even when disabledUse
if (log.isDebugEnabled())
before expensive calls
Catching exceptions without loggingSilent failures, hard to debugAlways log with
log.error("msg", exception)
Not using MDC for request contextLoses correlation across logsUse
MDC.put()
with try-finally
Using wrong log levelToo much noise or missing issuesFollow conventions: ERROR=requires action, WARN=potential issue
Logging sensitive dataSecurity/compliance violationMask PII, passwords, tokens before logging
反模式弊端解决方案
日志中使用字符串拼接会立即执行拼接逻辑,带来性能损耗使用参数化日志:
log.info("User {}", id)
高开销日志操作未加级别判断即使对应日志级别关闭也会浪费 CPU 资源调用高开销方法前先判断
if (log.isDebugEnabled())
捕获异常但不记录日志导致故障静默发生,难以排查始终使用
log.error("msg", exception)
记录异常
未使用 MDC 记录请求上下文丢失日志间的关联关系,排查问题时无法串链路搭配 try-finally 使用
MDC.put()
注入上下文
日志级别使用错误要么日志冗余太多,要么关键信息丢失遵循级别约定:ERROR=需要人工介入处理,WARN=潜在异常风险
记录敏感数据违反安全/合规要求日志输出前对个人身份信息、密码、令牌等敏感内容做掩码处理

Quick Troubleshooting

快速故障排查

IssueCauseSolution
NoClassDefFoundError: StaticLoggerBinderNo SLF4J implementation on classpathAdd Logback or Log4j2 dependency
Multiple bindings warningMultiple SLF4J implementationsKeep only one: Logback OR Log4j2
Logs not appearingWrong log levelCheck implementation config (logback.xml)
Parameters not replacedWrong placeholder syntaxUse
{}
not
%s
or other formats
MDC values emptyMDC cleared or wrong threadEnsure MDC.put() before logging, clear in finally
Exception stack trace missingException not last parameterPut exception as last param:
log.error("msg", e)
问题原因解决方案
NoClassDefFoundError: StaticLoggerBinder类路径下没有 SLF4J 实现依赖添加 Logback 或 Log4j2 依赖
多实现绑定警告类路径下存在多个 SLF4J 实现依赖仅保留一个实现:Logback 或 Log4j2
日志没有输出日志级别配置错误检查日志实现的配置文件(如 logback.xml)
参数占位符没有被替换占位符语法错误使用
{}
作为占位符,不要用
%s
或其他格式符
MDC 值为空MDC 被提前清空或者日志打印在其他线程确保打日志前已经执行
MDC.put()
,且在 finally 中清空上下文
异常堆栈信息缺失异常对象没有放在参数最后一位将异常对象作为最后一个参数传入:
log.error("msg", e)