错误日志

函数有时需要告诉外部系统一个错误,而不把它传播给其调用者。在这里,日志是一个明显的选择;但要注意记录错误的内容和方式。

  • 好的测试失败信息一样,日志信息应该清楚地表达出错的原因,并通过包括相关信息来帮助维护者诊断问题。
  • 避免重复。如果你返回一个错误,通常最好不要自己记录,而是让调用者处理。调用者可以选择记录错误,也可以使用rate.sometimes限制记录的速度。其他选择包括尝试恢复,甚至是停止程序。在任何情况下,让调用者控制有助于避免日志垃圾。 然而,这种方法的缺点是,任何日志都是用调用者的行座标写的。
  • PII要小心。许多日志汇不是敏感的终端用户信息的合适目的地。
  • 尽量少使用log.Error。ERROR级别的日志会导致刷新,比低级别的日志更昂贵。这可能会对你的代码产生严重的性能影响。当决定错误级别还是警告级别时,考虑最佳实践,即错误级别的消息应该是可操作的,而不是比警告 “更严重”。
  • 在谷歌内部,我们有监控系统,可以设置更有效的警报,而不是写到日志文件,希望有人注意到它。这与标准库expvar类似,但不完全相同。

自定义日志级别

使用日志分级(log.V)对你有利。分级的日志对开发和追踪很有用。建立一个关于粗略程度的约定是有帮助的。比如说。

  • V(1)写少量的额外信息
  • V(2)中跟踪更多信息
  • V(3)中倾倒大量的内部状态。

为了尽量减少粗略记录的成本,你应该确保即使在 log.V 关闭的情况下也不要意外地调用昂贵的函数。log.V提供两个API。更方便的那个带有这种意外支出的风险。如有疑问,请使用稍显粗略的风格。

// Good:for _, sql := range queries {  log.V(1).Infof("Handling %v", sql)  if log.V(2) {    log.Infof("Handling %v", sql.Explain())  }  sql.Run(...)}
 复制代码// Bad:// sql.Explain called even when this log is not printed.log.V(2).Infof("Handling %v", sql.Explain())