
本文定位AI 应用可观测性 / Trace / 审计日志 / Java 后端示例环境Spring Boot 3.3、Java 21、OpenTelemetry、Prometheus、PostgreSQL。实际部署时要结合数据保留、隐私和合规要求调整字段。摘要传统接口出错时我们通常可以通过请求参数、SQL、堆栈和响应快速定位。但大模型应用多了一层不确定性同一个问题可能因为模型版本、Prompt、检索结果、工具返回、温度和上下文长度不同而产生不同回答。只记录“用户问了什么、模型答了什么”无法解释系统为什么会错。本文设计一套面向 AI 应用的可观测方案把一次请求拆成路由、检索、重排、模型调用、工具调用、输出校验和用户反馈多个 Span并讨论哪些数据应该记录、哪些数据必须脱敏、如何利用日志复盘错误、如何把质量指标接入灰度和回归流程。一、可观测性要回答四个问题一个完整的 AI Trace 至少要回答当时看到了什么用户问题、历史上下文、召回 Chunk、工具返回和系统配置。为什么这样处理命中的路由、Prompt 版本、工具选择和模型参数。哪里出了问题超时、权限拒绝、检索为空、引用校验失败还是模型生成错误。怎样避免再次发生评测样本、修复版本、回归结果和上线状态。RequestTracePrompt/ContextRetrieval SpansModel SpanTool SpansValidationFeedback/Evaluation可观测性不是把所有原文都写进日志。真正有价值的是一组可关联、可查询、可脱敏的数据以及明确的保留策略。二、Trace 结构设计建议使用traceId关联一次用户请求spanId标识一个阶段requestId标识业务请求tenantId和userId用于权限范围内检索。每个 Span 都带开始时间、结束时间、状态、错误类别和版本信息。publicrecordAiTraceContext(StringtraceId,StringrequestId,StringtenantId,StringuserId,StringmodelVersion,StringpromptVersion){}publicTTobserve(Stringname,AiTraceContextcontext,SupplierTaction){longstartSystem.nanoTime();try{Tresultaction.get();traceStore.finish(context.traceId(),name,elapsed(start),OK,null);returnresult;}catch(RuntimeExceptionex){traceStore.finish(context.traceId(),name,elapsed(start),ERROR,classify(ex));throwex;}}推荐的 Span 名称保持稳定例如ai.route、ai.retrieve、ai.rerank、ai.llm、ai.tool、ai.validate。不要把用户输入直接拼进 Span 名称否则会造成高基数指标和日志查询困难。三、一次 RAG 请求应记录什么阶段建议记录不建议直接记录路由应用、工作流、用户意图、版本完整身份证号检索查询哈希、Chunk ID、排名、分数未脱敏全文模型模型、参数、输入输出 TokenAPI Key、完整隐私内容工具工具名、参数哈希、权限结果、耗时密码、密钥、完整数据库结果校验JSON 是否通过、引用是否有效未经脱敏的原始异常反馈点赞、点踩、人工修正无授权的个人画像输入原文是否保存取决于业务和合规要求。可以采用分层保存主日志只存哈希、长度和脱敏摘要原始内容放到加密存储短期保留访问需要审批。日志本身不能成为数据泄露的第二条路径。四、Prompt 和上下文版本化模型回答不可复现的一个常见原因是 Prompt 在代码里散落着修改后没有版本号。建议把系统 Prompt、上下文模板、工具描述和输出 Schema 作为可发布配置每次请求记录版本。{promptVersion:rag-answer-v12,contextPolicyVersion:ctx-policy-v4,toolCatalogVersion:tools-2026-08-01,model:model-alias-prod,temperature:0.1,maxTokens:1200}不要只记录“模型名称”。供应商同名模型可能发生后端更新应用应保存模型别名、请求时间、区域和必要的响应元数据。对高风险业务可以维护固定版本或在发布记录中保留供应商变更信息。五、检索结果如何可追溯AI Trace 不能只写“召回了 5 条文档”否则无法定位证据问题。每个候选至少记录 Chunk ID、文档 ID、版本、页码、检索器类型、原始排名、融合分数、权限过滤结果和最终是否进入 Prompt。CREATETABLEai_retrieval_event(id bigserialPRIMARYKEY,trace_idvarchar(128)NOTNULL,tenant_idvarchar(64)NOTNULL,query_hashvarchar(64)NOTNULL,chunk_idbigintNOTNULL,retrievervarchar(32)NOTNULL,original_rankintegerNOTNULL,scorenumeric(12,8),permittedbooleanNOTNULL,selectedbooleanNOTNULL,created_at timestamptzNOTNULLDEFAULTnow());查询时要先做租户和权限过滤再记录结果。不能为了“方便排查”把已经被判定为越权的文档原文写入普通日志。六、工具调用和模型调用的差异模型调用关注 Token、延迟、重试、供应商错误和输出格式工具调用还要关注权限、幂等、副作用和业务结果。二者应使用不同的错误分类MODEL_TIMEOUT不等于TOOL_ACCESS_DENIED前者可能重试后者通常不能重试。publicrecordLlmMetrics(Stringprovider,Stringmodel,intinputTokens,intoutputTokens,longlatencyMs,StringfinishReason){}publicrecordToolMetrics(StringtoolName,StringpermissionDecision,intattempt,longlatencyMs,StringbusinessStatus){}指标名称要保持稳定标签数量要受控。不要把tenantId、用户问题或工具参数作为 Prometheus 高基数标签可以放在日志或 Trace 属性中。七、质量指标和运营指标可观测不仅是技术指标还要覆盖结果质量成功率、P50/P95/P99 延迟。输入 Token、输出 Token、缓存命中率和单请求成本。检索 Recall、引用支持率、拒答准确率。工具调用成功率、重试率、人工转接率。用户点赞率、修正率、重复提问率。不同模型、Prompt 和知识库版本的质量差异。建议把质量指标按版本和场景分组不要用所有请求的一个平均数掩盖高风险场景的问题。故障诊断、财务制度和普通 FAQ 应分别设定目标。八、从一个错误回答复盘根因假设用户反馈“答案很自信但错了”排查顺序应该是根据traceId找到请求和租户上下文。检查实际使用的 Prompt、模型、工具目录和知识库版本。查看召回证据是否包含正确文档权限过滤是否正确。检查上下文拼装是否截断了关键条件。查看模型是否出现无依据补全引用校验是否通过。把问题和证据加入回归评测集。修复后在旧版本和新版本上对比确认没有引入副作用。如果日志只保存最终回答上述过程几乎无法完成。好的可观测性让“模型玄学”变成可分析的证据链。九、隐私与保留策略日志方案需要明确记录哪些字段、保留多久、谁可以查、导出是否脱敏、删除请求如何生效。租户管理员可以查看自己租户的审计信息但不能通过 Trace 查询其他租户内容。敏感字段可以采用掩码、哈希、分段加密和字段级访问控制。用户删除数据后向量库、缓存、日志、评测集和备份中的关联数据也要有清理策略。不要因为 AI 调试方便就永久保存所有输入输出。十、告警和自动化动作告警不应该只设“错误率超过 5%”。可以组合条件模型超时上升且备用模型调用增加、引用准确率下降且某个知识库版本刚发布、某个租户越权尝试明显增加、工具重试率达到阈值等。自动化动作应保守停止灰度、切换备用模型、冻结高风险工具或降低并发不要因为单个异常就自动删除数据或回滚全部知识库。每个自动动作都要有审计记录和人工恢复路径。十一、总结AI 应用的可观测性不是“多打印几行日志”而是把请求、上下文、检索、工具、模型、校验和反馈串成一条能复盘的证据链。记录版本才能复现记录权限才能追责记录检索才能区分数据问题和模型问题记录成本才能真正运营。建议先从一个核心用例做完整 Trace再逐步推广到其他应用。一次请求能够回答“它看到了什么、用了什么版本、为什么调用、哪里失败”系统才真正具备生产治理能力。读者讨论你现在的 AI 应用日志里是否能看到模型实际使用的 Prompt、召回文档和工具版本如果看不到建议先从 Trace ID 和版本字段开始补齐。