Filtering stacktraces by evaluating packages

Hello, I would like to simplify stacktraces when errors occur in an application. For example, with a hypothetical stack such as: com.xyz.Wombat.doSomething javax.servlet.http.HttpServlet.service org.appserver.JspCompiler.handleJsp org.appserver.ServletEngine.handleServlet java.lang.Thread.run ...going down from top-to-bottom, I'd like to detect that line "org.appserver.JspCompiler.handleJsp" has been found, and exclude it -- and all subsequent "lower down" stack frames -- from logging output. Looking at http://logback.qos.ch/manual/layouts.html#Evaluators I assume it must be possible with EventEvaluator because of the syntax %xEx{evaluator-n} but I can't find an example. Furthermore, as I set up LogBack programmatically (and not via XML or any of bundled "configurator"), I'd be happiest if I could be directed towards an API-based example. If it's of any use, here are two methods extracted from the class that I use to configure LogBack (incomplete but should help see what I'm trying to do, and how): private synchronized boolean maybeInitialize(final Logger logger, String pattern) { // will throw ClassCastException if our configuration is incorrect (or accessed from wrong classloader) // that's OK, it's what should happen... final ch.qos.logback.classic.Logger impl = (ch.qos.logback.classic.Logger)logger; // if there's an appender, then the logger seems to have been configured Iterator<Appender<ILoggingEvent>> it = impl.iteratorForAppenders(); if (it.hasNext()) { return false; } String logFileName = impl.getName(); if (logFileName.startsWith(LOG_FILE_STDPREFIX) && logFileName.length() > LOG_FILE_STDPREFIX.length()) { logFileName = logFileName.substring(LOG_FILE_STDPREFIX.length()); } logFileName += LOG_FILE_EXTENSION; Appender<ILoggingEvent> appender; if (CONFIG_VALUE_ROLL_TYPE_DATE.equals(_rollType)) { appender = createRollByDateFileAppender(logFileName, pattern != null ? pattern : PATTERN_FOR_DATE); } else if (CONFIG_VALUE_ROLL_TYPE_SIZE.equals(_rollType)) { appender = createRollBySizeFileAppender(logFileName, pattern); } else { appender = createFileAppender(logFileName, pattern); } appender.start(); impl.addAppender(appender); impl.setLevel(_level); impl.setAdditive(false); return true; } private synchronized boolean maybeInitialize(final Logger logger, String pattern) { // will throw ClassCastException if our configuration is incorrect (or accessed from wrong classloader) // that's OK, it's what should happen... final ch.qos.logback.classic.Logger impl = (ch.qos.logback.classic.Logger)logger; // if there's an appender, then the logger seems to have been configured Iterator<Appender<ILoggingEvent>> it = impl.iteratorForAppenders(); if (it.hasNext()) { return false; } String logFileName = impl.getName(); if (logFileName.startsWith(LOG_FILE_STDPREFIX) && logFileName.length() > LOG_FILE_STDPREFIX.length()) { logFileName = logFileName.substring(LOG_FILE_STDPREFIX.length()); } logFileName += LOG_FILE_EXTENSION; Appender<ILoggingEvent> appender; if (CONFIG_VALUE_ROLL_TYPE_DATE.equals(_rollType)) { appender = createRollByDateFileAppender(logFileName, pattern != null ? pattern : PATTERN_FOR_DATE); } else if (CONFIG_VALUE_ROLL_TYPE_SIZE.equals(_rollType)) { appender = createRollBySizeFileAppender(logFileName, pattern); } else { appender = createFileAppender(logFileName, pattern); } appender.start(); impl.addAppender(appender); impl.setLevel(_level); impl.setAdditive(false); return true; } Thanks, Christopher

I've done something very similar to this here: https://github.com/Mahoney/lidalia-logging/ Basically using the decorator pattern around Events. Specifically look at EventTransformingAppender and StackTraceCleanser, and have a look at src/main/resources/logback.xml to see how to configure it. It's currently very specific to getting rid of Groovy noise, but it would be trivial to generalise it to get rid of other frames. ----- Original Message -----
From: "Christopher BROWN" <brown@reflexe.fr> To: "LogBack Users list" <logback-user@qos.ch> Sent: Monday, 5 December, 2011 11:44:25 AM Subject: [logback-user] Filtering stacktraces by evaluating packages Hello,
I would like to simplify stacktraces when errors occur in an application. For example, with a hypothetical stack such as:
com.xyz.Wombat.doSomething javax.servlet.http.HttpServlet.service org.appserver.JspCompiler.handleJsp org.appserver.ServletEngine.handleServlet java.lang.Thread.run
...going down from top-to-bottom, I'd like to detect that line "org.appserver.JspCompiler.handleJsp" has been found, and exclude it -- and all subsequent "lower down" stack frames -- from logging output.
Looking at http://logback.qos.ch/manual/layouts.html#Evaluators I assume it must be possible with EventEvaluator because of the syntax %xEx{evaluator-n} but I can't find an example. Furthermore, as I set up LogBack programmatically (and not via XML or any of bundled "configurator"), I'd be happiest if I could be directed towards an API-based example.
If it's of any use, here are two methods extracted from the class that I use to configure LogBack (incomplete but should help see what I'm trying to do, and how):
private synchronized boolean maybeInitialize(final Logger logger, String pattern) { // will throw ClassCastException if our configuration is incorrect (or accessed from wrong classloader) // that's OK, it's what should happen... final ch.qos.logback.classic.Logger impl = (ch.qos.logback.classic.Logger)logger;
// if there's an appender, then the logger seems to have been configured Iterator<Appender<ILoggingEvent>> it = impl.iteratorForAppenders(); if (it.hasNext()) { return false; }
String logFileName = impl.getName(); if (logFileName.startsWith(LOG_FILE_STDPREFIX) && logFileName.length()
LOG_FILE_STDPREFIX.length()) { logFileName = logFileName.substring(LOG_FILE_STDPREFIX.length()); } logFileName += LOG_FILE_EXTENSION;
Appender<ILoggingEvent> appender; if (CONFIG_VALUE_ROLL_TYPE_DATE.equals(_rollType)) { appender = createRollByDateFileAppender(logFileName, pattern != null ? pattern : PATTERN_FOR_DATE); } else if (CONFIG_VALUE_ROLL_TYPE_SIZE.equals(_rollType)) { appender = createRollBySizeFileAppender(logFileName, pattern); } else { appender = createFileAppender(logFileName, pattern); }
appender.start();
impl.addAppender(appender); impl.setLevel(_level); impl.setAdditive(false);
return true; }
private synchronized boolean maybeInitialize(final Logger logger, String pattern) { // will throw ClassCastException if our configuration is incorrect (or accessed from wrong classloader) // that's OK, it's what should happen... final ch.qos.logback.classic.Logger impl = (ch.qos.logback.classic.Logger)logger;
// if there's an appender, then the logger seems to have been configured Iterator<Appender<ILoggingEvent>> it = impl.iteratorForAppenders(); if (it.hasNext()) { return false; }
String logFileName = impl.getName(); if (logFileName.startsWith(LOG_FILE_STDPREFIX) && logFileName.length()
LOG_FILE_STDPREFIX.length()) { logFileName = logFileName.substring(LOG_FILE_STDPREFIX.length()); } logFileName += LOG_FILE_EXTENSION;
Appender<ILoggingEvent> appender; if (CONFIG_VALUE_ROLL_TYPE_DATE.equals(_rollType)) { appender = createRollByDateFileAppender(logFileName, pattern != null ? pattern : PATTERN_FOR_DATE); } else if (CONFIG_VALUE_ROLL_TYPE_SIZE.equals(_rollType)) { appender = createRollBySizeFileAppender(logFileName, pattern); } else { appender = createFileAppender(logFileName, pattern); }
appender.start();
impl.addAppender(appender); impl.setLevel(_level); impl.setAdditive(false);
return true; }
Thanks, Christopher
_______________________________________________ Logback-user mailing list Logback-user@qos.ch http://mailman.qos.ch/mailman/listinfo/logback-user

Hi Robert, Thanks, I'll bookmark this. Having said that, I suspect there's a simpler way using EventEvaluator but I can't see how to wire that up to the exception conversion handler. Simpler meaning here "installing one class as opposed to wrapping up many classes", or "one extra line of Java code and a little class to go along with it". Also, if I understand your code correctly, it filters frames (e.g.: if there's a frame in the middle of the stack with org.codehaus.groovy.runtime.*, it gets dropped without necessarily affecting frames higher up or lower down), whereas the EventEvaluator acts as a cut-off ("don't go any further down"). Even if it's not exactly what I was looking for, I can see other cases where I could apply what you've suggested, so thanks again! -- Christopher On 5 December 2011 14:33, Robert Elliot <rob@lidalia.org.uk> wrote:
I've done something very similar to this here: https://github.com/Mahoney/lidalia-logging/
Basically using the decorator pattern around Events.
Specifically look at EventTransformingAppender and StackTraceCleanser, and have a look at src/main/resources/logback.xml to see how to configure it. It's currently very specific to getting rid of Groovy noise, but it would be trivial to generalise it to get rid of other frames.
----- Original Message -----
From: "Christopher BROWN" <brown@reflexe.fr> To: "LogBack Users list" <logback-user@qos.ch> Sent: Monday, 5 December, 2011 11:44:25 AM Subject: [logback-user] Filtering stacktraces by evaluating packages Hello,
I would like to simplify stacktraces when errors occur in an application. For example, with a hypothetical stack such as:
com.xyz.Wombat.doSomething javax.servlet.http.HttpServlet.service org.appserver.JspCompiler.handleJsp org.appserver.ServletEngine.handleServlet java.lang.Thread.run
...going down from top-to-bottom, I'd like to detect that line "org.appserver.JspCompiler.handleJsp" has been found, and exclude it -- and all subsequent "lower down" stack frames -- from logging output.
Looking at http://logback.qos.ch/manual/layouts.html#Evaluators I assume it must be possible with EventEvaluator because of the syntax %xEx{evaluator-n} but I can't find an example. Furthermore, as I set up LogBack programmatically (and not via XML or any of bundled "configurator"), I'd be happiest if I could be directed towards an API-based example.
If it's of any use, here are two methods extracted from the class that I use to configure LogBack (incomplete but should help see what I'm trying to do, and how):
private synchronized boolean maybeInitialize(final Logger logger, String pattern) { // will throw ClassCastException if our configuration is incorrect (or accessed from wrong classloader) // that's OK, it's what should happen... final ch.qos.logback.classic.Logger impl = (ch.qos.logback.classic.Logger)logger;
// if there's an appender, then the logger seems to have been configured Iterator<Appender<ILoggingEvent>> it = impl.iteratorForAppenders(); if (it.hasNext()) { return false; }
String logFileName = impl.getName(); if (logFileName.startsWith(LOG_FILE_STDPREFIX) && logFileName.length()
LOG_FILE_STDPREFIX.length()) { logFileName = logFileName.substring(LOG_FILE_STDPREFIX.length()); } logFileName += LOG_FILE_EXTENSION;
Appender<ILoggingEvent> appender; if (CONFIG_VALUE_ROLL_TYPE_DATE.equals(_rollType)) { appender = createRollByDateFileAppender(logFileName, pattern != null ? pattern : PATTERN_FOR_DATE); } else if (CONFIG_VALUE_ROLL_TYPE_SIZE.equals(_rollType)) { appender = createRollBySizeFileAppender(logFileName, pattern); } else { appender = createFileAppender(logFileName, pattern); }
appender.start();
impl.addAppender(appender); impl.setLevel(_level); impl.setAdditive(false);
return true; }
private synchronized boolean maybeInitialize(final Logger logger, String pattern) { // will throw ClassCastException if our configuration is incorrect (or accessed from wrong classloader) // that's OK, it's what should happen... final ch.qos.logback.classic.Logger impl = (ch.qos.logback.classic.Logger)logger;
// if there's an appender, then the logger seems to have been configured Iterator<Appender<ILoggingEvent>> it = impl.iteratorForAppenders(); if (it.hasNext()) { return false; }
String logFileName = impl.getName(); if (logFileName.startsWith(LOG_FILE_STDPREFIX) && logFileName.length()
LOG_FILE_STDPREFIX.length()) { logFileName = logFileName.substring(LOG_FILE_STDPREFIX.length()); } logFileName += LOG_FILE_EXTENSION;
Appender<ILoggingEvent> appender; if (CONFIG_VALUE_ROLL_TYPE_DATE.equals(_rollType)) { appender = createRollByDateFileAppender(logFileName, pattern != null ? pattern : PATTERN_FOR_DATE); } else if (CONFIG_VALUE_ROLL_TYPE_SIZE.equals(_rollType)) { appender = createRollBySizeFileAppender(logFileName, pattern); } else { appender = createFileAppender(logFileName, pattern); }
appender.start();
impl.addAppender(appender); impl.setLevel(_level); impl.setAdditive(false);
return true; }
Thanks, Christopher
_______________________________________________ Logback-user mailing list Logback-user@qos.ch http://mailman.qos.ch/mailman/listinfo/logback-user
Logback-user mailing list Logback-user@qos.ch http://mailman.qos.ch/mailman/listinfo/logback-user
participants (2)
-
Christopher BROWN
-
Robert Elliot