Home/Learn/Java A–Z/Logging in Java

Logging in Java

Beginner
Testing and Quality

Effective logging uses SLF4J as the facade with Logback or Log4j2 as the implementation — structured, levelled, and never blocking.

Overview

Logging is critical for diagnosing production issues. The standard approach: SLF4J (Simple Logging Facade for Java) as the API — your code only depends on the facade, not the implementation. Logback or Log4j2 as the implementation configured at deployment time. Key concepts: log levels (TRACE/DEBUG/INFO/WARN/ERROR), parameterised logging to avoid string concatenation costs, MDC (Mapped Diagnostic Context) for correlating logs in concurrent systems, and structured/JSON logging for log aggregation tools.

SLF4J and Logback Basics

Always declare loggers as private static final. Use parameterised logging ({}) instead of string concatenation — the concatenation is skipped if the log level is not enabled.

Log levels: TRACE (very detailed debug), DEBUG (developer info), INFO (notable events), WARN (potential issues), ERROR (failures requiring attention). In production, typically INFO or WARN.

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

public class OrderService {
    // One logger per class — static final
    private static final Logger log =
        LoggerFactory.getLogger(OrderService.class);

    public Order placeOrder(OrderRequest req) {
        log.debug("Placing order for user={} item={}", req.getUserId(), req.getItemId());

        try {
            Order order = processOrder(req);
            log.info("Order placed orderId={} userId={} amount={}",
                order.getId(), req.getUserId(), order.getAmount());
            return order;
        } catch (InsufficientStockException e) {
            log.warn("Stock insufficient for item={} requested={}",
                req.getItemId(), req.getQuantity());
            throw e;
        } catch (Exception e) {
            // Always log exception with message — not just e.getMessage()
            log.error("Failed to place order for user={}", req.getUserId(), e);
            throw new OrderException("Order processing failed", e);
        }
    }
}

MDC for Request Tracing

MDC (Mapped Diagnostic Context) attaches key-value pairs to the current thread's log context. These are automatically included in every log statement from that thread — perfect for correlating all logs for a single HTTP request.

Always clear MDC after the request to prevent ThreadLocal leaks in thread pool environments.

MDCTracing.java
import org.slf4j.MDC;

// In a servlet filter or Spring interceptor
public class TraceFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res,
            FilterChain chain) throws IOException, ServletException {
        String traceId = UUID.randomUUID().toString();
        String userId  = extractUserId((HttpServletRequest) req);

        MDC.put("traceId", traceId);
        MDC.put("userId",  userId);
        MDC.put("path",    ((HttpServletRequest) req).getRequestURI());

        try {
            chain.doFilter(req, res);
        } finally {
            MDC.clear(); // MUST clear — thread pool reuses threads!
        }
    }
}

// logback.xml pattern — includes MDC fields automatically
// <pattern>%d{ISO8601} [%thread] [%X{traceId}] [%X{userId}] %-5level %logger - %msg%n</pattern>

// Every log statement in the request now includes traceId + userId:
// 2025-06-15T10:30:00 [http-1] [a1b2c3d4] [user-42] INFO OrderService - Order placed orderId=...

Logback Configuration and Structured Logging

Logback is configured via logback.xml (classpath). Structured logging (JSON) makes logs parseable by tools like Elasticsearch, Splunk, and Loki.

Key practices: never log sensitive data (passwords, tokens, PII), use async appenders for high-throughput services, set separate log levels per package.

LogbackConfig.xml
<!-- logback.xml — JSON structured logging -->
<configuration>
  <appender name="JSON_CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="net.logstash.logback.encoder.LogstashEncoder">
      <!-- Includes MDC fields, stack traces, message, level, etc. -->
    </encoder>
  </appender>

  <!-- Async wrapper — log calls return immediately (non-blocking) -->
  <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
    <appender-ref ref="JSON_CONSOLE" />
    <queueSize>512</queueSize>
    <discardingThreshold>0</discardingThreshold>
  </appender>

  <!-- Per-package levels -->
  <logger name="com.example" level="DEBUG"/>
  <logger name="org.hibernate.SQL" level="DEBUG"/>
  <logger name="org.springframework" level="WARN"/>

  <root level="INFO">
    <appender-ref ref="ASYNC" />
  </root>
</configuration>

// Java output (JSON — parseable by log aggregators)
// {"@timestamp":"2025-06-15T10:30:00","level":"INFO",
//  "logger":"OrderService","traceId":"a1b2c3","message":"Order placed",
//  "orderId":"order-42","userId":"user-7","amount":99.99}

Key Points to Remember

  • Use SLF4J as the logging facade — never import Logback/Log4j2 classes in application code.
  • Parameterised logging ({}) avoids string concatenation when the level is disabled.
  • Always log exceptions as the last argument to include the full stack trace.
  • MDC adds request-scoped context (traceId, userId) to every log line — clear it in finally.
  • Use async appenders in production to prevent slow I/O from blocking application threads.

Practice Logging in Java in the Playground

Run and modify code directly in your browser - no setup needed.

Interview Questions

Sign in to ask Aria
1

Why should you use SLF4J instead of logging directly to Logback?

EasyOracle
2

What is the difference between log.info("value: " + x) and log.info("value: {}", x)?

EasyAmazon
3

What is MDC and how does it help in a multi-threaded server?

MediumGoogle
4

Why must you clear MDC in a finally block?

MediumNetflix
5

What is structured logging and why is it preferred in cloud environments?

MediumMicrosoft

Ask Aria about Logging in Java

Your personal AI tutor — ask anything about this concept