Skip to content

Expose cmux events diagnostics - #3935

Closed
austinywang wants to merge 21 commits into
mainfrom
issue-3672-cmux-events-diagnostics
Closed

austinywang wants to merge 21 commits into
mainfrom
issue-3672-cmux-events-diagnostics

Conversation

@austinywang

@austinywang austinywang commented May 12, 2026 •

Copy link
Copy Markdown
Contributor

Closes #3672.

Summary

  • Add cmux events status and events.status diagnostics for event bus retention, subscriptions, durable log paths/sizes, queue depth, and disk-only drops.
  • Add resettable disk-only drop counters while keeping unreported logging separate.
  • Document interpreting disk-only drops versus ack.resume.gap and add diagnostics unit coverage.

Testing

  • Not run locally per repo instructions; CI will run the test suite.

Note

Medium Risk
Adds a new socket RPC and CLI subcommand that surface internal event-bus and durable-log counters; risk is mainly around concurrency/locking and correctness of the new diagnostics/counter-reset behavior.

Overview
Adds cmux events status [--reset-counters] and a new v2 socket method events.status to fetch event-bus diagnostics as JSON (retention bounds/counts, active subscriptions with pending depth/limits, and durable event-log paths/sizes/queue depth plus disk-only drop counters).

Implements new internal tracking for slow-subscriber closures and refactors the durable log writer to maintain cached file sizes and separate reported vs logged drop counters, with optional counter reset. Updates capabilities/help/docs accordingly and adds unit tests covering the diagnostics payload, null sequence bounds, and reset semantics.

Reviewed by Cursor Bugbot for commit 0e80a2a. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Adds cmux events status and the events.status v2 RPC to print event-bus diagnostics as JSON, with an option to reset counters. Covers retention window, active subscriptions, and durable log paths/sizes/queue state; advertised in capabilities and CLI help. Implements #3672.

  • New Features

    • Added cmux events status [--reset-counters] and events.status; CLI prints JSON only.
    • Status includes protocol/version/boot_id, oldest_seq/latest_seq (null when empty)/next_seq, retained and active subscription counts, per-subscription names/categories/pending/max, slow_subscription_close_count, limits, and durable log enabled flag, paths, cached current/rotated sizes, queue depth/limit, and disk-only drop count.
    • Docs updated with payload schema, examples, gap and reset semantics, and note that diagnostics contain operational metadata only.
  • Bug Fixes

    • Count slow-subscriber closures; counter is resettable.
    • Reliable boolean reset_counters parsing from the socket worker; align disabled durable-log field types; use null for empty sequence bounds.

Written for commit 0e80a2a. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • New Features

    • Added cmux events status CLI subcommand (JSON output) with --reset-counters.
    • Diagnostics now report per-subscription pending details, slow-close counts, durable-log current/rotated sizes, and separated drop counters.
    • events.status made available via the socket RPC interface.
  • Documentation

    • CLI contract and user docs updated with usage, semantics, examples, and diagnostics interpretation.
  • Tests

    • New tests covering diagnostics output and durable log state.

Review Change Stack

@vercel

vercel Bot commented May 12, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment May 19, 2026 7:00am
cmux-staging Building Building Preview, Comment May 19, 2026 7:00am

@coderabbitai

coderabbitai Bot commented May 12, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR implements the cmux events status command and V2 RPC method to expose event-bus diagnostics, including retained sequence bounds, subscription metrics, slow-close counters, durable log file sizes, and disk-backpressure drop counts, with optional counter reset.

Changes

Event Diagnostics and Status Command

Layer / File(s) Summary
Event bus and durable log diagnostics
Sources/CmuxEventBus.swift, Sources/CmuxEventLogWriter.swift
CmuxEventSubscription and CmuxEventBus expose diagnosticsSnapshot() methods reporting subscription state, sequence bounds, and slow-subscription-close counters. CmuxEventLogWriter splits dropped-line tracking into disk-pressure and unreported counters, caches current/rotated file sizes on init and after I/O, and surfaces them via diagnosticsSnapshot(resetCounters:).
Socket RPC exposure
Sources/TerminalController.swift, Sources/TerminalControllerV2ParamParsingSupport.swift
Adds events.status as a V2 socket worker method that retrieves CmuxEventBus.diagnosticsSnapshot(), optionally resetting counters from request params. Updates v2Bool to nonisolated to support parameter parsing in the handler context. Method is included in advertised capabilities.
CLI status subcommand
CLI/CMUXCLI+Events.swift, CLI/cmux.swift
runEventsCommand routes a status argument to new runEventsStatusCommand, which parses --reset-counters, connects to the socket, calls the events.status RPC, and prints JSON diagnostics. Help text and global synopsis are updated to document the subcommand.
Test coverage
cmuxTests/CmuxEventBusTests.swift
New test cases validate diagnosticsSnapshot() structure (sequence bounds, subscription/durable-log metrics, counter state), verify NSNull bounds when retention is empty, and confirm counter reset behavior for slow closes and disk drops. Log rotation tests assert cached file sizes match the configured byte limits.
Documentation
docs/cli-contract.md, docs/events.md
CLI contract table and protocol spec document events and events status subcommands. events.md adds quick-start examples, clarifies ack.resume.gap semantics, explains disk-only drop interpretation, and introduces a Diagnostics section describing the status command, reset controls, and payload structure.

Sequence Diagram

sequenceDiagram
  participant CLI as cmux CLI
  participant TerminalController
  participant CmuxEventBus
  participant CmuxEventLogWriter
  CLI->>TerminalController: events.status RPC (reset_counters=true)
  TerminalController->>CmuxEventBus: diagnosticsSnapshot(resetCounters: true)
  CmuxEventBus->>CmuxEventBus: collect sequence/retained bounds
  CmuxEventBus->>CmuxEventBus: snapshot active subscriptions
  CmuxEventBus->>CmuxEventLogWriter: retrieve durable_log state
  CmuxEventLogWriter->>CmuxEventLogWriter: return cached sizes and counters
  CmuxEventLogWriter->>CmuxEventLogWriter: reset disk-only drop counter
  CmuxEventBus->>CmuxEventBus: reset slow-close counter
  CmuxEventBus-->>TerminalController: diagnostics dict
  TerminalController-->>CLI: OK response with JSON payload
  CLI->>CLI: print formatted JSON
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A little rabbit peeks in code so bright,

Diagnostics hop into the light,
Counters counted, files sized just so,
Status prints the health we need to know,
Hooray — the event-bus starts to glow!


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (3 errors, 1 warning, 2 inconclusive)

Check name Status Explanation Resolution
Cmux Swift Blocking Runtime ❌ Error CLI/CMUXCLI+Events.swift's waitBeforeReconnectingEventStream() uses Timer and RunLoop.run() for blocking 1-sec waits, violating swift-blocking-runtime rules for shipped code. Use async/await, DispatchSourceTimer, or callbacks instead of blocking Timer+RunLoop pattern for reconnect delays.
Cmux User-Facing Error Privacy ❌ Error Line 136 echoes unvalidated user input in error message. Violates privacy rules against exposing unredacted user-supplied values. Use generic message without echoing argument: "Unknown events status option. Use --help for usage."
Cmux Architecture Rethink ❌ Error Review comment flagged line 136 echoing raw arg values in error message ("Unknown events status option: \(arg)"), violating user-facing-errors.md. The fix was not applied. Replace "Unknown events status option: \(arg)" with generic message "Unknown events status option. Use --help for usage." to avoid exposing unredacted user input.
Docstring Coverage ⚠️ Warning Docstring coverage is 2.94% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Cmux Swift Auxiliary Window Close Shortcuts ❓ Inconclusive No result was produced after verification. Marking as INCONCLUSIVE. Re-run the check or adjust instructions to produce a final result.
Description check ❓ Inconclusive The PR description addresses the Summary and Testing sections of the template, but lacks a Demo Video section, incomplete checklist, and missing Review Trigger copy/paste block. Add Demo Video section (or note N/A for non-UI changes), include the requested Review Trigger block, and complete the checklist items with explicit confirmations or explanations.
✅ Passed checks (10 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Expose cmux events diagnostics' accurately and concisely describes the main feature addition: a new diagnostics surface for the cmux events subsystem.
Linked Issues check ✅ Passed All requirements from issue #3672 are met: CLI surface (cmux events status + events.status RPC) [#3672], diagnostics payload (boot_id, seq bounds, counts, per-subscription details) [#3672], durable log metadata (paths, sizes, queue depth, disk-only drops) [#3672], redacted payloads [#3672], documentation on drops vs ack.resume.gap [#3672], and unit test coverage [#3672].
Out of Scope Changes check ✅ Passed All changes are scope-aligned with #3672: diagnostics CLI/RPC, event bus counters/snapshots, durable log size caching, test coverage, and documentation updates. No extraneous changes detected.
Cmux Swift Actor Isolation ✅ Passed No Swift 6 actor isolation mistakes found. v2Bool marked nonisolated correctly. All @unchecked Sendable types properly locked. No implicit MainActor types.
Cmux No Hacky Sleeps ✅ Passed PR only modifies Swift source code and documentation. Check scope excludes Swift (covered separately) and only applies to TypeScript, JavaScript, shell scripts.
Cmux Swift Concurrency ✅ Passed New code is synchronous. No fire-and-forget Tasks, DispatchQueue.global().async, Combine usage, or completion handlers introduced. Snapshot methods use NSLock. No legacy concurrency patterns detected.
Cmux Swift @Concurrent ✅ Passed No Swift @concurrent annotation violations found. The v2Bool change from func to nonisolated func is correct for a pure synchronous helper. All async context properly handled.
Cmux Swift File And Package Boundaries ✅ Passed PR complies with Swift file/package boundary rules. New file (297 lines) has single responsibility. Oversized files touched incidentally. No mixed concerns or package boundary violations.
Cmux Swift Logging ✅ Passed No Swift logging violations found. Production code has no print/debugPrint/dump/NSLog; proper Logger with nonisolated isolation; privacy markers on sensitive data. CLI output is allowed.
Cmux Swiftui State Layout ✅ Passed This PR adds event bus diagnostics without any SwiftUI code. No SwiftUI imports, state annotations, or view definitions found. Check not applicable.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-3672-cmux-events-diagnostics

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented May 12, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds cmux events status [--reset-counters] and the events.status v2 socket RPC to expose event-bus diagnostics as JSON, closing #3672. It addresses all three issues raised in previous review threads: file-stat I/O is now cached on the IO queue rather than blocking the socket worker; null oldest_seq/latest_seq are correctly returned when the retained buffer is empty; and the new test is properly marked throws.

  • CmuxEventBus gains diagnosticsSnapshot() with a locked snapshot of retention state, active subscriptions, and a new resettable slowSubscriptionCloseCount; the eventLogWriter delegates to its own snapshot method.
  • CmuxEventLogWriter splits the old droppedLineCount into droppedDiskOnlyLineCount (user-visible, resettable) and unreportedDroppedLineCount (internal flush-warning tracker); currentLogSizeBytes/rotatedLogSizeBytes are cached and updated on the IO queue after each write batch and rotation so no filesystem stats are ever performed on the socket worker.
  • TerminalController routes events.status to the socket-worker execution policy (correctly off the main actor) and advertises it in capabilities; v2Bool is correctly narrowed to nonisolated since it accesses no actor state.

Confidence Score: 5/5

Safe to merge — all three threading and correctness issues from the prior review are resolved, and the new diagnostics path is cleanly isolated from the socket worker and main actor.

The lock discipline is consistent throughout: CmuxEventBus and CmuxEventLogWriter each protect their mutable state with NSLock and release before calling out; cached log sizes are updated exclusively on the IO queue; diagnosticsSnapshot() snapshots all values under the lock then does heavier subscription mapping outside it. The nonisolated annotation on v2Bool is correct since the method reads only from its parameters. No actor isolation mistakes, blocking primitives on the wrong queue, or data races were found.

No files require special attention.

Important Files Changed

Filename Overview
Sources/CmuxEventBus.swift Adds diagnosticsSnapshot() with locked reads for retention metadata, subscription snapshots, slow-close counter, and durable-log delegation; counter reset logic is correct; null sequence bounds when retained buffer is empty.
Sources/CmuxEventLogWriter.swift Splits droppedLineCount into droppedDiskOnlyLineCount and unreportedDroppedLineCount; caches log sizes updated on the IO queue after each write batch and rotation; no file stats on the socket worker thread.
Sources/TerminalController.swift Adds events.status to socketWorkerV2Methods (correctly off the main actor) and to capabilities; handler calls CmuxEventBus.shared.diagnosticsSnapshot safely.
Sources/TerminalControllerV2ParamParsingSupport.swift Marks v2Bool as nonisolated so it can be called from the nonisolated socketWorkerV2Response; safe because the function only reads from its parameters.
CLI/CMUXCLI+Events.swift Routes cmux events status [--reset-counters] to a new handler; arg parsing is simple and correct; sends events.status RPC and prints the JSON payload.
cmuxTests/CmuxEventBusTests.swift Adds four test cases covering the full diagnostics payload, null sequence bounds on empty buffer, slow-close counter reset, and disk-only drop counter reset without clearing pending depth.

Reviews (17): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile

Comment thread Sources/CmuxEventLogWriter.swift
Comment thread Sources/CmuxEventBus.swift
Comment thread cmuxTests/CmuxEventBusTests.swift Outdated
coderabbitai[bot]
coderabbitai Bot previously requested changes May 18, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CLI/cmux.swift`:
- Line 9309: The help text for the "cmux events status" subcommand omits an
explanation for the "--reset-counters" flag; update the status subcommand's help
block (the "cmux events status" usage/help generation code) to add an Options
section documenting "--reset-counters" and its effect, e.g., " --reset-counters 
Reset resettable diagnostic counters (slow_subscription_close_count,
dropped_disk_only_line_count)"; locate the help string or function that prints
the status subcommand help (the code that emits the usage line "cmux events
status [--reset-counters]") and insert this brief option description there so
users see it inline with other status options.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: cec631cf-4e23-49bf-87db-31c0561d209e

📥 Commits

Reviewing files that changed from the base of the PR and between 8eda4dd and 79b92af.

📒 Files selected for processing (3)
  • CLI/cmux.swift
  • Sources/TerminalController.swift
  • docs/cli-contract.md

Comment thread CLI/cmux.swift

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 9 files

Re-trigger cubic

@austinywang

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 18, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]
coderabbitai Bot previously requested changes May 18, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CLI/CMUXCLI`+Events.swift:
- Line 136: The error currently throws CLIError with the raw arg interpolated
("Unknown events status option: \(arg)"), which can leak secrets; change the
thrown message to a generic user-facing message such as "Unknown events status
option; run --help for valid options" and avoid including arg in the message,
while optionally logging the raw arg to a debug log only. Update the throw site
where CLIError is constructed (the Unknown events status option branch in the
events/status option handling) to use the generic message and, if needed, emit
the raw arg to a non-user-facing debug/logger call instead of the exception.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 70c1d226-dba9-436e-9d64-9e20d510c21c

📥 Commits

Reviewing files that changed from the base of the PR and between 79b92af and cede07a.

📒 Files selected for processing (3)
  • CLI/CMUXCLI+Events.swift
  • CLI/cmux.swift
  • Sources/TerminalController.swift

Comment thread CLI/CMUXCLI+Events.swift Outdated
@austinywang
austinywang dismissed stale reviews from coderabbitai[bot] and coderabbitai[bot] May 19, 2026 04:46

Stale CodeRabbit review: the inline reset-counters help thread is resolved and CodeRabbit confirmed it was addressed after commit b648454.

@lawrencecchen lawrencecchen added the stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening. label Sep 23, 2026
@github-project-automation github-project-automation Bot moved this from Todo to Done in cmux backlog Sep 23, 2026

This branch was successfully deployed

1 active deployment
Preview – cmux — 0e80a2ab Deployed May 19, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose cmux events diagnostics and backpressure counters

3 participants