应使用OpenTelemetry而非runtime/trace:前者支持跨服务trace-id串联、HTTP/gRPC/DB自动埋点与OTLP导出;后者仅记录单进程内调度、GC等运行时事件,不传播上下文,无法实现分布式链路追踪。

runtime/trace 不是用来做“执行链路监控”的——它压根不记录 HTTP 请求、DB 调用、服务间调用路径,也不生成 trace-id 或 span-id。你要的是分布式链路追踪(Distributed Tracing),该用 OpenTelemetry,不是 runtime/trace。
trace.Start() 必须传 *os.File,不能传路径或 os.Stdout
- 传字符串路径(比如
"trace.out")会静默失败,文件写不进去,最终只有几十字节 - 用
os.Stdout或log.Writer()混入日志后,go tool trace解析直接报failed to read trace: EOF或unrecognized trace version - 正确写法只有一种:
f, _ := os.Create("trace.out") trace.Start(f)注意:不用再defer f.Close()(trace.Stop()内部已关),但留着也不冲突
程序必须存活 >100ms 且触发调度事件,否则 trace.out 无有效数据
-
trace.Start()只开启采样,不保证立刻写事件;默认采样间隔约 10ms,纯计算循环(如for i := 0; i < 1e9; i++)几乎不触发调度 - 常见空文件/小文件原因:
•os.Exit(0)或 panic 导致defer trace.Stop()没执行
•main()函数秒退,没来得及调度 goroutine 或触发 GC
•trace.Start()放在http.ListenAndServe()后面,程序卡住没后续逻辑 - 稳定做法:
• 在trace.Start()后起一个 goroutine +time.Sleep强制让出 CPU
• 或直接time.Sleep(200 * time.Millisecond)留出窗口
go tool trace 必须走 HTTP 服务打开,不能双击或拖进浏览器
- 直接双击
trace.out或用file://打开 → 浏览器报CORS error,页面白屏 - 正确命令:
go tool trace -http=:8080 trace.out
然后访问http://localhost:8080 - 如果页面卡死或加载不动:
• 文件 >50MB(说明采集太久或事件太密集),换更轻量的观测窗口
• 检查file trace.out输出是否为Go execution trace;若显示data或empty,说明文件损坏
runtime/trace 的真实用途很窄:看 goroutine 为什么卡在 Runnable、GC STW 时间多长、系统调用是否阻塞、channel 是否频繁阻塞。它不记录函数名,不支持自定义标签,也不能导出到 Jaeger 或 Zipkin。想查“哪个 handler 最慢”,该用 net/http/pprof;想串起一次 HTTP → DB → RPC 请求,必须上 OpenTelemetry。


















