local_log.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import sys
  2. from datetime import datetime
  3. from pathlib import Path
  4. from loguru import logger as global_logger
  5. from config import settings
  6. from core.utils.trace_utils import get_current_trace_id
  7. class Local:
  8. """
  9. 本地日志记录器
  10. - 支持文件和控制台共享配置
  11. - 自动管理日志处理器生命周期
  12. - 确保日志格式一致性
  13. """
  14. _initialized_loggers = {} # 存储已初始化的日志器配置
  15. @staticmethod
  16. def _get_base_config(platform: str, mode: str) -> dict:
  17. """获取基础日志配置(文件和控制台共享)"""
  18. return {
  19. "format": (
  20. "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | "
  21. "<level>{level}</level> | "
  22. "<cyan>{extra[platform]}</cyan> | "
  23. "<cyan>{extra[mode]}</cyan> | "
  24. "<magenta>trace_id={extra[trace_id]}</magenta> | "
  25. "<cyan>{name}:{function}:{line}</cyan> | "
  26. "{message}"
  27. ),
  28. "backtrace": True, # 发生异常时显示完整堆栈回溯
  29. "diagnose": True, # 发生异常时显示变量值
  30. "enqueue": True, # 使用队列异步处理日志,提高性能
  31. "level": "INFO", # 默认级别,将被实际配置覆盖
  32. # 日志过滤设置
  33. "filter": lambda record: record["extra"].get("platform") == platform
  34. and record["extra"].get("mode") == mode
  35. }
  36. @staticmethod
  37. def init_logger(
  38. platform: str,
  39. mode: str,
  40. log_level: str = "INFO",
  41. log_to_console: bool = False,
  42. retention: str = "10 days",
  43. rotation: str = "00:00",
  44. compression: str = "gz",
  45. ):
  46. """初始化并返回带上下文的日志实例"""
  47. key = f"{platform}_{mode}"
  48. # 如果已初始化,直接返回
  49. if key in Local._initialized_loggers:
  50. return global_logger.bind(
  51. platform=platform,
  52. mode=mode,
  53. trace_id=get_current_trace_id()
  54. )
  55. # 创建日志存放路径
  56. log_dir = Path(f"{settings.LOG_DIR}/{platform}")
  57. log_dir.mkdir(parents=True, exist_ok=True)
  58. # 日志文件模式
  59. log_pattern = log_dir / f"{platform}-{mode}-{{time:YYYY-MM-DD}}.log"
  60. # 获取基础配置
  61. base_config = Local._get_base_config(platform, mode)
  62. base_config["level"] = log_level.upper()
  63. # 清理现有处理器(避免重复)
  64. global_logger.remove()
  65. # 添加文件日志处理器(继承基础配置)
  66. file_config = {
  67. **base_config,
  68. "sink": str(log_pattern),
  69. "rotation": rotation,
  70. "retention": retention,
  71. "compression": compression,
  72. "encoding": "utf-8"
  73. }
  74. global_logger.add(**file_config)
  75. # 添加控制台日志处理器(如果需要,继承基础配置并添加颜色)
  76. if log_to_console:
  77. console_config = {
  78. **base_config,
  79. "sink": sys.stdout,
  80. "colorize": True
  81. }
  82. global_logger.add(**console_config)
  83. # 标记为已初始化
  84. Local._initialized_loggers[key] = True
  85. # 返回绑定上下文的日志器
  86. return global_logger.bind(
  87. platform=platform,
  88. mode=mode,
  89. trace_id=get_current_trace_id()
  90. )