Skip to content

Commit 11a8afe

Browse files
billyvgmydea
andauthored
feat(replay): Add ReplayCanvas integration (#10112)
Adding this integration in addition to `Replay` will set up canvas recording. ```javascript Sentry.init({ dsn: '', integrations: [ Sentry.Replay(), Sentry.ReplayCanvas(), ] }); ``` --------- Co-authored-by: Francesco Novy <[email protected]>
1 parent 70d1cbb commit 11a8afe

File tree

52 files changed

+659
-108
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+659
-108
lines changed

.craft.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ targets:
3232
- name: npm
3333
id: '@sentry-internal/feedback'
3434
includeNames: /^sentry-internal-feedback-\d.*\.tgz$/
35+
## 1.8 ReplayCanvas package (browser only)
36+
- name: npm
37+
id: '@sentry-internal/replay-canvas'
38+
includeNames: /^sentry-internal-replay-canvas-\d.*\.tgz$/
3539

3640
## 2. Browser & Node SDKs
3741
- name: npm

.github/workflows/build.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ jobs:
100100
- *shared
101101
- 'packages/browser/**'
102102
- 'packages/replay/**'
103+
- 'packages/replay-canvas/**'
103104
- 'packages/feedback/**'
104105
browser_integration:
105106
- *shared
@@ -371,6 +372,7 @@ jobs:
371372
${{ github.workspace }}/packages/browser/build/bundles/**
372373
${{ github.workspace }}/packages/integrations/build/bundles/**
373374
${{ github.workspace }}/packages/replay/build/bundles/**
375+
${{ github.workspace }}/packages/replay-canvas/build/bundles/**
374376
${{ github.workspace }}/packages/**/*.tgz
375377
${{ github.workspace }}/packages/serverless/build/aws/dist-serverless/*.zip
376378

.size-limit.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ module.exports = [
1414
gzip: true,
1515
limit: '75 KB',
1616
},
17+
{
18+
name: '@sentry/browser (incl. Tracing, Replay with Canvas) - Webpack (gzipped)',
19+
path: 'packages/browser/build/npm/esm/index.js',
20+
import: '{ init, Replay, BrowserTracing, ReplayCanvas }',
21+
gzip: true,
22+
limit: '90 KB',
23+
},
1724
{
1825
name: '@sentry/browser (incl. Tracing, Replay) - Webpack with treeshaking flags (gzipped)',
1926
path: 'packages/browser/build/npm/esm/index.js',

dev-packages/browser-integration-tests/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"dependencies": {
4646
"@babel/preset-typescript": "^7.16.7",
4747
"@playwright/test": "^1.31.1",
48-
"@sentry-internal/rrweb": "2.7.3",
48+
"@sentry-internal/rrweb": "2.8.0",
4949
"@sentry/browser": "7.93.0",
5050
"@sentry/tracing": "7.93.0",
5151
"axios": "1.6.0",
Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
1-
import { getCanvasManager } from '@sentry-internal/rrweb';
21
import * as Sentry from '@sentry/browser';
32

43
window.Sentry = Sentry;
54
window.Replay = new Sentry.Replay({
65
flushMinDelay: 50,
76
flushMaxDelay: 50,
87
minReplayDuration: 0,
9-
_experiments: {
10-
canvas: {
11-
manager: getCanvasManager,
12-
},
13-
},
148
});
159

1610
Sentry.init({
@@ -20,5 +14,5 @@ Sentry.init({
2014
replaysOnErrorSampleRate: 0.0,
2115
debug: true,
2216

23-
integrations: [window.Replay],
17+
integrations: [window.Replay, new Sentry.ReplayCanvas()],
2418
});

dev-packages/browser-integration-tests/suites/replay/canvas/records/test.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { sentryTest } from '../../../../utils/fixtures';
44
import { getReplayRecordingContent, shouldSkipReplayTest, waitForReplayRequest } from '../../../../utils/replayHelpers';
55

66
sentryTest('can record canvas', async ({ getLocalTestUrl, page, browserName }) => {
7-
if (shouldSkipReplayTest() || browserName === 'webkit') {
7+
if (shouldSkipReplayTest() || browserName === 'webkit' || (process.env.PW_BUNDLE || '').startsWith('bundle')) {
88
sentryTest.skip();
99
}
1010

@@ -24,6 +24,16 @@ sentryTest('can record canvas', async ({ getLocalTestUrl, page, browserName }) =
2424

2525
await page.goto(url);
2626
await reqPromise0;
27+
const content0 = getReplayRecordingContent(await reqPromise0);
28+
expect(content0.optionsEvents).toEqual([
29+
{
30+
tag: 'options',
31+
payload: expect.objectContaining({
32+
shouldRecordCanvas: true,
33+
}),
34+
},
35+
]);
36+
2737
await Promise.all([page.click('#draw'), reqPromise1]);
2838

2939
const { incrementalSnapshots } = getReplayRecordingContent(await reqPromise2);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
window.Replay = new Sentry.Replay({
5+
flushMinDelay: 200,
6+
flushMaxDelay: 200,
7+
minReplayDuration: 0,
8+
});
9+
10+
Sentry.init({
11+
dsn: 'https://[email protected]/1337',
12+
sampleRate: 0,
13+
replaysSessionSampleRate: 1.0,
14+
replaysOnErrorSampleRate: 0.0,
15+
debug: true,
16+
17+
integrations: [new Sentry.ReplayCanvas(), window.Replay],
18+
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { expect } from '@playwright/test';
2+
3+
import { sentryTest } from '../../../../utils/fixtures';
4+
import { getReplaySnapshot, shouldSkipReplayTest, waitForReplayRequest } from '../../../../utils/replayHelpers';
5+
6+
sentryTest('sets up canvas when adding ReplayCanvas integration first', async ({ getLocalTestUrl, page }) => {
7+
if (shouldSkipReplayTest() || (process.env.PW_BUNDLE || '').startsWith('bundle')) {
8+
sentryTest.skip();
9+
}
10+
11+
const reqPromise0 = waitForReplayRequest(page, 0);
12+
13+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
14+
return route.fulfill({
15+
status: 200,
16+
contentType: 'application/json',
17+
body: JSON.stringify({ id: 'test-id' }),
18+
});
19+
});
20+
21+
const url = await getLocalTestUrl({ testDir: __dirname });
22+
23+
await page.goto(url);
24+
await reqPromise0;
25+
26+
const replay = await getReplaySnapshot(page);
27+
const canvasOptions = replay._canvas;
28+
expect(canvasOptions?.sampling.canvas).toBe(2);
29+
expect(canvasOptions?.dataURLOptions.quality).toBe(0.4);
30+
expect(replay._hasCanvas).toBe(true);
31+
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
window.Replay = new Sentry.Replay({
5+
flushMinDelay: 200,
6+
flushMaxDelay: 200,
7+
minReplayDuration: 0,
8+
});
9+
10+
Sentry.init({
11+
dsn: 'https://[email protected]/1337',
12+
sampleRate: 0,
13+
replaysSessionSampleRate: 1.0,
14+
replaysOnErrorSampleRate: 0.0,
15+
debug: true,
16+
17+
integrations: [window.Replay, new Sentry.ReplayCanvas()],
18+
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { expect } from '@playwright/test';
2+
3+
import { sentryTest } from '../../../../utils/fixtures';
4+
import { getReplaySnapshot, shouldSkipReplayTest, waitForReplayRequest } from '../../../../utils/replayHelpers';
5+
6+
sentryTest('sets up canvas when adding ReplayCanvas integration after Replay', async ({ getLocalTestUrl, page }) => {
7+
if (shouldSkipReplayTest() || (process.env.PW_BUNDLE || '').startsWith('bundle')) {
8+
sentryTest.skip();
9+
}
10+
11+
const reqPromise0 = waitForReplayRequest(page, 0);
12+
13+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
14+
return route.fulfill({
15+
status: 200,
16+
contentType: 'application/json',
17+
body: JSON.stringify({ id: 'test-id' }),
18+
});
19+
});
20+
21+
const url = await getLocalTestUrl({ testDir: __dirname });
22+
23+
await page.goto(url);
24+
await reqPromise0;
25+
26+
const replay = await getReplaySnapshot(page);
27+
const canvasOptions = replay._canvas;
28+
expect(canvasOptions?.sampling.canvas).toBe(2);
29+
expect(canvasOptions?.dataURLOptions.quality).toBe(0.4);
30+
expect(replay._hasCanvas).toBe(true);
31+
});

0 commit comments

Comments
 (0)