【问题标题】:When to log chained exceptions?何时记录链式异常?
【发布时间】:2012-10-28 07:01:12
【问题描述】:

我是一名绿色开发人员,试图在大型多层 Java 应用程序中获得错误处理的句柄 (har-har)。在很多情况下,我认为通过多层链接异常是一个好主意。例如当在最低层调用某些外部服务失败导致视图一直出现问题时:

  • 已请求内容 X,但用户未获得授权
    • 原因:授权用户列表为空
      • 原因:用户管理 web 服务响应错误请求 - 参数 foo 的格式必须类似于“xyz”

最重要的异常,我真正想检查的堆栈跟踪,是链中的最后一个;我提出了一个错误的请求,我需要修复 foo 的格式。但是当我让这个异常通过层冒泡时,很好地链接在对每一层有意义的异常中......当我最终捕获并记录这个东西时,默认的日志记录行为总是向我展示关于最外层异常的大量细节,并且可能是 5 行堆栈跟踪的根本原因。

这让我想在异常发生时记录它们,并让它们冒泡,但是你最终会记录大多数事情两次;它们何时发生以及何时最终被抓住。

这里的最佳做法是什么?

【问题讨论】:

  • 对此会有很多意见,但没有“真相”。选择适合你的,无论你选择什么,人们都会不同意。 (我个人喜欢将东西重新扔到最外层并在那里记录)

标签: java exception logging error-handling


【解决方案1】:

我会推荐一种不同的异常管理方法。在应用程序的最顶层(如请求入口点)创建一个 try catch 块来调用任何运行时异常。最好有 2 个 catch 块: - 针对您的应用程序特定(业务)异常 - 其余的(例外)

如您所见,您需要介绍自己的异常类型,您将对其进行扩展以针对不同目的创建不同的异常。例如,您可以为应用程序的每一层、每个集成等创建自定义异常。使用未经检查的异常,因为它们都将在顶层处理。当发生任何异常情况(捕获低级异常)时,您应该: - 放置与业务上下文相关的描述(例如“无法从数据库加载帐户数据” - 添加原始异常的描述(例如“原始错误:连接到数据库失败”) - 将原始异常传递给您的异常,以免丢失跟踪 - 扔了就忘了。换句话说,顶级 catch 块负责适当地处理它(回滚事务,显示错误消息或您可能需要的任何其他内容

【讨论】:

  • 似乎是个好办法;当我将自定义异常一直冒泡到顶层时,我有一个地方可以将它们的根本原因传递给记录器。但是,如果有一个地方我需要捕获并记录其中一个,我将记录包装的异常。将我的包装异常的堆栈跟踪截断为一行或没有行有什么问题吗?我不明白为什么这会导致问题,但修改堆栈跟踪对我来说听起来不太正确。
【解决方案2】:

很好的问题,我很好奇你会得到其他答案。

我倾向于采取“越多越好”的方法,并在每一步都记录下来。这会产生大日志吗?是的,但是当您在大型 Java 应用程序中调试问题时,您会感谢您拥有的每一行日志。还有一些工具(至少是grepawksed 三重奏)可以帮助您过滤大文件。

另一种技术是编写此日志记录代码,但将其关闭(如果您使用类似 log4j 的东西,则将其设置为 TRACE 级别)。这样,如果您遇到问题,您可能无法获得可用的日志,但只需一行更改(以降低日志记录阈值),您就可以开始生成大量数据以进行调试。

与前面的技术相结合,大多数日志库(我再次回到我对 log4j 的了解)允许您调整不同 java 包的日志级别。这意味着您可以将所有这些“catch and rethrow”日志行写入跟踪,并将低级包的日志记录关闭到WARN,而将高级包保持在DEBUGTRACE

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-08
    • 2014-02-28
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    • 2015-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多