94 lines
2.9 KiB
Python
94 lines
2.9 KiB
Python
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"):
|
||
record.trace_id = getattr(g, "trace_id")
|
||
# 处理 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)
|