Skip to main content
The Vexlo server keeps a function index: for every (team, service, name) it has seen, the observed callers and observed callees, counts, and up to five example calls. A function that ran has a row; nothing in the index describes code that was never marked. Rows are kept for 90 days. Every response body on this page was captured from a server seeded with the spec’s conformance trace, on team fixture. $READ_TOKEN holds a read token whose team-set includes fixture. The three routes take ?team=, ?environment=, and ?environment_unset= as on every read route (conventions). Narrow to one team when the token spans several: a response for a single team carries a team field, and a response spanning more than one team omits it. Counts are observed counts, not exact call counts, and they do not drift with delivery: a batch delivered twice leaves observed_count and error_count where they were, as it leaves the trace’s own shape unchanged (ingest). Every instant on this page (first_seen_at, last_seen_at, examples[].started_at) is derived from the time the server ingested the records, not from the client clock the trace’s own started_at reports.

GET /v1/functions

Lists functions, highest observed_count first.
observed_count and error_count sum across every observed caller of the function, and the two count different units. observed_count counts steps, once each: a function that ran once reads 1 however many attempts its step took. error_count counts attempts, one for every attempt that reported status: "error". PickBestFromCandidates, the step retried three times with every attempt failing, therefore reads observed_count: 1 and error_count: 3 on the second page below, and error_count above observed_count is what a retried function looks like rather than a contradiction. is_entry_point is true for a function observed opening a trace. Every function in this trace ran once, so every row reads observed_count: 1 and nothing on the response orders them: the keyset tie-break among equal counts is an internal row id that no response carries. The second page follows the cursor:
?name= narrows the list to one function:
The server applies ?name= after reading one page of rows ordered by observed_count, so on a service with more functions than limit an empty items alongside a next_cursor means only that the row is not on this page, never that the function was not observed. When you already hold the name, GET /v1/functions/detail looks it up directly and answers observed_count: 0 for a pair the index has never observed.

GET /v1/functions/detail

Returns one function with its observed callers and observed callees. The root function of the conformance trace:
A null caller name in observed_callers means the function was observed with no parent step: as an entry point, or as an orphan whose parent record never arrived. It alone does not prove an entry point; is_entry_point does. Here the two agree. The retried step:
The caller edge reads observed_count: 1, the one step, while the function’s error_count reads 3, one for each failed attempt of it. A caller edge carries no error_count at all. A pair the index has never seen answers 200 with observed_count: 0, empty lists, and empty strings for both instants. It is never a 404: “never observed” is the answer.
Omitting service is 422 service_required, and omitting name is 400 invalid_request:

GET /v1/functions/examples

Returns up to five example calls of one function, each pointing at a trace, a step, and an attempt, with the input and output handles of that attempt.
The example points at attempt 0 of the step at AACAAAIAAA in the conformance trace. That attempt raised, so it has no output slot, and the route renders one anyway with "state": "": treat an empty state as a slot that was not captured. started_at is the trace’s first_seen_at plus the attempt’s started_us, an ingest-relative instant. With include=values, each handle carries value in place of preview:
This is the one ?include= in the /v1 API, and with it the route is the second of two places a value is served, after GET /v1/traces/{id}/values. The pending state on both handles is the same read-side state the trace routes show for a non-root ok step whose value has arrived.