Skip to main content

Crate llm_cost_dashboard

Crate llm_cost_dashboard 

Source
Expand description

§llm-cost-dashboard

Price every LLM API call your app makes, from a plain log line or the provider’s own response, and see spend, budget, forecasts and per-model costs in a terminal dashboard, a Prometheus endpoint or your own Rust code.

crates.io docs.rs License: MIT

llm-dash tailing a request log: new requests stream in, a 60,000-token gpt-4o call is flagged as a 26.7x cost anomaly, then the cost explorer sorts by price and opens that call

use llm_cost_dashboard::ingest::Ingester;

let mut costs = Ingester::new();
// Any mix of your own log lines and saved OpenAI / Anthropic responses.
costs.ingest_line(r#"{"model":"gpt-4o-mini","input_tokens":5200,"output_tokens":400}"#)?;
costs.ingest_line(r#"{"model":"claude-sonnet-4-6","usage":{"input_tokens":900,"output_tokens":350,"cache_read_input_tokens":40000}}"#)?;
for (model, s) in costs.ledger().by_model() {
    println!("{model}: ${:.6} over {} call(s)", s.total_cost_usd, s.request_count);
}
println!("total: ${:.6}", costs.ledger().total_usd()); // total: $0.020970

(cargo run --example quickstart runs exactly this.)

§Why this crate

You wantllm-cost-dashboardAlternatives
Price calls from logs you already havePlain NDJSON, saved OpenAI or Anthropic responses, Claude Code session logs; prompt-cache reads and 5-minute / 1-hour cache writes priced separatelyccstat reads coding-assistant logs only (Claude, Codex, …) and is a CLI, not a library
A price table you can trust and extend104 built-in models, cross-checked in the test suite against llm-cost-cap; load LiteLLM’s community table (3,680 models) with --prices or load_prices_jsonllm-cost-cap: 16 models, no cache-write pricing, and its Claude Opus 4.5 to 4.7 and Haiku 4.5 prices are out of date
A forecast and a budget gateDamped Holt forecast that copes with sparse, bursty logs; org, team and project budgets; webhook alertsllm-cost-cap gates one call before it is sent (worth combining with this crate)
To watch it livellm-dash: ratatui dashboard that follows the log file, plus /metrics for Prometheus and Grafanaedgequake-llm tracks cost inside its own multi-provider client; you have to send your calls through it
A small dependencydefault-features = false leaves serde, chrono, csv and tokio’s sync parts; the TUI, HTTP server, webhooks and CLI are features

If all you need is “would this one call cost more than $X before I send it”, llm-cost-cap has no dependencies and a lookup with it takes about a quarter less time (see Benchmarks).

§Install

The dashboard (llm-dash)

Linux (x86_64, Ubuntu 20.04+ / Debian 11+), one line, installs to ~/.local/bin:

mkdir -p ~/.local/bin && curl -fsSL https://gitlab.com/mattbusel/llm-cost-dashboard/-/releases/permalink/latest/downloads/llm-dash-linux-x86_64.tar.gz | tar xz --strip-components=1 -C ~/.local/bin --wildcards '*/llm-dash'
Other systems
WindowsDownload llm-dash-windows-x86_64.exe and run it. (Unsigned, so SmartScreen may ask: More info, then Run anyway.)
Any system with Rustcargo binstall llm-cost-dashboard (prebuilt Linux and Windows binaries) or cargo install --locked llm-cost-dashboard

Shell completions: llm-dash --completions bash > ~/.local/share/bash-completion/completions/llm-dash (also zsh, fish, powershell, elvish).

The library

[dependencies]
llm-cost-dashboard = { version = "1.3", default-features = false }   # pricing, ingest, forecasts, exports

In GitLab CI: fail a pipeline when the projected monthly bill is over budget with the llm-spend-check CI/CD component.

§Cargo features

FeatureDefaultWhat it addsExtra dependencies
clionThe llm-dash binary (implies tui and server)clap, clap_complete, tracing-subscriber, toml
tuivia cliui: the ratatui dashboardratatui, crossterm
servervia cliapi: JSON/CSV endpoints and Prometheus /metricsaxum, tokio net
webhooksonSlack / generic webhook alerts, signed with HMAC-SHA256reqwest (rustls), hmac, sha2
async-openaioffinterop::async_openai: price async_openai chat completion responsesasync-openai (types only, no HTTP client)

With default-features = false the library still has the ledger, pricing, ingest, forecasting, budgets, anomaly detection and exports.

§Use the dashboard in 3 steps

1. Look around with sample data (no API key, no setup):

llm-dash --demo

You get the dashboard above, filled with 20 sample Claude, GPT and Gemini requests. Press x for the cost explorer, q to quit.

2. Point it at your own calls. Have your app append one JSON line per model call to a file. Your own fields or the provider’s response both work:

{"model":"gpt-4o-mini","input_tokens":512,"output_tokens":256,"latency_ms":340}
{"model":"gpt-4o","created":1790344980,"usage":{"prompt_tokens":5120,"completion_tokens":256,"prompt_tokens_details":{"cached_tokens":4096}}}

Or point it at Claude Code’s own session logs: llm-dash --log-file ~/.claude/projects/<project>/<session>.jsonl.

3. Watch that file live, with a monthly budget:

llm-dash --log-file requests.ndjson --budget 50

New lines show up as your app writes them. The budget gauge turns yellow at 80% and red past 100%, and a call that costs far more than usual for its model appears under Cost Anomalies.

§Works with what you already use

  • async-openai: enable the async-openai feature and call interop::async_openai::record_from_response(&response); cached prompt tokens are priced at the cached rate.
  • Any other client (reqwest, genai, rig, the Anthropic HTTP API): serialize the response to JSON and pass it to Ingester::ingest_line. OpenAI-style usage.prompt_tokens and Anthropic-style usage.input_tokens / cache_read_input_tokens / cache_creation_input_tokens are understood.
  • LiteLLM’s price table: llm-dash --prices model_prices_and_context_window.json or cost::pricing::load_prices_json. Your own prices use the same call with {"model": {"input_usd_per_1m": 0.5, "output_usd_per_1m": 1.5}}.
  • Prometheus / Grafana / VictoriaMetrics: llm-dash --serve 9898 (or api::router inside your axum app) exposes llm_cost_usd_total, llm_requests_total, llm_tokens_total and llm_projected_monthly_cost_usd at /metrics.
  • Claude Code: session logs under ~/.claude/projects are read directly; cargo run --example claude_code_spend totals every session at API list prices.
  • llm-cost-cap: use it to gate a call before sending, and this crate to account for it after.

§Examples

ExampleWhat it shows
quickstartThe 10-line example above
claude_code_spendWhat your Claude Code sessions would cost at API prices, per model and per day
budget_checkPrice a log, forecast 30 days, exit 1 when over budget (a CI gate)
metrics_server (--features server)Record calls from your app and serve /metrics for Prometheus

§Benchmarks

cargo bench --bench vs_competitors, on an Intel i7-13700KF, Windows 11, Rust 1.91, criterion medians:

Taskllm-cost-dashboard 1.3.0llm-cost-cap 0.1.0
Price one call (5 models in rotation)24.2 ns18.6 ns
Parse and price 10,000 mixed log lines (flat, OpenAI response, Claude Code)22.5 ms (445,000 lines/s)no log parser

llm-cost-cap is faster at a single lookup because it does an exact-match hash lookup only; this crate also matches case-insensitively, falls back from dated ids (claude-sonnet-4-5-20250929) to the undated price, and checks run-time price overrides. Before 1.3.0 the lookup was a linear scan at 61.6 ns.

§Sample output

What the one-shot reports print (real output from llm-dash 1.3.0 on the demo data):

$ llm-dash --demo --compare
Multi-Provider Cost Comparison  (104 models, 22/day requests, 730in/348out avg tokens)

  Model                                           Monthly USD   Daily USD   Per-1k-req USD  Provider
  ----------------------------------------------------------------------------------------------------
  ministral-3b-2410                                    0.0285      0.0009           0.0431  Mistral
  llama-3.1-8b-instant                                 0.0425      0.0014           0.0643  Meta (Llama)
  amazon.nova-micro-v1:0                               0.0490      0.0016           0.0743  AWS Bedrock
  gemini-1.5-flash-8b                                  0.0525      0.0018           0.0796  Google
  ... 79 more rows ...
Cheapest: ministral-3b-2410 ($0.0285/mo)  |  Most expensive: gpt-4.5-preview ($70.5870/mo)  |  Spread: 2480x
$ llm-dash --demo --budget 50 --forecast
Holt-Winters Cost Forecast (based on 20 records)

  Next hour:  $0.004256
  Next day:   $0.1111
  Next week:  $0.81
  Next month: $3.49

  80% CI (next hour): [$0.000000, $0.010753]
  Budget status: OK (monthly forecast $3.49 < 80% of $50.00 budget)

In the recording above, the log’s 70 requests cost $0.5845 in total, and one gpt-4o call with 60,000 input tokens cost $0.3375 on its own: 26.7 times that model’s running average, which is what the anomaly panel reports.

§Your log format

{"model":"claude-sonnet-4-6","input_tokens":512,"output_tokens":256,"latency_ms":340,"timestamp":"2026-09-25T14:03:00Z"}
{"model":"gpt-4o-mini","input_tokens":128,"output_tokens":64,"latency_ms":120,"provider":"openai","ts":1790344980}
{"model":"gpt-4o","input_tokens":900,"output_tokens":0,"latency_ms":30000,"error":"timeout"}

model, input_tokens and output_tokens are required; latency_ms, provider, error and timestamp are optional.

You can also log the API’s own response object. Token counts are read from prompt_tokens / completion_tokens (OpenAI and compatible servers) or from a nested usage object (OpenAI usage.prompt_tokens, Anthropic usage.input_tokens), and OpenAI’s created field counts as the timestamp:

{"model":"gpt-4o-mini","created":1790344980,"usage":{"prompt_tokens":512,"completion_tokens":256,"total_tokens":768}}
{"model":"claude-haiku-4-5","usage":{"input_tokens":900,"output_tokens":120},"latency_ms":610}

Claude Code session logs (~/.claude/projects/**/*.jsonl) are read as they are: each request is counted once although Claude Code repeats it on several lines, user turns and bookkeeping lines are skipped, and cache reads and 5-minute / 1-hour cache writes are priced separately.

timestamp (also accepted as ts, time, created_at or created) can be an RFC 3339 string or Unix seconds or milliseconds; a line without one is dated when it is read. The dashboard keeps watching --log-file, so lines your app appends while it is open show up live. Malformed lines are skipped (run with RUST_LOG=warn to see why each one was skipped). Model names are matched case-insensitively, and a dated id such as claude-sonnet-4-5-20250929 uses the undated price. Unknown models are priced at a guessed $5 / $15 per million tokens, and the one-shot reports list them on stderr so you can add real prices with --prices.

§The dashboard

Panels, left to right and top to bottom:

PanelWhat it tells you
SummaryWhat you have spent, and what a month costs at the last hour’s pace
BudgetSpend against --budget; yellow at 80%, red past 100%
ForecastPer-day and month-end spend from the trend across all your data. Until the log spans enough time, it uses the last hour’s pace and says so
Prompt CacheCached-token reads and writes (one line when your log has none)
Savings OpportunitiesCheaper models for your traffic, with the monthly saving
Cost by ModelOne bar per model, with its total
Recent RequestsThe latest calls, newest first
Cost AnomaliesCalls that cost 2x or more their model’s running average
Last 7 daysSpend per day, today highlighted
Spend over timeThe last 60 request costs

The screen refreshes every 250 ms. Before any data arrives, the requests panel shows how to feed it. Colors follow your terminal theme and are turned off when NO_COLOR is set.

KeyAction
q / EscQuit
dLoad demo data
rReset all data
eExport the session to llm-costs-<timestamp>.json and .csv in the current directory
j / k or arrow keysScroll the requests table
xOpen the cost explorer (s cycles sort order, Enter toggles detail, x or Esc closes it)

§Command-line reports

These load --demo and/or --log-file data, print a report and exit without starting the TUI:

llm-dash --demo --compare                     # rank every priced model by monthly cost for this workload
llm-dash --compare --workload-rph 1000        # same, for a hypothetical 1000 requests/hour
llm-dash --demo --anomaly                     # Z-score cost anomaly report
llm-dash --demo --export-csv costs.csv        # or --export-json costs.json
llm-dash --demo --export markdown             # csv | json | jsonl | markdown, to --out FILE or stdout
llm-dash --demo --forecast                    # projection of the next hour, day, week and month (damped Holt smoothing)
llm-dash --log-file requests.ndjson --diff 2026-09-01 2026-09-02   # Markdown diff between two date prefixes

--forecast puts the log on a regular grid (about a day per bucket when the log covers 3 days or more, an hour when it covers 3 hours or more), counts quiet periods as zero spend, and runs Holt’s method with a damped trend over the per-bucket spend, so sparse logs give a sensible number instead of $0.

--forecast and --diff need timestamps in your log lines (see above). Without them every record is dated at load time, so --forecast says there is not enough time spread and --diff lists the dates it does have.

§CLI reference

FlagDefaultDescription
--budget <USD>10.0Monthly budget limit
--log-file <PATH>NDJSON request log to load at startup and keep following
--demooffPre-load demo data
--serve <PORT>Also start the HTTP API (below)
--webhook-url <URL>Slack or generic webhook for budget alerts (repeatable)
--webhook-threshold <USD>80% of budgetSpend level that fires the webhook
--webhook-format <FORMAT>genericslack or generic
--alerts <RULES_TOML>Check budget alert rules once against the loaded data, then start the dashboard
--prices <FILE>Load extra or corrected prices (LiteLLM JSON or a plain model map)
--bind <IP>127.0.0.1Address for --serve; use 0.0.0.0 to accept other machines
--completions <SHELL>Print a shell completion script and exit
--session <NAME>Tag every ingested record with a session id
--export-csv <PATH>, --export-json <PATH>Write all records and exit
--export <FORMAT>, --out <FILE>Export tagged requests as csv, json, jsonl or markdown and exit
--compare, --workload-rph <N>1000Multi-provider cost ranking and exit
--forecastoffPrint a spend forecast and exit (needs at least 3 records)
--anomalyoffPrint an anomaly report and exit
--diff <A> <B>Compare two date-prefix periods and exit

RUST_LOG controls log verbosity; logs go to stderr. Without it, the reports print warnings only and the dashboard prints no logs at all, since stderr lines would be drawn over it.

§HTTP API

llm-dash --demo --serve 8080
curl localhost:8080/api/summary       # JSON cost summary
curl localhost:8080/api/export.json   # full ledger as JSON
curl localhost:8080/api/export.csv    # full ledger as CSV
curl localhost:8080/metrics           # Prometheus text format

The server listens on 127.0.0.1 unless you pass --bind 0.0.0.0 (1.2.x listened on every interface).

§Budget alerts

Webhook alerts (Slack or a generic JSON POST) fire when spend crosses --webhook-threshold:

llm-dash --budget 50 --webhook-url "https://hooks.slack.com/services/..." --webhook-threshold 40 --webhook-format slack

Rule files for --alerts look like this:

[[rules]]
name = "daily-5-usd"
threshold_usd = 5.0
window = "daily"        # daily | weekly | monthly
cooldown_secs = 3600

§Supported models

104 models across Anthropic, OpenAI, Google, DeepSeek, Mistral, Meta Llama (Together AI and Groq), xAI, Cohere, Perplexity, Amazon Bedrock, Alibaba Qwen, Writer and AI21. Prices are USD per million tokens, from src/cost/pricing.rs (last updated 2026-10-03); check them against your provider before relying on the numbers.

Anthropic / Claude 5 family (Anthropic list prices, 2026-09) (6)
ModelInput ($/1M)Output ($/1M)
claude-fable-5-1$10$50
claude-fable-5$10$50
claude-opus-5-5$4$20
claude-opus-5$5$25
claude-sonnet-5-5$2$10
claude-sonnet-5$2$10
Anthropic / Claude 4 family (10)
ModelInput ($/1M)Output ($/1M)
claude-opus-4-8$5$25
claude-opus-4-7$5$25
claude-opus-4-6$5$25
claude-opus-4-5$5$25
claude-opus-4-1$15$75
claude-opus-4$15$75
claude-sonnet-4-5$3$15
claude-sonnet-4$3$15
claude-sonnet-4-6$3$15
claude-haiku-4-5$1$5
Anthropic / Claude 3.5 family (3)
ModelInput ($/1M)Output ($/1M)
claude-3-5-sonnet-20241022$3$15
claude-3-5-haiku-20241022$0.8$4
claude-3-5-sonnet-20240620$3$15
Anthropic / Claude 3 family (3)
ModelInput ($/1M)Output ($/1M)
claude-3-opus-20240229$15$75
claude-3-sonnet-20240229$3$15
claude-3-haiku-20240307$0.25$1.25
OpenAI / GPT-5 and GPT-4.1 families (6)
ModelInput ($/1M)Output ($/1M)
gpt-5$1.25$10
gpt-5-mini$0.25$2
gpt-5-nano$0.05$0.4
gpt-4.1$2$8
gpt-4.1-mini$0.4$1.6
gpt-4.1-nano$0.1$0.4
OpenAI / GPT-4o family (5)
ModelInput ($/1M)Output ($/1M)
gpt-4o$2.5$10
gpt-4o-mini$0.15$0.6
gpt-4-turbo$10$30
gpt-4.5-preview$75$150
chatgpt-4o-latest$5$15
OpenAI / o-series reasoning models (6)
ModelInput ($/1M)Output ($/1M)
o1$15$60
o1-preview$15$60
o1-mini$1.1$4.4
o3$2$8
o3-mini$1.1$4.4
o4-mini$1.1$4.4
OpenAI / Legacy (3)
ModelInput ($/1M)Output ($/1M)
gpt-4$30$60
gpt-3.5-turbo$0.5$1.5
gpt-3.5-turbo-instruct$1.5$2
Google / Gemini 2 family (6)
ModelInput ($/1M)Output ($/1M)
gemini-2.5-pro$1.25$10
gemini-2.5-flash$0.3$2.5
gemini-2.5-flash-lite$0.1$0.4
gemini-2.0-flash$0.1$0.4
gemini-2.0-flash-lite$0.075$0.3
gemini-2.0-flash-thinking$0.15$0.6
Google / Gemini 1.5 family (3)
ModelInput ($/1M)Output ($/1M)
gemini-1.5-pro$1.25$5
gemini-1.5-flash$0.075$0.3
gemini-1.5-flash-8b$0.0375$0.15
DeepSeek (7)
ModelInput ($/1M)Output ($/1M)
deepseek-r1$0.55$2.19
deepseek-v3$0.27$1.1
deepseek-v2-5$0.14$0.28
deepseek-chat$0.28$0.42
deepseek-coder$0.14$0.28
deepseek-r1-distill-llama-70b$0.55$2.19
deepseek-r1-distill-qwen-32b$0.55$2.19
Mistral (10)
ModelInput ($/1M)Output ($/1M)
mistral-large-2411$2$6
mistral-large-2407$3$9
mistral-small-2501$0.1$0.3
mistral-small-2402$1$3
mistral-nemo$0.15$0.15
codestral-2501$0.3$0.9
pixtral-large-2411$2$6
pixtral-12b-2409$0.15$0.15
ministral-8b-2410$0.1$0.1
ministral-3b-2410$0.04$0.04
Meta / Llama (via Together AI / Groq) (9)
ModelInput ($/1M)Output ($/1M)
meta-llama/llama-3.1-405b-instruct-turbo$5$5
meta-llama/llama-3.1-70b-instruct-turbo$0.88$0.88
meta-llama/llama-3.1-8b-instruct-turbo$0.18$0.18
meta-llama/llama-3.3-70b-instruct-turbo$0.88$0.88
meta-llama/llama-3.2-90b-vision-instruct-turbo$1.2$1.2
meta-llama/llama-3.2-11b-vision-instruct-turbo$0.18$0.18
llama-3.3-70b-versatile$0.59$0.79
llama-3.1-70b-versatile$0.59$0.79
llama-3.1-8b-instant$0.05$0.08
xAI Grok (5)
ModelInput ($/1M)Output ($/1M)
grok-3$3$15
grok-3-mini$0.3$0.5
grok-2-1212$2$10
grok-2-vision-1212$2$10
grok-beta$5$15
Cohere (4)
ModelInput ($/1M)Output ($/1M)
command-r-plus-08-2024$2.5$10
command-r-08-2024$0.15$0.6
command-a-03-2025$2.5$10
command-r7b-12-2024$0.0375$0.15
Perplexity (4)
ModelInput ($/1M)Output ($/1M)
sonar-pro$3$15
sonar$1$1
sonar-reasoning-pro$2$8
sonar-reasoning$1$5
Amazon (Bedrock) (5)
ModelInput ($/1M)Output ($/1M)
amazon.nova-pro-v1:0$0.8$3.2
amazon.nova-lite-v1:0$0.06$0.24
amazon.nova-micro-v1:0$0.035$0.14
amazon.titan-text-express-v1$0.2$0.6
amazon.titan-text-lite-v1$0.3$0.4
Alibaba Qwen (5)
ModelInput ($/1M)Output ($/1M)
qwen-max$1.6$6.4
qwen-plus$0.4$1.2
qwen-turbo$0.05$0.2
qwen2.5-72b-instruct$0.9$0.9
qwen2.5-7b-instruct$0.1$0.1
Writer (2)
ModelInput ($/1M)Output ($/1M)
palmyra-x-004$5$15
palmyra-x-003-instruct$1.5$2
AI21 Labs (2)
ModelInput ($/1M)Output ($/1M)
jamba-1.5-large$2$8
jamba-1.5-mini$0.2$0.4

§Library usage

Everything the dashboard does is also a Rust library (docs.rs).

Examples: ledger, cheapest model, budgets, anomalies, forecasts, tags
[dependencies]
llm-cost-dashboard = { version = "1.3", default-features = false }

The crate is llm_cost_dashboard. A ledger of priced requests:

use llm_cost_dashboard::{CostLedger, CostRecord};

let mut ledger = CostLedger::new();
// model, provider, input tokens, output tokens, latency ms
ledger.add(CostRecord::new("gpt-4o-mini", "openai", 512, 256, 34))?;
ledger.add(CostRecord::new("claude-sonnet-4-6", "anthropic", 1200, 400, 900))?;
println!("total: ${:.6}", ledger.total_usd());
println!("projected per month: ${:.2}", ledger.projected_monthly_usd(1));

Which model would be cheapest for this traffic:

use llm_cost_dashboard::comparison::{ProviderComparison, WorkloadProfile};
use llm_cost_dashboard::CostLedger;

let ledger = CostLedger::new(); // your populated ledger
let profile = WorkloadProfile::from_ledger(&ledger).unwrap_or_else(|| WorkloadProfile::from_rph(1000));
let cmp = ProviderComparison::compute(&profile);
for p in cmp.top_n_cheapest(5) {
    println!("{:<40} ${:>8.2}/mo  ({})", p.model, p.monthly_cost_usd, p.provider);
}

Org, team and project budgets with roll-up and alerts:

use llm_cost_dashboard::budget::hierarchy::{OrgTree, ProjectConfig, TeamConfig};

let mut tree = OrgTree::new("AcmeCorp", 1_000.0, 0.80); // $1k org limit, alert at 80%
tree.add_team(TeamConfig { name: "platform".into(), limit_usd: 400.0, alert_threshold: 0.75 });
tree.add_project(ProjectConfig {
    team: "platform".into(),
    name: "embeddings-prod".into(),
    limit_usd: 200.0,
    alert_threshold: 0.90,
})?;

for alert in tree.spend("platform", "embeddings-prod", 190.0)? {
    println!("[BUDGET ALERT] {}: {:.1}% used", alert.path, alert.fill * 100.0);
}
let summary = tree.summary();
println!("org: ${:.2} of ${:.2}", summary.org_spent_usd, summary.org_limit_usd);

Cost spikes, with a rolling Z-score detector:

use llm_cost_dashboard::anomaly::CostAnomalyDetector;

let mut detector = CostAnomalyDetector::new(50, 3.0); // window of 50, flag beyond 3 sigma
for cost in [0.001, 0.0012, 0.0009, 0.0011, 0.001, 0.25] {
    if let Some(event) = detector.observe("gpt-4o", cost) {
        println!("spike: ${:.4} (z = {:.1})", event.cost_usd, event.z_score);
    }
}

Spend forecasting from (unix_seconds, cumulative_usd) observations, by linear regression (SpendForecaster) or Holt-Winters smoothing (CostForecaster):

use llm_cost_dashboard::forecast::{CostForecaster, SpendForecaster};

let mut ols = SpendForecaster::new();
let mut hw = CostForecaster::new();
for (ts, total) in [(1_700_000_000.0, 0.0), (1_700_003_600.0, 0.50), (1_700_007_200.0, 1.05)] {
    ols.record(ts, total);
    hw.record(ts, total);
}
if let Some(f) = ols.forecast(Some(100.0)) {
    println!("month-end ${:.2}, R^2 {:.2}", f.projected_month_end_usd, f.confidence);
}
if let Some(f) = hw.forecast(Some(100.0)) {
    println!("next day ${:.2}, next month ${:.2}", f.next_day_usd, f.next_month_usd);
}

FinOps tags on requests, with grouping and reports:

use chrono::Utc;
use llm_cost_dashboard::tagging::{CostTag, TagFilter, TagReport, TagStore, TaggedRequest};

let mut store = TagStore::new();
store.push(TaggedRequest {
    request_id: 1,
    model_id: "gpt-4o-mini".to_string(),
    cost_usd: 0.015,
    tokens_in: 512,
    tokens_out: 256,
    tags: vec![CostTag::new("project", "search"), CostTag::new("env", "production")],
    timestamp: Utc::now(),
});
let prod = store.query(&TagFilter { key: Some("env".into()), value: Some("production".into()), ..Default::default() });
let by_project = store.group_by("project");
let report = TagReport::generate(&store, "project");

Other public modules include budget::planner (period budgets split by percentage, reconciled against actuals), tenant (per-tenant quotas and reports), alerts (TOML rule engine behind --alerts), alerting and webhook (Slack and generic webhooks with cooldowns), validator (checks Anthropic, OpenAI and Google API keys against their model-list endpoints), recommendations (cheaper-model suggestions), session, export, trends, model_compare, prediction and diff. See the rustdoc (cargo doc --open) for their APIs.

§How it works

Source layout
src/
  main.rs            CLI (clap): TUI launch and the one-shot report flags
  ui/                ratatui app state, event loop, dashboard layout, widgets, cost explorer
  log/               NDJSON parsing into LogEntry
  cost/              CostRecord, CostLedger, pricing table (pricing.rs)
  budget/            budget envelope, org/team/project hierarchy, planner
  comparison.rs      multi-provider monthly cost ranking
  ingest.rs          log lines to priced records (the library entry point)
  interop.rs         adapters for other crates (async-openai)
  forecast.rs        OLS and damped-Holt forecasters
  anomaly.rs         rolling and Welford Z-score detectors
  api/               axum server for --serve
  alerting.rs, alerts.rs, webhook/   alert rules and delivery
  export.rs          CSV / JSON / JSONL / Markdown export
  ...                about 60 further analysis modules (tagging, tenants, allocation, carbon, SLA, and more)
tests/, benches/     integration tests and criterion benchmarks

§Status and limitations

  • The dashboard follows --log-file as it grows (polling every half second) but does not read stdin. The one-shot reports (--forecast, --diff, exports) read the file once.
  • Time-based reports are only as good as the timestamp field in your log lines; lines without one are dated when read.
  • --alerts checks its rules once, against the data loaded at start-up.
  • Prices are a built-in table (cross-checked against LiteLLM’s table in October 2026: 63 of the 74 models both list agree; the rest are third-party resellers with different prices); load LiteLLM’s file with --prices to stay current.
  • The crate is large (about 80 modules). The core path (ledger, pricing, TUI, export, comparison, HTTP API) is what the binary uses; many analysis modules are library-only.
cargo test
cargo bench
RUST_LOG=debug cargo run -- --demo --compare

§License

MIT, see LICENSE.

§Where to start in the API

§Modules

  • alerting - webhook-based alert delivery with cooldown deduplication
  • allocation - team/project cost allocation with chargeback/showback workflows
  • anomaly - rolling Z-score cost spike detector
  • api - optional Axum HTTP API server and Prometheus endpoint (feature server)
  • budget - hard budget enforcement, soft alert thresholds, and org→team→project hierarchy (budget::hierarchy::OrgTree)
  • comparison - multi-provider side-by-side cost comparison and monthly projections (comparison::ProviderComparison)
  • cost - per-request cost records and the append-only ledger
  • cost::pricing - static pricing table and cost computation helpers
  • error - unified error type
  • export - CSV and JSON cost data export (file-based and in-memory)
  • forecast - OLS regression and Holt-Winters exponential smoothing cost forecaster
  • log - newline-delimited JSON log ingestion with header-based provider detection
  • org - multi-tenant organization -> team -> project hierarchy with spend tracking
  • recommendations - model recommendation engine with projected monthly savings
  • scheduler - cron-based automated export scheduling
  • session - per-session budget and cost tracking
  • tagging - FinOps cost attribution via structured tag rules and tag-aggregated ledger
  • tags - lightweight key=value cost attribution tags with top-N spend queries
  • trace - lightweight distributed tracing
  • trends - daily time-series aggregation, moving averages, period-over-period comparison, and ASCII sparklines
  • ui - ratatui TUI application state and event loop (feature tui)
  • validator - API key validation for Anthropic, OpenAI, and Google
  • webhook - Slack / generic webhook alerts on budget threshold

Re-exports§

pub use budget::BudgetAlert;
pub use budget::BudgetEnvelope;
pub use budget::OrgSummary;
pub use budget::OrgTree;
pub use budget::ProjectConfig;
pub use budget::ProjectSummary;
pub use budget::TeamConfig;
pub use budget::TeamSummary;
pub use comparison::CostProjection;
pub use comparison::ProviderComparison;
pub use comparison::WorkloadProfile;
pub use cost::CacheBreakdown;
pub use cost::CostLedger;
pub use cost::CostRecord;
pub use cost::ModelStats;
pub use error::DashboardError;
pub use export::CostExporter;
pub use export::ExportFormat;
pub use forecast::CostForecaster;
pub use forecast::ForecastResult;
pub use forecast::HoltWintersForecast;
pub use forecast::SpendForecaster;
pub use forecast::Trend;
pub use forecast::EsCostForecaster;
pub use forecast::ForecastMethod;
pub use forecast::SimpleEsModel;
pub use forecast::DoubleEsModel;
pub use forecast::HoltWintersModel;
pub use log::LogEntry;
pub use log::RequestLog;
pub use org::Organization;
pub use org::Project;
pub use org::Team;
pub use tags::TagIndex;
pub use tags::TaggedRecord;
pub use tags::Tags;
pub use trace::SpanStore;
pub use trace::TraceSpan;
pub use ui::App;tui
pub use validator::AnthropicValidator;
pub use validator::GoogleValidator;
pub use validator::MultiValidator;
pub use validator::OpenAiValidator;
pub use validator::ValidationResult;
pub use webhook::WebhookConfig;
pub use webhook::WebhookFormat;
pub use allocation::AllocationBucket;
pub use allocation::AllocationRule;
pub use allocation::AllocationTag;
pub use allocation::AllocationLedger;
pub use allocation::AllocationReport;
pub use allocation::BudgetHierarchy;
pub use allocation::CostAllocation;
pub use allocation::CostAllocator;
pub use allocation::Environment;
pub use allocation::ProjectBudget;
pub use allocation::TeamBudget;
pub use allocation::TeamUsage;
pub use allocation::teams_tab_rows;
pub use trends::DailySpend;
pub use trends::TrendAnalyzer;
pub use trends::TrendReport;
pub use alerts::Alert;
pub use alerts::AlertChannel;
pub use alerts::AlertEngine;
pub use alerts::AlertRule;
pub use alerts::AlertSummary;
pub use alerts::AlertWindow;
pub use anomaly::AnomalyConfig;
pub use anomaly::AnomalyDetector;
pub use anomaly::AnomalyReport;
pub use anomaly::AnomalyResult;
pub use budget::planner::AllocationStatus;
pub use budget::planner::BudgetAllocation;
pub use budget::planner::BudgetForecast;
pub use budget::planner::BudgetPeriod;
pub use budget::planner::BudgetPlan;
pub use budget::planner::BudgetPlanner;
pub use tenant::Tenant;
pub use tenant::TenantIsolator;
pub use tenant::TenantLedger;
pub use tenant::TenantReport;

Modules§

aggregator
Time-Bucketed Cost Aggregation
alert_manager
Multi-channel alerting with cooldown, suppression, and escalation.
alert_rules
Alert Rules Engine
alerting
Webhook Alerter
alerts
Budget Alert System
allocation
Team and Project Cost Allocation
anomaly
Cost Anomaly Detection
anomaly_detector
Statistical anomaly detection for cost spikes.
apiserver
HTTP API Server
audit_logger
Immutable audit trail for cost events.
benchmark
Model Benchmark Score Tracker
benchmark_runner
Model comparison benchmarking.
billing
Billing
budget
Budget Envelope
budget_controller
Budget Controller
budget_planner
Budget Planner
capacity
Capacity Planning
capacity_planner
Resource capacity planning with growth models and forecasting.
carbon
Carbon footprint estimator for LLM requests.
chargeback
Chargeback / Cost Allocation
clustering
Semantic cost clustering by prompt similarity.
cohort_analyzer
User cohort analysis for LLM cost data.
comparison
Multi-Provider Cost Comparison
cost
Cost Ledger
cost_allocation
Cost Allocation
cost_allocator_v2
Hierarchical cost allocation with tags and departments.
cost_attribution
Fine-grained cost attribution — record, group, filter, and export LLM spend across multiple organisational dimensions.
cost_forecast
Time-Series Cost Forecasting
cost_governance
Policy-based cost governance with approval workflows and monthly spend tracking.
cost_optimizer
Model selection optimizer to minimise cost while meeting a quality threshold.
cost_predictor
Predict future costs using linear regression on token usage patterns.
dashboard_metrics
Prometheus-style metrics collection for the LLM cost dashboard.
diff
Cost Diff Reporter
efficiency_analyzer
Analyze model efficiency: tokens/sec, cost/quality trade-offs, OLS regression.
error
Unified error type for the LLM cost dashboard.
experiment_tracker
Track LLM experiments and hyperparameter sweeps with Pearson correlation sensitivity.
export
Export
forecast
Spend Forecast Engine
ingest
Turn log lines into priced CostRecords without the dashboard.
integration_webhooks
Webhook Event System with Delivery Tracking
interop
Price responses from the Rust LLM clients you already use.
invoice_generator
Invoice Generator
log
Request Log
model_compare
Model Comparison Dashboard
model_lifecycle
Model version lifecycle tracking, deprecation dates, and migration planning.
model_registry
Model Registry
multi_tenant
Multi-Tenant Manager
notification
Notification Dispatcher
org
Multi-Tenant Organization View
prediction
Cost Prediction Engine
price_tracker
Track model pricing changes over time with alerts.
pricing_engine
Dynamic pricing engine with versioned price history and tier discounts.
quota
Rolling Window Quota Enforcement
recommendations
Model Recommendation Engine
replay
Event Sourcing Replay
resource_quota
Per-user and per-team resource quota management.
roi_calculator
ROI calculator for LLM deployments.
savings_calculator
Cost savings opportunity identification for LLM workloads.
scheduler
Export Scheduler
session
Session Tracking
session_cost
Per-Session Cost Tracking with Budget Enforcement
sla
SLA tier cost tracking and budget alerting.
sla_monitor
SLA tracking and compliance monitoring.
tagging
FinOps Cost Tagging and Attribution
tags
Cost Attribution Tags
tail
Log file tailing
tenant
Multi-Tenant Cost Isolator
token_optimizer
Prompt token optimization via redundancy removal.
trace
Trace Spans
trend
Cost Trend Analyzer
trend_analyzer
Time-series trend analysis: OLS linear trend, moving averages, exponential smoothing, seasonality detection, STL-style decomposition, and Holt’s forecasting.
trends
Historical Trend Analytics
uitui
UI Layer
usage_limiter
Per-user / per-team hard and soft usage limits with overage handling.
usage_report
Usage Report
usage_reporter
Generate usage reports in multiple formats.
validator
API Key Validator
visualization
Terminal Visualization
webhook
Webhook Alerts
webhook_dispatch
Outbound Webhook Delivery