如何使用 java 的 Logger 类记录堆栈跟踪

问题描述 投票:0回答:15

我正在使用Java的

Logger
类。我想将
ex.printStackTrace()
传递给
Logger.log(loglevel, String)
,但是
printStackTrace()
返回
void
。所以我无法传递并打印异常的堆栈跟踪。

有什么方法可以将

void
转换为
String
,或者有其他方法可以打印异常的整个堆栈跟踪吗?

java logging stack-trace java.util.logging
15个回答
70
投票

您需要了解

void
实际上是
nothingness
。你无法改变什么都不是的东西。您可能最终将
void
打印为字符串,但是(相信我),您不希望这样。

我想你正在寻找的是

// assuming ex is your Exception object
logger.error(ex.getMessage(), ex);
// OR
Logger.log(errorLogLevel, ex.getMessage(), ex)

这将使用您配置的记录器打印错误消息。有关更多详细信息,您可以查看 Exception#getMessage()

的 java 文档

41
投票

使用

java.util.logging.Logger#log(Level, String, Throwable)
并传入
ex
作为第三个参数,如下所示:

LOGGER.log(Level.INFO, ex.getMessage(), ex);

28
投票

另一种选择是:

import org.apache.commons.lang3.exception.ExceptionUtils;

log.error("Exception : " + ExceptionUtils.getStackTrace(exception));

13
投票

有一个重载的 printStackTrace 方法,它接受 PrintWriter。

你可以做这样的事情

Writer buffer = new StringWriter();
PrintWriter pw = new PrintWriter(buffer);
ex.printStackTrace(pw);
Logger.log(loglevel, buffer.toString());

12
投票

使用以下格式,您可以获得堆栈跟踪:

java.util.logging.SimpleFormatter.format=%1$tF %1$tT [%4$-7s][%2$s] %5$s %6$s%n

此形态中的点是 %6$s。它将打印堆栈跟踪。


6
投票

您无法将

void
转换为
String
;不存在这样的转换。
void
不会返回 anything,因此您没有任何可检索的值。

您可能想要做的是通过

ex.getMessage()
获取异常消息。


4
投票

您可以使用 getStackTrace() 方法获取 StackTraceElements 数组,并从那里生成一个字符串。否则,如果仅最终错误消息就足够了,请使用 Makoto 建议的

getMessage()
方法。

要从

String
对象数组中获取
StackTraceElement
形式的堆栈跟踪,您需要迭代该数组(取自 JDK7 源代码):

StringBuilder builder = new StringBuilder();
StackTraceElement[] trace = getOurStackTrace();
    for (StackTraceElement traceElement : trace)
        builder.append("\tat " + traceElement + "\n");

另一个选项是使用

printStackTrace(PrintStream s)
,您可以在其中指定要打印堆栈跟踪的位置:

ByteArrayOutputStream out1 = new ByteArrayOutputStream();
PrintStream out2 = new PrintStream(out1);
ex.printStackTrace(out2);
String message = out1.toString("UTF8");

2
投票

如果您需要查看堆栈跟踪而不抛出异常,可以使用 ExceptionUtils

String stackTrace = ExceptionUtils.getStackTrace(new Exception("YourMessage"));
log.error(stackTrace);

1
投票

您可以使用下面的方法将堆栈跟踪转换为字符串。如果

e
是异常对象

StringWriter stringWriter= new StringWriter();
PrintWriter printWriter= new PrintWriter(stringWriter);
e.printStackTrace(printWriter);
String stackTraceAsString= stringWriter.toString(); 

1
投票

谢谢大家。我可以使用

记录堆栈跟踪详细信息
LOGGER.log(Level.INFO, ex.getMessage(),ex);
//ex is my exception object

0
投票

正如 Makoto 所说,你可能想做一个 ex.getMessage()。

进一步澄清,

void
表示没有返回任何内容。你不能把什么都扔进什么东西:)


0
投票

您还可以使用 apache 库中的 ExceptionUtils 或下面的日志语句

    try{
      doSomething();
    }
    catch(Exception e){
    log.error("Exception in method doSomething ",e);
    }

0
投票

之前的建议似乎都只是将堆栈跟踪放入日志中,而没有在每行前面加上记录器详细信息的前缀。我的建议如下处理堆栈跟踪元素并将每行格式化为记录器行:

log.error("{}", e.toString());
StackTraceElement[] stElements = e.getStackTrace();

log.error("(stacktrace) {}", e.toString());

for (StackTraceElement ste: stElements) {
    log.error("(stacktrace)     at {}.{}({}.java:{})", 
        new Object[] {ste.getClassName(), ste.getMethodName(), 
                      ste.getClassName(), ste.getLineNumber()});
}

Throwable thisThrowable = e;
boolean causedBy = true;
while (causedBy) {
    Throwable throwable = thisThrowable.getCause();
    if (throwable != null) {
        log.error("(stacktrace) Caused by: {}", throwable.toString());
        stElements = throwable.getStackTrace();
        for (StackTraceElement ste: stElements) {
            log.error("(stacktrace)     at {}.{}({}.java:{})", 
                 new Object[] {ste.getClassName(), ste.getMethodName(),                    
                               ste.getClassName(), ste.getLineNumber()});
        }
        thisThrowable = throwable;  // For the next caused-by check
    } else {
        log.error("(stacktrace) No Caused-by Exception");
        causedBy = false;  // No more caused-by Throwables, so end the loop
    }
}

堆栈跟踪的每一行都以“(stacktrace)”为前缀。这样做的好处是能够在转储日志文件时过滤掉它们,或者能够轻松找到它们。


0
投票

使用 java.util.Arrays 你也可以轻松解决这个问题:

try {
    doSomething();
} catch (Exception e) {
    logger.error(Arrays.toString(e.getStackTrace()));
}

Arrays.toString(Object[] a) 为每个元素调用 Object.toString() ,如果对象为 null,则返回带有“null”的 String。元素由逗号和空格分隔。 StackTraceElement 实现了 toString(),因此从 e.getStackTrace() 获得的数组可以很好地转换。


0
投票

可以使用下面的代码组。

public static Connection openConnection()  {
        Connection con = null;
        try {
            // load the driver
            
            //System.out.println("Load JDBC Driver");
            DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
        }
        catch (SQLException e) {
            logger.info("FAILED TO LOAD JDBC DRIVER");
            //System.out.println("Fail to Load JDBC Driver ");
            logger.error(e.getMessage(), e);
            return null;
        }
© www.soinside.com 2019 - 2024. All rights reserved.