【问题标题】:Where/what level should logging code go?日志记录代码应该在哪里/什么级别?
【发布时间】:2010-09-07 12:11:10
【问题描述】:

我想知道日志记录代码应该放在哪里。例如,我的存储库是否应该记录它自己的错误?或者我应该从 UI/控制器记录所有错误?有没有关于这个的一般设计原则,或者有没有人链接到一篇好文章或类似的东西。

【问题讨论】:

    标签: design-patterns language-agnostic logging exception-handling


    【解决方案1】:

    记录和追踪是 (IMO) 一门艺术,知道记录什么以及在哪里需要经验。

    我发现学习日志记录艺术的最佳(最差?)方法是体验尝试诊断伪劣日志记录问题的痛苦!

    我只能给你一些建议:

    考虑如何使用日志消息。

    良好日志记录的关键是考虑如果出现问题将如何使用日志消息,相反,不良日志记录最糟糕的事情是你会只有当您遇到问题并且您没有足够的信息时才意识到这一点!

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

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

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

    此外,请确保您可以识别记录消息的内容。如果您在日志中看到的只是一个多次出现在您的代码库中的字符串(或者更糟的是根本没有!)那么您将需要推理和狡猾地找出该日志消息的来源(并且没有知道消息来自何处,您就几乎没有希望理解它)

    • 在多线程/多处理器应用程序中,始终记录线程 ID 和进程 ID。
    • 如果您有任何类型的请求 ID,请将其记录下来。
    • 如果您认为您将花费任何合理的时间查看日志文件,那么您应该强烈考虑提供任何 pdb 等...文件,以便查看源文件和行号。

    仅在出现问题时使用日志记录

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

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

    (可能的例外是,如果您想要统计错误发生的频率或其他信息 - 这又要考虑如何使用日志记录。)

    一般来说,正确处理错误比记录日志更可取,但是良好的错误处理比良好的日志记录更困难 - 在这些情况下,需要日志中提供的额外信息。

    您也不应该将 loggingauditing 混淆(尽管在许多系统中两者是重叠的)。

    越多越好!

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

    • 存储空间不足。
    • 您会显着影响应用的性能。
    • 您会被大量日志淹没,在发生错误时无法轻松处理。
    • 你记录了针对你老板的脏话。

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

    如果您对是否记录某些内容有疑问,请记录它。

    只记录一次异常。

    说了这么多,我觉得有必要澄清一下异常的日志记录。

    一般来说,您应该只记录一次异常(在处理它的地方)。不要试图记录您稍后抛出给调用者的异常“以防万一”调用者没有正确记录异常 - 所发生的一切是您最终会在它通过时多次记录相同的异常从层到层(我已经看到它发生了,很难看到实际发生了多少错误)。

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

    记录任何相关的内容,无论在何处都可以记录。

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

    不用担心你应该不应该把日志放在哪里——只要把它放在需要的地方。

    【讨论】:

    • “只有在出现问题时才使用日志”:我不同意这种说法。日志记录用于各种事物、事件、时间/日期信息、程序流程信息、处理结果……即使在没有问题的完美世界中,您仍然需要记录很多事情。我什至会争辩说,程序中记录器发出的大多数消息都处于“信息”日志级别。
    【解决方案2】:

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

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

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

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

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

    【讨论】:

      【解决方案3】:

      我觉得 Microsoft 架构指南很好读。 http://msdn.microsoft.com/en-us/library/ff650706.aspx

      日志记录是所有层的交叉关注点

      【讨论】:

        【解决方案4】:

        到目前为止,我使用了“黑盒”策略。每段代码(函数或/和类)在许多方面都有自己的责任:输入测试、做它应该做的事情、错误处理、记录信息。因此,如果您的代码位于业务层,它应该抛出业务错误,并记录业务信息

        【讨论】:

          【解决方案5】:

          我认为在应用程序中非常重要的常见错误处理。

          来自JavaWorld,以下是常见错误处理必不可少的原因:

          1. 膨胀的日志:每个catch块都包含一个日志语句,导致源代码污染导致日志条目臃肿冗余。

          2. 冗余实现:相同类型的错误具有不同的表示,这使得处理方式变得复杂。

          3. 封装损坏:来自其他组件的异常被声明为方法签名的一部分,打破了接口和实现之间的明确划分。

          4. Noncommittal 异常声明:方法签名被泛化为抛出 java.lang.Exception。这样,可以确保客户端对方法的错误语义没有任何线索。

          【讨论】:

          • 当他说“我的存储库应该记录它自己的错误吗?或者我应该记录来自 UI/控制器的所有错误?”时,我认为问题是关于记录错误的。
          猜你喜欢
          • 1970-01-01
          • 2019-06-05
          • 2019-01-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-18
          相关资源
          最近更新 更多