187 lines
4.6 KiB
Markdown
187 lines
4.6 KiB
Markdown
|
|
# Cost Tracking System
|
||
|
|
|
||
|
|
Mission Control now tracks real usage costs by reading OpenClaw session data and calculating costs based on actual token usage.
|
||
|
|
|
||
|
|
## How It Works
|
||
|
|
|
||
|
|
1. **Data Collection**: The `collect-usage.ts` script reads `openclaw status --json` to get current session data
|
||
|
|
2. **Cost Calculation**: Uses model pricing table to calculate costs based on input/output tokens
|
||
|
|
3. **Storage**: Saves snapshots to SQLite database (`data/usage-tracking.db`)
|
||
|
|
4. **API**: The `/api/costs` endpoint queries the database to serve real cost data to the dashboard
|
||
|
|
|
||
|
|
## Model Pricing
|
||
|
|
|
||
|
|
Current pricing (as of Feb 2026):
|
||
|
|
|
||
|
|
| Model | Input ($/M tokens) | Output ($/M tokens) |
|
||
|
|
|-------|-------------------|---------------------|
|
||
|
|
| Opus 4.6 | $15.00 | $75.00 |
|
||
|
|
| Sonnet 4.5 | $3.00 | $15.00 |
|
||
|
|
| Haiku 3.5 | $0.80 | $4.00 |
|
||
|
|
| Gemini Flash | $0.15 | $0.60 |
|
||
|
|
| Gemini Pro | $1.25 | $5.00 |
|
||
|
|
| Grok 4.1 Fast | $2.00 | $10.00 |
|
||
|
|
|
||
|
|
Pricing is defined in `src/lib/pricing.ts`.
|
||
|
|
|
||
|
|
## Manual Collection
|
||
|
|
|
||
|
|
To collect usage data manually:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cd /root/.openclaw/workspace/mission-control
|
||
|
|
npx tsx scripts/collect-usage.ts
|
||
|
|
```
|
||
|
|
|
||
|
|
This will:
|
||
|
|
- Read current OpenClaw session data
|
||
|
|
- Calculate costs for each agent + model combination
|
||
|
|
- Save a snapshot to the database (replacing any existing data for the same hour)
|
||
|
|
|
||
|
|
## Automatic Collection (Cron)
|
||
|
|
|
||
|
|
To set up hourly automatic collection:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cd /root/.openclaw/workspace/mission-control
|
||
|
|
./scripts/setup-cron.sh
|
||
|
|
```
|
||
|
|
|
||
|
|
This adds a cron job that runs every hour at minute 0.
|
||
|
|
|
||
|
|
**View cron jobs:**
|
||
|
|
```bash
|
||
|
|
crontab -l
|
||
|
|
```
|
||
|
|
|
||
|
|
**View logs:**
|
||
|
|
```bash
|
||
|
|
tail -f /var/log/mission-control-usage.log
|
||
|
|
```
|
||
|
|
|
||
|
|
**Remove cron job:**
|
||
|
|
```bash
|
||
|
|
crontab -e
|
||
|
|
# Delete the line containing 'collect-usage.ts'
|
||
|
|
```
|
||
|
|
|
||
|
|
## Database Schema
|
||
|
|
|
||
|
|
```sql
|
||
|
|
CREATE TABLE usage_snapshots (
|
||
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
|
|
timestamp INTEGER NOT NULL,
|
||
|
|
date TEXT NOT NULL, -- YYYY-MM-DD
|
||
|
|
hour INTEGER NOT NULL, -- 0-23
|
||
|
|
agent_id TEXT NOT NULL,
|
||
|
|
model TEXT NOT NULL,
|
||
|
|
input_tokens INTEGER NOT NULL,
|
||
|
|
output_tokens INTEGER NOT NULL,
|
||
|
|
total_tokens INTEGER NOT NULL,
|
||
|
|
cost REAL NOT NULL,
|
||
|
|
created_at INTEGER DEFAULT (strftime('%s', 'now'))
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
## Querying the Database
|
||
|
|
|
||
|
|
**Total cost today:**
|
||
|
|
```bash
|
||
|
|
sqlite3 data/usage-tracking.db \
|
||
|
|
"SELECT SUM(cost) FROM usage_snapshots WHERE date = date('now');"
|
||
|
|
```
|
||
|
|
|
||
|
|
**Cost by agent (last 30 days):**
|
||
|
|
```bash
|
||
|
|
sqlite3 data/usage-tracking.db \
|
||
|
|
"SELECT agent_id, ROUND(SUM(cost), 2) as cost
|
||
|
|
FROM usage_snapshots
|
||
|
|
WHERE date >= date('now', '-30 days')
|
||
|
|
GROUP BY agent_id
|
||
|
|
ORDER BY cost DESC;"
|
||
|
|
```
|
||
|
|
|
||
|
|
**Cost by model:**
|
||
|
|
```bash
|
||
|
|
sqlite3 data/usage-tracking.db \
|
||
|
|
"SELECT model, ROUND(SUM(cost), 2) as cost
|
||
|
|
FROM usage_snapshots
|
||
|
|
WHERE date >= date('now', '-30 days')
|
||
|
|
GROUP BY model
|
||
|
|
ORDER BY cost DESC;"
|
||
|
|
```
|
||
|
|
|
||
|
|
**Daily trend (last 7 days):**
|
||
|
|
```bash
|
||
|
|
sqlite3 data/usage-tracking.db \
|
||
|
|
"SELECT date, ROUND(SUM(cost), 2) as cost
|
||
|
|
FROM usage_snapshots
|
||
|
|
WHERE date >= date('now', '-7 days')
|
||
|
|
GROUP BY date
|
||
|
|
ORDER BY date DESC;"
|
||
|
|
```
|
||
|
|
|
||
|
|
## API Endpoints
|
||
|
|
|
||
|
|
### GET /api/costs
|
||
|
|
|
||
|
|
Returns cost summary, breakdowns, and trends.
|
||
|
|
|
||
|
|
**Query params:**
|
||
|
|
- `timeframe` (default: `30d`) - Number of days to include in aggregations
|
||
|
|
|
||
|
|
**Response:**
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"today": 0.80,
|
||
|
|
"yesterday": 1.25,
|
||
|
|
"thisMonth": 12.50,
|
||
|
|
"lastMonth": 38.90,
|
||
|
|
"projected": 52.30,
|
||
|
|
"budget": 100.00,
|
||
|
|
"byAgent": [
|
||
|
|
{ "agent": "main", "cost": 5.50, "tokens": 450000, "percentOfTotal": 44 }
|
||
|
|
],
|
||
|
|
"byModel": [
|
||
|
|
{ "model": "anthropic/claude-sonnet-4-5", "cost": 8.30, "tokens": 890000, "percentOfTotal": 66 }
|
||
|
|
],
|
||
|
|
"daily": [
|
||
|
|
{ "date": "02-20", "cost": 0.80, "input": 12000, "output": 8000 }
|
||
|
|
],
|
||
|
|
"hourly": [
|
||
|
|
{ "hour": "14:00", "cost": 0.12 }
|
||
|
|
]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
**No data showing up:**
|
||
|
|
- Run `npx tsx scripts/collect-usage.ts` to collect initial data
|
||
|
|
- Check database exists: `ls -lh data/usage-tracking.db`
|
||
|
|
- Query database: `sqlite3 data/usage-tracking.db "SELECT COUNT(*) FROM usage_snapshots;"`
|
||
|
|
|
||
|
|
**Unknown model warnings:**
|
||
|
|
- Update `src/lib/pricing.ts` with new model pricing
|
||
|
|
- Rebuild: `npm run build`
|
||
|
|
- Restart: `systemctl restart mission-control`
|
||
|
|
|
||
|
|
**Costs seem wrong:**
|
||
|
|
- Verify pricing in `src/lib/pricing.ts`
|
||
|
|
- Check token counts: `openclaw status --json | jq '.sessions.byAgent[].recent[].totalTokens'`
|
||
|
|
- Recalculate: delete database and re-collect
|
||
|
|
|
||
|
|
## Future Enhancements
|
||
|
|
|
||
|
|
- [ ] Budget alerts (email/Telegram when >80% spent)
|
||
|
|
- [ ] Export reports (PDF/CSV)
|
||
|
|
- [ ] Cost forecasting with ML
|
||
|
|
- [ ] Per-session cost tracking (not just agent totals)
|
||
|
|
- [ ] Integration with OpenRouter billing API for real invoices
|
||
|
|
- [ ] Cost optimization suggestions ("switch to Haiku for heartbeats")
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Created:** 2026-02-20
|
||
|
|
**Author:** Tenacitas 🦞
|