Usage, Quota & Spend Tracking (Deutsch)
Übersicht
Abschnitt betitelt „Übersicht“Jede Anfrage, die OmniRoute durchläuft, erzeugt einen Nutzungsdatensatz, der Folgendes erfasst:
- Identität: welcher API-Schlüssel, Anbieter, welches Modell und welche Kombination
- Tokens: Prompt-Tokens, Vervollständigungs-Tokens, zwischengespeicherte Tokens, Gesamtzahl
- Kosten: Betrag in USD (anhand von Preisdaten berechnet)
- Zeitmessung: Latenz, Start-/Endzeitstempel
- Status: erfolgreich, Fehler, ratenbegrenzt usw.
Diese Datensätze werden zu Analysen aggregiert, als Kontingent-Snapshots gespeichert und zur Durchsetzung von Budgetlimits pro Schlüssel verwendet.
Anfrage ──▶ chatCore ──▶ usage.record() ──▶ SQLite │ ┌───────┼───────┐ ▼ ▼ ▼ Analysen Kontingent Abrechnung (Dashboard) (Durchsetzung) (Export)Was erfasst wird
Abschnitt betitelt „Was erfasst wird“Der Dienst usage.ts erfasst für jede Anfrage ein Nutzungsereignis:
| Feld | Typ | Quelle |
|---|---|---|
id |
string | Beim Erfassen generierte UUID |
apiKeyId |
string | Der API-Schlüssel, der die Anfrage initiiert hat |
provider |
string | Anbieter-ID (openai, anthropic usw.) |
model |
string | Modell-ID (gpt-5, claude-opus-4-6 usw.) |
comboId |
string? | Kombinations-ID, falls über eine Kombination weitergeleitet |
promptTokens |
number | Aus der Antwort des Upstream-Anbieters |
completionTokens |
number | Aus der Antwort des Upstream-Anbieters |
cachedTokens |
number | Tokens aus Cache-Treffern (Anthropic-Prompt-Caching usw.) |
totalTokens |
number | Prompt + Vervollständigung |
costUsd |
number | Anhand von Preisdaten berechnet |
latencyMs |
number | Gesamtdauer der Anfrage |
status |
enum | success, error, rate_limited, timeout, cancelled |
errorClass |
string? | Fehlerklasse, falls Status != Erfolg |
timestamp |
string | ISO 8601 UTC |
metadata |
object | Benutzerdefinierte, durch Plugins eingefügte Daten |
Woher die Tokens stammen
Abschnitt betitelt „Woher die Tokens stammen“Tokens werden im Antwort-Handler aus der Antwort des Upstream-Anbieters extrahiert:
// Aus open-sse/handlers/chatCore.tsconst response = await providerExecutor.execute(provider, request);const usage = response.usage || { prompt_tokens: 0, completion_tokens: 0, cached_tokens: 0,};Für Anbieter, die keine Nutzungsdaten zurückgeben (einige Web-Cookie-Anbieter), schätzt OmniRoute die Token-Anzahl anhand der Heuristik ~4 Zeichen pro Token (siehe open-sse/services/autoCombo/pipelineRouter.ts).
Zwischengespeicherte Tokens
Abschnitt betitelt „Zwischengespeicherte Tokens“OmniRoute erfasst cached_tokens getrennt von prompt_tokens, weil:
- Anthropic-Prompt-Caching für zwischengespeicherte Tokens einen reduzierten Preis berechnet (10 % des normalen Preises)
- Einige Anbieter
cache_read_input_tokenszurückgeben, die anders abgerechnet werden sollten - Analysen die Cache-Trefferrate anzeigen können =
cached_tokens / prompt_tokens
Kostenberechnung
Abschnitt betitelt „Kostenberechnung“Die Kosten werden anhand von Preisdaten berechnet, die von LiteLLM synchronisiert werden (src/lib/pricingSync.ts):
| Modell | Eingabe $/1M | Ausgabe $/1M | Cache $/1M |
|---|---|---|---|
| gpt-5 | $2.50 | $10.00 | — |
| claude-opus-4-6 | $15.00 | $75.00 | $1.50 |
| claude-sonnet-4-5 | $3.00 | $15.00 | $0.30 |
| gemini-2.5-pro | $1.25 | $10.00 | — |
Die Kostenformel (src/lib/usage/costCalculator.ts):
cost = (prompt_tokens - cached_tokens) * input_price + cached_tokens * cached_price + completion_tokens * output_price;Warum werden zwischengespeicherte Token von den Prompt-Token abgezogen? Der zwischengespeicherte Anteil wird separat berechnet; wenn der Eingabepreis auf den gesamten Prompt angewendet würde, käme es zu einer Doppelberechnung.
Preissynchronisierung
Abschnitt betitelt „Preissynchronisierung“Die Preisdaten werden über den Endpunkt /api/pricing/sync automatisch von LiteLLM synchronisiert (ausgelöst durch die integrierte Cron-Aufgabe, nicht durch eine benutzerseitige Umgebungsvariable):
# Manuelle Auslösungcurl -X POST http://localhost:20128/api/pricing/syncBei Modellen ohne Preisdaten greift OmniRoute auf eine Kostenschätzung anhand interner Durchschnittspreise zurück (basierend auf den Preisdaten von LiteLLM).
Aggregation nach Datumsbereich
Abschnitt betitelt „Aggregation nach Datumsbereich“Das Modul usageAnalytics.ts berechnet Dashboard-Widgets aus Rohdaten zur Nutzung. Es unterstützt 7 Zeiträume:
| Zeitraum | Zeitfenster | Anwendungsfall |
|---|---|---|
1d |
Letzte 24 Stunden | Erkennung stündlicher Kostenspitzen |
7d |
Letzte 7 Tage | Wöchentliche Auswertung |
30d |
Letzte 30 Tage | Monatliche Abrechnung |
90d |
Letzte 90 Tage | Quartalsanalyse |
ytd |
Seit dem 1. Januar des aktuellen Jahres | Überwachung des Jahresbudgets |
all |
Gesamter Zeitraum | Gesamtstatistiken |
custom |
Benutzerdefinierter Start-/Endpunkt | Audits, Ad-hoc-Abfragen |
Berechnete Dashboard-Widgets
Abschnitt betitelt „Berechnete Dashboard-Widgets“Für jeden Datumsbereich berechnet die Analyseschicht Folgendes:
| Widget | Beschreibung |
|---|---|
| Übersichtskarten | Gesamtzahl der Anfragen, Gesamtkosten, Gesamtzahl der Token, Erfolgsquote |
| Tägliches Trenddiagramm | Kosten und Token pro Tag, nach Modell gestapelt |
| Aktivitäts-Heatmap | Raster aus Tageszeit × Wochentag, Farbe = Anzahl der Anfragen |
| Modellaufschlüsselung | Kreisdiagramm der Kosten nach Modell |
| Anbieteraufschlüsselung | Balkendiagramm der Anfragen nach Anbieter |
| Wichtigste API-Schlüssel | Tabelle der 10 Schlüssel mit den höchsten Kosten |
| Fehleranalyse | Fehlerrate im Zeitverlauf, häufigste Fehlerklassen |
Programmatischer Zugriff
Abschnitt betitelt „Programmatischer Zugriff“import { computeAnalytics } from "@/lib/usageAnalytics";
const analytics = await computeAnalytics( history, // Datensätze des Nutzungsverlaufs "7d", // Zeitraum: "1d" | "7d" | "30d" | "90d" | "ytd" | "all" | "custom" connectionMap, // Zuordnung der Anbieter-Verbindungen (connectionId → Kontoname) { startDate: "2025-01-01", // optional: für den Zeitraum "custom" endDate: "2025-06-01", // optional: für den Zeitraum "custom" });
console.log(analytics.summary.totalCost); // 12.34 (Cent)console.log(analytics.byModel[0]); // { model, cost, requests, promptTokens, completionTokens }
---
## Kontingentdurchsetzung
Das Kontingent pro API-Schlüssel wird an zwei Stellen durchgesetzt:
1. **Weiches Limit** (`quotaWarnAt`): Warnung im Dashboard, wenn die Nutzung den Schwellenwert überschreitet2. **Hartes Limit** (`quotaLimit`): Anfrage wird bei Überschreitung mit HTTP 429 abgelehnt
### Konfiguration
```ts// Pro API-Schlüsselawait updateApiKey(keyId, { quotaWarnAt: 5_00, // $5.00 — Warnung anzeigen quotaLimit: 10_00, // $10.00 — harte Begrenzung quotaWindow: "month", // "day" | "week" | "month" | "all"});Durchsetzungsablauf
Abschnitt betitelt „Durchsetzungsablauf“Anfrage ──▶ quotaCheck() │ ├── Innerhalb des Limits? ──▶ zulassen │ └── Limit überschritten? ──▶ 429 Too Many Requests mit Retry-After-HeaderKontingent-Snapshots
Abschnitt betitelt „Kontingent-Snapshots“Die Tabelle quotaSnapshots speichert den historischen Kontingentstatus für Trendanalysen:
| Feld | Beschreibung |
| ———– | —————————————— | —— | —–– |
| apiKeyId | Der verfolgte Schlüssel |
| window | “day” | “week” | “month” |
| used | In diesem Zeitfenster verbrauchte Kosten (Cent) |
| limit | Das Limit (Cent) |
| resetAt | Zeitpunkt, zu dem das Zeitfenster zurückgesetzt wird |
| createdAt | Zeitpunkt, zu dem der Snapshot erstellt wurde |
Snapshots werden bei jeder Anfrage erstellt, deren Kosten > 0 sind, und für Folgendes verwendet:
- Darstellung des Kontingent-Fortschrittsbalkens im Dashboard
- Anzeige von Diagrammen zum Kontingenttrend der letzten 30 Tage
- Auslösung von Warnungen, wenn sich die Nutzung dem Limit nähert
REST-API
Abschnitt betitelt „REST-API“Nutzungsdatensätze auflisten
Abschnitt betitelt „Nutzungsdatensätze auflisten“GET /api/usage?range=7d&limit=100GET /api/usage?apiKeyId=key-123&range=30dGET /api/usage?provider=openai&range=1dAntwort:
{ "records": [ { "id": "uuid", "apiKeyId": "key-123", "provider": "openai", "model": "gpt-5", "promptTokens": 1234, "completionTokens": 567, "totalTokens": 1801, "costUsd": 0.005, "latencyMs": 1234, "status": "success", "timestamp": "2026-06-08T12:00:00Z" } ], "total": 1234, "nextCursor": "..."}Analysezusammenfassung abrufen
Abschnitt betitelt „Analysezusammenfassung abrufen“GET /api/usage/analytics?range=7d&groupBy=modelAntwort:
{ "summary": { "totalCost": 12.34, "totalRequests": 5678, "totalTokens": 12345678, "successRate": 0.987, "avgLatencyMs": 1234 }, "models": [ { "model": "gpt-5", "cost": 8.5, "requests": 1234, "tokens": 4567890 }, { "model": "claude-opus-4-6", "cost": 3.84, "requests": 234, "tokens": 234567 } ], "daily": [ { "date": "2026-06-01", "cost": 1.5, "requests": 800 }, { "date": "2026-06-02", "cost": 2.0, "requests": 1000 } ]}Nutzungsanalysen abfragen
Abschnitt betitelt „Nutzungsanalysen abfragen“Auf Nutzungsdaten wird über das Dashboard oder MCP-Tools zugegriffen, nicht über direkte REST-Export-Endpunkte. Verfügbare Analysen:
/api/usage/analytics— aggregierte Nutzungsmetriken (gruppiert nach Modell, Anbieter, Schlüssel)/api/usage/quota— aktueller Kontingentstatus pro API-Schlüssel/api/usage/history— Protokolle des Anfrageverlaufs
MCP-Tools
Abschnitt betitelt „MCP-Tools“Zwei MCP-Tools stellen Agenten Nutzungsdaten zur Verfügung (siehe open-sse/mcp-server/tools/):
| Tool | Beschreibung |
|---|---|
omniroute_cost_report |
Erstellt einen Kostenbericht pro Schlüssel für einen bestimmten Zeitraum |
omniroute_check_quota |
Gibt den aktuellen Kontingentstatus für einen API-Schlüssel zurück |
Beispiel für einen Agentenaufruf:
{ "tool": "omniroute_cost_report", "args": { "period": "week" }}Aufbewahrung und Bereinigung
Abschnitt betitelt „Aufbewahrung und Bereinigung“Nutzungsdaten wachsen um ca. 1–10 KB pro Anfrage. Bei entsprechender Skalierung kann dies erheblich sein.
Aufbewahrungseinstellungen
Abschnitt betitelt „Aufbewahrungseinstellungen“Die Aufbewahrung des Nutzungsverlaufs wird über die Datenbankeinstellungen in der Benutzeroberfläche oder über /api/settings/database konfiguriert.
Standardmäßig wird der Nutzungsverlauf 90 Tage lang aufbewahrt.
Bereinigung
Abschnitt betitelt „Bereinigung“Alte Datensätze werden durch src/lib/db/cleanup.ts bereinigt:
- Wird durch den Cron-Hintergrundprozess ausgelöst
- Löscht Datensätze aus
usage_history, die älter als die konfigurierte AufbewahrungseinstellungusageHistorysind
Speicherplatzschätzung
Abschnitt betitelt „Speicherplatzschätzung“| Anfragerate | Speicherbedarf für 30 Tage | Speicherbedarf für 90 Tage |
|---|---|---|
| 100 Anfragen/Tag | ~3 MB | ~9 MB |
| 1.000 Anfragen/Tag | ~30 MB | ~90 MB |
| 10.000 Anfragen/Tag | ~300 MB | ~900 MB |
| 100.000 Anfragen/Tag | ~3 GB | ~9 GB |
Bei sehr hohem Datenverkehr sollten Sie Folgendes erwägen:
- Verkürzen des Aufbewahrungszeitraums über die Datenbankeinstellungen
- Verwenden von
aggregated_metricsanstelle von Rohdatensätzen (nur für Analysen)
Tipps zur Kostenoptimierung
Abschnitt betitelt „Tipps zur Kostenoptimierung“1. Das richtige Modell verwenden
Abschnitt betitelt „1. Das richtige Modell verwenden“# Schnelle Antwort — günstig und schnell verwendencurl -d '{"model":"auto/fast","messages":[...]}'
# Komplexe Aufgabe — hohe Qualität verwendencurl -d '{"model":"auto/smart","messages":[...]}'2. Caching aktivieren
Abschnitt betitelt „2. Caching aktivieren“Das Prompt-Caching von Anthropic spart bei wiederholtem Kontext 90 %:
// Das Caching erfolgt automatisch — fügen Sie einfach denselben umfangreichen System-Prompt einconst response = await openai.chat({ model: "claude-sonnet-4-5", system: longSystemPrompt, // Wird automatisch im Cache gespeichert messages: [{ role: "user", content: "..." }],});3. Komprimierung verwenden
Abschnitt betitelt „3. Komprimierung verwenden“Die RTK- und Caveman-Komprimierung spart bei Sitzungen mit intensiver Tool-Nutzung 15–95 %:
const config = { compression: { engine: "rtk", intensity: "aggressive", },};4. Kontingente pro Schlüssel festlegen
Abschnitt betitelt „4. Kontingente pro Schlüssel festlegen“Legen Sie immer quotaLimit fest, um unkontrollierte Kosten zu vermeiden:
await updateApiKey(keyId, { quotaLimit: 10_00 }); // Obergrenze von 10 $/Monat5. Größte Verbraucher prüfen
Abschnitt betitelt „5. Größte Verbraucher prüfen“Verwenden Sie das Dashboard oder /api/usage/analytics, um nach API-Schlüssel zu gruppieren und nach Kosten zu sortieren:
GET /api/usage/analytics?groupBy=apiKeyFehlerbehebung
Abschnitt betitelt „Fehlerbehebung“„Kosten sind höher als erwartet“
Abschnitt betitelt „„Kosten sind höher als erwartet““- Prüfen Sie
/api/usage/analytics?groupBy=model— ermitteln Sie das teure Modell - Prüfen Sie
/api/usage/analytics?groupBy=apiKey— ermitteln Sie den größten Verbraucher - Vergewissern Sie sich, dass die Preisdaten aktuell sind:
POST /api/pricing/sync
„Datensätze fehlen“
Abschnitt betitelt „„Datensätze fehlen““- Prüfen Sie die Einstellungen zur Datenbankaufbewahrung unter Dashboard → Database → Cleanup — alte Datensätze werden durch die regelmäßige Bereinigungsaufgabe (
src/lib/db/cleanup.ts) gelöscht - Prüfen Sie
src/lib/db/usage*.tsauf Fehler — Fehler beim Schreiben in die Datenbank werden protokolliert, aber nicht angezeigt - Vergewissern Sie sich, dass die Anfrage tatsächlich
chatCoreerreicht hat — prüfen Sie das Combo-Routing
„Kontingent wird nicht durchgesetzt“
Abschnitt betitelt „„Kontingent wird nicht durchgesetzt““- Prüfen Sie die Einstellung
quotaLimitdes Schlüssels - Vergewissern Sie sich, dass
quotaWindowkorrekt festgelegt ist - Suchen Sie nach
quotaSnapshots-Datensätzen — sie sollten bei jeder Anfrage erstellt werden
Siehe auch
Abschnitt betitelt „Siehe auch“- DATABASE_GUIDE.md — Schema für Nutzungstabellen
- ENVIRONMENT.md — Umgebungsvariablen für die Preissynchronisierung
- AUTO-COMBO.md — Wie
auto/fastundauto/cheapdie Kosten senken - API_REFERENCE.md — Vollständige Referenz zu
/api/usage/* - Quelle:
open-sse/services/usage.ts,src/lib/usageAnalytics.ts,src/lib/db/usage*.ts
HagiCode
HagiCode ist ein agentischer Coding-Arbeitsplatz mit strukturierten Workflows, Multi-Agent-Ausführung und Hero-Dungeon-Ansichten.
Mit einem intelligenteren, schnelleren und unterhaltsameren agentischen Workflow wird aus Ideen nutzbare Software.

- SmartStrukturierte Workflows machen aus Absichten einen umsetzbaren Weg von der Idee bis zur Auslieferung.
- EfficientMulti-Agent-Workflows führen Recherche, Umsetzung und Prüfung parallel aus.
- FunHero Dungeon macht lange Coding-Sitzungen anschaulich und gemeinschaftlich.