记录代码应该在哪里/哪个级别?

fea*_*net 18 language-agnostic logging design-patterns exception-handling

我想知道日志记录代码应该去哪里.例如,我的存储库是否应该记录它自己的错误?或者我应该从UI /控制器记录所有错误?是否有任何关于此的一般设计原则,或者是否有人链接到一篇好文章或某些东西.

Jus*_*tin 19

记录和跟踪是(IMO)的一门艺术,知道要记录什么以及需要经验的地方.

我发现学习伐木艺术的最好(最差?)方式是体验试图用粗暴的伐木来诊断问题的痛苦!

我能为您提供的是一些建议:

考虑如何使用日志消息.

良好记录是思考如何将日志信息使用,如果有问题,相反有关记录不佳的最糟糕的事情是,你将永远只能认识它,当你有一个问题,你没有足够的信息!

始终考虑日志消息对正在阅读它的人所说的内容,例如:

  • Windows API调用失败了吗?如果是这样,那么你可能需要记录HRESULTGetLastError结果(如果有的话),因为它有很多用处.
  • 无法在集合中找到条目?如果没有找到没有找到的条目的名称,那么任何人都不能推断出来 - 知道收集的数量也很方便,这样你就可以判断收集是否为空.

一个常见的错误是不考虑记录时需要哪些信息,但是您还应该仔细考虑何时记录消息 - 如果在正常操作下频繁记录消息,那么最好它的用处是有问题的,最坏的情况是日志消息可能会产生误导.

此外,请确保您可以识别记录消息的内容.如果您在日志中看到的只是一个字符串,它出现在您的代码库中很多次(或者更糟糕的是根本没有!)那么您将需要进行演绎和狡猾来确定该日志消息的来源(并且没有知道消息来自哪里,你对理解消息的希望渺茫)

  • 在多线程/多处理器应用程序中,始终记录线程ID和进程ID.
  • 如果您有任何类型的请求ID,也请记录.
  • 如果您认为您将花费任何合理的时间查看日志文件,那么您应该强烈考虑运送任何pdb等...需要文件才能查看源文件和行号.

记录仅在出现问题时使用

不要将日志记录错误处理混淆.错误处理是响应和解决该错误的行为(例如向用户显示消息),日志(通常)仅在出现错误且原因不清楚时使用.

例如:如果用户试图打开一个不存在的文件,那么如果错误被正确处理(通过告诉用户无法找到该文件),那么就不需要记录该错误.

(可能的例外情况可能是,如果您想要统计该错误发生的频率或其他事情 - 这会回到思考如何使用日志记录.)

通常,正确处理错误比记录更可取,但是良好的错误处理比良好的日志记录更难 - 这些是需要日志中提供的额外信息的情况.

您也不应该将日志记录审计混淆(尽管在许多系统中这两者重叠).

越多越好!

您可以记录太多的唯一方法是:

  • 你的存储空间不足.
  • 您会显着影响应用的效果.
  • 如果出现错误,您将无法轻松处理日志.
  • 你记录针对你老板的亵渎.

记录存在纯粹是为了诊断问题的原因(不要将记录与审计混淆) - 如果你没有任何问题,那么没有人会查看你的日志,也不会造成任何伤害!直到遇到问题,在这种情况下,您需要尽可能多的信息.

如果您对是否记录某些内容有疑问,请记录下来.

仅记录一次异常.

说完上述内容后,我觉得有必要澄清异常的记录.

通常,您应该只记录一次异常(在处理它的位置).不要试图记录以后抛出给调用者的异常"以防万一"调用者没有正确记录异常 - 所有发生的事情是你最终会因为通过多次记录同样的异常从层到层(我已经看到它发生了,这使得很难看到实际发生了多少错误).

记录错误是调用者的责任 - 唯一可能的异常可能是在系统边界(例如Web服务)之间传递,在这种情况下,无法跨所有错误详细信息进行传输.

记录任何相关的内容,无论它与记录相关的任何地方.

例如,如果您正在编写基于服务器的应用程序,那么您的日志文件需要位于服务器上,系统管理员可以在其中读取它们 - 如果有可能在客户端上发生错误(例如在JavaScript中),那么您的日志记录代码需要使用JavaScript.解决方案?您的JavaScript日志记录需要将自己提交给服务器(ala log4js)

不要担心,你应该不应该把日志-只要把它放在任何需要它.


Pét*_*rök 11

通常,最好在您拥有所有必要信息的地方记录事物.为了使您的应用程序更简单,最好不要传递数据,以便您可以将其记录到其他地方.(异常似乎是一个例外 - 对于双关语:-)抱歉 - 但它们的主要目的不是记录,这只是一个可能的副作用.)

不需要将日志记录限制到体系结构的特定模块/层(除了一些特殊情况,例如不应该记录任何内容的设备驱动程序,或者不能对环境做出假设的应用程序库).

请注意,即使在同一应用程序中,不同的日志消息也可能有不同的用途:

  • 提供有关应用程序中(正常)事件流的信息(即批处理应用程序可以记录它开始和结束,可能是处理的简要结果等).这些消息最好相对较少,包含有限数量的信息,因为它们通常意味着供人阅读(例如系统管理员在早上检查应用程序是否成功运行).由于这些是"正常"消息,因此它们的优先级位于比例的中间,例如INFO.
  • 警告异常事件(例如错误,崩溃,丢失文件......).这些消息应该很少(在普通应用程序中),但可能包含过多的信息(例如堆栈跟踪,核心转储等),这可能有助于识别底层错误.但是,当它们发生时,我们几乎总是希望看到它们,因此它们具有高优先级,例如ERROR或FATAL.
  • 提供有关应用程序特定部分发生情况的详细信息(通常用于调试目的).这些消息通常是真正的生猪,通常会生成千兆字节的日志数据.因此我们只想在特定情况下看到它们,因此很容易将它们的级别设置为低,例如DEBUG.

现代日志框架(如Log4J系列)允许非常灵活地处理来自应用程序不同部分的不同类型(级别)的消息.但是,在向代码添加大量日志消息之前,最好规划您的日志记录方案.即您计划在哪些类型的消息中记录应用程序的哪些部分,以及您将如何使用这些消息?您需要多少个什么样的日志目标(控制台,文件,数据库)?