7b99b41ede
Much of design/ described work that has since shipped. Trim each doc to
its durable rationale + still-open items (the code is the source of truth
for shipped detail; git history holds the full originals).
- Shipped plans -> status stubs: stats-capture, gamestream-host-plan,
apple-stage2-presenter, windows-service.
- Trimmed completed-out / open-kept: implementation-plan, hdr-pipeline,
host-latency, gpu-contention (fixed stale status table), game-library,
linux-setup (fixed m0->spike + stale zero-copy claim),
session-aware-host-followups, windows-client-bootstrap,
windows-dualsense-{scoping,game-detection}, windows-virtual-display,
security-review (per-finding status table; #12 still open),
apollo-comparison (shipped backlog collapsed to one-liners).
- Windows-host cluster consolidated: windows-host.md -> redirect into
windows-host-rewrite.md (whose stale scorecard is corrected -- goal1 is
merged, M4 done); windows-secure-desktop.md archived (now a fallback
behind IDD-push primary).
- Kept evergreen: ci.md, gamescope-multiuser.md, windows-build-and-packaging.md.
- New design/README.md: per-doc status table + consolidated open-items
roll-up so nothing is tracked in only one buried doc.
- Repoint 5 code comments to the archived secure-desktop doc path.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.5 KiB
3.5 KiB
Stats capture & graphing — design
Status: SHIPPED (commit
5bf787e) — hostcrates/punktfunk-host/src/stats_recorder.rs, mgmt endpoints/api/v1/stats/*(mgmt.rs), web console Performance page (web/src/sections/Stats/). Implemented; not yet on-glass validated. This doc is trimmed to design rationale + open items; the shipped code is the source of truth (data models, recorder API, endpoint list, and UI layout all live there).
Goal: let an operator enable performance-stats capture from the web console, play a session,
stop, and review the captured time-series as graphs. Captures are saved to disk
(browse/compare past sessions; survive host restart) and cover both streaming paths: native
punktfunk/1 (virtual_stream) and GameStream/Moonlight (gamestream/stream.rs).
Why / design rationale
- Reuse the existing per-stage instrumentation that was startup-gated by
PUNKTFUNK_PERF=1(stdout-only, read once at startup). The key behavioral change: make the per-frame measurement predicateperf || recorder.is_armed(), re-evaluated each frame via a cheapRelaxedatomic.PUNKTFUNK_PERF=1still emits itstracing::info!log line exactly as before; the web toggle additionally builds aStatsSampleat the aggregation boundary — so the web toggle works at runtime with zero startup flags. - No async on the per-frame path.
is_armed()is aRelaxedatomic load; sample construction happens only at the existing ~2 s native / ~1 s GameStream aggregation boundary, never per frame. One sharedArc<StatsRecorder>is created once in the unified host entry and threaded into both streaming loops +MgmtState, mirroring the existingArc<NativePairing>sharing pattern. - Stage sets are the per-frame critical path so stacking is meaningful. native:
capture/submit(NVENC enqueue) /encode(lock_bitstream= NVENC schedule + ASIC, the dominant stage under GPU load) /send(paced_submit: seal + FEC + pace + sendmmsg). gamestream:capture/encode/packetize/send. Native source vectors mapst_cap→capture,st_submit→submit,st_wait→encode,pace_us→send;encode_ustotal ≈ capture+submit+encode and is not emitted as its own stage to avoid double-counting. - Gotchas / accepted-risk decisions:
idis path-traversal-safe.load/deletereject any id not matching^[A-Za-z0-9._-]+$(no/, no.., no:— keep it a valid Windows filename) and only ever joindir/<id>.json. Endpoints are bearer-authed, but defend in depth.- Bounded memory, keep the start.
MAX_SAMPLEScap (~5400 ≈ 3 h @ 2 s); on overflow stop appending and set atruncatedflag — do NOT drop oldest, a saved recording must keep its start. - Atomic disk write. Write
<id>.json.tmpthen rename so a crash mid-write can't leave a half file. Captures dir~/.config/punktfunk/captures/(0700), next tocert.pem. - Counters that a path doesn't expose are recorded as
0— do NOT fabricate. - mgmt endpoints are bearer-token only (operator actions) — deliberately NOT in the mTLS
cert_may_accessread-only allowlist. - Charts render client-only (mounted guard) so SSR doesn't choke on
ResponsiveContainer's 0-width measure.
Open items
- On-glass validation. Implemented but not yet validated on real hardware end-to-end (arm from the console, play, stop, review graphs across both native + GameStream paths).