Appearance
轨迹日志与执行可观测性
可观测性由三层组成:线程内 ConversationContext、领域事件/实时持久化监听器、JSONL trajectory 与数据库投影。应用日志适合排障,trajectory 适合恢复和审计,SSE 适合用户实时反馈,三者不能互相替代。
1. 链路上下文
ConversationContext.start 创建 ConversationTrace,绑定 traceId、sessionId、agentId、userId、流式标记、原始输入、runId 和开始时间。当前实现使用 InheritableThreadLocal,dispatcher/虚拟线程执行时必须在 worker 上重新绑定并在 finally 清理,避免线程复用造成跨 session 污染。
节点由 TrackedNodeAction/ConversationContext.startNode 包装,记录:
| 字段 | 含义 |
|---|---|
nodeName、nodeType、graphName | 主图/子图节点身份 |
iteration | Agentic Loop 轮次 |
userVisible | 是否对前端展示 |
| start/end/duration | 节点时延 |
| status/error | 成功、失败和异常 |
| totalTokens | 节点下关联模型用量 |
2. 调用记录类型
ConversationTrace 聚合不同调用:
| 记录 | 关键字段 | 典型来源 |
|---|---|---|
AgentExecutionCall | Agent、动作、输入摘要、终态 | 子 Agent/主 Agent |
LlmExecutionCall/LlmCall | provider、model、call type、tokens、延迟、成本 | ChatModel/Streaming wrapper |
ToolExecutionCall | toolName、executorType、params、status、duration | ToolCallNode/Skill/RAG |
RagExecutionCall | Dataset、retriever、query、命中、质量 | Rag/Embedding listener |
NodeExecution | 节点状态和迭代 | TrackedNodeAction |
SmartLlmCallListener、SmartStreamingChatModelWrapper、SmartEmbeddingModelListener 和 SmartEmbeddingStoreListener 会把 LangChain4j 回调转换为统一调用记录。流式模型在成功、错误、取消三种路径都要完成一次记录,否则总 token/成本和首 token 延迟会失真。
3. 事件发布与持久化
text
ConversationContext.record...
-> EventPublisherHolder/ApplicationEventPublisher
-> RealtimeLogPersistenceListener
-> node_execution_log / llm_call_log / tool_call_log / rag_logJSONL 监听器同时写 session event ledger:
- 节点开始/完成、LLM 请求结果、工具开始/结果、RAG、Skill、Todo、重规划。
- assistant text delta、structured block 和运行控制事件。
- checkpoint、compaction、branch、Sandbox 生命周期和错误。
数据库表适合分页查询和运营统计;JSONL 保留顺序、sequence、payload 引用和恢复所需 cursor。事件写入失败不能吞掉 Agent 主流程,但必须触发告警并保留可诊断错误。
4. 脱敏和负载策略
普通日志和数据库摘要不得写入 API key、Bearer Token、完整 system prompt、用户文件全文或外部服务密钥。SessionPersistenceProperties 对通用、LLM、工具、请求 profile 设置不同 inline 字节阈值,超过后写 blob 引用;恢复和轨迹详情再按权限读取。
建议记录:模型名、provider、输入/输出 token、耗时、状态、错误类型、参数摘要、结果长度、引用 ID。对完整 payload 使用访问控制、租户校验和保留期限。
5. 关键指标
| 指标 | 维度 | 用途 |
|---|---|---|
| 首 token 延迟 | provider/model/Agent | 判断排队、建连或模型慢 |
| 总运行时延 | session/run/终态 | 用户体验和超时分析 |
| input/output/total tokens | model/tenant/Agent | 成本与上下文压缩 |
| 工具成功率/超时率 | tool/serviceType | 依赖健康和重试判断 |
| RAG 命中、质量分、空结果率 | Dataset/retriever | 检索质量 |
| 队列积压、channel wait | queue/session | 背压和 SSE 配置 |
| pause/recovery blocked/cancel | run status | 控制链路可靠性 |
| SSE 断开和 pending event 数 | session/channel | 前端连接问题 |
6. 常用排障路径
text
traceId
-> ConversationTrace 状态/总时延
-> NodeExecution 最后节点
-> LlmExecutionCall 或 ToolExecutionCall
-> JSONL sequence / checkpoint
-> SSE pending 或 response snapshot常见判断:
- 没有 trace:检查 dispatcher 是否在 worker 建立
ConversationContext。 - 有 trace 无节点:检查 Agent 是否在 channel 等待或配置加载前失败。
- 节点成功但无模型调用:可能走了直接回答、缓存工具结果或
web_search_only路径。 - 工具显示成功但任务失败:查看 refining 的连续失败、重规划和
loopSignal。 - 数据库有完成状态但页面无文本:检查
SseStreamHandlerflush、assistant snapshot 和 pending event。
7. 新节点/新提供器的埋点要求
新节点必须使用 TrackedNodeAction 或 ConversationContext.withNode,声明正确 NodeType 和 userVisible。新模型/Embedding/Store provider 必须接入对应 listener,记录成功与失败、token/向量维度、延迟和 trace 绑定。新工具必须写 executorType、toolCallId、side-effect、输入摘要、结果长度和失败原因。