2010-12-03 93 views
130

说你捕获异常,并得到在标准输出下面的(比如说,控制台),如果你做一个e.printStackTrace()如何发送堆栈跟踪到log4j?

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的一个记录器,以获得以下内容:

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); 
} 

回答

218

您将异常直接传递给记录器,例如,

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

这取决于log4j呈现堆栈跟踪。

+24

记录器接受一个对象为它的第一个参数,将的toString()它。但是第二个参数必须是Throwable并显示堆栈跟踪。 – 2010-12-03 16:50:20

+1

我从来不知道什么东西进入第一个String,通常我只落得做`log.error(e.getLocalizedMessage(),E)`这完全是多余的。它是否为第一个参数处理空值? – 2010-12-03 16:52:11

+4

@Mark:试着给它一个比例外消息更适合上下文的消息,例如:那时它究竟在做什么? – skaffman 2010-12-03 16:53:37

6

您还可以通过ExceptionUtils.getStackTrace以字符串形式获取堆栈跟踪。

参见:ExceptionUtils.java

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

-2

创建此class:在你的代码

StdOutErrLog.tieSystemOutAndErrToLog(); 
2

这个答案可能不相关的问这个问题,但相关的问题的标题

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); 
     } 
    }; 
} 
} 

调用此。

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()); 
    } 
} 

OR

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(); 
} 

OR

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

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

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

你会得到异常的头部,而不是整个堆栈跟踪。因为记录器会认为你传递了一个字符串。 做没有{}为skaffman说

7

如果你想记录一个堆栈跟踪不涉及例外只是这样做:

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); 
0

从skaffman答案肯定是正确的答案。所有记录的方法,如error()warn()info()debug()采取Throwable作为第二个参数:

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

但是,您可以提取堆栈跟踪的字符串为好。有时候,如果你想采取格式化使用功能的优势可能是有用的“{}”占位符 - 参见方法void info(String var1, Object... var2);在这种情况下,说你有一个堆栈跟踪字符串,那么实际上你可以做这样的事情:

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);

其实,我写了有一个堆栈跟踪作为一个字符串的提取工具的选项巧妙地过滤的开源库从堆栈中抽出一些噪音。即如果你指定你感兴趣的软件包前缀,那么你的解压栈跟踪将被过滤掉一些不相关的部分,并给你提供非常有用的信息。这篇文章的链接解释了这个库有哪些实用工具,以及在哪里可以获得它(既作为maven工件也作为git源代码)以及如何使用它。 Open Source Java library with stack trace filtering, Silent String parsing Unicode converter and Version comparison查看段落“堆栈跟踪噪声滤波器

0

这将是很好的log4j错误/异常日志记录 - 通过的Splunk /其他日志/监视S/W可读。一切都是键值对的形式。 的log4j将从异常获得堆栈跟踪物镜e

try { 
      --- 
      --- 
    } catch (Exception e) { 
     log.error("api_name={} method={} _message=\"error description.\" msg={}", 
        new Object[]{"api_name", "method_name", e.getMessage(), e}); 
    } 
0
Try this: 

catch (Throwable t) { 
    logger.error("any message" + t); 
    StackTraceElement[] s = t.getStackTrace(); 
    for(StackTraceElement e : s){ 
     logger.error("\tat " + e); 
    } 
}