skip to content

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

level: middleimportance: should knowfreq 45%

answer

  1. group = alias for a set of packages
  2. logging.group.<name>=pkgA,pkgB
  3. then logging.level.<name>=LEVEL
  4. predefined: web, sql
  5. expands to per-member thresholds

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.

solid answer

~40 s

A log group is an alias for a collection of logger names. You often want to raise or lower several related packages together — for example the whole web stack or all SQL-related loggers. Instead of repeating a level for each package, you define logging.group.<group-name> as a comma-separated list of packages, then target that alias with logging.level.<group-name>. For instance logging.group.tomcat=org.apache.catalina,org.apache.coyote,org.apache.tomcat and then logging.level.tomcat=TRACE flips all three at once. It is purely a configuration convenience — the underlying per-logger thresholds are what actually apply. Spring Boot also ships two predefined groups you can use without declaring them: web and sql. Groups make it easy to expose a single toggle (a property or, later, a loggers-endpoint call) that controls a meaningful slice of the system.

code

java · 18 lines
java
// application.properties equivalent (config, shown as reference):
//
//   logging.group.tomcat=org.apache.catalina,org.apache.coyote,org.apache.tomcat
//   logging.level.tomcat=TRACE
//
// After startup you can verify the effective level programmatically:
import ch.qos.logback.classic.LoggerContext;
import org.slf4j.LoggerFactory;

public class LevelInspector {
    public static void main(String[] args) {
        LoggerContext ctx = (LoggerContext) LoggerFactory.getILoggerFactory();
        // Each group member resolves to TRACE, exactly as if set individually.
        System.out.println(ctx.getLogger("org.apache.catalina").getEffectiveLevel());
        System.out.println(ctx.getLogger("org.apache.coyote").getEffectiveLevel());
        System.out.println(ctx.getLogger("org.apache.tomcat").getEffectiveLevel());
    }
}

go deeper

for a junior

Aware that a group bundles packages under one name for convenience.

for a middle

Can define a group and set its level, and knows web/sql are predefined.

for a senior

Explains that a group expands to per-member thresholds and pairs groups with runtime toggles.

for a principal

Uses groups to design operator-facing toggles and keep per-environment overrides minimal and meaningful.

## The problem groups solve When you want to change logging for a *concept* (the web layer, SQL, a third-party library) you usually have to touch several packages. Setting `logging.level` for each one individually is verbose and easy to get wrong. A **log group** gives that set of packages a single alias. ## Defining a group Under the `logging.group.<group-name>` namespace you list the member logger names, comma-separated: ```properties # Define the group logging.group.tomcat=org.apache.catalina,org.apache.coyote,org.apache.tomcat # Set a level for every member at once logging.level.tomcat=TRACE ``` Now all three packages resolve to TRACE. In YAML the same reads: ```yaml logging: group: tomcat: "org.apache.catalina,org.apache.coyote,org.apache.tomcat" level: tomcat: TRACE ``` ## How it actually works A group is **not** a new logger. Spring Boot expands the group alias to its member logger names and applies the level to each of them, exactly as if you had written the individual `logging.level.<package>` entries. So all the normal rules (threshold semantics, most-specific-prefix-wins) still apply to the members. ## Predefined groups Spring Boot registers two groups out of the box so you can target them without defining them yourself: - **`web`** — the Spring web/HTTP stack (see the dedicated question for exact members). - **`sql`** — the SQL-related loggers (Spring JDBC core, Hibernate SQL, jOOQ). So `logging.level.web=DEBUG` and `logging.level.sql=DEBUG` work immediately. ## When to use groups - To provide operators a single, meaningful toggle ("turn on SQL logging") instead of a list of packages. - To keep environment overrides small — one line per concern. - To pair with runtime level changes (the loggers endpoint can target a group name too) so on-call engineers flip a slice without memorising packages. ## Gotchas - A group only takes effect once you set a level on it; defining `logging.group.x` alone does nothing. - Group members are logger-name prefixes, so listing a package covers its subpackages. - If both an individual package level and a group containing it are set, they both simply set that package's threshold — the last-resolved/most-specific configuration governs; avoid contradictory declarations. - A group name lives in the same `logging.level.*` space, so do not name a group identically to a real package you also configure separately, to avoid confusion.

  • You defined logging.group.payments=com.example.payments but see no change. Why?
    Defining the group only creates the alias. You must also set a level on it, e.g. logging.level.payments=DEBUG; otherwise the members keep inheriting from root.
  • Is a group a real logger you can log through?
    No. It is a configuration-time alias. Spring Boot expands it to its member logger names and applies the level to each; there is no logger literally named after the group.

saying these in an interview costs you the question

  • Thinking logging.group creates a new logger you can call log.info on.
  • Believing defining a group alone changes levels without a matching logging.level entry.
  • Assuming you must always define web and sql yourself (they are predefined).
  • Confusing logging.group with logging.pattern or logging.file.

context