131 lines
4.4 KiB
Python
131 lines
4.4 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
统一日志配置模块
|
||
提供系统级别的日志配置和管理
|
||
"""
|
||
|
||
import os
|
||
import sys
|
||
import logging
|
||
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler
|
||
from pathlib import Path
|
||
|
||
|
||
class LoggerConfig:
|
||
"""日志配置管理类"""
|
||
|
||
def __init__(self, logs_dir: str = None):
|
||
"""初始化日志配置"""
|
||
if logs_dir:
|
||
self.logs_dir = Path(logs_dir)
|
||
else:
|
||
project_root = Path(__file__).parent.parent
|
||
self.logs_dir = project_root / "logs"
|
||
|
||
self.logs_dir.mkdir(exist_ok=True)
|
||
|
||
self.log_format = '%(asctime)s - %(name)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s'
|
||
self.date_format = '%Y-%m-%d %H:%M:%S'
|
||
self.log_level = self._get_log_level_from_env()
|
||
self._initialized = False
|
||
|
||
def _get_log_level_from_env(self) -> int:
|
||
log_level_str = os.getenv('LOG_LEVEL', 'INFO').upper()
|
||
level_mapping = {
|
||
'DEBUG': logging.DEBUG,
|
||
'INFO': logging.INFO,
|
||
'WARNING': logging.WARNING,
|
||
'WARN': logging.WARNING,
|
||
'ERROR': logging.ERROR,
|
||
'CRITICAL': logging.CRITICAL,
|
||
'FATAL': logging.CRITICAL
|
||
}
|
||
return level_mapping.get(log_level_str, logging.INFO)
|
||
|
||
def setup_logging(self,
|
||
app_name: str = "lzwcai_mcpskills_template",
|
||
log_level: int = logging.INFO,
|
||
max_file_size: int = 10 * 1024 * 1024,
|
||
backup_count: int = 5,
|
||
console_output: bool = True) -> logging.Logger:
|
||
if self._initialized:
|
||
return logging.getLogger()
|
||
|
||
root_logger = logging.getLogger()
|
||
root_logger.setLevel(log_level)
|
||
|
||
for handler in root_logger.handlers[:]:
|
||
root_logger.removeHandler(handler)
|
||
|
||
formatter = logging.Formatter(self.log_format, self.date_format)
|
||
|
||
# 1. 主日志文件 - 按大小滚动
|
||
main_log_file = self.logs_dir / f"{app_name}.log"
|
||
file_handler = RotatingFileHandler(
|
||
main_log_file,
|
||
maxBytes=max_file_size,
|
||
backupCount=backup_count,
|
||
encoding='utf-8'
|
||
)
|
||
file_handler.setLevel(log_level)
|
||
file_handler.setFormatter(formatter)
|
||
root_logger.addHandler(file_handler)
|
||
|
||
# 2. 错误日志文件
|
||
error_log_file = self.logs_dir / f"{app_name}_error.log"
|
||
error_handler = RotatingFileHandler(
|
||
error_log_file,
|
||
maxBytes=max_file_size,
|
||
backupCount=backup_count,
|
||
encoding='utf-8'
|
||
)
|
||
error_handler.setLevel(logging.ERROR)
|
||
error_handler.setFormatter(formatter)
|
||
root_logger.addHandler(error_handler)
|
||
|
||
# 3. 按日期滚动的日志文件
|
||
daily_log_file = self.logs_dir / f"{app_name}_daily.log"
|
||
daily_handler = TimedRotatingFileHandler(
|
||
daily_log_file,
|
||
when='midnight',
|
||
interval=1,
|
||
backupCount=30,
|
||
encoding='utf-8'
|
||
)
|
||
daily_handler.setLevel(log_level)
|
||
daily_handler.setFormatter(formatter)
|
||
daily_handler.suffix = "%Y-%m-%d"
|
||
root_logger.addHandler(daily_handler)
|
||
|
||
# 4. 控制台输出 (MCP协议使用stdio时,必须将日志输出到stderr)
|
||
if console_output:
|
||
console_handler = logging.StreamHandler(sys.stderr)
|
||
console_handler.setLevel(log_level)
|
||
console_formatter = logging.Formatter(
|
||
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||
self.date_format
|
||
)
|
||
console_handler.setFormatter(console_formatter)
|
||
root_logger.addHandler(console_handler)
|
||
|
||
self._initialized = True
|
||
root_logger.info(f"日志系统初始化完成 - 日志目录: {self.logs_dir}")
|
||
|
||
return root_logger
|
||
|
||
def get_module_logger(self, module_name: str) -> logging.Logger:
|
||
return logging.getLogger(module_name)
|
||
|
||
|
||
# 全局日志配置实例
|
||
logger_config = LoggerConfig()
|
||
|
||
|
||
def setup_system_logging(app_name: str = "lzwcai_mcpskills_template",
|
||
log_level: int = logging.INFO) -> logging.Logger:
|
||
return logger_config.setup_logging(app_name, log_level)
|
||
|
||
|
||
def get_logger(name: str) -> logging.Logger:
|
||
return logger_config.get_module_logger(name)
|