freeleaps-service-hub/apps/metrics/webapi/routes/registration_metrics.py
weicao 35fbda6954 Refactor metrics service: rename files for better readability
- Rename starrocks_client.py -> database_client.py
- Rename daily_registered_users.py -> user_registration_models.py
- Rename daily_registration_service.py -> registration_analytics_service.py
- Rename daily_registration.py -> registration_metrics.py
- Rename site_settings.py -> app_settings.py
- Rename application.py -> app_factory.py
- Update all import statements and references
- Update README.md with new file structure
2025-09-15 16:31:20 +08:00

230 lines
8.2 KiB
Python

from fastapi import APIRouter, HTTPException, Query
from datetime import date, datetime, timedelta
from typing import Optional
from loguru import logger
from backend.services.registration_analytics_service import RegistrationService
from backend.models.user_registration_models import UserRegistrationResponse, UserRegistrationQuery
router = APIRouter(prefix="/api/metrics", tags=["registration"])
# Initialize service
registration_service = RegistrationService()
@router.get("/daily-registered-users", response_model=UserRegistrationResponse)
async def get_daily_registered_users(
start_date: date = Query(..., description="Start date in YYYY-MM-DD format"),
end_date: date = Query(..., description="End date in YYYY-MM-DD format"),
product_id: str = Query("freeleaps", description="Product identifier")
):
"""
Get daily registered users count for a date range
Returns two lists:
- dates: List of dates in YYYY-MM-DD format
- counts: List of daily registration counts
Example:
- GET /api/metrics/daily-registered-users?start_date=2024-01-01&end_date=2024-01-07
"""
try:
# Validate date range
if start_date > end_date:
raise HTTPException(
status_code=400,
detail="Start date must be before or equal to end date"
)
# Check date range is not too large (max 1 year)
if (end_date - start_date).days > 365:
raise HTTPException(
status_code=400,
detail="Date range cannot exceed 365 days"
)
logger.info(f"Querying registration data from {start_date} to {end_date} for product {product_id}")
# Get data from service
result = registration_service.get_daily_registered_users(
start_date, end_date, product_id
)
logger.info(f"Successfully retrieved data for {len(result.dates)} days")
return result
except HTTPException:
raise
except Exception as e:
logger.error(f"Failed to get daily registered users: {e}")
raise HTTPException(
status_code=500,
detail=f"Internal server error: {str(e)}"
)
@router.get("/registration-summary")
async def get_registration_summary(
start_date: date = Query(..., description="Start date in YYYY-MM-DD format"),
end_date: date = Query(..., description="End date in YYYY-MM-DD format"),
product_id: str = Query("freeleaps", description="Product identifier")
):
"""
Get summary statistics for user registrations in a date range
Returns summary statistics including:
- total_registrations: Total number of registrations
- average_daily: Average daily registrations
- max_daily: Maximum daily registrations
- min_daily: Minimum daily registrations
- days_with_registrations: Number of days with registrations
- total_days: Total number of days in range
"""
try:
# Validate date range
if start_date > end_date:
raise HTTPException(
status_code=400,
detail="Start date must be before or equal to end date"
)
if (end_date - start_date).days > 365:
raise HTTPException(
status_code=400,
detail="Date range cannot exceed 365 days"
)
logger.info(f"Querying registration summary from {start_date} to {end_date} for product {product_id}")
# Get summary from service
summary = registration_service.get_registration_summary(
start_date, end_date, product_id
)
return summary
except HTTPException:
raise
except Exception as e:
logger.error(f"Failed to get registration summary: {e}")
raise HTTPException(
status_code=500,
detail=f"Internal server error: {str(e)}"
)
@router.get("/recent-registered-users", response_model=UserRegistrationResponse)
async def get_recent_registered_users(
days: int = Query(7, ge=1, le=365, description="Number of recent days to query"),
product_id: str = Query("freeleaps", description="Product identifier")
):
"""
Get daily registered users count for recent N days
Returns registration data for the last N days from today
Example:
- GET /api/metrics/recent-registered-users?days=7
- GET /api/metrics/recent-registered-users?days=30&product_id=freeleaps
"""
try:
# Calculate date range
end_date = date.today()
start_date = end_date - timedelta(days=days-1)
logger.info(f"Querying recent {days} days registration data from {start_date} to {end_date} for product {product_id}")
# Get data from service
result = registration_service.get_daily_registered_users(
start_date, end_date, product_id
)
logger.info(f"Successfully retrieved recent {days} days data, total registrations: {result.total_registrations}")
return result
except Exception as e:
logger.error(f"Failed to get recent registered users: {e}")
raise HTTPException(
status_code=500,
detail=f"Internal server error: {str(e)}"
)
@router.get("/registered-users-by-days", response_model=UserRegistrationResponse)
async def get_registered_users_by_days(
start_date: date = Query(..., description="Start date in YYYY-MM-DD format"),
days: int = Query(..., ge=1, le=365, description="Number of days from start date"),
product_id: str = Query("freeleaps", description="Product identifier")
):
"""
Get daily registered users count starting from a specific date for N days
Returns registration data for N days starting from the specified start date
Example:
- GET /api/metrics/registered-users-by-days?start_date=2024-01-01&days=7
- GET /api/metrics/registered-users-by-days?start_date=2024-09-01&days=30&product_id=freeleaps
"""
try:
# Calculate end date
end_date = start_date + timedelta(days=days-1)
logger.info(f"Querying registration data from {start_date} for {days} days (until {end_date}) for product {product_id}")
# Get data from service
result = registration_service.get_daily_registered_users(
start_date, end_date, product_id
)
logger.info(f"Successfully retrieved {days} days data from {start_date}, total registrations: {result.total_registrations}")
return result
except Exception as e:
logger.error(f"Failed to get registered users by days: {e}")
raise HTTPException(
status_code=500,
detail=f"Internal server error: {str(e)}"
)
@router.post("/daily-registered-users", response_model=UserRegistrationResponse)
async def get_daily_registered_users_post(
query: UserRegistrationQuery
):
"""
Get daily registered users count for a date range (POST method)
Same as GET method but accepts parameters in request body
"""
try:
# Validate date range
if query.start_date > query.end_date:
raise HTTPException(
status_code=400,
detail="Start date must be before or equal to end date"
)
if (query.end_date - query.start_date).days > 365:
raise HTTPException(
status_code=400,
detail="Date range cannot exceed 365 days"
)
logger.info(f"Querying registration data from {query.start_date} to {query.end_date} for product {query.product_id}")
# Get data from service
result = registration_service.get_daily_registered_users(
query.start_date, query.end_date, query.product_id
)
logger.info(f"Successfully retrieved data for {len(result.dates)} days")
return result
except HTTPException:
raise
except Exception as e:
logger.error(f"Failed to get daily registered users: {e}")
raise HTTPException(
status_code=500,
detail=f"Internal server error: {str(e)}"
)