请求日志(观测性)
「设备昨晚为什么没回话?」——以前只能猜,现在打开控制台「日志」页看一眼:那个时间点它的请求是 401(key 被撤了)、429(限流)、400(发了空文本)还是 5xx(上游故障),一行元数据就能定位。
能看什么
机器侧每次请求记一行元数据,覆盖这些端点:/v1/agent、/v1/tts、/v1/tts/stream、/v1/asr、/v1/kb/docs、/v1/kb/docs/:id、/v1/kb/search。
每行字段:
| 字段 | 含义 |
|---|---|
endpoint | 端点标签(固定小集合,见上) |
status | 最终 HTTP 状态码(SSE 流内的 error 事件不改状态码,与 Agent API 文档口径一致) |
latency_ms | 处理时延(毫秒)。agent / 流式 TTS 这类流式端点记到响应头就绪为止,不含流本身的播放时长 |
app_id / device_id | 这次请求用的是哪个 App 的 key / 哪台设备的 key(通用 key 两者皆空) |
session_id | 会话 id(仅 /v1/agent;就是你传的寻址串) |
text_chars | 涉及文本的字符数(只有长度,没有内容;ASR 记识别产出文本的长度) |
error_class | 错误分类词:4xx / 5xx;成功为空 |
channel | /v1/agent 的通道:byo(你配了自带通道)或 platform。这是配置口径——某一轮是否实际发生了回落,以对话流里的 provider_fallback / stats.channel 事件为准 |
ts | 记录时刻(UTC) |
每行还附带 summary:筛选范围内的请求数、错误数、时延 p50 / p95(服务端 SQL 聚合,lower nearest-rank 变体口径(offset=floor((n-1)·p/100),n=5/p=95 取第 4 行))。
看不到什么(刻意不记,这是承诺)
任何对话内容都不在日志里——你发的文本、喵喵的回复、提示词、音频字节、知识库正文、检索词原文,一概不存。text_chars 只是长度,error_class 只是分类词(绝不带上游错误原文)。
为什么这么设计:
- 隐私:日志一旦记内容,控制台、API、导出、备份每一条读路径都变成泄露面。源头不记,审计只需要盯一张表的 schema,而不是盯每条读代码。
- 体积:每请求一行已经是写放大,再带内容,7 天留存就能把库撑爆。
排障要的是「哪个端点、什么时候、什么状态、多慢」,不是对话本身——对话历史有专门的 会话 API,凭你的 key 按 session_id 读。
另外两类看不到的:
- 鉴权失败的请求(401/429)不记:没通过鉴权就没有租户归属,这行没法记到你名下。它们表现为「日志里压根没有那个时间点的行」——key 无效或被限流时设备端会直接收到 401/429。
- 流中途的失败:流式端点(agent /
/v1/tts/stream)日志记在响应头就绪时(此时状态码已定为 200),之后流里如果出错,走的是流内error事件,不会回头改日志行。
保留 7 天
日志只留 7 天,平台每 6 小时自动清理一次过期行。要长期留存,请用 API 定期拉走自存。
双面 API
控制台「日志」页(侧栏「观测」组)和机器侧 API 同形同源:
# 机器侧:租户通用 key(App 级 / 设备 key 会被 403——运行凭证读不了全租户日志)
curl -H "Authorization: Bearer sk-meow-..." \
"https://<你的域名>/v1/logs?limit=50&endpoint=/v1/agent&since=2026-06-11T00:00:00Z"参数:limit(默认 100,上限 500)、endpoint(精确匹配)、status(精确匹配)、since(ISO 8601 起始时刻)。响应形状见 API 参考 的 /v1/logs。
控制台页额外提供:端点下拉、「仅错误」开关(只过滤表格行,summary 仍是整个筛选范围的口径)、时间范围(近 1 小时 / 24 小时 / 7 天)。