可观测性
phi-agent 自动采集结构化指标,无需额外配置 — 每个 session 都会在现有会话数据旁边写入 session_metrics.json。
采集内容
每轮指标 (TurnMetrics)
| 字段 | 说明 |
|---|---|
turn_number |
当前第几轮 |
duration_ms |
本轮总耗时 |
time_to_first_token_ms |
用户等待第一个 token 的时间(核心体验指标) |
llm_duration_ms |
LLM 纯耗时 |
tool_duration_ms |
工具执行耗时 |
input_tokens / output_tokens |
LLM 返回的 token 用量 |
tool_call_count / tools_used |
调用了哪些工具、多少次 |
tool_success / tool_failed |
工具成功/失败次数 |
outcome |
completed / tool_calls / error / cancelled / max_turns |
has_thinking |
模型是否使用了深度思考 |
user_input |
截断至 80 字 |
会话汇总 (SessionMetrics)
| 字段 | 说明 |
|---|---|
total_turns |
会话总轮数 |
total_input_tokens / total_output_tokens |
累计 token |
estimated_cost |
基于模型定价的费用估算 |
tool_breakdown |
每种工具的调用次数(如 {"shell": 5, "check_quality": 2}) |
tool_fail_rate |
工具调用失败比例 |
p50_turn_ms / p95_turn_ms / p99_turn_ms |
延迟百分位 |
outcome |
completed / failed / cancelled / max_turns |
error_count |
出错的轮数 |
CLI 命令
# 列出本机所有会话
phi metrics list
# 输出:
# Session Turns Tokens Cost Outcome
# 20260729_abc12345 (phi-bard) 5 27,000 $0.18 ✅ completed
# 20260729_def67890 (phi) 3 11,000 $0.06 ✅ completed
# 查看指定会话详情
phi metrics show 20260729_abc12345
# 查看最近一个会话
phi metrics last
环境变量
| 变量 | 默认值 | 说明 |
|---|---|---|
PHI_METRICS_ENABLED |
true |
设为 false 完全禁用指标采集(适合资源受限设备) |
PHI_NODE_ID |
"" |
节点标识,区分是哪台机器产生的指标 |
PHI_COST_PER_1K_TOKENS |
内置 | 自定义模型定价。格式:输入费用,输出费用 每千 token(如 0.002,0.008)。不设则使用内置的 Claude/GPT 定价表。 |
业务自定义指标
custom 字段允许注入任意 JSON 数据,框架不感知内容:
use phi_telemetry::{init_telemetry, save_metrics};
// 初始化观测并注入 session 级别的业务数据
let mut handle = init_telemetry(agent.runtime(), session_id, node_id, model);
handle.set_session_custom(serde_json::json!({
"product": "my-app",
"version": "1.0"
}));
// ... agent 运行 ...
// 关闭并保存
handle.shutdown().await;
let session = handle.session.read().await;
let mut session = session.clone();
session.finalize(SessionOutcome::Completed);
save_metrics(&session, &session_dir)?;
最终 session_metrics.json 中:
架构
观测代码运行在独立的 tokio task 中,通过 mpsc channel 与 agent 通信:
sequenceDiagram
participant A as Agent Task<br/>(runtime)
participant O as Observer Task<br/>(tokio::spawn)
Note over A,O: 正常运行
A->>O: on_turn_end hook → tx.send(TurnEnd)
O->>O: build metrics, accumulate in memory
Note over A,O: Observer panic
A->>O: tx.send(msg)
O--xA: channel closed
Note over A: let _ = send, 继续运行不受影响
- Observer panic 永远不会影响 agent — hook 静默丢弃失败的发送
- 会话期间 metrics 在内存中累积,
save_metrics()在shutdown()后写入磁盘 - Channel 是 unbounded 的 — 绝不阻塞 agent 热路径
文件布局
~/.phi-agent/sessions/<session_id>/
├── turn_001.jsonl ← 完整事件流(对话、思考、工具参数/结果)
├── turn_002.jsonl
├── session_meta.json ← 会话元信息
├── session.log ← tracing 日志
└── session_metrics.json ← 结构化指标(几 KB)