From 1bd24636c912f11dd67b285b165ebbb7de6fdc07 Mon Sep 17 00:00:00 2001 From: jocelyn Date: Tue, 10 Jun 2025 15:04:35 +0800 Subject: [PATCH] [ADD]add logic of loop frame --- utils/log.py | 119 +++++++++++++++++++++++++++++++++++++++ utils/loop_frame_tool.py | 0 2 files changed, 119 insertions(+) create mode 100644 utils/log.py create mode 100644 utils/loop_frame_tool.py diff --git a/utils/log.py b/utils/log.py new file mode 100644 index 0000000..a531729 --- /dev/null +++ b/utils/log.py @@ -0,0 +1,119 @@ +import logging +import os +import sys +import redis +from loguru import logger as logurulogger +import redis.exceptions +from app.config import config +import json +from redis.retry import Retry +from redis.backoff import ExponentialBackoff + +LOG_FORMAT = ( + "{level: <8} " + "{process.name} | " # 进程名 + "{thread.name} | " + "{time:YYYY-MM-DD HH:mm:ss.SSS} - " + "{process} " + "{module}.{function}:{line} - " + "{message}" +) +LOG_NAME = ["uvicorn", "uvicorn.access", "uvicorn.error", "flask"] + +# 配置 Redis 连接池 +redis_pool = redis.ConnectionPool( + host=config.LOG_REDIS_HOST, # Redis 服务器地址 + port=config.LOG_REDIS_PORT, # Redis 服务器端口 + db=config.LOG_REDIS_DB, # 数据库编号 + password=config.LOG_REDIS_AUTH, # 密码 + max_connections=config.max_connections, # 最大连接数 + socket_connect_timeout=config.socket_connect_timeout, # 连接超时时间 + socket_timeout=config.socket_timeout, # 等待超时时间 +) + + +class InterceptHandler(logging.Handler): + def emit(self, record): + try: + level = logurulogger.level(record.levelname).name + except AttributeError: + level = logging._levelToName[record.levelno] + + frame, depth = logging.currentframe(), 2 + while frame.f_code.co_filename == logging.__file__: + frame = frame.f_back + depth += 1 + + logurulogger.opt(depth=depth, exception=record.exc_info).log( + level, record.getMessage() + ) + +class Logging: + """自定义日志""" + + def __init__(self): + self.log_path = "logs" + self._connect_redis() + if config.IS_LOCAL: + os.makedirs(self.log_path, exist_ok=True) + self._initlogger() + self._reset_log_handler() + + def _connect_redis(self): + retry = Retry(ExponentialBackoff(), 3) # 重试3次,指数退避 + self.redis_client = redis.Redis(connection_pool=redis_pool,retry=retry) # 使用连接池 + + def _initlogger(self): + """初始化loguru配置""" + logurulogger.remove() + if config.IS_LOCAL: + logurulogger.add( + os.path.join(self.log_path, "error.log.{time:YYYY-MM-DD}"), + format=LOG_FORMAT, + level=logging.ERROR, + rotation="00:00", + retention="1 week", + backtrace=True, + diagnose=True, + enqueue=True + ) + logurulogger.add( + os.path.join(self.log_path, "info.log.{time:YYYY-MM-DD}"), + format=LOG_FORMAT, + level=logging.INFO, + rotation="00:00", + retention="1 week", + enqueue=True + ) + logurulogger.add( + sys.stdout, + format=LOG_FORMAT, + level=logging.DEBUG, + colorize=True, + ) + + logurulogger.add(self._log_to_redis, level="INFO", format=LOG_FORMAT) + self.logger = logurulogger + + + def _log_to_redis(self, message): + """将日志写入 Redis 列表""" + try: + self.redis_client.rpush(f"nlp.logger.{config.env_version}.log", json.dumps({"message": message})) + except redis.exceptions.ConnectionError as e: + logger.error(f"write {message} Redis connection error: {e}") + except redis.exceptions.TimeoutError as e: + logger.error(f"write {message} Redis operation timed out: {e}") + except Exception as e: + logger.error(f"write {message} Unexpected error: {e}") + + def _reset_log_handler(self): + for log in LOG_NAME: + logger = logging.getLogger(log) + logger.handlers = [InterceptHandler()] + + def getlogger(self): + return self.logger + +logger = Logging().getlogger() + diff --git a/utils/loop_frame_tool.py b/utils/loop_frame_tool.py new file mode 100644 index 0000000..e69de29