diff --git a/backend/app/api/routes/agents.py b/backend/app/api/routes/agents.py index 78a2991..7ed9ac1 100644 --- a/backend/app/api/routes/agents.py +++ b/backend/app/api/routes/agents.py @@ -363,6 +363,73 @@ async def list_project_agents( raise +# ===== Project Agent Metrics Endpoint ===== +# NOTE: This endpoint MUST be defined before /{agent_id} routes +# to prevent FastAPI from trying to parse "metrics" as a UUID + + +@router.get( + "/projects/{project_id}/agents/metrics", + response_model=AgentInstanceMetrics, + summary="Get Project Agent Metrics", + description="Get aggregated usage metrics for all agents in a project.", + operation_id="get_project_agent_metrics", +) +@limiter.limit(f"{60 * RATE_MULTIPLIER}/minute") +async def get_project_agent_metrics( + request: Request, + project_id: UUID, + current_user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +) -> Any: + """ + Get aggregated usage metrics for all agents in a project. + + Returns aggregated metrics across all agents including total + tasks completed, tokens used, and cost incurred. + + Args: + request: FastAPI request object (for rate limiting) + project_id: UUID of the project + current_user: Current authenticated user + db: Database session + + Returns: + AgentInstanceMetrics: Aggregated project agent metrics + + Raises: + NotFoundError: If the project is not found + AuthorizationError: If the user lacks access to the project + """ + try: + # Verify project access + project = await verify_project_access(db, project_id, current_user) + + # Get aggregated metrics for the project + metrics = await agent_instance_crud.get_project_metrics( + db, project_id=project_id + ) + + logger.debug( + f"User {current_user.email} retrieved project metrics for {project.slug}" + ) + + return AgentInstanceMetrics( + total_instances=metrics["total_instances"], + active_instances=metrics["active_instances"], + idle_instances=metrics["idle_instances"], + total_tasks_completed=metrics["total_tasks_completed"], + total_tokens_used=metrics["total_tokens_used"], + total_cost_incurred=metrics["total_cost_incurred"], + ) + + except (NotFoundError, AuthorizationError): + raise + except Exception as e: + logger.error(f"Error getting project agent metrics: {e!s}", exc_info=True) + raise + + @router.get( "/projects/{project_id}/agents/{agent_id}", response_model=AgentInstanceResponse, @@ -908,65 +975,3 @@ async def get_agent_metrics( except Exception as e: logger.error(f"Error getting agent metrics: {e!s}", exc_info=True) raise - - -@router.get( - "/projects/{project_id}/agents/metrics", - response_model=AgentInstanceMetrics, - summary="Get Project Agent Metrics", - description="Get aggregated usage metrics for all agents in a project.", - operation_id="get_project_agent_metrics", -) -@limiter.limit(f"{60 * RATE_MULTIPLIER}/minute") -async def get_project_agent_metrics( - request: Request, - project_id: UUID, - current_user: User = Depends(get_current_user), - db: AsyncSession = Depends(get_db), -) -> Any: - """ - Get aggregated usage metrics for all agents in a project. - - Returns aggregated metrics across all agents including total - tasks completed, tokens used, and cost incurred. - - Args: - request: FastAPI request object (for rate limiting) - project_id: UUID of the project - current_user: Current authenticated user - db: Database session - - Returns: - AgentInstanceMetrics: Aggregated project agent metrics - - Raises: - NotFoundError: If the project is not found - AuthorizationError: If the user lacks access to the project - """ - try: - # Verify project access - project = await verify_project_access(db, project_id, current_user) - - # Get aggregated metrics for the project - metrics = await agent_instance_crud.get_project_metrics( - db, project_id=project_id - ) - - logger.debug( - f"User {current_user.email} retrieved project metrics for {project.slug}" - ) - - return AgentInstanceMetrics( - total_instances=metrics["total_instances"], - active_instances=metrics["active_instances"], - idle_instances=metrics["idle_instances"], - total_tasks_completed=metrics["total_tasks_completed"], - total_tokens_used=metrics["total_tokens_used"], - total_cost_incurred=metrics["total_cost_incurred"], - ) - - except (NotFoundError, AuthorizationError): - raise - except Exception as e: - logger.error(f"Error getting project agent metrics: {e!s}", exc_info=True) - raise