From 0ef41c6cdecf18c444010dd6fdc14e5c3a015728 Mon Sep 17 00:00:00 2001 From: zy7y <13271962515@163.com> Date: Wed, 14 Jun 2023 19:52:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86=E3=80=81=E4=BD=BF=E7=94=A8?= =?UTF-8?q?route=5Fclass=E8=AE=B0=E5=BD=95=E8=AF=B7=E6=B1=82=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/core/exceptions.py | 18 +++++++++++++++++- backend/core/log.py | 9 ++++++++- backend/core/middleware.py | 30 +++++++++++++++++++++++++++++- backend/router/auth.py | 3 ++- backend/router/menu.py | 3 ++- backend/router/role.py | 3 ++- backend/router/user.py | 3 ++- 7 files changed, 62 insertions(+), 7 deletions(-) diff --git a/backend/core/exceptions.py b/backend/core/exceptions.py index 9e9762f..c15d295 100644 --- a/backend/core/exceptions.py +++ b/backend/core/exceptions.py @@ -2,6 +2,8 @@ from fastapi.exceptions import HTTPException from starlette.requests import Request from starlette.responses import JSONResponse +from core.log import logger + class TokenAuthFailure(HTTPException): pass @@ -19,4 +21,18 @@ async def http_exception(request: Request, exc: HTTPException): ) -exception_handlers = {HTTPException: http_exception} +async def global_exception(request: Request, exc): + if hasattr(request.state, "request_id"): + request_id = request.state.request_id + else: + request_id = None + logger.info("request_id 获取失败 请确认对应APIRouter使用了route_class=LogRoute ") + logger.exception(f"{request_id} Exception Log: {exc}") + return JSONResponse({ + "msg": str(exc), + "code": 500, + "data": None + }) + + +exception_handlers = {Exception: global_exception, HTTPException: http_exception} diff --git a/backend/core/log.py b/backend/core/log.py index abd9b05..cf15bce 100644 --- a/backend/core/log.py +++ b/backend/core/log.py @@ -2,7 +2,14 @@ import logging logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) -handler = logging.StreamHandler() + +# 创建一个 FileHandler,用于写入日志文件 +handler = logging.FileHandler('log_file.log') +handler.setLevel(logging.INFO) + +# 设置日志格式 formatter = logging.Formatter("[%(asctime)s] %(levelname)s %(message)s") handler.setFormatter(formatter) + +# 添加 FileHandler 到日志处理器中 logger.addHandler(handler) diff --git a/backend/core/middleware.py b/backend/core/middleware.py index 9687341..c258926 100644 --- a/backend/core/middleware.py +++ b/backend/core/middleware.py @@ -1,10 +1,18 @@ +import time +import uuid +from typing import Callable + from fastapi.middleware import Middleware from fastapi.middleware.cors import CORSMiddleware +from fastapi.routing import APIRoute from starlette.middleware.base import BaseHTTPMiddleware +from starlette.requests import Request +from starlette.responses import Response from core.log import logger +# fix: 中间件没法获取到request 请求体数据 响应体 class CustomRequestLogMiddleware(BaseHTTPMiddleware): async def dispatch(self, request, call_next): logger.info( @@ -16,8 +24,28 @@ class CustomRequestLogMiddleware(BaseHTTPMiddleware): return response +class LogRoute(APIRoute): + def get_route_handler(self) -> Callable: + original_route_handler = super().get_route_handler() + + async def custom_route_handler(request: Request) -> Response: + request_id = str(uuid.uuid4()) + request.state.request_id = request_id + logger.info(f"{request_id} Request Log {request.client} {request.method}" + f" {request.url} {request.headers}\n {await request.body()}") + before = time.time() + response: Response = await original_route_handler(request) + duration = time.time() - before + response.headers["X-Response-Time"] = str(duration) + logger.info(f"{request_id} Response Log {duration}s {response.headers}\n" + f" {response.body.decode('utf-8')}") + return response + + return custom_route_handler + + middlewares = [ - Middleware(CustomRequestLogMiddleware), + # Middleware(CustomRequestLogMiddleware), Middleware( CORSMiddleware, allow_origins=["*"], diff --git a/backend/router/auth.py b/backend/router/auth.py index 8c53b9b..409ef6c 100644 --- a/backend/router/auth.py +++ b/backend/router/auth.py @@ -1,9 +1,10 @@ from fastapi import APIRouter, WebSocket +from core.middleware import LogRoute from schemas import common as BaseSchema from service import auth as AuthService -router = APIRouter(tags=["公共"]) +router = APIRouter(tags=["公共"], route_class=LogRoute) LoginResult = BaseSchema.Response[BaseSchema.LoginResult] diff --git a/backend/router/menu.py b/backend/router/menu.py index daa9c44..70ffa87 100644 --- a/backend/router/menu.py +++ b/backend/router/menu.py @@ -1,10 +1,11 @@ from fastapi import APIRouter +from core.middleware import LogRoute from schemas import common as BaseSchema from schemas import menu as MenuSchema from service.menu import service as MenuService -router = APIRouter(prefix="/menu", tags=["菜单管理"]) +router = APIRouter(prefix="/menu", tags=["菜单管理"], route_class=LogRoute) Response = BaseSchema.Response diff --git a/backend/router/role.py b/backend/router/role.py index e638f65..4dbc62b 100644 --- a/backend/router/role.py +++ b/backend/router/role.py @@ -1,12 +1,13 @@ from fastapi import APIRouter, Depends from typing import List +from core.middleware import LogRoute from schemas import common as BaseSchema from schemas import role as RoleSchema from schemas.common import QueryData from service.role import service as RoleService -router = APIRouter(prefix="/role", tags=["角色管理"]) +router = APIRouter(prefix="/role", tags=["角色管理"], route_class=LogRoute) Response = BaseSchema.Response ListAll = BaseSchema.ListAll diff --git a/backend/router/user.py b/backend/router/user.py index b315ea9..729fff3 100644 --- a/backend/router/user.py +++ b/backend/router/user.py @@ -1,13 +1,14 @@ from fastapi import APIRouter, Depends from typing import List +from core.middleware import LogRoute from core.security import check_permissions from schemas import common as BaseSchema from schemas import user as UserSchema from schemas.common import QueryData from service.user import service as UserService -router = APIRouter(prefix="/user", tags=["用户管理"]) +router = APIRouter(prefix="/user", tags=["用户管理"], route_class=LogRoute) Response = BaseSchema.Response ListAll = BaseSchema.ListAll