2012-03-07 33 views
22

我的Java堆棧跟蹤有很多條我不關心,顯示方法調用通過代理和Spring反射方法以及類似的東西。它可以很難挑出實際來自我的代碼的堆棧跟蹤部分。 Ruby on Rails包含一個「堆棧跟蹤清理器」,您可以在其中指定堆棧跟蹤模式列表以從打印的堆棧跟蹤中忽略 - 對於Java來說,通用地做這種事情的最佳方式是什麼?從Java堆棧跟蹤中清除噪音

如果這種方法在任何地方都能正常工作,包括在Eclipse jUnit runner中,那最好。

+0

啊是的,根據Cay Horstmann的「來自地獄的堆棧跟蹤」:https://plus.google.com/+CayHorstmann/posts/YAwGCVpLXgH – 2015-11-22 14:13:33

回答

9

具有偏好堆棧跟蹤器圖案(看看的java>的junit或喜好搜索stacktrace)。您可以忽略軟件包(也包含通配符),類或方法。可以用於直接測試呼叫(通過運行爲測試),不適用於命令行運行,如antmaven

+0

感謝!這絕對解決了我的jUnit插件問題。 – bhollis 2012-03-07 21:17:09

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

+0

不幸的是,intelliJ插件不再兼容。 (至少在03/17 Ubuntu的構建) – Blauhirn 2017-06-18 11:34:07

1

不是你正在尋找的東西(並且據我所知,沒有針對你的問題的通用解決方案,至少我從來沒有聽說過一個着名的工具來清理並從Java堆棧中提取信息) 。

無論如何,this post from July, 05, 2011 at Faux' Blog描述了一個早期階段的Java代理,其目的是豐富(而不是過濾)棧跟蹤。它提供了一個鏈接到git倉庫與mavenized項目。也許你可以從這裏走,調整他的代碼並推出自己的解決方案(誰知道,甚至可能啓動一個開源項目)。

+0

我已經看到了,但希望我不會寫我自己的。似乎要走的路。 – bhollis 2012-03-07 21:17:47

2

對於log4j的:

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

或log4j.properties:

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

用代碼,使之

log4j.throwableRenderer=package1.FilteringThrowableRenderer 
6

其實我寫了一個庫 (https://github.com/michaelgantman/Mgnt/releases/tag/1.01) 包含幾個實用程序。其中之一是我廣泛使用的通用堆棧跟蹤 過濾器,並發現它非常有用。這個類被稱爲 TextUtils,它有幾個覆蓋簽名的方法getStacktrace()。 它需要一個Throwable實例,並允許設置相關包 的包前綴。比方說,你的公司的代碼始終駐留在 與啓動包「com.plain。*」你設置這樣的前綴,併爲此

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

這會過濾掉非常巧妙所有跟蹤的無用部分離開 你用非常簡潔的stacktrace。此外,我發現它十分便利,以預先設定的 前綴,然後只需使用舒適方法

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() 
0

這個插件的相當不錯

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

只是一個廣義的grep格式化爲Eclipse工具控制檯,所以沒有額外的依賴關係。我將所有不相關的噪音都格式化爲灰色文字。