SLF4J - Quick Reference
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.
Essential Patterns
Logger Declaration
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
}
Logging Levels
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
// 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);
Exception Logging
try { processOrder(order); } catch (OrderException e) { // Exception is always last parameter log.error("Failed to process order {}: {}", order.getId(), e.getMessage(), e); }
MDC (Mapped Diagnostic Context)
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(); }
Conditional Logging
if (log.isDebugEnabled()) { log.debug("Expensive computation result: {}", expensiveMethod()); }
// Better with lambdas (SLF4J 2.0+) log.atDebug().log(() -> "Result: " + expensiveMethod());
Fluent API (SLF4J 2.0+)
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
Anti-Patterns
Anti-Pattern Why It's Bad Solution
String concatenation in logs Always evaluated, performance hit Use parameterized logging: log.info("User {}", id)
Logging without level check for expensive ops Wastes CPU even when disabled Use if (log.isDebugEnabled()) before expensive calls
Catching exceptions without logging Silent failures, hard to debug Always log with log.error("msg", exception)
Not using MDC for request context Loses correlation across logs Use MDC.put() with try-finally
Using wrong log level Too much noise or missing issues Follow conventions: ERROR=requires action, WARN=potential issue
Logging sensitive data Security/compliance violation Mask PII, passwords, tokens before logging
Quick Troubleshooting
Issue Cause Solution
NoClassDefFoundError: StaticLoggerBinder No SLF4J implementation on classpath Add Logback or Log4j2 dependency
Multiple bindings warning Multiple SLF4J implementations Keep only one: Logback OR Log4j2
Logs not appearing Wrong log level Check implementation config (logback.xml)
Parameters not replaced Wrong placeholder syntax Use {} not %s or other formats
MDC values empty MDC cleared or wrong thread Ensure MDC.put() before logging, clear in finally
Exception stack trace missing Exception not last parameter Put exception as last param: log.error("msg", e)