Profiling platform coverage
What Watchtower accepts, what it shows for each runtime, and what it does not do. Recipes per runtime are in ingest/profilers. Ingest endpoints are in ingest/profiles.
Runtimes
Runtime | Sample types | Ingest path | Symbolization | Span links |
|---|---|---|---|---|
Go (first-party | cpu, heap (alloc and inuse), goroutine, mutex, block | pprof push to | in the binary (pprof carries names) | yes, |
JVM | cpu, wall, alloc, lock (async-profiler) | folded stacks via | names in the output | no |
Python | cpu (py-spy) | folded stacks via | names in the output | no |
Ruby | cpu (rbspy) | folded stacks via | names in the output | no |
.NET | cpu (dotnet-trace converted to folded) | folded stacks via | names in the output | no |
Node.js | cpu (V8 |
| names in the output | no |
Rust, C, C++, any Linux binary | cpu ( | folded stacks via | debug files uploaded with | no |
Vendor and standard interop
Source | Accepted | Notes |
|---|---|---|
pprof (gzip or raw) | yes |
|
Pyroscope | yes | compatible, not Pyroscope; multipart uploads are not accepted |
OTLP profiles | yes | HTTP protobuf and gRPC; JSON is not accepted yet |
async-profiler collapsed, py-spy raw, rbspy collapsed, perf script | yes | as folded stacks |
Datadog, Elastic and Grafana profilers | not natively | their agents speak private wire formats tied to their backends; push their pprof or folded export instead |
Requirement coverage
Id | Capability | Status |
|---|---|---|
PRF-001 | Profile diff and comparison | query API and compare view |
PRF-002 | Trace-to-profile linking |
|
PRF-003 | Profile regression issues | regression detection over the function rollup |
PRF-004 | Continuous profiling policy | per-project policy, rules and remote config |
PRF-005 | Flame graph views | flame, table, call graph |
PRF-006 | Symbolization and debug info | debug files uploaded per project |
PRF-007 | Profile ingest formats | pprof, OTLP, folded, Pyroscope |
PRF-008 | Whole-system eBPF profiler | planned (Linux only, privileged) |
PRF-009 | Memory and allocation profiling | alloc and inuse sample types, leak candidates |
PRF-010 | Off-CPU and lock profiling | sample types stored and queried; eBPF collection with PRF-008 |
PRF-011 | Language profilers | Go first-party; other runtimes through the profilers above |
PRF-012 | Profile storage and retention | see below |
PRF-013 | Profiler platform coverage | this page |
Retention, archive and deletion
Retention. ClickHouse rows expire through a TTL on the project's
retention_daysfor profiles. A daily worker job deletes the raw originals in object storage that are older than the same number of days.Archive. Set
WT_PROFILE_ARCHIVE_DAYSon the worker to moveprofile_samples_v1partitions older than that many days to the ClickHouse storage volume namedcold. Default 0 is off. If the table's storage policy has nocoldvolume the job does nothing; configuring the policy is the operator's job.Deletion.
DELETE /v1/projects/{p}/profiles?before=<RFC 3339>[&service=<name>](role withDeleteTelemetry) answers202with adeletion_idand writes an audit event. Guarantees: the audit event is recorded before anything is deleted; ClickHouse applies the row deletes as asynchronous mutations, so rows can stay visible for a short time after the202; raw originals are deleted right after the mutations are queued, and a failed object delete is picked up by the daily retention job. Deletion does not reach backups; they age out on their own schedule.
Depth additions
JFR. Native recordings are parsed (
POST /v1/profiles?format=jfr).Sample types.
gc_pause,exceptionsandnative_allocjoin cpu, wall, alloc, inuse, offcpu and lock.Per-type retention. A row in
profile_type_retention_v1lowers the retention of one sample type for a project; it never raises the project's retention.Timeline and heatmap.
GET /v1/projects/{p}/profiles/timeline?service=&by=thread|host|containerreturns value per time bucket for each label value (at most 50 rows and 2000 buckets).Insights. CPU burst (over 75% for 10 s), burst saturation (a full core for 1 s) and starvation (no samples for 100 ms between busy buckets) cards.
Lock contention. The eBPF agent has uprobes for pthread mutex and rwlock waits (
go/agent/ebpf_profiler); loader wiring and the object build are pending.Hide packages. The explorer hides frames by prefix per service (browser setting); hidden time moves to the nearest visible caller.
Gaps
Windows ETW.
Symbol servers (debug files are uploaded, not fetched).