import logging import uuid import json from datetime import datetime from fastapi import Request, FastAPI from starlette.responses import JSONResponse from starlette.requests import HTTPConnection from typing import Callable, Awaitable from .context import g def add_request_routes(app: FastAPI): @app.middleware("http") async def before_request(request: Request, call_next: Callable[[Request], Awaitable[JSONResponse]]): # 先从header中获取x-request-id,如果没有则生成新的 trace_id = request.headers.get('X-Request-ID') if not trace_id: trace_id = "agent_" + str(uuid.uuid4()) # user_id = "未知的 user_id" g.trace_id = trace_id # g.user_id = user_id response = await call_next(request) response.headers['X-Request-ID'] = g.trace_id return response class Formatter(logging.Formatter): def formatTime(self, record, datefmt=None): # 将时间戳转换为datetime对象 dt = datetime.fromtimestamp(record.created) # 格式化时间戳到毫秒 if datefmt: s = dt.strftime(datefmt) # 去除微秒的后三位,保留毫秒部分 s = s[:-3] else: # 去除微秒的后三位,保留毫秒部分 s = dt.strftime("%H:%M:%S.%f")[:-3] return s def format(self, record): # 处理 trace_id - 在没有请求上下文时使用默认值 if not hasattr(record, "trace_id"): try: record.trace_id = getattr(g, "trace_id") except LookupError: record.trace_id = "N/A" # 处理 user_id # if not hasattr(record, "user_id"): # record.user_id = getattr(g, "user_id") # 格式化时间戳 record.timestamp = self.formatTime(record, self.datefmt) return super().format(record) # 这里注册session 上下文追踪一次就可以了 def init_logger_once(name,level): logger = logging.getLogger(name) logger.setLevel(level=level) formatter = Formatter("%(timestamp)s | %(levelname)-5s | %(trace_id)s | %(name)s:%(funcName)s:%(lineno)s - %(message)s", datefmt='%Y-%m-%d %H:%M:%S.%f') handler = logging.StreamHandler() handler.setFormatter(formatter) logger.addHandler(handler) def init_with_fastapi(app,level=logging.INFO): init_logger_once("app",level) add_request_routes(app) def info(message, *args, **kwargs): app_logger = logging.getLogger('app') app_logger.info(message, *args, **kwargs) def debug(message, *args, **kwargs): app_logger = logging.getLogger('app') app_logger.debug(message, *args, **kwargs) def warning(message, *args, **kwargs): app_logger = logging.getLogger('app') app_logger.warning(message, *args, **kwargs) def error(message, *args, **kwargs): app_logger = logging.getLogger('app') app_logger.error(message, *args, **kwargs) def critical(message, *args, **kwargs): app_logger = logging.getLogger('app') app_logger.critical(message, *args, **kwargs)