-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
docs(nextjs): Improve Session Replay platform-includes #16020
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
70f1f7c
4176399
62acef8
e3218e9
c167a4c
61123bc
87bb5b5
ada433e
87e2f7a
8d6beac
845677b
1243298
3bc1b87
b81199f
bce58cb
8d8a92a
1d9e7e7
2f98e12
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,7 +45,7 @@ By default, our Session Replay SDK masks all DOM text content, images, and user | |
| </Alert> | ||
| </PlatformSection> | ||
|
|
||
| ## Pre-requisites | ||
| ## Prerequisites | ||
|
|
||
| <PlatformContent includePath="session-replay/pre-requisites" /> | ||
|
|
||
|
|
@@ -57,6 +57,14 @@ By default, our Session Replay SDK masks all DOM text content, images, and user | |
|
|
||
| To set up the integration, add the following to your Sentry initialization. There are several options you can pass to the integration constructor. See the [configuration documentation](/platforms/javascript/session-replay/configuration/) for more details. | ||
|
|
||
| <PlatformSection supported={["javascript.nextjs"]}> | ||
| <Alert> | ||
|
|
||
| Session Replay only runs in the browser, so you only need to configure it in `instrumentation-client.ts`. The server (`sentry.server.config.ts`) and edge (`sentry.edge.config.ts`) entry points run in Node.js and Edge runtimes where Replay is not available. | ||
|
|
||
| </Alert> | ||
| </PlatformSection> | ||
|
|
||
| <PlatformContent | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There seems to be a line in here that is now redundant from the line above: We're already saying that in the alert now.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good catch, removed from |
||
| includePath="session-replay/setup" | ||
| fallbackPlatform="javascript" | ||
|
|
@@ -67,88 +75,122 @@ To set up the integration, add the following to your Sentry initialization. Ther | |
| ### Canvas Recording | ||
|
|
||
| <Alert level="warning"> | ||
| There is currently no PII scrubbing in canvas recordings! | ||
| </Alert> | ||
|
|
||
| There is currently no PII scrubbing in canvas recordings! | ||
| <SplitLayout> | ||
|
|
||
| </Alert> | ||
| <SplitSection> | ||
| <SplitSectionText> | ||
|
|
||
| #### Enable Canvas Recording | ||
|
|
||
| If you want to record HTML canvas elements, you'll need to add an additional integration in your Sentry configuration. The canvas integration is exported from the browser SDK, so no additional package is required. Canvas recording is opt-in and will be tree-shaken from your bundle if it's not being used: | ||
| Add `replayCanvasIntegration()` to record HTML canvas elements. This is opt-in and tree-shaken from your bundle if not used. | ||
|
|
||
| </SplitSectionText> | ||
| <SplitSectionCode> | ||
|
|
||
| <PlatformContent includePath="session-replay/setup-canvas" /> | ||
|
|
||
| </SplitSectionCode> | ||
| </SplitSection> | ||
|
|
||
| <SplitSection> | ||
| <SplitSectionText> | ||
|
|
||
| #### 3D and WebGL Canvases | ||
|
|
||
| The canvas recording integration works by exporting the canvas as an image (at a rate of 2 frames per second). However, in order to export images from 3D and WebGL canvases, the integration needs to enable `preserveDrawingBuffer` which can negatively affect canvas performance. If your canvas application is impacted by enabling `preserveDrawingBuffer`, you'll need to enable manual snapshotting and call a `snapshot()` method inside of your re-paint loop. There are two steps to using manual snapshotting: | ||
| For 3D/WebGL canvases, the integration needs `preserveDrawingBuffer` to export images, which can affect performance. To avoid this, enable manual snapshotting and call `snapshot()` inside your paint loop. | ||
|
|
||
| **Step 1.** | ||
| Enable manual snapshotting when initializing the `ReplayCanvas` integration. | ||
| Call `snapshot()` in the same execution loop as draw commands to avoid capturing empty buffers. | ||
|
|
||
| </SplitSectionText> | ||
| <SplitSectionCode> | ||
|
|
||
| ```javascript | ||
| // Step 1: Enable manual snapshotting | ||
| Sentry.replayCanvasIntegration({ | ||
| // Enabling the following will ensure your canvas elements are not forced | ||
| // into `preserveDrawingBuffer`. | ||
| enableManualSnapshot: true, | ||
| }); | ||
| ``` | ||
|
|
||
| **Step 2** | ||
| Call the following `snapshot()` method inside your application's paint loop. `snapshot()` needs to be called in the same execution loop as the canvas draw commands, otherwise you may be snapshotting empty canvas buffers. This is due to how WebGL works when `preserveDrawingBuffer` is `false`. | ||
|
|
||
| ```javascript | ||
| // Step 2: Call snapshot in your paint loop | ||
| function paint() { | ||
| const canvasRef = document.querySelector("#my-canvas"); | ||
| Sentry.getClient().getIntegrationByName("ReplayCanvas").snapshot(canvasRef); | ||
| Sentry.getClient() | ||
| ?.getIntegrationByName("ReplayCanvas") | ||
| ?.snapshot(canvasRef); | ||
| } | ||
| ``` | ||
|
|
||
| </SplitSectionCode> | ||
| </SplitSection> | ||
|
|
||
| <SplitSection> | ||
| <SplitSectionText> | ||
|
|
||
| #### WebGPU Canvases | ||
|
|
||
| WebGPU works differently from WebGL in how it manages the lifetime of rendered frames. The canvas texture returned by `getCurrentTexture()` is only valid until the current task completes – after that, the texture expires, and its contents are no longer accessible. This means that by default, when `snapshot()` defers capture to the next animation frame, it will capture an empty or invalid canvas. There are two steps to capturing WebGPU canvases: | ||
| WebGPU canvas textures expire after the current task completes. Use `skipRequestAnimationFrame: true` to capture immediately after rendering. | ||
|
|
||
| **Step 1.** | ||
| Enable manual snapshotting when initializing the `ReplayCanvas` integration. | ||
| </SplitSectionText> | ||
| <SplitSectionCode> | ||
|
|
||
| ```javascript | ||
| // Step 1: Enable manual snapshotting | ||
| Sentry.replayCanvasIntegration({ | ||
| // Enabling the following will ensure your canvas elements are not forced | ||
| // into `preserveDrawingBuffer`. | ||
| enableManualSnapshot: true, | ||
| }); | ||
| ``` | ||
|
|
||
| **Step 2.** | ||
| Call the `snapshot()` method inside your application's paint loop with `skipRequestAnimationFrame: true` to capture the snapshot immediately: | ||
|
|
||
| ```javascript | ||
| // Step 2: Snapshot immediately after rendering | ||
| function paint() { | ||
| const canvasRef = document.querySelector("#my-canvas"); | ||
| const canvasIntegration = Sentry.getClient().getIntegrationByName("ReplayCanvas"); | ||
| const canvasIntegration = Sentry.getClient() | ||
| ?.getIntegrationByName("ReplayCanvas"); | ||
|
|
||
| // ... your WebGPU rendering commands ... | ||
|
|
||
| // Capture immediately after rendering - required for WebGPU | ||
| canvasIntegration.snapshot(canvasRef, { skipRequestAnimationFrame: true }); | ||
| // Capture immediately - required for WebGPU | ||
| canvasIntegration?.snapshot(canvasRef, { | ||
| skipRequestAnimationFrame: true, | ||
| }); | ||
| } | ||
| ``` | ||
|
|
||
| </SplitSectionCode> | ||
| </SplitSection> | ||
|
|
||
| </SplitLayout> | ||
| </PlatformSection> | ||
|
|
||
| ### Content Security Policy (CSP) | ||
|
|
||
| Session Replay uses a WebWorker to perform work (for example, compression) off the main UI thread so as not to degrade the performance of your application. Add the below entry to make sure that workers can be loaded: | ||
| <SplitLayout> | ||
|
|
||
| ``` | ||
| worker-src 'self' blob: | ||
| ``` | ||
| <SplitSection> | ||
| <SplitSectionText> | ||
|
|
||
| #### Configure CSP for Replay | ||
|
|
||
| Session Replay uses a WebWorker for compression off the main UI thread. Add these CSP entries to allow workers to load. | ||
|
|
||
| <PlatformSection notSupported={["javascript.electron"]}> | ||
|
|
||
| [Safari versions <= 15.4](https://caniuse.com/?search=worker-src) do not support `worker-src`, you will need to additionally add an entry for `child-src`: | ||
| Safari versions ≤ 15.4 also need `child-src`. | ||
|
|
||
| ``` | ||
| </PlatformSection> | ||
|
|
||
| </SplitSectionText> | ||
| <SplitSectionCode> | ||
|
|
||
| ```text | ||
| worker-src 'self' blob: | ||
| child-src 'self' blob: | ||
| ``` | ||
|
|
||
| </PlatformSection> | ||
| </SplitSectionCode> | ||
| </SplitSection> | ||
|
|
||
| </SplitLayout> | ||
|
|
||
| If you're unable to update your CSP policy to allow inline web workers, you can also [use a custom compression worker](./configuration#using-a-custom-compression-worker) instead. | ||
|
|
||
|
|
@@ -178,40 +220,53 @@ If you prefer not to record an entire session, you can elect to capture a replay | |
|
|
||
| ## Sampling | ||
|
|
||
| Sampling allows you to control how much of your website's traffic will result in a Session Replay. There are two sample rates you can adjust to get the replays relevant to you: | ||
| Sampling controls how much traffic results in a Session Replay. | ||
|
|
||
| <SplitLayout> | ||
|
|
||
| 1. <PlatformIdentifier name="replays-session-sample-rate" /> - The sample rate | ||
| for replays that begin recording immediately and last the entirety of the | ||
| user's session. | ||
| 2. <PlatformIdentifier name="replays-on-error-sample-rate" /> - The sample rate | ||
| for replays that are recorded when an error happens. This type of replay will | ||
| record up to a minute of events prior to the error and continue recording | ||
| until the session ends. | ||
| <SplitSection> | ||
| <SplitSectionText> | ||
|
|
||
| ```javascript {5-6} {filename:instrumentation-client.ts} | ||
| #### Configure Sample Rates | ||
|
|
||
| - <PlatformIdentifier name="replays-session-sample-rate" /> - Percentage of sessions to record fully | ||
| - <PlatformIdentifier name="replays-on-error-sample-rate" /> - Percentage of sessions to record when an error occurs (buffers 1 minute before the error) | ||
|
|
||
| **Tip:** Keep `replaysOnErrorSampleRate` at `1.0` - error sessions provide the most debugging value. | ||
|
|
||
| #### Recommended Production Sample Rates | ||
|
|
||
| <div className="table-fit-content"> | ||
|
|
||
| | Traffic Volume | Session Rate | Error Rate | | ||
| | -------------------------- | ------------ | ---------- | | ||
| | **High** (100k+/day) | `0.01` (1%) | `1.0` | | ||
| | **Medium** (10k-100k/day) | `0.1` (10%) | `1.0` | | ||
| | **Low** (under 10k/day) | `0.25` (25%) | `1.0` | | ||
|
|
||
| </div> | ||
|
|
||
| </SplitSectionText> | ||
| <SplitSectionCode> | ||
|
|
||
| ```javascript {filename:instrumentation-client.ts} | ||
| Sentry.init({ | ||
| // ... other configuration | ||
| dsn: "___PUBLIC_DSN___", | ||
|
|
||
| // Capture 10% of all sessions | ||
| replaysSessionSampleRate: 0.1, | ||
|
|
||
| // Session Replay sampling rates | ||
| replaysSessionSampleRate: 0.1, // Capture 10% of all sessions | ||
| replaysOnErrorSampleRate: 1.0, // Capture 100% of error sessions | ||
| // Capture 100% of sessions with errors | ||
| replaysOnErrorSampleRate: 1.0, | ||
|
|
||
| // For development/testing, you can set replaysSessionSampleRate to 1.0 | ||
| // to capture all sessions for complete visibility | ||
| integrations: [Sentry.replayIntegration()], | ||
| }); | ||
| ``` | ||
|
|
||
| ### Recommended Production Sample Rates | ||
|
|
||
| Choose your `replaysSessionSampleRate` based on your traffic volume: | ||
|
|
||
| | Traffic Volume | Session Sample Rate | Error Sample Rate | Description | | ||
| |---|---|---|---| | ||
| | **High** (100k+ sessions/day) | `0.01` (1%) | `1.0` (100%) | Minimal session capture, all errors | | ||
| | **Medium** (10k-100k sessions/day) | `0.1` (10%) | `1.0` (100%) | Balanced approach | | ||
| | **Low** (under 10k sessions/day) | `0.25` (25%) | `1.0` (100%) | Higher session capture for better insights | | ||
| </SplitSectionCode> | ||
| </SplitSection> | ||
|
|
||
| **Why keep `replaysOnErrorSampleRate` at 1.0?** Error sessions provide the most valuable debugging context, so capturing all of them is recommended regardless of traffic volume. | ||
| </SplitLayout> | ||
|
|
||
| ### How Sampling Works | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,7 @@ | ||
| The Replay integration is already included with the Sentry SDK. We recommend installing the SDK through our installation wizard: | ||
| Session Replay is included with `@sentry/nextjs`. If you haven't installed Sentry yet, run the wizard: | ||
|
|
||
| ```bash | ||
| npx @sentry/wizard@latest -i nextjs | ||
| ``` | ||
|
|
||
| If you already have Sentry installed, skip to [Set Up](#set-up) below. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,13 @@ | ||
| <PlatformSection supported={["javascript"]}> | ||
|
|
||
| For the sentry-replay integration to work, you must have the [Sentry browser SDK package](https://www.npmjs.com/package/@sentry/browser), or an equivalent framework SDK (for example, [@sentry/react](https://www.npmjs.com/package/@sentry/react)) installed. The minimum version required for the SDK is `7.27.0`. If you're on an older version of the SDK, please check the [migration document](https://github.com/getsentry/sentry-javascript/blob/master/MIGRATION.md). | ||
|
|
||
| </PlatformSection> | ||
|
|
||
| <PlatformSection notSupported={["javascript"]}> | ||
|
|
||
| Session Replay requires your SDK to be version `7.27.0` or higher. If you're on an older version, please check the [migration document](https://github.com/getsentry/sentry-javascript/blob/master/MIGRATION.md). | ||
|
|
||
| </PlatformSection> | ||
|
|
||
| Session Replay requires Node 12+, and browsers newer than IE11. |
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see the
PlatformSelectioncomponent in the preview. Is it because there's only"javascript.nextjs"being added to thesupportedprop?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PlatformSection not selection 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh shoot it's Platform Section 😭