Observability(可观测性)—— 让系统内部状态可见
解决什么问题:生产环境出问题时"看不到、查不到、不知道为什么"—— 可观测性 = 系统在被询问时能告诉你它内部发生了什么—— 通过 Logs(事件流)/ Metrics(数值)/ Traces(请求链)让内部状态可见。 没有可观测性 = 反馈环测量环节缺失 = 控制论意义上的失控。
它是什么
Observability(可观测性) 是 L2 设计层的核心质量属性——指系统能通过外部输出推断内部状态的能力。
可观测性的 3 大支柱:
| 支柱 | 数据形态 | 用途 |
|---|---|---|
| Logs(日志) | 离散事件 | "发生了什么" |
| Metrics(指标) | 数值时间序列 | "现在状态如何" |
| Traces(追踪) | 请求链路 | "调用链如何流转" |
SE@G Ch 23(Winters / SRE)原话: "Observability is the ability to ask questions about your system without shipping new code. Logs, metrics, and traces are the three pillars that make this possible."
控制论 Ch 4 §4.6(钱学森): "反馈控制系统... 只有能测量的输出,才能形成有效的反馈。"
可观测性 = 控制论"反馈环"的"测量"环节的工程化。
可观测性 vs 监控:
| 维度 | 可观测性 | 监控 |
|---|---|---|
| 范围 | 全量内部状态可见 | 预定义指标的告警 |
| 问题 | "为什么" | "出事了" |
| 数据 | 高维、关联、可查询 | 单维、聚合、阈值告警 |
| 应对 | 未知问题的根因分析 | 已知问题的快速响应 |
V2 视角(V2.7 B5 段 3 反馈 + B2 段 4 Hyrum's Law): 可观测性 = 反馈环的"测量"环节——没有可观测性的系统 = 反馈环不闭合 = 失控。 可观测性也对抗 Hyrum's Law——契约未被使用 = 契约未被测量 = 隐性技术债。
关键属性
| 属性 | 值/含义 |
|---|---|
| 高基数 | 可按任意维度查询(用户 ID / 请求 ID / 标签) |
| 关联性 | 跨服务/跨事件的关联 ID |
| 时序性 | 严格时间戳 + 因果顺序 |
| 可查询 | 支持任意维度的实时查询 |
| 低成本 | 不影响生产性能(采样 / 聚合) |
| 可保留 | 数据可长期存储(小时 → 天 → 月) |
| 告警友好 | 支持阈值告警 + 异常检测 |
| 反模式 | 只采不查 / 无 traceId / 日志不可解析 / 无关联 |
| 判错标志 | 出问题只能看日志末尾 / 跨服务问题查不到原因 / 监控告警风暴 |
怎么用
场景 1:结构化日志(Structured Logs)
import structlog
logger = structlog.get_logger()
# ❌ 非结构化日志(难以查询)
logger.info(f"Order {order_id} created by customer {customer_id} with {len(items)} items")
# ✅ 结构化日志(可查询)
logger.info("order.created",
order_id=order.id,
customer_id=order.customer_id,
item_count=len(order.items),
total_amount=str(order.total_amount),
trace_id=current_trace_id,
)结构化日志的 5 个核心规则:
- JSON 格式——机器可解析
- 关键字段——业务 ID(orderId / customerId)+ traceId
- 时间戳——ISO 8601 + 毫秒精度
- 日志级别——DEBUG / INFO / WARN / ERROR / FATAL
- 不要敏感信息——密码 / 身份证 / 银行卡绝不写入日志
场景 2:Metrics(指标)—— 数值时间序列
from prometheus_client import Counter, Histogram, Gauge
# Counter(累计计数)
orders_created = Counter(
"orders_created_total",
"Total number of orders created",
["customer_segment", "order_type"] # 标签维度
)
# Histogram(分布统计)
order_amount = Histogram(
"order_amount_cny",
"Order amount distribution",
buckets=[10, 50, 100, 500, 1000, 5000, 10000]
)
# Gauge(当前状态)
active_orders = Gauge(
"active_orders_count",
"Currently active orders in the system"
)
# 使用
orders_created.labels(customer_segment="vip", order_type="online").inc()
order_amount.observe(order.total_amount.value)
active_orders.inc()Metrics 的 4 类指标(USE / RED 框架):
| 框架 | 维度 | 指标 |
|---|---|---|
| USE | 资源(每台机器) | Utilization / Saturation / Errors |
| RED | 服务(每个端点) | Rate / Errors / Duration |
| 4 大黄金信号 | 整体 | Latency / Traffic / Errors / Saturation |
| 业务指标 | 业务层面 | 订单量 / GMV / 转化率 |
场景 3:Distributed Tracing(分布式追踪)
from opentelemetry import trace
tracer = trace.get_tracer("order-service")
# 创建 span
with tracer.start_as_current_span("place_order") as span:
span.set_attribute("customer.id", customer_id)
span.set_attribute("order.items_count", len(items))
# 跨服务调用会自动传播 trace context
with tracer.start_as_current_span("inventory.reserve") as child_span:
result = inventory_client.reserve(items)
child_span.set_attribute("inventory.reserved_count", result.count)
with tracer.start_as_current_span("payment.charge") as child_span:
payment = payment_client.charge(amount)
child_span.set_attribute("payment.amount", str(amount))Trace 的 5 个核心概念:
- Trace = 一次完整请求的调用链
- Span = 调用链中的一个环节
- TraceId = 整个调用链的唯一 ID(贯穿所有服务)
- SpanId = 当前 span 的 ID
- ParentSpanId = 上游 span 的 ID
Trace 的关键作用:
- 看到完整调用链(不只是单服务)
- 看到每个环节的耗时(定位慢在哪)
- 看到每个环节的错误(定位失败在哪)
场景 4:关联 ID(Correlation ID)—— 跨服务追踪
import uuid
class RequestContext:
"""请求上下文 = 跨服务/跨事件的关联 ID"""
trace_id: str
span_id: str
user_id: str
request_id: str
# HTTP 头传递
# X-Trace-Id: abc-123-xyz
# X-Request-Id: req-456
# 事件传递
@dataclass(frozen=True)
class OrderCreated:
order_id: str
customer_id: str
trace_id: str # 跨事件传递
causation_id: str # 直接父事件 ID关联 ID 的 4 个核心作用:
- 跨服务串联——一个请求的完整链路
- 跨事件串联——异步系统的事件链
- 用户行为串联——一个用户的所有操作
- 故障定位——出问题能快速找到"所有相关日志"
场景 5:告警分级与降噪
# SLO-based alerting(基于 SLO 的告警)
- alert: OrderErrorBudgetBurn
expr: |
sum(rate(orders_failed_total[5m])) /
sum(rate(orders_total[5m])) > 0.01
for: 5m
labels:
severity: critical
annotations:
summary: "订单错误预算燃烧率 > 1%"
description: "过去 5 分钟订单错误率 > 1%,请检查"
# 多窗口告警(避免噪声)
- alert: HighLatencyMultiWindow
expr: |
(
rate(http_request_duration_seconds_sum[1m]) /
rate(http_request_duration_seconds_count[1m]) > 0.5
)
and
(
rate(http_request_duration_seconds_sum[1h]) /
rate(http_request_duration_seconds_count[1h]) > 0.3
)告警分级的 4 个级别:
| 级别 | 含义 | 响应时间 | 示例 |
|---|---|---|---|
| P0 / Critical | 业务中断 | 立即 | 订单全挂 |
| P1 / High | 部分功能受损 | 15 分钟 | 支付失败率 > 5% |
| P2 / Medium | 性能下降 | 1 小时 | P99 延迟 > SLO |
| P3 / Low | 提示 | 4 小时 | 错误预算消耗快 |
场景 6:可观测性的"3 个反模式"
反模式 1:只采不查
症状:
- 100+ 业务指标
- 但没有人主动查询
- 出了问题只能看 ERROR 日志
正解:
- 每个指标必须服务一个"会被问到的问题"
- 季度清理不用的指标
- 指标要有 owner反模式 2:无关联 ID
症状:
- 订单服务有 traceId
- 库存服务有自己的 requestId
- 两个 ID 没关系
正解:
- 同一请求的所有服务必须用同一 traceId
- 异步事件必须带 traceId
- 跨系统传递用 HTTP 头 / 事件字段反模式 3:日志洪水
症状:
- 每个请求 100+ 条日志
- 存储成本失控
- 真正的问题日志被淹没
正解:
- 关键路径日志(INFO)
- 调试日志用 DEBUG(按需开启)
- 业务事件日志 = 状态变更(如 order.created)
- 不要日志"普通操作"(如"读取成功")常见误区
- "可观测性 = 多采日志"——错。可观测性 = 能从外部推断内部状态,不是日志量
- "日志 = 可观测性"——错。日志只是 3 大支柱之一,Metrics + Traces 同样重要
- "告警 = 可观测性"——错。告警是"已知问题响应",可观测性是"未知问题定位"
- "高基数标签"——错。Metrics 标签基数高(用户 ID)= 存储爆炸。用 Traces 而非 Metrics
- "采样 = 丢数据"——半对。采样是有损压缩,关键路径 100% / 其他采样,不是简单丢弃
- "只关注技术指标"——错。业务指标 + 技术指标同样重要(订单成功率 vs CPU 利用率)
- "上线后再加可观测性"——错。可观测性是设计阶段就要规划——后期补 = 改不动 / 补不全
关键洞察
可观测性 = 控制论"反馈环"的"测量"环节的工程化—— 没有可观测性 = 反馈环不闭合 = 失控。
可观测性不是"加日志/加监控",是让系统能回答你"为什么"—— 当一个未知问题发生时,能不能在 30 分钟内找到根因,决定了系统能不能活。
V2 B5 反馈的工程含义—— Logs = 事件流(发生了什么) Metrics = 数值时间序列(现在状态) Traces = 调用链(哪里慢/哪里错) 三者互补,不可替代。
V2 B2 段 4 Hyrum's Law 的工程含义—— 没被测量的行为 = 隐性技术债。 没被观察的接口 = 隐性依赖。 可观测性 = 让"隐性"变"显性" = 让技术债可偿还。
判断可观测性是否足够的 5 个标准:
- 未知问题能在 30 分钟内定位(根因分析能力)
- 已知问题能在 5 分钟内告警(响应能力)
- 数据能跨服务/跨事件关联(全链路能力)
- 业务指标 + 技术指标都有(双视角能力)
- 告警噪声 < 5%(信噪比)
可观测性的最高境界 = "未知的未知"也能被回答—— 不是"出事了去找日志",是"系统出问题时能自动告诉你为什么"。
相关链接
- Maintainability——可观测性辅助可维护性
- Performance Consistency——性能指标的可观测
- CQRS + Event Sourcing——事件流 = 业务可观测性的 SSOT
- [V3 涌现作为] · 反馈——可观测性 = 反馈环的测量
- [V3 涌现视域] · 认识自己——观测到的 ≠ 实际的(B2 的清醒)
- L4 Event Observability——事件驱动下的可观测性