Files
olivv-cs-ComfyUI-FunPack/core/backend_log.py
T
digital-garbage 6371c4ad48 core, app: ComfyUI's log, where a user can reach it
Fourth off the port list. Users do not open devtools, and "it did not work"
with nothing to read is where a bug report dies -- especially on a rented box
behind a tunnel, where the terminal that has the answer is not on this desk.

Read from ComfyUI's own log FILE rather than from a buffer in this process.
v4 kept both and its own comment says why the file is the half that matters: a
crash and restart empties an in-memory buffer, and the lines from before the
crash are exactly the ones worth reading. So this is the smaller half and the
more useful one.

Three things the panel refuses to do, each because of what a log is FOR:

* It does not redraw while text is being selected. Copying a stack trace is the
  one thing anybody opens a log to do, and a panel that repaints under the drag
  makes it impossible.
* It keeps the last lines when the server stops answering. The most interesting
  thing a log can say is that ComfyUI just died, and replacing the lines from
  just before it went with the error that says it is gone throws away the only
  evidence of why.
* No log file is an ANSWER, with the reason and where to look instead. An empty
  list reads as a quiet log, and the difference matters precisely when somebody
  opened the panel because something else already broke.
2026-09-06 14:13:47 +03:00

65 lines
2.5 KiB
Python

"""The last lines ComfyUI printed.
Users do not open devtools, and "it did not work" with nothing to read is where
a bug report dies. This is the log they can actually reach.
Read from ComfyUI's own file rather than from a buffer in this process. v4 kept
both and its own docstring says why the file is the half that matters: a
CRASH AND RESTART empties an in-memory buffer, and the lines before the crash
are exactly the ones worth reading. A file survives it. So this is the smaller
half and the more useful one, and the buffer can be added if a case turns up
that the file misses.
Never raises. A log panel that fails is worse than one that says it found no
file, because the reason someone opened it is that something else already broke.
"""
from __future__ import annotations
from pathlib import Path
#: Read from the end. A ComfyUI log runs to megabytes over a long session and
#: nobody scrolls back through a boot from three days ago.
MAX_BYTES = 512 * 1024
MAX_LINES = 2000
def log_file() -> Path | None:
"""ComfyUI's log, or None when this install does not write one."""
try:
import folder_paths
base = Path(folder_paths.base_path)
except Exception: # noqa: BLE001
return None
for name in ("comfyui.log", "comfyui.prev.log"):
candidate = base / "user" / name
if candidate.is_file():
return candidate
return None
def recent(limit: int = 600) -> dict:
"""`{lines, path, detail}`. `detail` is set only when there is nothing to show.
The absence of a log is a real state with a real cause -- ComfyUI started
without one -- so it is reported as an answer rather than as an empty list
that looks like a quiet log.
"""
limit = max(1, min(int(limit or 600), MAX_LINES))
path = log_file()
if path is None:
return {"lines": [], "path": None,
"detail": "ComfyUI is not writing a log file here, so there is nothing "
"to show. Its output is in the terminal it was started from."}
try:
size = path.stat().st_size
with path.open("rb") as fh:
if size > MAX_BYTES:
fh.seek(size - MAX_BYTES)
fh.readline() # drop the partial first line
text = fh.read().decode("utf-8", errors="replace")
except OSError as exc:
return {"lines": [], "path": str(path),
"detail": f"Could not read {path.name}: {exc.strerror or exc}."}
return {"lines": text.splitlines()[-limit:], "path": str(path), "detail": ""}