AI 应用上线后怎么排查问题?日志与可观测性应该这样设计

AI 应用上线后怎么排查问题?日志与可观测性应该这样设计
上一篇文章讨论了 Memory。Memory 让 AI 应用可以在可控范围内延续上下文。但当一个 AI 应用真的上线后仅仅能记住上下文还不够。它还必须能被排查、被追踪、被复盘。因为线上问题一定会出现。模型可能回答异常。Prompt 可能被错误拼接。RAG 可能检索不到正确内容。Tool 可能调用失败。Workflow 可能卡在某个节点。Agent 可能重复执行无效步骤。Token 成本可能突然升高。用户输入可能触发边界情况。如果没有日志和可观测性开发者只能靠猜。而 AI 应用最怕的就是靠猜排查问题。所以从 Demo 走向工程化日志与可观测性是必须补上的一层能力。一、AI 应用的问题不只是代码报错传统后端系统排查问题通常关注接口是否报错。数据库是否异常。响应时间是否过长。服务器资源是否不足。异常栈在哪里。这些在 AI 应用里仍然重要。但 AI 应用的问题更多。例如模型没有报错但回答质量很差。接口返回 200但用户觉得结果不对。Tool 调用成功了但用了错误参数。RAG 检索返回了内容但不是用户真正需要的内容。Agent 执行完了但路径明显绕远了。Workflow 没有崩溃但某个节点输出不合理。Token 消耗没有报警但单次请求成本比预期高很多。这些问题不是普通异常栈能解释的。它们需要更细的链路记录。也需要专门面向 AI 应用的观测指标。二、为什么 print 日志不够很多 Demo 项目会这样写日志print(start workflow)print(call llm)print(result:,result)这在本地调试阶段还可以。但上线后远远不够。首先print 没有结构。你很难按用户、请求、模型、任务、错误类型去检索。其次print 很难串联链路。一次用户请求可能包含多次模型调用、多次 Tool 调用、多次检索和多个 Workflow 节点。如果没有统一 trace_id很难知道这些日志属于同一次请求。第三print 容易泄露敏感信息。开发阶段随手打印 Prompt、用户输入、接口参数线上可能就会把隐私或密钥打进日志。第四print 不适合统计。你很难从一堆文本中稳定统计模型耗时、Token 成本、失败率和工具调用次数。所以AI 应用需要结构化日志。不是多打几行 print。三、一次 AI 请求应该有 trace_idAI 应用的调用链通常比较长。例如一次问答请求可能是用户请求 ↓ 解析输入 ↓ 加载 Memory ↓ RAG 检索 ↓ 构造 Prompt ↓ 调用 LLM ↓ 判断是否调用 Tool ↓ 执行 Tool ↓ 再次调用 LLM ↓ 返回结果如果每一步日志没有关联排查问题会非常痛苦。所以每次请求都应该生成一个 trace_id。例如trace_id req_20260711_100001_xxxx后续所有日志都带上这个 trace_id{trace_id:req_20260711_100001_xxxx,event:llm_call_start,model:deepseek-chat,workflow:rag_workflow}这样排查问题时就能把一次请求下的所有事件串起来。trace_id 是可观测性的基础。没有 trace_id日志只是散落的碎片。四、请求日志应该记录什么请求日志是入口层日志。它回答的是谁在什么时候发起了什么类型的请求最终结果如何。请求日志可以记录trace_id请求链路 ID。 user_id用户 ID 或匿名 ID。 endpoint接口路径或入口名称。 method请求方法。 request_type请求类型。 status成功或失败。 latency_ms总耗时。 created_at请求时间。 error_code错误码。例如{trace_id:req_001,event:request_finished,endpoint:/chat,status:success,latency_ms:3420}请求日志不一定要记录完整用户输入。很多时候只需要记录输入长度、类型、是否命中某类规则。如果必须记录输入也要做脱敏和权限控制。五、模型调用日志应该记录什么模型调用是 AI 应用最核心、也最容易出问题的地方。模型调用日志应该至少记录trace_id请求链路 ID。 provider模型供应商。 model模型名称。 prompt_versionPrompt 版本。 input_tokens输入 token。 output_tokens输出 token。 total_tokens总 token。 latency_ms模型耗时。 status成功或失败。 error_type错误类型。 retry_count重试次数。例如{trace_id:req_001,event:llm_call_finished,provider:openai,model:gpt-4.1,prompt_version:qa_v3,input_tokens:1200,output_tokens:360,latency_ms:2100,status:success}这里有一个重点不要默认把完整 Prompt 和完整 Response 全部写进普通日志。因为里面可能包含用户隐私、业务数据或敏感上下文。更合理的做法是默认记录结构化元数据。必要时记录脱敏后的摘要。调试环境可以打开详细日志。生产环境详细日志需要权限和保留周期。六、Token 成本必须可观测AI 应用和传统后端最大的不同之一是模型调用有直接成本。一次请求消耗多少 token可能直接影响账单。如果没有 Token 统计很难发现成本异常。需要观察的指标包括单次请求平均 token。单个用户 token 消耗。单个 Workflow token 消耗。单个模型 token 消耗。每日总 token。输入 token 和输出 token 比例。重试导致的额外 token。例如某个 Workflow 改版后平均输入 token 从 1000 增加到 8000。接口仍然正常。用户也可能没有马上反馈。但成本已经明显异常。所以 Token 不是附属信息。它应该是 AI 应用的核心指标。七、Tool 调用日志应该记录什么Tool 调用让 Agent 具备行动能力。但 Tool 也是风险点。每一次 Tool 调用都应该可追踪。Tool 调用日志可以记录trace_id请求链路 ID。 tool_name工具名称。 tool_version工具版本。 permission_level权限级别。 arguments_schema参数结构。 latency_ms执行耗时。 status成功或失败。 error_type错误类型。 result_size结果大小。例如{trace_id:req_001,event:tool_call_finished,tool_name:search_docs,permission_level:read_only,latency_ms:320,status:success}注意不要随意记录完整参数。比如文件路径、用户输入、业务 ID、接口返回都可能包含敏感信息。更稳妥的做法是记录参数结构和脱敏后的关键字段。Tool 日志的目标不是把所有内容打出来。而是让开发者能知道工具有没有被调用、调用是否成功、耗时多少、失败在哪里。八、RAG 检索也需要日志RAG 系统里模型回答不好问题不一定在模型。很可能是检索阶段出了问题。例如没有检索到内容。检索到了错误文档。top_k 设置不合理。相似度分数太低。文档切片质量差。过滤条件写错。所以 RAG 检索也需要日志。可以记录trace_id请求链路 ID。 query_length查询长度。 collection知识库名称。 top_k召回数量。 hit_count命中数量。 score_range相似度范围。 latency_ms检索耗时。 rerank_used是否使用重排。例如{trace_id:req_001,event:retrieval_finished,collection:product_docs,top_k:5,hit_count:5,latency_ms:180}如果需要记录命中文档也建议记录文档 ID、chunk ID 和分数。不要默认记录完整原文内容。九、Workflow 节点状态要能追踪复杂 AI 应用通常不是一次模型调用。它可能包含多个 Workflow 节点。例如load_memory retrieve_docs build_prompt call_llm parse_answer call_tool finalize_response每个节点都应该有开始、结束、失败日志。例如{trace_id:req_001,event:workflow_node_finished,workflow:rag_workflow,node:retrieve_docs,status:success,latency_ms:210}这样当用户说结果慢时可以看到慢在检索、模型、Tool还是最终处理。当结果错误时也可以看是哪个节点开始偏离。Workflow 可观测性的关键是把黑盒流程拆成可追踪节点。十、Agent step 也要能复盘Agent 的问题往往更难排查。因为 Agent 不是固定流程。它可能根据上下文动态决定下一步。所以 Agent step 需要记录。可以记录trace_id请求链路 ID。 agent_nameAgent 名称。 step_index步骤序号。 thought_type步骤类型。 selected_tool选择的工具。 decision_status决策状态。 latency_ms步骤耗时。例如{trace_id:req_001,event:agent_step,agent_name:research_agent,step_index:3,selected_tool:search_docs,decision_status:tool_call}这里要注意不一定要记录完整推理过程。很多场景只需要记录可审计的决策摘要。例如选择了哪个 Tool、为什么进入某个分支、当前步骤是否成功。这样既能复盘又能降低敏感信息和冗余日志风险。十一、错误日志要分层AI 应用错误不能只分成成功和失败。更合理的做法是分层。例如config_error配置错误。 llm_error模型调用错误。 retrieval_error检索错误。 tool_error工具调用错误。 workflow_error流程错误。 validation_error参数校验错误。 permission_error权限错误。 rate_limit_error限流错误。 timeout_error超时错误。这样做的好处是报警更准确。统计更清楚。排查路径更短。例如都是失败但模型限流和 Tool 参数错误完全是两类问题。前者可能要调整重试、降级或额度。后者可能要修 schema、Prompt 或参数校验。错误日志越清晰线上恢复越快。十二、日志必须脱敏日志不是越详细越好。尤其是 AI 应用输入输出里很容易包含敏感信息。不能直接记录的内容包括API Key。Token。密码。验证码。身份证号。手机号。邮箱。支付信息。用户隐私内容。原始大文件全文。所以需要 Redactor也就是脱敏模块。例如classRedactor:defredact(self,text:str)-str:textself.mask_api_keys(text)textself.mask_phone_numbers(text)textself.mask_emails(text)returntext在写日志之前先脱敏。在保存 Prompt 或 Response 之前也要脱敏。日志系统不能成为隐私泄露的入口。十三、AI Scaffold 里的可观测性模块在 AI Scaffold 中可以把可观测性作为独立模块。项目结构可以这样设计app/ ├── observability/ │ ├── __init__.py │ ├── logger.py │ ├── tracing.py │ ├── metrics.py │ ├── events.py │ ├── redactor.py │ └── exporters.py ├── llm/ │ └── client.py ├── tools/ │ └── registry.py ├── workflows/ │ └── rag_workflow.py ├── agents/ │ └── assistant_agent.py └── config/ └── settings.py其中logger.py负责结构化日志。tracing.py负责 trace_id 和链路追踪。metrics.py负责统计指标。events.py定义 AI 应用里的事件类型。redactor.py负责敏感信息脱敏。exporters.py负责对接外部日志平台或监控系统。LLM、Tool、Workflow、Agent 都不应该各写一套日志逻辑。它们应该统一发事件。由 observability 模块负责记录、脱敏和导出。十四、总结AI 应用上线后排查问题不能只靠 print。因为 AI 应用的问题可能来自模型、Prompt、RAG、Tool、Workflow、Agent、Memory、配置、权限和用户输入。一个合理的日志与可观测性设计至少应该做到每次请求有 trace_id。请求日志结构化。模型调用记录 provider、model、耗时和 token。Token 成本可统计。Tool 调用可追踪。RAG 检索可复盘。Workflow 节点状态可观察。Agent step 可以审计。错误类型要分层。日志写入前必须脱敏。生产环境不要默认记录完整 Prompt 和 Response。可观测性模块要统一而不是散落在各个业务模块里。对于 AI Scaffold 来说可观测性不是上线后的附加功能。它应该从项目结构阶段就被考虑进去。因为 AI 应用越复杂越需要知道每一次结果是怎么来的。能跑只是第一步。能解释、能排查、能复盘才是工程化系统真正可维护的开始。下一篇文章可以继续讨论安全治理当 Agent 能调用 Tool、读取 Memory、访问外部系统时如何设计权限边界、审计机制和 Prompt Injection 防护。

最新新闻

日新闻

周新闻

月新闻