Go

Embed
Preview of the card
<a href="https://forumulate.com/p/watchtower/docs/profilers-go"><img src="https://forumulate.com/api/public/orgs/watchtower/spaces/docs/pages/ed128446-85e8-4ec7-9691-1d3491e4746a/social-card.svg?v=3e7ae33eec8b" alt="Go" width="600" height="315"></a>

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_id

RemoteConfig 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