freeleaps-ops/apps/gitea-webhook-ambassador-python/app/handlers/logs.py
Nicolas f6c515157c feat: 添加 Python 版本的 Gitea Webhook Ambassador
- 新增完整的 Python 实现,替代 Go 版本
- 添加 Web 登录界面和仪表板
- 实现 JWT 认证和 API 密钥管理
- 添加数据库存储功能
- 保持与 Go 版本一致的目录结构和启动脚本
- 包含完整的文档和测试脚本
2025-07-20 21:17:10 +08:00

106 lines
3.5 KiB
Python

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)}")