如何将日志记录与异常处理链相结合?

ein*_*ica 5 java error-handling logging 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.");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

所以,上面我描述了3个位置(底部,顶部和沿途) - 但这不仅仅是一个记录在哪里的问题,而是一个问题.在中间的每个级别,您有2x2选项:

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

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

注意:我一般不会询问错误处理/异常使用,只是关于上面描述的困境.

Nar*_*hai 2

我倾向于遵循的一些建议:

一些最佳实践的链接

1)跟踪异常发生的位置。当异常发生时,如果类或 API 知道异常发生的上下文,那么跟踪并提供适当的日志会更好。但是,如果 API 无法处理或评论确切的上下文,则 API 不应记录该事件并将其留给调用者。

2)包装异常:当可以抛出大量异常并且所有异常形成一个类似的组 ( SQLException) 时,该组提供单个异常并允许您在需要时提取信息。否则,调用者需要处理的异常将会激增。

3)重新抛出异常:如果 API 记录异常并且用户可以对此采取一些操作,则必须重新抛出异常以告诉用户发生了某些错误情况。

4)异常的正确原因:异常消息不应该太技术性以至于调用者无法理解,消息本身应该引导用户理解异常的根本原因。

更新: Java 中的异常管理