我在当前项目中使用 logback。
它提供六个级别的日志记录: TRACE DEBUG INFO WARN ERROR OFF
我正在寻找一个经验法则来确定常见活动的日志级别。例如,如果一个线程被锁定,日志消息应该设置为调试级别还是信息级别。或者,如果正在使用套接字,则应在调试级别或跟踪级别记录其特定 ID。
我将感谢每个日志记录级别的更多示例的答案。
我主要构建大规模、高可用性类型的系统,所以我的回答偏向于从生产支持的角度来看待它;也就是说,我们大致分配如下:
错误:系统处于困境,客户可能受到影响(或即将受到影响),修复可能需要人工干预。 “凌晨 2 点规则”适用于此 - 如果您正在待命,如果发生这种情况,您是否希望在凌晨 2 点被叫醒?如果是,则将其记录为“错误”。
警告:发生意外的技术或业务事件,客户可能会受到影响,但可能不需要立即进行人工干预。待命人员不会立即接到电话,但支持人员会希望尽快审查这些问题以了解影响是什么。基本上任何需要跟踪但可能不需要立即干预的问题。
信息:我们希望大量查看的内容,以防我们需要对问题进行取证分析。系统生命周期事件(系统启动、停止)到这里。 “会话”生命周期事件(登录、注销等)位于此处。还应考虑重要的边界事件(例如数据库调用、远程 API 调用)。典型的业务异常可能出现在此处(例如,由于凭据错误而导致登录失败)。您认为需要在大批量生产中看到的任何其他事件都在这里。
调试:几乎所有不会使“信息”剪切的东西......任何有助于跟踪系统流程和隔离问题的消息,尤其是在开发和质量保证阶段。我们使用“调试”级别的日志来记录大多数重要方法的进入/退出,并在方法内标记有趣的事件和决策点。
跟踪:我们不经常使用它,但这将用于非常详细和潜在的大量日志,即使在正常开发过程中您通常也不希望启用这些日志。示例包括转储完整的对象层次结构,在大循环的每次迭代期间记录一些状态等。
与选择正确的日志级别一样或更重要的是确保日志有意义并具有所需的上下文。例如,您几乎总是希望在日志中包含线程 ID,以便在需要时关注单个线程。您可能还希望采用一种机制将业务信息(例如用户 ID)与线程相关联,以便它也被记录。在您的日志消息中,您需要包含足够的信息以确保该消息是可操作的。像“ FileNotFound 异常被捕获”这样的日志不是很有帮助。更好的消息是“尝试打开配置文件时捕获的 FileNotFound 异常:/usr/local/app/somefile.txt.userId=12344。”
还有许多不错的日志记录指南...例如,这是来自 JCL (Jakarta Commons Logging) 的编辑片段:
error - 其他运行时错误或意外情况。期望这些在状态控制台上立即可见。 warn - 使用已弃用的 API、API 使用不当、“几乎”错误、其他不希望或意外但不一定“错误”的运行时情况。期望这些在状态控制台上立即可见。 info - 有趣的运行时事件(启动/关闭)。期望这些在控制台上立即可见,所以要保守并保持在最低限度。调试 - 有关通过系统的流程的详细信息。期望这些仅写入日志。跟踪 - 更详细的信息。期望这些仅写入日志。
我的方法,我认为更多的是从开发而不是运营的角度来看,是:
错误表示某些任务的执行无法完成;无法发送电子邮件,无法呈现页面,无法将某些数据存储到数据库中,诸如此类。肯定出了什么问题。
警告意味着发生了意外的事情,但可以继续执行,也许是降级模式;缺少配置文件但使用了默认值,价格计算为负数,因此将其限制为零,等等。有些地方不对劲,但还没有完全出错 - 警告通常表明会有很快就出错了。
信息意味着发生了一些正常但重要的事情;系统启动,系统停止,每日库存更新作业运行,等等。这些不应该是持续的洪流,否则有太多的阅读。
调试意味着发生了一些正常且无关紧要的事情;一个新用户来到该站点,一个页面被渲染,一个订单被接受,一个价格被更新。这是从信息中排除的东西,因为它太多了。
Trace 是我从未真正使用过的东西。
这也可能有助于了解某个级别的日志记录请求(来自代码)是否会导致在给定部署配置的有效日志记录级别的情况下实际记录它。从此处的其他答案中确定您想要配置部署的有效级别,然后参考此内容以查看您的代码中的特定日志记录请求是否会被实际记录...
举些例子:
“在 WARN 处记录的日志代码行是否会实际登录到配置为 ERROR 的部署中?”桌子上说,不。
“在 WARN 处记录的日志代码行是否会真正登录到配置有 DEBUG 的部署中?”桌子上说,是的。
以更形象的方式,这里是选择规则的工作原理。在下表中,垂直标头表示记录请求的级别,用 p 表示,而水平标头表示记录器的有效级别,用 q 表示。行(级别请求)和列(有效级别)的交集是由基本选择规则产生的布尔值。
因此,请求日志记录的代码行只有在其部署的有效日志记录级别小于或等于该代码行请求的严重级别时才会真正被记录。
我从基于组件的体系结构中回答这个问题,其中组织可能运行许多可能相互依赖的组件。在传播失败期间,日志记录级别应该有助于识别哪些组件受到影响以及哪些是根本原因。
错误 - 该组件发生故障,并且原因被认为是内部的(任何内部的、未处理的异常、封装的依赖项失败……例如数据库、REST 示例是它从依赖项收到 4xx 错误)。让我(这个组件的维护者)起床。
WARN - 此组件发生故障,被认为是由依赖组件引起的(REST 示例将是依赖项的 5xx 状态)。让那个组件的维护者起床。
INFO - 我们想向操作员提供的任何其他信息。如果您决定记录快乐路径,那么我建议将每个重要操作(例如每个传入的 http 请求)限制为 1 条日志消息。
对于所有日志消息,请务必记录有用的上下文(并优先考虑使消息易于阅读/有用,而不是具有大量“错误代码”)
调试(及以下) - 根本不应该使用(当然也不应该在生产中使用)。在开发中,我建议结合使用 TDD 和调试(如有必要),而不是使用日志语句污染代码。在生产中,上述 INFO 日志记录与其他指标相结合就足够了。
可视化上述日志级别的一个好方法是为每个组件想象一组监控屏幕。当一切运行良好时,它们是绿色的,如果一个组件记录了一个警告,那么它会变成橙色(琥珀色),如果有任何东西记录一个错误,那么它会变成红色。
如果发生事故,您应该让一个(根本原因)组件变为红色,并且所有受影响的组件都应变为橙色/琥珀色。
其他答案没有什么不同,我的框架具有几乎相同的级别:
错误:应用程序上的严重逻辑错误,例如数据库连接超时。在不久的将来需要修复错误的事情警告:不是破坏性问题,而是需要注意的事情。就像未找到请求的页面信息:用于函数/方法的第一行,以显示已调用的过程或已执行的步骤,如插入查询完成日志:逻辑信息,如 if 语句的结果调试:变量永久观看的相关内容