Files
openrouter-watcher/src/openrouter_monitor/routers/stats.py
Luca Sacchi Ricciardi 16f740f023 feat(stats): T32-T33 implement dashboard and usage endpoints
Add statistics router with two endpoints:
- GET /api/stats/dashboard: Aggregated dashboard statistics
  - Query param: days (1-365, default 30)
  - Auth required
  - Returns DashboardResponse

- GET /api/usage: Detailed usage statistics with filtering
  - Required params: start_date, end_date
  - Optional filters: api_key_id, model
  - Pagination: skip, limit (max 1000)
  - Auth required
  - Returns List[UsageStatsResponse]

Also add get_usage_stats() service function for querying
individual usage records with filtering and pagination.
2026-04-07 15:22:31 +02:00

119 lines
3.3 KiB
Python

"""Statistics router for OpenRouter API Key Monitor.
T32-T33: Stats endpoints for dashboard and usage data.
"""
from datetime import date
from typing import List, Optional
from fastapi import APIRouter, Depends, Query, status
from sqlalchemy.orm import Session
from openrouter_monitor.database import get_db
from openrouter_monitor.dependencies import get_current_user
from openrouter_monitor.models import User
from openrouter_monitor.schemas.stats import (
DashboardResponse,
UsageStatsResponse,
)
from openrouter_monitor.services.stats import (
get_dashboard_data,
get_usage_stats,
)
router = APIRouter(prefix="/api", tags=["statistics"])
@router.get(
"/stats/dashboard",
response_model=DashboardResponse,
status_code=status.HTTP_200_OK,
summary="Get dashboard statistics",
description="Get aggregated statistics for the dashboard view.",
)
async def get_dashboard(
days: int = Query(
default=30,
ge=1,
le=365,
description="Number of days to look back (1-365)",
),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
) -> DashboardResponse:
"""Get dashboard statistics for the current user.
Args:
days: Number of days to look back (default 30, max 365)
db: Database session
current_user: Authenticated user
Returns:
DashboardResponse with summary, by_model, by_date, and top_models
"""
return get_dashboard_data(db, current_user.id, days)
@router.get(
"/usage",
response_model=List[UsageStatsResponse],
status_code=status.HTTP_200_OK,
summary="Get detailed usage statistics",
description="Get detailed usage statistics with filtering and pagination.",
)
async def get_usage(
start_date: date = Query(
...,
description="Start date for the query (YYYY-MM-DD)",
),
end_date: date = Query(
...,
description="End date for the query (YYYY-MM-DD)",
),
api_key_id: Optional[int] = Query(
default=None,
description="Filter by specific API key ID",
),
model: Optional[str] = Query(
default=None,
description="Filter by model name",
),
skip: int = Query(
default=0,
ge=0,
description="Number of records to skip for pagination",
),
limit: int = Query(
default=100,
ge=1,
le=1000,
description="Maximum number of records to return (1-1000)",
),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
) -> List[UsageStatsResponse]:
"""Get detailed usage statistics with filtering.
Args:
start_date: Start date for the query period (required)
end_date: End date for the query period (required)
api_key_id: Optional filter by API key ID
model: Optional filter by model name
skip: Number of records to skip (pagination)
limit: Maximum number of records to return
db: Database session
current_user: Authenticated user
Returns:
List of UsageStatsResponse matching the filters
"""
return get_usage_stats(
db=db,
user_id=current_user.id,
start_date=start_date,
end_date=end_date,
api_key_id=api_key_id,
model=model,
skip=skip,
limit=limit,
)