Skip to content

18.2 Perfetto 性能追踪:registerPerfettoAgent()

本节焦点:通过 registerPerfettoAgent()(教学命名)将追踪模块注册进系统,把每一次 Agent 运行建模为一次微服务调用:有入口 span、子 span(工具、模型、渲染),可在 Perfetto UI 中切片分析。


学习目标

  1. 解释 Perfetto / Chrome Tracing 模型:tracksliceflow 的基本语义。
  2. 设计 registerPerfettoAgent 的 API:注册 name、版本、采样开关。
  3. 映射 Agent 回合 → turn slice,工具调用 → child slice,HTTP → nested slice。
  4. 评估 开销:生产环境采样率、异步 buffer。
  5. 关联 全链路遥测(18.3):同一 traceId 贯通日志与追踪。

生活类比:机场航班雷达

每次 Agent 运行像一架航班:起飞(turn 开始)、巡航(模型思考)、经停(工具)、降落(输出完成)。
Perfetto 是雷达屏幕:你看到的是时间轴上的航迹,而不是黑盒。


核心注册流程(概念 API)

typescript
// 教学用 API 名
type PerfettoAgentModule = {
  name: string;
  version: string;
  onTrace: (emit: PerfettoEmitter) => void;
};

declare function registerPerfettoAgent(mod: PerfettoAgentModule): Disposable;

type PerfettoEmitter = {
  beginSlice(cat: string, title: string, args?: Record<string, unknown>): void;
  endSlice(): void;
  instant(name: string, args?: Record<string, unknown>): void;
};

源码片段:在 Agent 回合包一层

typescript
const perfetto = registerPerfettoAgent({
  name: "claude-code-agent",
  version: "2.0.0",
  onTrace(emit) {
    bus.on("turn:start", ({ id }) => {
      emit.beginSlice("agent", `turn:${id}`, { id });
    });
    bus.on("turn:end", () => emit.endSlice());

    bus.on("tool:start", ({ name }) => {
      emit.beginSlice("tool", name);
    });
    bus.on("tool:end", () => emit.endSlice());

    bus.on("http:start", ({ route }) => {
      emit.beginSlice("http", route);
    });
    bus.on("http:end", ({ status }) => {
      emit.instant("http:status", { status });
      emit.endSlice();
    });
  },
});

// 应用退出
process.on("exit", () => perfetto.dispose());

微服务心智:每次运行 = 一次调用链

Span类比微服务
turnAPI Gateway 入站请求
model.stream下游 LLM 服务
tool.grep内部工具微服务
mcp.fetch外部 MCP 提供方

traceId / spanId 对齐(示意)

typescript
import { randomUUID } from "node:crypto";

function startTurnTrace() {
  const traceId = randomUUID();
  const baggage = { traceId };
  return baggage;
}

日志行应带 traceId,便于从 Perfetto slice 跳转到 结构化日志


生产开关

环境建议
开发100% 追踪或 Chrome trace_event
预发50% 采样
生产1–5% 采样 + 慢请求全量
typescript
const SAMPLE_RATE = Number(process.env.PERFETTO_SAMPLE ?? "0.01");

function maybe<T>(fn: () => T): T | undefined {
  if (Math.random() < SAMPLE_RATE) return fn();
  return undefined;
}

输出格式注意

  • Perfetto JSONChrome Trace EventOpenTelemetry 可互转;选型依现有栈。
  • 时钟域:前端 performance.now() 与后端 hrtime对齐策略(服务器权威 vs 客户端展示)。

常见坑

后果
begin 无配对 endtrace 文件损坏 / UI 错乱
slice 过密(每 token)体积爆炸
PII 打进 args合规风险

脱敏示例

typescript
function redact(s: string) {
  return s.length > 200 ? s.slice(0, 200) + "…" : s;
}

与第 17 篇性能优化的闭环

优化在 Perfetto 中验证
并行预取启动阶段 slice 墙钟变短
懒加载tool.register slice 后移
流式model.firstChunk instant 提前

自测

  1. 为何要把 toolmodel 分成不同 category
  2. 采样率与 问题可复现性 如何权衡?
  3. instant 事件与 slice 的区别?

表:推荐 category 命名

category用途
agent回合级
modelAPI 调用
tool本地工具
mcp远程 MCP
uiReact commit / 渲染

小结

  • registerPerfettoAgent() 是把追踪插件化的枢纽;每次 Agent 运行视为微服务调用链最利于对齐团队语言。
  • 配对 slice控制粒度脱敏 是上线三板斧。
  • traceId 日志贯通后,才能从「感觉慢」走到「哪一段慢」。

上一节:index.md · 下一节:03-telemetry.md

本项目仅用于教育学习目的。Claude Code 源码版权归 Anthropic, PBC 所有。