Skip to content

[Feature] Improve CLI Realtime Logs#100

Merged
antonio-amjr merged 4 commits into
project-chip:v2.16-cli-developfrom
antonio-amjr:feature/improve_cli_realtime_logs
Jul 7, 2026
Merged

[Feature] Improve CLI Realtime Logs#100
antonio-amjr merged 4 commits into
project-chip:v2.16-cli-developfrom
antonio-amjr:feature/improve_cli_realtime_logs

Conversation

@antonio-amjr

@antonio-amjr antonio-amjr commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Fix: project-chip/certification-tool#1026

Description

Extends the existing real-time log streaming feature with two new capabilities:

  • A new-execution notification banner
  • A navigatable test hierarchy tree panel.

New execution notification

  • Polls /api/status (every 3 s) after the current SSE stream ends, detecting when a new test run has started by comparing run_title and start_time
  • Displays a dismissable banner (⚠ New execution started) with a Reload button that refreshes the page and a Dismiss button that stops polling and keeps the current view
  • The page never auto-reloads — the user is always in control
  • A newExecutionPending flag gates all incoming SSE data handlers; while the flag is set, events are buffered rather than discarded — if the reconnection turns out to be the same execution (network hiccup), the buffer is replayed in order; if it is a new execution, the buffer is discarded and the banner is shown
  • Handles the async race between the connected SSE event and the /api/status fetch by setting the flag preemptively before the fetch resolves

Execution Tree panel

  • Sidebar showing the full test hierarchy: Run → Suite → Case → Step, with real-time state icons (pending / executing / passed / failed / error / skipped)
  • Tree is built from TestRunExecutionWithChildren in LogStreamHandler.init_tree() and broadcast as a tree_init SSE event; reconnecting clients receive the current snapshot directly from the shared tree_state dict
  • State updates streamed as tree_update SSE events, applied incrementally without re-rendering the whole tree
  • Each node is collapsible/expandable; toggles start in the expanded (▼) position matching the initially visible children
  • Clicking a step node scrolls the log panel to the corresponding log entry using a two-tier strategy:
    • Tier 1 (precise): pattern-matches "Executing Test Step: <title>" log entries and tags them as DOM anchors; clicking jumps directly to that entry
    • Tier 2 (fallback): records the log-entry index at the moment a tree_update(step, executing) event fires and scrolls to that index if no anchor is found
  • The tree does not auto-scroll to follow the currently executing step, so users can freely inspect earlier steps during a run

Files Changed

File Change
log_stream_handler.py Replaced single shared log_queue with a per-client broadcast set (_clients + _clients_lock); added _broadcast() which snapshots the set and puts events into every active client queue independently; added init_tree(), update_tree_node(), _build_tree(); mutable tree_state dict shared with HTTP server
logs_http_server.py stream_logs() now creates a per-client queue.Queue, registers it in the broadcast set on connect, and removes it in a finally block on disconnect — concurrent or reconnecting clients each receive their own complete event stream; added /api/status endpoint; SSE stream routes tree_init / tree_update event types; sends tree_state snapshot to reconnecting clients
websocket.py Calls get_log_stream_handler() on each test state update to forward tree events
logging.py Added get_log_stream_handler() accessor
log_viewer.html Split layout (tree sidebar + log panel), new-execution banner, full tree rendering and update logic, two-tier scroll anchoring

Unit Tests

Unit tests were updated to reflect the changes. Here's a summary of what changed in each file:

tests/test_run/test_log_stream_handler.py:

  • test_log_queue_is_queuetest_clients_is_empty_set — verifies _clients is an empty set
  • test_puts_none_sentinel_into_queuetest_broadcasts_none_sentinel_on_stop — registers a real client queue in h._clients, asserts it receives None after stop()
  • test_skips_sentinel_when_queue_fulltest_stop_does_not_raise_when_client_queue_full — pre-fills a client queue to capacity, asserts no raise
  • All TestAddLogEntry tests — replaced h.log_queue reads with either patch.object(h, "_broadcast") (for the no-op case) or a client queue registered in h._clients (for all data-content assertions)

tests/test_run/test_logs_http_server.py:

  • _make_handler — now sets explicit defaults: active_clients=set(), clients_lock=threading.Lock(), tree_state={}, tree_lock=None so stream_logs() never tries to deepcopy a MagicMock
  • Added _pre_filled_queue(*items) helper — returns a pre-populated queue for use with patch("...queue.Queue", return_value=...)
  • All TestStreamLogs tests — removed server_attrs={"log_queue": q}, now patch queue.Queue to return a pre-filled queue instead; test_no_log_queue_on_server_returns_early renamed to test_no_active_clients_on_server_returns_early with matching
    server_attrs
  • TestLogsHTTPServerStart — all three tests now call start(active_clients=..., clients_lock=..., tree_state={}, ...) instead of start(log_queue=...); test_sets_server_attributes asserts mock_ths.active_clients and mock_ths.clients_lock instead of mock_ths.log_queue

Screenshots

Screenshot 2026-07-03 at 10 32 08

@antonio-amjr antonio-amjr requested review from oxesoft and rquidute July 3, 2026 13:45
@antonio-amjr antonio-amjr self-assigned this Jul 3, 2026
@antonio-amjr antonio-amjr added the enhancement New feature or request label Jul 3, 2026
@mergify

mergify Bot commented Jul 3, 2026

Copy link
Copy Markdown

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces real-time log streaming and execution tree visualization to the test runner, updating the execution hierarchy dynamically and streaming updates to a web-based log viewer via Server-Sent Events (SSE). Key feedback highlights critical thread-safety issues where the shared tree_state dictionary is mutated and read across threads without synchronization, suggesting the introduction of a threading.Lock. Additionally, the reviewer noted that multiple concurrent clients will compete for the single shared log queue, recommending a broadcast pattern with client-specific queues. Other issues include potential event loss during reconnection status checks due to lack of buffering, and the use of the deprecated global window.event in the HTML log viewer.

Comment thread th_cli/test_run/log_stream_handler.py
Comment thread th_cli/test_run/log_stream_handler.py Outdated
Comment thread th_cli/test_run/log_stream_handler.py
Comment thread th_cli/test_run/log_stream_handler.py
Comment thread th_cli/test_run/logs_http_server.py
Comment thread th_cli/test_run/logs_http_server.py
Comment thread th_cli/test_run/logs_http_server.py Outdated
Comment thread th_cli/test_run/log_viewer.html
Comment thread th_cli/test_run/log_viewer.html Outdated
Comment thread th_cli/test_run/log_viewer.html Outdated
…nnections

Also, dropped events during reconnection are now buffered and replayed instead of silently lost.
@antonio-amjr antonio-amjr merged commit da831de into project-chip:v2.16-cli-develop Jul 7, 2026
3 of 4 checks passed
@antonio-amjr antonio-amjr deleted the feature/improve_cli_realtime_logs branch July 7, 2026 18:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants