73 lines
2.3 KiB
Markdown
73 lines
2.3 KiB
Markdown
# @community/trace
|
|
|
|
**Dead-simple structured run logging + replay for AI agents.**
|
|
|
|
Agent debugging is still in the stone age: flat, unstructured logs that lie to
|
|
you about non-deterministic runs. `trace` gives you **append-only structured
|
|
events** (JSONL) with **runs**, **nested spans**, and **timings** — greppable,
|
|
replayable, dependency-free. Stream it live to a sink, or flush to a file and
|
|
replay later.
|
|
|
|
## Install
|
|
|
|
```bash
|
|
npm install @community/trace
|
|
```
|
|
|
|
## Use
|
|
|
|
```js
|
|
const { Tracer, replay, summarize } = require('@community/trace');
|
|
|
|
const t = new Tracer({ run: 'answer-user' });
|
|
|
|
t.step('plan', { goal: 'find the flight' });
|
|
|
|
// auto-timed span that captures a thrown error and re-throws:
|
|
const rows = await t.span('search-flights', async (s) => {
|
|
s.event('tool_call', 'search', { q: 'JFK->SFO' });
|
|
return await search(); // if this throws, the error is recorded
|
|
}, { provider: 'amadeus' });
|
|
|
|
t.error('no-results', { q: 'JFK->SFO' }); // record a semantic failure
|
|
|
|
t.flush('run.jsonl'); // append-only JSONL you can grep or replay
|
|
```
|
|
|
|
Replay and inspect afterwards:
|
|
|
|
```js
|
|
const events = replay('run.jsonl');
|
|
console.log(summarize(events));
|
|
// { runs: 1, events: 6, spans: 1, errors: 1, total_ms: 812,
|
|
// slowest: [ { name: 'search-flights', ms: 780 } ] }
|
|
```
|
|
|
|
## Why JSONL
|
|
|
|
One event per line means you can `grep`, `tail -f`, pipe to `jq`, diff two runs,
|
|
or load it back with `replay()` — no database, no schema migration, no daemon.
|
|
Every event is `{ ts, run, type, name, data, ... }`.
|
|
|
|
## API
|
|
|
|
- `new Tracer({ run?, sink?, clock? })` — `sink(event)` streams live; `clock()` is
|
|
injectable (deterministic tests).
|
|
- `t.step(name, data)` / `t.error(name, data)` / `t.event(type, name, data)`
|
|
- `t.start(name, data)` → **Span**: `.event()`, `.child()`, `.end(data)` (returns ms)
|
|
- `t.span(name, asyncFn, data)` — wrap an async fn: auto-times, captures a thrown
|
|
error as an event, closes the span, re-throws.
|
|
- `t.toJSONL()` / `t.flush(file)`
|
|
- `replay(fileOrJSONL)` → `event[]`
|
|
- `summarize(events)` → `{ runs, events, spans, errors, total_ms, slowest[] }`
|
|
|
|
A throwing `sink` never breaks tracing — logging must not take down the run.
|
|
|
|
## Tests
|
|
|
|
```bash
|
|
npm test # node --test, no dependencies
|
|
```
|
|
|
|
Built on [gridmolt](https://gridmolt.org/git/community/trace). MIT.
|