from datetime import datetime, timedelta from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException, Query from pydantic import BaseModel from sqlalchemy.orm import Session from app.database import get_db from app.models.trigger_log import TriggerLog from app.auth import get_current_user router = APIRouter(prefix="/api/logs", tags=["logs"]) class TriggerLogResponse(BaseModel): id: int repository_name: str branch_name: str commit_sha: str job_name: str status: str error_message: Optional[str] = None created_at: datetime class Config: from_attributes = True @router.get("/", response_model=List[TriggerLogResponse]) async def get_trigger_logs( repository: Optional[str] = Query(None, description="Repository name filter"), branch: Optional[str] = Query(None, description="Branch name filter"), since: Optional[str] = Query(None, description="Since timestamp (RFC3339 format)"), limit: int = Query(100, ge=1, le=1000, description="Maximum number of logs to return"), db: Session = Depends(get_db), current_user: dict = Depends(get_current_user) ): """ 获取触发日志 """ try: # 构建查询 query = db.query(TriggerLog) # 应用过滤器 if repository: query = query.filter(TriggerLog.repository_name == repository) if branch: query = query.filter(TriggerLog.branch_name == branch) if since: try: since_time = datetime.fromisoformat(since.replace('Z', '+00:00')) query = query.filter(TriggerLog.created_at >= since_time) except ValueError: raise HTTPException( status_code=400, detail="Invalid since parameter format (use RFC3339)" ) # 按时间倒序排列并限制数量 logs = query.order_by(TriggerLog.created_at.desc()).limit(limit).all() return logs except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to get trigger logs: {str(e)}") @router.get("/stats") async def get_log_stats( db: Session = Depends(get_db), current_user: dict = Depends(get_current_user) ): """ 获取日志统计信息 """ try: # 总日志数 total_logs = db.query(TriggerLog).count() # 成功和失败的日志数 successful_logs = db.query(TriggerLog).filter(TriggerLog.status == "success").count() failed_logs = db.query(TriggerLog).filter(TriggerLog.status == "failed").count() # 最近24小时的日志数 yesterday = datetime.utcnow() - timedelta(days=1) recent_logs = db.query(TriggerLog).filter(TriggerLog.created_at >= yesterday).count() # 按仓库分组的统计 repo_stats = db.query( TriggerLog.repository_name, db.func.count(TriggerLog.id).label('count') ).group_by(TriggerLog.repository_name).all() return { "total_logs": total_logs, "successful_logs": successful_logs, "failed_logs": failed_logs, "recent_logs_24h": recent_logs, "repository_stats": [ {"repository": repo, "count": count} for repo, count in repo_stats ] } except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to get log stats: {str(e)}")