GUI: Add "Generate debug log" action#3328
Draft
C-Achard wants to merge 4 commits into
Draft
Conversation
Introduce a new debug subsystem under deeplabcut/core/debug. Adds an in-memory, bounded log recorder (InMemoryDebugRecorder) with safe fail-open semantics, helper functions to install/get the recorder, and a scoped log_timing context manager. Provides utilities to collect runtime, package, and external executable information (LibrarySpec, ExecutableSpec, collect_version_summary, collect_executable_summary, collect_debug_sections) and to format/assemble a full debug report (format_debug_report, build_debug_report). Includes small helper functions (_which, _command_version) and sane defaults (lists of core/GUI/TensorFlow libs, ffmpeg executable). Exports are wired in __init__.py.
Introduce a reusable debug text dialog and helper functions for generating and displaying DeepLabCut diagnostic reports. Adds deeplabcut/gui/dialogs/debug_dialog.py implementing DebugTextDialog (read-only log view with refresh/copy/keyboard shortcut), providers to render logs and full issue reports, show_debug_report_dialog to install/reuse recorders and present the report, and create_generate_debug_log_action to wire up a QAction. Also exports these symbols via deeplabcut/gui/dialogs/__init__.py. Dialog instances are attached to the parent to avoid GC and duplicate windows.
Import and install a debug recorder and add a "Generate Debug Log" action to the Help menu. The patch imports create_generate_debug_log_action and install_debug_recorder, creates a recorder (logger_name="deeplabcut"), builds the debug-log action with specified options (include_module_paths=False, include_executable_paths=True, log_limit=1000), inserts it into the Help menu with a separator, and adjusts menu sizing. This allows users to generate debug logs from the GUI.
Add a new test module for deeplabcut.core.debug covering InMemoryDebugRecorder and log_timing. Tests verify install_debug_recorder idempotency and retrieval, message and exception capture, bounded buffer behavior, render_text contents, clear() resetting records and drop count, and log_timing behavior when enabled, disabled, and with thresholding. Uses pytest fixtures to create isolated logger namespaces and monkeypatch to simulate timings and logger behavior.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds a DeepLabCut-scoped debug reporting utility (in-memory log recorder + environment/package/tool summary) and wires it into the GUI via a new Help → Generate debug log action that shows a copy/paste-ready report dialog.
Changes:
- Added
deeplabcut.core.debugutilities to record recent logs and build an environment/debug report. - Added a new GUI dialog + action factory to display/copy the generated debug report.
- Added a minimal pytest suite covering the in-memory recorder and timing context manager.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
deeplabcut/core/debug/debug_logger.py |
Implements the recorder, timing helper, environment/tool/package collection, and report formatting. |
deeplabcut/core/debug/_debug_utils.py |
Adds helper utilities for resolving executables and extracting version output. |
deeplabcut/core/debug/__init__.py |
Exposes the debug utilities as a public package API. |
deeplabcut/gui/dialogs/debug_dialog.py |
Adds a reusable dialog for viewing/copying debug text + helpers to open it from actions. |
deeplabcut/gui/dialogs/__init__.py |
Exports the new debug dialog helpers at the package level. |
deeplabcut/gui/window.py |
Installs the recorder at GUI startup and adds the Help menu action. |
tests/core/debug/test_logger.py |
Adds tests for recorder behavior and log_timing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+187
to
+202
| root_logger = logging.getLogger(logger_name) | ||
|
|
||
| existing = getattr(root_logger, _DEBUG_HANDLER_ATTR, None) | ||
| if isinstance(existing, InMemoryDebugRecorder): | ||
| return existing | ||
|
|
||
| recorder = InMemoryDebugRecorder(capacity=capacity, level=logging.DEBUG) | ||
| recorder.set_name("deeplabcut-debug-recorder") | ||
|
|
||
| # Important: | ||
| # - attach only to a DLC-owned logger namespace, not the global root logger | ||
| # - set logger level to DEBUG so DLC debug calls are emitted | ||
| # - keep propagation unchanged | ||
| root_logger.addHandler(recorder) | ||
| root_logger.setLevel(logging.DEBUG) | ||
|
|
| executables=executables, | ||
| include_paths=include_executable_paths, | ||
| ) | ||
| if exec_items and _section_has_useful_values(exec_items): |
Comment on lines
+113
to
+115
| # Debug recorder | ||
| self._debug_recorder = install_debug_recorder(logger_name="deeplabcut") | ||
|
|
Comment on lines
+198
to
+205
| dlg = getattr(parent, attr_name, None) | ||
| if isinstance(dlg, DebugTextDialog): | ||
| return dlg | ||
|
|
||
| dlg = DebugTextDialog( | ||
| title=title, | ||
| text_provider=text_provider, | ||
| parent=parent, |
Comment on lines
+3
to
+6
| from .debug_logger import ( | ||
| DLC_ALL_LIBS_SPECS, | ||
| DLC_LOG_TIMING, | ||
| LOG_QUEUE_MAXLEN, |
Comment on lines
+1
to
+5
| from __future__ import annotations | ||
|
|
||
| import logging | ||
| import platform | ||
| import sys |
Comment on lines
+1
to
+5
| from __future__ import annotations | ||
|
|
||
| import shutil | ||
| import subprocess | ||
| from collections.abc import Sequence |
Comment on lines
+1
to
+2
| from collections.abc import Sequence | ||
|
|
Comment on lines
+1
to
+5
| from collections.abc import Sequence | ||
|
|
||
| from .debug_dialog import ( | ||
| DebugTextDialog, | ||
| create_generate_debug_log_action, |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
To standardize error reports and make it easier for users to share diagnostics, this PR adds a utility that generates a copy-pasteable summary of the user environment.
This is added here with three components:
Scope
The initial version added here provides:
Debug utils
loggingGUI
Tests
Note
No project or config info is included as of yet. This could be a very worthwhile extension in subsquent PRs.
Automated summary
This pull request introduces a new debug logging and reporting system for DeepLabCut, including both core functionality and GUI integration. The changes provide a robust mechanism to capture, view, and report diagnostic information, making it easier for users and developers to troubleshoot issues. The update also adds comprehensive tests for the debug recorder and integrates a new "Generate debug log" action into the application's Help menu.
Core debug logging and reporting system:
deeplabcut.core.debugpackage that exposes debug logging utilities and report generation functions, includingInMemoryDebugRecorder,build_debug_report, and related helpers via its__init__.py._debug_utils.pywith helper functions to resolve executable paths and versions, supporting richer debug reports.GUI integration:
debug_dialog.py, a new GUI dialog for displaying and copying debug logs and reports, with utilities to create actions and dialogs for generating debug logs.gui/dialogs/__init__.pyto export the new debug dialog utilities.window.py), initializing it on startup and adding a "Generate debug log" action to the Help menu for easy access. [1] [2] [3] [4]Testing:
test_logger.py) covering recorder installation, message capture, bounded queue behavior, text rendering, clearing, and log timing utilities.