我的Java堆栈跟踪有很多我不关心的条目,显示通过代理和Spring反射方法的方法调用以及类似的东西。它可能很难从我的代码中挑选出实际来自堆栈跟踪的部分。 Ruby on Rails包含一个“堆栈跟踪清理器”,您可以在其中指定堆栈跟踪模式列表,以便从打印的堆栈跟踪中省略 - 对于Java来说,通用的最佳方法是什么?
最好能在各处工作,包括Eclipse jUnit runner。
答案 0 :(得分:14)
intellij-idea允许自定义stack trace folding,对dynamic languages特别有用。
和Analyzing external stack traces工具。
我可以想象一般工具/过滤器处理日志框架(如logback或log4j)级别。我不认为对此有任何普遍支持,但我认为实施这一点是个好主意。我会看看,也许这不是那么多工作。
更新:我为filtering irrelevant stack trace lines in logs实施了logback,也遵循了LBCLASSIC-325。
答案 1 :(得分:10)
eclipse首选堆栈跟踪过滤器模式(查看 java > junit 或搜索{{1}在首选项中)。您可以忽略包(也包含通配符),类或方法。适用于直接测试调用(通过运行为junit测试),而不适用于stacktrace
或ant
等命令行运行。
答案 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格式化实用程序,因此没有其他依赖项。我将所有无关的噪音格式化为灰色文本。