Skip to content

feat(player): richer stats for nerds with plan detail and recent events - #36

Closed
JonahMMay wants to merge 1 commit into
fix/restore-prairie-customizationsfrom
feat/richer-stats-for-nerds
Closed

JonahMMay wants to merge 1 commit into
fix/restore-prairie-customizationsfrom
feat/richer-stats-for-nerds

Conversation

@JonahMMay

Copy link
Copy Markdown

Stacked on #35 (base fix/restore-prairie-customizations). Merge #35 first. GitHub then retargets this PR to main.

Problem

Stats for nerds on iOS and tvOS showed only Aether telemetry. When a stream failed or degraded, the panel did not show the server's plan, why the planner chose it, or the player's own error. prairie-smarttv Silo-Server#116 and the web overlay already show this.

Solution

Reuses PlaybackStats, AetherPlaybackStatsProjection and PlaybackStatsPanel. The new Prairie-only logic is in Screens/Player/PlaybackDiagnostics.swift (pure Foundation):

  • Plan section (new rows in PlaybackStats.planRows):
    • Method: Direct play, Remux (progressive/HLS) or Transcode (HLS)
    • Plan: container, video codec, resolution, dynamic range, audio codec, channels and bitrate from the protocol-v3 effective_recipe, falling back to source
    • Planner reason (decision_reason)
    • Quality: the active picker label
    • Audio track: the selected track's label with language, channels and codec, plus its track id
    • Stream path: the kind (Remote, Loopback proxy or Offline file) and the path with query, fragment, user info, ids/signatures (:id) and media filenames ([media]) removed
  • Recent events: PlaybackEventLog is a ring buffer of the last 8 events, recorded whether or not diagnostics upload is on.
    • Events recorded: plan committed, first frame, rebuffering, stalls, ended, replans (warning for recovery, info for user changes), quality and audio changes, external playback, typed Aether failures, and untyped playback errors.
    • Messages pass through MediaLogRedactor, capped at 160 characters.
    • Consecutive repeats collapse into one entry with a ×N count, so a flapping state cannot push the causing error out of the buffer.
    • The log survives item teardown, so an error stays readable after it happens.
  • tvOS Info HUD stats pane: Plan sits under Source in the left column. Recent events (timestamp and message, colored by severity) close the right column and are a paging target.
  • iOS overlay: the plan rows join the compact set, and long values wrap at 320 pt. The event list sits beside the rows when the screen is wide enough (landscape) and drops to 4 events below them otherwise. The overlay stays inert.
  • Resolution, bitrate, dropped frames and buffer rows already existed. They are unchanged.

Tests

  • New PlaybackDiagnosticsTests: ring buffer capacity and order, repeat collapse, severity not collapsed, blank or zero-capacity input, redaction and length cap, time and severity formatting, event row order and identity, plan summary formatting for every delivery, a summary built from the vendored v2 plan fixture, and stream-path redaction (query, user info, UUID, loopback, manifest names kept, media filenames, offline files).
  • AetherPlaybackStatsProjectionTests: plan detail passes through to PlaybackStats, and tokens never reach any row.
  • The invariant manifest gains 6 anchors (53 total, all passing).

Risks

  • UI layout has only been checked in code review. I had no simulator, so I have no screenshots. Please check the tvOS pane and the iOS landscape overlay on a device.

AI disclosure: written by Claude Opus 5.5 (claude-opus-5-5[1m]) in the Claude Code agent harness. No other AI tooling.

🤖 Generated with Claude Code

Stats for nerds showed Aether telemetry only, so a failed or degraded
stream said nothing about what the server planned or what went wrong.
Match prairie-smarttv Silo-Server#116 on iOS and tvOS:

- Plan section: method (direct play / remux / transcode), container,
  codecs, resolution, dynamic range and bitrate from the protocol-v3
  plan, the planner's decision reason, active quality, selected audio
  track, and the stream path with query, user info, ids and media
  filenames stripped.
- Recent events: a ring buffer of the last 8 player events and errors
  (plan, first frame, rebuffering, stalls, replans, quality and audio
  changes, typed Aether failures), timestamped, redacted through
  MediaLogRedactor, with consecutive repeats collapsed so a flapping
  state can't flush the error that caused it.
- tvOS Info HUD stats pane shows Plan in the left column and Recent
  events at the end of the right column (added to the paging targets).
  The iOS overlay adds the plan rows and lists events beside the rows in
  landscape, or four events below them when narrow.

Unit tests cover the ring buffer, summary and path formatting, and the
projection pass-through. Invariant anchors added for the new wiring.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: b11cfea1-1ae9-459b-858b-774f52d965fa

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@JonahMMay
JonahMMay deleted the branch fix/restore-prairie-customizations September 30, 2026 14:33
@JonahMMay JonahMMay closed this Sep 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant