A span event is one timed operation — a request, a render, a database call — inside a trace. Spans point at their parent span, which is how the trace waterfall is built. Spans are also how metrics travel: there's no separate metric event, and no separate trace event either.
Where it comes from
span(name, fn)/asyncSpan(name, fn)— sent whenfnreturns, throws, or its promise settles.startInactiveSpan(name)— sent when you callend().- Integrations that time things automatically (e.g. outgoing HTTP requests).
Payload
json
{
"type": "span",
"timestamp": "2026-09-24T10:15:02.913Z",
"tags": {},
"contexts": { "environment": "production", "http.method": "GET", "http.status_code": 200 },
"payload": {
"uuid": "c1d9…",
"name": "GET /api/cart",
"traceId": "5b7c0e1a-…",
"parentId": "8a2f…",
"startTime": "2026-09-24T10:15:02.481Z",
"endTime": "2026-09-24T10:15:02.913Z",
"duration": 432,
"op": "http.client",
"status": "ok",
"metrics": { "cart.items": 3, "response.bytes": 5120 }
}
}| Field | Type | Description |
|---|---|---|
uuid | string | This span's id. |
name | string | What was timed — the first argument to span(). |
traceId | string | The trace this span belongs to. |
parentId | string, optional | The enclosing span's id. Absent on a trace's root span. |
startTime | string | ISO 8601 start time. |
endTime | string | ISO 8601 end time. |
duration | number | Duration in milliseconds. |
op | string, optional | Operation category (http.client, db, ui.render, …) from { op } in the span's options. |
status | ok | error | cancelled | error when the callback threw or its promise rejected, otherwise ok, unless changed with span.setStatus(). |
metrics | object | name → number values recorded with span.metric(name, value). |
Values set with span.setData(key, value) aren't part of the payload — they're merged into the event's contexts.
Traces
A trace isn't an event of its own: it's the traceId its spans share. The first span that arrives with a new traceId creates the trace on the project's Traces page, and every later span with the same id joins it.
The trace's environment, user, tags and contexts come from its root spans (no parentId) — until one arrives, from the earliest span seen. In the browser one page trace can have several roots (a click that fires a request after the pageload span ended); each merges its tags and contexts into the trace instead of replacing them.
Trace-level contexts ride on the root span. browserTracingIntegration puts previous_trace.id — the trace of the page the user came from — on the pageload/navigation span, and the dashboard links the page traces of one visit through it (see Walking a visit).
Metrics
Every span.metric(name, value) call inside a span lands in its metrics map. Calling it twice with the same name keeps only the last value. Metrics are charted on the project's Metrics page and are always tied to the span (and trace) they were recorded in.
Sampling
The SDK's tracesSampleRate is decided per traceId, not per span: every span of a trace is either sent or dropped together, so you never see a half-sampled waterfall. Errors and logs from an unsampled trace are still sent and still carry its trace.id.
Quota
Counts as one toward the monthly spans limit — the only limit tracing is billed by, since a trace isn't an event of its own. The values in metrics cost nothing of their own.