codeconsole opened a new pull request, #15666: URL: https://github.com/apache/grails-core/pull/15666
## Summary Follow-up to #15564. `GrailsUtil` held a hardcoded `private static final DefaultStackTraceFilterer` that ignored both `grails.logging.stackTraceFiltererClass` (the class-swap key that `GrailsExceptionResolver` honors) and the new `grails.exceptionresolver.logFullStackTraceOnFilter` flag introduced by #15564. Non-resolver callers of the filterer — most visibly `GroovyPageView.handleException` → `GrailsUtil.deepSanitize` on GSP view-render exceptions, plus scheduled jobs and custom code calling `sanitizeRootCause` / `deepSanitize` directly — produced `StackTrace` logger emissions that no config key could suppress. The only workaround was silencing the `StackTrace` logger in logback, which the user guide already calls out as a fallback rather than the intended control surface. This PR closes that gap: `GrailsUtil` now resolves its filterer lazily on first use from `Holders.findApplication().getConfig()`, honoring the same two keys the resolver honors and propagating `logFullStackTraceOnFilter` to `DefaultStackTraceFilterer` instances exactly the way `GrailsExceptionResolver.applyLogFullStackTraceOnFilter()` does. ## Why this matters Pre-7.1, applications could set `grails.logging.stackTraceFiltererClass` to a custom filterer and reach every framework caller — including `GrailsUtil`. The transition through #15564 and the years prior left `GrailsUtil` as the one path the key never reached, which only becomes visible when GSP rendering throws (because that's the path that calls `GrailsUtil.deepSanitize` directly, bypassing the resolver). Apps hitting this today see 2 unfilterable `StackTrace` records per render-time exception in 7.1.x (3 in 7.0.x, before #15564 dropped the redundant trailing `filter(source)`), with no Grails-level knob. After this PR, setting `grails.exceptionresolver.logFullStackTraceOnFilter: false` silences every caller of the filterer — resolver and `GrailsUtil` alike — without logback intervention. ## Design - **Lazy + cached.** Pre-context callers (early init, plain `main`, tests that don't wire an application) get a fresh uncached `DefaultStackTraceFilterer` so a later call after the context boots can still populate the cache. Post-context callers resolve from config and cache for JVM lifetime, matching the historical semantics of the previous `static final` field. - **Backwards compatible.** Unset config yields `DefaultStackTraceFilterer` with `logFullStackTraceOnFilter=true` — identical to the previous hardcoded value. No behavior change for apps that don't set the new keys. - **Defensive.** Every config-read and instantiation path swallows `Throwable` and falls back to `DefaultStackTraceFilterer` with a logged warning. A bad config value can't break `GrailsUtil` callers. - **Respects custom filterers.** `setLogFullStackTraceOnFilter` only applied when the resolved instance is a `DefaultStackTraceFilterer` (or subclass) — matching `GrailsExceptionResolver.applyLogFullStackTraceOnFilter()` exactly. Custom `StackTraceFilterer` implementations remain responsible for their own logging policy. ## Tests New `GrailsUtilStackFiltererSpec` covers three branches: - Falls back to a `DefaultStackTraceFilterer` when no `GrailsApplication` is discoverable - Honors `grails.logging.stackTraceFiltererClass` (verifies a custom filterer is instantiated and invoked) - Propagates `logFullStackTraceOnFilter=false` to `DefaultStackTraceFilterer` instances (verifies no `StackTrace` emission) Existing `GrailsUtilTests` and `StackTraceFiltererSpec` are unchanged and continue to pass. Full `:grails-core:test` and `:grails-web-mvc:test` suites green locally. ## Docs - `loggingFullStackTraces.adoc`: NOTE block clarifying that `GrailsUtil` now participates in the same emission policy as the resolver, so the matrix applies to `GrailsUtil`-driven paths too (including the GSP render path). - `upgrading71x.adoc` §2.13: short paragraph noting `GrailsUtil` now honors both keys and that apps previously silencing the `StackTrace` logger in logback purely to suppress GSP-render noise can now use `logFullStackTraceOnFilter: false` instead. ## Test plan - [ ] CI passes (grails-core + grails-web-mvc test suites) - [ ] Existing apps with no new-key config: identical log output to pre-PR (verified via default-path test) - [ ] App with `grails.exceptionresolver.logFullStackTraceOnFilter: false`: GSP-render exceptions produce zero `StackTrace` records (manually verified against a repro app on 7.2.0-SNAPSHOT after applying the patch) - [ ] App with custom `grails.logging.stackTraceFiltererClass`: `GrailsUtil.deepSanitize` routes through the custom class (verified via custom-class test) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
