File size: 3,432 Bytes
621645b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3d87b51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
621645b
3d87b51
621645b
3d87b51
 
 
 
 
621645b
 
 
 
 
3d87b51
621645b
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/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"
    )