|
@@ -4,77 +4,118 @@ import sys
|
|
|
from pathlib import Path
|
|
|
import colorlog
|
|
|
from logging.handlers import TimedRotatingFileHandler
|
|
|
-import datetime
|
|
|
|
|
|
-# 创建日志记录器
|
|
|
-log = logging.getLogger(__name__)
|
|
|
-log.setLevel(logging.INFO)
|
|
|
|
|
|
-# 获取项目根目录
|
|
|
project_root = Path(os.path.abspath(os.path.dirname(__file__))).parent.parent
|
|
|
|
|
|
-# 日志目录设置
|
|
|
-if sys.platform.startswith('linux'):
|
|
|
- log_dir = Path('/home/crossborder/logs')
|
|
|
-else:
|
|
|
- log_dir = project_root / 'logs'
|
|
|
-
|
|
|
-os.makedirs(log_dir, exist_ok=True) # 自动创建目录(如果不存在)
|
|
|
-
|
|
|
-# 创建带日期归档的文件处理器 - 关键修改点
|
|
|
-log_file = log_dir / 'cross.log'
|
|
|
-file_handler = TimedRotatingFileHandler(
|
|
|
- filename=str(log_file),
|
|
|
- when='midnight', # 每天午夜切换新日志
|
|
|
- interval=1, # 每天的间隔
|
|
|
- backupCount=30, # 保留30天的日志
|
|
|
- encoding='utf-8',
|
|
|
- utc=False # 使用本地时间
|
|
|
-)
|
|
|
-
|
|
|
-# 设置时间后缀格式 - 在日志文件名后添加日期
|
|
|
-file_handler.suffix = "%Y-%m-%d"
|
|
|
-file_handler.setLevel(logging.INFO)
|
|
|
-
|
|
|
-# 创建控制台处理器(带颜色)
|
|
|
-console_handler = colorlog.StreamHandler()
|
|
|
-console_handler.setLevel(logging.DEBUG if os.getenv('DEBUG') else logging.INFO)
|
|
|
-
|
|
|
-# 文件格式器
|
|
|
-plain_formatter = logging.Formatter(
|
|
|
- '%(asctime)s - %(name)s:%(lineno)d - %(levelname)s - %(message)s',
|
|
|
- datefmt='%Y-%m-%d %H:%M:%S'
|
|
|
-)
|
|
|
-
|
|
|
-# 控制台颜色格式器
|
|
|
-color_formatter = colorlog.ColoredFormatter(
|
|
|
- '%(log_color)s%(asctime)s - %(name)s:%(lineno)d - %(levelname)s - %(message)s',
|
|
|
- datefmt='%Y-%m-%d %H:%M:%S',
|
|
|
- log_colors={
|
|
|
- 'DEBUG': 'cyan',
|
|
|
- 'INFO': 'green',
|
|
|
- 'WARNING': 'yellow',
|
|
|
- 'ERROR': 'red',
|
|
|
- 'CRITICAL': 'red,bg_white',
|
|
|
- }
|
|
|
-)
|
|
|
-
|
|
|
-# 应用格式器
|
|
|
-file_handler.setFormatter(plain_formatter)
|
|
|
-console_handler.setFormatter(color_formatter)
|
|
|
-
|
|
|
-# 添加处理器到记录器
|
|
|
-log.addHandler(file_handler)
|
|
|
-log.addHandler(console_handler)
|
|
|
-
|
|
|
-# 禁用不必要库的日志
|
|
|
-logging.getLogger("urllib3").setLevel(logging.WARNING)
|
|
|
-logging.getLogger("selenium").setLevel(logging.WARNING)
|
|
|
-
|
|
|
-# 测试日志
|
|
|
-if __name__ == "__main__":
|
|
|
- log.debug("DEBUG级别日志 - 通常不会显示")
|
|
|
- log.info("INFO级别日志 - 程序运行信息")
|
|
|
- log.warning("WARNING级别日志 - 需要注意的问题")
|
|
|
- log.error("ERROR级别日志 - 错误信息")
|
|
|
- log.critical("CRITICAL级别日志 - 严重错误")
|
|
|
+def configure_logging():
|
|
|
+ """配置全局日志系统(只执行一次)"""
|
|
|
+ # 移除之前直接创建log实例的代码
|
|
|
+
|
|
|
+ # 创建根记录器并配置
|
|
|
+ root_logger = logging.getLogger()
|
|
|
+ root_logger.setLevel(logging.DEBUG)
|
|
|
+
|
|
|
+ # 清除可能存在的旧处理器
|
|
|
+ for handler in root_logger.handlers[:]:
|
|
|
+ root_logger.removeHandler(handler)
|
|
|
+
|
|
|
+
|
|
|
+ # 日志目录设置
|
|
|
+ if sys.platform.startswith('linux'):
|
|
|
+ log_dir = Path('/home/crossborder/logs')
|
|
|
+ else:
|
|
|
+ log_dir = project_root / 'logs'
|
|
|
+
|
|
|
+ os.makedirs(log_dir, exist_ok=True)
|
|
|
+
|
|
|
+ # 创建带日期归档的文件处理器
|
|
|
+ log_file = log_dir / 'cross.log'
|
|
|
+ file_handler = TimedRotatingFileHandler(
|
|
|
+ filename=str(log_file),
|
|
|
+ when='midnight',
|
|
|
+ interval=1,
|
|
|
+ backupCount=30,
|
|
|
+ encoding='utf-8',
|
|
|
+ utc=False
|
|
|
+ )
|
|
|
+ file_handler.suffix = "%Y-%m-%d"
|
|
|
+ file_handler.setLevel(logging.INFO)
|
|
|
+
|
|
|
+ # 创建控制台处理器(带颜色)
|
|
|
+ console_handler = colorlog.StreamHandler()
|
|
|
+ console_handler.setLevel(logging.DEBUG if os.getenv('DEBUG') else logging.INFO)
|
|
|
+
|
|
|
+ # 文件格式器
|
|
|
+ plain_formatter = logging.Formatter(
|
|
|
+ '%(asctime)s - %(name)s:%(lineno)d - %(levelname)s - %(message)s',
|
|
|
+ datefmt='%Y-%m-%d %H:%M:%S'
|
|
|
+ )
|
|
|
+
|
|
|
+ # 控制台颜色格式器
|
|
|
+ color_formatter = colorlog.ColoredFormatter(
|
|
|
+ '%(log_color)s%(asctime)s - %(name)s:%(lineno)d - %(levelname)s - %(message)s',
|
|
|
+ datefmt='%Y-%m-%d %H:%M:%S',
|
|
|
+ log_colors={
|
|
|
+ 'DEBUG': 'cyan',
|
|
|
+ 'INFO': 'green',
|
|
|
+ 'WARNING': 'yellow',
|
|
|
+ 'ERROR': 'red',
|
|
|
+ 'CRITICAL': 'red,bg_white',
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ file_handler.setFormatter(plain_formatter)
|
|
|
+ console_handler.setFormatter(color_formatter)
|
|
|
+
|
|
|
+ # 添加处理器到根记录器
|
|
|
+ root_logger.addHandler(file_handler)
|
|
|
+ root_logger.addHandler(console_handler)
|
|
|
+
|
|
|
+ # 禁用不必要库的日志
|
|
|
+ logging.getLogger("urllib3").setLevel(logging.WARNING)
|
|
|
+ logging.getLogger("selenium").setLevel(logging.WARNING)
|
|
|
+
|
|
|
+ # 项目顶级记录器(用于统一控制项目日志级别)
|
|
|
+ project_logger = logging.getLogger("crossborder")
|
|
|
+ project_logger.setLevel(logging.INFO)
|
|
|
+
|
|
|
+
|
|
|
+def get_logger(name=None):
|
|
|
+ if not name:
|
|
|
+ name = "crossborder"
|
|
|
+
|
|
|
+ # 处理主模块
|
|
|
+ if name == "__main__":
|
|
|
+ main_module = sys.modules['__main__']
|
|
|
+ # 获取入口文件的绝对路径
|
|
|
+ if hasattr(main_module, '__file__'):
|
|
|
+ main_file = Path(main_module.__file__).resolve()
|
|
|
+ try:
|
|
|
+ # 计算相对于项目根目录的路径
|
|
|
+ relative_path = main_file.relative_to(project_root)
|
|
|
+ # 转换为模块名:去掉扩展名,分隔符替换为点
|
|
|
+ name = str(relative_path.with_suffix('')).replace(os.sep, '.')
|
|
|
+ except ValueError:
|
|
|
+ # 如果入口文件不在项目根目录下,则使用文件名(不含扩展名)
|
|
|
+ name = main_file.stem
|
|
|
+ else:
|
|
|
+ # 例如交互式环境,没有__file__,则保留为"__main__"
|
|
|
+ pass
|
|
|
+
|
|
|
+ # 确保日志系统已配置
|
|
|
+ if not logging.getLogger().hasHandlers():
|
|
|
+ configure_logging()
|
|
|
+
|
|
|
+ # 添加项目顶级命名空间(如果还没有),除非已经是crossborder开头
|
|
|
+ if not name.startswith("crossborder."):
|
|
|
+ name = "crossborder." + name
|
|
|
+
|
|
|
+ return logging.getLogger(name)
|
|
|
+
|
|
|
+
|
|
|
+# 在模块导入时自动配置(可选)
|
|
|
+configure_logging()
|
|
|
+
|
|
|
+# ====== 注意:不再直接导出log实例 ======
|
|
|
+# 业务模块应使用 get_logger(__name__) 获取记录器
|