codeconsole opened a new pull request, #15564:
URL: https://github.com/apache/grails-core/pull/15564

   ## Fix duplicate stack trace logging in DefaultStackTraceFilterer            
                                                                                
                                                                                
                                                                                
                                                         
     When an exception occurs in a Grails controller, the same error is logged 
multiple times to the `StackTrace` logger. For a typical  
     `InvocationTargetException` wrapping a `RuntimeException`, this produces 
3-4 separate ERROR log entries for a single request:
                                                                                
                                                         
     1. `StackTrace` logger: Full stack trace of the wrapper exception
     2. `StackTrace` logger: Full stack trace of the root cause
     3. `StackTrace` logger: Full stack trace of the wrapper again (condensed)  
                                                         
     4. `GrailsExceptionResolver` logger: The exception with request context
                                                                                
                                                         
     Entries 1-3 all come from `DefaultStackTraceFilterer.filter()`. The 
`filter(Throwable source, boolean recursive)` method walks the  
     cause chain and calls `filter(Throwable source)` for each throwable. But 
`filter(Throwable source)` logs the full stack trace via   
     `STACK_LOG.error(FULL_STACK_TRACE_MESSAGE, source)` every time it trims a 
trace — so each cause in the chain gets its own log entry.
                                                                     
     This is compounded by the fact that 
`GrailsExceptionResolver.logStackTrace()` then logs the exception a final time 
with request     
     context. The filterer and the resolver were written independently — the 
filterer doesn't know the resolver will also log, and the
     resolver doesn't know the filterer already logged.                         
                                                         
                                                                     
     ### Fix
   
     Extract the stack trace trimming logic into a private 
`doFilter(Throwable)` method that filters without logging. The recursive walk 
     calls `doFilter()` for each cause in the chain. The public 
`filter(Throwable source)` method calls `doFilter()` and then logs the
     full stack trace **once** for the top-level exception (which naturally 
includes its causes in the log output).                      
                                                                     
     This reduces the `StackTrace` logger output from N entries (one per cause) 
to 1 entry, while preserving all existing behavior:      
      
     - Stack traces are still recursively filtered for all causes               
                                                         
     - The full unfiltered trace is still logged before trimming (for debugging)
     - The `StackTraceFilterer` interface is unchanged                          
                                                         
     - Custom `GrailsExceptionResolver` subclasses are unaffected
     - All existing tests pass without modification 


-- 
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