Disable Jansi in generated logback-spring.xml to fix console logging after DevTools restart#15694
Disable Jansi in generated logback-spring.xml to fix console logging after DevTools restart#15694jamesfredley wants to merge 3 commits into
Conversation
…after DevTools restart Grails Forge generated logback-spring.xml with <withJansi>true</withJansi> on non-Windows operating systems. Jansi's AnsiConsole.systemInstall() globally replaces System.out/System.err and tracks installation with a static reference counter that lives in the Spring Boot DevTools base classloader, so it survives restarts. Logback's ConsoleAppender calls systemInstall() on start() but never calls systemUninstall() on stop(). After the first DevTools restart the old appender closes the shared Jansi stream while the counter stays above zero, so systemInstall() is a no-op and the new appender writes to a closed, stale stream. Console logging then silently stops, which matches the reported behavior (logging works at startup, dies after the first reload). Spring Boot does not enable Jansi in its own logback defaults; it renders ANSI colors via its own AnsiOutput and the %clr converter, which works without globally replacing System.out. There is therefore no benefit to enabling Jansi, so this removes the OS-based toggle and always generates <withJansi>false</withJansi>, matching the base profile skeleton. Fixes #15663 Assisted-by: claude-code:claude-opus-4.8
There was a problem hiding this comment.
Pull request overview
This PR updates Grails Forge’s generated Logback configuration to disable Jansi consistently, addressing console logging loss after Spring Boot DevTools restarts and aligning Forge output with the base profile skeleton.
Changes:
- Removes OS-dependent Jansi toggling from the Logback feature.
- Hard-codes
<withJansi>false</withJansi>in the generatedlogback-spring.xml. - Adds regression coverage across all application types for the generated Logback config.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/logging/Logback.java |
Removes OS lookup and passes the simplified template arguments. |
grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/logging/template/logback.rocker.raw |
Emits <withJansi>false</withJansi> directly in generated Logback config. |
grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/logging/LogbackSpec.groovy |
Adds a regression test asserting generated configs disable Jansi. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
jdaugherty
left a comment
There was a problem hiding this comment.
I disagree with this PR. It breaks the color logging. We should only be disabling jansi if devtools is selected as the reloading, we shouldn't remove it by default.
| OperatingSystem operatingSystem = generatorContext.getOperatingSystem(); | ||
| boolean jansi = false; | ||
|
|
||
| if (operatingSystem != OperatingSystem.WINDOWS) { |
There was a problem hiding this comment.
This breaks color logging on other OSs. I don't agree with this solution.
|
The change explicitly sets grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/logging/template/logback.rocker.raw |
|
@jdaugherty we should look into why Spring Boot deliberately does not enable Jansi in its own logback defaults. This has been a landmine for Grails for multiple versions. Color is nice, but not at the cost that has been paid, and this time this is Mac/Linux too. The PR that updates Jansi for CLI, might improve this situation. No sure. |
Windows is horrible with utf-8 / coloring. It's the only platform that has this issue. For why Spring Boot doesn't use that default, it doesn't have a lot of defaults. That doesn't stop us from having convention over configuration. This should be a requirement of Linux/Mac OS |
✅ All tests passed ✅🏷️ Commit: ab395d6 Learn more about TestLens at testlens.app. |
Summary
Grails Forge generated
grails-app/conf/logback-spring.xmlwith<withJansi>true</withJansi>on non-Windows operating systems. This breaks console logging after the first Spring Boot DevTools restart.Root cause
AnsiConsole.systemInstall()globally replacesSystem.out/System.errand tracks installation with a static reference counter. That state lives in the Spring Boot DevTools base classloader, so it survives restarts.ConsoleAppendercallssystemInstall()onstart()but never callssystemUninstall()onstop(). After the first DevTools restart, the old appender closes the shared Jansi stream while the counter stays above zero, sosystemInstall()is a no-op and the new appender writes to a closed, stale stream. Console logging then silently stops - exactly the reported behavior (works at startup, dies after the first reload).AnsiOutputand the%clrconverter, which does not replaceSystem.out. There is therefore no benefit to enabling Jansi.Change
<withJansi>false</withJansi>and remove the now-pointless OS-based toggle inLogback, making Forge consistent with the base profile skeleton (which already hardcodesfalse).LogbackSpecregression test asserting the generated config disables Jansi for every application type.Verification
:grails-forge-core:compileJavapasses and the generated Rocker template emits the literal<withJansi>false</withJansi>.LogbackSpectest covers all application types.Fixes #15663