mirror of
https://github.com/PaddlePaddle/FastDeploy.git
synced 2025-10-06 00:57:33 +08:00

Some checks failed
Deploy GitHub Pages / deploy (push) Has been cancelled
* feat(log):add_request_and_response_log * feat[log]:add error log to file
162 lines
5.7 KiB
Python
162 lines
5.7 KiB
Python
"""
|
||
# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.
|
||
#
|
||
# Licensed under the Apache License, Version 2.0 (the "License"
|
||
# you may not use this file except in compliance with the License.
|
||
# You may obtain a copy of the License at
|
||
#
|
||
# http://www.apache.org/licenses/LICENSE-2.0
|
||
# Unless required by applicable law or agreed to in writing, software
|
||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
# See the License for the specific language governing permissions and
|
||
# limitations under the License.
|
||
"""
|
||
|
||
"""
|
||
日志模块:用于初始化和获取 FastDeploy 日志记录器。
|
||
本模块提供 get_logger 方法,统一管理各子模块的日志记录行为。
|
||
"""
|
||
|
||
import logging
|
||
import os
|
||
import threading
|
||
from pathlib import Path
|
||
|
||
from fastdeploy import envs
|
||
from fastdeploy.logger.formatters import ColoredFormatter
|
||
from fastdeploy.logger.handlers import DailyRotatingFileHandler, LazyFileHandler
|
||
from fastdeploy.logger.setup_logging import setup_logging
|
||
|
||
|
||
class FastDeployLogger:
|
||
_instance = None
|
||
_initialized = False
|
||
_lock = threading.RLock()
|
||
|
||
def __new__(cls):
|
||
"""单例模式实现"""
|
||
if cls._instance is None:
|
||
with cls._lock:
|
||
if cls._instance is None:
|
||
cls._instance = super().__new__(cls)
|
||
return cls._instance
|
||
|
||
def _initialize(self):
|
||
"""显式初始化日志系统"""
|
||
with self._lock:
|
||
if not self._initialized:
|
||
setup_logging()
|
||
self._initialized = True
|
||
|
||
def get_logger(self, name, file_name=None, without_formater=False, print_to_console=False):
|
||
"""
|
||
获取日志记录器(兼容原有接口)
|
||
|
||
Args:
|
||
name: 日志器名称
|
||
file_name: 日志文件名(保持兼容性)
|
||
without_formater: 是否不使用格式化器
|
||
print_to_console: 是否打印到控制台
|
||
"""
|
||
# 如果只有一个参数,使用新的统一命名方式
|
||
if file_name is None and not without_formater and not print_to_console:
|
||
# 延迟初始化
|
||
if not self._initialized:
|
||
self._initialize()
|
||
return self._get_unified_logger(name)
|
||
|
||
# 兼容原有接口
|
||
return self._get_legacy_logger(name, file_name, without_formater, print_to_console)
|
||
|
||
def _get_unified_logger(self, name):
|
||
"""
|
||
新的统一日志获取方式
|
||
"""
|
||
if name is None:
|
||
return logging.getLogger("fastdeploy")
|
||
|
||
# 处理 __main__ 特殊情况
|
||
if name == "__main__":
|
||
import __main__
|
||
|
||
# 获取主模块的 __file__ 属性
|
||
if hasattr(__main__, "__file__"):
|
||
# 获取主模块的文件名
|
||
base_name = Path(__main__.__file__).stem
|
||
# 创建带前缀的日志器
|
||
return logging.getLogger(f"fastdeploy.main.{base_name}")
|
||
return logging.getLogger("fastdeploy.main")
|
||
|
||
# 如果已经是fastdeploy命名空间,直接使用
|
||
if name.startswith("fastdeploy.") or name == "fastdeploy":
|
||
return logging.getLogger(name)
|
||
else:
|
||
# 其他情况添加fastdeploy前缀
|
||
return logging.getLogger(f"fastdeploy.{name}")
|
||
|
||
def _get_legacy_logger(self, name, file_name, without_formater=False, print_to_console=False):
|
||
"""
|
||
兼容原有接口的日志获取方式
|
||
"""
|
||
|
||
log_dir = envs.FD_LOG_DIR
|
||
if not os.path.exists(log_dir):
|
||
os.makedirs(log_dir, exist_ok=True)
|
||
|
||
is_debug = int(envs.FD_DEBUG)
|
||
# logger = logging.getLogger(name)
|
||
# 为了兼容原有接口,使用命名空间进行隔离,避免logger覆盖、混乱等问题
|
||
legacy_name = f"legacy.{name}"
|
||
logger = logging.getLogger(legacy_name)
|
||
|
||
# 设置日志级别
|
||
if is_debug:
|
||
logger.setLevel(level=logging.DEBUG)
|
||
else:
|
||
logger.setLevel(level=logging.INFO)
|
||
|
||
# 设置格式化器
|
||
formatter = ColoredFormatter(
|
||
"%(levelname)-8s %(asctime)s %(process)-5s %(filename)s[line:%(lineno)d] %(message)s"
|
||
)
|
||
|
||
# 清除现有的handlers(保持原有逻辑)
|
||
for handler in logger.handlers[:]:
|
||
logger.removeHandler(handler)
|
||
|
||
# 创建主日志文件handler
|
||
LOG_FILE = f"{log_dir}/{file_name}"
|
||
backup_count = int(envs.FD_LOG_BACKUP_COUNT)
|
||
# handler = LazyFileHandler(filename=LOG_FILE, backupCount=backup_count, level=hanlder_level)
|
||
handler = DailyRotatingFileHandler(LOG_FILE, backupCount=backup_count)
|
||
|
||
# 创建ERROR日志文件handler(新增功能)
|
||
if not file_name.endswith(".log"):
|
||
file_name = f"{file_name}.log" if "." not in file_name else file_name.split(".")[0] + ".log"
|
||
ERROR_LOG_FILE = os.path.join(log_dir, file_name.replace(".log", "_error.log"))
|
||
error_handler = LazyFileHandler(
|
||
filename=ERROR_LOG_FILE, backupCount=backup_count, level=logging.ERROR, formatter=None
|
||
)
|
||
|
||
if not without_formater:
|
||
handler.setFormatter(formatter)
|
||
error_handler.setFormatter(formatter)
|
||
|
||
# 添加文件handlers
|
||
logger.addHandler(handler)
|
||
logger.addHandler(error_handler)
|
||
|
||
# 控制台handler
|
||
if print_to_console:
|
||
console_handler = logging.StreamHandler()
|
||
if not without_formater:
|
||
console_handler.setFormatter(formatter)
|
||
logger.addHandler(console_handler)
|
||
console_handler.propagate = False
|
||
|
||
# 设置propagate(保持原有逻辑)
|
||
# logger.propagate = False
|
||
|
||
return logger
|