From the open engine’s docs (traza 0.28.0). View source Engine routes reach a Traza Cloud project through the gateway.
Getting started
From nothing to a span you can see in the browser. Nothing else needs to be installed: no database, no queue, no mandatory container.
1. Install
The fastest path is a release archive — the server with the dashboard already built, no toolchains:
curl -LO https://github.com/toshish/traza/releases/download/v0.24.2/traza-0.24.2-macos-aarch64.tar.gz
tar xzf traza-0.24.2-macos-aarch64.tar.gz && cd traza-0.24.2-macos-aarch64
(linux-x86_64 and linux-aarch64 likewise; the container image is
ghcr.io/toshish/traza, and cargo install traza --locked --bin traza-server
installs the server API from crates.io — the dashboard comes from an archive
or a ui/ build.)
Or build from source: stable Rust (1.81 or newer) builds the server, Node 22 or newer builds the dashboard — only if you want the dashboard; the API does not need it.
git clone https://github.com/toshish/traza.git
cd traza
cargo build --release
(cd ui && npm ci && npm run build) # optional: emits ui/dist
cargo build --release produces traza-server and the tooling binaries in
target/release/:
| Binary | Purpose |
|---|---|
traza-server |
The HTTP server |
seed |
Loads a realistic demo corpus, for trying the UI |
bench, ingest-bench, query-bench, storage-bench, index-mem-bench, content-bench |
Benchmarks (see benchmarking) |
2. Run the server
./target/release/traza-server --data-dir ./data --port 8080
It starts in milliseconds and tells you exactly what it is promising:
traza-server listening on 127.0.0.1:8080
traza-server: durability=wal — acknowledged writes are fsynced to the write-ahead log and recovered on restart
traza-server serving dashboard from /path/to/traza/ui/dist
If you skipped the UI build, the third line is replaced by a list of every
directory searched. That is not an error — the API is unaffected, and GET /
returns a 404 explaining how to build the dashboard.
The default bind is loopback. Binding anywhere else without authentication is refused; see administration.
3. Send a span
A span batch is a JSON array, or an object with a spans key. Both halves of
the primary key (trace_id, span_id) must be non-empty; everything else has
a sensible default.
curl -X POST http://localhost:8080/v1/spans \
-H 'Content-Type: application/json' \
-d '[{
"trace_id": "trace-1",
"span_id": "span-1",
"name": "charge",
"service": "checkout",
"start_time_unix_nano": 1700000000000000000,
"end_time_unix_nano": 1700000000002500000,
"status": "ok",
"attributes": {"region": "us-east", "http.method": "POST"}
}]'
{"accepted":1,"durability":"wal"}
The response names what the acknowledgement guarantees, so a client never has to infer it. See durability.
4. Read it back
Fetch the whole trace:
curl http://localhost:8080/v1/traces/trace-1
{"annotations":[],"spans":[{"attributes":{"http.method":"POST","region":"us-east"},"end_time_ns":1700000000002500000,"events":[],"name":"charge","parent_span_id":null,"service":"checkout","span_id":"span-1","start_time_ns":1700000000000000000,"status":"ok","trace_id":"trace-1"}],"trace_id":"trace-1"}
Search across traces. Filters are ANDed; attr.KEY matches one attribute
exactly and may be repeated:
curl 'http://localhost:8080/v1/spans?service=checkout&attr.region=us-east&min_duration_ms=2&limit=50'
Check what the store holds:
curl http://localhost:8080/v1/stats
{"buffered_records":1,"bytes_on_disk":0,"durability":"wal","persisted_records":0,"record_count":1,"segment_count":0,"total_records":1,"wal_bytes":261}
bytes_on_disk and segment_count are zero because nothing has been sealed
into a segment yet — the span is durable in the write-ahead log
(wal_bytes is non-zero), not yet in a segment. POST /v1/flush seals it
immediately if you want to watch that happen.
The full route list is in the HTTP API reference.
5. See it in the browser
Open http://localhost:8080/. If you built ui/dist in step 1, the trace
browser loads: recent spans with a filter bar, per-trace waterfalls, span
detail, sessions, and LLM analytics. See the
trace browser guide.
To get a feel for it with real-shaped data rather than one span, load the demo corpus over the API:
./target/release/seed --url http://localhost:8080 --scale 3
seed: 580 spans (3/3 scale units)
seed: posted 580 spans and 9 annotations to http://localhost:8080
The corpus is deliberately messy in the ways production is messy: three
attribute dialects, tool-calling agent trees, multi-turn sessions, multimodal
and oversized payloads, failures with linked retries, a runaway agent that
cannot make progress, a large healthy fan-out that must not be mistaken for
one, and ordinary non-LLM traffic. Raise --scale for more. seed --data-dir DIR writes through the
engine directly instead, which is faster but requires that no server is running
against that directory — a data directory has exactly one writer.
If the server has authentication configured, give seed --url a token through
TRAZA_TOKEN — singular, and not to be confused with the server’s own
TRAZA_TOKENS. It needs rw:
TRAZA_TOKEN=your-rw-token ./target/release/seed --url http://localhost:8080 --scale 3
Without it the request is rejected before its body is read, and the connection
closes — seed reports Connection reset by peer.
6. Point a real application at it
Any OpenTelemetry SDK exports to Traza with two environment variables:
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:8080
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf # or http/json
Traza serves OTLP over HTTP, not gRPC. Apps instrumented with OpenLLMetry or the OpenTelemetry GenAI conventions land queryable with no attribute renaming: sessions, token counts, and model rollups populate on their own. See ingest and LLM semantics.
7. Let your agent read it
Traza can serve the Model Context Protocol, so the coding agent in
your terminal can answer “why did last night’s run cost four dollars” against
this store instead of you pasting JSON between two windows. Restart with
--mcp, then point a client at it:
traza-server --data-dir ./data --port 8080 --mcp
claude mcp add --transport http traza http://localhost:8080/v1/mcp
A scripted version of the whole thing — seed, serve, investigate, clean up —
is examples/mcp-demo/run.sh.
Ask it to call describe_store first — service and model names differ per
store, and that call is what stops an agent guessing one and reporting that
nothing is wrong. The dashboard’s MCP screen shows the live tool list and
generates the configuration for clients that need a stdio subprocess instead.
Where to go next
- Data model — what a span is, and why re-ingesting one is safe
- HTTP API reference — every route and parameter
- MCP server — the tools, resources and prompts an agent gets
- Deployment — running it somewhere that matters
- Configuration reference — every flag