v1.0.0-012 : LLM Quota Monitoring — RPM & RPD Real-Time + Indikator Merah
Menambahkan tampilan sisa kuota RPM dan RPD per model per API key secara real-time dari database log, beserta indikator merah otomatis ketika kuota Gemini Free Tier habis atau terkena HTTP 429.
Sebelumnya, halaman LLM Monitoring hanya menampilkan status supported/unsupported berdasarkan ping sederhana ke Gemini API. Tidak ada informasi berapa sisa kuota RPM (Request Per Minute) dan RPD (Request Per Day) yang tersedia. Jika kuota habis, sistem baru diketahui setelah terjadi error parsing.
Endpoint ini sekarang menghitung pemakaian RPM & RPD secara real-time dari tabel mcp_request_logs:
-- Pemakaian hari ini (RPD)SELECT model_used, COUNT(*) as countFROM mcp_request_logsWHERE created_at >= CURRENT_DATEGROUP BY model_used;
-- Pemakaian dalam 60 detik terakhir (RPM)SELECT model_used, COUNT(*) as countFROM mcp_request_logsWHERE created_at >= NOW() - INTERVAL '1 minute'GROUP BY model_used;Setiap entry key dalam model_keys sekarang berisi:
| Field | Tipe | Keterangan |
|---|---|---|
supported |
boolean | Model tersedia di key ini |
quota_exceeded |
boolean | TRUE jika rem_rpm ≤ 0 atau rem_rpd ≤ 0 atau HTTP 429 |
rpm_display |
string | Format: sisa / limit (contoh: 14 / 15) |
rpd_display |
string | Format: sisa / limit (contoh: 1487 / 1500) |
status_code |
number | HTTP status code dari ping API Gemini |
error_msg |
string | Pesan error jika ping gagal |
| Model | RPM | RPD |
|---|---|---|
gemini-2.5-flash |
15 | 1.500 |
gemini-3.1-flash-lite-preview |
15 | 1.500 |
gemini-3-flash-preview |
15 | 1.500 |
gemini-2.0-flash |
15 | 1.500 |
gemini-1.5-pro |
2 | 50 |
interface KeyStatus { key_name: string; masked_key: string; supported: boolean; quota_exceeded: boolean; // baru status_code: number; // baru error_msg: string; // baru rpm_display: string; // baru rpd_display: string; // baru}
interface ModelKeys { model_name: string; rpm_limit: number; // baru rpd_limit: number; // baru used_rpm: number; // baru used_rpd: number; // baru rem_rpm: number; // baru rem_rpd: number; // baru keys: KeyStatus[];}| Kondisi | Tampilan |
|---|---|
| Model tidak didukung key ini | — (abu-abu) + kode error kecil |
quota_exceeded = true |
🔴 Background merah, badge QUOTA EXCEEDED + RPM/RPD sisa |
supported = true & kuota ada |
🟢 Background hijau, badge READY + RPM/RPD sisa |
| Key aktif yang sedang digunakan | Ring emerald highlight |
Sebuah key dianggap quota exceeded jika salah satu kondisi terpenuhi:
rem_rpm <= 0(pemakaian dalam 60 detik terakhir ≥ limit RPM)rem_rpd <= 0(pemakaian hari ini ≥ limit RPD)- Ping API Gemini mengembalikan HTTP 429
- Pesan error mengandung kata
quotaatauexhausted
Format diubah dari sisa/limit → terpakai/limit agar tidak ambigu:
| Sebelum | Sesudah | Makna |
|---|---|---|
RPM: 15/15 |
RPM: 0/15 |
Baru terpakai 0 dari 15 |
RPD: 1500/1500 |
RPD: 0/1500 |
Baru terpakai 0 dari 1500 |
Format lama 15/15 dibaca “sudah habis semua”, padahal artinya “sisa 15 dari 15”. Format baru 0/15 langsung jelas = baru terpakai 0.
- Hapus teks “READY” — cukup dot hijau/merah sebagai indikator
- 1 baris:
● RPM: 0/15 RPD: 0/1500 - QUOTA EXCEEDED juga 1 baris:
🔴 RPM: 15/15 RPD: 1500/1500
Model yang semua key-nya tidak mendukung (bukan quota exceeded) dihapus dari list agar tabel lebih bersih dan fokus hanya pada model yang relevan.
// Filter: hanya tampilkan model yang minimal 1 key supported atau quota_exceededconst supportedModelRows = data.model_keys.filter(row => row.keys.some(k => k.supported || k.quota_exceeded));| File | Perubahan |
|---|---|
mcp-server/src/index.ts |
Endpoint GET /api/v1/llm-monitoring dengan query RPM/RPD real-time + import pool |
mcp-server/mcp-frontend/src/pages/LlmMonitoring.tsx |
Interface + render sel matrix: badge merah, format used/limit, hapus “READY”, filter model tidak didukung |