import logging import os from config import LOG_LEVEL __all__ = ["get_logger"] DEFAULT_LOG_LEVEL = LOG_LEVEL class ColoredFormatter(logging.Formatter): """Optional: Add colors for better readability in terminal""" # ANSI color codes COLORS = { 'DEBUG': '\033[36m', # Cyan 'INFO': '\033[32m', # Green 'WARNING': '\033[33m', # Yellow 'ERROR': '\033[31m', # Red 'CRITICAL': '\033[35m', # Magenta } RESET = '\033[0m' def format(self, record: logging.LogRecord) -> str: if record.levelname in self.COLORS: record.levelname = ( f"{self.COLORS[record.levelname]}" f"[{record.levelname}]{self.RESET}" ) return super().format(record) def get_logger( name: str = "lifeflow", use_colors: bool = True, level: str = None ) -> logging.Logger: """ 取得 Logger 實例 Args: name: Logger 名稱 use_colors: 是否使用彩色輸出(預設開啟) Returns: Logger Example: logger = get_logger(__name__) logger.info("Operation completed") try: risky_operation() except Exception as e: logger.error("Operation failed", exc_info=True) logger.debug(f"Processing {len(items)} items") """ logger = logging.getLogger(name) # 避免重複設定 if logger.handlers: return logger log_level = os.getenv("LOG_LEVEL", DEFAULT_LOG_LEVEL) if level is None else level logger.setLevel(log_level.upper() if isinstance(log_level, str) else log_level) # 建立 Console Handler handler = logging.StreamHandler() handler.setLevel(log_level) # 選擇 Formatter if use_colors and os.getenv("NO_COLOR") is None: # 終端機支援顏色 formatter = ColoredFormatter( fmt="%(levelname)-7s | %(asctime)s | %(name)s: %(message)s", datefmt="%H:%M:%S" ) else: # 純文字(例如:導向檔案、CI/CD 環境) formatter = logging.Formatter( fmt="%(levelname)-5s | (asctime)s | %(name)s: %(message)s", datefmt="%Y-%m-%d %H:%M:%S" ) handler.setFormatter(formatter) logger.addHandler(handler) logger.propagate = False return logger