← Back to list

SLF4J and Logging

Master SLF4J and Logging

Raushan Kumar · 2025-12-22 17:13 · 0 claps · 2.4 min read
#spring-boot #slf4j #logging #logback #logger
Open on Medium ↗

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

  1. Message creation
  2. Thread blocking
  3. Disk I/O
  4. Synchronous writes
  5. 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