Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

Session replay: client-owned session id and a per-tab window id

Aperta
#615 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
20/100
Tipo di issue
Funzionalità
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
typescript

Direzione di ricerca

Start by reading linked issues #537, #599, #613 and #614, then trace the web SDK's track/identify/replay payload assembly, the ingest session-resolution path, and the session_replay_chunks schema/migration. Follow how replay chunks are keyed by session and how the player orders and seeks them. Done means an agreed rollout split into the four described PRs, with client session-id fallback and per-window replay loading covered by tests.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

We run OpenPanel session replay in production on a fork (a few thousand recorded sessions a day, web and a canvas-heavy app) and hit a set of failures that all come from the same two gaps: the browser does not own its session id, and recordings are not separated per tab. Before sending code, I would like to agree on the design, since this touches how sessions are resolved. Two small SDK fixes from the same work are already up: #613 and #614.

Problems

1. Chunks recorded before the first track response land in the wrong session. The recorder starts immediately, but the SDK has no session id until the first /track answers, so early chunks (usually including the full snapshot) are queued and later resolved on the server from IP and user agent. That is #537; #599 patches the queue flush, but the root cause is that the client cannot know its session id synchronously.

2. Different people behind the same NAT share sessions. The server derives the device (and so the session) from a hash of IP and user agent. Offices, mobile carriers (CGNAT) and university networks put many users on one IP, often with an identical UA. Their events and replays merge into one session, and the player tries to play two different people's DOMs as one recording.

3. Two tabs of one session interleave in one recording. Every tab runs its own rrweb recorder, but chunks are keyed only by session. Opening a second tab produces two independent DOM streams under one session id; ordered by time, they make the player jump between pages and fail with "Node not found" after a seek.

Proposal

A. Client-owned session id (opt-in or default, your call)

The web SDK keeps the session in localStorage, shared by every tab of the origin, the same contract PostHog uses:

  • _op_session_id, _op_session_start_ms, _op_last_activity_ms
  • rotate when idle longer than the session timeout (30 min) or older than a hard cap (24 h)
  • activity is read fresh from storage on each check, so an idle tab does not rotate a session a sibling tab keeps alive
  • rotation is lazy (checked when the id is read), so there are no timers or cross-tab coordination
  • in-memory fallback when storage is unavailable

The SDK sends the id on every track/identify/replay payload. Ingest uses it when present and valid, and falls back to today's server-side resolution otherwise, so old SDKs and server-side SDKs keep working unchanged. Replay chunks then always have their session id from the first event, which fixes #537 at the root, and NAT collisions disappear because the id no longer depends on IP and UA.

B. Per-tab window_id

A random id generated per tab per page load (kept in sessionStorage, renewed when the session rotates) and sent with each replay chunk:

  • session_replay_chunks gets a window_id String DEFAULT '' column; existing rows and old SDKs read as one window, so nothing changes for them
  • the player loads one window at a time and shows a tab switcher when a session has several, so each recording is a single coherent DOM stream
  • optionally exposed as getWindowId() so apps can attach it to their own events and deep-link a business event to the exact tab recording

Rollout

Each part is backward compatible on its own and could land as small PRs:

  1. ingest accepts an optional client session id (validated, falls back to current resolution)
  2. web SDK session manager (behind an option first if you prefer)
  3. window_id column migration + ingest + replay buffer
  4. player: per-window loading and a tab switcher

From our production

After we moved to a client-owned session id and per-tab window id, the multi-tab and NAT-collision recordings stopped appearing, and early chunks (including the first full snapshot) stay in the right session.

Happy to implement this in that order if the direction works for you, or to adjust it (for example keeping the server as the source of truth and only binding the client id when present).

Lingua principale
TypeScript
Stelle
7.2k
Fork
531
Merge medio
23h 58m
PR unite (30g)
51

Preparare l'ambiente

  • Include un Dockerfile o un file Docker Compose
  • Nessun modello di pull request
  • Nessuna guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di Openpanel-dev/openpanel

Tutte le issue di Openpanel-dev/openpanel

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.