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

发布于 2024-10-06 05:57:03 字数 813 浏览 0 评论 0原文

假设您捕获了一个异常,并在执行 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 );
}

Say you catch an exception and get the following on the standard output (like, say, the console) if you do a 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)

Now I want to send this instead to a logger like, say, log4j to get the following:

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)

How can I do this?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

我恋#小黄人 2024-10-13 05:57:03

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

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

由 log4j 来呈现堆栈跟踪。

You pass the exception directly to the logger, e.g.

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

It's up to log4j to render the stack trace.

鸵鸟症 2024-10-13 05:57:03

如果您想记录堆栈跟踪而不涉及异常,只需执行以下操作:

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

If you want to log a stacktrace without involving an exception just do this:

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);
不必你懂 2024-10-13 05:57:03

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

请参阅: ExceptionUtils.java

我仅将它用于 log.debug,以保持 log.error 简单。

You can also get stack trace as string via ExceptionUtils.getStackTrace.

See: ExceptionUtils.java

I use it only for log.debug, to keep log.error simple.

大海や 2024-10-13 05:57:03

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

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

但是,您也可以将堆栈跟踪提取为字符串。有时,如果您希望使用“{}”占位符利用格式化功能,它可能会很有用 - 请参阅方法 void info(String var1, Object... var2); 在这种情况下,假设您有一个stacktrace as 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);

我实际上编写了一个开源库,它有一个实用程序,用于将堆栈跟踪提取为字符串,并提供一个选项来智能地过滤掉堆栈跟踪中的一些噪音。即,如果您指定您对提取的堆栈跟踪感兴趣的包前缀,则会从一些不相关的部分中过滤掉,并留下非常简洁的信息。这是文章的链接,解释了该库有哪些实用程序以及从哪里获取它(作为 Maven 工件和 git 源)以及如何使用它。 具有堆栈跟踪过滤功能的开源 Java 库, Silent String解析Unicode转换器和版本比较参见段落“Stacktrace噪声过滤器

The answer from skaffman is definitely the correct answer. All logger methods such as error(), warn(), info(), debug() take Throwable as a second parameter:

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

However, you can extract stacktrace as a String as well. Sometimes it could be useful if you wish to take advantage of formatting feature using "{}" placeholder - see method void info(String var1, Object... var2); In this case say you have a stacktrace as String, then you can actually do something like this:

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

This will print parametrized message and the stacktrace at the end the same way it does for method: logger.error("error: ", e);

I actually wrote an open source library that has a Utility for extraction of a stacktrace as a String with an option to smartly filter out some noise out of stacktrace. I.e. if you specify the package prefix that you are interested in your extracted stacktrace would be filtered out of some irrelevant parts and leave you with very consized info. Here is the link to the article that explains what utilities the library has and where to get it (both as maven artifacts and git sources) and how to use it as well. Open Source Java library with stack trace filtering, Silent String parsing Unicode converter and Version comparison See the paragraph "Stacktrace noise filter"

逐鹿 2024-10-13 05:57:03

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

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

您将获得异常的标头,而不是整个堆栈跟踪。因为记录器会认为你正在传递一个字符串。
正如 skaffman 所说,不用 {} 即可完成

Just because it happened to me and can be useful.
If you do this

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

you will get the header of the exception and not the whole stacktrace. Because the logger will think that you are passing a String.
Do it without {} as skaffman said

此刻的回忆 2024-10-13 05:57:03

在 Log4j 2 中,您可以使用 Logger.writing() 用于记录捕获的异常的堆栈跟踪。

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

In Log4j 2, you can use Logger.catching() to log a stacktrace from an exception that was caught.

    try {
        String msg = messages[messages.length];
        logger.error("An exception should have been thrown");
    } catch (Exception ex) {
        logger.catching(ex);
    }
∞梦里开花 2024-10-13 05:57:03

这个答案可能与所提出的问题无关,但与问题的标题有关。

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

This answer may be not related to the question asked but related to title of the question.

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());
}
信仰 2024-10-13 05:57:03

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

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

this would be good log4j error/exception logging - readable by splunk/other logging/monitoring s/w. everything is form of key-value pair.
log4j would get the stack trace from Exception obj e

    try {
          ---
          ---
    } catch (Exception e) {
        log.error("api_name={} method={} _message=\"error description.\" msg={}", 
                  new Object[]{"api_name", "method_name", e.getMessage(), e});
    }
z祗昰~ 2024-10-13 05:57:03
Try this:

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

catch (Throwable t) {
    logger.error("any message" + t);
    StackTraceElement[] s = t.getStackTrace();
    for(StackTraceElement e : s){
        logger.error("\tat " + e);
    }   
}
奢望 2024-10-13 05:57:03

您可以使用以下代码:

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 打印到您的日志中。

You can use bellow code:

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


    }

}

Here you can just call : LogWriterUtility.errorWithAnalysis( YOUR_EXCEPTION_INSTANCE);

It will print stackTrace into your log.

塔塔猫 2024-10-13 05:57:03

创建这个

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

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

Call this in your code

StdOutErrLog.tieSystemOutAndErrToLog();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文