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.
119 lines
3.3 KiB
Python
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,
|
|
)
|