清除Java堆栈跟踪中的噪音
我的Java堆栈跟踪有很多我不关心的条目,显示通过代理和Springreflection方法的方法调用以及类似的东西。 它可能很难从我的代码中挑选出实际来自堆栈跟踪的部分。 Ruby on Rails包含一个“堆栈跟踪清理器”,您可以在其中指定堆栈跟踪模式列表以从打印的堆栈跟踪中省略 – 对于Java来说,通用的最佳方法是什么?
如果这在任何地方都有效,那将是最好的,包括Eclipse jUnit runner。
eclipse有一个首选项Stack trace过滤模式 (查看java > junit或在首选项中搜索stacktrace
)。 您可以忽略包(也包含通配符),类或方法。 适用于直接测试调用(通过Run as junit Test ),而不是像ant
或maven
这样的命令行运行。
intellij-idea允许自定义堆栈跟踪折叠 ,尤其适用于动态语言 。
IntelliJ http://blogs.jetbrains.com/idea/wp-content/uploads/2010/07/screen-shot-2010-07-12-at-100921-pm.png
和分析外部堆栈跟踪工具。
我可以想象一般工具/filter在日志框架(如logback或log4j )级别上工作。 我不认为对此有任何普遍支持,但我认为实施这一点是个好主意。 我会看看,也许这不是那么多工作。
更新:我在日志中实现了过滤不相关的堆栈跟踪线以进行回溯 ,也遵循LBCLASSIC-325 。
我实际上写了一个包含几个实用程序的库( https://github.com/michaelgantman/Mgnt/releases/tag/1.01 )。 其中一个是我广泛使用的通用堆栈跟踪filter,发现它非常有用。 该类称为TextUtils,它具有带有多个重写签名的方法getStacktrace()。 它需要一个Throwable实例,并允许设置相关包的包前缀。 假设您公司的代码始终位于以“com.plain。*”开头的包中。所以您设置了这样的前缀并执行此操作
logger.info(TextUtils.getStacktrace(e, true, "com.plain."));
这将非常巧妙地过滤掉跟踪中所有无用的部分,为您提供非常简洁的堆栈跟踪。 此外,我发现预先设置前缀非常方便,然后只使用方便的方法
TextUtils.getStacktrace(e);
它也会这样做。 要预设前缀,只需使用方法
setRelevantPackage("com.plain.");
此外,如果您使用Spring环境,您可以将以下段添加到Spring配置中,然后全部设置:
该库附带写得很好(我希望)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()
对于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 skippedLinePrefixes; public FilteringThrowableRenderer() { String skippedPackagesString = "java,org"; // TODO: move it to config String[] skippedPackages = skippedPackagesString.trim().split(PACKAGES_SEPARATOR); skippedLinePrefixes = new ArrayList (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 result = new ArrayList (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
不完全是你想要的(并且据我所知,你的问题没有通用的解决方案,至少我从来没有听说过一个着名的工具来清理和从Java堆栈中提取信息)。
无论如何, 2011年7月5日在Faux’Blog上发布的这篇文章描述了早期阶段的Java代理,其目的是丰富(而不是过滤)堆栈跟踪。 它提供了一个带有mavenized项目的git存储库的链接。 也许你可以从这里开始,调整他的代码并推出自己的解决方案(谁知道,甚至可能启动一个开源项目)。
这个插件很不错
https://marketplace.eclipse.org/content/grep-console
只是Eclipse控制台的通用grep格式化实用程序,因此没有其他依赖项。 我将所有无关的噪音格式化为灰色文本。
- java.lang.IllegalStateException:在servlet中提交响应后无法转发
- 线程“AWT-EventQueue-0”中的exceptionjava.lang.ClassCastException:javax.swing.JTable
- 处理加密exception
- EJB3.1系统exception与javax.ejb.EJBException
- 为什么spring只处理未经检查的exception
- Java:在构造函数中抛出exception,我的对象是否仍然可以创建?
- 索引越界exceptionjava
- java.lang.Exception与滚动你自己的exception
- 为什么并行性ForkJoinPool加倍我的exception?