指标、追踪与延迟
从“感觉变慢”升级到测量吞吐、延迟、错误率和资源使用。
指标、追踪与延迟
Node 服务常记录请求耗时和错误率。AI 推理和机器人节点还需要关注队列等待、端到端延迟、丢帧和 CPU/内存使用,因此指标必须跟着数据流走。可观察性不是“多打日志”,而是为关键事件定义稳定的指标、日志和追踪关联。先画一条消息从入口到输出的路径,再决定在哪些边界记录时间、状态和资源。
平均值会掩盖尾延迟:一次偶发的 GPU 分配或锁等待可能让 p99 超过控制周期。指标名称、单位和标签要稳定,标签数量也要有限,不能把用户 id 或任意 URL 作为高基数标签。日志保存具体样本的摘要,指标负责聚合趋势,追踪负责一次请求跨组件的时间线。
学习目标
- 能区分指标、日志和追踪分别回答的问题,并为关键路径选择少量字段。
- 能测量端到端延迟、队列等待和失败率,而不只测单个函数时间。
- 能控制标签基数与敏感数据,确保观测本身不会增加风险或成本。
性能优化从一个可测量的问题开始
下面这段代码只保留同一个意图,重点观察输入边界、数据流和失败语义,而不是逐字符翻译。
const start = performance.now();
const result = await infer(input);
metrics.observe("infer_ms", performance.now() - start);
return result; # Python
start = time.perf_counter()
result = infer(input)
metrics.observe("infer_seconds", time.perf_counter() - start)
return result
// C++
auto start = Clock::now();
auto result = infer(input);
metrics.observe("infer_ms", elapsed_ms(start)); 指标、日志和追踪各自回答什么
指标回答“总体是否变坏”,例如请求数、错误率、p50/p95/p99 延迟、队列深度和丢帧数;结构化日志回答“这条消息为什么失败”,例如 message_id、schema_version 和 error_type;追踪回答“时间花在哪里”,例如排队、预处理、推理和序列化 span。Python 与 C++ 的采集库不同,但字段命名和关联 id 应由系统契约统一。
start = time.perf_counter()
with tracer.start_as_current_span("infer") as span:
span.set_attribute("model_version", model_version)
result = model.predict(batch)
elapsed_ms = (time.perf_counter() - start) * 1000
metrics.histogram("infer_latency_ms", elapsed_ms, {"model": model_name})
端到端延迟与资源指标
为每条消息记录产生时间、入队时间、开始处理时间和输出时间,才能分开测量采集延迟、队列等待、推理耗时和发送耗时。机器人系统要监控 deadline miss、丢弃原因和传感器频率;AI 服务要监控批大小、GPU 显存、模型加载次数和输入 shape。不要把所有字段都作为标签,详细内容放在采样日志或追踪事件里。
常见错误与排错思路
常见错误是只测函数耗时,忽略排队和序列化;或者使用本地时钟比较跨机器事件,导致时间线倒退。排错时先用同一个 message_id 找到入口、队列、推理和输出四个事件,再比较 p95 与单个慢样本;若指标暴增,检查标签是否把 request id 当维度。时间测量用单调时钟,墙上时间只用于跨系统展示。
为一次处理建立最小观测点
沿“接收—排队—推理—返回”给同一请求关联 request id,在每段记录开始和结束时间;指标记录可聚合的阶段耗时、成功/失败数与队列深度,日志记录具体错误类别,追踪则连接一次请求跨越的组件。避免把用户 id、完整 URL 或事件 id 放进无限增长的指标标签。
const started = performance.now();
const result = { ok: true, stage: "inference" }; // 代表一次已完成的阶段
const elapsedMs = performance.now() - started;
console.log({ stage: result.stage, ok: result.ok, elapsedMs: Math.round(elapsedMs) });
实际服务应使用单调时钟测持续时间,避免系统时间校准导致负延迟。日志输出适合本地示意;生产环境还应使用结构化 logger,统一采样、脱敏和保留周期。
验证指标是否有诊断价值
人为注入一次慢队列、一次模型超时和一次非法输入,检查面板是否能区分等待、计算、依赖和输入问题。记录 p50/p95/p99 而不只看平均值;平均值可能掩盖少数严重卡顿。每个指标要有单位、统计窗口和告警行动,日志则带 request id 与组件版本。
告警阈值应关联用户可感知目标和持续窗口,避免一次短尖峰就触发噪声。采样率、指标保留期限和隐私脱敏也属于观测设计;新增字段前确认它既能帮助定位,又不会造成高基数或暴露用户数据。
若指标无法回答“下一步查哪里”,先减少噪声并补阶段边界。若标签数量随请求数增长,改为低基数错误类别,把高基数标识保留在受控日志或 trace 中。
迁移练习
请完成:为传感器到推理结果的链路选择三个核心指标、两个日志字段和一个追踪 span,写出它们的单位、标签与采样策略。
指标、追踪与延迟练习
为传感器到推理结果的链路选择三个核心指标、两个日志字段和一个追踪 span,写出它们的单位、标签与采样策略。
给我一点提示
至少包含一个延迟指标、一个失败指标和一个积压指标;避免把 message_id 作为指标标签。
查看参考答案
指标可选 end_to_end_latency_ms 的 p95、validation_errors_total、queue_depth;标签只用低基数的 model_version 或 error_type。日志带 message_id 和 input_shape,追踪包含 queue_wait 与 infer span,详细慢样本按比例采样。 本节结论
可观察性是迁移基础的收束点:它让 Python 和 C++ 的性能、可靠性都能被验证。完成后,请用一条固定消息走完整条链路,确认指标、日志和追踪能通过关联 id 对上。
小结
指标用于趋势和告警,日志用于具体上下文,追踪用于跨组件因果路径;时间和队列必须覆盖端到端。接下来做性能优化时,应先用这些观测建立基线,再定位真正热点。
阶段共 8 节课,按顺序完成更容易建立完整的迁移模型。