AI 应用的 API 监控怎么做:从探测上游模型接口到告警的完整清单
AI 应用的 API 监控要分三层做:先用不消耗 token 的请求探测上游模型接口能不能连上,再在应用里给每次真实调用记录成功率和延迟,最后抽检输出质量,因为返回 200 不代表答案是对的。只做第一层,会漏掉限流、超时和“模型变笨”;只看厂商状态页,又会比自己的用户晚知道故障。下面按这三层给出探测频率、探测点位置、要记录的字段和一份可以直接照做的清单。
为什么不能只看官方状态页?
官方状态页是厂商人工发布的事件公告,有两个天然的局限:一是发布有延迟,工程师要先确认影响范围才会挂出事件;二是它描述的是厂商视角的组件状态,不知道你的请求从哪里出发、经过哪条线路。
状态页的事件等级本身也需要会读。比如 cdnping 从 2026-09-17 起同步的状态页记录里,Cloudflare 有 19 条 minor、3 条 major 事件,OpenAI 有 19 条 minor、4 条 major,其中有些只涉及某个区域或某个子产品,例如 Cloudflare 2026-10-16 的两条 minor 事件分别是 Ashburn 的 5xx 增多和泰国的网络性能问题。哪些和你有关,要结合你实际调用的接口判断,详细的读法见怎么看 OpenAI 状态页和 Claude 状态页。
所以状态页适合作为“确认是厂商问题”的证据,不适合作为第一个告警来源。第一个告警应该来自你自己的探测和埋点。
第一层:外部可达性怎么探测?
这一层回答“从某个位置出发,能不能把请求送到 API 入口并拿到响应”。它不关心模型输出,只关心 DNS、TCP、TLS、HTTP 这几步是否正常。
用什么请求探测才不花钱?
不要用真实的对话请求做高频探测,既耗 token,又会把模型推理的波动混进网络指标里。常见做法有两种:
- 不带密钥请求一个需要鉴权的路径,例如
GET /v1/models。拿到 401 说明 DNS、TLS 和网关都通了,只是鉴权没过,这正是可达性探测想要的结果。 - 带密钥请求模型列表接口。这类接口一般不按 token 计费,是否计费以各家官方文档为准;它还能顺便确认密钥有效。
下面是一个可以直接运行的探测脚本,用 curl 的计时变量把各阶段拆开:
#!/usr/bin/env bash
# probe.sh:对多个 API 入口做一次可达性探测,输出一行一条记录
endpoints=(
"openai https://api.openai.com/v1/models"
"anthropic https://api.anthropic.com/v1/models"
"deepseek https://api.deepseek.com/models"
)
for e in "${endpoints[@]}"; do
set -- $e
curl -s -o /dev/null --max-time 10 \
-w "$(date -u +%FT%TZ) $1 code=%{http_code} dns=%{time_namelookup} tcp=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n" \
"$2" || echo "$(date -u +%FT%TZ) $1 code=000 error=curl_exit_$?"
done
判断规则可以很简单:code 是 2xx、401 或 403 算“可达”;000(连接失败或超时)和 5xx 算“不可达”;429 单独记为“限流”,不要混进可用率。路径以各家官方文档为准,上面的写法只是示例。
多久探测一次?
可以从 5 分钟一次起步,cdnping 的边缘探测也用这个间隔。频率太高,单次网络抖动会制造大量告警;频率太低,例如 15 分钟一次,一次 20 分钟的故障可能只被采到一两个点。告警条件建议写成“连续 2 次失败”或“最近 3 次里有 2 次失败”,而不是单次失败就告警。
探测点放在哪里,结论差别有多大?
同时调用境外 API 和国产 API 的应用,探测点放在哪里,测出来的延迟甚至可用性会差很多。
以 cdnping 的 API 状态页为例,它从 Cloudflare 边缘每 5 分钟探测一次各家官方 API 入口。下面是 2026-10-17 08:40–10:05(UTC)这一窗口的快照,探测节点在丹佛(DEN),共 242 条探测记录。cdnping 从 2026-10-17 才开始采集,字段名里的“24h”实际只覆盖这一个多小时,只能用来说明方法,不能当成长期结论:
| 服务 | 入口 | p50(ms) | p95(ms) | 窗口内可用率 |
|---|---|---|---|---|
| OpenAI API | api.openai.com | 96 | 194 | 100% |
| Claude API | api.anthropic.com | 73 | 84 | 100% |
| Gemini API | generativelanguage.googleapis.com | 69 | 89 | 100% |
| DeepSeek API | api.deepseek.com | 353 | 414 | 100% |
| Kimi 开放平台 | api.moonshot.cn | 375 | 1125 | 94.4% |
| 阿里云百炼 | dashscope.aliyuncs.com | 615 | 1152 | 100% |
| 火山方舟 | ark.cn-beijing.volces.com | 485 | 1149 | 100% |
数据来源:cdnping 边缘探测,开放数据 /api/status,CC BY 4.0,口径见数据方法。
这张表里能看出两件事:
- 从美国节点看,境外 API 的 p50 在 100 ms 以内,国产 API 在 350–615 ms。这主要反映探测点到入口的距离,不代表国产 API 本身慢。把同样的脚本放在国内机房跑,差距很可能缩小甚至反过来。只用一个位置的探测结论去判断“哪家快”,是错的。
- 窗口很短时,一次失败就会明显拉低可用率。Kimi 开放平台在这个窗口里显示 94.4%。按 5 分钟一次算,一个多小时只有 18 个左右的采样点,失败 1 次就是 17/18 ≈ 94.4%。看可用率时要同时看样本量。
实际部署时,探测点应该和你的用户、你的服务器尽量在同一网络环境:
| 探测点 | 回答的问题 | 适合放什么 |
|---|---|---|
| 你的应用服务器所在机房 | 我的后端能不能调通上游 | 必须有,这是告警主来源 |
| 境内另一个机房或云区域 | 是单机房线路问题,还是普遍问题 | 用来排除自己机房的网络故障 |
| 境外节点或边缘网络 | 上游入口本身是否正常 | 可以先用 cdnping /status 这类公开数据当参照 |
自建之前,可以先把 /status 和 /down 当成外部参照:你的探测失败而公开探测正常,问题多半在你这一侧的网络;两边同时失败,再去翻状态页。判断思路和ChatGPT 挂了吗?三步判断是服务故障还是自己的网络问题一样。
第二层:真实请求的成功率和延迟怎么埋点?
可达性探测通过,不代表用户请求能成功。限流、额度耗尽、长上下文超时、流式响应中途断开,这些只有真实请求才会暴露。所以应用侧每次调用模型都要留一条记录。
每次调用要记录哪些字段?
| 字段 | 说明 | 用途 |
|---|---|---|
| ts | 请求开始时间 | 时间序列 |
| provider / endpoint | 调用的供应商和入口地址 | 按上游拆分 |
| model | 请求里的模型名,以及响应里返回的模型名 | 发现静默换模型 |
| status | HTTP 状态码,流式请求另记是否完整结束 | 计算成功率 |
| error_type | 超时、连接失败、429、5xx、内容过滤等 | 区分责任方 |
| connect_ms | 建立连接耗时 | 区分网络和推理 |
| ttft_ms | 首 token 时间 | 用户体感延迟 |
| total_ms | 总耗时 | 长请求排查 |
| input_tokens / output_tokens | 用量 | 对账、算吞吐 |
| retry_count | 重试次数 | 防止重试掩盖故障 |
| request_id | 上游返回的请求 ID | 给厂商提工单 |
延迟至少拆成连接、首 token、总耗时三段,原因和拆法在AI API 延迟拆解:连接建立、网关往返与首 token 时间里有详细说明。只记总耗时的话,输出长度一变,数字就没有可比性。
可用率按什么口径算?
口径不统一,不同团队算出来的数字没法比。建议明确写下来:
- 分子:成功的请求数。
- 分母:成功数加上“因上游自身原因失败”的请求数。
- 5xx、连接失败、超时算上游失败;400 参数错误、401 密钥错误算你自己的问题,不进分母;429 单独统计。
- 重试成功的请求,第一次失败照样记一次失败,否则重试会把故障藏起来。
公开数据里也能找到类似的口径。例如 AGI Plan 公开的逐小时请求统计(https://agiplan.dev/api/status/requests?month=YYYY-MM)只把 5xx 算作平台失败,可用率等于成功 /(成功 + 平台失败)。AGI Plan 是 cdnping 的商业合作方,这里提它只是作为口径参考。自己算可用率的完整脚本和口径讨论,见自己测 AI API 的可用率:指标、脚本与口径。
告警阈值怎么定?
建议先跑一到两周,拿自己的基线再定阈值,下面只是起步时的示例:
- 5 分钟窗口内某个上游的失败率超过平时基线的数倍,且请求数不少于 20 次。
- 首 token 时间的 p95 连续 15 分钟高于基线的两倍。
- 429 占比突然上升,往往是额度或速率限制的问题,应该通知负责账号和额度的人,而不是值班的网络工程师。
请求量少的深夜时段,要给阈值设最小样本数,否则 3 个请求里失败 1 个也会触发告警。
第三层:返回 200 但答案错了,怎么发现?
这一层是普通 API 监控通常不需要的。上游可能换了推理供应商或量化精度,接口全程返回 200,用户只会觉得“变笨了”。
可行的做法:
- 固定一组回归样本。例如准备 20 到 50 条有确定答案的提示,例如固定格式的 JSON 抽取、简单计算、指定关键词的分类,每天或每小时跑一次,记录通过率。
- 核对响应里的模型名。请求的模型和响应返回的模型不一致,要单独告警。更多一致性检查方法见怎么确认 API 给你的是哪个模型。
- 关注供应商和量化变化。通过聚合平台调用开源模型时,同一个模型名背后可能是不同供应商、不同精度。cdnping 的模型监测页基于 OpenRouter 公开 API,记录各推理供应商的可用率、延迟、量化精度和上下架变化,同一模型在不同供应商上的差别见同一模型换个 OpenRouter 供应商,可用率能差多少,背景知识见模型变笨还是换了供应商:推理供应商与 fp8、fp4 模型量化。
- 把用户反馈也当作信号。点踩率、重新生成率突然上升,有时比回归样本更早反映问题。
回归样本会消耗 token,频率不用高,但必须固定提示词和参数(温度设为 0 或尽量低),否则结果的波动大部分来自采样随机性。
可以直接照做的检查清单
可达性探测
- 每个上游入口都有一条不耗 token 的探测,5 分钟一次
- 探测点至少覆盖应用服务器所在机房,最好再加一个不同网络的位置
- 401/403 视为可达,000 和 5xx 视为不可达,429 单列
- 告警条件是连续多次失败,而不是单次失败
- 准备一个外部参照(例如 /status),用来区分自己网络问题和上游问题
真实请求埋点
- 每次调用记录上面字段表中的字段,至少包括状态码、错误类型、首 token 时间、request_id
- 可用率口径写进文档:哪些错误算上游、哪些算自己、重试怎么记
- 按供应商、模型、入口分别出图,不要只看全局成功率
- 告警阈值基于自己的基线,并设置最小样本数
输出质量
- 有一组固定回归样本定时运行,记录通过率
- 核对响应中的模型名
- 关注上游的供应商、量化精度和官网更新(可以订阅 /changes 的 RSS)
故障时
- 先看自己的探测和埋点,再看公开探测,最后看官方状态页
- 留存失败请求的 request_id,便于向厂商反馈
- 有备用上游时,切换条件和回切条件提前写好
先做哪一件
三层的成本差别很大:可达性探测几乎不花钱,半天就能搭起来;埋点需要改应用代码;质量抽检要持续维护样本。如果只能先做一件事,就先在应用服务器上跑探测脚本,再把它和 /status 的公开数据对照着看。上游出问题时,这样能比用户反馈更早知道,也能分清是自己的线路问题还是上游的问题。
调用境外 AI 服务时,请遵守各服务的使用条款和所在地的法律法规;各服务支持哪些地区,以其官方说明为准。