logger.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. """
  2. React Agent 独立日志管理器
  3. 专门为 react_agent 模块设计的日志管理器,完全独立于主项目的日志系统
  4. """
  5. import os
  6. import logging as std_logging
  7. from pathlib import Path
  8. from typing import Dict
  9. from datetime import datetime
  10. class ReactAgentLogManager:
  11. """React Agent 专用日志管理器"""
  12. _loggers: Dict[str, std_logging.Logger] = {}
  13. _file_handlers: Dict[str, std_logging.FileHandler] = {}
  14. @classmethod
  15. def get_logger(cls, name: str) -> std_logging.Logger:
  16. """
  17. 获取或创建logger
  18. Args:
  19. name: logger名称
  20. Returns:
  21. 配置好的logger实例
  22. """
  23. logger_key = f"react_agent.{name}"
  24. if logger_key not in cls._loggers:
  25. logger = cls._create_logger(name)
  26. cls._loggers[logger_key] = logger
  27. return cls._loggers[logger_key]
  28. @classmethod
  29. def _create_logger(cls, name: str) -> std_logging.Logger:
  30. """创建新的logger实例"""
  31. # 创建logger
  32. logger_name = f"react_agent.{name}"
  33. logger = std_logging.getLogger(logger_name)
  34. # 设置日志级别
  35. logger.setLevel(std_logging.DEBUG)
  36. # 防止日志重复(清除已有处理器)
  37. logger.handlers.clear()
  38. logger.propagate = False
  39. # 添加控制台处理器
  40. console_handler = cls._create_console_handler()
  41. logger.addHandler(console_handler)
  42. # 添加文件处理器
  43. file_handler = cls._create_file_handler()
  44. if file_handler:
  45. logger.addHandler(file_handler)
  46. return logger
  47. @classmethod
  48. def _create_console_handler(cls) -> std_logging.StreamHandler:
  49. """创建控制台处理器"""
  50. handler = std_logging.StreamHandler()
  51. handler.setLevel(std_logging.INFO)
  52. formatter = std_logging.Formatter(
  53. '%(asctime)s [%(levelname)s] ReactAgent: %(message)s',
  54. datefmt='%Y-%m-%d %H:%M:%S'
  55. )
  56. handler.setFormatter(formatter)
  57. return handler
  58. @classmethod
  59. def _create_file_handler(cls) -> std_logging.FileHandler:
  60. """创建文件处理器"""
  61. try:
  62. # 获取项目根目录的绝对路径
  63. project_root = Path(__file__).parent.parent
  64. logs_dir = project_root / "logs"
  65. logs_dir.mkdir(parents=True, exist_ok=True)
  66. # 使用当前日期作为日志文件名
  67. today = datetime.now().strftime('%Y%m%d')
  68. log_file = logs_dir / f"react_agent_{today}.log"
  69. # 为当天创建独立的文件处理器
  70. handler_key = f"file_handler_{today}"
  71. if handler_key not in cls._file_handlers:
  72. handler = std_logging.FileHandler(log_file, encoding='utf-8')
  73. handler.setLevel(std_logging.DEBUG)
  74. formatter = std_logging.Formatter(
  75. '%(asctime)s [%(levelname)s] [%(name)s] %(filename)s:%(lineno)d - %(message)s',
  76. datefmt='%Y-%m-%d %H:%M:%S'
  77. )
  78. handler.setFormatter(formatter)
  79. cls._file_handlers[handler_key] = handler
  80. return cls._file_handlers[handler_key]
  81. except Exception as e:
  82. # 如果文件处理器创建失败,记录到stderr但不影响程序运行
  83. import sys
  84. sys.stderr.write(f"[WARNING] 无法创建react_agent日志文件处理器: {e}\n")
  85. return None
  86. @classmethod
  87. def cleanup_today_logger(cls):
  88. """清理今天的logger和文件处理器"""
  89. try:
  90. today = datetime.now().strftime('%Y%m%d')
  91. handler_key = f"file_handler_{today}"
  92. # 关闭文件处理器
  93. if handler_key in cls._file_handlers:
  94. cls._file_handlers[handler_key].close()
  95. del cls._file_handlers[handler_key]
  96. # 清理相关的logger
  97. keys_to_remove = [key for key in cls._loggers.keys() if key.startswith("react_agent.")]
  98. for key in keys_to_remove:
  99. logger = cls._loggers[key]
  100. for handler in logger.handlers:
  101. handler.close()
  102. logger.handlers.clear()
  103. del cls._loggers[key]
  104. except Exception as e:
  105. import sys
  106. sys.stderr.write(f"[WARNING] 清理react_agent日志资源失败: {e}\n")
  107. @classmethod
  108. def cleanup_all(cls):
  109. """清理所有logger和文件处理器"""
  110. try:
  111. # 关闭所有文件处理器
  112. for handler in cls._file_handlers.values():
  113. handler.close()
  114. cls._file_handlers.clear()
  115. # 清理所有logger
  116. for logger in cls._loggers.values():
  117. for handler in logger.handlers:
  118. handler.close()
  119. logger.handlers.clear()
  120. cls._loggers.clear()
  121. except Exception as e:
  122. import sys
  123. sys.stderr.write(f"[WARNING] 清理所有react_agent日志资源失败: {e}\n")
  124. def get_react_agent_logger(name: str) -> std_logging.Logger:
  125. """
  126. 便捷函数:获取react_agent模块的logger
  127. Args:
  128. name: logger名称
  129. Returns:
  130. 配置好的logger实例
  131. """
  132. return ReactAgentLogManager.get_logger(name)