feat(backend): RBAC admin roles + runtime logs service
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
# =============================================================================
|
||||
# 企微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)
|
||||
Reference in New Issue
Block a user