Appearance
Telemetry objects
Telemetry rides the same endpoint as events: POST /v1/ingest, NDJSON, one object per line, the same keys and responses. An object with kind set to request, job, task, command, exception or span is telemetry; anything else is an event or a log line.
The Laravel SDK sends all of this for you. Use this page to write your own sender.
A bundle
One object per request, job run, scheduled task run or command: the root, its children, a summary and its exceptions.
json
{"kind":"request","event_id":"0192f0c4-7b1e-7cc1-9a51-3f1c2d4e5a6b","ts":"2026-10-20T09:14:03.410Z",
"trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","span_id":"00f067aa0ba902b7",
"name":"GET /orders/{order}","duration_ms":182.4,"status":"ok","http_status":200,"method":"GET",
"user_id":"42","release":"2026.10.3",
"spans":[
{"kind":"query","span_id":"a1b2c3d4e5f60718","start_ms":20.0,"duration_ms":61.0,"name":"select * from order_lines where order_id = ?","count":37},
{"kind":"http","span_id":"b2c3d4e5f6071829","start_ms":90.3,"duration_ms":40.1,"name":"POST api.stripe.com","http_status":200}],
"summary":{"queries":{"count":38,"duration_ms":66.9}},
"exceptions":[{"type":"App\\Exceptions\\PaymentDeclined","message":"Card declined","handled":true,
"frames":[{"file":"app/Services/Payments.php","line":88,"function":"charge","in_app":true}]}]}| Field | Root (request job task command) | Child (query http cache mail notification span) |
|---|---|---|
event_id, ts | Required; ts is the start | — |
trace_id | Required, 32 hex | Inherited |
span_id | Required, 16 hex | 16 hex |
parent_span_id | Optional; set it on a job dispatched by a request so both show in one trace | Optional, else the root |
name | Route pattern, job class, task command or command name | SQL with ? for values, METHOD host, hit/miss, a class name or free text |
duration_ms | Required | Optional |
start_ms | — | Offset from the root's ts |
status | ok or error (a 5xx counts as error) | Same |
http_status, method, route | Requests | http_status on http children |
count, max_ms | — | Identical calls folded into one, and the slowest |
summary | Exact totals per kind, kept even when you send no children | — |
exceptions | Up to 5 | — |
user_id, release, props | Optional | props optional |
Limits
- 64 KB per object as JSON; a bigger one is kept in Unparsed as
bundle_too_large, never stored in part. - 60 children after folding identical ones; the slowest are kept and the rest add up as one
(other)child per kind. - 5 exceptions, 50 frames and 8 KB per stack, 100 props.
- Names up to 512 bytes, SQL up to 2 KB.
- Up to 1,000 distinct names per kind per day; later new names count under
(other).
What we clean up
- Route names with ids in them (
/orders/8812) become patterns (/orders/{id}); query strings are dropped. - SQL literals become
?. Send the SQL your framework already shows with placeholders; never send bound values. httpnames keepMETHOD hostonly.
Exceptions
Inside a bundle, or on their own with kind: exception:
json
{"kind":"exception","event_id":"0192f0c4-8a2b-7cc1-9a51-3f1c2d4e5a6c","ts":"2026-10-20T09:15:00Z",
"type":"NSRangeException","message":"index 7 beyond bounds [0 .. 4]","handled":false,
"frames":[{"file":"Feed/FeedViewModel.swift","line":120,"function":"apply(update:)","in_app":true}],
"release":"3.2.0 (411)"}- They are stored as events named
exception(levelerror, orcriticalwhenhandledis false), so Logs, boards and alerts see them. - They group into issues by type, the message with numbers, ids and quoted text masked, and the first in-app frame. Send your own
fingerprintto group differently.
Logs in a trace
Add trace_id (32 hex) and span_id (16 hex) to any log line or event. The Logs page links it to the trace.
What counts toward your plan
A bundle counts one event per started 4 KB of JSON, or one per exception inside it if that is more: a typical request, with or without its queries, is one event. A standalone span counts one event per started 4 KB; a standalone exception counts one.