mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-04-12 05:42:14 -03:00
137 lines
4.4 KiB
Python
137 lines
4.4 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
import os
|
|
import threading
|
|
import uuid
|
|
from collections import deque
|
|
from dataclasses import dataclass
|
|
from datetime import datetime, timezone
|
|
from typing import Any
|
|
|
|
|
|
LOG_FORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
_SESSION_HANDLER_NAME = "lora_manager_standalone_session_memory"
|
|
_FILE_HANDLER_NAME = "lora_manager_standalone_session_file"
|
|
_session_state: "StandaloneSessionLogState | None" = None
|
|
_session_lock = threading.Lock()
|
|
|
|
|
|
@dataclass
|
|
class StandaloneSessionLogState:
|
|
started_at: str
|
|
session_id: str
|
|
log_file_path: str | None
|
|
memory_handler: "StandaloneSessionMemoryHandler"
|
|
|
|
|
|
class StandaloneSessionMemoryHandler(logging.Handler):
|
|
def __init__(self, capacity: int = 4000) -> None:
|
|
super().__init__()
|
|
self._entries: deque[str] = deque(maxlen=capacity)
|
|
self._lock = threading.Lock()
|
|
|
|
def emit(self, record: logging.LogRecord) -> None:
|
|
try:
|
|
rendered = self.format(record)
|
|
except Exception:
|
|
rendered = record.getMessage()
|
|
|
|
with self._lock:
|
|
self._entries.append(rendered)
|
|
|
|
def render(self, max_lines: int | None = None) -> str:
|
|
with self._lock:
|
|
entries = list(self._entries)
|
|
|
|
if max_lines is not None and max_lines > 0:
|
|
entries = entries[-max_lines:]
|
|
|
|
if not entries:
|
|
return ""
|
|
|
|
return "\n".join(entries) + "\n"
|
|
|
|
|
|
def _build_log_file_path(settings_file: str | None, started_at: datetime) -> str | None:
|
|
if not settings_file:
|
|
return None
|
|
|
|
settings_dir = os.path.dirname(os.path.abspath(settings_file))
|
|
log_dir = os.path.join(settings_dir, "logs")
|
|
os.makedirs(log_dir, exist_ok=True)
|
|
timestamp = started_at.strftime("%Y%m%dT%H%M%SZ")
|
|
return os.path.join(log_dir, f"standalone-session-{timestamp}.log")
|
|
|
|
|
|
def setup_standalone_session_logging(settings_file: str | None) -> StandaloneSessionLogState:
|
|
global _session_state
|
|
|
|
with _session_lock:
|
|
if _session_state is not None:
|
|
return _session_state
|
|
|
|
started_dt = datetime.now(timezone.utc)
|
|
started_at = started_dt.replace(microsecond=0).isoformat()
|
|
session_id = f"{started_dt.strftime('%Y%m%dT%H%M%SZ')}-{uuid.uuid4().hex[:8]}"
|
|
formatter = logging.Formatter(LOG_FORMAT)
|
|
root_logger = logging.getLogger()
|
|
if root_logger.level > logging.INFO:
|
|
root_logger.setLevel(logging.INFO)
|
|
|
|
memory_handler = StandaloneSessionMemoryHandler()
|
|
memory_handler.set_name(_SESSION_HANDLER_NAME)
|
|
memory_handler.setFormatter(formatter)
|
|
root_logger.addHandler(memory_handler)
|
|
|
|
log_file_path = _build_log_file_path(settings_file, started_dt)
|
|
if log_file_path:
|
|
file_handler = logging.FileHandler(log_file_path, encoding="utf-8")
|
|
file_handler.set_name(_FILE_HANDLER_NAME)
|
|
file_handler.setFormatter(formatter)
|
|
root_logger.addHandler(file_handler)
|
|
|
|
_session_state = StandaloneSessionLogState(
|
|
started_at=started_at,
|
|
session_id=session_id,
|
|
log_file_path=log_file_path,
|
|
memory_handler=memory_handler,
|
|
)
|
|
|
|
logger = logging.getLogger("lora-manager-standalone")
|
|
logger.info("LoRA Manager standalone startup time: %s", started_at)
|
|
logger.info("LoRA Manager standalone session id: %s", session_id)
|
|
if log_file_path:
|
|
logger.info("LoRA Manager standalone session log path: %s", log_file_path)
|
|
|
|
return _session_state
|
|
|
|
|
|
def get_standalone_session_log_snapshot(max_lines: int = 2000) -> dict[str, Any] | None:
|
|
state = _session_state
|
|
if state is None:
|
|
return None
|
|
|
|
return {
|
|
"started_at": state.started_at,
|
|
"session_id": state.session_id,
|
|
"log_file_path": state.log_file_path,
|
|
"in_memory_text": state.memory_handler.render(max_lines=max_lines),
|
|
}
|
|
|
|
|
|
def reset_standalone_session_logging_for_tests() -> None:
|
|
global _session_state
|
|
|
|
with _session_lock:
|
|
root_logger = logging.getLogger()
|
|
handlers_to_remove = [
|
|
handler
|
|
for handler in root_logger.handlers
|
|
if handler.get_name() in {_SESSION_HANDLER_NAME, _FILE_HANDLER_NAME}
|
|
]
|
|
for handler in handlers_to_remove:
|
|
root_logger.removeHandler(handler)
|
|
handler.close()
|
|
_session_state = None
|