清除Java堆栈跟踪中的噪音

时间:2012-03-07 17:51:59

标签: java exception stack-trace

我的Java堆栈跟踪有很多我不关心的条目,显示通过代理和Spring反射方法的方法调用以及类似的东西。它可能很难从我的代码中挑选出实际来自堆栈跟踪的部分。 Ruby on Rails包含一个“堆栈跟踪清理器”,您可以在其中指定堆栈跟踪模式列表,以便从打印的堆栈跟踪中省略 - 对于Java来说,通用的最佳方法是什么?

最好能在各处工作,包括Eclipse jUnit runner。

6 个答案:

答案 0 :(得分:14)

允许自定义stack trace folding,对dynamic languages特别有用。

IntelliJ http://blogs.jetbrains.com/idea/wp-content/uploads/2010/07/screen-shot-2010-07-12-at-100921-pm.png

Analyzing external stack traces工具。

我可以想象一般工具/过滤器处理日志框架(如)级别。我不认为对此有任何普遍支持,但我认为实施这一点是个好主意。我会看看,也许这不是那么多工作。

更新:我为filtering irrelevant stack trace lines in logs实施了,也遵循了LBCLASSIC-325

答案 1 :(得分:10)

首选堆栈跟踪过滤器模式(查看 java > junit 或搜索{{1}在首选项中)。您可以忽略包(也包含通配符),类或方法。适用于直接测试调用(通过运行为测试),而不适用于stacktraceant等命令行运行。

答案 2 :(得分:6)

我实际上写了一个库 (https://github.com/michaelgantman/Mgnt/releases/tag/1.01) 包含几个实用程序。其中之一是通用堆栈跟踪 我广泛使用的过滤器,发现它非常有用。这个班叫 TextUtils和它的方法getStacktrace()有几个重写的签名。 它需要一个Throwable实例,并允许设置包的包前缀 这是相关的。我们假设您公司的代码始终位于包中 从" com.plain开始。*"所以你设置这样的前缀并执行此操作

logger.info(TextUtils.getStacktrace(e, true, "com.plain."));

这将非常巧妙地过滤出所留下的痕迹的所有无用部分  你有一个非常简洁的堆栈跟踪。另外我发现预先设置它非常方便 前缀,然后只使用方便的方法

TextUtils.getStacktrace(e);

它也会这样做。要预设前缀,只需使用方法

setRelevantPackage("com.plain.");

此外,如果您使用Spring环境,则可以将以下段添加到您的  Spring配置然后你们都设置了:

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
  <property name="targetClass" value="com.mgnt.utils.TextUtils"/>
  <property name="targetMethod" value="setRelevantPackage"/>
  <property name="arguments" value="com.plain."/>
</bean>

图书馆附带写得很好(我希望)Javadoc,它详细解释了所有内容。但这里有一个小小的预告:你会得到一个跟随的堆栈跟踪:

at com.plain.BookService.listBooks()
at com.plain.BookService$$FastClassByCGLIB$$e7645040.invoke()
at net.sf.cglib.proxy.MethodProxy.invoke()
...
at com.plain.LoggingAspect.logging()
at sun.reflect.NativeMethodAccessorImpl.invoke0()
...
at com.plain.BookService$$EnhancerByCGLIB$$7cb147e4.listBooks()
at com.plain.web.BookController.listBooks()

而不是

at com.plain.BookService.listBooks()
at com.plain.BookService$$FastClassByCGLIB$$e7645040.invoke()
at net.sf.cglib.proxy.MethodProxy.invoke()
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint()
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed()
at com.plain.LoggingAspect.logging()
at sun.reflect.NativeMethodAccessorImpl.invoke0()
at sun.reflect.NativeMethodAccessorImpl.invoke()
at sun.reflect.DelegatingMethodAccessorImpl.invoke()
at java.lang.reflect.Method.invoke()
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs()
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod()
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke()
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
at org.springframework.aop.interceptor.AbstractTraceInterceptor.invoke()
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke()
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke()
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept()
at com.plain.BookService$$EnhancerByCGLIB$$7cb147e4.listBooks()
at com.plain.web.BookController.listBooks()

答案 3 :(得分:2)

对于log4j:

package package1;

public class FilteringThrowableRenderer implements ThrowableRenderer {
    private static final String PACKAGES_SEPARATOR = "\\s*,\\s*";

    private final static String TRACE_PREFIX = "\tat ";

    private static final String FILTERED_WARNING = " [Stacktrace is filtered]";

    ThrowableRenderer defaultRenderer = new EnhancedThrowableRenderer();

    List<String> skippedLinePrefixes;

    public FilteringThrowableRenderer() {
        String skippedPackagesString = "java,org"; // TODO: move it to config
        String[] skippedPackages =
            skippedPackagesString.trim().split(PACKAGES_SEPARATOR);
        skippedLinePrefixes = new ArrayList<String>(skippedPackages.length);
        for (String packageName : skippedPackages) {
            skippedLinePrefixes.add(TRACE_PREFIX + packageName);
        }
    }

    @Override
    public String[] doRender(Throwable throwable) {
        String[] initialTrace = defaultRenderer.doRender(throwable);
        if (!skippedLinePrefixes.isEmpty()) {
            List<String> result = new ArrayList<String>(initialTrace.length);

            boolean filtered = false;
            trace: for (String element : initialTrace) {
                for (String skippedLinePrefix : skippedLinePrefixes) {
                    if (element.startsWith(skippedLinePrefix)) {
                        filtered = true;
                        continue trace;
                    }
                }
                result.add(element);
            }
            if (filtered && result.size() > 0) {
                result.set(0, result.get(0) + FILTERED_WARNING);
            }
            return result.toArray(new String[result.size()]);
        } else {
            return initialTrace;
        }
    }
}

使用代码启用它:

ThrowableRendererSupport loggerRepository =
    (ThrowableRendererSupport) LogManager.getLoggerRepository();
loggerRepository.setThrowableRenderer(new FilteringThrowableRenderer());

或使用log4j.properties:

log4j.throwableRenderer=package1.FilteringThrowableRenderer

答案 4 :(得分:1)

不完全是您正在寻找的(并且据我所知,没有针对您的问题的通用解决方案,至少我从来没有听说过一个着名的工具来清理和从Java堆栈中提取信息)。

无论如何,this post from July, 05, 2011 at Faux' Blog描述了早期阶段的Java代理,其目的是丰富(而不是过滤)堆栈跟踪。它提供了一个带有mavenized项目的git存储库的链接。也许你可以从这里开始,调整他的代码并推出自己的解决方案(谁知道,甚至可能启动一个开源项目)。

答案 5 :(得分:0)

这个插件很不错

https://marketplace.eclipse.org/content/grep-console

只是Eclipse控制台的通用grep格式化实用程序,因此没有其他依赖项。我将所有无关的噪音格式化为灰色文本。