add error log to file (#3431)
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:
xiaolei373
2025-08-20 09:52:34 +08:00
committed by GitHub
parent 3a6058e445
commit 5d131485d8
11 changed files with 1396 additions and 30 deletions

161
fastdeploy/logger/logger.py Normal file
View 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