skip to content

What are the Spring Boot log levels, how are they ordered, and how do you set the threshold for a specific logger?

level: juniorimportance: must knowfreq 70%

answer

  1. TRACE<DEBUG<INFO<WARN<ERROR (+OFF)
  2. level = floor: that level and more severe
  3. logging.level.<logger>=LEVEL
  4. root default = INFO
  5. most specific prefix wins

basics

~10 s

Levels from least to most severe: TRACE, DEBUG, INFO, WARN, ERROR. Setting a logger to a level shows that level and everything more severe. Configure with logging.level.<logger>, e.g. logging.level.org.springframework.web=DEBUG. Default root level is INFO.

solid answer

~40 s

Spring Boot uses the severity order TRACE < DEBUG < INFO < WARN < ERROR (plus OFF to disable). A logger's configured level is a threshold: it emits messages at that level and every more-severe level, and suppresses less-severe ones. So INFO shows INFO/WARN/ERROR but hides DEBUG/TRACE. You set a level per logger name (usually a package) via the property logging.level.<logger-name>=LEVEL, e.g. logging.level.com.example.orders=DEBUG. The special name root sets the fallback for everything: logging.level.root=WARN. Boot's default root level is INFO. Level names are case-insensitive. Logger names are hierarchical by dotted path, so the most specific configured prefix wins. This works the same whether the backend is Logback (default) or Log4j2.

code

java · 19 lines
java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public class OrderService {
    // Logger name = fully-qualified class name -> com.example.orders.OrderService
    private static final Logger log = LoggerFactory.getLogger(OrderService.class);

    public void place(String id) {
        log.trace("entering place() id={}", id); // hidden unless threshold <= TRACE
        log.debug("validating order {}", id);    // hidden unless threshold <= DEBUG
        log.info("order {} placed", id);          // shown at default INFO
        log.warn("inventory low for {}", id);     // shown
        log.error("payment failed for {}", id);   // shown
    }
}
// With logging.level.com.example.orders=DEBUG the trace() line stays hidden
// but debug()/info()/warn()/error() are all emitted.

go deeper

for a junior

Must know the five levels, their order, that a level shows itself plus more-severe, and the logging.level.<logger> property.

for a middle

Should explain root fallback, hierarchical name resolution, and OFF.

for a senior

Should distinguish threshold vs statement level, and warn about noisy broad packages in prod.

for a principal

Frames level policy as an operational concern: defaults per environment, avoiding TRACE/DEBUG on hot paths, and cost of logging.

## What a log level is A **log level** is a severity label attached to each log statement in code. Using SLF4J (the logging facade Spring Boot uses by default, typically via Logback as the implementation), you write statements like `logger.debug(...)`, `logger.info(...)`, `logger.warn(...)`. The level of the *statement* is fixed in code; what you configure at runtime is the **threshold** for each logger. ## The severity order (least to most severe) `TRACE` < `DEBUG` < `INFO` < `WARN` < `ERROR`. There is also the pseudo-level `OFF` which disables all output for that logger. (Some backends such as Log4j2 also define `FATAL`; Spring Boot's core set is the five above plus `OFF`.) ## Threshold semantics A logger's configured level acts as a **floor**. It emits every message at that level or **more severe**, and drops anything **less severe**: - `INFO` -> shows INFO, WARN, ERROR; hides DEBUG, TRACE. - `DEBUG` -> shows DEBUG, INFO, WARN, ERROR; hides TRACE. - `WARN` -> shows WARN, ERROR only. - `OFF` -> shows nothing. ## Setting a level In `application.properties`/`application.yml`, use the property namespace `logging.level.<logger-name>`: ```properties logging.level.root=INFO logging.level.org.springframework.web=DEBUG logging.level.com.example.orders=TRACE logging.level.org.hibernate=WARN ``` The `<logger-name>` is almost always a **package prefix** but can be any logger name (including a fully-qualified class name). Values are **case-insensitive** (`debug` == `DEBUG`). ## The root logger and defaults `logging.level.root` sets the fallback level applied to any logger that has no more-specific configuration. Spring Boot's **default root level is INFO**, which is why you see INFO/WARN/ERROR out of the box but not DEBUG. ## Hierarchical name resolution Logger names form a tree by dotted segments. `com.example.orders` is a child of `com.example`, which is a child of `com`, whose parent is `root`. When Spring resolves the effective level for a logger, the **most specific configured prefix wins**; if none matches it inherits from its nearest configured ancestor, ultimately `root`. ## Convenience shortcuts Spring Boot also honours two shortcuts on the command line / properties: `debug=true` and `trace=true`. These do **not** flip everything to DEBUG globally; they enable DEBUG/TRACE for a curated set of core loggers (embedded container, Hibernate, Spring Boot) while leaving your app at its configured level. ## Gotchas - Setting a level does not change *what the code logs* — a `logger.trace(...)` call still exists; you just make it visible by lowering the threshold to TRACE. - Lowering a broad package like `org.springframework` to DEBUG is extremely noisy in production. - `logging.level.<name>` controls filtering; it does not control formatting/pattern (that is `logging.pattern.*`) or destinations (that is `logging.file.*`).

  • If root is INFO but logging.level.com.example=DEBUG, what does the logger com.example.orders.OrderService emit?
    It inherits from the most specific configured ancestor, com.example=DEBUG, so it emits DEBUG and everything more severe. root=INFO is only the fallback when no more-specific prefix matches.
  • What does logging.level.org.hibernate=OFF do?
    OFF is a pseudo-level that disables all output for that logger subtree — no messages at any level from org.hibernate are emitted.

saying these in an interview costs you the question

  • Thinking INFO shows DEBUG (it hides less-severe levels).
  • Believing the level order is ERROR<WARN<INFO (severity is inverted from that).
  • Claiming debug=true switches every logger in the app to DEBUG (it only targets a core set).
  • Assuming logging.level also changes the output format or file destination.

context