freeleaps-service-hub/apps/metrics/webapi/routes/starrocks_metrics/metrics_query.py

96 lines
3.6 KiB
Python

from fastapi import APIRouter
from typing import Optional, List, Dict, Any
from pydantic import BaseModel, Field
from datetime import date
from common.log.module_logger import ModuleLogger
from backend.services.registration_analytics_service import RegistrationService
class RegistrationDataPoint(BaseModel):
"""Single data point in registration time series."""
date: str = Field(..., description="Date in YYYY-MM-DD format")
value: int = Field(..., description="Number of registered users")
product_id: str = Field(..., description="Product identifier")
class RegistrationTimeSeriesResponse(BaseModel):
"""Response model for registration time series data."""
metric_name: str = Field(..., description="Name of the queried metric")
data_points: List[RegistrationDataPoint] = Field(..., description="List of data points")
total_points: int = Field(..., description="Total number of data points")
time_range: Dict[str, str] = Field(..., description="Start and end date of the query")
total_registrations: int = Field(..., description="Total number of registrations in the period")
class RegistrationQueryRequest(BaseModel):
"""Request model for registration query."""
product_id: str = Field("freeleaps", description="Product ID to identify which product's data to query")
start_date: str = Field(..., description="Start date in YYYY-MM-DD format")
end_date: str = Field(..., description="End date in YYYY-MM-DD format")
router = APIRouter()
# Initialize service and logger
registration_service = RegistrationService()
module_logger = ModuleLogger(__file__)
@router.post("/starrocks/dru_query", response_model=RegistrationTimeSeriesResponse)
async def metrics_query(
request: RegistrationQueryRequest
):
"""
Query registration time series data.
Returns XY curve data (time series) for user registrations within the given date range.
"""
await module_logger.log_info(
f"Querying registration data for product '{request.product_id}' from {request.start_date} to {request.end_date}")
# Parse dates - handle both YYYY-M-D and YYYY-MM-DD formats
def parse_date(date_str: str) -> date:
try:
return date.fromisoformat(date_str)
except ValueError:
# Try to parse YYYY-M-D format and convert to YYYY-MM-DD
parts = date_str.split('-')
if len(parts) == 3:
year, month, day = parts
return date(int(year), int(month), int(day))
raise ValueError(f"Invalid date format: {date_str}")
start_date = parse_date(request.start_date)
end_date = parse_date(request.end_date)
# Query the registration data
result = registration_service.get_daily_registered_users(
start_date=start_date,
end_date=end_date,
product_id=request.product_id
)
# Format response
response = RegistrationTimeSeriesResponse(
metric_name="daily_registered_users",
data_points=[
RegistrationDataPoint(
date=date_str,
value=count,
product_id=request.product_id
)
for date_str, count in zip(result.dates, result.counts)
],
total_points=len(result.dates),
time_range={
"start": request.start_date,
"end": request.end_date
},
total_registrations=result.total_registrations
)
await module_logger.log_info(
f"Successfully queried registration data with {len(result.dates)} data points, total registrations: {result.total_registrations}")
return response