Feat 83 recording (socket profiler recording & replay)#200
Draft
theultimatewasteofspace wants to merge 41 commits into
Draft
Feat 83 recording (socket profiler recording & replay)#200theultimatewasteofspace wants to merge 41 commits into
theultimatewasteofspace wants to merge 41 commits into
Conversation
- Add userId column to trace table (nullable FK to user) - Refactor recorder to use server-wide activeRecordingId flag - Attach/detach trace listeners on every connected user's socket - New mid-recording connections auto-attach listeners on init - Each trace tagged with the userId that emitted it - Add recordingGetTraces endpoint for edit modal
…cator - Add userId to trace table for per-user event tagging - Refactor recorder to server-wide capture across all connected sockets - Add participantUserIds filter on recording (null = everyone) - Start Recording modal with user picker and online status - Edit Recording modal with trace pruning - Discard Recording button in save modal - New endpoints: recordingGetTraces, recordingGetOnlineUsers
# Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. # # Lines starting with '#' will be ignored, and an empty message aborts # the commit.
- Server.recoverInterruptedRecordings() runs on startup to mark stale 'recording' rows as 'interrupted' after a server restart, freeing the Start Recording button - RecordingModal confirm() now waits for rename + trace deletions before closing modal and reporting success
Each socket connection now writes a distinct socketId on every trace, so admin's two tabs are recorded as two separate streams instead of being collapsed into one merged userId stream. Foundation for per-session replay. - Migration: collapsed three trace migrations into one create-trace with userId + socketId from the start - Model: added socketId field - Recorder: writes socket.id on every trace
- Pre-select admin inside the getOnlineUsers callback so userTable is stable when we resolve the row, fixing 'Record 2 User(s)' when only admin was checked - getOnlineUsers now returns per-user session count, exposed as Sessions column in the start-recording table
groupTracesBySocket replaces groupTracesByUser. Each session (socket connection) becomes one replay client, so admin's two recorded tabs replay as two parallel clients instead of one merged stream. Falls back to per-user grouping for legacy recordings without socketId.
added 5 commits
May 3, 2026 16:24
Recording participants are now socketIds (one per active socket connection), not userIds. Admin's two tabs are two selectable sessions. New connections during a recording are silently uncaptured - a warning toast goes to the recording owner so they know. - Migration: add participantSocketIds JSONB to recording table (participantUserIds kept for now in case selection model changes, but no longer written to) - Recorder: isUserIncluded -> isSessionIncluded, getOnlineUsers -> getOnlineSessions returning per-socket entries - Server: warning toast to recording owner on uncaptured connection - Start modal: per-session table, pre-selects current tab's session, shows '(this tab)' marker on owner's row
- TopBar.vue: red pulsing icon visible app-wide during recordings (admins always see; non-admin participants see when their socketId is in participantSocketIds; click is informational only) - Dashboard.vue: remove RecordingBar mount/import - SocketProfiler.vue: stop button calls recorderStop directly instead of going through eventBus -> RecordingBar - StartRecordingModal.vue: drop name input (renamed at save time in RecordingModal instead) - Recording model: publicTable=true so recording state reaches participants reactively (admin and non-admin) - recorder.js: drop debugging console.logs RecordingBar.vue file kept untouched in the repo for git history.
Click Play on a recording opens a configuration modal instead of firing the replay immediately. The modal lets the user configure the run before starting: - Mode selector (Scaling now; Load mode placeholder for later) - Speed: Fast or Realtime - Max iterations (required positive integer) - Continue past failures toggle - Multi-recording selection (sessions get pooled) - Live load preview: pool size, peak parallel sockets, cumulative socket-runs Scaling math change: sessions from all selected recordings are pooled into one list of N sessions. Iteration K runs K * N parallel sockets, cycling the pool with wraparound. Linear add per iteration (K=1 -> N sockets, K=2 -> 2N, ..., K=M -> M*N). - replayer.js: rewritten around buildSessionPool + runScalingTest on the pooled list. New replayRun signature accepts recordingIds array, maxIterations, continueOnFailure - ReplayResultsModal.vue: flat iteration list (was per-recording). Each session row labels its source recording so multi-recording runs are still readable - SocketProfiler.vue: Play button opens StartReplayModal instead of running directly - worker.js: emitWithTimeout now resolves success: false on timeout (was silently passing as success: true) - StartRecordingModal.vue: drop stray 's' character (lint fix) Cross-session timing offsets are intentionally not preserved during scaling — that's a separate behavioral-replay mode for future work.
The original extend-nav-socket-profiler migration inserted Socket Profiler into the legacy Admin group (id 2). Dev's later restructure-nav_group migration replaced the Admin layout with category-based groups but didn't relocate Socket Profiler since it lived on a separate feature branch at the time. After merging dev into feat-83-recording, Socket Profiler ends up stranded in the legacy Admin group and disappears from the sidebar. This migration relocates it into Manage, alongside other admin operational tools like Users.
added 6 commits
May 11, 2026 13:44
…igation - Topbar.vue: show ticking HH:MM:SS timer next to the recording dot, updates every second via setInterval - Restore click-to-navigate: admins jump to /dashboard/Socket_Profiler when clicking the icon (route path was wrong in the previous attempt; used the actual path from the router this time) - Tooltip text simplified: elapsed time is now visible inline, no need to duplicate it in the tooltip
macOS auto-generates .DS_Store in every folder, which polluted git status output. Adding the pattern to .gitignore and removing the two tracked instances so they stop showing up as modified.
The mounted() method's closing brace was missing, causing a Vite compile error. Added the missing }, between setInterval and beforeUnmount.
The trace table in RecordingModal now shows when each trace fired, both as absolute wall-clock time (HH:MM:SS) and as offset from the recording's start time (+HH:MM:SS). - Reads the recording's startTime reactively from the Vuex store so the elapsed calculation works in both the save-after-stop flow and the edit flow - Falls back to '-' gracefully when timestamps are missing
- SocketProfiler.vue: move :max-table-height before @action - StartRecordingModal.vue: reorder input attributes to match Vue style guide (directives -> bindings -> plain attrs)
The log was added during development to verify DB-change tracking was working. The same info is now captured properly in each trace's dbChanges result field, so the server-console echo is redundant.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements Issue #83 — Socket Profiler recording & replay tool for stress-testing CARE.
What's included
Recording side
recordingandtracetables with full lifecycle (start → recording → finished/interrupted → soft-deleted)interruptedon next bootReplay side
success: truewithin 2s (will adjust later)UI
Architectural decisions
publicTable: trueon Recording model: needed so non-admin participants get the recording row in their store and the topbar icon can render.Known issues or observations
Roadmap (out of scope for this PR)
Migration & merge notes
dev(53 commits behind at last sync). The merge was clean at the file level except for.gitignoreandpackage-lock.json, both auto-resolved.restructure-nav_groupmigration relocated nav elements but didn't touch Socket Profiler since it lived on this branch. A small follow-up migration (20260506220447-move-socket-profiler-to-manage) moves Socket Profiler into the Manage group.Testing
End-to-end manual testing covered:
Closes #83