简体   繁体   English

仅获取 Stack Trace 的前 N ​​行

[英]Fetch only first N lines of a Stack Trace

I have a Factory method that returns an object from a ID call.我有一个从 ID 调用返回一个对象的工厂方法。

Mock code:模拟代码:

public static Object getById(String id) {
    Object o = CRUD.doRecovery(Class, id);
    if(o == null) {
         printLogMessage("recovery by ID returned Null: " + id);
         // would really like to show only a few lines of stack trace.
    }
    return o;
}

How can I show only the first N lines of the stack trace (so I know the caller of the method) without dumping the whole stack trace on the log or having to rely on external libs?如何仅显示堆栈跟踪的前 N ​​行(所以我知道该方法的调用者),而无需将整个堆栈跟踪转储到日志中或不得不依赖外部库?

You can use the ex.getStackTrace() to get the stack elements, the StackTraceElement contains one line of the full stacks, then print print what ever you want.您可以使用ex.getStackTrace()获取堆栈元素, StackTraceElement包含一行完整堆栈,然后打印您想要的任何内容。

StackTraceElement[] elements = ex.getStackTrace();
print(elements[0]);

I'm assuming from what you are asking, that you don't have an exception to deal with.我从你的要求中假设,你没有例外处理。 In which case you can get the current stack trace from:在这种情况下,您可以从以下位置获取当前堆栈跟踪:

StackTraceElement[] elements = Thread.currentThread().getStackTrace()

This will tell you pretty much everything you need to know about where you've come from in the code.这将告诉你几乎所有你需要知道的关于你从哪里来的代码。

This method displays i lines of the stack trace, skipping the first two.此方法显示堆栈跟踪的i行,跳过前两行。

public static String traceCaller(Exception ex, int i) {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    StringBuilder sb = new StringBuilder();
    ex.printStackTrace(pw);
    String ss = sw.toString();
    String[] splitted = ss.split("\n");
    sb.append("\n");
    if(splitted.length > 2 + i) {
        for(int x = 2; x < i+2; x++) {
            sb.append(splitted[x].trim());
            sb.append("\n");
        }
        return sb.toString();
    }
    return "Trace too Short.";
}

The first two lines are the exception name and the method that called traceCaller() .前两行是异常名称和调用traceCaller()的方法。 Tweak it if you want to show these lines.如果您想显示这些线条,请调整它。

Thanks go to @ BrianAgnew ( stackoverflow.com/a/1149712/1532705 ) for the StringWriter PrintWriter idea感谢 @ BrianAgnew ( stackoverflow.com/a/1149712/1532705 ) 提供 StringWriter PrintWriter 的想法

If you just want to truncate the stack trace, you can print the entire stack trace to a StringWriter then remove what you don't want:如果您只想截断堆栈跟踪,您可以将整个堆栈跟踪打印到 StringWriter,然后删除您不想要的:

public static void main(String[] args) throws ParseException {
    try {
        throw new Exception("Argh!");
    } catch (Exception e) {
        System.err.println(shortenedStackTrace(e, 1));
    }
}

public static String shortenedStackTrace(Exception e, int maxLines) {
    StringWriter writer = new StringWriter();
    e.printStackTrace(new PrintWriter(writer));
    String[] lines = writer.toString().split("\n");
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < Math.min(lines.length, maxLines); i++) {
        sb.append(lines[i]).append("\n");
    }
    return sb.toString();
}

Alternatively, use e.getStackTrace() to obtain a StackTraceElement[] array.或者,使用e.getStackTrace()获取StackTraceElement[]数组。 This gives you the caller stack (from inner to outer), but not the error message.这为您提供了调用者堆栈(从内部到外部),而不是错误消息。 You'll have to use e.getMessage() to get the error message.您必须使用e.getMessage()来获取错误消息。

Some logging frameworks can be configured to truncate stack traces automatically.一些日志框架可以配置为自动截断堆栈跟踪。 Eg see this question and answer about log4j configuration.例如,请参阅有关 log4j 配置的问题和答案

If you just want to see the stack trace at any point in the code, you can get the elements from the Thread.currentThread() object:如果您只想查看代码中任何一点的堆栈跟踪,您可以从Thread.currentThread()对象中获取元素:

Thread.currentThread().getStackTrace();

Guava could help.番石榴可以提供帮助。 For example we want to see only first ten rows:例如,我们只想查看前十行:

log.error("Error:", Joiner.on("\n").join(Iterables.limit(asList(ex.getStackTrace()), 10)));

For an abbreviated version of e.printStackTrace():对于 e.printStackTrace() 的缩写版本:

        Exception e = ...
        System.out.println(e.toString());
        StackTraceElement[] elements = e.getStackTrace();
        for(int i = 0; i<elements.length && i < STACK_TRACE_LIMIT; i++) {
            System.out.println("\tat "+elements[i]);
        }

Replace STACK_TRACE_LIMIT with the limit you want or remove && i < STACK_TRACE_LIMIT to reproduce the output of a simple stack trace (eg, no nested exceptions)用您想要的限制替换STACK_TRACE_LIMIT或删除&& i < STACK_TRACE_LIMIT以重现简单堆栈跟踪的输出(例如,没有嵌套异常)

The innermost method calls are at index 0, main is at index length-1.最里面的方法调用位于索引 0,main 位于索引 length-1。

exemple to display the fifth first lines:显示第五行的示例:

        final int nbLinesToShow = 5;
        try {
            /* your code here */
        } catch (final NullPointerException e) {
            // catch error
            final StackTraceElement[] elements = e.getStackTrace();
            System.err.println(
                    "===================================== \n" + "[ERROR] lorem ipsum");
            for (int i = 0; i < nbLinesToShow; i++) {
                System.err.println(elements[i]);
            }
        }

Snippet in below link works for N lines.下面链接中的片段适用于 N 行。

Below snippet helps to strip off exception stacktrace.下面的代码片段有助于剥离异常堆栈跟踪。

public class LoggerHelper {

private static final String SEPARATOR = "\r\n";
private static final String CAUSE_CAPTION = "Caused by: ";
private static final String SUPPRESSED_CAPTION = "Suppressed: ";

/**
 * The first 10 lines of exception stack information are returned by default
 *
 * @param e
 * @return
 */
public static String printTop10StackTrace(Throwable e) {
    if (e == null) {
        return "";
    }
    return printStackTrace(e, 20);
}

public static String printStackTrace(Throwable e, int maxLineCount) {
    if (e == null || maxLineCount <= 0) {
        return "";
    }
    StringBuilder sb = new StringBuilder(maxLineCount * 10);
    sb.append(e.toString()).append(SEPARATOR);
    StackTraceElement[] trace = e.getStackTrace();
    if (trace == null) {
        return e.toString();
    }
    int count = maxLineCount > trace.length ? trace.length : maxLineCount;
    int framesInCommon = trace.length - count;
    for (int i = 0; i < count; i++) {
        sb.append("\tat ").append(trace[i]).append(SEPARATOR);
    }
    if (framesInCommon != 0) {
        sb.append("\t... ").append(framesInCommon).append(" more").append(SEPARATOR);
    }
    // Print suppressed exceptions, if any
    Throwable[] suppressedExceptions = e.getSuppressed();
    if (ArrayUtils.isNotEmpty(suppressedExceptions)) {
        for (Throwable suppressedException : suppressedExceptions) {
            sb.append(printEnclosedStackTrace(suppressedException, maxLineCount, trace, SUPPRESSED_CAPTION, "\t"));
        }
    }
    // Print cause, if any
    Throwable cause = e.getCause();
    if (cause != null) {
        sb.append(printEnclosedStackTrace(cause, maxLineCount, trace, CAUSE_CAPTION, ""));
    }
    return sb.toString();
}

private static String printEnclosedStackTrace(Throwable e, int maxLineCount, StackTraceElement[] enclosingTrace,
                                              String caption, String prefix) {
    StringBuilder sb = new StringBuilder(maxLineCount * 5);
    StackTraceElement[] trace = e.getStackTrace();
    int m = trace.length - 1;
    int n = enclosingTrace.length - 1;
    while (m >= 0 && n >= 0 && trace[m].equals(enclosingTrace[n])) {
        m--;
        n--;
    }
    int count = maxLineCount > (m + 1) ? (m + 1) : maxLineCount;
    int framesInCommon = trace.length - count;
    // Print our stack trace
    sb.append(prefix).append(caption).append(e.toString()).append(SEPARATOR);
    for (int i = 0; i < count; i++) {
        sb.append(prefix).append("\tat ").append(trace[i]).append(SEPARATOR);
    }
    if (framesInCommon != 0) {
        sb.append(prefix).append("\t... ").append(framesInCommon).append(" more").append(SEPARATOR);
    }
    // Print suppressed exceptions, if any
    Throwable[] suppressedExceptions = e.getSuppressed();
    if (ArrayUtils.isNotEmpty(suppressedExceptions)) {
        for (Throwable suppressedException : suppressedExceptions) {
            sb.append(printEnclosedStackTrace(suppressedException, maxLineCount, trace, SUPPRESSED_CAPTION, prefix + "\t"));
        }
    }
    // Print cause, if any
    Throwable cause = e.getCause();
    if (cause != null) {
        sb.append(printEnclosedStackTrace(cause, maxLineCount, trace, CAUSE_CAPTION, prefix));
    }
    return sb.toString();
 }

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 配置Java安装以仅打印堆栈跟踪的前几行 - Configure Java installation to print only the first few lines of stack trace 使用Java持久性查询语言在子查询中仅获取前n行 - FETCH FIRST n ROWS ONLY within subquery using Java Persistence Query Language 显示堆栈跟踪元素仅包含我编写的Java类 - Display stack trace elements exclusive only the Java classes that I wrote 正则表达式模式匹配时仅分析并打印堆栈跟踪 - Parse and print only the stack trace when Regex pattern matches Springboot 堆栈跟踪日志过滤器仅来自我的包 - Springboot stack-trace logging filter only from my packages 如何增加 Java 堆栈跟踪转储的显示行数? - How do I increase the number of displayed lines of a Java stack trace dump? &quot;~[classes/:?]&quot; 字符串(或类似的,如 ~[?:?])何时出现在 Java 中堆栈跟踪行的末尾? - When does the "~[classes/:?]" string (or similar such as ~[?:?]) appear at the end of stack-trace lines in Java? 在迭代日志文件条目时打印几个堆栈跟踪行 - Print few stack trace lines while iterating through log file entries 有没有办法让 IntelliJ 向我显示我的文件中堆栈跟踪中发生错误的实际行? - Is there a way to get IntelliJ to show me the actual lines in my file where an error occurred in the stack trace? 日食中的堆栈跟踪 - Stack trace in eclipse
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM