Go
First-party: go/profiler (module watchtower/profiler). Sample types: cpu, heap, allocs, goroutine, mutex, block. Span links: yes, via profiler.WithSpan. Overhead is bounded by the sample rate (default 99 Hz); uploads never block the app and failures are only counted (Dropped()).
p, err := profiler.Start(profiler.Config{
Endpoint: os.Getenv("WT_ENDPOINT"), APIKey: os.Getenv("WT_INGEST_KEY"),
Service: "checkout", Version: "1.4.2", Env: "prod",
Types: []string{"cpu", "heap", "mutex", "block"}, RemoteConfig: true,
})
if err == nil { defer p.Stop() }
profiler.WithSpan(ctx, span, func(ctx context.Context) { handle(ctx) }) // labels span_id, trace_idRemoteConfig honors GET /v1/profiling/config (enabled, sample_rate_hz, upload_interval_s). The interval has ±20% startup jitter. To push an existing pprof instead, use wtctl profile upload cpu.pb.gz --service checkout --version 1.4.2 --format pprof.
Updated