Files
planet/backend/app/api/v1/alerts.py
2026-03-05 11:46:58 +08:00

125 lines
3.6 KiB
Python

from datetime import datetime
from typing import Optional
from fastapi import APIRouter, Depends
from sqlalchemy import select, func, case
from sqlalchemy.ext.asyncio import AsyncSession
from app.db.session import get_db
from app.models.user import User
from app.core.security import get_current_user
from app.models.alert import Alert, AlertSeverity, AlertStatus
router = APIRouter()
@router.get("")
async def list_alerts(
severity: str = None,
status: str = None,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
query = select(Alert)
if severity:
query = query.where(Alert.severity == AlertSeverity(severity))
if status:
query = query.where(Alert.status == AlertStatus(status))
query = query.order_by(
case(
(Alert.severity == AlertSeverity.CRITICAL, 1),
(Alert.severity == AlertSeverity.WARNING, 2),
(Alert.severity == AlertSeverity.INFO, 3),
),
Alert.created_at.desc(),
)
result = await db.execute(query)
alerts = result.scalars().all()
total_query = select(func.count(Alert.id))
if severity:
total_query = total_query.where(Alert.severity == AlertSeverity(severity))
if status:
total_query = total_query.where(Alert.status == AlertStatus(status))
total_result = await db.execute(total_query)
total = total_result.scalar()
return {
"total": total,
"data": [alert.to_dict() for alert in alerts],
}
@router.post("/{alert_id}/acknowledge")
async def acknowledge_alert(
alert_id: int,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
result = await db.execute(select(Alert).where(Alert.id == alert_id))
alert = result.scalar_one_or_none()
if not alert:
return {"error": "Alert not found"}
alert.status = AlertStatus.ACKNOWLEDGED
alert.acknowledged_by = current_user.id
alert.acknowledged_at = datetime.utcnow()
await db.commit()
return {"message": "Alert acknowledged", "alert": alert.to_dict()}
@router.post("/{alert_id}/resolve")
async def resolve_alert(
alert_id: int,
resolution: str,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
result = await db.execute(select(Alert).where(Alert.id == alert_id))
alert = result.scalar_one_or_none()
if not alert:
return {"error": "Alert not found"}
alert.status = AlertStatus.RESOLVED
alert.resolved_by = current_user.id
alert.resolved_at = datetime.utcnow()
alert.resolution_notes = resolution
await db.commit()
return {"message": "Alert resolved", "alert": alert.to_dict()}
@router.get("/stats")
async def get_alert_stats(
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
critical_query = select(func.count(Alert.id)).where(
Alert.severity == AlertSeverity.CRITICAL,
Alert.status == AlertStatus.ACTIVE,
)
warning_query = select(func.count(Alert.id)).where(
Alert.severity == AlertSeverity.WARNING,
Alert.status == AlertStatus.ACTIVE,
)
info_query = select(func.count(Alert.id)).where(
Alert.severity == AlertSeverity.INFO,
Alert.status == AlertStatus.ACTIVE,
)
critical_result = await db.execute(critical_query)
warning_result = await db.execute(warning_query)
info_result = await db.execute(info_query)
return {
"critical": critical_result.scalar() or 0,
"warning": warning_result.scalar() or 0,
"info": info_result.scalar() or 0,
}