如何发送堆栈跟踪到log4j?

假设你捕获一个exception,并在标准输出(如控制台)上得到以下内容,如果你使用e.printStackTrace()

java.io.FileNotFoundException: so.txt at java.io.FileInputStream.<init>(FileInputStream.java) at ExTest.readMyFile(ExTest.java:19) at ExTest.main(ExTest.java:7) 

现在我想把这个发送到像log4j这样的logging器来获得以下内容:

 31947 [AWT-EventQueue-0] ERROR Java.io.FileNotFoundException: so.txt 32204 [AWT-EventQueue-0] ERROR at java.io.FileInputStream.<init>(FileInputStream.java) 32235 [AWT-EventQueue-0] ERROR at ExTest.readMyFile(ExTest.java:19) 32370 [AWT-EventQueue-0] ERROR at ExTest.main(ExTest.java:7) 

我怎样才能做到这一点?

 try { ... } catch (Exception e) { final String s; ... // <-- What goes here? log.error( s ); } 

您直接将例外传递给logging器,例如

 try { ... } catch (Exception e) { log.error( "failed!", e ); } 

这取决于log4j渲染堆栈跟踪。

如果你想logging一个堆栈跟踪而不涉及exception,只需执行以下操作:

 String message = ""; for(StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) { message = message + System.lineSeparator() + stackTraceElement.toString(); } log.warn("Something weird happened. I will print the the complete stacktrace even if we have no exception just to help you find the cause" + message); 

您也可以通过ExceptionUtils.getStackTrace获取堆栈跟踪string。

请参阅: ExceptionUtils.java

我只用它log.debug ,保持log.error简单。

这个答案可能与所提问题无关,而与问题题目有关。

 public class ThrowableTest { public static void main(String[] args) { Throwable createdBy = new Throwable("Created at main()"); ByteArrayOutputStream os = new ByteArrayOutputStream(); PrintWriter pw = new PrintWriter(os); createdBy.printStackTrace(pw); try { pw.close(); os.close(); } catch (IOException e) { e.printStackTrace(); } logger.debug(os.toString()); } } 

要么

 public static String getStackTrace (Throwable t) { StringWriter stringWriter = new StringWriter(); PrintWriter printWriter = new PrintWriter(stringWriter); t.printStackTrace(printWriter); printWriter.close(); //surprise no IO exception here try { stringWriter.close(); } catch (IOException e) { } return stringWriter.toString(); } 

要么

 StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); for(StackTraceElement stackTrace: stackTraceElements){ logger.debug(stackTrace.getClassName()+ " "+ stackTrace.getMethodName()+" "+stackTrace.getLineNumber()); } 

只是因为它发生在我身上,可能是有用的。 如果你这样做

 try { ... } catch (Exception e) { log.error( "failed! {}", e ); } 

你会得到exception的头,而不是整个堆栈跟踪。 因为logging器会认为你正在传递一个string。 如skaffman所说,不要做{}

从skaffman的答案绝对是正确的答案。 所有的logging器方法如error()warn()info()debug()将Throwable作为第二个参数:

 try { ... } catch (Exception e) { logger.error("error: ", e); } 

但是,您也可以将堆栈跟踪提取为一个string。 有时如果您希望利用格式化function使用“{}”占位符,请参阅void info(String var1, Object... var2); 在这种情况下,说你有一个堆栈跟踪作为string,那么你实际上可以做这样的事情:

 try { ... } catch (Exception e) { String stacktrace = TextUtils.getStacktrace(e); logger.error("error occurred for usename {} and group {}, details: {}",username, group, stacktrace); } 

logger.error("error: ", e);这将打印参数化消息和logger.error("error: ", e);结束方式相同logger.error("error: ", e);

我实际上编写了一个开源库,有一个实用工具,用于将堆栈跟踪提取为一个string,并可以从堆栈跟踪中巧妙地过滤掉一些噪音。 也就是说,如果你指定了你感兴趣的软件包前缀,那么你的解压栈跟踪将被过滤掉一些不相关的部分,给你留下非常有用的信息。 这里是链接到文章,解释什么样的实用程序库,以及在哪里获得它(既作为maven工件和git来源),以及如何使用它。 带有堆栈跟踪过滤的开源Java库,静音stringparsingUnicode转换器和版本比较请参见段落“ 堆栈跟踪 噪声filter

这将是良好的log4j错误/exceptionlogging – 通过splunk /其他日志logging/监视s / w可读。 一切都是键值对的forms。 log4j会从Exception对象获得堆栈跟踪

  try { --- --- } catch (Exception e) { log.error("api_name={} method={} _message=\"error description.\" msg={}", new Object[]{"api_name", "method_name", e.getMessage(), e}); } 
 Try this: catch (Throwable t) { logger.error("any message" + t); StackTraceElement[] s = t.getStackTrace(); for(StackTraceElement e : s){ logger.error("\tat " + e); } } 

创build这个class

 public class StdOutErrLog { private static final Logger logger = Logger.getLogger(StdOutErrLog.class); public static void tieSystemOutAndErrToLog() { System.setOut(createLoggingProxy(System.out)); System.setErr(createLoggingProxy(System.err)); } public static PrintStream createLoggingProxy(final PrintStream realPrintStream) { return new PrintStream(realPrintStream) { public void print(final String string) { logger.info(string); } public void println(final String string) { logger.info(string); } }; } } 

在你的代码中调用这个

 StdOutErrLog.tieSystemOutAndErrToLog();