全链路可观测体系建设
可观测性全链路追踪性能基准Token 成本架构
落地从编排决策、RAG 检索、模型调用到工具调用的全链路追踪体系,统一埋点生成追踪日志,实现运行状态可视化,问题排查效率显著提升
项目介绍
这是一个面向企业知识管理的AI智能体平台,支持多格式文档上传与解析、智能分块与向量化、知识库构建、多轮对话问答、ReActAgent 智能编排、RAG检索增强生成等全链路业务闭环。
技术栈:SpringBoot、SpringAI-Alibaba、MCP、Milvus、Kafka、MinIO、Redis、Redisson、RAG、Tavily等。
全链路可观测体系建设
落地从编排决策、RAG 检索、模型调用到工具调用的全链路追踪体系,统一埋点生成追踪日志,实现运行状态可视化,问题排查效率显著提升。
一、架构全景
全链路追踪体系覆盖对话请求的完整生命周期,在关键节点统一埋点,形成从"用户提问"到"回答输出"的完整可观测链路:
用户请求
│
├─ [编排决策层] ChatPreparationOrchestrator
│ ├─ MEMORY 会话记忆装载
│ ├─ REWRITE 问题改写
│ └─ ROUTE 路由判定
│
├─ [执行引擎层] 各 Executor
│ ├─ RAG_RETRIEVE 双通道混合检索
│ ├─ EVIDENCE_BUDGET 证据评估与预算控制
│ ├─ ANSWER_GENERATE 回答生成
│ ├─ REACT_AGENT Agent 自主决策
│ └─ GRAPH_QUERY 结构图查询
│
├─ [模型调用层] ObservedChatModelService
│ └─ 每次 LLM 调用:Token 用量、成本、耗时、provider
│
├─ [工具调用层] TavilySearchTool
│ └─ 每次工具调用:输入、输出、耗时、状态
│
└─ [收尾归档层] BusinessChatService
├─ RECOMMENDATION 推荐问题生成
└─ FINALIZE 归档汇总
所有追踪数据通过三条通道持久化:
- 阶段追踪 →
super_agent_chat_exchange_trace_stage表 - 检索观测 →
super_agent_chat_retrieval_result+super_agent_chat_channel_execution表 - 调试快照 →
super_agent_chat_exchange表的debug_traceJSON 列
二、核心组件设计
2.1 ConversationTraceRecorder —— 追踪中枢
ConversationTraceRecorder(ConversationTraceRecorder.java)是整个追踪体系的唯一门面,每个 TaskInfo 持有一个实例,随对话生命周期贯穿所有环节。
public class ConversationTraceRecorder {
private final ConversationTraceStageStore traceStageStore; // 阶段持久化
private final RetrievalObserveStore retrievalObserveStore; // 检索观测持久化
private final String conversationId;
private final long exchangeId;
private final String traceId; // UUID,串联整条链路
private final List<ChatModelUsageTrace> modelUsageTraces; // 线程安全的模型调用收集
private final ChatLimitStats limitStats; // 限流统计
}
核心 API:
| 方法 | 用途 |
|---|---|
startStage(code, mode, summary, snapshot) | 开启一个追踪阶段,写入 RUNNING 状态,返回 StageHandle |
completeStage(handle, summary, snapshot) | 标记阶段完成,自动计算耗时 = now - startTimeMs |
failStage(handle, summary, error, snapshot) | 标记阶段失败,自动提取异常堆栈注入快照 |
addModelUsageTrace(trace) | 追加模型调用记录(线程安全) |
snapshotModelUsageTraces() | 获取当前所有模型调用记录的快照 |
recordRetrievalResults(results) | 批量持久化检索结果观测 |
recordChannelExecutions(executions) | 批量持久化通道执行观测 |
StageHandle 是一个 Java Record,持有 stageId、startTimeMs、stageCode。耗时在 completeStage / failStage 时自动计算,无需手动传入。
2.2 追踪阶段定义
ConversationTraceStageCode 枚举定义了全部 11 个追踪阶段,按执行顺序排列:
| 阶段 | 中文名 | 排序 | 触发位置 |
|---|---|---|---|
MEMORY | 会话记忆 | 10 | ChatPreparationOrchestrator |
INTENT | 意图分析 | 20 | 预留 |
REWRITE | 问题改写 | 30 | ChatPreparationOrchestrator |
ROUTE | 路由判定 | 40 | ChatPreparationOrchestrator |
GRAPH_QUERY | 结构图查询 | 45 | GraphOnlyExecutor / GraphThenEvidenceExecutor |
RAG_RETRIEVE | RAG 检索 | 50 | RagChatExecutor |
EVIDENCE_BUDGET | 证据评估与预算控制 | 60 | RagChatExecutor |
ANSWER_GENERATE | 回答生成 | 70 | RagChatExecutor |
REACT_AGENT | ReAct Agent | 75 | ReactAgentExecutor |
RECOMMENDATION | 推荐问题 | 80 | BusinessChatService.finishSuccessfully() |
FINALIZE | 收尾归档 | 90 | BusinessChatService 三种结束路径 |
每个阶段有四种状态(ConversationTraceStageState):RUNNING → COMPLETED / FAILED / SKIPPED。
2.3 阶段持久化
ConversationTraceStageStore 接口定义阶段存储契约,由 MybatisConversationTraceStageStore 实现,写入 super_agent_chat_exchange_trace_stage 表:
| 字段 | 说明 |
|---|---|
id | UID 生成器主键 |
dialogue_code | 会话 ID |
exchange_id | 交换轮次 ID |
trace_id | 链路追踪 ID(UUID) |
stage_code | 阶段枚举代码 |
stage_name | 阶段中文名 |
stage_order | 排序号 |
execution_mode | 当前执行模式 |
stage_state | RUNNING / COMPLETED / FAILED / SKIPPED |
start_time | 阶段开始时间 |
end_time | 阶段结束时间 |
duration_ms | 阶段耗时(毫秒) |
summary_text | 阶段摘要文本 |
error_message | 错误信息 |
snapshot_json | 阶段快照(JSON) |
每个阶段独立事务写入,startStage 执行 INSERT,completeStage / failStage 执行 UPDATE,非阻塞。
三、分层埋点详解
3.1 编排决策层 —— ChatPreparationOrchestrator
编排器是埋点最密集的环节,覆盖 MEMORY、REWRITE、ROUTE 三个阶段,全部以 try/catch 包裹确保异常时记录失败状态。
MEMORY 阶段快照(ChatPreparationOrchestrator.java:91-114):
traceRecorder.completeStage(memoryStage, "会话记忆装载完成。", Map.of(
"compressionApplied", memoryContext.isCompressionApplied(),
"coveredExchangeId", memoryContext.getCoveredExchangeId(),
"coveredExchangeCount", memoryContext.getCoveredExchangeCount(),
"compressionCount", memoryContext.getCompressionCount(),
"longTermSummary", memoryContext.getLongTermSummary(),
"recentTranscript", memoryContext.getRecentTranscript()
));
REWRITE 阶段快照:记录改写前后的完整对比——originalQuestion、historyContext、rewriteQuestion、subQuestions、rawModelOutput,便于排查改写是否引入偏差。
ROUTE 阶段快照:根据聊天模式不同,记录不同的路由信息:
OPEN_CHAT:记录 chatMode、executionMode、时间感知标记AUTO_DOCUMENT:记录置信度、候选文档数、首选文档RETRIEVAL:记录执行模式、章节线索、导航摘要
3.2 RAG 检索层 —— RagChatExecutor + RagRetrievalEngine
RagChatExecutor 负责三个阶段:RAG_RETRIEVE → EVIDENCE_BUDGET → ANSWER_GENERATE。
RAG_RETRIEVE 阶段(RagChatExecutor.java:58-113):在 Mono.fromCallable 中异步执行检索,成功时快照包含丰富的检索过程数据:
retrievalQuestion, usedChannels, retrievalNotes,
referenceCount, subQuestionCount,
subQuestions: [{ index, question, referenceCount, documentCount,
fusedCandidateCount, parentCandidateCount, rerankedCandidateCount,
channelTraces: [{ channelName, recalledCount, acceptedCount }],
references: [{ referenceId, documentName, sectionPath, channel }]
}]
这层埋点可以看到每个子问题走了哪些通道、各通道召回/接受多少、融合和重排序后剩多少,形成完整的检索漏斗。
EVIDENCE_BUDGET 阶段:快照包含预算分配 + 完整 prompt 文本:
totalBudget, perSubQuestionBudget,
renderedReferenceCount, omittedReferenceCount,
renderedReferenceDetails, omittedReferenceDetails,
systemPrompt, userPrompt
有了完整 prompt 文本,出问题时可以直接复现 LLM 的输入上下文。
检索观测独立存储:RagRetrievalEngine 在每个子问题检索完成后,调用 traceRecorder.recordRetrievalResults() 和 recordChannelExecutions() 批量持久化到独立表,支持按文档、按通道维度的精细化分析:
| 视图 | 表 | 粒度 |
|---|---|---|
RetrievalResultView | super_agent_chat_retrieval_result | 每个文档片段的评分、门控、选中状态 |
ChannelExecutionView | super_agent_chat_channel_execution | 每个通道的召回数、接受数、平均分 |
3.3 模型调用层 —— ObservedChatModelService
ObservedChatModelService(ObservedChatModelService.java)是对 Spring AI ChatModel 的包装层,在每次 LLM 调用前后自动收集用量数据,对调用方透明。
支持两种调用模式:
同步调用 callText():
public String callText(String stageName, String systemPrompt, String userPrompt,
ConversationTraceRecorder traceRecorder) {
long startTime = System.currentTimeMillis();
String provider = resolveProvider(); // deepseek / openai-compatible / ollama
String model = resolveModel();
ChatResponse response = chatModel.call(buildPrompt(...));
// 从 ChatResponseMetadata 提取真实 Token 用量
ChatModelUsageTrace trace = buildUsageTrace(stageName, provider, model,
response.getMetadata(), System.currentTimeMillis() - startTime, "COMPLETED", ...);
traceRecorder.addModelUsageTrace(trace);
}
流式调用 streamText():
return chatModel.stream(buildPrompt(...))
.doOnNext(outputBuilder::append) // 累积输出
.doOnComplete(() -> {
// 流结束时统一记录用量
appendUsage(traceRecorder, buildUsageTrace(..., "COMPLETED", ...));
})
.doOnError(error -> {
// 失败时基于估算记录
appendUsage(traceRecorder, ChatModelUsageTrace.builder()
.status("FAILED").estimatedCost(...).build());
});
每次模型调用收集的追踪数据(ChatModelUsageTrace):
| 字段 | 来源 | 说明 |
|---|---|---|
stageName | 调用方传入 | 如 "rewrite"、"rag_answer"、"summary" |
provider | chatModel.getClass().getName() 解析 | deepseek / openai-compatible / ollama |
model | ChatOptions.getModel() | 具体模型名称 |
promptTokens | Usage.getPromptTokens() | API 返回的真实值 |
completionTokens | Usage.getCompletionTokens() | API 返回的真实值 |
totalTokens | Usage.getTotalTokens() | API 返回的真实值 |
estimatedCost | 模型费率计算 | qwen-plus: $0.004/0.012, deepseek: $0.002/0.008 |
durationMs | System.currentTimeMillis() - startTime | 调用耗时 |
status | COMPLETED / FAILED | 调用状态 |
Token 估算兜底策略:当 API 未返回 Usage 时,按 ceil(content.length() / 4) 估算(1 Token ≈ 4 中文字符)。
Provider 自动检测:
String className = chatModel.getClass().getName().toLowerCase();
if (className.contains("deepseek")) return "deepseek";
if (className.contains("openai")) return "openai-compatible";
if (className.contains("ollama")) return "ollama";
3.4 工具调用层 —— TavilySearchTool
工具调用追踪不走 ConversationTraceRecorder,而是通过 ChatDebugTrace 中的 ChatToolTrace 列表记录。
TavilySearchTool(TavilySearchTool.java)在工具执行前后:
// 工具调用前注册
ChatToolTrace trace = ChatToolTrace.builder()
.toolName("tavily_search")
.status("RUNNING")
.inputSummary(clipText(input, 200))
.topic(extractTopic(input))
.build();
debugTrace.getToolTraces().add(trace);
// 工具调用完成后更新
trace.setStatus("COMPLETED");
trace.setReferenceCount(results.size());
trace.setDurationMs(durationMs);
trace.setOutputSummary(summary);
ChatToolTrace 字段:
| 字段 | 说明 |
|---|---|
toolName | 工具名称 |
status | RUNNING / COMPLETED / FAILED |
inputSummary | 输入摘要(截断 200 字符) |
effectiveInput | 实际送入工具的输入 |
outputSummary | 输出摘要 |
errorMessage | 错误信息 |
topic | 搜索主题词 |
referenceCount | 返回结果数 |
durationMs | 执行耗时 |
四、执行器埋点全景
五个执行器的追踪阶段对照:
| 执行器 | 追踪阶段 | 核心快照内容 |
|---|---|---|
RagChatExecutor | RAG_RETRIEVE + EVIDENCE_BUDGET + ANSWER_GENERATE | 检索漏斗、预算分配、完整 prompt、首字延迟 |
ReactAgentExecutor | REACT_AGENT | 工具名称列表、使用工具数 |
GraphOnlyExecutor | GRAPH_QUERY | 目标章节、父子章节、前后兄弟节点、答案文本 |
GraphThenEvidenceExecutor | GRAPH_QUERY | 目标章节、编号项索引、匹配项数、答案文本 |
ClarificationExecutor | ROUTE(完成阶段) | 澄清回复、澄清原因、文档选项列表 |
ANSWER_GENERATE 阶段特别记录了 firstResponseTimeMs(首字延迟),这是衡量用户体验的关键指标——从请求到用户看到第一个字的时间。
五、生命周期收尾
BusinessChatService 在对话的三种结束路径中统一完成收尾追踪:
finishSuccessfully() → FINALIZE + RECOMMENDATION + refreshDebugTraceRuntimeStats()
finishWithFailure() → FINALIZE + refreshDebugTraceRuntimeStats()
stopTask() → FINALIZE + refreshDebugTraceRuntimeStats()
FINALIZE 阶段快照:
Map.of(
"finalStatus", "SUCCESS" / "FAILURE" / "STOPPED",
"referenceCount", taskInfo.references().size(),
"answerLength", taskInfo.answerBuffer().length(),
"recommendationCount", ...,
"errorMessage", ...
)
refreshDebugTraceRuntimeStats() 在收尾时执行:
- 从
traceRecorder.snapshotModelUsageTraces()获取本轮所有模型调用记录 - 汇总到
ChatLimitStats(modelCallsUsed、toolCallsUsed、totalCost 等) - 写入
ChatDebugTrace对象 ChatDebugTrace作为 JSON 最终持久化到super_agent_chat_exchange.debug_trace列
这意味着每轮对话最终都有一份完整的 JSON 快照,包含全部阶段的决策过程、模型调用详情、工具调用记录,可用于离线分析和问题复现。
六、可视化:调试追踪数据模型
ChatDebugTrace 是每轮对话的完整调试快照,在前端管理后台以结构化面板展示:
public class ChatDebugTrace {
// 编排决策
String executionMode, chatMode, originalQuestion, rewriteQuestion,
rewriteSubQuestions, retrievalQuestion, agentQuestion;
DocumentNavigationDecision navigationDecision;
// 记忆状态
String historySummary, longTermSummary, recentHistoryTranscript,
answerRecentTranscript, answerHistoryContext;
boolean historyCompressionApplied;
// 时间感知
String currentDateText;
boolean requiresFreshSearch, requiresCurrentDateAnchoring;
// 检索过程
List<SubQuestionEvidence> retrievalSubQuestions;
String retrievalNotes, usedChannels;
// Prompt 完整文本
String ragSystemPrompt, ragUserPrompt, noEvidenceReply;
// 工具调用
List<ChatToolTrace> toolTraces;
// 模型用量
List<ChatModelUsageTrace> modelUsageTraces;
ChatLimitStats limitStats;
}
前端通过 AdminObservabilityDetailView.vue 以时间线 UI 展示所有阶段,每个阶段可展开查看详细快照。observabilityHelpers.js(1136 行)负责将后端数据转换为前端可渲染的 6 个诊断面板:
| 面板 | 内容 |
|---|---|
| 结果 | 最终回答、引用、推荐问题 |
| 执行 | 执行模式、阶段耗时、工具调用 |
| 规划 | 改写问题、路由决策、文档选择 |
| 请求 | 原始问题、聊天模式、记忆状态 |
| 生成 | 完整 system prompt / user prompt |
| 用量 | 按阶段分组的模型调用 Token 与成本 |
七、性能基准子系统
StageBenchmarkService(StageBenchmarkService.java)独立于单次请求追踪,按 (stageCode, executionMode) 维度聚合历史耗时数据,提供 P50/P90/P99 延迟分布。
7.1 数据积累策略
private static final int MAX_RECENT_SAMPLES = 200; // 每维度保留最近 200 个样本
public void recordDuration(String stageCode, String executionMode, long durationMs) {
// 1. 查询现有基准记录
// 2. 追加新样本到 recentDurations JSON 数组
// 3. 超过 200 个则丢弃最旧的
// 4. 排序后计算 P50/P90/P99/avg/max/min
// 5. 更新数据库
}
7.2 百分位计算
List<Long> sorted = new ArrayList<>(durations);
Collections.sort(sorted);
int size = sorted.size();
P50 = sorted.get((int) (size * 0.5));
P90 = sorted.get(Math.min((int) (size * 0.9), size - 1));
P99 = sorted.get(Math.min((int) (size * 0.99), size - 1));
7.3 数据库实体
super_agent_chat_stage_benchmark 表:
| 字段 | 说明 |
|---|---|
stage_code + execution_mode | 联合维度 |
recent_durations | JSON 数组,存储最近 200 个耗时样本 |
sample_count | 累计样本数 |
avg/p50/p90/p99/max/min_duration_ms | 预计算的统计值 |
last_update_time | 最后更新时间 |
7.4 API 暴露
POST /api/chat/stage/benchmarks → StageBenchmarkView 列表,前端以表格形式展示各阶段在各执行模式下的延迟分布:
Stage: RAG_RETRIEVE Mode: RETRIEVAL
P50: 320ms P90: 680ms P99: 1200ms Avg: 380ms Samples: 156
八、追踪 API 接口汇总
| 接口 | 功能 | 返回内容 |
|---|---|---|
POST /api/chat/exchange/detail | 轮次详情 | stageTraces(全部阶段视图) |
POST /api/chat/exchange/retrieval/results | 检索结果观测 | 每个文档片段的评分、门控状态 |
POST /api/chat/exchange/channel/executions | 通道执行观测 | 每个通道的召回/接受统计 |
POST /api/chat/stage/benchmarks | 性能基准 | P50/P90/P99 延迟分布 |
九、数据流向总览
TaskInfo 创建
│
├─ traceId = UUID.randomUUID()
├─ ConversationTraceRecorder 实例化
│
├─ ChatPreparationOrchestrator.prepare()
│ ├─ startStage(MEMORY) → completeStage(MEMORY)
│ ├─ startStage(REWRITE) → completeStage(REWRITE)
│ └─ startStage(ROUTE) → completeStage(ROUTE)
│
├─ Executor.execute()
│ ├─ RagChatExecutor:
│ │ ├─ startStage(RAG_RETRIEVE) → completeStage(RAG_RETRIEVE)
│ │ │ └─ recordRetrievalResults() + recordChannelExecutions()
│ │ ├─ startStage(EVIDENCE_BUDGET) → completeStage(EVIDENCE_BUDGET)
│ │ └─ startStage(ANSWER_GENERATE) → completeStage(ANSWER_GENERATE)
│ │ └─ streamText() → addModelUsageTrace()
│ ├─ ReactAgentExecutor:
│ │ └─ startStage(REACT_AGENT) → completeStage(REACT_AGENT)
│ │ └─ TavilySearchTool → registerToolTrace() → completeToolTrace()
│ └─ GraphOnlyExecutor / GraphThenEvidenceExecutor:
│ └─ startStage(GRAPH_QUERY) → completeStage(GRAPH_QUERY)
│
└─ BusinessChatService 收尾
├─ startStage(RECOMMENDATION) → completeStage(RECOMMENDATION)
├─ startStage(FINALIZE) → completeStage(FINALIZE)
└─ refreshDebugTraceRuntimeStats()
└─ snapshotModelUsageTraces() → ChatDebugTrace JSON → exchange.debug_trace
所有追踪数据通过 traceId(UUID)串联整条链路,前端点击任意轮次即可看到完整的阶段时间线。
十、配置与数据库
10.1 相关数据库表
| 表名 | 用途 |
|---|---|
super_agent_chat_exchange_trace_stage | 阶段追踪记录(每阶段一行) |
super_agent_chat_retrieval_result | 检索结果观测(每文档片段一行) |
super_agent_chat_channel_execution | 通道执行观测(每子问题-通道一行) |
super_agent_chat_stage_benchmark | 性能基准(每 stageCode+mode 一行) |
super_agent_chat_exchange.debug_trace | 完整调试快照(JSON 列) |
10.2 追踪开关
追踪系统无需显式开关——所有埋点代码在调用前检查 traceRecorder == null,为 null 时优雅跳过。traceRecorder 仅在 BusinessChatService.createTaskInfo() 中创建,测试或简化场景不创建即可关闭全链路追踪。
十一、完整文件清单
核心追踪组件
| 文件 | 职责 |
|---|---|
chatagent/service/ConversationTraceRecorder.java | 追踪门面:阶段启停、模型用量收集、检索观测委托 |
chatagent/service/ConversationTraceStageStore.java | 阶段持久化接口 |
chatagent/service/MybatisConversationTraceStageStore.java | 阶段持久化 MyBatis 实现 |
chatagent/model/trace/ConversationTraceStageCode.java | 11 个阶段枚举定义 |
chatagent/model/trace/ConversationTraceStageState.java | 阶段状态枚举(RUNNING/COMPLETED/FAILED/SKIPPED) |
chatagent/model/trace/ConversationTraceStageView.java | 阶段视图 DTO |
模型调用观测
| 文件 | 职责 |
|---|---|
chatagent/service/ObservedChatModelService.java | LLM 调用包装:Token 用量、成本、Provider 检测 |
chatagent/model/debug/ChatModelUsageTrace.java | 每次模型调用的追踪数据 |
chatagent/model/debug/ChatLimitStats.java | 限流与用量统计 |
调试追踪
| 文件 | 职责 |
|---|---|
chatagent/model/debug/ChatDebugTrace.java | 完整轮次调试快照 |
chatagent/model/debug/ChatToolTrace.java | 每次工具调用的追踪数据 |
chatagent/tool/TavilySearchTool.java | 工具调用埋点 |
检索观测
| 文件 | 职责 |
|---|---|
chatagent/model/RetrievalResultView.java | 检索结果观测视图 |
chatagent/model/ChannelExecutionView.java | 通道执行观测视图 |
chatagent/service/RetrievalObserveStore.java | 检索观测持久化接口 |
chatagent/service/MybatisRetrievalObserveStore.java | 检索观测 MyBatis 实现 |
性能基准
| 文件 | 职责 |
|---|---|
chatagent/service/StageBenchmarkService.java | 阶段延迟 P50/P90/P99 统计 |
chatagent/data/SuperAgentChatStageBenchmark.java | 基准数据库实体 |
chatagent/mapper/SuperAgentChatStageBenchmarkMapper.java | MyBatis Mapper |
chatagent/model/StageBenchmarkView.java | 基准视图 DTO |
集成点
| 文件 | 职责 |
|---|---|
chatagent/rag/service/ChatPreparationOrchestrator.java | 编排决策层埋点(MEMORY/REWRITE/ROUTE) |
chatagent/rag/executor/RagChatExecutor.java | RAG 执行层埋点(RAG_RETRIEVE/EVIDENCE_BUDGET/ANSWER_GENERATE) |
chatagent/rag/executor/ReactAgentExecutor.java | Agent 执行层埋点(REACT_AGENT) |
chatagent/rag/executor/GraphOnlyExecutor.java | 图查询埋点(GRAPH_QUERY) |
chatagent/rag/executor/GraphThenEvidenceExecutor.java | 图+证据埋点(GRAPH_QUERY) |
chatagent/rag/executor/ClarificationExecutor.java | 澄清埋点(ROUTE 完成) |
chatagent/rag/service/RagRetrievalEngine.java | 检索观测埋点 |
chatagent/service/BusinessChatService.java | 生命周期收尾(RECOMMENDATION/FINALIZE/refreshDebugTrace) |
数据库实体
| 文件 | 职责 |
|---|---|
chatagent/data/SuperAgentChatExchangeTraceStage.java | 阶段追踪表实体 |
chatagent/mapper/SuperAgentChatExchangeTraceStageMapper.java | MyBatis Mapper |
前端
| 文件 | 职责 |
|---|---|
vue/src/views/admin/AdminObservabilityDetailView.vue | 可观测性详情页(时间线 UI) |
vue/src/views/admin/observabilityHelpers.js | 追踪数据转换(1136 行,含阶段解析、用量分组、检索结果分组) |
十二、设计亮点总结
- 单一门面:
ConversationTraceRecorder是唯一入口,所有埋点只需传入 stageCode + snapshot,API 极简 - 自动耗时计算:
StageHandle记录startTimeMs,complete/fail 时自动计算durationMs,无需手动传入 - 异常自动捕获:
failStage(StageHandle, String, Throwable, Object)自动提取异常类名和完整堆栈注入快照,不再丢异常上下文 - Null-Safe 优雅降级:所有埋点代码检查
traceRecorder == null,测试或简化场景无需追踪即可正常运行 - 模型调用透明观测:
ObservedChatModelService包装 Spring AI ChatModel,同步/流式调用均自动收集 Token 用量和成本,对调用方完全透明 - Provider 自动检测:通过类名反射自动识别 DeepSeek / OpenAI / Ollama,无需手动配置
- Token 估算兜底:API 返回 Usage 时用真实值,未返回时按字符数估算,确保 100% 覆盖
- 检索漏斗可视化:从召回数 → 闸门过滤 → RRF 融合 → 父块提升 → Rerank 精排 → 最终 TopK,每个环节的数据都记录在快照中
- 完整 Prompt 存储:EVIDENCE_BUDGET 阶段保存完整 system prompt 和 user prompt,问题排查时可直接复现 LLM 输入
- 性能基准独立:
StageBenchmarkService按阶段+模式维度滚动保留 200 个样本,提供 P50/P90/P99 分布,支持长期性能回归监控 - traceId 全链路串联:一个 UUID 贯穿 MEMORY → REWRITE → ROUTE → RAG_RETRIEVE → ANSWER_GENERATE → FINALIZE,前端一键展示完整时间线
- 三种结束路径统一收尾:正常结束、异常结束、用户停止均触发 FINALIZE + 调试快照刷新,保证追踪数据不丢失
