Sessions
A session is a full recording of one user's interactions with a browser app, typically the lifetime of an open tab. Where an Issue shows you a single moment that something broke, a session shows you the entire journey: what the user clicked, navigated to, scrolled past, and saw on screen, with the same console logs and network calls layered on top.
Sessions require a browser SDK, and the TracePath browser SDK is not published yet. This page describes the model the dashboard already implements, so you know what session replay will give you; there is nothing to install today. Backend services instrument with OpenTelemetry, which produces traces, metrics and logs but not sessions. Mail [email protected] to be told when the browser SDK ships.
Sessions are a browser-only concept, produced when always-on session recording is enabled in a browser SDK. OpenTelemetry backends and mobile apps do not produce sessions.
Sessions vs. Exception Clips
TracePath's browser SDK has always shipped a short rrweb clip alongside every captured exception: the rolling window of events from just before the error fired. That clip stays on the issue detail page; it answers "what did the page look like the moment things went wrong?".
A session is the larger envelope around those moments:
| Exception Clip | Session | |
|---|---|---|
| Default behaviour | On (rolling window flushed with each captured exception) | Off (opt in with recordAllSessions: true) |
| Scope | Last ~10 s before an exception | Entire tab lifetime, capped at 60 min |
| Storage | One file per exception | One file per ~30 s segment, many per session |
| When uploaded | At exception capture | Continuously, every segment rotation |
| Where surfaced | Inline on the issue page | Sessions list + dedicated detail page; linked from issues |
Both can coexist: an exception fired during an always-on session gets its inline clip on the issue page and a "View full session →" link to the parent session.
What a Session Records
The recording uses rrweb (opens in a new tab) to capture DOM mutations, input events, mouse movement, and viewport changes. Replay is a faithful reconstruction: text, layout, scrolling, hover states, even mouse trails. Privacy markers (rr-mask, rr-block, rr-ignore) work the same way they do for exception clips. See Session Replay in the JS SDK guide for the full masking reference.
Alongside the rrweb stream, each segment carries:
- Logs: every
console.{debug,log,info,warn,error}call recorded during the segment window. - Actions:
fetch/XMLHttpRequestcalls, History API navigations, and anyrecordAction(...)breadcrumbs.
The dashboard's session detail page renders these as separate tabs below the player, scrub-synced to the replay timeline.
Session Lifecycle
A session begins automatically when the SDK initializes with recordAllSessions: true (or when the page is restored from the bfcache after a back/forward navigation; a fresh sessionId is generated each time).
It ends on the first of:
| Trigger | When | Behaviour |
|---|---|---|
| Inactivity timeout | 15 minutes since the last DOM event rrweb observed | Session is closed; subsequent activity opens a new one |
| Maximum duration | 60 minutes from session start | Hard cap regardless of activity |
| Page unload | pagehide fires (close tab, hard refresh, navigate away) | Final segment is drained, closing payload sent via fetch keepalive |
If a session ends without an explicit close (e.g. the browser is force-quit before pagehide runs, or the closing flush is dropped), its ended_at stays NULL on the backend and the dashboard renders the duration as Abandoned once the row has been quiet for ≥ 15 min.
Attributes
Every session ships with a context map. Three layers contribute:
- Auto-collected defaults: the SDK stamps
url,path,referrer,userAgent,language,platform,viewport,screen, andtimezonefromwindow/navigator. The backend additionally stampsclient.ipfrom the request. - Global scope: anything set via
setAttribute("userId", "u_42")/setAttributes({ tenant: "acme" })on the SDK. These refresh the open session and flow through subsequent sessions and exceptions. You can also passattributesat initialization. - Per-call attributes:
captureExceptionWithAttributes(err, { … })for exceptions only.
Layering: defaults → global scope → per-call. Higher layers win on key collision.
See the framework-specific guides for the API:
- JS SDK initialization
- React:
setAttribute*plus the<TracePathAttributes>component /useTracePathAttributeshook for declarative reactive scope - Svelte:
setAttribute*plus theuseTracePathAttributesfactory - Vue:
setAttribute*(drive fromwatchEffect) - React Native: same as React, layered above device info
Filtering Sessions
The Sessions page in the dashboard accepts:
- Search: paste a full session UUID for an exact match, or search a partial session ID, IP address, or attribute value (such as a user ID or email). Text search ignores case.
- Attribute filters: click Add filter or an attribute on a session row. Choose Equals, Not equals, Contains, or Not contains. Equals is case-sensitive; Contains ignores case and treats characters such as
%literally. Excluded filters also include sessions without that attribute. - Filter chips: click a chip to edit it or its × to remove it. All filters and the search combine with AND. Filters are stored in the URL for sharing and back/forward navigation.
Identity is what makes these filters useful: set userId, email or a tenant key from your app after login, and every session and exception from that point carries it. Attribute values must be strings. Setting them replaces the current session's context; clearing them removes app-defined values while retaining the browser defaults.
With that in place, add userId=u_42 to find that user's sessions, or combine tenant=acme with email Contains example.com.
Sessions and Issues
Every exception captured inside an always-on session is stamped with the parent sessionId. From the dashboard:
- The issue detail page keeps showing the inline 10 s clip but renders a "View full session →" button when a session id is present.
- The session detail page renders a table of every exception that fired during that session, each linked back to its issue.
This stitching is independent of whether the exception was caught by your code or by the SDK's global handlers.
Cost and Storage
Always-on session recording is more data than exception-only capture: every active tab uploads continuously, ~30 s segments, until the user leaves. Plan accordingly:
- Default segment duration is 30 s. This is a 3× reduction in S3 reads compared to a 10 s cadence; tune via
sessionRecordingSegmentDuration(ms) if your traffic profile differs. - Logs and actions are drained from the rolling buffer at each segment rotation, so a single segment carries the activity it spans (no double-counting across segments).
- Recordings older than the platform retention window are pruned automatically.
For most apps, recording a sample of sessions (or only premium-tier users, etc.) is the right balance. Set recordAllSessions: false to turn it off entirely. The SDK falls back to exception-only clips with no per-segment uploads.
Next Steps
- Session Replay in the JS SDK: privacy masking, segment rotation, and the wire format.
- Issues: how exceptions are grouped and what an issue page shows.
- Attributes: the broader attribute model that backs sessions, exceptions, traces, and tasks.