Every report carries a single chronological chain, captured automatically. You only write code when you want to add something of your own.
{
"t": 1765800000123,
"seq": 42,
"kind": "network",
"level": "error",
"message": "POST /api/cart",
"data": {
"reqId": 17,
"status": 500
}
}
Kinds
| Kind | Recorded when |
|---|---|
navigation | A route change. See Screen tracking. |
tap | The user interacts with a control. |
console | Your app logs. See Console & network. |
network | A request completes. |
lifecycle | The tab is hidden or restored (visibilitychange). |
error | An uncaught error fires. See Crash reporting. |
custom | You called addBreadcrumb. |
Which kinds are recorded at all is configurable per app on the server — see Server config.
Adding your own
import { addBreadcrumb } from '@traceitx/react';
addBreadcrumb({
message: 'Coupon applied',
kind: 'custom',
level: 'info',
data: { code: 'SUMMER25', discount: 0.25 },
});
It is also on the hook, if you already have it:
const { addBreadcrumb } = useTraceItX();
addBreadcrumb never throws. An unknown kind coerces to custom and an
invalid level is dropped rather than passed through — instrumentation must not
be able to break the app it is instrumenting.
Put identifiers in data, not in message. data survives as structured
fields an agent can filter on; message is prose, and prose is what gets
truncated first.
The shared clock
t is absolute epoch milliseconds, on the same clock as the session replay
— that is what lets a viewer line a crumb up against the frame that was on
screen when it fired. seq is a monotonic per-session counter breaking ties
inside the same millisecond, so ordering stays stable at high event rates.
Limits
Caps and trimming behaviour — the entry cap, the byte budget, and the trim markers that record what was dropped — are in Errors & limits.