如何发送堆栈跟踪到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();