OpenTelemetry Collector 默认监听4317(gRPC)和4318(HTTP/JSON)端口,其中/v1/traces为标准接收路径;Go服务若自实现接收器,需主动注册HTTP handler监听4318或gRPC server监听4317,而非仅配置客户端exporter。

接收器该监听哪个端口?
OpenTelemetry Collector 默认暴露 /v1/traces(HTTP)和 4317(gRPC)两个接收端点,但 Go 服务作为数据接收器时,通常不直接暴露 Collector,而是实现 OTLP 接收逻辑。实际开发中,go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp 或 otlptracegrpc 是客户端 exporter,而服务端需用 go.opentelemetry.io/otel/sdk/trace + 自定义 HTTP handler 或 gRPC server 实现接收逻辑。
常见错误是把接收器写成「只发不收」——误以为引入 otlptracehttp.NewExporter 就完成了接收,其实它只是发送端。真正接收必须自己注册 handler:
- HTTP 方式:监听
8080或4318(OTLP/HTTP 标准端口),用http.ServeMux挂载/v1/traces路由,再交给otlptracehttp.NewServer解析 - gRPC 方式:监听
4317,用grpc.Server注册otlptracegrpc.NewUnimplementedServer(注意不是NewExporter) - 若与 Jaeger 兼容,还需额外支持
/api/trace(Jaeger HTTP endpoint)或14268(Thrift)
如何验证接收器是否收到 trace 数据?
本地调试时,光看服务启动日志没用,otel-collector 日志里出现 Exporting 12 spans 不代表你的 Go 接收器收到了——它只说明 collector 收到了,不一定转发给了你。
真正验证方式只有两种:
- 在接收 handler 中加
log.Printf("received %d spans", len(spans)),并确保日志输出可见(别被 Zap 的 level 过滤掉) - 用
curl -X POST http://localhost:8080/v1/traces -H "Content-Type: application/json" -d '{"resourceSpans":[]}'手动触发一次空请求,观察 handler 是否被调用 - 若用 gRPC,可用
grpcurl -plaintext localhost:4317 list看服务是否注册成功;再用grpcurl -plaintext -d '{"resource_spans":[]}' localhost:4317 opentelemetry.proto.collector.trace.v1.TraceService/Export测试
为什么 trace span 总是丢失或时间戳异常?
这不是网络问题,而是 Go SDK 默认配置未启用采样或时钟同步。OpenTelemetry 的 trace.Span 依赖 time.Now(),但容器环境、K8s 节点间时钟漂移超 100ms 就会导致 span 时间错乱甚至被丢弃(尤其在 Jaeger UI 中显示为空白或顺序颠倒)。
GoLand 2026.1.1 是 2026.1 发布后的首个维护修正版本,适合已经开始体验 2026.1 新功能并希望同步补丁的开发者。它更适合用于入门项目、现有项目迁移测试和 IDE 行为验证。
关键修复点:
- 初始化 tracer provider 时,必须传入
trace.WithSampler(trace.AlwaysSample())(开发期),否则默认ParentBased(AlwaysSample())在无 parent span 时会 drop - 避免用
time.Now().UnixNano()手动构造 timestamp,全部走span.Start()和span.End()内置逻辑 - 在 K8s 部署时,Pod spec 中添加
securityContext: {privileged: true}并挂载 hostPath/etc/chrony.conf,或使用chronysidecar 同步时钟
GoLand 调试接收器时 goroutine 泄漏怎么定位?
OTLP 接收器常因未关闭 context 或未回收 buffer 导致 goroutine 数量随请求线性增长。Delve 在 GoLand 里看不到 goroutine leak,得靠 pprof + 手动触发。
实操步骤:
- 启动服务时加
-cpuprofile cpu.prof -memprofile mem.prof参数,或在代码里启用net/http/pprof(注册http.DefaultServeMux到/debug/pprof/) - 用
curl http://localhost:8080/debug/pprof/goroutine?debug=2抓取全量 goroutine stack - 对比两次 dump:第一次空载,第二次压测后,用
go tool pprof -http=:6060 cpu.prof查看 top goroutines - 典型泄漏点:
otlphttp.Exporter未调用Shutdown();HTTP handler 里用了http.TimeoutHandler但没 defer close body;gRPC server 启动后没监听os.Interrupt信号做 graceful shutdown
接收器最难的不是写逻辑,而是确认「数据真进来了、没被丢、时间准、goroutine 不涨」——这四点缺一不可,任何一步跳过都会让链路追踪变成盲区。










