intellicrack.ui.log_viewer
Live log viewer package.
Provides a standalone QMainWindow (LogViewerWindow) that subscribes to the structlog stream via QtSignalingHandler and
backfills history from the on-disk JSON-Lines log file.
- class LogFileTailReader[source]
Bases:
QObjectWatches a JSON-Lines log file and emits new records as they appear.
The reader does an initial backfill on a worker thread, then uses a
QFileSystemWatcheron both the file and its parent directory so log rotation (truncate-or-rename) and slow first-write scenarios are handled. Each diff read is capped at_MAX_INCREMENTAL_BYTESbytes; if more data is available it re-schedules itself viaQTimer.singleShot()to keep the GUI responsive.- Variables:
record_emitted – Emitted with a
LogRecordDictfor each parsed line, including synthetic rotation notices.initial_load_complete – Emitted (with the offset where live tailing resumes) once the historical load finishes.
- __init__(log_path, max_initial_bytes=5242880, parent=None)[source]
Initialize the reader for the given log file.
- Parameters:
log_path (Path) – Path to the JSON-Lines log file (need not exist yet; the directory watcher will pick it up on creation).
max_initial_bytes (int) – Maximum number of trailing bytes read on first load.
parent (QObject | None) – Parent
QObjectfor ownership.
- Return type:
None
- start()[source]
Begin the initial historical load and set up file watching.
Repeated calls are no-ops once a load is in progress. Tests can call
force_poll()afterstart()if needed.- Return type:
None
- stop()[source]
Stop watching and tear down internal resources without blocking the GUI thread.
The historical-load worker is not owned by this reader (it is created with no parent in
start()), so it is safe to detach from it here even while it is still running: droppingself._initial_workerdoes not risk premature collection of the still-runningQThreadbecauseRetainedWorkeralready pinned it in the shared worker registry, which is immune to Python’s cyclic garbage collector. The worker keeps running in the background, is dropped from that registry once it finishes, and deletes itself via its ownfinishedsignal once the read completes. This avoids both a synchronous GUI-thread wait and the Qt crash that results from destroying aQThreadwhile it is still running.- Return type:
None
- force_poll()[source]
Trigger an immediate incremental read.
Useful for tests where signals from
QFileSystemWatchermay be delivered asynchronously.- Return type:
None
- class LogFilterProxyModel[source]
Bases:
QSortFilterProxyModelSort/filter proxy applying the viewer’s filter state to a model.
- Variables:
min_level (int) – Records with a numeric level below this value are hidden.
- __init__(parent=None)[source]
Initialize the proxy with permissive defaults.
- Parameters:
parent (QObject | None) – Parent
QObject.- Return type:
None
- min_level: int
- set_min_level(level)[source]
Set the minimum numeric level shown.
- Parameters:
level (int) – Numeric
logginglevel (e.g.logging.WARNING).- Return type:
None
- set_logger_pattern(pattern)[source]
Set the logger-name regex filter.
Invalid regular expressions silently clear the filter so the viewer remains usable while the user is mid-typing.
- Parameters:
pattern (str) – Regular-expression source string. Empty disables the filter.
- Return type:
None
- logger_pattern_source()[source]
Return the source string of the currently compiled logger pattern.
- Returns:
The pattern’s source, or empty string when no pattern.
- Return type:
- set_text_query(query)[source]
Set the free-text search query.
- Parameters:
query (str) – Substring to look for in the event identifier or the JSON form of the extras.
- Return type:
None
- set_case_sensitive(*, case_sensitive)[source]
Toggle whether the free-text search is case sensitive.
- Parameters:
case_sensitive (bool) –
Trueto match exactly as typed.- Return type:
None
- filterAcceptsRow(source_row, source_parent)[source]
Return whether the given source row passes all active filters.
- class LogRecordDetailsDialog[source]
Bases:
QDialogModal dialog showing the full JSON of a single log record.
- Variables:
record (intellicrack.ui.log_viewer._record.LogRecordDict) – The record being displayed.
- __init__(record, parent=None)[source]
Initialize the dialog with the given record.
- Parameters:
record (LogRecordDict) – Normalized log record to display.
parent (QWidget | None) – Parent widget.
- Return type:
None
- record: LogRecordDict
- class LogRecordDict[source]
Bases:
TypedDictNormalized log record shape consumed by the viewer model.
- Variables:
timestamp (str) – Human-readable timestamp string in local time.
level (str) – Upper-case level name (e.g.
"INFO").logger (str) – Dotted logger name.
module (str) – Source module short name.
function (str) – Source function name.
line_number (int) – Source line number, or
0when unknown.event (str) – The structured event identifier (the structlog
eventkey).extras (dict[str, object]) – Remaining structured key/value pairs from the event dict.
- timestamp: str
- level: str
- logger: str
- module: str
- function: str
- line_number: int
- event: str
- class LogRecordTableModel[source]
Bases:
QAbstractTableModelBounded ring-buffer table model for log records.
Incoming records are buffered into
_pendingand flushed in a singlebeginInsertRowstransaction on a 50 ms timer. The buffer is capped atmax_rowsand evicts the oldest entries viabeginRemoveRowsso views stay consistent under load.- Variables:
max_rows (int) – Soft cap on the number of stored rows.
- __init__(max_rows=50000, parent=None)[source]
Initialize the model with the given soft row cap.
- Parameters:
max_rows (int) – Maximum number of rows kept in the ring buffer.
parent (QObject | None) – Parent
QObjectfor ownership.
- Return type:
None
- max_rows: int
- property total_received: int
Total number of records ever appended.
- Returns:
Cumulative count, including evicted records.
- Return type:
- level_foreground(level)[source]
Return the resolved foreground color for a log level.
- Parameters:
level (str) – Log level name (e.g.
"INFO").- Returns:
- The theme-resolved foreground color, or
Nonewhen the level has no dedicated color.
- The theme-resolved foreground color, or
- Return type:
QColor | None
- level_background(level)[source]
Return the resolved background color for a log level.
- Parameters:
level (str) – Log level name (e.g.
"CRITICAL").- Returns:
- The theme-resolved background color, or
Nonewhen the level has no background override.
- The theme-resolved background color, or
- Return type:
QColor | None
- append_record(record)[source]
Queue a record for the next coalesced insert.
- flush()[source]
Force-drain pending records into the model immediately.
Useful in tests and at shutdown to avoid losing buffered rows.
- Return type:
None
- clear()[source]
Remove all records and pending buffers from the model.
- Return type:
None
- set_max_rows(max_rows)[source]
Update the row cap, evicting oldest rows if necessary.
- Parameters:
max_rows (int) – New row cap; clamped to
[1_000, 500_000].- Return type:
None
- record_at(row)[source]
Return the record at the given row, if any.
- Parameters:
row (int) – Row index into the underlying ring buffer.
- Returns:
- The record, or
Nonewhen out of range.
- The record, or
- Return type:
LogRecordDict | None
- all_records()[source]
Iterate over all stored records.
- Returns:
Iterator over the ring buffer.
- Return type:
Iterable[LogRecordDict]
- rowCount(parent=None)[source]
Return the number of rows currently stored.
- Parameters:
parent (QModelIndex | None) – Parent index; non-default values yield zero per table-model conventions.
- Returns:
Row count.
- Return type:
- columnCount(parent=None)[source]
Return the number of columns exposed by the model.
- Parameters:
parent (QModelIndex | None) – Parent index; non-default values yield zero per table-model conventions.
- Returns:
Fixed column count.
- Return type:
- headerData(section, orientation, role=ItemDataRole.DisplayRole)[source]
Return header text for the given section and orientation.
- class LogViewerWindow[source]
Bases:
QMainWindowModeless log viewer window.
Subscribes to the global
QtSignalingHandlerand tails the on-disk JSON-Lines log to backfill history. Owned by the main window; geometry and filter state persist viaQSettings.- Variables:
log_path (Path) – Path to the JSON-Lines log file currently displayed.
- __init__(config, parent=None)[source]
Initialize the viewer for the given application config.
- Parameters:
config (Config) – Application configuration providing the logs path.
parent (QWidget | None) – Optional parent window (typically the
MainWindow).
- Return type:
None
- log_path: Path
- property model: LogRecordTableModel
The underlying log-record table model.
- Returns:
The source model backing the table.
- Return type:
LogRecordTableModel
- property proxy: LogFilterProxyModel
The filter proxy connected between model and view.
- Returns:
The active proxy model.
- Return type:
LogFilterProxyModel
- property pause_action: QAction | None
The toolbar Pause action, available once the toolbar is built.
- Returns:
- The Pause
QAction, orNoneif the UI is not yet constructed.
- The Pause
- Return type:
QAction | None
- is_paused()[source]
Return whether the live capture is currently paused.
- Returns:
Truewhen the handler is suppressing emission.- Return type:
- set_min_level(level)[source]
Programmatically set the proxy’s minimum level filter.
- Parameters:
level (int) – Numeric
logginglevel (e.g.logging.WARNING).- Return type:
None
- clear()[source]
Clear all records from the model.
Public entry point exposed for callers that don’t have access to the toolbar’s Clear action.
- Return type:
None
- closeEvent(a0)[source]
Persist settings and detach the tail reader when the window closes.
- Parameters:
a0 (QCloseEvent | None) – Close event from Qt.
- Return type:
None
- class QtSignalingHandler[source]
Bases:
HandlerLogging handler that forwards records into a Qt signal.
The handler converts each accepted
logging.LogRecordinto aLogRecordDicton the calling thread, then emitsrecord_receivedso connected slots can run on the GUI thread via a queued connection. The handler is safe to install on the root logger alongside the existing console and file handlers.- Variables:
bridge (intellicrack.ui.log_viewer._handler._HandlerBridge) – Internal
QObjectexposingrecord_received.paused (bool) – When
True, records are accepted but no signal is emitted.
- __init__()[source]
Initialize the handler at level
NOTSETwith the structlog formatter pre-attached.- Return type:
None
- bridge: _HandlerBridge
- paused: bool
- property record_received: pyqtBoundSignal
Expose the bridge’s record-received signal.
- Returns:
- Bound signal emitted with a
LogRecordDict.
- Return type:
pyqtBoundSignal
- set_paused(*, paused)[source]
Toggle whether the handler emits to subscribers.
- Parameters:
paused (bool) –
Truesuppresses emission;Falseresumes it.- Return type:
None
- emit(record)[source]
Convert
recordto a dict and emit it on the bridge.Re-entrant emissions on the same thread are dropped to avoid infinite recursion when a connected slot logs. Emissions are skipped silently after the underlying
QObjectbridge has been destroyed (typical during application teardown) so the logging pipeline does not surfaceRuntimeErrorcascades while Qt cleanup is in progress.- Parameters:
record (LogRecord) – The standard logging record to forward.
- Return type:
None
- get_qt_log_handler()[source]
Return the currently installed Qt log handler, if any.
- Returns:
- The shared handler instance, or
Nonewhen not installed.
- Return type:
QtSignalingHandler | None
- install_qt_log_handler()[source]
Install (or return the existing) Qt-signaling handler on the root logger.
The function is idempotent: repeated calls return the same handler instance and do not attach duplicate handlers. The handler is attached to the root logger so it observes records from
intellicrack(which propagates) and any third-party libraries.- Returns:
The shared handler instance.
- Return type:
QtSignalingHandler
- level_name_to_int(name)[source]
Return the numeric
logginglevel for a name, defaulting toINFO.- Parameters:
name (str) – Upper- or lower-case level name (e.g.
"WARNING").- Returns:
Numeric level, or
logging.INFOwhen unknown.- Return type:
- parse_json_line(line)[source]
Parse a single JSON-Lines log entry into a
LogRecordDict.Lines that are blank, not valid JSON, or not JSON objects are skipped by returning
None. Missing fields fall back to safe defaults so the viewer never crashes on partially-written or non-structlog lines.- Parameters:
line (str) – A single text line from the log file.
- Returns:
- The parsed record, or
Nonewhen the line cannot be parsed as a structured record.
- The parsed record, or
- Return type:
LogRecordDict | None
- record_to_json_text(record)[source]
Render a record as a pretty-printed JSON string for the details dialog.
- Parameters:
record (LogRecordDict) – Normalized log record.
- Returns:
Indented JSON text safe to display in a monospace viewer.
- Return type:
- uninstall_qt_log_handler()[source]
Detach and forget the shared handler if one is installed.
Used by tests to keep state clean between cases. Safe to call when no handler has been installed.
- Return type:
None
Submodules
Modeless |