Files

72 lines
2.9 KiB
Python
Raw Permalink Normal View History

# =============================================================================
# 企微IT智能服务台 — 运行期日志 API (standard SOP 第三阶段)
# =============================================================================
# 说明:管理后台查看后端运行期日志
# GET /admin/runtime-logs 正常查询(分页 + 级别/时间/关键字筛选)
# GET /admin/runtime-logs?download=true 下载命中行(text/plain 附件)
# 权限:require_admin(非 admin 返回 403,由依赖装饰器强制)
# =============================================================================
import logging
from datetime import datetime
from typing import Optional
from fastapi import APIRouter, Depends, Query
from fastapi.responses import StreamingResponse
from app.dependencies import require_admin, get_current_user, UserInfo
from app.services.runtime_log_service import (
iter_runtime_log_lines,
query_runtime_logs,
)
from app.utils.response import success_response
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/admin/runtime-logs", tags=["运行期日志"])
@router.get("")
@require_admin
async def get_runtime_logs(
level: str = Query("INFO", description="日志级别阈值(DEBUG/INFO/WARNING/ERROR/CRITICAL),返回 >= 该级别"),
from_time: Optional[datetime] = Query(None, alias="from", description="起始时间(ISO8601)"),
to_time: Optional[datetime] = Query(None, alias="to", description="结束时间(ISO8601)"),
keyword: Optional[str] = Query(None, description="按消息关键字子串筛选(大小写不敏感)"),
page: int = Query(1, ge=1, description="页码"),
page_size: int = Query(50, ge=1, le=500, description="每页条数"),
download: bool = Query(False, description="true 时返回命中行文本下载"),
current_user: UserInfo = Depends(get_current_user),
):
"""查询后端运行期日志(分页 + 级别/时间/关键字筛选)。
权限:仅 admin 角色可访问,非 admin 由 require_admin 装饰器返回 403。
"""
# 下载模式:流式返回命中行文本,触发浏览器文件下载
if download:
ts = datetime.now().strftime("%Y%m%d-%H%M%S")
headers = {
"Content-Disposition": f'attachment; filename="runtime-logs-{ts}.log"'
}
return StreamingResponse(
iter_runtime_log_lines(
level=level,
from_time=from_time,
to_time=to_time,
keyword=keyword,
),
media_type="text/plain; charset=utf-8",
headers=headers,
)
# 普通查询:分页返回结构化条目
result = await query_runtime_logs(
level=level,
from_time=from_time,
to_time=to_time,
keyword=keyword,
page=page,
page_size=page_size,
)
return success_response(data=result)