Go服务启动前必须显式调用sw.Init(),且须在main()开头、任何服务器初始化之前执行;HTTP埋点需用sw.HttpWrapper包装gin.Engine而非中间件,gRPC需匹配go2sky与grpc-go版本,跨goroutine须用sw.ContinuedFromContext重建上下文,Tag/Log必须在span.End()前设置。

Go服务启动前必须显式调用 sw.Init()
Go没有Java Agent那种自动字节码注入能力,所以sw.Init()不是可选配置,而是硬性前置条件。漏掉或放错位置,OAP后台就看不到服务名,拓扑图永远为空。
- 在
main()函数最开头执行,早于gin.Default()、http.ListenAndServe()或任何grpc.NewServer() - 传参至少包含
service_name和backend_address(如"127.0.0.1:11800"),不要依赖环境变量——代码配置优先级高于SW_AGENT_COLLECTOR_BACKEND_SERVICES - 若使用
go run main.go启动,确认没被IDE或shell里残留的SW_*环境变量覆盖
Gin HTTP请求埋点要用 sw.HttpWrapper 包装路由层
手动解析sw8头、自己调CreateEntrySpan是常见错误做法。Gin本身不拦截HTTP头,必须靠sw.HttpWrapper在底层完成解码与Span创建。
- 对
*gin.Engine,不能直接r.Use(...)中间件替代;要包装整个gin.Engine实例:http.ListenAndServe(":8080", sw.HttpWrapper(r)) - 下游调用时,从当前Span提取上下文:
carrier := sw.ContextCarrier{}; span.GetContext().Extract(&carrier),再通过req.Header.Set("sw8", carrier.ToString())透传 - 避免在其他中间件提前读取
req.Body(比如JSON解析、日志记录),否则sw.HttpWrapper会因body已耗尽而跳过埋点
gRPC调用链断裂常因 go2sky 与 grpc-go 版本不匹配
rpc error: code = Unknown desc = context deadline exceeded不是网络问题,而是插件未适配新版gRPC的流控策略。v1.9+的grpc-go默认启用严格Deadline,旧版go2sky插件没处理。
- 检查
go2sky版本:推荐使用v1.10.0+,对应grpc-go v1.60.0+ - 若用
go2sky-plugins/gin/v3,确认其依赖的go2sky主版本一致,不要混用v1.8和v1.10 - 跨goroutine传递Span时,必须用
sw.ContinuedFromContext(ctx)重建上下文,不能只传原始context.Context
自定义Span的Tag和Log必须在 span.End() 前设置
一旦调用span.End(),Span状态锁定,后续Tag()或Log()调用无效,数据不会上报。
立即学习“go语言免费学习笔记(深入)”;
- 所有业务逻辑中想标记的字段(如
"user_id"、"sql"、"error")都要在span.End()之前完成 - 入口Span(
CreateEntrySpan)通常由sw.HttpWrapper自动创建,你只需在Handler内获取并操作:span := sw.GetSpan(r.Context()) - 本地Span(
CreateLocalSpan)需手动管理生命周期,务必配对defer span.End(),并在defer前设置Tag/Log
sw.Init()的执行时机和sw8头透传的完整性——前者导致服务根本不上报,后者导致链路在第一个HTTP跳转就断开。这两处出问题,后面所有埋点都白搭。


















