diff --git a/docs/platforms/javascript/common/session-replay/index.mdx b/docs/platforms/javascript/common/session-replay/index.mdx index ebb7924c28aa2..b8e3fc7491331 100644 --- a/docs/platforms/javascript/common/session-replay/index.mdx +++ b/docs/platforms/javascript/common/session-replay/index.mdx @@ -45,7 +45,7 @@ By default, our Session Replay SDK masks all DOM text content, images, and user -## Pre-requisites +## Prerequisites @@ -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. + + + +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. + + + + + There is currently no PII scrubbing in canvas recordings! + -There is currently no PII scrubbing in canvas recordings! + - + + + +#### 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. + + + + + + + + + #### 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. + + + ```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); } ``` + + + + + + #### 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. + + ```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, + }); } ``` + + + + + ### 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: + -``` -worker-src 'self' blob: -``` + + + +#### 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. -[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`. -``` + + + + + +```text +worker-src 'self' blob: child-src 'self' blob: ``` - + + + + 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. + + -1. - The sample rate - for replays that begin recording immediately and last the entirety of the - user's session. -2. - 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. + + -```javascript {5-6} {filename:instrumentation-client.ts} +#### Configure Sample Rates + +- - Percentage of sessions to record fully +- - 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 + +
+ +| 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` | + +
+ +
+ + +```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 | + +
-**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. +
### How Sampling Works diff --git a/platform-includes/session-replay/install/javascript.nextjs.mdx b/platform-includes/session-replay/install/javascript.nextjs.mdx index 3050f964b7f1a..55aa8a0dc9d11 100644 --- a/platform-includes/session-replay/install/javascript.nextjs.mdx +++ b/platform-includes/session-replay/install/javascript.nextjs.mdx @@ -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. diff --git a/platform-includes/session-replay/pre-requisites/javascript.mdx b/platform-includes/session-replay/pre-requisites/javascript.mdx index bbdaab4f11357..fd7ddde7d0d7a 100644 --- a/platform-includes/session-replay/pre-requisites/javascript.mdx +++ b/platform-includes/session-replay/pre-requisites/javascript.mdx @@ -1,3 +1,13 @@ + + 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). + + + + +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). + + + Session Replay requires Node 12+, and browsers newer than IE11. diff --git a/platform-includes/session-replay/setup/javascript.ember.mdx b/platform-includes/session-replay/setup/javascript.ember.mdx deleted file mode 100644 index 6dfbe1e76d647..0000000000000 --- a/platform-includes/session-replay/setup/javascript.ember.mdx +++ /dev/null @@ -1,45 +0,0 @@ -```javascript {8,12,14-20} -import * as Sentry from "@sentry/ember"; - -Sentry.init({ - dsn: "___PUBLIC_DSN___", - - // This sets the sample rate to be 10%. You may want this to be 100% while - // in development and sample at a lower rate in production - replaysSessionSampleRate: 0.1, - - // If the entire session is not sampled, use the below sample rate to sample - // sessions when an error occurs. - replaysOnErrorSampleRate: 1.0, - - integrations: [ - Sentry.replayIntegration({ - // Additional SDK configuration goes in here, for example: - maskAllText: true, - blockAllMedia: true, - }), - ], -}); -``` - -### Verify - -While you're testing, we recommend that you set `replaysSessionSampleRate` to `1.0`. This ensures that every user session will be sent to Sentry. - -Once testing is complete, **we recommend lowering this value in production**. We still recommend keeping `replaysOnErrorSampleRate` set to `1.0`, so that, whenever possible, every error has an associated replay with additional debugging context. - - -### PII & Privacy Considerations - -Personally identifiable information (PII) and privacy are important considerations when enabling Session Replay. There are multiple ways in which Sentry helps you avoid collecting PII, including: -- [Masking](/platforms/javascript/session-replay/privacy/#masking), which replaces the text content with something else -- the default behavior being to replace each character with a *. -- Making [network request, response bodies, and headers](/platforms/javascript/session-replay/privacy/#network-request-and-response-bodies-and-headers) an opt-in feature, because the best way to avoid getting PII into Sentry is by not adding URLs of endpoints that may contain PII. - -While we have certain privacy considerations in place, Sentry's Session Replay allows you to set up the [privacy configurations](/platforms/javascript/session-replay/privacy/#privacy-configuration) that work best for your use case. For example, if you're working on a static website that's free of PII or other types of private data, you can opt out of the default text masking and image blocking settings. -To learn more about Session Replay privacy, [read our docs.](/platforms/javascript/session-replay/privacy/) - -### Lazy-loading Replay - -Once you've added the integration, Replay will start automatically. If you don't want to start it immediately (lazy-load it), you can use `addIntegration`: - - diff --git a/platform-includes/session-replay/setup/javascript.gatsby.mdx b/platform-includes/session-replay/setup/javascript.gatsby.mdx deleted file mode 100644 index 0ca513d3a2a50..0000000000000 --- a/platform-includes/session-replay/setup/javascript.gatsby.mdx +++ /dev/null @@ -1,45 +0,0 @@ -```javascript {8,12,14-20} -import * as Sentry from "@sentry/gatsby"; - -Sentry.init({ - dsn: "___PUBLIC_DSN___", - - // This sets the sample rate to be 10%. You may want this to be 100% while - // in development and sample at a lower rate in production - replaysSessionSampleRate: 0.1, - - // If the entire session is not sampled, use the below sample rate to sample - // sessions when an error occurs. - replaysOnErrorSampleRate: 1.0, - - integrations: [ - Sentry.replayIntegration({ - // Additional SDK configuration goes in here, for example: - maskAllText: true, - blockAllMedia: true, - }), - ], -}); -``` - -### Verify - -While you're testing, we recommend that you set `replaysSessionSampleRate` to `1.0`. This ensures that every user session will be sent to Sentry. - -Once testing is complete, **we recommend lowering this value in production**. We still recommend keeping `replaysOnErrorSampleRate` set to `1.0`, so that, whenever possible, every error has an associated replay with additional debugging context. - - -### PII & Privacy Considerations - -Personally identifiable information (PII) and privacy are important considerations when enabling Session Replay. There are multiple ways in which Sentry helps you avoid collecting PII, including: -- [Masking](/platforms/javascript/session-replay/privacy/#masking), which replaces the text content with something else -- the default behavior being to replace each character with a *. -- Making [network request, response bodies, and headers](/platforms/javascript/session-replay/privacy/#network-request-and-response-bodies-and-headers) an opt-in feature, because the best way to avoid getting PII into Sentry is by not adding URLs of endpoints that may contain PII. - -While we have certain privacy considerations in place, Sentry's Session Replay allows you to set up the [privacy configurations](/platforms/javascript/session-replay/privacy/#privacy-configuration) that work best for your use case. For example, if you're working on a static website that's free of PII or other types of private data, you can opt out of the default text masking and image blocking settings. -To learn more about Session Replay privacy, [read our docs.](/platforms/javascript/session-replay/privacy/) - -### Lazy-loading Replay - -Once you've added the integration, Replay will start automatically. If you don't want to start it immediately (lazy-load it), you can use `addIntegration`: - - diff --git a/platform-includes/session-replay/setup/javascript.mdx b/platform-includes/session-replay/setup/javascript.mdx index 3fc549ddf02da..94fc46c9d0708 100644 --- a/platform-includes/session-replay/setup/javascript.mdx +++ b/platform-includes/session-replay/setup/javascript.mdx @@ -1,6 +1,19 @@ -```javascript {9,13,15-21} -// import Sentry from your framework SDK (e.g. @sentry/react) instead of @sentry/browser -import * as Sentry from "@sentry/browser"; + + + + + +#### Add Replay Integration + +Add `replayIntegration()` to your initialization and configure the sample rates. + +**Testing tip:** Set `replaysSessionSampleRate: 1.0` during development to capture all sessions. + + + + +```javascript +import * as Sentry from "___SDK_PACKAGE___"; Sentry.init({ dsn: "___PUBLIC_DSN___", @@ -13,34 +26,66 @@ Sentry.init({ // sessions when an error occurs. replaysOnErrorSampleRate: 1.0, - integrations: [ - Sentry.replayIntegration({ - // Additional SDK configuration goes in here, for example: - maskAllText: true, - blockAllMedia: true, - }), - ], + integrations: [Sentry.replayIntegration()], }); ``` -### Verify + + + + + + +#### Privacy Options + +By default, Replay masks all text and blocks media. Customize privacy settings based on your needs. + +See Session Replay Privacy for all options. -While you're testing, we recommend that you set `replaysSessionSampleRate` to `1.0`. This ensures that every user session will be sent to Sentry. + + -Once testing is complete, **we recommend lowering this value in production**. We still recommend keeping `replaysOnErrorSampleRate` set to `1.0`, so that, whenever possible, every error has an associated replay with additional debugging context. +```javascript +Sentry.replayIntegration({ + // Text masking (default: true) + maskAllText: true, + // Block images/videos (default: true) + blockAllMedia: true, + + // Mask specific inputs + maskAllInputs: true, +}), +``` + + + + + ### PII & Privacy Considerations -Personally identifiable information (PII), and privacy are important considerations when enabling Session Replay. There are multiple ways in which Sentry helps you avoid collecting PII, including: -- [Masking](/platforms/javascript/session-replay/privacy/#masking), which replaces the text content with something else. (The default behavior being to replace each character with a *.) -- Making [Network request, response bodies, and headers](/platforms/javascript/session-replay/privacy/#network-request-and-response-bodies-and-headers) an opt-in feature, because the best way to avoid getting PII into Sentry is by not adding URLs of endpoints that may contain PII. +Personally identifiable information (PII) and privacy are important considerations when enabling Session Replay. There are multiple ways in which Sentry helps you avoid collecting PII, including: +- Masking, which replaces text content with something else (the default behavior being to replace each character with a `*`). +- Making network request and response bodies opt-in, to avoid capturing endpoints that may contain PII. + +For static websites without sensitive data, you can opt out of the default masking and blocking settings. -While we have certain privacy considerations in place, Sentry's Session Replay allows you to set up the [privacy configurations](/platforms/javascript/session-replay/privacy/#privacy-configuration) that work best for your use case. For example, if you're working on a static website that's free of PII or other types of private data, you can opt out of the default text masking and image blocking settings. -To learn more about Session Replay privacy, [read our docs.](/platforms/javascript/session-replay/privacy/) + -### Lazy-loading Replay + + -Once you've added the integration, Replay will start automatically. If you don't want to start it immediately (lazy-load it), you can use `addIntegration`: +#### Lazy-Loading Replay + +Load Replay only when needed instead of at startup. Useful for reducing initial bundle size. + + + + + + + + diff --git a/platform-includes/session-replay/setup/javascript.nextjs.mdx b/platform-includes/session-replay/setup/javascript.nextjs.mdx index f1bc4524c22e5..796576a54db9e 100644 --- a/platform-includes/session-replay/setup/javascript.nextjs.mdx +++ b/platform-includes/session-replay/setup/javascript.nextjs.mdx @@ -1,6 +1,18 @@ -On your client-side NextJS app, add: + -```javascript {8,12,14-20} {filename:instrumentation-client.ts} + + + +#### Add Replay Integration + +Add `replayIntegration()` to your client initialization and configure the sample rates. + +**Testing tip:** Set `replaysSessionSampleRate: 1.0` during development to capture all sessions. + + + + +```typescript {filename:instrumentation-client.ts} import * as Sentry from "@sentry/nextjs"; Sentry.init({ @@ -14,34 +26,76 @@ Sentry.init({ // sessions when an error occurs. replaysOnErrorSampleRate: 1.0, - integrations: [ - Sentry.replayIntegration({ - // Additional SDK configuration goes in here, for example: - maskAllText: true, - blockAllMedia: true, - }), - ], + integrations: [Sentry.replayIntegration()], }); ``` -### Verify + + + + + -While you're testing, we recommend that you set `replaysSessionSampleRate` to `1.0`. This ensures that every user session will be sent to Sentry. +#### Privacy Options -Once testing is complete, **we recommend lowering this value in production**. We still recommend keeping `replaysOnErrorSampleRate` set to `1.0`, so that, whenever possible, every error has an associated replay with additional debugging context. +By default, Replay masks all text and blocks media. Customize privacy settings based on your needs. + +See Session Replay Privacy for all options. + + + + +```typescript {filename:instrumentation-client.ts} +Sentry.replayIntegration({ + // Text masking (default: true) + maskAllText: true, + + // Block images/videos (default: true) + blockAllMedia: true, + + // Mask specific inputs + maskAllInputs: true, +}), +``` + + + + + ### PII & Privacy Considerations -Personally identifiable information (PII), and privacy are important considerations when enabling Session Replay. There are multiple ways in which Sentry helps you avoid collecting PII, including: +Personally identifiable information (PII) and privacy are important considerations when enabling Session Replay. There are multiple ways in which Sentry helps you avoid collecting PII, including: +- Masking, which replaces text content with something else (the default behavior being to replace each character with a `*`). +- Making network request and response bodies opt-in, to avoid capturing endpoints that may contain PII. + +For static websites without sensitive data, you can opt out of the default masking and blocking settings. + + + + + + +#### Lazy-Loading Replay -- [Masking](/platforms/javascript/session-replay/privacy/#masking), which replaces the text content with something else. (The default behavior being to replace each character with a \*.) -- Making [Network request, response bodies, and headers](/platforms/javascript/session-replay/privacy/#network-request-and-response-bodies-and-headers) an opt-in feature, because the best way to avoid getting PII into Sentry is by not adding URLs of endpoints that may contain PII. +Load Replay only when needed instead of at startup. Useful for reducing initial bundle size. -While we have certain privacy considerations in place, Sentry's Session Replays allow you to set up the [privacy configurations](/platforms/javascript/session-replay/privacy/#privacy-configuration) that work best for your use case. For example, if you're working on a static website that's free of PII or other types of private data, you can opt out of the default text masking and image blocking settings. -To learn more about session replay privacy, [read our docs.](/platforms/javascript/session-replay/privacy/) + + -### Lazy-loading Replay +```typescript {filename:instrumentation-client.ts} +// Don't add replayIntegration to init +Sentry.init({ + integrations: [], +}); + +// Later, when you want to start recording: +import("@sentry/nextjs").then((lazyLoadedSentry) => { + Sentry.addIntegration(lazyLoadedSentry.replayIntegration()); +}); +``` -Once you've added the integration, Replay will start automatically. If you don't want to start it immediately (lazy-load it), you can use `addIntegration`: + + - + diff --git a/platform-includes/session-replay/setup/javascript.react.mdx b/platform-includes/session-replay/setup/javascript.react.mdx deleted file mode 100644 index dcdb75dff72b6..0000000000000 --- a/platform-includes/session-replay/setup/javascript.react.mdx +++ /dev/null @@ -1,45 +0,0 @@ -```javascript {8,12,14-20} -import * as Sentry from "@sentry/react"; - -Sentry.init({ - dsn: "___PUBLIC_DSN___", - - // This sets the sample rate to be 10%. You may want this to be 100% while - // in development and sample at a lower rate in production - replaysSessionSampleRate: 0.1, - - // If the entire session is not sampled, use the below sample rate to sample - // sessions when an error occurs. - replaysOnErrorSampleRate: 1.0, - - integrations: [ - Sentry.replayIntegration({ - // Additional SDK configuration goes in here, for example: - maskAllText: true, - blockAllMedia: true, - }), - ], -}); -``` - -### Verify - -While you're testing, we recommend that you set `replaysSessionSampleRate` to `1.0`. This ensures that every user session will be sent to Sentry. - -Once testing is complete, **we recommend lowering this value in production**. We still recommend keeping `replaysOnErrorSampleRate` set to `1.0`, so that, whenever possible, every error has an associated replay with additional debugging context. - - -### PII & Privacy Considerations - -Personally identifiable information (PII) and privacy are important considerations when enabling Session Replay. There are multiple ways in which Sentry helps you avoid collecting PII, including: -- [Masking](/platforms/javascript/session-replay/privacy/#masking), which replaces the text content with something else -- the default behavior being to replace each character with a *. -- Making [network request, response bodies, and headers](/platforms/javascript/session-replay/privacy/#network-request-and-response-bodies-and-headers) an opt-in feature, because the best way to avoid getting PII into Sentry is by not adding URLs of endpoints that may contain PII. - -While we have certain privacy considerations in place, Sentry's Session Replay allows you to set up the [privacy configurations](/platforms/javascript/session-replay/privacy/#privacy-configuration) that work best for your use case. For example, if you're working on a static website that's free of PII or other types of private data, you can opt out of the default text masking and image blocking settings. -To learn more about Session Replay privacy, [read our docs.](/platforms/javascript/session-replay/privacy/) - -### Lazy-loading Replay - -Once you've added the integration, Replay will start automatically. If you don't want to start it immediately (lazy-load it), you can use `addIntegration`: - - diff --git a/platform-includes/session-replay/setup/javascript.svelte.mdx b/platform-includes/session-replay/setup/javascript.svelte.mdx deleted file mode 100644 index 078ecd6774291..0000000000000 --- a/platform-includes/session-replay/setup/javascript.svelte.mdx +++ /dev/null @@ -1,45 +0,0 @@ -```javascript {8,12,14-20} -import * as Sentry from "@sentry/svelte"; - -Sentry.init({ - dsn: "___PUBLIC_DSN___", - - // This sets the sample rate to be 10%. You may want this to be 100% while - // in development and sample at a lower rate in production - replaysSessionSampleRate: 0.1, - - // If the entire session is not sampled, use the below sample rate to sample - // sessions when an error occurs. - replaysOnErrorSampleRate: 1.0, - - integrations: [ - Sentry.replayIntegration({ - // Additional SDK configuration goes in here, for example: - maskAllText: true, - blockAllMedia: true, - }), - ], -}); -``` - -### Verify - -While you're testing, we recommend that you set `replaysSessionSampleRate` to `1.0`. This ensures that every user session will be sent to Sentry. - -Once testing is complete, **we recommend lowering this value in production**. We still recommend keeping `replaysOnErrorSampleRate` set to `1.0`, so that, whenever possible, every error has an associated replay with additional debugging context. - - -### PII & Privacy Considerations - -Personally identifiable information (PII) and privacy are important considerations when enabling Session Replay. There are multiple ways in which Sentry helps you avoid collecting PII, including: -- [Masking](/platforms/javascript/session-replay/privacy/#masking), which replaces the text content with something else -- the default behavior being to replace each character with a *. -- Making [network request, response bodies, and headers](/platforms/javascript/session-replay/privacy/#network-request-and-response-bodies-and-headers) an opt-in feature, because the best way to avoid getting PII into Sentry is by not adding URLs of endpoints that may contain PII. - -While we have certain privacy considerations in place, Sentry's Session Replay allows you to set up the [privacy configurations](/platforms/javascript/session-replay/privacy/#privacy-configuration) that work best for your use case. For example, if you're working on a static website that's free of PII or other types of private data, you can opt out of the default text masking and image blocking settings. -To learn more about Session Replay privacy, [read our docs.](/platforms/javascript/session-replay/privacy/) - -### Lazy-loading Replay - -Once you've added the integration, Replay will start automatically. If you don't want to start it immediately (lazy-load it), you can use `addIntegration`: - - diff --git a/platform-includes/session-replay/setup/javascript.vue.mdx b/platform-includes/session-replay/setup/javascript.vue.mdx deleted file mode 100644 index c3a9a632757b3..0000000000000 --- a/platform-includes/session-replay/setup/javascript.vue.mdx +++ /dev/null @@ -1,45 +0,0 @@ -```javascript {8,12,14-20} -import * as Sentry from "@sentry/vue"; - -Sentry.init({ - dsn: "___PUBLIC_DSN___", - - // This sets the sample rate to be 10%. You may want this to be 100% while - // in development and sample at a lower rate in production - replaysSessionSampleRate: 0.1, - - // If the entire session is not sampled, use the below sample rate to sample - // sessions when an error occurs. - replaysOnErrorSampleRate: 1.0, - - integrations: [ - Sentry.replayIntegration({ - // Additional SDK configuration goes in here, for example: - maskAllText: true, - blockAllMedia: true, - }), - ], -}); -``` - -### Verify - -While you're testing, we recommend that you set `replaysSessionSampleRate` to `1.0`. This ensures that every user session will be sent to Sentry. - -Once testing is complete, **we recommend lowering this value in production**. We still recommend keeping `replaysOnErrorSampleRate` set to `1.0`, so that, whenever possible, every error has an associated replay with additional debugging context. - - -### PII & Privacy Considerations - -Personally identifiable information (PII) and privacy are important considerations when enabling Session Replay. There are multiple ways in which Sentry helps you avoid collecting PII, including: -- [Masking](/platforms/javascript/session-replay/privacy/#masking), which replaces the text content with something else -- the default behavior being to replace each character with a *. -- Making [network request, response bodies, and headers](/platforms/javascript/session-replay/privacy/#network-request-and-response-bodies-and-headers) an opt-in feature, because the best way to avoid getting PII into Sentry is by not adding URLs of endpoints that may contain PII. - -While we have certain privacy considerations in place, Sentry's Session Replay allows you to set up the [privacy configurations](/platforms/javascript/session-replay/privacy/#privacy-configuration) that work best for your use case. For example, if you're working on a static website that's free of PII or other types of private data, you can opt out of the default text masking and image blocking settings. -To learn more about Session Replay privacy, [read our docs.](/platforms/javascript/session-replay/privacy/) - -### Lazy-loading Replay - -Once you've added the integration, Replay will start automatically. If you don't want to start it immediately (lazy-load it), you can use `addIntegration`: - - diff --git a/src/components/codeBlock/index.tsx b/src/components/codeBlock/index.tsx index 09c01cc0a6db5..30796aaa7c79b 100644 --- a/src/components/codeBlock/index.tsx +++ b/src/components/codeBlock/index.tsx @@ -134,7 +134,7 @@ export function CodeBlock({filename, language, children, externalLink}: CodeBloc // Only apply keyword interpolation after component mounts to prevent hydration mismatch // Server and client both render raw text initially, then client upgrades after mount const processedChildren = isMounted - ? makeKeywordsClickable(highlightedChildren) + ? makeKeywordsClickable(highlightedChildren, {sdkPackage: codeContext?.sdkPackage}) : highlightedChildren; return ( diff --git a/src/components/codeContext.tsx b/src/components/codeContext.tsx index 4fdf172cd8ff0..a086a2db41bec 100644 --- a/src/components/codeContext.tsx +++ b/src/components/codeContext.tsx @@ -110,6 +110,7 @@ type CodeContextType = { codeKeywords: CodeKeywords; isLoading: boolean; onboardingOptions: OnboardingOptionType[]; + sdkPackage: string | null; sharedKeywordSelection: [ Record, React.Dispatch>, @@ -329,7 +330,15 @@ const getLocallyStoredSelections = (): SelectedCodeTabs => { return {}; }; -export function CodeContextProvider({children}: {children: React.ReactNode}) { +type CodeContextProviderProps = { + children: React.ReactNode; + sdkPackage?: string | null; +}; + +export function CodeContextProvider({ + children, + sdkPackage = null, +}: CodeContextProviderProps) { const [codeKeywords, setCodeKeywords] = useState(cachedCodeKeywords ?? DEFAULTS); const [isLoading, setIsLoading] = useState(cachedCodeKeywords ? false : true); const [storedCodeSelection, setStoredCodeSelection] = useState({}); @@ -381,6 +390,7 @@ export function CodeContextProvider({children}: {children: React.ReactNode}) { isLoading, onboardingOptions, updateOnboardingOptions: options => setOnboardingOptions(options), + sdkPackage, }; return {children}; diff --git a/src/components/codeKeywords/codeKeywords.tsx b/src/components/codeKeywords/codeKeywords.tsx index 70011cb34a638..0b2ce43357575 100644 --- a/src/components/codeKeywords/codeKeywords.tsx +++ b/src/components/codeKeywords/codeKeywords.tsx @@ -7,10 +7,19 @@ import {OrgAuthTokenCreator} from './orgAuthTokenCreator'; export const KEYWORDS_REGEX = /\b___(?:([A-Z_][A-Z0-9_]*)\.)?([A-Z_][A-Z0-9_]*)___\b/g; export const ORG_AUTH_TOKEN_REGEX = /___ORG_AUTH_TOKEN___/g; +export const SDK_PACKAGE_REGEX = /___SDK_PACKAGE___/g; type ChildrenItem = ReturnType[number] | React.ReactNode; -export function makeKeywordsClickable(children: React.ReactNode) { +type MakeKeywordsClickableOptions = { + sdkPackage?: string | null; +}; + +export function makeKeywordsClickable( + children: React.ReactNode, + options: MakeKeywordsClickableOptions = {} +) { + const {sdkPackage} = options; const items = Children.toArray(children); return items.reduce((arr: ChildrenItem[], child) => { @@ -18,7 +27,7 @@ export function makeKeywordsClickable(children: React.ReactNode) { const updatedChild = cloneElement( child as ReactElement, {}, - makeKeywordsClickable((child as ReactElement).props.children) + makeKeywordsClickable((child as ReactElement).props.children, options) ); arr.push(updatedChild); return arr; @@ -27,9 +36,13 @@ export function makeKeywordsClickable(children: React.ReactNode) { // Reset regex lastIndex before testing to avoid stale state from previous matches ORG_AUTH_TOKEN_REGEX.lastIndex = 0; KEYWORDS_REGEX.lastIndex = 0; + SDK_PACKAGE_REGEX.lastIndex = 0; if (ORG_AUTH_TOKEN_REGEX.test(child)) { makeOrgAuthTokenClickable(arr, child); + } else if (SDK_PACKAGE_REGEX.test(child)) { + // Simple string replacement for SDK package (fallback to @sentry/browser on non-platform pages) + arr.push(child.replace(SDK_PACKAGE_REGEX, sdkPackage || '@sentry/browser')); } else if (KEYWORDS_REGEX.test(child)) { const isDSNKeyword = /___PUBLIC_DSN___/.test(child); makeProjectKeywordsClickable(arr, child, isDSNKeyword); diff --git a/src/components/docPage/index.tsx b/src/components/docPage/index.tsx index 9390875a78d01..6beddff9cdc98 100644 --- a/src/components/docPage/index.tsx +++ b/src/components/docPage/index.tsx @@ -1,6 +1,11 @@ import {ReactNode} from 'react'; -import {getCurrentGuide, getCurrentPlatform, nodeForPath} from 'sentry-docs/docTree'; +import { + getCurrentGuide, + getCurrentPlatform, + getCurrentPlatformOrGuide, + nodeForPath, +} from 'sentry-docs/docTree'; import {serverContext} from 'sentry-docs/serverContext'; import {FrontMatter} from 'sentry-docs/types'; import {PaginationNavNode} from 'sentry-docs/types/paginationNavNode'; @@ -19,6 +24,7 @@ import {Header} from '../header'; import Mermaid from '../mermaid'; import {PaginationNav} from '../paginationNav'; import {PlatformSdkDetail} from '../platformSdkDetail'; +import {getSdkPackageName} from '../platformSdkPackageName'; import {Sidebar} from '../sidebar'; import {SidebarTableOfContents} from '../sidebarTableOfContents'; import {ReaderDepthTracker} from '../track-reader-depth'; @@ -35,7 +41,7 @@ type Props = { sidebar?: ReactNode; }; -export function DocPage({ +export async function DocPage({ children, frontMatter, notoc = false, @@ -47,6 +53,8 @@ export function DocPage({ const {rootNode, path} = serverContext(); const currentPlatform = getCurrentPlatform(rootNode, path); const currentGuide = getCurrentGuide(rootNode, path); + const platformOrGuide = getCurrentPlatformOrGuide(rootNode, path); + const sdkPackage = await getSdkPackageName(platformOrGuide); const hasToc = (!notoc && !frontMatter.notoc) || !!(currentPlatform || currentGuide); const hasGithub = !!path?.length && path[0] !== 'api'; @@ -98,7 +106,9 @@ export function DocPage({ {/* This exact id is important for Algolia indexing */}
- {children} + + {children} +
diff --git a/src/components/docPage/type.scss b/src/components/docPage/type.scss index 9973978f9b8fb..93bf779ebd626 100644 --- a/src/components/docPage/type.scss +++ b/src/components/docPage/type.scss @@ -215,6 +215,15 @@ word-break: break-word; } } + + } + + // Override for compact tables that don't need min-width + .table-fit-content table { + td:last-child, + th:last-child { + min-width: unset; + } } dt + dd { diff --git a/src/components/platformSdkPackageName.tsx b/src/components/platformSdkPackageName.tsx index 51dc20b71ed77..2b0cc4003f0e7 100644 --- a/src/components/platformSdkPackageName.tsx +++ b/src/components/platformSdkPackageName.tsx @@ -1,6 +1,7 @@ import getPackageRegistry from 'sentry-docs/build/packageRegistry'; import {getCurrentPlatformOrGuide} from 'sentry-docs/docTree'; import {serverContext} from 'sentry-docs/serverContext'; +import {Platform, PlatformGuide} from 'sentry-docs/types/platform'; type PlatformSdkPackageNameProps = { /** @@ -11,15 +12,14 @@ type PlatformSdkPackageNameProps = { }; /** - * Displays the SDK package name for the current platform or guide. + * Gets the SDK package name for a platform or guide. * Example: `@sentry/react` */ -export async function PlatformSdkPackageName({fallback}: PlatformSdkPackageNameProps) { - const fallbackName = fallback || 'Sentry'; - const {rootNode, path} = serverContext(); - const platformOrGuide = getCurrentPlatformOrGuide(rootNode, path); +export async function getSdkPackageName( + platformOrGuide: Platform | PlatformGuide | null | undefined +): Promise { if (!platformOrGuide) { - return {fallbackName} ; + return null; } const packageRegistry = await getPackageRegistry(); @@ -27,14 +27,26 @@ export async function PlatformSdkPackageName({fallback}: PlatformSdkPackageNameP const entries = Object.entries(allSdks || {}); const pair = entries.find(([sdkName]) => sdkName === platformOrGuide.sdk); if (!pair) { - return {fallbackName} ; + return null; } const [, sdkData] = pair; if (!sdkData) { - return {fallbackName} ; + return null; } - const prettifiedName = sdkData.canonical.replace(/^npm:/, ''); + return sdkData.canonical.replace(/^npm:/, '') || null; +} + +/** + * Displays the SDK package name for the current platform or guide. + * Example: `@sentry/react` + */ +export async function PlatformSdkPackageName({fallback}: PlatformSdkPackageNameProps) { + const fallbackName = fallback || 'Sentry'; + const {rootNode, path} = serverContext(); + const platformOrGuide = getCurrentPlatformOrGuide(rootNode, path); + + const sdkPackage = await getSdkPackageName(platformOrGuide); - return {prettifiedName || fallbackName} ; + return {sdkPackage || fallbackName} ; }