mcpField
A
awesome-logging-standards

awesome-logging-standards

github.com/khasky开发2258 次安装1 周前更新
代码仓库

关于 awesome-logging-standards

用于添加或审查应用日志的技能,强调结构一致、包含有用上下文,并避免泄露密钥或个人信息。适合制定日志规范、为服务添加日志及排查问题的开发者。

主要功能

  1. 01建议使用可查询的结构化日志
  2. 02指导统一日志级别
  3. 03为事件补充运维上下文
  4. 04避免记录密钥和个人信息
  5. 05提供验证步骤与审查清单

适用场景

  1. 01为服务端点添加日志
  2. 02数据泄露事件后审查日志
  3. 03制定项目日志规范

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/khasky/awesome-agent-skills --skill awesome-logging-standards

安装后在 Claude Code 中输入/awesome-logging-standards确认已加载。

附带文件evals/eval_queries.json

详细介绍

日志记录标准

采用一致的日志记录方式,使操作可调试且符合规范,同时不泄露机密或个人身份信息。

何时启用

  • 添加或重构日志语句时
  • 用户询问“日志记录”“日志格式”或“应该记录什么”时
  • 制定或审查项目的日志记录标准时
  • 发生日志信息不足或泄露数据的事故后

核心原则

  • 埋点前先明确“正常工作”的定义——写下值班人员实际会问的 2–4 个问题(“这个用户的结账是否成功?”“哪个依赖项速度慢?”),并确保每条信号都能对应其中一个问题。无法回答任何运维问题的日志行就是噪声。
  • 结构化——优先使用键值字段(例如 JSON),而非冗长的文字描述,以便查询和解析日志。在整个应用中使用相同的结构(时间戳、级别、消息、字段)。
  • 基数——绝不要在指标或标签中使用无界值作为索引键或标签键(user_id、email、完整 URL、原始错误文本),否则基数会急剧膨胀;应将它们保留为事件字段。针对症状(用户可见的故障)而非原因(某台主机的 CPU 使用率)设置告警。
  • 验证遥测本身——添加埋点后,主动触发故障,并确认仅凭日志或指标就能找到它。未经测试的可观测性往往会悄无声息地出错——例如,在生成指标之前进行采样,会按采样比例扭曲请求速率指标,但表面上看不出任何异常。
  • 级别——保持一致:ERROR(故障、异常)、WARN(可恢复问题、弃用)、INFO(关键业务事件、请求摘要)、DEBUG(详细流程;在生产环境中禁用或采样)。
  • 上下文——在可用时包含 request_id、trace_id 或 correlation_id。仅在安全且符合政策的情况下,才包含 user_id、order_id 或类似标识符。除非确有需要且符合规范,否则不要以明文形式记录完整个人身份信息(邮箱、电话、地址)。
  • 不记录机密——绝不要记录密码、令牌、API 密钥或完整卡号。应脱敏或省略。用于调试时,仅在政策允许的情况下进行掩码处理或只显示末 4 位。
  • 统一位置——使用项目的日志记录库(Winston、Pino、log4j、structlog 等),并输出到平台采集日志的同一管道(例如 stdout)。

工作流程

  1. 检查现有做法——项目使用什么格式(JSON、纯文本)?使用什么库?有哪些级别?遵循现有做法。
  2. 选择级别——故障使用 error;可恢复问题或弃用使用 warn;关键操作(请求完成、订单创建)使用 info;详细流程使用 debug。不要在高负载路径中使用 info 记录冗长的逐项日志;应使用 debug 或经过采样的 info。
  3. 添加上下文——请求 ID、操作名称、时长、状态。仅在政策允许时添加标识符(user_id、order_id)。记录为结构化字段;如果日志记录器支持结构化字段,不要将这些信息插入消息字符串。
  4. 脱敏——不得包含机密;消息或字段中不得包含完整个人身份信息。如果调试时必须记录敏感信息,应采用脱敏或采样,并做好说明。
  5. 验证——日志写入 stdout 或已配置的接收端;格式可解析;样例输出中不含机密或个人身份信息。

应记录的内容

类别级别内容不要记录
请求开始/结束INFO方法、路径(去除查询字符串)、状态、duration_ms、request_id请求正文、包含令牌的标头、查询字符串、包含令牌或个人身份信息的路径片段
错误ERROR消息、错误类型、堆栈(服务端)、request_id完整请求/响应、机密
可恢复问题WARN消息、上下文(例如重试次数)、request_id
关键业务事件INFO事件名称、相关 ID(安全时可包含 order_id、user_id)、结果完整载荷、个人身份信息
外部调用INFO 或 DEBUG服务、操作、duration_ms、结果(成功/失败)完整请求/响应、凭据
详细流程DEBUG步骤、状态、ID机密、个人身份信息

格式(结构化)

JSON(推荐用于生产环境):

{
  "timestamp": "2024-03-15T10:30:00.123Z",
  "level": "info",
  "message": "Request completed",
  "request_id": "abc-123",
  "method": "GET",
  "path": "/api/orders",
  "status": 200,
  "duration_ms": 45
}

字段:优先使用一致的名称(根据项目使用 snake_case 或 camelCase)。将可变数据放入字段,而不仅仅放在消息字符串中,以便查询日志。

宽事件(规范日志行)

对于由请求驱动的服务,优先为每个服务的每个请求记录一条上下文丰富的结构化事件,而不是分散的日志行:

  • 中间件创建事件,并负责计时、状态和发出事件 — 在 finally 中发出,确保失败时也会生成事件。处理程序只需沿途添加业务字段。
  • 在每个事件中包含环境字段:提交哈希、服务版本、区域。
  • 记录业务上下文,而不只是机制细节:“高级客户结账 2,499 美元失败”胜过“结账失败”。
  • 分散的逐步日志行应保持在 debug 级别;宽事件才是可查询的事件记录。

好与坏

好:

logger.info({ request_id, method, path, status, duration_ms }, 'Request completed');
logger.error({ err, request_id }, 'Payment failed');
logger.debug({ order_id, step: 'validation' }, 'Validating order');

坏:

console.log('User ' + user.email + ' did something');  // PII in log
logger.info('Token: ' + token);  // Secret in log
logger.error('Error: ' + err);   // May include stack or internal detail in message; use structured field

规则

  • 不要添加会转储完整请求/响应或环境变量的日志。如需调试,建议脱敏或采样。
  • 如果项目有日志或隐私政策(保留期限、PII、机密信息),请遵循该政策。
  • 写入前先清理 path:删除查询字符串,并将包含令牌、电子邮件或其他个人标识符的路径段替换为路由模板(/users/:id)。无需完整地址时,应屏蔽客户端 IP(将 IPv4 的最后一个八位组置零,将 IPv6 的最后 80 位清零)。
  • 记录事件,而不是数据:“用户更改了电子邮件”,附上用户 ID,绝不记录旧值和新值。
  • 将审计日志(敏感读取、管理员操作)与应用程序日志分开,并为其设置独立的保留期限和访问列表;应用程序日志可广泛访问且生命周期短,审计日志则两者皆非。
  • 使用与代码库其他部分相同的库和格式。没有充分理由时,不要引入第二套日志系统。

检查清单

  • 级别恰当(error/warn/info/debug)
  • 包含上下文(相关时包括 request_id、操作、持续时间)
  • 消息或字段中不含机密信息或完整 PII
  • 日志记录器支持时使用结构化格式(字段)
  • 符合项目使用的库和格式

反模式

反模式更好的做法
记录完整请求/响应记录方法、路径、状态、持续时间;脱敏或省略正文/标头
在服务端代码中使用 console.log使用项目日志记录器,并设置级别和结构
将所有内容都插入消息字符串使用结构化字段(request_id、order_id 等)
在循环的每次迭代中都以 info 级别记录日志使用 debug 级别或进行采样(例如每 N 次记录一次)
在生产代码路径中遗留打印调试代码(print()、fmt.Println、console.log)删除,或转换为带字段的 logger.debug
“之后再脱敏”从一开始就脱敏或省略;不要记录机密信息

评论

支持 Markdown