Files
gemini-balance/app/router/log_routes.py
snaily 51bb71bdb5 ```git
feat: 添加密钥检查调度器并重构前端UI

主要变更:

- **调度器功能:**
    - 集成 APScheduler 实现定时任务,用于定期检查API密钥的有效性。
    - 在 `.env.example` 和 `app/config/config.py` 中添加了 `CHECK_INTERVAL_HOURS` 和 `TIMEZONE` 配置项。
    - 在应用生命周期 (`app/core/application.py`) 中添加了调度器的启动和停止逻辑。
    - 新增 `app/scheduler/` 目录及相关实现 (`key_checker.py`)。
    - 新增 `app/router/scheduler_routes.py` 用于调度器相关API (如果未来需要)。
    - 在 `requirements.txt` 中添加 `apscheduler` 依赖。

- **前端重构与改进:**
    - 引入 `app/templates/base.html` 作为基础模板,统一页面结构和样式引入。
    - 使用新的样式(推测为Tailwind CSS)重构了 `auth.html`, `config_editor.html`, `error_logs.html`, `keys_status.html` 页面,提升了UI一致性和响应式布局。
    - 删除了旧的CSS文件 (`auth.css`, `config_editor.css`, `error_logs.css`, `keys_status.css`)。
    - 更新了对应的 JavaScript 文件 (`config_editor.js`, `error_logs.js`, `keys_status.js`) 以适应新的HTML结构和交互。
    - 在 `keys_status.html` 页面增加了按失败次数过滤密钥、批量重置失败次数、确认模态框等功能。
    - 添加了新的 Logo 图片 (`logo.png`, `logo1.png`)。

- **其他:**
    - 更新了 `app/router/routes.py` 以包含新的路由。
    - 对 `app/service/key/key_manager.py` 和 `app/database/services.py` 进行了相关调整以支持新功能。
```
2025-04-11 03:16:51 +08:00

72 lines
2.6 KiB
Python

"""
日志路由模块
"""
from typing import Any, Dict, List, Optional
from datetime import datetime
from pydantic import BaseModel
from fastapi import APIRouter, HTTPException, Request, Query
from fastapi.responses import RedirectResponse
from app.core.security import verify_auth_token
from app.log.logger import get_log_routes_logger
from app.database.services import get_error_logs, get_error_logs_count
# 创建路由
router = APIRouter(prefix="/api/logs", tags=["logs"])
logger = get_log_routes_logger()
# Define a response model that includes the total count for pagination
class ErrorLogResponse(BaseModel):
logs: List[Dict[str, Any]]
total: int
@router.get("/errors", response_model=ErrorLogResponse)
async def get_error_logs_api(
request: Request,
limit: int = Query(20, ge=1, le=1000), # Default to 20 to match frontend
offset: int = Query(0, ge=0),
key_search: Optional[str] = Query(None, description="Search term for Gemini key (partial match)"),
error_search: Optional[str] = Query(None, description="Search term for error type or log message"),
start_date: Optional[datetime] = Query(None, description="Start datetime for filtering (YYYY-MM-DDTHH:MM)"),
end_date: Optional[datetime] = Query(None, description="End datetime for filtering (YYYY-MM-DDTHH:MM)")
):
"""
获取错误日志
Args:
request: 请求对象
limit: 限制数量
offset: 偏移量
Returns:
ErrorLogResponse: An object containing the list of logs and the total count.
"""
auth_token = request.cookies.get("auth_token")
if not auth_token or not verify_auth_token(auth_token):
logger.warning("Unauthorized access attempt to error logs")
return RedirectResponse(url="/", status_code=302)
try:
# Fetch logs with search parameters
logs = await get_error_logs(
limit=limit,
offset=offset,
key_search=key_search,
error_search=error_search,
start_date=start_date,
end_date=end_date
)
# Fetch total count with the same search parameters
total_count = await get_error_logs_count(
key_search=key_search,
error_search=error_search,
start_date=start_date,
end_date=end_date
)
return ErrorLogResponse(logs=logs, total=total_count)
except Exception as e:
logger.exception(f"Failed to get error logs: {str(e)}") # Use logger.exception for stack trace
raise HTTPException(status_code=500, detail=f"Failed to get error logs: {str(e)}")