feat(stats): per-user API quota attribution + admin usage page
Track who burned how much YouTube API quota. A QuotaEvent audit log (migration 0009) records every spend with the triggering user (NULL = background/system) and an action label, set via a request/job-scoped contextvar (quota.attribute) so no call signatures change. User-initiated work (sync subscriptions, unsubscribe, opt-in recent backfill, manual enrich) attributes to the user; scheduler work to System, split by action. - backend: QuotaEvent model + migration 0009; quota.attribute() contextvar; record_usage logs events; entry points wrapped (routes/sync, routes/channels, scheduler); GET /api/quota/my-usage + GET /api/quota/admin - frontend: admin-only Stats page (header nav, page=stats) with daily bars + per-user breakdown by action and range picker; 'Your API usage' in Settings -> Sync for every user Verified: attribution + endpoints compute correctly; events are per-user vs System.
This commit is contained in:
parent
0dad71cf6e
commit
d610647d13
15 changed files with 451 additions and 26 deletions
|
|
@ -26,7 +26,7 @@ from starlette.middleware.sessions import SessionMiddleware
|
|||
|
||||
from app import auth
|
||||
from app.config import settings
|
||||
from app.routes import admin, channels, feed, health, me, sync, tags
|
||||
from app.routes import admin, channels, feed, health, me, quota, sync, tags
|
||||
from app.scheduler import shutdown_scheduler, start_scheduler
|
||||
|
||||
|
||||
|
|
@ -67,6 +67,7 @@ app.include_router(feed.router)
|
|||
app.include_router(me.router)
|
||||
app.include_router(channels.router)
|
||||
app.include_router(admin.router)
|
||||
app.include_router(quota.router)
|
||||
|
||||
# The built SPA (populated by the Docker frontend build stage).
|
||||
STATIC_DIR = Path(__file__).parent / "static_spa"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue