【问题标题】:try-catch for logging purposes?try-catch 用于记录目的?
【发布时间】:2016-04-26 06:29:54
【问题描述】:

根据这个答案:https://stackoverflow.com/a/1722991/680026 如果你真的做除了记录以外的事情,你应该只使用 try-catch:

如果您只想记录异常并且不捕获异常 把它扔到堆栈上。它没有任何意义,而且代码混乱。

但是在更高级别不可用的日志记录信息呢? 例如:

private void AddSomethingToTable(string tablename, string fieldname) {
  try {
    InsertFieldToTable(tablename, fieldname);
  } catch (Exception ex) {
    log.ErrorFormat("Could not insert field '{0}' into table '{1}'", fieldname, tablename);
    throw;
  }
}

private void main() {
  try {
    AddSomethingToTable("users","firstname");
    AddSomethingToTable("users","lastname");
    AddSomethingToTable("users","age");
  } catch (Exception ex) {
    MessageToUser("Sorry. Saving did not work.",ex);
  }
}

如您所见:在我的(完全虚构的)示例中,我记录了有关确实导致错误的字段的信息。这可能是开始查找错误的一些有用信息。

因此,即使我只记录了错误,这些信息也可能很重要,并且在该方法之外会丢失。

这是对 try-catch 的有效使用,还是有其他建议的方法来记录它? (我不认为总是记录这些信息(不管是否发生错误)是一个有效的解决方案)

【问题讨论】:

  • 我认为您用“但是在更高的实例中不可用的日志信息”回答了您自己的问题。我不喜欢“总是做X,从不做Y”,因为有时它是必要的。这也是为什么这里不鼓励“最佳实践”问题的原因。如果需要记录信息来解决问题,并且如果您不立即记录,则会丢失此信息,请记录信息。
  • 这个related question 可能会对你有所帮助。

标签: c# .net exception try-catch


【解决方案1】:

我们以与您建议的类似方式使用 Try Catch 块,它对我们很有效。 我们已经实现了 ELMAH https://code.google.com/p/elmah/,它非常适合记录未捕获的错误。通过 Try Catch 块中的一行代码,您还可以将捕获的异常写入日志。

Catch ex As Exception
            Elmah.ErrorSignal.FromCurrentContext.Raise(ex) 
            Return False
 End Try

错误被处理(相关函数返回 false),用户没有得到黄屏死机,我们可以在日志中查找任何错误的完整详细信息。

【讨论】:

  • 记录错误并不是我所说的“已处理”。
  • 我并不是说记录错误本身正在处理它。在上面的示例中,当出现异常时,该函数返回 false,以便应用程序可以处理它。可能不适用于所有场景,但对我们有用
【解决方案2】:

来自您的链接问题:

捕获异常的基本经验法则是当且仅当您有一种有意义的处理方式时才捕获异常。

我强调“基本经验法则”,因为它不是法律。这是一个最佳实践。即遵循它,直到你有一个很好的动机不这样做。

如果您捕获异常以包含信息,您可能应该抛出一个具有更多上下文信息的新的有意义的异常。类似:

try 
{
    //kldfsdölsdöls
}
catch (Exception ex)
{
    throw new MoreDetailedException("Text with context data", ex);
}

这样,您将获得收集到同一异常中的每个堆栈级别的所有上下文信息(因为您在其中包含了内部异常)。因此,顶层的日志条目将在同一行中包含所有信息。

【讨论】:

    【解决方案3】:

    但是如果日志信息在更高版本中不可用呢? 实例?

    您可以在重新抛出异常时将这些信息传回给调用者

    private void AddSomethingToTable(string tablename, string fieldname) {
      try {
        InsertFieldToTable(tablename, fieldname);
      } catch (Exception ex) {
        string str = string.Format("Could not insert field '{0}' into table '{1}'", fieldname, tablename);
        throw new Exception(str, ex);
      }
    

    }

    【讨论】:

    • 问题是关于仅使用 try/catch 的做法,您可以对错误进行有意义的处理。换句话说,将他的 try catch 放置在低级方法中仅仅是为了添加日志记录,或者只是将其保留在可能的最高级别是错误的。
    • @user1666620,可能是我的错误解释,但部分问题是如果它没有登录到较低级别的捕获中,那么调用者中会丢失数据(OP 指出)。我想在这里指出相同的内容。
    • @Rahul 再次查看 OP 的问题,然后阅读链接的答案。他已经在低级方法中记录数据。他在问“这是否是错误的做法”,
    • 不知何故你们俩都是对的 :) 我要求记录信息,但 Rahul 提供了一种可能的不同方法,我没有明确要求,但在某些情况下可能是一种解决方案
    【解决方案4】:

    我想你用

    回答了你自己的问题

    但是在更高的实例中不可用的日志信息呢

    和

    此信息可能很重要,并且在该方法之外会丢失

    我不喜欢“总是做 X 而从不做 Y”,因为有时必须违背所谓的“最佳实践”才能为您的应用做最好的事情。

    如果记录信息对于解决问题是必要的,并且如果您不立即记录它会丢失此信息,请记录该信息。

    【讨论】:

      【解决方案5】:

      您尝试做的事情没有错。另一个问题/答案的想法是最好在你真正处理它的地方记录错误。在 .NET 中,每个异常都包含一个堆栈跟踪。这意味着上层可以在产生这个错误的代码中报告位置。在一个地方而不是多个地方这样做更有意义。这是他们的主意。

      【讨论】:

        猜你喜欢
        • 2014-08-23
        • 2011-11-17
        • 2014-09-09
        • 2012-04-25
        • 2012-05-14
        • 2013-06-17
        • 1970-01-01
        • 1970-01-01
        • 2013-01-15
        相关资源
        最近更新 更多