CoolFace
Apppublic

xfvsdf/qqbot

sourceHugging Faceupdated 11mo agoView on Hugging Face
0likes
log.py143 linesDownload Raw Back to root
1"""2日志模块 - 使用环境变量配置3"""4import os5import sys6import threading7from datetime import datetime8 9# 日志级别定义10LOG_LEVELS = {11    'debug': 0,12    'info': 1,13    'warning': 2,14    'error': 3,15    'critical': 416}17 18# 线程锁,用于文件写入同步19_file_lock = threading.Lock()20 21# 文件写入状态标志22_file_writing_disabled = False23_disable_reason = None24 25def _get_current_log_level():26    """获取当前日志级别"""27    level = os.getenv('LOG_LEVEL', 'info').lower()28    return LOG_LEVELS.get(level, LOG_LEVELS['info'])29 30def _get_log_file_path():31    """获取日志文件路径"""32    return os.getenv('LOG_FILE', 'log.txt')33 34def _write_to_file(message: str):35    """线程安全地写入日志文件"""36    global _file_writing_disabled, _disable_reason37    38    # 如果文件写入已被禁用,直接返回39    if _file_writing_disabled:40        return41    42    try:43        log_file = _get_log_file_path()44        with _file_lock:45            with open(log_file, 'a', encoding='utf-8') as f:46                f.write(message + '\n')47                f.flush()  # 强制刷新到磁盘,确保实时写入48    except (PermissionError, OSError, IOError) as e:49        # 检测只读文件系统或权限问题,禁用文件写入50        _file_writing_disabled = True51        _disable_reason = str(e)52        print(f"Warning: File system appears to be read-only or permission denied. Disabling log file writing: {e}", file=sys.stderr)53        print(f"Log messages will continue to display in console only.", file=sys.stderr)54    except Exception as e:55        # 其他异常仍然输出警告但不禁用写入(可能是临时问题)56        print(f"Warning: Failed to write to log file: {e}", file=sys.stderr)57 58def _log(level: str, message: str):59    """60    内部日志函数61    """62    level = level.lower()63    if level not in LOG_LEVELS:64        print(f"Warning: Unknown log level '{level}'", file=sys.stderr)65        return66    67    # 检查日志级别68    current_level = _get_current_log_level()69    if LOG_LEVELS[level] < current_level:70        return71    72    # 格式化日志消息73    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")74    entry = f"[{timestamp}] [{level.upper()}] {message}"75    76    # 输出到控制台77    if level in ('error', 'critical'):78        print(entry, file=sys.stderr)79    else:80        print(entry)81    82    # 实时写入文件83    _write_to_file(entry)84 85def set_log_level(level: str):86    """设置日志级别提示"""87    level = level.lower()88    if level not in LOG_LEVELS:89        print(f"Warning: Unknown log level '{level}'. Valid levels: {', '.join(LOG_LEVELS.keys())}")90        return False91    92    print(f"Note: To set log level '{level}', please set LOG_LEVEL environment variable")93    return True94 95class Logger:96    """支持 log('info', 'msg') 和 log.info('msg') 两种调用方式"""97    98    def __call__(self, level: str, message: str):99        """支持 log('info', 'message') 调用方式"""100        _log(level, message)101 102    def debug(self, message: str):103        """记录调试信息"""104        _log('debug', message)105    106    def info(self, message: str):107        """记录一般信息"""108        _log('info', message)109    110    def warning(self, message: str):111        """记录警告信息"""112        _log('warning', message)113    114    def error(self, message: str):115        """记录错误信息"""116        _log('error', message)117    118    def critical(self, message: str):119        """记录严重错误信息"""120        _log('critical', message)121    122    def get_current_level(self) -> str:123        """获取当前日志级别名称"""124        current_level = _get_current_log_level()125        for name, value in LOG_LEVELS.items():126            if value == current_level:127                return name128        return 'info'129    130    def get_log_file(self) -> str:131        """获取当前日志文件路径"""132        return _get_log_file_path()133    134 135# 导出全局日志实例136log = Logger()137 138# 导出的公共接口139__all__ = ['log', 'set_log_level', 'LOG_LEVELS']140 141# 使用说明:142# 1. 设置日志级别: export LOG_LEVEL=debug (或在.env文件中设置)143# 2. 设置日志文件: export LOG_FILE=log.txt (或在.env文件中设置)