warp / common /logging.py
maltose1's picture
Upload 201 files
3d87b51 verified
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
统一的日志系统配置
"""
import logging
from logging.handlers import RotatingFileHandler
from pathlib import Path
from typing import Optional
class LoggerFactory:
"""日志工厂类,用于创建统一配置的logger"""
DEFAULT_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
@classmethod
def create_logger(
cls,
name: str,
log_file: str,
log_dir: Path = Path("logs"),
max_bytes: int = 10*1024*1024,
backup_count: int = 5,
console_level: int = logging.WARNING, # 提高控制台输出级别,减少日志
file_level: int = logging.INFO # 文件仍然记录INFO级别
) -> logging.Logger:
"""
创建一个配置好的logger实例
Args:
name: Logger名称
log_file: 日志文件名
log_dir: 日志目录
max_bytes: 单个日志文件最大大小
backup_count: 日志文件备份数量
console_level: 控制台输出级别
file_level: 文件输出级别
"""
# 创建logger
logger = logging.getLogger(name)
logger.setLevel(min(console_level, file_level))
# 清除已有的handlers
for handler in logger.handlers[:]:
logger.removeHandler(handler)
# 尝试创建文件处理器(如果权限允许)
file_handler_added = False
try:
# 确保日志目录存在
log_dir.mkdir(exist_ok=True)
# 文件处理器
file_handler = RotatingFileHandler(
log_dir / log_file,
maxBytes=max_bytes,
backupCount=backup_count,
encoding='utf-8'
)
file_handler.setLevel(file_level)
# 设置格式
formatter = logging.Formatter(cls.DEFAULT_FORMAT)
file_handler.setFormatter(formatter)
# 添加文件处理器
logger.addHandler(file_handler)
file_handler_added = True
except (PermissionError, OSError) as e:
# 如果无法创建文件处理器,降级到仅控制台输出
print(f"Warning: Unable to create log file '{log_file}': {e}", file=__import__('sys').stderr)
print(f"Logging will only output to console.", file=__import__('sys').stderr)
# 控制台处理器(总是添加)
console_handler = logging.StreamHandler()
# 如果没有文件处理器,降低控制台级别以确保看到所有重要日志
if not file_handler_added:
console_handler.setLevel(logging.INFO)
else:
console_handler.setLevel(console_level)
# 设置格式
formatter = logging.Formatter(cls.DEFAULT_FORMAT)
console_handler.setFormatter(formatter)
# 添加控制台处理器
logger.addHandler(console_handler)
return logger
# 创建默认的logger实例
def get_logger(name: str = "default") -> logging.Logger:
"""获取logger实例,使用统一的配置"""
return LoggerFactory.create_logger(
name=name,
log_file=f"{name}.log"
)