skip to content

Log Levels & Groups

Levels are set per logger with properties, and logging groups alias a set of packages so you can raise web or SQL logging in one line. Interviewers ask which level goes to production, and why DEBUG everywhere is both noisy and expensive.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

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

open as a page

Spring Boot ships two predefined log groups. Which are they, and what would logging.level.sql=DEBUG turn on?

level: middleimportance: should knowfreq 40%

basics

~10 s

The predefined groups are web and sql. logging.level.sql=DEBUG raises the SQL-related loggers — Spring JDBC core, Hibernate's SQL logger, and jOOQ's logger listener — so you can see executed SQL without listing each package.

open as a page

What is logging.group in Spring Boot and why would you use it?

level: middleimportance: should knowfreq 45%

basics

~10 s

logging.group lets you give one name to a set of packages, then set the level for all of them at once. Define logging.group.<name>=pkgA,pkgB, then logging.level.<name>=DEBUG applies the level to every package in the group.

open as a page

Explain how Spring resolves the effective level of a logger given multiple logging.level entries at different specificities.

level: seniorimportance: should knowfreq 38%

basics

~20 s

Logger names form a dotted tree rooted at root. A logger's effective level comes from the most specific configured ancestor prefix; if none is set it inherits down from root. The longest matching prefix wins.

open as a page

How would you design a log-level and log-group strategy across environments, and what pitfalls do levels/groups introduce at scale?

level: principalimportance: nice to knowfreq 25%

basics

~20 s

Keep root at INFO (or WARN) in prod, DEBUG for your own packages in dev. Use groups (custom plus web/sql) as named toggles so operators raise a subsystem without listing packages. Avoid DEBUG/TRACE on hot paths and never leak sensitive data.

open as a page