155 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			155 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Python
		
	
	
	
import logging
 | 
						||
import os
 | 
						||
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler
 | 
						||
from typing import Union
 | 
						||
 | 
						||
 | 
						||
class Logger:
 | 
						||
    """
 | 
						||
    日志工具类封装
 | 
						||
 | 
						||
    功能:
 | 
						||
    1. 支持控制台和文件两种输出方式
 | 
						||
    2. 支持按大小或时间轮转日志文件
 | 
						||
    3. 支持自定义日志格式
 | 
						||
    4. 支持不同日志级别
 | 
						||
    5. 线程安全
 | 
						||
    """
 | 
						||
 | 
						||
    def __init__(
 | 
						||
            self,
 | 
						||
            name: str = "root",
 | 
						||
            level: Union[int, str] = logging.INFO,
 | 
						||
            console: bool = True,
 | 
						||
            file: bool = False,
 | 
						||
            file_path: str = "logs/app.log",
 | 
						||
            max_bytes: int = 10 * 1024 * 1024,  # 10MB
 | 
						||
            backup_count: int = 5,
 | 
						||
            when: str = "midnight",
 | 
						||
            interval: int = 1,
 | 
						||
            fmt: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
 | 
						||
            datefmt: str = "%Y-%m-%d %H:%M:%S",
 | 
						||
            mode: str = "size"  # 'size' 或 'time'
 | 
						||
    ):
 | 
						||
        """
 | 
						||
        初始化日志工具
 | 
						||
 | 
						||
        :param name: 日志名称
 | 
						||
        :param level: 日志级别
 | 
						||
        :param console: 是否输出到控制台
 | 
						||
        :param file: 是否输出到文件
 | 
						||
        :param file_path: 日志文件路径
 | 
						||
        :param max_bytes: 每个日志文件的最大大小(字节),仅mode='size'时有效
 | 
						||
        :param backup_count: 保留的备份日志文件数量
 | 
						||
        :param when: 日志轮转时间单位,如'S'(秒)、'M'(分)、'H'(小时)、'D'(天)、'midnight'(午夜),仅mode='time'时有效
 | 
						||
        :param interval: 轮转间隔,仅mode='time'时有效
 | 
						||
        :param fmt: 日志格式
 | 
						||
        :param datefmt: 日期格式
 | 
						||
        :param mode: 日志轮转模式,'size'按大小轮转,'time'按时间轮转
 | 
						||
        """
 | 
						||
        self.logger = logging.getLogger(name)
 | 
						||
        self.logger.setLevel(level)
 | 
						||
 | 
						||
        # 避免重复添加handler
 | 
						||
        if self.logger.handlers:
 | 
						||
            return
 | 
						||
 | 
						||
        formatter = logging.Formatter(fmt=fmt, datefmt=datefmt)
 | 
						||
 | 
						||
        # 控制台输出
 | 
						||
        if console:
 | 
						||
            console_handler = logging.StreamHandler()
 | 
						||
            console_handler.setFormatter(formatter)
 | 
						||
            self.logger.addHandler(console_handler)
 | 
						||
 | 
						||
        # 文件输出
 | 
						||
        if file:
 | 
						||
            # 创建日志目录
 | 
						||
            log_dir = os.path.dirname(file_path)
 | 
						||
            if log_dir and not os.path.exists(log_dir):
 | 
						||
                os.makedirs(log_dir)
 | 
						||
 | 
						||
            if mode == "size":
 | 
						||
                # 按大小轮转
 | 
						||
                file_handler = RotatingFileHandler(
 | 
						||
                    filename=file_path,
 | 
						||
                    maxBytes=max_bytes,
 | 
						||
                    backupCount=backup_count,
 | 
						||
                    encoding="utf-8"
 | 
						||
                )
 | 
						||
            else:
 | 
						||
                # 按时间轮转
 | 
						||
                file_handler = TimedRotatingFileHandler(
 | 
						||
                    filename=file_path,
 | 
						||
                    when=when,
 | 
						||
                    interval=interval,
 | 
						||
                    backupCount=backup_count,
 | 
						||
                    encoding="utf-8"
 | 
						||
                )
 | 
						||
 | 
						||
            file_handler.setFormatter(formatter)
 | 
						||
            self.logger.addHandler(file_handler)
 | 
						||
 | 
						||
    def debug(self, msg: str, *args, **kwargs):
 | 
						||
        """记录调试信息"""
 | 
						||
        self.logger.debug(msg, *args, **kwargs)
 | 
						||
 | 
						||
    def info(self, msg: str, *args, **kwargs):
 | 
						||
        """记录普通信息"""
 | 
						||
        self.logger.info(msg, *args, **kwargs)
 | 
						||
 | 
						||
    def warning(self, msg: str, *args, **kwargs):
 | 
						||
        """记录警告信息"""
 | 
						||
        self.logger.warning(msg, *args, **kwargs)
 | 
						||
 | 
						||
    def error(self, msg: str, *args, **kwargs):
 | 
						||
        """记录错误信息"""
 | 
						||
        self.logger.error(msg, *args, **kwargs)
 | 
						||
 | 
						||
    def critical(self, msg: str, *args, **kwargs):
 | 
						||
        """记录严重错误信息"""
 | 
						||
        self.logger.critical(msg, *args, **kwargs)
 | 
						||
 | 
						||
    def exception(self, msg: str, *args, exc_info=True, **kwargs):
 | 
						||
        """记录异常信息"""
 | 
						||
        self.logger.exception(msg, *args, exc_info=exc_info, **kwargs)
 | 
						||
 | 
						||
    def log(self, level: int, msg: str, *args, **kwargs):
 | 
						||
        """通用日志记录方法"""
 | 
						||
        self.logger.log(level, msg, *args, **kwargs)
 | 
						||
 | 
						||
    def set_level(self, level: Union[int, str]):
 | 
						||
        """设置日志级别"""
 | 
						||
        self.logger.setLevel(level)
 | 
						||
 | 
						||
    def add_handler(self, handler: logging.Handler):
 | 
						||
        """添加自定义handler"""
 | 
						||
        self.logger.addHandler(handler)
 | 
						||
 | 
						||
    def remove_handler(self, handler: logging.Handler):
 | 
						||
        """移除handler"""
 | 
						||
        self.logger.removeHandler(handler)
 | 
						||
 | 
						||
 | 
						||
logger: Logger
 | 
						||
 | 
						||
 | 
						||
def app_logger() -> Logger:
 | 
						||
    return logger
 | 
						||
 | 
						||
 | 
						||
def init() -> Logger:
 | 
						||
    # 创建日志实例
 | 
						||
    global logger
 | 
						||
    logger = Logger(
 | 
						||
        name="my_app",
 | 
						||
        level=logging.DEBUG,
 | 
						||
        console=True,
 | 
						||
        file=True,
 | 
						||
        file_path="logs/app.log",
 | 
						||
        max_bytes=1024 * 1024,  # 1MB
 | 
						||
        backup_count=3,
 | 
						||
        mode="size"
 | 
						||
    )
 | 
						||
    return logger
 |