Skip to content

Stop generating logback-spring.xml by default; add opt-in Logback Configuration Forge feature#15757

Open
codeconsole wants to merge 13 commits into
apache:8.0.xfrom
codeconsole:remove-skeleton-logback-spring-xml
Open

Stop generating logback-spring.xml by default; add opt-in Logback Configuration Forge feature#15757
codeconsole wants to merge 13 commits into
apache:8.0.xfrom
codeconsole:remove-skeleton-logback-spring-xml

Conversation

@codeconsole

@codeconsole codeconsole commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Stops scaffolding grails-app/conf/logback-spring.xml into newly created
Grails applications, in both app-generation paths, and adds an opt-in
Logback Configuration Forge feature that generates the starter file on
demand.

  • Profile skeleton — deletes
    grails-profiles/base/skeleton/grails-app/conf/logback-spring.xml.
  • Grails Forge — the default logback feature no longer emits a
    logback-spring.xml template; it keeps adding the grails-logging
    dependency. A new visible logback-config feature (Logback
    Configuration
    ) generates the starter file for projects that prefer to
    manage logging in XML; selecting it supersedes the default feature.

Note: the content fixes to the generated file (composing Spring Boot's
defaults.xml + console-appender.xml, INFO root level instead of
ERROR, no Jansi) were extracted from this PR and landed separately in
#15973. The starter file the logback-config feature emits is that
simplified version.

Logging keeps working with zero configuration. The base profile declares
spring-boot-starter-logging and Forge adds org.apache.grails:grails-logging
(which pulls in the Boot logging starter), so Logback and Spring Boot's own
default Logback configuration
are on the classpath and apply automatically
when the app supplies no config of its own: an INFO root logger and a
colorized console pattern.

Why the file should not be created automatically

1. Spring Boot already provides a complete default configuration

When the Boot logging starter is present and no user config is found,
Spring Boot applies its bundled Logback setup. This is the explicit,
documented "it just works with zero config" contract of Spring Boot.
Shipping a logback-spring.xml in the generated app opts every new app out
of that contract on day one and replaces a well-maintained, version-matched
default with a static file the framework must keep in sync with Boot.

2. It matches the Spring Boot 4.x convention

The modern Spring Boot convention (and what start.spring.io produces) is to
ship no logging config file at all. A generated Spring Boot 4.x app
relies on Boot's defaults and adds a logback-spring.xml only when it
genuinely needs to customize. Removing this file brings Grails app generation
in line with that convention and with what Spring/Boot developers already
expect.

3. Environment-specific logging does not require the file

Grails environments map to Spring profiles, so per-environment log levels
work with zero XML from the environments block every app already has:

environments:
    development:
        logging:
            level:
                com.example.myapp: DEBUG

logback-spring.xml (with <springProfile>) remains the answer for
env-specific appenders and routing, which properties cannot express — and
the Logback Configuration Forge feature generates a starter file for
exactly that case.

Documentation

  • Logging reference (conf/config/logging.adoc) — documents zero-config
    logging as the default for new applications, application.yml level and
    pattern tuning, per-environment levels, when to add logback-spring.xml
    (and that it replaces Boot's bundled configuration entirely, so it must
    declare its own appenders), and the boundaries between the two modes.
  • Upgrade guide (upgrading80x.adoc) — new section "Logback
    Configuration No Longer Generated by Default"
    covering the change, that
    existing applications are unaffected, and how to re-add the file.

Tests

LogbackSpec asserts no logback-spring.xml is generated by default for
any application type, that logback-config generates the simplified starter
(Boot includes, INFO root, development springProfile, no Jansi), and
that grails-logging is declared exactly once either way.

Related: #15756

Stop scaffolding grails-app/conf/logback-spring.xml into newly created
applications. The base profile already declares
spring-boot-starter-logging, so Logback and Spring Boot's default
configuration (base.xml -> defaults.xml + console-appender.xml) are on
the classpath and apply automatically when no user config is present.

A generated config file is therefore not required for logging to work,
and the one we ship overrides Boot's sensible defaults out of the gate:

* Root level is forced to ERROR, hiding WARN/INFO that Boot shows by
  default and that most apps want during development.
* It pins a CONSOLE appender with withJansi=false, opting every new app
  out of ANSI color that Boot enables automatically on capable consoles.
* Most of the file is commented-out boilerplate (file appender, sample
  loggers), which reads as clutter in a brand-new project.

This matches Spring Boot 4.x conventions: apps log correctly with zero
config, and users add grails-app/conf/logback-spring.xml only when they
need to customize. Levels and patterns remain configurable from
application.yml via logging.level.*, logging.pattern.* and
logging.file.* without any XML.
@codeconsole codeconsole force-pushed the remove-skeleton-logback-spring-xml branch from 52cc29c to 94067b6 Compare June 23, 2026 23:19
The Logback feature now only adds the grails-logging dependency and no
longer renders grails-app/conf/logback-spring.xml. grails-logging brings
spring-boot-starter-logging, so Logback and Spring Boot's default
configuration apply automatically when the generated app supplies no
config, matching Spring Boot 4.x's zero-config logging convention.

Removes the now-unused logback.rocker.raw template and updates
LogbackSpec to assert the file is not generated. The grails-logging
dependency assertion is unchanged.
@codeconsole codeconsole changed the title Remove logback-spring.xml from the app skeleton (match Spring Boot 4.x zero-config logging) Stop generating logback-spring.xml in new apps (match Spring Boot 4.x zero-config logging) Jun 23, 2026
@codeconsole

Copy link
Copy Markdown
Contributor Author

#15756

@codeconsole codeconsole requested review from jamesfredley, jdaugherty, matrei and sbglasius and removed request for jdaugherty June 24, 2026 07:11

@sbglasius sbglasius left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be documented, both in the upgrade notes and under configuration, since this will come as a surprise to seasoned Grails developers (I would be one of them).

@jdaugherty jdaugherty left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be ok to stop generating, but we need to do the following:

  1. document this change in the upgrade guide
  2. add a forge feature to revert the behavior

@jamesfredley

Copy link
Copy Markdown
Contributor

Unless it can do <springProfile name="development"> somehow, I am a no on this. Environment specific logging config is an expected feature in Grails.

There were so many tickets when Logback nuked the groovy config and I don't want us back in that situation. This PR is just for application generator and we want new users to have a excellent out of the box experience.

@jamesfredley jamesfredley left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above

@jamesfredley

Copy link
Copy Markdown
Contributor

A quick round with AI leads me to believe the environment/spring profile specific logging is only possible via logback-spring.xml. So at a max I would only be OK stripping parts of that file that are no longer needed and are explicitly duplicative of spring default and continuing to generate a logback-spring.xml that provides the same historical environment specific logging, low default level in dev, as expected.

Adds a visible `logback-config` logging feature that generates
grails-app/conf/logback-spring.xml for projects that prefer to manage
their Logback configuration in XML.

Logback remains available in every generated app via Spring Boot's
zero-config logging (the default Logback feature adds grails-logging);
this feature only emits an editable starter config file. As a
mutually-exclusive logging feature it supersedes the default when
selected, so it re-declares grails-logging to keep Logback on the
classpath.

- LogbackConfig: visible OneOf LoggingFeature that adds the
  logback-spring.xml template and grails-logging dependency.
- Restore the logback.rocker.raw template used to render the file.
- LogbackSpec: cover feature visibility, file generation across all
  application types, and that grails-logging is declared exactly once.
@codeconsole codeconsole changed the title Stop generating logback-spring.xml in new apps (match Spring Boot 4.x zero-config logging) Stop generating logback-spring.xml by default; add opt-in Logback Configuration Forge feature Jun 26, 2026
…guration feature

Addresses review feedback that the change must be documented in both the
upgrade guide and the configuration reference.

- upgrading80x.adoc: add section 27 explaining that new apps no longer
  generate grails-app/conf/logback-spring.xml, that logging works via
  Spring Boot's zero-config defaults, how to tune it from application.yml,
  how to add a logback-spring.xml for custom/environment-specific logging,
  and that existing apps are unaffected.
- logging.adoc: document zero-config logging, application.yml tuning, when
  to add logback-spring.xml, and the Grails Forge Logback Configuration
  feature that generates a starter file.
@codeconsole

Copy link
Copy Markdown
Contributor Author

@sbglasius Good call — this is now documented in both places:

  • Upgrade guide (upgrading80x.adoc): new section "Logback Configuration No Longer Generated by Default" covering what changed, that logging still works out of the box via Spring Boot's zero-config defaults, how to tune levels/patterns from application.yml, and how/when to add a logback-spring.xml for custom or environment-specific logging. It also notes that existing applications are unaffected.
  • Configuration reference (conf/config/logging.adoc): now documents zero-config logging, application.yml tuning, and when to add logback-spring.xml.

Both in ed420b1.

@codeconsole

Copy link
Copy Markdown
Contributor Author

@jdaugherty Both points are addressed:

  1. Documented in the upgrade guide — new section in upgrading80x.adoc (ed420b1).
  2. Forge feature to revert the behavior — added a visible "Logback Configuration" feature that generates grails-app/conf/logback-spring.xml on demand (0eea153). It's a mutually-exclusive logging feature, so selecting it supersedes the default feature and re-declares grails-logging — the dependency is identical either way; the only difference is the generated file.

@jamesfredley

Copy link
Copy Markdown
Contributor

I would be onboard if the logback-spring.xml feature in forge was default and could be unselected to achieve the desired idea for this PR, since I think the majority of users of forge would want logback-spring.xml

@codeconsole

codeconsole commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

I would be onboard if the logback-spring.xml feature in forge was default and could be unselected to achieve the desired idea for this PR, since I think the majority of users of forge would want logback-spring.xml

@jamesfredley per the description, logback-spring.xml still works. It just isn't needed. We should focus on making new apps as lightweight as possible while still allowing power users to customize like you are suggesting. The default shouldn't be kitchen sink.

What about "default and could be unselected" like you suggest for 8.0 and then consider defaulting to off in 9.0?

…ack-spring-xml

# Conflicts:
#	grails-doc/src/en/guide/upgrading/upgrading80x.adoc
…block

Environment-specific log levels do not require logback-spring.xml: the Grails
environments block in application.yml (and a profile-specific
application-development.yml) drive per-environment levels with no XML, because
Grails environments map to Spring profiles. Document this in both the upgrade
guide and the logging configuration reference, and reframe logback-spring.xml
as needed only for things properties cannot express (custom appenders,
structured output, per-environment appender routing).
@jamesfredley

Copy link
Copy Markdown
Contributor

@codeconsole I understand why you want it off by default, but I don't think that is the majority use case for generated apps on forge, which in theory are greenfield. I'd love to be able to deselect it for your use case but have default long term, since having more detailed logs in dev is expected behavior and having less detailed logs in prod is also.

@codeconsole

codeconsole commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

@jamesfredley Completely agree env-specific logging is expected and we must not regress it. I tested it on Grails 8 (Spring Boot 4): generated an app, booted it in development, and checked the effective level of loggers configured three different ways.

Mechanism Result in development
environments: development: logging.level… in application.yml ✅ applied
application-development.yml with logging.level… ✅ applied
logback-spring.xml <springProfile name="development"> ✅ applied (still works under Spring Boot 4)

Two takeaways:

  1. <springProfile> still works in Grails 8 / Spring Boot 4 — this is not a repeat of the Logback-killed-Groovy-config situation; nothing regressed.
  2. Environment-specific log levels don't require logback-spring.xml at all. The Grails environments block in application.yml — which every app already has — drives per-environment levels with zero XML. logback-spring.xml is still the answer for env-specific appenders / patterns, which properties can't express.

Given that, I'd argue against generating a replacement file. The old generated logback-spring.xml was largely commented-out placeholders, and seeding any "default" env logging is just config a new app has to read and undo — the same papercut the PR is removing. So instead of shipping a file:

  • Logging works out of the box (Spring Boot defaults), and env-specific logging is fully available with no file — e.g. dev-verbose for your own package:
    environments:
        development:
            logging:
                level:
                    com.example: DEBUG
  • For anyone who wants the XML / <springProfile> route (custom appenders, structured output), the PR adds an opt-in Logback Configuration feature in Forge that generates a starter logback-spring.xml.
  • The upgrade guide and logging reference now document all of this.

Does that address the concern? If you'd still prefer a generated app to demonstrate env logging, we could seed a commented environments/logging.level example rather than active config — though I lean against shipping anything the user didn't ask for.

…pt-in Forge feature

Per review feedback on apache#15757, flip the default: newly generated
applications (profile skeleton and Grails Forge) continue to include the
starter grails-app/conf/logback-spring.xml, and the zero-config behavior
this PR introduced becomes an opt-in, visible Forge feature
(logback-zero-config) that omits the file and relies on Spring Boot's
default Logback configuration.

The docs now describe the generated file as optional, document tuning
levels and per-environment logging from application.yml, and note that a
future major release may flip the default to zero-config.
@codeconsole codeconsole changed the title Stop generating logback-spring.xml by default; add opt-in Logback Configuration Forge feature Add opt-in zero-config Logback Forge feature; document logback-spring.xml as optional Jul 10, 2026
@codeconsole

Copy link
Copy Markdown
Contributor Author

@jamesfredley Done — the default is flipped back per your feedback (298cd59). Newly generated applications (both the profile skeleton and Forge) include the starter grails-app/conf/logback-spring.xml exactly as before; nothing is removed or changed by default. The net diff is now purely additive:

  • A visible Zero-config Logback Logging Forge feature (logback-zero-config) for those who want to opt out of the generated file and rely on Spring Boot's defaults.
  • Docs describing the file as optional, including application.yml-only per-environment logging via the environments block, and when logback-spring.xml / <springProfile> is still the right tool.
  • The upgrade guide notes that a future major release may revisit making zero-config the default, so that discussion is on the record for 9.0.

PR title/description updated to match.

…INFO root level

Strip the parts of the generated file that duplicated Spring Boot's own
configuration, per review discussion on apache#15757:

- Compose Spring Boot's defaults.xml and console-appender.xml instead of
  hand-copying the console appender (this also drops the explicit
  withJansi setting; Boot's appender does not use Jansi).
- Raise the root level from ERROR to INFO, matching Spring Boot's
  default so new applications no longer suppress WARN/INFO output.
- Keep the <springProfile name="development"> block for
  environment-specific logging, with the commented example logger now
  using the application's real default package (the skeleton previously
  contained a leftover hard-coded 'Test38' logger name).
- Trim the commented file-appender example to the Boot include form.
@codeconsole codeconsole changed the title Add opt-in zero-config Logback Forge feature; document logback-spring.xml as optional Simplify generated logback-spring.xml and add opt-in zero-config Logback Forge feature Jul 10, 2026
@codeconsole

Copy link
Copy Markdown
Contributor Author

Following up on your "at a max I would only be OK stripping parts of that file that are no longer needed and are explicitly duplicative of spring defaults" — done in d2422cd. The generated logback-spring.xml (skeleton and Forge) now composes Spring Boot's own defaults.xml + console-appender.xml instead of hand-copying them, uses Boot's default INFO root level instead of ERROR (so new apps no longer swallow WARN/INFO output), and keeps the <springProfile name="development"> block for environment-specific logging:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>

    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
    </root>

    <springProfile name="development">
        <logger name="StackTrace" level="ERROR"/>

<!--        <logger name="com.example.myapp" level="DEBUG"/>-->

<!--        <logger name="org.hibernate.SQL" level="DEBUG"/>-->
<!--        <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>-->
<!--        <logger name="org.springframework.security" level="TRACE"/>-->
    </springProfile>

<!--    logging to a file: set logging.file.name in application.yml and include Spring Boot's file appender -->
<!--    <include resource="org/springframework/boot/logging/logback/file-appender.xml"/>-->
<!--    <root level="INFO">-->
<!--        <appender-ref ref="FILE"/>-->
<!--    </root>-->
</configuration>

(The commented example logger is rendered with the app's actual default package. This also fixes a leftover hard-coded Test38 logger name that the skeleton file had been shipping.)

@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 49.6848%. Comparing base (08bd0bf) to head (a62acb7).
⚠️ Report is 2 commits behind head on 8.0.x.

Additional details and impacted files

Impacted file tree graph

@@                Coverage Diff                 @@
##                8.0.x     #15757        +/-   ##
==================================================
+ Coverage     49.6709%   49.6848%   +0.0138%     
- Complexity      17017      17024         +7     
==================================================
  Files            2004       2004                
  Lines           93896      93896                
  Branches        16448      16448                
==================================================
+ Hits            46639      46652        +13     
+ Misses          40078      40067        -11     
+ Partials         7179       7177         -2     

see 5 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

----
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example produces an application with no log output at all. Once a logback-spring.xml exists, it replaces Spring Boot's bundled configuration entirely, and defaults.xml only contributes conversion rules and a few logger levels — no appenders. With no console-appender.xml include and no <root> with an appender-ref, the root logger has no appenders, so everything (including the org.hibernate.SQL DEBUG the example enables) goes nowhere. Anyone who copies this snippet when re-adding the file will silence their application.

The example should match the generated starter's shape:

<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>

    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
    </root>

    <springProfile name="development">
        <logger name="org.hibernate.SQL" level="DEBUG"/>
    </springProfile>
</configuration>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — you're right, with no appender the example silenced everything it claimed to enable. Fixed in 2b1902f: the example now matches the generated starter's shape (defaults.xml + console-appender.xml includes and a <root level="INFO"> with the CONSOLE appender-ref), and the surrounding text now states explicitly that a custom logback-spring.xml replaces Spring Boot's bundled configuration entirely and must declare its own appenders.

com.example.myapp: DEBUG # your packages
org.hibernate.SQL: DEBUG # see the generated SQL
file:
name: logs/myapp.log # setting this activates Spring Boot's file appender

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"setting this activates Spring Boot's file appender" is only true in the zero-config case. When a logback-spring.xml is present — which is the default for newly generated applications, per the paragraph above — the custom file replaces Boot's base.xml, so logging.file.name sets the LOG_FILE property but nothing consumes it: no file appender appears until the user uncomments the file-appender.xml include in the generated file. Since this section presents the yaml as generally applicable, the comment will mislead the majority of readers who still have the generated file.

Suggest scoping it, e.g. # activates Boot's file appender when no logback-spring.xml is present (otherwise uncomment the file-appender include in that file). The same line in the upgrade-guide section is fine as-is, because there it sits under "With no configuration file present…".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — with the generated file present (the default), logging.file.name sets LOG_FILE but nothing consumes it. Scoped in 2b1902f using your suggested wording: the comment now reads "activates Boot's file appender only when no logback-spring.xml is present (otherwise uncomment the file-appender include in that file)". Left the upgrade-guide occurrence as-is since it sits under "With no configuration file present…".


When properties are not enough — custom appenders, structured output, or per-environment appender routing — add a `grails-app/conf/logback-spring.xml` file. Use the `-spring` variant (not plain `logback.xml`), because it is processed by Spring Boot and unlocks `<springProfile>` and `<springProperty>`. The Grails environments `development`, `test` and `production` map to the corresponding Spring profiles, so `<springProfile name="development">` blocks configure environment-specific logging — one of the features lost when Logback removed Groovy configuration.

TIP: When generating a project with https://start.grails.org[Grails Forge], select the *Zero-config Logback Logging* feature to omit the generated `grails-app/conf/logback-spring.xml` and rely entirely on Spring Boot's defaults plus `application.yml` tuning as described above.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neither doc spells out what selecting zero-config gives up relative to the generated file. The current text explains what still works (levels, patterns, per-environment levels via environments), but a reader choosing between the two modes can't see the boundary. Worth one sentence here listing what requires the XML file and is therefore lost until it's re-added:

  • <springProfile>-conditional appenders/routing (per-environment levels still work via yaml, but per-environment appenders don't)
  • the starter's development-profile StackTrace logger setting
  • activating a file appender purely via logging.file.name works in zero-config (Boot's base.xml), so that one actually only works in this mode — another reason to scope the comment on line 33.

Everything else in this section applies to both modes, which is exactly why an explicit supported/unsupported line would make the choice easy.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 2b1902f — a paragraph after the Forge TIP now draws the boundary explicitly: without the file you give up what only XML can express (<springProfile>-conditional appenders/routing — per-environment levels still work via the environments block — and the starter's development-profile StackTrace logger), while logging.file.name auto-activation of the file appender only works without the file, which is also why the yaml comment above is now scoped.

@codeconsole codeconsole requested a review from borinquenkid July 11, 2026 00:26
…ed-file behavior

Address review feedback on apache#15757:

- The upgrade-guide example logback-spring.xml declared no appenders, so
  copying it produced an application with no log output (a custom file
  replaces Spring Boot's bundled configuration entirely, and defaults.xml
  contributes no appenders). The example now composes Boot's defaults.xml
  and console-appender.xml with a root appender-ref, matching the
  generated starter's shape.
- Scope the logging.file.name comment in the logging reference: it only
  activates Boot's file appender when no logback-spring.xml is present;
  otherwise the file-appender include in the generated file must be
  uncommented.
- Spell out the boundary between the generated file and zero-config: what
  each mode gives up (springProfile-conditional appenders/routing and the
  StackTrace dev logger vs logging.file.name auto-activation).
…figuration feature

With the generated file's content fixes landed separately in apache#15973
(simplified to compose Spring Boot's defaults with an INFO root level),
flip this PR back to its original intent: newly generated applications
ship no logback-spring.xml at all.

- Profile skeleton: remove grails-app/conf/logback-spring.xml.
- Forge: the default logback feature only adds the grails-logging
  dependency; Spring Boot's zero-config Logback defaults apply. A new
  visible logback-config feature (Logback Configuration) generates the
  simplified starter file on demand and supersedes the default feature.
- Docs: the logging reference and upgrade guide describe zero-config
  logging as the default for new applications, application.yml level
  tuning (including per-environment via the environments block), when to
  add logback-spring.xml, and the boundaries between the two modes.
- Tests: LogbackSpec asserts no file is generated by default and that
  logback-config emits the simplified configuration with grails-logging
  declared exactly once.
@codeconsole codeconsole changed the title Simplify generated logback-spring.xml and add opt-in zero-config Logback Forge feature Stop generating logback-spring.xml by default; add opt-in Logback Configuration Forge feature Jul 11, 2026
@codeconsole

Copy link
Copy Markdown
Contributor Author

With the generated file's content fixes now merged separately via #15973, this PR is flipped back to its original scope (537614e): newly generated applications ship no logback-spring.xml — Spring Boot's zero-config Logback defaults apply — and the visible Logback Configuration (logback-config) Forge feature generates the #15973-simplified starter file on demand for anyone who wants to manage logging in XML.

Since the earlier discussion, the concerns raised then have been addressed in what's now the default-less setup:

  • Per-environment log levels work with zero XML via the environments block in application.yml (verified earlier in this thread on Grails 8 / Spring Boot 4, alongside <springProfile> which also still works).
  • The docs (logging reference + upgrade guide) spell out the zero-config defaults, application.yml tuning, when the XML file is still needed (env-specific appenders/routing), that a custom file replaces Boot's bundled configuration and must declare its own appenders, and the exact boundaries between the two modes.

PR title/description updated back to match.

Document the remaining Spring Boot logging properties so application.yml
covers the full non-XML surface: console/file output patterns, custom and
predefined (web, sql) logger groups, per-appender thresholds, file-appender
rotation via logging.logback.rollingpolicy.*, the debug/trace top-level
shortcuts, and ANSI color control via spring.output.ansi.enabled. Notes
which properties are consumed by Boot's appenders and therefore apply in
both zero-config mode and a logback-spring.xml composing Boot's includes.
@codeconsole

codeconsole commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

@jamesfredley before this goes further I want to take each concern you've raised head-on, with working configuration for every behavior you've said requires logback-spring.xml. The short version: every expectation you've named is met with zero XML — including environment-conditional appenders, not just levels — and the catalog at the end maps each logback-spring.xml construct to its no-file equivalent.

1. "Environment/spring profile specific logging is only possible via logback-spring.xml"

This is the factual crux, and it's not correct — I verified it earlier in this thread on a generated Grails 8 app (Spring Boot 4) by checking effective logger levels at boot. Grails environments map to Spring profiles, so per-environment logging works three ways, two of them with no XML:

# grails-app/conf/application.yml — the environments block every Grails app already has
environments:
    development:
        logging:
            level:
                com.example.myapp: DEBUG
# grails-app/conf/application-development.yml — profile-specific config, same effect
logging:
    level:
        com.example.myapp: DEBUG

And <springProfile> in a logback-spring.xml still works under Spring Boot 4 if the file is added — nothing regressed. All three were ✅ in the table above.

2. "having more detailed logs in dev is expected behavior and having less detailed logs in prod is also"

Agreed — and here it is, complete, in the config format every Grails developer already uses daily:

environments:
    development:
        logging:
            level:
                com.example.myapp: DEBUG
                org.hibernate.SQL: DEBUG
    production:
        logging:
            level:
                root: WARN

Dev verbose, prod quiet, per-environment, zero XML. This is not a workaround; it's the same Spring Boot property surface the docs in this PR now cover end to end (levels, patterns, logger groups, per-appender thresholds, file output + rotation, debug:/trace: shortcuts).

3. "continuing to generate a logback-spring.xml that provides the same historical environment specific logging, low default level in dev, as expected"

The historical file never provided that. Here is what it actually shipped, verbatim:

<root level="ERROR">          <!-- applied to EVERY environment, including development -->
    <appender-ref ref="CONSOLE"/>
</root>

<springProfile name="development">
    <logger name="StackTrace" level="ERROR" />
    <!-- every other logger in this block was commented out -->
</springProfile>

Out of the box, the historical file gave a new developer ERROR-only logging in development — it suppressed all WARN and INFO output, including framework startup warnings. That is less dev logging than Spring Boot's zero-config default (INFO root, colorized console) provides. The "excellent out of the box experience" you're defending is one where a new user's first question is "why isn't my app logging anything?" — the exact papercut #15973 just had to fix. If historical expected behavior is the standard, the file fails it and the Boot default exceeds it.

4. "There were so many tickets when Logback nuked the groovy config and I don't want us back in that situation"

That situation was a capability removal: logback.groovy stopped working and there was no equivalent. Nothing here stops working. logback-spring.xml with <springProfile> remains fully supported, documented, and testable — this PR only stops scaffolding a file into applications that don't need one. The recovery path is one click (the Logback Configuration Forge feature) or copying the documented snippet, and both the upgrade guide and the logging reference now spell it out. There is no lost capability for anyone to file a ticket about.

5. "I don't think that is the majority use case for generated apps on forge, which in theory are greenfield"

Greenfield is precisely where zero-config is the right default. A greenfield app has no custom appenders, no structured output pipeline, no per-environment routing — it needs sensible levels and a readable console, which Boot's defaults provide with no file to read, understand, or undo. This is also what every greenfield Spring Boot app gets: start.spring.io ships no logging config file at all, and Grails 8 is a Spring Boot 4 framework. A majority-of-users argument favors the convention the surrounding ecosystem has already settled on — and the users who do want the XML file are exactly the ones capable of ticking a clearly named Forge feature.

The equivalence catalog: everything <springProfile> does in XML, done in YAML

The environments block conditions any logging.* property — the same conditionality <springProfile> provides for XML blocks — and Spring Boot exposes its appenders through properties. Concretely, everything you would reach for the file to do:

Verbose loggers in development only

<springProfile name="development">
    <logger name="com.example.myapp" level="DEBUG"/>
    <logger name="org.hibernate.SQL" level="DEBUG"/>
</springProfile>
environments:
    development:
        logging:
            level:
                com.example.myapp: DEBUG
                org.hibernate.SQL: DEBUG

Quieter root level in production only

<springProfile name="production">
    <root level="WARN"/>
</springProfile>
environments:
    production:
        logging:
            level:
                root: WARN

Custom console pattern

<property name="CONSOLE_LOG_PATTERN"
          value="%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
logging:
    pattern:
        console: "%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n"

File appender in production only — the "env-conditional appender" case. Boot activates its file appender when logging.file.name is set, so setting it under one environment activates the appender in that environment only:

<springProfile name="production">
    <include resource="org/springframework/boot/logging/logback/file-appender.xml"/>
    <root level="INFO">
        <appender-ref ref="FILE"/>
    </root>
</springProfile>
environments:
    production:
        logging:
            file:
                name: /var/log/myapp/app.log
            logback:
                rollingpolicy:
                    max-file-size: 10MB
                    max-history: 30

Structured JSON logs in production only — the canonical "XML-only" example. The XML route needs a third-party dependency (logstash-logback-encoder) plus the appender definition; Spring Boot 4 does it natively from properties (ECS, Logstash or GELF format):

<!-- requires net.logstash.logback:logstash-logback-encoder on the classpath -->
<springProfile name="production">
    <appender name="JSON" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
    </appender>
    <root level="INFO">
        <appender-ref ref="JSON"/>
    </root>
</springProfile>
environments:
    production:
        logging:
            structured:
                format:
                    console: ecs

Per-appender thresholds (logging.threshold.console / file) and logger groups (logging.group.*) are properties too, and all of the above compose freely per environment.

The only thing the property surface cannot express is declaring an arbitrary third-party Logback appender (Sentry, SMTP, syslog, a sifting appender). Two things about that: it does not require logback-spring.xml either — modern integrations ship Spring Boot starters that register their appenders automatically (Sentry's does exactly this), and Logback is fully configurable programmatically — and the generated file never declared one; that entire section was commented out. logback-spring.xml is a convenient format for hand-built Logback topologies, not a gatekeeper for any capability. Removing it from the skeleton takes away nothing any generated app ever had.

Given that every expectation raised here is demonstrably met without the file — conditionally per environment, appenders included — and the historical file demonstrably did not deliver the dev experience being cited in its defense, I think the default should stay off. Happy to walk through any of the examples above on a live generated app.

@testlens-app

testlens-app Bot commented Jul 12, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

🏷️ Commit: a62acb7
▶️ Tests: 22242 executed
⚪️ Checks: 59/59 completed


Learn more about TestLens at testlens.app.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

4 participants