fix(agents): move project metrics endpoint before {agent_id} routes

FastAPI processes routes in order, so /agents/metrics must be defined
before /agents/{agent_id} to prevent "metrics" from being parsed as a UUID.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-31 13:19:53 +01:00
parent 3492941aec
commit d71891ac4e

View File

@@ -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