Files
Elevator/elevator_saga/utils/logger.py
2025-10-19 22:35:02 +08:00

209 lines
5.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Unified logging system for Elevator Saga
统一的日志系统 - 支持多级别、带颜色的日志输出
"""
import os
import sys
from enum import Enum
from typing import Optional
class LogLevel(Enum):
"""日志级别枚举"""
DEBUG = 0
INFO = 1
WARNING = 2
ERROR = 3
@classmethod
def from_string(cls, level_str: str) -> "LogLevel":
"""从字符串转换为日志级别"""
level_map = {
"DEBUG": cls.DEBUG,
"INFO": cls.INFO,
"WARNING": cls.WARNING,
"ERROR": cls.ERROR,
}
return level_map.get(level_str.upper(), cls.DEBUG)
class Color:
"""ANSI颜色代码"""
# 基础颜色
RESET = "\033[0m"
BOLD = "\033[1m"
# 前景色
BLACK = "\033[30m"
RED = "\033[31m"
GREEN = "\033[32m"
YELLOW = "\033[33m"
BLUE = "\033[34m"
MAGENTA = "\033[35m"
CYAN = "\033[36m"
WHITE = "\033[37m"
# 亮色
BRIGHT_BLACK = "\033[90m"
BRIGHT_RED = "\033[91m"
BRIGHT_GREEN = "\033[92m"
BRIGHT_YELLOW = "\033[93m"
BRIGHT_BLUE = "\033[94m"
BRIGHT_MAGENTA = "\033[95m"
BRIGHT_CYAN = "\033[96m"
BRIGHT_WHITE = "\033[97m"
class Logger:
"""统一日志记录器"""
def __init__(self, name: str = "ElevatorSaga", min_level: LogLevel = LogLevel.INFO, use_color: bool = True):
"""
初始化日志记录器
Args:
name: 日志记录器名称
min_level: 最低日志级别
use_color: 是否使用颜色
"""
self.name = name
self.min_level = min_level
self.use_color = use_color and sys.stdout.isatty()
# 日志级别对应的颜色
self.level_colors = {
LogLevel.DEBUG: Color.BRIGHT_BLACK,
LogLevel.INFO: Color.BRIGHT_CYAN,
LogLevel.WARNING: Color.BRIGHT_YELLOW,
LogLevel.ERROR: Color.BRIGHT_RED,
}
# 日志级别对应的标签
self.level_labels = {
LogLevel.DEBUG: "DEBUG",
LogLevel.INFO: "INFO",
LogLevel.WARNING: "WARNING",
LogLevel.ERROR: "ERROR",
}
def _format_message(self, level: LogLevel, message: str, prefix: Optional[str] = None) -> str:
"""
格式化日志消息
Args:
level: 日志级别
message: 消息内容
prefix: 可选的前缀(如模块名)
Returns:
格式化后的消息
"""
level_label = self.level_labels[level]
if self.use_color:
color = self.level_colors[level]
level_str = f"{color}{level_label:8}{Color.RESET}"
else:
level_str = f"{level_label:8}"
if prefix:
prefix_str = f"[{prefix}] "
else:
prefix_str = ""
return f"{level_str} {prefix_str}{message}"
def _log(self, level: LogLevel, message: str, prefix: Optional[str] = None) -> None:
"""
记录日志
Args:
level: 日志级别
message: 消息内容
prefix: 可选的前缀
"""
if level.value < self.min_level.value:
return
formatted = self._format_message(level, message, prefix)
print(formatted, flush=True)
def debug(self, message: str, prefix: Optional[str] = None) -> None:
"""记录DEBUG级别日志"""
self._log(LogLevel.DEBUG, message, prefix)
def info(self, message: str, prefix: Optional[str] = None) -> None:
"""记录INFO级别日志"""
self._log(LogLevel.INFO, message, prefix)
def warning(self, message: str, prefix: Optional[str] = None) -> None:
"""记录WARNING级别日志"""
self._log(LogLevel.WARNING, message, prefix)
def error(self, message: str, prefix: Optional[str] = None) -> None:
"""记录ERROR级别日志"""
self._log(LogLevel.ERROR, message, prefix)
def set_level(self, level: LogLevel) -> None:
"""设置最低日志级别"""
self.min_level = level
# 全局日志记录器实例
_global_logger: Optional[Logger] = None
def _get_default_log_level() -> LogLevel:
"""从环境变量获取默认日志级别默认为DEBUG"""
env_level = os.environ.get("ELEVATOR_LOG_LEVEL", "DEBUG")
return LogLevel.from_string(env_level)
def get_logger(name: str = "ElevatorSaga", min_level: Optional[LogLevel] = None) -> Logger:
"""
获取全局日志记录器
Args:
name: 日志记录器名称
min_level: 最低日志级别如果为None则从环境变量读取默认DEBUG
Returns:
Logger实例
"""
global _global_logger
if _global_logger is None:
if min_level is None:
min_level = _get_default_log_level()
_global_logger = Logger(name, min_level)
return _global_logger
def set_log_level(level: LogLevel) -> None:
"""设置全局日志级别"""
logger = get_logger()
logger.set_level(level)
# 便捷函数
def debug(message: str, prefix: Optional[str] = None) -> None:
"""记录DEBUG日志"""
get_logger().debug(message, prefix)
def info(message: str, prefix: Optional[str] = None) -> None:
"""记录INFO日志"""
get_logger().info(message, prefix)
def warning(message: str, prefix: Optional[str] = None) -> None:
"""记录WARNING日志"""
get_logger().warning(message, prefix)
def error(message: str, prefix: Optional[str] = None) -> None:
"""记录ERROR日志"""
get_logger().error(message, prefix)