- A trace is the execution graph for one request in one service. Its
trace_idis 32 lowercase hex characters, assigned by the SDK. - A step is one marked function in that trace’s call tree, carrying the function’s name as
module.qualnameand identified by its path: the per-level ordinals from the root. - An attempt is one execution of a step. A retried step has several, indexed from 0.
ok or error
with the exception class on error, and the values it saw, one per slot: input, output,
error, and logs where log capture is on for the service. Kept slots follow the service’s
capture policy.
Identity, and why order does not matter
A step’s identity is its path, so ingest is an idempotent upsert: a duplicate record changes nothing, and a record that arrives before its parent lands in the right place. Shape is what ran, with its timing and status and none of the captured bytes. A marked call appends it to the SDK’s in-process outbox as each attempt completes, and the writer thread writes the outbox to the spool directory every second, so records still there when the process is killed never reach disk. Values leave on a different clock, when the root returns. On age alone, the SDK never reports an open attempt before one second, and reports it by two seconds unless the record it holds for that attempt was dropped, for example past the 4,096 open records it holds at most. A dropped record is loss: the attempt reaches the trace only once it completes, and the trace’s close counts it inrecords_lost. That close and the process’s
two-second shutdown flush report every held attempt, whatever its age. A reported attempt reads
status: in_flight, with no duration and no slots.
One real trace
assign o-5003 in the demo service was rejected: no dasher works that zone. The root caught the
error, so the trace reads root_status: ok with one errored step.
Trace 1396289cd6ab96fa9f46ba176d7e8695, steps removed
duration_ms is whole milliseconds and this request took under one, so it reads 0.
The ten steps, indented by depth: name, path, status, duration, and the preview of the output
slot, or of the error slot where there is none. A preview is a value’s first 64 code points, which
is why the root’s output stops inside rejected.
The steps array, one line per step
DasherSelection.pick raised NoEligibleDasherError, and the step that holds the reason
succeeded: candidates found no dashers because in_zone found none. in_zone appears twice, at
AABAAAAAAA and AABAAAI: the same function at two paths is two steps.
null is check_serviceable’s recorded output, because it returns None. serviced_zones
returned a frozenset, which the SDK does not encode, so the slot holds a type marker instead and
the zone names are nowhere in the trace.
The root’s values, whole:
Values for path of the same trace
reason is the message the errored step produced, carried up by the function that caught it.
captured_via says an adapter turned that return value, a dataclass, into a dict.
What the data does not claim
A trace shows the paths that ran, never the branches not taken, and only marked functions appear in it. So the function index reports observed callers and observed callees, never “the callers”, and a cross-service request produces one trace per service, related by the tags the services carry, such as an order id. The API names that relationshares_tag. A shared
tag proves neither that one called the other nor that the two are one request, since assign,
quote, and track on one order all carry its order id.
A trace-detail response also carries a coverage object, reading clean above. records_lost,
records_shed, truncated and instance_mismatch are always there, and a search result carries
them as flat scalars per item. service_loss_24h counts what the service lost over 24 hours, and
is there only while GET /v1/coverage still lists that service. A
trace from a since-quiet service carries the four alone; a missing key is not a zero.
completeness: complete turns on those four and on the arrival of the root attempt’s completion
record, never on service_loss_24h.
Reading it in three rungs
Three rungs, each measured on a server seeded with the spec’s 17-step conformance trace, not the one above. Find answers what exists and returns no captured value:vexlo_search_traces over
its default page of 10 traces, 1,473 tokens. Shape returns one trace’s structure with previews and
no bytes: vexlo_get_trace, 3,184. Values return the bytes for the paths you name:
vexlo_get_values for one path’s two slots, 113. The full table is on
token costs.
Use cases maps six questions onto the data that answers each.