Skip to content
Spring Boot sb lombok 3 min read

@Slf4j Logging

@Slf4j generates a configured SLF4J Logger as a private static final field named log, so you can start logging without the repetitive LoggerFactory.getLogger(...) declaration. SLF4J is the logging facade that Spring Boot uses by default (over Logback), making @Slf4j the natural choice for Spring applications.

The generated log field

Adding @Slf4j to a class gives you an immediately usable log reference:

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class PaymentService {

    public void charge(String orderId) {
        log.info("Charging order {}", orderId);
    }
}

Lombok generates exactly the field you would otherwise write by hand:

private static final org.slf4j.Logger log =
        org.slf4j.LoggerFactory.getLogger(PaymentService.class);

Because it is static final and keyed to the class, it follows the standard logging convention and is correctly named in your log output.

Parameterized logging

Always use SLF4J’s {} placeholders instead of string concatenation. The arguments are only converted to strings if the log level is actually enabled, which avoids wasted work in hot paths.

@Slf4j
@Service
public class OrderService {

    public Order place(OrderRequest request) {
        log.debug("Placing order for customer={} items={}",
                request.getCustomerId(), request.getItemCount());

        try {
            return process(request);
        } catch (PaymentException ex) {
            // pass the exception as the LAST argument to log the stack trace
            log.error("Payment failed for customer={}", request.getCustomerId(), ex);
            throw ex;
        }
    }
}

Tip: Do not write log.debug("order " + request) — the concatenation runs even when debug is disabled. The {} form defers it. To log an exception’s stack trace, pass the Throwable as the final argument (no placeholder for it).

Output:

2026-06-13T10:42:11.220+05:30  INFO 5120 --- [nio-8080-exec-1] c.e.app.OrderService : Placing order for customer=42 items=3
2026-06-13T10:42:11.880+05:30 ERROR 5120 --- [nio-8080-exec-1] c.e.app.OrderService : Payment failed for customer=42
com.example.app.PaymentException: card declined
    at com.example.app.OrderService.process(OrderService.java:51)
    ...

Log levels

The log field exposes the five standard SLF4J levels. Guard truly expensive message construction with an isXxxEnabled() check.

MethodUse for
log.error(...)failures that need attention
log.warn(...)recoverable problems, deprecations
log.info(...)high-level lifecycle / business events
log.debug(...)diagnostic detail for development
log.trace(...)very fine-grained tracing
if (log.isDebugEnabled()) {
    log.debug("Computed report: {}", expensiveToString());
}

Configure thresholds per package in application.yml — see Logging Configuration:

logging:
  level:
    root: INFO
    com.example.app: DEBUG

Other logger annotations

Lombok offers one annotation per logging framework. They all generate the same log field but bind to a different backend; choose based on the facade/implementation on your classpath. With Spring Boot, @Slf4j is almost always the right one.

AnnotationBacking API
@Slf4jSLF4J (recommended for Spring Boot)
@CommonsLogApache Commons Logging
@Log4j2Apache Log4j 2
@Logjava.util.logging
@FloggerGoogle Flogger

You can also rename the field with @Slf4j(topic = "audit") to log under a specific category:

@Slf4j(topic = "AUDIT")
@Component
public class AuditLogger {
    public void record(String action) {
        log.info("action={}", action); // logger named "AUDIT"
    }
}

Note: @Slf4j only declares the logger; it does not configure output format or appenders. Those are controlled by Logback (logback-spring.xml) or properties, covered in Logging Configuration.

Last updated June 13, 2026
Was this helpful?