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]

Reply via email to