From 5c269bf243b450d8f3218244268b0b2c0fbd696b Mon Sep 17 00:00:00 2001 From: inference-bot Date: Sat, 26 Sep 2026 16:09:38 -0600 Subject: [PATCH] Support ?days=N filter on /admin/model-usage --- app/main.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/app/main.py b/app/main.py index 1a22700..2d56eba 100644 --- a/app/main.py +++ b/app/main.py @@ -1320,16 +1320,24 @@ async def admin_overview(request: Request): @app.get("/admin/model-usage") @limiter.limit("30/minute") -async def admin_model_usage(request: Request): +async def admin_model_usage(request: Request, days: int = 0): """Co-op-wide per-model usage from LiteLLM spend logs. - Authenticated by the X-Admin-Token header. Aggregates every spend-log row + Authenticated by the X-Admin-Token header. Aggregates spend-log rows (across ALL members) by model: total spend, tokens, and request count, - sorted by spend descending. No per-member breakdown — this is co-op-level + sorted by spend descending. Optional ?days=N limits to the last N days + (0 or omitted = all-time). No per-member breakdown — this is co-op-level so admins can see which models the membership actually uses. """ _verify_admin_token(request) + cutoff = None + if days and days > 0: + from datetime import datetime, timedelta, timezone + cutoff = (datetime.now(timezone.utc) - timedelta(days=days)).strftime( + "%Y-%m-%dT%H:%M:%S" + ) + models = {} total_spend = 0.0 total_tokens = 0 @@ -1350,6 +1358,10 @@ async def admin_model_usage(request: Request): # raw `model` field holds messy upstream/internal names. Older # rows predating the alias convention have model_group empty, # so fall back to `model` for those. + if cutoff: + started = str(row.get("startTime") or "") + if started and started < cutoff: + continue model = row.get("model_group") or row.get("model") or "unknown" m = models.setdefault(model, {"spend": 0.0, "tokens": 0, "requests": 0}) m["spend"] += float(row.get("spend") or 0.0)