Skip to main content

View trace analytics

What you'll do: read time-series totals — request volume, error rate, tokens, cost, and latency percentiles — over every trace your team has recorded, and break that same data down by model to compare providers at a glance.

Every span your team has ever recorded — whether it came from a gateway completion or was posted directly via POST /traces from the SDK — lands in one spans table. The analytics endpoint aggregates across all of it, which makes it a superset of GET /gateway/usage, which only counts gateway traffic. If you also call the SDK's trace() to record work that never went through the gateway (a retrieval step, a tool call outside a traced loop), those spans show up here too, but not in gateway usage.

Full runnable script

A standalone script that ingests one trace and exercises every read in this guide — analytics, facets, settings, feedback, and sessions — lives at scripts/guides/view-trace-analytics on GitHub (Python) and its TypeScript sibling.

1. Read totals for the default window

With no query params, the window defaults to the last 30 days and the metrics are grouped by day.

curl -s -H "Authorization: Bearer $ACRUXCORE_API_KEY" \
"$ACRUXCORE_BASE_URL/traces/analytics"

Response (status 200) — one team's real traffic over the trailing 30 days, across six spans recorded that day (five llm spans across two models, one tool span with no model):

{
"from": "2026-07-05",
"to": "2026-08-04",
"groupBy": "day",
"totals": {
"requests": 6,
"errorRate": 0.16666666666666666,
"promptTokens": 404,
"completionTokens": 48,
"totalTokens": 452,
"costUsd": 0.0001146,
"latencyMs": { "p50": 0, "p95": 0, "p99": 0 }
},
"buckets": [
{
"key": "2026-08-04",
"requests": 6,
"errorRate": 0.16666666666666666,
"promptTokens": 404,
"completionTokens": 48,
"totalTokens": 452,
"costUsd": 0.0001146,
"latencyMs": { "p50": 0, "p95": 0, "p99": 0 }
}
]
}

2. Group by model

Pass group_by=model (groupBy: 'model' / group_by="model" in the SDKs) to see the same window broken down per model — the fastest way to compare cost, error rate, and latency across providers on one screen.

curl -s -H "Authorization: Bearer $ACRUXCORE_API_KEY" \
"$ACRUXCORE_BASE_URL/traces/analytics?group_by=model"

Response (status 200):

{
"from": "2026-07-05",
"to": "2026-08-04",
"groupBy": "model",
"totals": {
"requests": 6,
"errorRate": 0.16666666666666666,
"promptTokens": 404,
"completionTokens": 48,
"totalTokens": 452,
"costUsd": 0.0001146,
"latencyMs": { "p50": 0, "p95": 0, "p99": 0 }
},
"buckets": [
{
"key": "gpt-4o",
"requests": 1,
"errorRate": 1,
"promptTokens": 300,
"completionTokens": 0,
"totalTokens": 300,
"costUsd": 0.00009,
"latencyMs": { "p50": 0, "p95": 0, "p99": 0 }
},
{
"key": "gpt-4o-mini",
"requests": 4,
"errorRate": 0,
"promptTokens": 104,
"completionTokens": 48,
"totalTokens": 152,
"costUsd": 0.0000246,
"latencyMs": { "p50": 0, "p95": 0, "p99": 0 }
}
]
}
A null group key is counted, but not broken out

totals.requests is 6 above, but the two buckets only add up to 5 (1 + 4). The sixth span — a tool-kind span with no model — has a null group key under group_by=model, so it's counted in totals but omitted from buckets entirely, rather than showing up as a bucket with key: null. The same rule applies to group_by=session and group_by=prompt_version for a span with no session id or prompt version.

Other supported dimensions and filters — group_by=session / group_by=prompt_version, kind=llm|tool|retrieval|embedding|agent|chain|other, model=<exact-name>, and an explicit from/to window — are documented with their own curl-verified examples in the Traces API reference under Trace Analytics.

3. In the dashboard

The same numbers back Observability → Dashboards in the web app: a date-range picker (last 7/30/90 days, month-to-date, year-to-date, or a custom range) plus a group_by control, rendered as time-series line charts for day or grouped bar charts for model/session/prompt_version. For the bar views, a chip-and-autocomplete filter narrows the charts down to a chosen subset of models or prompt versions without an extra request.

What's next