【问题标题】:How do I log a stacktrace using java's Logger class如何使用 java 的 Logger 类记录堆栈跟踪
【发布时间】:2015-10-03 14:14:18
【问题描述】:

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

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

【问题讨论】:

标签: java logging stack-trace java.util.logging


【解决方案1】:

您需要了解void 实际上是nothingness。你不能转换什么都不是。您最终可能会将void 打印为字符串,但是(相信我),您不希望这样。

我认为你正在寻找的是

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

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

【讨论】:

  • 谢谢赛义夫阿西夫。我现在可以记录整个堆栈跟踪。
  • logger.error() 不是java.util.logging,但我不会拒绝你,因为我很高兴发现logger.log(Level, Exception, Supplier)。看起来甲骨文让java.util.logging.Logger 变得非常丑陋!既然他们这样做了,奇怪的是他们没有更进一步并创建logger.severe(String, Exception)
  • 该问题要求使用 Java 的 Logger 类的解决方案。 java.util.logging.Logger 没有名为“error”的方法。正因为如此,我才对这个答案投了反对票。
  • 这根本没有回答将堆栈跟踪打印到记录器的最初意图。 getMessage() 不是为此而设计的。
  • 所以,答案是:logger.log(Level.SEVERE, ex.getMessage(), ex);
【解决方案2】:

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

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

【讨论】:

  • 我没有得到堆栈跟踪来记录这个,只有第二个参数。
  • 可以通过更改日志格式来抑制堆栈跟踪。您使用的是哪种格式化程序以及您的日志格式是什么样的?
  • 这是问题的真正答案。
  • @PanuHaaramo 这取决于您使用的格式化程序。格式化程序需要在format 中调用record.getThrown()。看看SimpleFormatter
【解决方案3】:

另外一种选择是:

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

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

【讨论】:

  • 如果你指的是 org.apache.commons.lang3.exception.ExceptionUtils,那就是 ExceptionUtils.getStackTrace(e)
【解决方案4】:

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

你可以这样做

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

【讨论】:

  • 这是最简单的方法恕我直言,它真的打印堆栈跟踪,而不仅仅是消息。
【解决方案5】:

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

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

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

【讨论】:

    【解决方案6】:

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

    您可能想要做的是通过ex.getMessage() 获取异常消息。

    【讨论】:

      【解决方案7】:

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

      要从StackTraceElement 对象数组中以String 形式获取堆栈跟踪,您需要遍历数组(取自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");
      

      【讨论】:

      • 只要使用apache commons ExceptionUtils库即可;无需重新发明轮子
      • 1. String message = out1.toString("UTF8"); - 编译错误,预期为 0 个参数,但得到 1 个 2。它工作正常 out2.out.toString。如果out2.toString -> 'PrintStream@hash'
      【解决方案8】:

      谢谢大家。我可以使用

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

      【讨论】:

        【解决方案9】:

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

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

        【讨论】:

          【解决方案10】:

          正如 Makoto 所说,您可能想要执行 ex.getMessage()。

          为了进一步澄清,void 表示没有返回任何内容。你不能把任何东西都投进去:)

          【讨论】:

          • 他想要堆栈跟踪,而不仅仅是消息。
          【解决方案11】:

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

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

          【讨论】:

            【解决方案12】:

            你也可以使用 Apache 库中的 ExceptionUtils 或者日志语句下面的语句

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

            【讨论】:

              【解决方案13】:

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

              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)”为前缀。这样做的好处是能够在转储日志文件时将它们过滤掉,或者能够轻松找到它们。

              【讨论】:

                猜你喜欢
                • 2021-02-07
                • 2011-04-06
                • 1970-01-01
                • 2013-11-16
                • 1970-01-01
                • 2014-11-01
                • 1970-01-01
                • 2012-03-22
                • 1970-01-01
                相关资源
                最近更新 更多