Engineering note
日志、指标与可观测性:看见 Agent 到底做了什么
这是「Agent 工程实战」的第 14 篇。专题从一个能聊天、能调工具的 .NET Agent 出发,逐步补齐可靠性、安全、测试与发布能力。
本篇要解决的问题: 把请求、工具、耗时和错误串成可追踪事件,同时避免日志泄露敏感信息。
本章定位:本章建立 Agent 的观察能力。你会区分日志、指标和审计,设计 session、turn、tool call 三种关联 ID,并处理敏感信息脱敏。
建议阅读方式:先通读原理,再对照当前项目源码,最后完成本章实践。当 Agent 出现“偶尔不工作”时,没有可观测性就只能猜;本章会把猜测变成证据。
本章导读
本章建立 Agent 的观察能力。你会区分日志、指标和审计,设计 session、turn、tool call 三种关联 ID,并处理敏感信息脱敏。
本章采用“源码观察 → 概念拆解 → 工程改造 → 实践验证”的顺序。示例中的接口和代码骨架用于说明设计方向,真正提交代码时应结合项目当前状态逐步落地。
14.1 你至少需要知道什么
一次用户请求应能回答:
- 什么时候开始、什么时候结束;
- 调用了哪一个模型;
- 进行了几步工具调用;
- 每个工具耗时多久、是否成功;
- 模型请求是否重试;
- 输入输出 token 或字符数是多少;
- 最终失败发生在哪一层。
14.2 结构化日志
不要只使用 Console.WriteLine 拼字符串。建议日志字段固定化:
{
"event": "tool.completed",
"session_id": "...",
"tool": "filesystem.read_file",
"duration_ms": 18,
"success": true
}
敏感参数应脱敏。文件内容、API Key 和完整命令参数不应默认写入日志。
14.3 指标
第一批指标可以很少:
agent_turn_total;agent_turn_failure_total;model_request_duration_ms;tool_call_duration_ms;tool_call_failure_total;model_tokens_total。
14.4 本章交付物
ILogger;- request/session/turn/tool correlation ID;
- 结构化事件日志;
- 工具耗时和失败统计;
- 一份脱敏规则。
14.5 日志不是把所有内容都打印出来
调试阶段很容易把请求 JSON、完整工具参数和文件内容全部打印出来。短期看很方便,长期会造成密钥泄露、隐私泄露和日志成本上升。
建议日志分为三类:
- 生命周期日志:请求开始、结束、取消、失败;
- 决策日志:模型选择了哪个工具、调用 ID 是什么;
- 诊断日志:耗时、状态码、解析失败位置。
内容本身只在明确的 debug 模式下记录,并且仍然经过脱敏和截断。
14.6 相关 ID 的传递
一次用户输入至少需要三个 ID:
session_id:长期会话
turn_id:一次用户输入到最终回答
tool_call_id:模型发起的一次工具调用
日志中同时写入这三个 ID,才能从用户问题追踪到某次工具失败。不要只依赖时间戳,因为并发请求的时间可能重叠。
14.7 指标与日志的区别
日志适合解释一次具体请求为什么失败;指标适合观察整体趋势。例如“某次 ReadFile 失败”是日志,“过去 5 分钟 ReadFile 失败率为 12%”是指标。
先用内存计数器或简单 JSON 日志都可以,但字段一旦稳定,就不要频繁改名。稳定的指标名称能支持后续告警和仪表盘。
14.8 练习:设计一次失败的追踪
想象用户请求最终失败在第三次工具调用。写出至少五条日志事件,并确保只通过 session_id、turn_id 和 tool_call_id 就能还原执行顺序。再检查这些日志是否泄露了文件内容和密钥。
14.9 本章产出
完成本章后,遇到“模型没有回答”这种模糊问题,你应该可以定位是配置、HTTP、SSE、循环、工具还是上下文导致的。
单篇实战作业
实践:设计一条失败请求的日志链,确认只凭三个关联 ID 就能还原完整执行顺序。
建议把作业拆成一个独立提交,并在提交说明中写清楚:改动前的行为、改动后的行为、验证命令、尚未解决的风险。当 Agent 出现“偶尔不工作”时,没有可观测性就只能猜;本章会把猜测变成证据。
章节复盘
复盘问题:发生线上故障时,你能否区分 provider、网络、循环、工具和数据问题?
本章的完成标准不是把所有设计一次性做完,而是能把它变成项目中的一个明确边界,并为下一章留下可验证的接口。
下一篇:第 15 篇《测试 Agent,而不是只测试方法》
如果你正在把 Agent 放进真实工作流,建议完成本篇的实战作业后再继续:每一步都应留下可验证的代码、测试或运行记录。