AI Token Dashboard

Pro

4 variants: overview KPI grid, usage breakdown (donut + bars), cost trend area chart and model comparison table for LLM usage and cost analysis.

</>sv-ai-token-dashboard aitokensanalytics
import { SvAiTokenDashboardComponent } from '@styloviz-pro/ai-token-dashboard';

Demo & usage

Basic usage

Pro

Usage example — open the gallery for the full interactive demo.

Pro

An interactive demo for this component lives in the gallery.

Open live demo

More examples

Cost trend & comparison

Pro

When to use

  • Monitoring LLM token usage and cost across models and time.
  • FinOps and engineering dashboards that track AI spend.
  • For general (non-token) analytics, use the Charts components.

Async states

  • loading
  • error
  • retry

Inputs

NameTypeDefaultDescription
loadingbooleanfalseTrue while the data is being fetched.
errorSvDataError | string | nullnullLoad failure. Use `toSvDataError()` from `@styloviz/core` to normalize an `HttpErrorResponse`.
variantTokenUsageVariant'overview'View: overview KPIs, usage breakdown, cost trend or model comparison.
dailyreadonly DailyUsage[][]Per-day token usage and cost.
modelsreadonly ModelUsage[][]Per-model totals. `cachedInputTokens` and `reasoningTokens` are optional SUBSETS of `inputTokens` / `outputTokens`, never additions: supply them and `breakdown` names each model's cached and reasoning share while `overview` names the share across all models; omit them and neither line renders.
budgetsreadonly BudgetItem[][]Budgets and their consumption.
usagereadonly SvUsageRecord[][]The usage export the `tenants` variant attributes. Raw records, one per (tenant, key, user, period) slice — the shape a billing pipeline already emits. The grouping is done here rather than by the host precisely because that is where the arithmetic goes wrong.
attributeBySvAttributionScope (two-way)'tenant'Which axis the `tenants` variant attributes along.
periodUsagePeriod (two-way)'30d'The reporting window. Two-way, so it can be driven from your own state.
efficiencyMinRequestsnumberSV_EFFICIENCY_MIN_REQUESTSRequests a row needs before its cost per request is compared with the fleet at all. WITHOUT A FLOOR THE ANOMALY COLUMN IS PERMANENTLY TOPPED BY NOISE: one tenant makes two calls, one of them a 200k-token document, and their rate is forty times the fleet's — so the column that exists to find the runaway agent spends every month pointing at somebody who owes eleven cents. WHERE the floor sits is traffic-shaped, though: 25 requests is a month for one tenant and a minute for another.
efficiencyBandnumberSV_EFFICIENCY_BANDDistance from the fleet rate, as a share, that reads expensive or cheap. A SHARE STRICTLY BELOW 1. The cheap test is `ratio <= 1 - band`, so at 1 it asks for a non-positive cost per request and above 1 for a negative one: no row could ever be cheap, and the column would lose half its vocabulary while still rendering the legend for it.
billingSvBillingContext{}What the invoice will do to these numbers. A COST DASHBOARD THAT DISAGREES WITH THE INVOICE DESTROYS TRUST IN ONE BILLING CYCLE — and it *will* disagree: list prices, in USD, before tax, before whatever discount the contract carries, over a window the provider has not finished settling. Every one of those gaps is ordinary and none of them used to be stated, so the first time finance compared the two, this page was simply "wrong".
passRatesReadonly<Record<string, number>>{}Pass rate per model id, 0–1, from your eval suite. THE FIGURE THAT MAKES THIS PAGE WORTH MORE THAN THE PROVIDER'S OWN BILLING SCREEN. A model at a third of the price that passes two thirds as often is not cheaper, and every dashboard in this category ranks by raw spend and calls the cheap one a saving. Pair it with `sv-eval-scorecard` and the ranking changes. Each `breakdown` row shows the multiple of its raw cost and the amount per passing result, in the display currency.

Outputs

EventPayload typeDescription
retryvoidThe host should re-run the failed load.
budgetThresholdCrossedBudgetThresholdEventEmitted the moment a budget WORSENS into `warning` or `critical` — not on every render while it stays there, and not when it recovers back down. A host wires this straight to a Slack/email alert without having to diff `budgets` itself on every change.
attributeByChangeSvAttributionScopeEmits the new `attributeBy` whenever it changes — the output half of `[(attributeBy)]`.
periodChangeUsagePeriodEmits the new `period` whenever it changes — the output half of `[(period)]`.

Wire it to your API

This component is headless about transport: it renders what you give it and reports what the user asks for. Nothing below requires @styloviz/data — drive it from whatever you already use.

Template

Pro

Bound to the names this component actually exposes.

Host class

Pro

Drive the three async inputs from your own fetch.

  • This component does not emit a query, so it renders what you give it. Fetch on your own trigger and bind `daily`, `loading` and `error`.
  • Normalize failures with `toSvDataError()` from `@styloviz/core`. It derives `retryable` from the status, so a 404 does not get a "Try again" button that can only fail again.

Full walkthrough: Connecting to a backend.

Customization & theming

  • `cachedInputTokens` and `reasoningTokens` are subsets of input and output, shown as notes rather than added to the total: per model in `breakdown`, and summed across models on the `overview` Token Distribution card. Beside the quality-adjusted multiple, `breakdown` shows the amount — cost per passing result against cost per request — in the display currency.
  • `daily`, `models` and `budgets` are inputs defaulting to the bundled sample, so the dashboard demonstrates itself out of the box and reports your real usage when you have it.
  • `period` is two-way, so the reporting window can be driven from your own state and used to refetch.
  • KPI, breakdown, trend and comparison views.
  • Per-model cost and token tracking.
  • Configurable currency and period.
  • Emits `periodChange` when the usage period changes.
  • The cost-efficiency verdict is host policy: `[efficiencyMinRequests]` (25) is the traffic a row needs before it is compared with the fleet at all — without a floor the anomaly column is permanently topped by a tenant who made two calls, one of them a long document — and `[efficiencyBand]` (0.5) is how far from the fleet rate reads expensive or cheap. Both default to the still-exported `SV_EFFICIENCY_MIN_REQUESTS` / `SV_EFFICIENCY_BAND`, and `svAttribute` takes them as an optional last argument. A band at or above 1 is refused, because "cheap" would then ask for a non-positive cost per request and no row could ever reach it.
  • `[billing]` — currency, rate, tax, discount, and how far the provider has settled — drives both the figures and a note that says **which gaps this page cannot account for**. Every displayed cost — totals, per-model, per-request, per-1M, budgets and attribution — goes through `svDisplayCost`, so the discount, tax and conversion the note claims are the ones the numbers carry, and the note renders under every variant that shows a cost, not only the breakdown. `rateAsOf` names the day the conversion rate was taken; a converted figure with no rate date says so, because an invoice converted on a different day will differ. A non-USD `currency` with no usable `rate` stays in USD and the note names the missing conversion — labelling unconverted dollars in another currency would be a claim about money nobody has. Budgets are compared with usage at list price, so they are displayed on the same basis as the spend they cap. A cost dashboard that disagrees with the invoice destroys trust in one billing cycle, and it will disagree: list prices, in USD, before tax, before whatever the contract discount is, over a window nobody has settled. A dashboard that says 'estimated' and stops has not helped — the reader needs to know which direction it is wrong in before taking it to finance.
  • `cachedInputTokens` and `reasoningTokens` are **subsets** of the input and output figures, never additions, so nothing on the page moves when a host adopts them. Cached input bills at a fraction, so counting it with fresh input overstates spend on exactly the workload somebody optimised; reasoning output is billed and never shown, so a reader who counts the words they got back and a bill that counts the tokens produced disagree by a factor — and the reader concludes the provider is overcharging.
  • `[passRates]` (model id → 0–1, from your eval suite) turns spend into **cost per result that passed**, rendered as a multiple of the sticker price because that survives a currency change and a period change. A model at a third of the price that passes two thirds as often is not cheaper, and every dashboard in this category ranks by raw spend and calls the cheap one a saving. At a zero pass rate the figure is refused rather than rendered as infinity — which would put a number in a column somebody will sort — or as the raw cost, which would say the failures were free. A pass rate outside 0–1 is labelled out of range (above 1 it reads as a percentage passed by mistake) rather than 'not recorded', and a model with no spend reads 'no spend recorded' rather than NaN×.

Best practices

  • Do: Show both tokens and cost — stakeholders care about the dollar figure.
  • Do: Break usage down per model so expensive calls are visible.
  • Tip: Pick the variant by audience: overview for execs, comparison for engineers.

Accessibility

  • Chart values are surfaced as text/tables.
  • Period and sort segmented controls are labelled and report aria-pressed.
  • Color-coded series paired with labels.

Feedback on AI Token Dashboard

Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.

Loads giscus.app and GitHub — nothing is fetched until you click.