Profiling API
August 4, 2026 · View on GitHub
Gigapipe implements the Pyroscope API for continuous profiling with support for querying, rendering, and exporting profile data.
Profiles ingested via the OpenTelemetry profiles signal are queryable through these same endpoints — see OTLP Profiles below.
Profile Endpoints
Profile Types
List available profile types in your data.
POST /querier.v1.QuerierService/ProfileTypes
Request body:
{
"start": 1704067200000,
"end": 1704153600000
}
Response: Returns profile types in format name:sample_type:sample_unit:period_type:period_unit.
Label Names
POST /querier.v1.QuerierService/LabelNames
Parameters:
matchers- Array of label selectorsstart- Start time in millisecondsend- End time in milliseconds
Label Values
POST /querier.v1.QuerierService/LabelValues
Parameters:
matchers- Array of label selectorsname- Label name to querystart- Start time in millisecondsend- End time in milliseconds
Select Series
Query profile time series data.
POST /querier.v1.QuerierService/SelectSeries
Parameters:
profileTypeID- Profile type IDlabelSelector- Label selector querystart- Start time in millisecondsend- End time in millisecondsgroupBy- Array of labels to group bystep- Query resolution in secondsaggregation- Aggregation type (sum, avg, etc.)
Merge Stack Traces
Aggregate profiles into flamegraph format.
POST /querier.v1.QuerierService/SelectMergeStacktraces
Parameters:
profileTypeID- Profile type IDlabelSelector- Label selector querystart- Start time in millisecondsend- End time in millisecondsmaxNodes- Optional limit on number of nodes returned
Render Endpoints
Render Flamegraph
GET /pyroscope/render?query={selector}&from={timestamp}&until={timestamp}
Query parameters:
query- Profile query in formatprofile_type{label_selector}from- Start timestamp in millisecondsuntil- End timestamp in millisecondsformat- Output format:dotfor Graphviz DOT format, omit for JSON flamegraph (default)maxNodes- Limit nodes in output (0 = unlimited, only applies to DOT format)
Example:
curl "http://localhost:3100/pyroscope/render?query=process_cpu:cpu:nanoseconds:cpu:nanoseconds{service_name=\"my-app\"}&from=1704067200000&until=1704153600000"
Render Diff
Compare two profiles side-by-side.
GET /pyroscope/render-diff?leftQuery={query}&leftFrom={ts}&leftUntil={ts}&rightQuery={query}&rightFrom={ts}&rightUntil={ts}
DOT Format Export
Export profile data as Graphviz DOT format for external visualization or AI analysis.
Add format=dot to the render endpoint:
GET /pyroscope/render?query={selector}&from={timestamp}&until={timestamp}&format=dot
Response content type: text/vnd.graphviz; charset=utf-8
DOT Output Features
- Node labels: Function names with total and self sample counts and percentages
- Heat colors: Light gray (0% self samples) to red (100% self samples)
- Edge weights: Proportional to sample share (1-100 scale)
- Font scaling: Node font size 8-24pt based on self-sample percentage
- Human-readable values: Auto-formatted by unit type (e.g.,
1.23sfor nanoseconds,1.23 MBfor bytes)
Limiting Graph Size
Use maxNodes to control output complexity:
curl "http://localhost:3100/pyroscope/render?query=process_cpu:cpu:nanoseconds:cpu:nanoseconds{service_name=\"app\"}&from=1704067200000&until=1704153600000&format=dot&maxNodes=50"
Visualization Workflow
Generate a PNG with Graphviz:
curl "http://localhost:3100/pyroscope/render?query=process_cpu:cpu:nanoseconds:cpu:nanoseconds{service_name=\"my-app\"}&from=1704067200000&until=1704153600000&format=dot" | dot -Tpng > profile.png
Generate SVG:
curl "http://localhost:3100/pyroscope/render?query=process_cpu:cpu:nanoseconds:cpu:nanoseconds{service_name=\"my-app\"}&from=1704067200000&until=1704153600000&format=dot" | dot -Tsvg > profile.svg
Query Syntax
Profile Type ID Format
name:sample_type:sample_unit:period_type:period_unit
Examples:
process_cpu:cpu:nanoseconds:cpu:nanoseconds- CPU profilingmemory:alloc_space:bytes:space:bytes- Memory allocationgoroutine:goroutine:count:goroutine:count- Goroutine counts
Label Selector Syntax
{label1="value1", label2="value2"}
Examples:
{service_name="api-server"}- Single label{service_name="api-server", env="production"}- Multiple labels
Complete Query Format
process_cpu:cpu:nanoseconds:cpu:nanoseconds{service_name="my-app", env="prod"}
OTLP Profiles
Beyond Pyroscope SDK clients, gigapipe ingests the OpenTelemetry profiles signal
(profiles/v1development) over HTTP protobuf at POST /v1development/profiles.
See OTLP Profiles Ingestion for the ingestion path and
collector configuration. On the query side, OTLP profiles work through the same
Pyroscope-compatible endpoints described above.
Storage
OTLP profiles land in the same ClickHouse profiles tables as Pyroscope
profiles. Ingested rows carry the otel_v1development payload type internally so
the reader can distinguish them from native Pyroscope payloads.
Coexistence with Pyroscope profiles
Because both signals share the same tables, a single query can return data
sourced from both Pyroscope SDKs and OTLP collectors. No separate endpoint,
datasource, or query syntax is needed — the SelectSeries,
SelectMergeStacktraces, and /pyroscope/render endpoints all operate over the
combined data.
OTLP → pprof conversion on read
OTLP profiles are stored in their native OTLP encoding and converted to pprof on read, at query time. This keeps ingestion cheap and lets the existing flamegraph / series / stacktrace code paths consume OTLP and Pyroscope profiles identically.
Type namespace differences
The type label for an OTLP profile is derived from the OTLP sample_type type
string (e.g. cpu, samples), whereas Pyroscope profiles use their mapped
profile types (e.g. process_cpu, memory). When querying OTLP-sourced
profiles, match on the OTLP-derived type in the profile type ID rather than the
Pyroscope name.
Use Cases
Performance Analysis
curl -X POST http://localhost:3100/querier.v1.QuerierService/SelectMergeStacktraces \
-H "Content-Type: application/json" \
-d '{
"profileTypeID": "process_cpu:cpu:nanoseconds:cpu:nanoseconds",
"labelSelector": "{service_name=\"api\"}",
"start": 1704067200000,
"end": 1704153600000
}'
Memory Leak Detection
Compare memory profiles over time:
curl "http://localhost:3100/pyroscope/render-diff?leftQuery=memory:inuse_space:bytes:space:bytes{app=\"service\"}&leftFrom=1704067200000&leftUntil=1704070800000&rightQuery=memory:inuse_space:bytes:space:bytes{app=\"service\"}&rightFrom=1704153600000&rightUntil=1704157200000"
Export for AI Analysis
curl "http://localhost:3100/pyroscope/render?query=process_cpu:cpu:nanoseconds:cpu:nanoseconds{service=\"app\"}&from=1704067200000&until=1704153600000&format=dot" > profile.dot