java - 如何将日志记录与异常处理链结合起来?

标签 java logging error-handling coding-style conventions

假设我有以下代码:

void foo() {
    /* ... */
    try {
        bar(param1);
    } catch (MyException e) {
        /* ??? */
    }
}

void bar(Object param1) throws MyException {
    /* ... */
    try {
       baz(param2);
    } catch (MyException e) {
        /* ??? */
    }
}

void baz(Object param2) throws MyException {
    /* ... */
    if (itsAllATerribleMistakeOhNo) {
        /* ??? */
        throw new MyException("oops, error.");
    }
}

我想知道应该在哪里以及如何记录错误。

  • 在下面的 baz() 中发生错误的地方,我确切地知道是什么操作出了问题,并且可以记录该事实。
  • 在顶部,我有最一般的上下文(例如,在处理我们遇到错误的连接的 IP 是什么。)
  • 在这个过程中,我可能有一些在顶部或底部都不知道的上下文。

另一个复杂的问题是,当您从顶部查看时,底部的错误可能不会真正被视为错误(例如,在数据库中查找某些内容失败;也许您不确定)——所以我可能会选择logger.WARN() 而不是 logger.ERROR()

所以,上面我描述了 3 个位置(底部、顶部和沿途)- 但这不仅仅是在哪里记录的问题,还有要吐出什么的问题。在中间的每个级别,您都有 2x2 个选项:

  • 记录/不记录消息
  • 抛出原始异常/用添加的消息将异常包装在新异常中。

关于这些复杂的选择,最佳实践或一些常识是什么?

注意:我不是在问一般的错误处理/异常使用,只是在问上面描述的困境。

最佳答案

说到日志记录,我更喜欢将所有日志记录放在应用程序边界的顶部。通常我使用拦截器或过滤器以通用方式处理所有日志记录。通过这个概念,我可以保证一切都被记录一次,而且只记录一次。

在这种情况下,您将登录到您的 foo() 方法或您的应用程序的任何入口点(您提到了 IP 地址,我想我们正在谈论一个 servlet 容器或应用程序服务器)。

然后,在过滤器/拦截器中捕获您自己的异常并根据您的需要记录它。添加一个 catch throwable 以捕获您未在代码中处理的所有其他异常并将它们记录为错误,因为显然您在堆栈跟踪中遗漏了一些更深的东西。

这个概念需要提前计划。您可能会使用自己的 ApplicationException 来存储错误消息(字符串)以及一些严重级别(可能在枚举中)。当您进行实际日志记录时,您需要它来选择正确的日志级别。

这适用于所有情况,并且优点是所有日志记录都只发生一次。但是,在一种情况下您仍然需要登录代码:如果您可以完全处理代码中某处的错误(即发生异常并且您可以做一些事情让您可以继续工作而无需(重新)抛出一个异常(exception))。由于您没有抛出异常,否则不会记录任何内容。

总结一下:

  • 以一般方式在最顶层位置登录,最好使用拦截器或过滤器。
  • 包装您自己的 ApplicationExceptions 中的异常,并添加严重性和其他感兴趣的内容以记录您的应用程序。

关于java - 如何将日志记录与异常处理链结合起来?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15197188/

相关文章:

azure - 使用 Application Insights 更改用于登录 ASP.NET Core 的 Instrumentation key

java - 仅在OptionsItemSelected 上显示文本的弹出窗口

java - log4j2 配置 XML 文件,用于 2 个日志文件,每次运行都有新文件夹

javascript - 使用 log4js 运行 logger.js 时 logger.setLevel 不是函数

c++ - ifstream::close 是否会重置 failbit 和/或 badbit?

asp.net-mvc-3 - MVC 3 json 请求应在异常时收到 json 响应

php - 无法使用 try catch block 捕获 PHP file_get_contents 错误

java - 在更改 Camel 版本时,War 未部署在 weblogic 中

java - @GET 和 @POST 使用相同的路径

java - 如何将奇数索引转换为索引 {0,1,2,3,4,5}?