From 7bd73d6e750889a6f4ae75ba1de8e8dbf557f550 Mon Sep 17 00:00:00 2001 From: vladmandic Date: Sat, 24 Jan 2026 13:54:37 +0100 Subject: [PATCH] log captured exceptions Signed-off-by: vladmandic --- CHANGELOG.md | 5 ++++- extensions-builtin/sdnext-modernui | 2 +- installer.py | 23 ++++++++++++++++++++--- modules/errors.py | 9 ++++++++- 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee9eb6d46..869b7d9f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## Todo - update `rocm/windows` - + ## Update for 2026-01-24 - **Features** @@ -23,7 +23,10 @@ - relocate all json data files to `data/` folder existing data files are auto-migrated on startup - further work on type consistency and type checking, thanks @awsr + - log captured exceptions - add ui placeholders for future agent-scheduler work, thanks @ryanmeador + - implement abort system on repeated errors, thanks @awsr + currently used by lora and textual-inversion loaders - update package requirements - **Fixes** - add video ui elem_ids, thanks @ryanmeador diff --git a/extensions-builtin/sdnext-modernui b/extensions-builtin/sdnext-modernui index cdddbbd17..188dd69e7 160000 --- a/extensions-builtin/sdnext-modernui +++ b/extensions-builtin/sdnext-modernui @@ -1 +1 @@ -Subproject commit cdddbbd17ac0f49fc4fccd5fac2446940294ca40 +Subproject commit 188dd69e7532f1d9db8174c8fcc67b47b2625aed diff --git a/installer.py b/installer.py index c47d7ac1e..06e25bb76 100644 --- a/installer.py +++ b/installer.py @@ -112,7 +112,7 @@ def install_traceback(suppress: list = []): width = os.environ.get("SD_TRACEWIDTH", console.width if console else None) if width is not None: width = int(width) - traceback_install( + log.excepthook = traceback_install( console=console, extra_lines=int(os.environ.get("SD_TRACELINES", 1)), max_frames=int(os.environ.get("SD_TRACEFRAMES", 16)), @@ -168,7 +168,6 @@ def setup_logging(): def get(self): return self.buffer - class LogFilter(logging.Filter): def __init__(self): super().__init__() @@ -215,6 +214,23 @@ def setup_logging(): logging.Logger.trace = partialmethod(logging.Logger.log, logging.TRACE) logging.trace = partial(logging.log, logging.TRACE) + def exception_hook(e: Exception, suppress=[]): + from rich.traceback import Traceback + tb = Traceback.from_exception(type(e), e, e.__traceback__, show_locals=False, max_frames=16, extra_lines=1, suppress=suppress, theme="ansi_dark", word_wrap=False, width=console.width) + # print-to-console, does not get printed-to-file + exc_type, exc_value, exc_traceback = sys.exc_info() + log.excepthook(exc_type, exc_value, exc_traceback) + # print-to-file, temporarily disable-console-handler + for handler in log.handlers.copy(): + if isinstance(handler, RichHandler): + log.removeHandler(handler) + with console.capture() as capture: + console.print(tb) + log.critical(capture.get()) + log.addHandler(rh) + + log.traceback = exception_hook + level = logging.DEBUG if (args.debug or args.trace) else logging.INFO log.setLevel(logging.DEBUG) # log to file is always at level debug for facility `sd` log.print = rprint @@ -240,8 +256,10 @@ def setup_logging(): ) logging.basicConfig(level=logging.ERROR, format='%(asctime)s | %(name)s | %(levelname)s | %(module)s | %(message)s', handlers=[logging.NullHandler()]) # redirect default logger to null + pretty_install(console=console) install_traceback() + while log.hasHandlers() and len(log.handlers) > 0: log.removeHandler(log.handlers[0]) @@ -288,7 +306,6 @@ def setup_logging(): logging.getLogger("torch").setLevel(logging.ERROR) logging.getLogger("ControlNet").handlers = log.handlers logging.getLogger("lycoris").handlers = log.handlers - # logging.getLogger("DeepSpeed").handlers = log.handlers ts('log', t_start) diff --git a/modules/errors.py b/modules/errors.py index 29566d597..a3397143a 100644 --- a/modules/errors.py +++ b/modules/errors.py @@ -17,11 +17,18 @@ def install(suppress=[]): def display(e: Exception, task: str, suppress=[]): - log.error(f"{task or 'error'}: {type(e).__name__}") if isinstance(e, ErrorLimiterAbort): return + log.critical(f"{task or 'error'}: {type(e).__name__}") + """ + trace = traceback.format_exc() + log.error(trace) + for line in traceback.format_tb(e.__traceback__): + log.error(repr(line)) console = get_console() console.print_exception(show_locals=False, max_frames=16, extra_lines=1, suppress=suppress, theme="ansi_dark", word_wrap=False, width=console.width) + """ + log.traceback(e, suppress=suppress) def display_once(e: Exception, task):