Logging Observability

提供结构化日志、分布式追踪与指标收集的最佳实践,适用于系统可观测性建设。

已扫描
适合谁
后端开发工程师、运维与 SRE 团队
不适合谁
无技术背景的普通用户、仅需简单功能的非开发者
国内可用性
需网络配置。可能需要网络配置或第三方服务可访问。
安装难度
新手友好(★☆☆)。基于终端操作、依赖、API Key 和本地环境要求的初步判断。

安装与下载

openclaw skills install @wpank/logging-observability

Skill 说明

命令、参数、文件名以原文为准

日志与可观测性

适用于日志、指标和追踪三大支柱的系统可观测性设计模式。

三大支柱

支柱目的解答的问题示例
日志发生了什么此请求为何失败?{"level":"error","msg":"payment declined","user_id":"u_82"}
指标多少 / 多快延迟是否在增加?http_request_duration_seconds{route="/api/orders"} 0.342
追踪请求流程性能瓶颈在哪里?Span: api-gateway → auth → order-service → db

每个支柱在相互关联时效果最佳。在每条日志中嵌入 trace_id,以便从日志条目跳转到完整的分布式追踪。


结构化日志

始终以结构化的 JSON 格式输出日志 —— 不要使用自由文本字符串。

必需字段

字段用途是否必需
timestampISO-8601 格式(含毫秒)
level严重程度(DEBUG … FATAL)
service日志来源服务名称
message可读的人类描述
trace_id分布式追踪关联标识
span_id追踪中的当前跨度
correlation_id业务级关联标识(如订单 ID)适用时
error结构化错误对象出错时
context请求相关的元数据推荐

上下文增强

在中间件层级附加上下文,使下游日志自动继承:

app.use((req, res, next) => {
  const ctx = {
    trace_id: req.headers['x-trace-id'] || crypto.randomUUID(),
    request_id: crypto.randomUUID(),
    user_id: req.user?.id,
    method: req.method,
    path: req.path,
  };
  asyncLocalStorage.run(ctx, () => next());
});

库推荐

语言优势性能
PinoNode.jsNode.js 中最快的日志库,开销极低优秀
structlogPython可组合处理器,支持上下文绑定良好
zerologGo零分配 JSON 日志优秀
zapGo高性能,支持类型字段优秀
tracingRust支持跨度与事件,异步感知优秀

选择原生输出结构化 JSON 的日志库。避免需要后期处理的日志工具。


日志级别

级别使用时机示例
FATAL应用无法继续运行,进程将退出数据库连接池耗尽
ERROR操作失败,需关注支付扣款失败:CARD_DECLINED
WARN意外但可恢复上游超时重试第 2/3 次
INFO正常业务事件订单 ORD-1234 成功创建
DEBUG开发者排查问题缓存未命中,键为 user:82:preferences
TRACE极细粒度(生产环境极少使用)进入 validateAddress,载荷为 ...

规则: 生产环境默认日志级别为 INFO 及以上。若记录 ERROR,应有人响应处理。每个 FATAL 都应触发告警。


分布式追踪

OpenTelemetry 设置

优先使用 OpenTelemetry 而非厂商专用 SDK:

import { NodeSDK } from '@opentelemetry/sdk-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';

const sdk = new NodeSDK({
  serviceName: 'order-service',
  traceExporter: new OTLPTraceExporter({
    url: 'http://otel-collector:4318/v1/traces',
  }),
  instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();

跨度创建

const tracer = trace.getTracer('order-service');

async function processOrder(order: Order) {
  return tracer.startActiveSpan('processOrder', async (span) => {
    try {
      span.setAttribute('order.id', order.id);
      span.setAttribute('order.total_cents', order.totalCents);
      await validateInventory(order);
      await chargePayment(order);
      span.setStatus({ code: SpanStatusCode.OK });
    } catch (err) {
      span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
      span.recordException(err);
      throw err;
    } finally {
      span.end();
    }
  });
}

上下文传播

  • 使用 W3C Trace Context (traceparent 头部) —— OTel 默认方式
  • 在 HTTP、gRPC 和消息队列间传播
  • 对异步工作器:将 traceparent 序列化至任务负载中

追踪采样

策略使用场景
始终开启低流量服务、调试
概率采样 (N%)一般生产环境
速率限制 (N/sec)高吞吐服务
尾部采样需要捕获所有错误追踪时

无论采用何种策略,始终对 100% 的错误追踪进行采样。


指标收集

RED 方法(请求驱动)

监控每个服务端点的以下三项:

指标衡量内容Prometheus 示例
速率每秒请求量rate(http_requests_total[5m])
错误失败请求比例rate(http_requests_total{status=~"5.."}[5m])
持续时间响应时间histogram_quantile(0.99, http_request_duration_seconds)

USE 方法(资源驱动)

用于基础设施组件(CPU、内存、磁盘、网络):

指标衡量内容示例
利用率资源繁忙百分比CPU 使用率 78%
饱和度队列或等待的工作量线程池中有 12 个请求排队
错误资源上的错误事件最近一分钟内发生 3 次磁盘 I/O 错误

监控栈

markdown


name: Logging Observability

version: 0.1.0

description: 用于实现可观测性的日志与监控最佳实践

summary: 一套完整的日志、指标、链路追踪和告警设计指南,适用于微服务架构

category: observability

tags:

- logging

- metrics

- tracing

- alerting

- dashboard

- best practices


工具概览

工具类别适用场景
Prometheus指标基于拉取的指标采集,告警规则定义
Grafana可视化指标、日志、链路追踪的仪表盘展示
Jaeger链路追踪分布式调用链的可视化分析
Loki日志日志聚合(常与 Grafana 配合使用)
OpenTelemetry数据采集无厂商锁定的遥测数据采集框架

推荐方案: 优先采用 OTel Collector → Prometheus + Grafana + Loki + Jaeger 组合。仅当运维成本显著高于收益时,再考虑迁移到 SaaS 平台。


告警设计

严重性等级

严重性响应时限示例
P1立即响应服务完全不可用,数据丢失
P2小于 30 分钟错误率 > 5%,延迟 p99 > 5 秒
P3工作时间内响应磁盘使用率 > 80%,证书将在 7 天内过期
P4尽力处理非关键功能弃用警告

告警疲劳预防策略

  • 告警关注症状而非原因 — 如“错误率 > 5%”,而非“Pod 重启”
  • 支持多窗口、多燃烧速率检测 — 同时捕捉突发峰值与缓慢上升趋势
  • 强制关联操作手册链接 — 每个告警必须附带诊断与修复指引
  • 每月审查一次 — 删除或调整从不触发或持续触发的告警
  • 合并相关告警 — 使用抑制规则防止子级告警泛滥
  • 合理设置阈值 — 若告警每日触发且被忽略,应提高阈值或直接删除

仪表盘模式

总览仪表盘(“作战室”)

  • 所有服务的总请求量(每秒)
  • 全局错误率(百分比)及趋势线
  • p50 / p95 / p99 延迟
  • 按严重性分类的活跃告警数量
  • 图表上叠加部署标记

服务级仪表盘(按服务)

  • 每个端点的 RED 指标(Rate, Errors, Duration)
  • 依赖健康状态(上游/下游成功率)
  • 资源使用情况(CPU、内存、连接数)
  • 错误列表(按出现次数排序,显示最近一次时间)

可观测性检查清单

每个服务必须具备:

  • [ ] 使用结构化 JSON 格式记录日志,保持统一 schema
  • [ ] 请求中传播关联 ID / trace ID
  • [ ] 每个外部接口暴露 RED 指标
  • [ ] 提供健康检查端点(/healthz/readyz
  • [ ] 支持 OpenTelemetry 的分布式链路追踪
  • [ ] 为 RED 指标和资源使用情况配置仪表盘
  • [ ] 对错误率、延迟、饱和度设置告警,并附带操作手册链接
  • [ ] 日志级别可在运行时动态调整,无需重新部署
  • [ ] PII 数据脱敏已验证并经过测试
  • [ ] 定义日志、指标、链路追踪的数据保留策略

反模式

反模式问题解决方案
记录 PII隐私或合规风险隐藏或剔除 PII;使用令牌引用
过度日志输出存储成本激增,有效信息被淹没仅记录业务事件,而非数据流转过程
未结构化日志无法查询或基于字段告警使用结构化 JSON 并保持一致 schema
字符串拼接日志破坏结构化字段,存在注入风险将字段作为元数据传递,而非嵌入消息
缺少关联 ID无法跨服务追踪请求在所有请求中生成并传播 trace_id
告警风暴当班人员疲劳,真实问题被掩盖使用分组、抑制、去重机制
指标高基数标签Prometheus 内存溢出,仪表盘超时绝对不要将用户 ID 或请求 ID 作为标签

绝对禁止事项

  1. 绝不能记录密码、令牌、API Key 或任何密钥 — 即使是 DEBUG 级别也不行
  2. 绝不能在生产环境使用 console.log / print — 必须使用结构化日志器
  3. 绝不能将用户 ID、邮箱或请求 ID 作为指标标签 — 会导致标签基数爆炸
  4. 绝不能创建没有操作手册链接的告警 — 无法执行的告警会削弱团队信任
  5. 绝不能仅依赖日志 — 必须结合指标和链路追踪才能实现完整可观测性
  6. 绝不能默认记录请求/响应体 — 必须明确开启,并确保 PII 已脱敏
  7. 绝不能忽视日志量级 — 应设定日志配额,并在服务超过每日限额时发出告警
  8. 绝不能在异步流程中跳过上下文传播 — 断裂的链路追踪比无追踪更糟糕
W
@wpank

已收录 6 个 Skill

相关推荐