繁体   English   中英

如何将堆栈跟踪发送到log4j?

[英]How to send a stacktrace to log4j?

假设您执行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之类的记录器,以获取以下信息:

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

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

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

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

如果要在不涉及异常的情况下记录堆栈跟踪,请执行以下操作:

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以字符串形式获取堆栈跟踪。

请参阅: 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 );
}

您将获得异常的标头,而不是整个stacktrace。 因为记录器会认为您正在传递字符串。 如skaffman所说,不用{}

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

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

但是,您也可以将stacktrace提取为String。 如果您希望利用占位符“ {}”来使用格式化功能,有时可能会很有用-请参见方法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);
}

这将在最后输出参数化的消息和stacktrace,方法与方法相同: logger.error("error: ", e);

我实际上写了一个开放源代码库,该库具有一个实用程序,可将String作为一个String提取出来,并带有一个选项,用于从stacktrace中巧妙地滤除一些噪声。 即,如果您指定了对提取的堆栈跟踪感兴趣的软件包前缀,则会从一些不相关的部分中滤除掉这些信息,并给您留下非常大的信息。 这里是文章的链接,解释了该库具有哪些实用程序以及在何处获取它(作为Maven工件和git源)以及如何使用它。 带有堆栈跟踪过滤,静默字符串解析Unicode转换器和版本比较的开源Java库,请参见“ Stacktrace噪声过滤器

这将是很好的log4j错误/异常日志记录-splunk /其他日志记录/监视软件可以读取。 一切都是键值对形式。 log4j将从异常obj e获取堆栈跟踪

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

您可以使用以下代码:

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

public class LogWriterUtility {
    Logger log;

    public LogWriterUtility(Class<?> clazz) {
        log = LogManager.getLogger(clazz);
    }

public void errorWithAnalysis( Exception exception) {

        String message="No Message on error";
        StackTraceElement[] stackTrace = exception.getStackTrace();
        if(stackTrace!=null && stackTrace.length>0) {
            message="";
            for (StackTraceElement e : stackTrace) {
                message += "\n" + e.toString();
            }
        }
        log.error(message);


    }

}

您可以在这里致电: LogWriterUtility.errorWithAnalysis( YOUR_EXCEPTION_INSTANCE);

它将把stackTrace打印到您的日志中。

在Log4j 2中,可以使用Logger.catching()从捕获到的异常中记录堆栈跟踪

    try {
        String msg = messages[messages.length];
        logger.error("An exception should have been thrown");
    } catch (Exception ex) {
        logger.catching(ex);
    }

创建这个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();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM