import logging import os import sys from logging.handlers import RotatingFileHandler class SystemLogger: """ 自定義系統日誌管理器 封裝 logging 模組,提供統一的日誌格式與輸出設定 (Console + File) """ def __init__(self, name="System", log_file='system.log'): self.logger = logging.getLogger(name) self.logger.setLevel(logging.DEBUG) # 避免重複添加 Handler (防止日誌重複輸出) if not self.logger.handlers: # 取得專案根目錄 (假設此檔案位於 utils/ 目錄下,往上兩層為根目錄) base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) log_dir = os.path.join(base_dir, 'logs') # 確保 logs 目錄存在 if not os.path.exists(log_dir): try: os.makedirs(log_dir) except OSError: pass # 忽略無法建立目錄的錯誤,改由 Console 輸出 file_path = os.path.join(log_dir, log_file) # 1. 檔案輸出 (RotatingFileHandler) - 支援自動切割 try: file_handler = RotatingFileHandler( file_path, maxBytes=10*1024*1024, # 10MB 切割 backupCount=5, encoding='utf-8' ) file_handler.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') file_handler.setFormatter(formatter) self.logger.addHandler(file_handler) except Exception as e: print(f"⚠️ Logger Init Warning: 無法建立日誌檔案 ({e})") # 2. 控制台輸出 (StreamHandler) console_handler = logging.StreamHandler(sys.stdout) console_handler.setLevel(logging.INFO) console_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') console_handler.setFormatter(console_formatter) self.logger.addHandler(console_handler) def get_logger(self): return self.logger