# 问答耗时观测(F097) F101新增Redis回读细分:metrics.spans增加客户端HGETALL、字段解析、检查点选择、JSON/Base64及反序列化时间;metrics.measurements记录返回/选中编码数据量及固定字段分类。以.session_result_load定位最终回读,详见[Redis读取诊断](redis-read-timing.md)。不改变原读取行为,需重启后采集。 每个已接纳的 chat 请求在后台工作线程退出时写一条 `event=request_performance` JSON日志。按用户要求包含原始 `thread_id`,并保留每轮独立的 `request_id`、脱敏 `session_ref` 和 `outcome`。问题、回答、公司资料、资料标题、引用、附件地址和模型输入均不进入统计。其他既有日志继续通过request_id关联。 无需前端改动,没有新增SSE事件,不改变result或Redis会话结构。需重启后端后采集新请求,旧请求无法补算。此次仅增加观测,没有调整模型、并发数、检索预算、重试或生成提示。 ## 指标口径 `metrics.total_ms`:HTTP处理函数收到请求至后台工作线程退出前统计时的墙钟耗时,包含解析、接纳、排队、业务处理及收尾。直接调用Service时从Job创建计时。使用单调时钟,不受系统校时影响。 `metrics.milestones_ms`均为相对相同起点的时间,未发生为null,不用0冒充: | 字段 | 含义 | | --- | --- | | worker_started | 工作线程开始处理;包含HTTP前置处理,纯工作线程排队见worker_queue | | first_card | 第一张完整item成功进入服务端事件队列 | | first_text | 首次非空answer_delta、answer或summary成功入队;包括程序前置说明、补问或降级答复 | | first_model_text | 首次模型公开正文增量成功入队,区别于程序前置说明;非流式/同题QA路径可能为空 | | result_ready | 完整result成功入队 | | terminal_ready | done/error成功入队;断线等情况下可为空 | 这些是服务端指标,不是浏览器收到或渲染时间。被撤回的首段草稿仍计首次输出;不代表首段内容最终通过校验。前端显示延迟、网络和代理缓冲需要另行联调。`total_ms`是后台生命周期,可能晚于终止事件;超时/断线后的在途同步调用结束仍会记录。进程被强制终止则无法保证输出统计。 `metrics.spans`各项包含count、total_ms、max_ms、failed_count。total_ms是该类已完成区间之和;并发子调用和嵌套父阶段相互重叠,不能将全部项相加当作请求总耗时。failed_count仅指异常逃出计时区间,已被业务内部处理的失败需结合result_ready原有诊断;LangGraph正常补问中断不算失败。 | 项 | 范围 | | --- | --- | | session_load / session_result_load / history_save | 会话读取、最终状态读取、请求历史保存;图内部检查点写入未单列 | | prepare / analyze / search / basic / honors / plan / retrieve / recommend等 | 实际图节点运行,包括节点内子阶段;中断恢复可能多次计数 | | attachments | 附件下载、解析和图片识别 | | rerank / analysis / highlights | 初筛、全文分析、卡片短文案阶段墙钟时间 | | reduction / synthesis | 中间笔记每批整理、最终综合;按实际调用累加,重试计入 | | model_wait.阶段 | 等待共享模型并发名额;count包含获取超时 | | model_call.阶段 | 获取名额后到调用返回/抛错,count包含重试和失败;不等于模型服务端纯推理时间 | | executor_wait.阶段 | 本请求候选/证据块/初筛等线程池排队时间,按任务累加 | | retrieval_wait.retrieve / retrieval_call.retrieve | 等待共享检索名额、取得名额后的检索处理 | | embedding_wait.retrieve / embedding_call.retrieve | 本地向量锁等待及向量计算(可能含初始化) | | vector_search | 每条查询跨六库检索的耗时,多个查询可重叠 | | content_read | 每库完整资料分段读取调用,空集合可能为0毫秒 | | worker_queue / event_queue | Job接纳至工作线程启动;事件入队耗时(含慢消费造成的背压) | 在线请求的模型等待能反映后台会话分析、公司分类对共享名额的竞争;本日志不另行统计那些后台任务自身耗时。无模型调用的分支不制造model_call项。 ## 采集与分析 筛选`event=request_performance`,用thread_id聚合同一会话的多轮请求,用request_id与阶段/错误日志关联。先按闲聊、知识咨询、具体需求、公司确认恢复、附件场景分组,再分别统计首卡、首字、总耗时的中位数和P95;null样本单独计数,失败/降级/中断单独分组。不能把人工等待补问的多轮间隔算入单次请求耗时。 优先比较analysis、reduction、synthesis墙钟时间及对应model_wait/model_call;executor_wait高表示本请求任务排队,model_wait高表示共享模型名额竞争,event_queue高表示消费背压。先收集重启后代表性真实样本,再决定下一项提速。本次合成验证仅证明计时、隔离和协议兼容,不代表线上性能基线或提速效果。