from fastapi import APIRouter from typing import Optional, List, Dict, Any from pydantic import BaseModel, Field from common.log.module_logger import ModuleLogger from backend.services.prometheus_metrics_service import PrometheusMetricsService class MetricDataPoint(BaseModel): """Single data point in a time series.""" date: str = Field(..., description="Timestamp in ISO format") value: Optional[float] = Field(None, description="Metric value") labels: Optional[Dict[str, str]] = Field(None, description="Metric labels") class MetricTimeSeriesResponse(BaseModel): """Response model for metric time series data.""" metric_name: str = Field(..., description="Name of the queried metric") data_points: List[MetricDataPoint] = 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 time of the query") step: str = Field("1h", description="Query resolution step") class MetricQueryRequest(BaseModel): """Request model for metric query.""" product_id: str = Field(..., description="Product ID to identify which product's metrics to query") metric_name: str = Field(..., description="Name of the metric to query") start_time: str = Field(..., description="Start time in ISO format or RFC3339") end_time: str = Field(..., description="End time in ISO format or RFC3339") step: str = Field("1h", description="Query resolution step (e.g., 1m, 5m, 1h)") router = APIRouter() # Initialize service and logger prometheus_service = PrometheusMetricsService() module_logger = ModuleLogger(__file__) @router.post("/prometheus/metrics_query", response_model=MetricTimeSeriesResponse) async def metrics_query( request: MetricQueryRequest ): """ Query metrics time series data. Returns XY curve data (time series) for the specified metric within the given time range. """ await module_logger.log_info( f"Querying metric '{request.metric_name}' from product '{request.product_id}' from {request.start_time} to {request.end_time}") # Query the metric data data_points = await prometheus_service.query_metric_by_time_range( product_id=request.product_id, metric_name=request.metric_name, start_time=request.start_time, end_time=request.end_time, step=request.step ) # Format response response = MetricTimeSeriesResponse( metric_name=request.metric_name, data_points=[ MetricDataPoint( date=point["date"], value=point["value"], labels=point["labels"] ) for point in data_points ], total_points=len(data_points), time_range={ "start": request.start_time, "end": request.end_time }, step=request.step ) await module_logger.log_info( f"Successfully queried metric '{request.metric_name}' with {len(data_points)} data points") return response