64 lines
2.3 KiB
Python
64 lines
2.3 KiB
Python
# --- logger.py ---
|
|
import logging
|
|
import sys
|
|
|
|
# 定義終端機輸出的 ANSI 顏色
|
|
COLORS = {
|
|
"DEBUG": "\033[36m", # 青色 (Cyan)
|
|
"INFO": "\033[32m", # 綠色 (Green)
|
|
"WARNING": "\033[33m", # 黃色 (Yellow)
|
|
"ERROR": "\033[31m", # 紅色 (Red)
|
|
"CRITICAL": "\033[1;31m",# 粗體紅色 (Bold Red)
|
|
"RESET": "\033[0m" # 重置顏色
|
|
}
|
|
|
|
class ColoredFormatter(logging.Formatter):
|
|
def format(self, record):
|
|
log_color = COLORS.get(record.levelname, COLORS["RESET"])
|
|
# 格式:時間 | 等級 | 模組名稱 | 訊息
|
|
format_str = f"{log_color}%(asctime)s | %(levelname)-7s | %(name)-15s | %(message)s{COLORS['RESET']}"
|
|
formatter = logging.Formatter(format_str, datefmt="%Y-%m-%d %H:%M:%S")
|
|
return formatter.format(record)
|
|
|
|
# 定義系統中受管控的模組清單
|
|
MANAGED_LOGGERS = [
|
|
"app.database", # 資料庫操作
|
|
"app.scraper", # 爬蟲與快取
|
|
"app.diagnostics", # CM 診斷
|
|
"app.backup", # 備份與還原
|
|
"app.ssh" # SSH 連線引擎
|
|
]
|
|
|
|
def setup_logger(name: str, level=logging.INFO):
|
|
logger = logging.getLogger(name)
|
|
logger.setLevel(level)
|
|
# 避免重複添加 Handler 導致日誌印兩次
|
|
if not logger.handlers:
|
|
handler = logging.StreamHandler(sys.stdout)
|
|
handler.setFormatter(ColoredFormatter())
|
|
logger.addHandler(handler)
|
|
logger.propagate = False # 防止日誌往上傳遞給 root logger (避免被 FastAPI 預設格式覆蓋)
|
|
return logger
|
|
|
|
# 系統啟動時,初始化所有模組,預設等級為 INFO
|
|
for name in MANAGED_LOGGERS:
|
|
setup_logger(name, logging.INFO)
|
|
|
|
def get_logger(name: str):
|
|
"""供各個檔案引入 logger 使用"""
|
|
if name not in MANAGED_LOGGERS:
|
|
return setup_logger(name)
|
|
return logging.getLogger(name)
|
|
|
|
def get_all_log_levels():
|
|
"""取得目前所有模組的日誌等級 (供前端 UI 顯示)"""
|
|
return {name: logging.getLevelName(logging.getLogger(name).level) for name in MANAGED_LOGGERS}
|
|
|
|
def set_log_level(name: str, level_str: str):
|
|
"""動態設定特定模組的日誌等級"""
|
|
if name in MANAGED_LOGGERS:
|
|
level = getattr(logging, level_str.upper(), logging.INFO)
|
|
logging.getLogger(name).setLevel(level)
|
|
return True
|
|
return False
|