Search code examples
loggingjbossjboss-eap-7

Filtering Middleware Frames from Stack Trace Logs in JBoss 7 with Filter-spec


I want to reduce the length of my exception logging on JBoss 7 while losing as little valuable information as possible. What I am trying to do is to filter out any JBoss middleware stack frames which usual provide litle insight into actual issues in application code. Example of frames I am trying to filter: "at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)" or " at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)".

I have been able filter out regular log entries completely using a filter-spec in the logging configuration in the JBoss configuration file:

<console-handler name="CONSOLE">
    <level name="TRACE" />
    <formatter>
    <pattern-formatter
            pattern="%K{level}%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n" />
</formatter>
    <filter-spec value="not(match(&quot;Validation&quot;))" />
</console-handler>

I have also been able to replace log entries that match a particular filter expression:

<console-handler name="CONSOLE">
    <level name="TRACE" />
    <formatter>
    <pattern-formatter
            pattern="%K{level}%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n" />
</formatter>
    <filter-spec value="substituteAll(&quot;Validation&quot;, &quot;Im here!!!!&quot;)" />
    <filter-spec value="not(match(&quot;Validation&quot;))" />
</console-handler>

But when I try to substitute an exception stacktrace frame instead of a regular log entry it does not work. the filter-spec I am trying to use is:

<filter-spec value="substituteAll(&quot;sun.reflect.NativeMethodAccessorImpl&quot;, &quot;&quot;)" />

But this filter seems to ignore stack traces.

Can anyone suggest a way to filter these stack traces in a JBoss environment?


Solution

  • Unfortunately filters don't work on exceptions. Also currently there's no ability to use custom filters either. You can however either use a custom-formatter or custom-handler which could do that for your.

    An example custom handler could look something like:

    public class TrimCauseHandler extends Handler {
    
        private Handler delegate;
    
        @Override
        public synchronized void publish(final LogRecord record) {
            if (delegate != null) {
                final Throwable cause = record.getThrown();
                if (cause != null) {
                    final Collection<StackTraceElement> st = new ArrayList<>();
                    for (StackTraceElement e : cause.getStackTrace()) {
                        final String className = e.getClassName();
                        if (className.startsWith("org.jboss.as") || className.startsWith("org.wildfly")) {
                            continue;
                        }
                        st.add(e);
                    }
                    cause.setStackTrace(st.toArray(new StackTraceElement[0]));
                }
                record.setThrown(cause);
                delegate.publish(record);
            }
        }
    
        @Override
        public synchronized void flush() {
            if (delegate != null) {
                delegate.flush();
            }
        }
    
        @Override
        public synchronized void close() throws SecurityException {
            if (delegate != null) {
                delegate.close();
            }
        }
    
        public synchronized Handler getDelegate() {
            return delegate;
        }
    
        public synchronized void setDelegate(final Handler delegate) {
            this.delegate = delegate;
        }
    }
    

    Then a CLI command to use it for the console handler would be something like:

    /subsystem=logging/custom-handler=test:add(module=your.module, class=org.jboss.example.handlers.TrimCauseHandler, properties={delegate="CONSOLE"})
    /subsystem=logging/root-logger=ROOT:remove-handler(name=CONSOLE)
    /subsystem=logging/root-logger=ROOT:add-handler(name=test)
    

    It doesn't look like arrays are supported property types so you'd have to wrap each handler in a TrimCauseHandler or do something odd like make setDelegate() add the handler to a collection of some sort.

    Update

    I just want to point out there is now an open JIRA to allow for custom filters.