mirror of
https://github.com/PaddlePaddle/FastDeploy.git
synced 2025-10-06 17:17:14 +08:00
add error log to file (#3431)
Some checks failed
Deploy GitHub Pages / deploy (push) Has been cancelled
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
This commit is contained in:
161
fastdeploy/logger/logger.py
Normal file
161
fastdeploy/logger/logger.py
Normal file
@@ -0,0 +1,161 @@
|
||||
"""
|
||||
# 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
|
Reference in New Issue
Block a user