- Add complete metrics microservice structure - Implement StarRocks database integration - Add user registration data query APIs: - Daily registered users by date range - Recent N days registration data - Registration data by start date and days - Registration summary statistics - Add comprehensive error handling and logging - Include test scripts and documentation
230 lines
8.1 KiB
Python
230 lines
8.1 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_service import RegistrationService
|
|
from backend.models.registered_users 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)}"
|
|
)
|