Files
gemini-balance/app/router/log_routes.py
T
snaily 69261e98de feat(error_logs): 添加错误日志搜索和日期过滤功能
- 在后端 (`services.py`, `log_routes.py`) 实现按 Gemini 密钥(模糊匹配)、错误类型/内容(模糊匹配)和日期范围(开始/结束日期)过滤错误日志的逻辑。
- 添加新函数 `get_error_logs_count` 以高效获取符合过滤条件的总日志数,用于分页。
- 更新 `/api/logs/errors` API 端点以接受 `key_search`, `error_search`, `start_date`, `end_date` 查询参数。端点现在返回包含过滤后日志和总数的对象。
- 增强前端 (`error_logs.html`, `error_logs.js`, `error_logs.css`):
    - 添加用于密钥搜索、错误/日志搜索和日期范围选择的输入字段。
    - 实现 JavaScript 逻辑以捕获搜索参数,使用过滤器触发 API 调用,并在新搜索时重置到第一页。
    - 更新表格渲染以显示顺序行号而非数据库 ID。
    - 在表格视图中遮罩 Gemini 密钥(显示前/后 4 个字符)以提高可读性,同时仍在详细信息模态框中显示完整密钥。
    - 优化新搜索控件、表格外观(内边距、边框、悬停效果、斑马条纹)和按钮样式的 CSS,以提供更清晰的用户界面。
- 通过使用 `logger.exception` 包含堆栈跟踪来改进后端服务中的错误日志记录。
2025-04-10 19:16:06 +08:00

72 lines
2.5 KiB
Python

"""
日志路由模块
"""
from typing import Any, Dict, List, Optional
from datetime import date
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[date] = Query(None, description="Start date for filtering (YYYY-MM-DD)"),
end_date: Optional[date] = Query(None, description="End date for filtering (YYYY-MM-DD)")
):
"""
获取错误日志
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)}")