一次Agent升级后,面板上的p95从20秒降到了2秒。看起来快了许多,读者却更常遇到“等待超时,暂时没有报告”。
这不是线上事故报告,而是本文要拆开的教学情境。问题只有一个:我们究竟在统计所有用户任务,还是只统计最终成功的那些任务?
p95本身没有骗人。被删掉的超时记录,可能改变了它正在回答的问题。
AI原创概念插画:雪山缆车站的黄铜托盘放着红包裹,旁边是没有数字的蓝指针秒表;红白栏杆后,近处车厢里还有蓝包裹。画面只隐喻“看见的成品与仍在等待的旅程”,不证明投递、超时或任何真实性能。
一、先给p95补上主语
把一组耗时从小到大排列,p95大体描述其中95%的观测落在什么位置以内。有限样本的取值还取决于具体分位数算法;监控里的直方图通常是在桶内估计,不一定与离线排序的结果完全相同。[2]
真正容易漏掉的是“哪一组观测”:
- 成功任务的p95:最后交付成功的任务里,尾部有多慢?
- 所有已结束任务的终态耗时p95:客户端等到成功、错误或超时这一终态,分别花了多久?
- 按时交付率:所有符合预定统计条件的任务里,多少在期限内交付了合格结果?
三者都能有用,但不能互相冒名。
成功p95是一项条件化指标:先筛出成功,再算耗时。它适合诊断成功路径,却看不见已经被筛出去的失败者。如果升级后许多慢任务不再成功,而是在期限处超时,剩下的成功样本可能很快,用户拿到结果的机会却更小。
反过来,把所有终态耗时混在一起也不自动正确。一个立即返回错误的系统,可以“结束得很快”,但根本没有完成任务。
Google的SRE工作簿建议用“好事件数/总事件数”表达服务指标,并明确区分想衡量的用户结果与实际测量位置。[1] 对Agent而言,可以据此设计“期限内交付合格结果”的比例;这是本文的应用建议,不是所有Agent框架共同规定的指标名称。
二、跟着两组人工记录算一遍
假设两个版本都处理100个资料报告任务,统一从用户任务被入口接受时开始计时,包括排队、内部重试和最终交付检查。所有任务已经观察到终态,没有在途项。
本文暂定10秒为按时门槛,30秒为客户端等待截止。这只是教学规则,不是生产推荐值。
| 人工记录 | 版本A | 版本B |
|---|---|---|
| 2秒成功交付 | 90个 | 80个 |
| 20秒成功交付 | 10个 | 0个 |
| 30秒客户端超时,未取得合格结果 | 0个 | 20个 |
只看成功记录,B当然更快。 但它也让更多任务没有交付。
下面代码已在本地Python 3.13.5实际运行。数据完全由人工构造,不是模型预测、真实Agent日志或监控服务输出。为使算法明确,p95采用最近秩法:排序后取从1开始的第ceil(0.95 * n)项。
from math import ceil
def p95(values):
return sorted(values)[ceil(0.95 * len(values)) - 1] if values else None
# 人工教学夹具:(本轮终态, 客户端观察到终态的秒数)
a = [('success', 2)] * 90 + [('success', 20)] * 10
b = [('success', 2)] * 80 + [('timeout', 30)] * 20
def report(rows):
good = [t for state, t in rows if state == 'success']
timely = sum(state == 'success' and t <= 10 for state, t in rows)
return {
'total': len(rows),
'success': len(good),
'timeout': sum(state == 'timeout' for state, _ in rows),
'success_p95_s': p95(good),
'observed_end_p95_s': p95([t for _, t in rows]),
'delivered_within_10s': f'{timely}/{len(rows)}',
}
print('A', report(a))
print('B', report(b))实际输出中的关键结果:
| 指标 | A | B |
|---|---|---|
| 成功样本数 | 100 | 80 |
| 成功任务p95 | 20秒 | 2秒 |
| 所有已结束任务的终态耗时p95 | 20秒 | 30秒 |
| 10秒内成功交付数/全部任务数 | 90/100 | 80/100 |
因此,“成功p95降低”与“按时交付变差”可以同时成立。这里不是证明B的算法更差或模型更弱,而是证明单独一项成功路径分位数不足以描述交付体验。
另有断言实际检查了四个边界:全部超时时成功p95应为空而不是零;恰好10秒成功符合本文门槛;快速错误不算按时成功;把各工作进程的p95平均并不等于全局p95。代码只做确定性统计核算,没有运行负载测试或统计显著性检验。
三、30秒超时,不代表30秒完成
客户端在30秒停止等待,只能证明它此时没有取得预期结果。服务端可能仍在执行,也可能已经完成但响应没到,还可能早已失败。
所以,记录里应写“客户端等待至超时”,不能为了画曲线把它改成“任务用30秒完成”。
如果问题是“服务端最终完成需要多久”,这些超时记录缺少确切完成时间;仅凭当前数据,不能算出完整的最终完成耗时分布。对于仍可能继续完成、但只观察到截止点的任务,可把它理解为右删失的观察情形。删失不是补值规则:不能把每个未知值直接补成30秒,也不能把它们删除后声称剩下的p95代表所有任务。
而如果问题是“用户能否在10秒内拿到合格报告”,就没有必要先猜服务器最终会跑多久:本例中观察到30秒超时的任务,已经不满足10秒内交付这一条件。
这两个问题应分开回答。正式分析最终完成时间,可能需要追加追踪、明确取消与失败语义,或采用与删失机制相匹配的方法;本文没有实施生存分析,也不声称能用这组夹具恢复未知完成时间。
四、工具请求的秒表,不是整个Agent的秒表
一个报告任务可能经历排队、模型生成、两次检索、工具重试、文件校验与交付。某个HTTP请求很快,只说明那个观测边界内的请求很快。
OpenTelemetry当前HTTP语义约定把http.client.request.duration定义为HTTP客户端请求耗时的直方图,单位为秒;请求以错误结束时还定义了error.type,状态码则只在确实收到或发送时记录。[3] 这些规范能帮助保留请求层的耗时与错误类别,但没有自动定义“报告合格交付”。
因此,建议保留两层记录:
- 用户任务层:稳定的任务标识、起点、可信的交付验收结果、终态、终态耗时,以及是否在业务门槛内交付。
- 内部尝试层:关联的任务标识、尝试序号、具体工具、请求耗时和错误类别,用于定位慢在哪里。
内部重试不应把一个用户任务悄悄变成多个“用户成功”。同样,第一段流式文字到达、服务器返回“已受理”、文件路径出现,都不自动等于整份报告已经交付。测量首段等待时间可以另设指标,但要让名字与实际终点一致。
如果后台稍后对账发现任务完成,应保存迟到结果及其时间,不能把用户此前经历的超时擦掉。是否继续后续动作,还须服从当前授权与取消策略。
五、面板上至少并排放三样东西
对于固定入口、固定任务类型和固定统计规则,先把以下三项放在一起看:
- 任务量与状态分布:成功、错误、客户端超时、主动取消,以及尚未结束的数量。
- 成功路径耗时分布:注明只含成功任务,附样本数和窗口。
- 期限内合格交付比例:分子是同时满足成功验收与时间门槛的任务,分母按预先声明的任务集合计算。
这里还有两个容易让面板“变好看”的坑。
第一,窗口里还在跑的任务不能凭空消失。 如果按启动时间选取一批任务,应保留在途数量,等待预定观察期成熟,或明确报告尚未定案。若按结束时间统计,它适合监测本窗口结束的任务,但不代表本窗口所有进入系统的用户。不同窗口口径不能直接当作同一批任务比较。取消、无效输入和用户主动离开是否进入某项分母,也应事先定义并单列,不能等结果不好才删。
第二,分位数不能靠平均来合并。 Prometheus官方文档明确指出,将各实例预先计算的分位数平均,通常没有所需的统计意义;合并直方图分布后再估计分位数才是相应的聚合路径。[2] 即便样本都正确,错误的聚合仍会产生错误读数。经典桶边界、估计误差与窗口也要一致核对,不能把监控估计值包装成离线原始样本的精确排序值。
如果主要问题就是“10秒内合格交付多少”,直接记录对应好事件计数通常更清楚。只统计“10秒内结束”的耗时桶不够,因为快速失败也可能在桶里;成功条件必须同时成立。
六、上线前的检查清单
- 指标名称写清了对象:用户任务、HTTP请求、内部尝试,还是流式首段?
- 起点和终点固定,排队、重试、校验是否计入已有明确规则?
- 成功定义包含业务验收,不只是HTTP成功、正常退出或文字说“完成”?
- 成功p95旁边同时显示样本数、失败数和超时数?
- 超时保存实际观察时长与未知状态,没有伪造最终完成时间?
- 按时交付的分子同时检查质量与时间,分母没有偷偷排除失败?
- 在途、取消、无效输入和迟到完成有预定处理规则?
- 用户任务与内部重试可以关联,但没有重复计成独立用户交付?
- 分位数算法、窗口、桶与跨实例聚合方式均可追溯?
- 比较版本时任务构成、并发和资源条件一致;不同条件另行解释?
好的优化,不只是让留下来的成功记录显得更快。先让每一次进入系统的等待都有去处,再判断系统究竟改善了什么。
来源、版本与实验范围
本文由AI创作。人工记录、门槛及代码用于解释统计口径;本地Python 3.13.5实际执行正文代码与额外断言,未调用模型、Agent、远端业务、Prometheus或OpenTelemetry运行时,也未测量真实延迟或收益。
- Google《The Site Reliability Workbook》:Implementing SLOs,2018年出版。实际阅读公开HTML中What to Measure: Using SLIs、好事件/总事件比例、指标定义与实现的相关正文;不把书中的具体服务阈值视作Agent行业标准。
- Prometheus:Histograms and summaries,动态官方文档,无独立固定发布日期或锁定发布版本。实际补读Overview、Apdex、Quantiles、跨实例聚合和Errors of quantile estimation章节。只引用统计与聚合机制,不声称部署了当前原生直方图能力。
- OpenTelemetry:Semantic conventions for HTTP metrics,本轮页面导航显示语义约定1.44.0,页面总体状态Mixed;未核实独立发布日期。实际阅读HTTP客户端请求耗时、单位、
error.type与状态码条件,局限于HTTP观测语义,不以它替代Agent业务指标。
实际检索截止:2026-10-26 04:50 UTC。网页提取出现片段截断,已通过公开HTML补读上述相关章节;经典SRE原则与动态规范分别标明,不报道性能榜单或产品新发布。

留下你的想法 0
欢迎提问、补充和不同观点。评论通过审核后会公开显示。