Skip to content

Instantly share code, notes, and snippets.

@todd-elvers
Last active November 7, 2018 18:10
Show Gist options
  • Save todd-elvers/3e756b9e73c39d5ab246d016bc9bfc02 to your computer and use it in GitHub Desktop.
Save todd-elvers/3e756b9e73c39d5ab246d016bc9bfc02 to your computer and use it in GitHub Desktop.
Suppressing logging events based on exception (includes Grails example)
import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;
/**
* This is a simple filter that suppresses logging events based on the exception that caused it.
*/
public class ExceptionSuppressingFilter extends Filter<LoggingEvent> {
private Set<String> exceptionClassNamesToSuppress = new HashSet<>();
@Override
public FilterReply decide(LoggingEvent event) {
// We only care about logs that were generated from exceptions
if (event.getThrowableProxy() == null) return FilterReply.NEUTRAL;
return shouldSuppress(event)
? FilterReply.DENY
: FilterReply.NEUTRAL;
}
private boolean shouldSuppress(LoggingEvent event) {
return exceptionClassNamesToSuppress.contains(event.getThrowableProxy().getClassName());
}
/**
* Since {@link LoggingEvent} only has a reference to the name of the exception that was thrown,
* we only store the names of the classes of the exceptions to suppress, not the exceptions
* themselves.
*
* @param exceptionsToSuppress the exceptions we do not want Logback to log to the console.
*/
public void setExceptionsToSuppress(List<Class<Exception>> exceptionsToSuppress) {
this.exceptionClassNamesToSuppress = exceptionsToSuppress.stream()
.map(Class::getName)
.collect(Collectors.toSet());
}
}
import grails.util.BuildSettings
import grails.util.Environment
import org.springframework.boot.logging.logback.ColorConverter
import org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter
import java.nio.charset.Charset
conversionRule 'clr', ColorConverter
conversionRule 'wex', WhitespaceThrowableProxyConverter
// See http://logback.qos.ch/manual/groovy.html for details on configuration
appender('STDOUT', ConsoleAppender) {
encoder(PatternLayoutEncoder) {
charset = Charset.forName('UTF-8')
pattern =
'%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} ' + // Date & time
'[%clr(%5p)] ' + // Log level
'%clr(%-40.40logger{39}){cyan} %clr(:){faint} ' + // Logger
'%m%n%wex' // Message
}
// This suppresses log messages depending on what exception caused them
filter(ExceptionSuppressingFilter) {
exceptionsToSuppress = [
YourSpecialExceptionHere.class
]
}
}
root WARN, ['STDOUT']
@todd-elvers
Copy link
Author

This is a generalized solution for suppressing logging events based on the exception that caused it. This obviously does not prevent the exception, it simply instructs Logback to not log the exception.

Use case: we had a particular test that was causing an exception because the testing framework could programmatically logout faster than Grails could finish processing the request, which caused errors in strange places. However this only ever happened during the tests, real users could not reasonably create this exception. The solution to this was to capture the scenario where this test-only exception was occurring and re-throw it as one of our custom exceptions, then we were able to use the above code to silence that exception entirely.

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