SLF4J and Logging
Master SLF4J and Logging
SLF4J and Logging
What is SLF4J?
SLF4J is NOT a logger implementation.
SLF4J is:
A common language for logging
Think of SLF4J as English.
- Log4j → Hindi
- Logback → French
- JUL → Spanish
You write in English (SLF4J) At runtime, someone translates it.
API vs Implementation
This is the most important concept.
API = Rules
Implementation = Actual work
Logging API (SLF4J)
SLF4J says:
These methods exist: info(), debug(), error()
It does NOT say:
- Where logs go
- How logs are written
- How fast logs are written
So SLF4J = interface/abstraction
Logging Implementation (Logback, Log4j2, JUL)
These do the real work:
- Write to file
- Write to the console
- Rotate files
- Async logging
- Formatting
So Logback = concrete class/engine
What are Log4j, Logback, and JUL?
What is SLF4J?
Logging API (interface)
Logback: Logging implementation (default in Spring Boot)
Log4j2: Another implementation
JUL (java.util.logging)Java’s built-in logging
All of them implement logging But only SLF4J is the standard API
Why Spring Boot uses SLF4J + Logback
Spring Boot says:
I want developers to write logging code once and never worry about implementation.
So Spring Boot:
- Exposes SLF4J to developers
- Chooses Logback internally
- Auto-configures everything
The developer just writes:
private static final Logger log =
LoggerFactory.getLogger(MyClass.class);
Logger Levels
Logger levels answer one question: How serious is this message, and who should care?
TRACE (lowest level)
Purpose: Extremely detailed internal flow
- Method entry/exit
- Variable-by-variable state
- Loop internals
Audience: Framework developers, deep debugging Production: ❌ NEVER enabled Cost: Very high
Example:
log.trace("Entering calculateSalary() with base={}", base);
DEBUG
Purpose: Developer-level diagnostics
- Why something failed
- Conditional paths
- Data used in decisions
Audience: Developers Production: Usually OFF Cost: Medium
Example:
log.debug("User {} fetched with roles {}", userId, roles);
INFO
Purpose: Business flow visibility
- Application started
- User registered
- Order placed
- Payment successful
Audience: Developers + Ops + Business Production: ✅ YES Cost: Low
Example:
log.info("Order {} placed successfully", orderId);
WARN
Purpose: Something is wrong, but system survives
- Fallback triggered
- Retry happening
- Deprecated API used
- Unexpected input but handled
Audience: Ops + Developers Production: ✅ YES Action: Investigate soon
Example:
log.warn("Login failed for user {} - invalid password", username);
ERROR
Purpose: Operation failed
- Exception occurred
- Request failed
- Data not saved
- External system down
Audience: Ops + Developers Production: 🚨 ALERT Action: Immediate
Example:
log.error("Payment failed for order {}", orderId, ex);
FATAL (not used in Spring Boot)
- JVM-level crash
- Application cannot continue
Spring Boot does not use FATAL separately.
🔑 Mental Rule (Remember This)
Level Question: it answers TRACE. What exactly happened step-by-step? DEBUG: Why did this happen? INFO: What is the system doing? WARN: Is something risky happening? ERROR: Did something fail?
Performance Concerns in Logging
Logging is NOT free. ( It refers to the below cost)
Costs:
- CPU
- I/O
- Disk
- Memory
- Lock contention
Why Logging Hurts Performance
- Message creation
- Thread blocking
- Disk I/O
- Synchronous writes
- Log rotation
Why Avoid String Concatenation
❌ BAD:
log.debug("User id: " + userId);
What happens:
- Java builds the string before checking log level
- Even if DEBUG is OFF
✅ GOOD:
log.debug("User id: {}", userId);
Why?
- SLF4J checks the level first
- String formatting happens only if enabled
Performance Rule
Never do work for logs that won’t be printed.
How to switch from Logback → Log4j2
Step 1: Exclude default logging
In pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
This removes:
- Logback
- Default SLF4J binding
Step 2: Add Log4j2 starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
This provides:
- Log4j2 core
- Log4j2 SLF4J binding
Step 3: No code change needed ✅
Your code stays the same:
private static final Logger log =
LoggerFactory.getLogger(MyClass.class);
SLF4J now delegates to Log4j2 instead of Logback.
Note: If there is any logback.xml or logback-spring.xml file, then make sure you are creating another file with the name of log4j2.xml or log4j2-spring.xml file. (naming pattern matters, so keep the same as mentioned.)
메타데이터
- post_id
- 09cc134d0732
- slug
- slf4j-and-logging-09cc134d0732
- url
- https://medium.com/@raushan1156/slf4j-and-logging-09cc134d0732
- canonical_url
- https://medium.com/@raushan1156/slf4j-and-logging-09cc134d0732
- author_url
- https://medium.com/@raushan1156
- status
- ok
- fetched_at
- 2026-07-14 00:24:19