Skip to content

Commit da68244

Browse files
committed
Merge remote-tracking branch 'origin/develop' into DominikB2014/add-span-domain-to-span-data
2 parents 8962a5a + acf58d3 commit da68244

File tree

247 files changed

+3425
-1027
lines changed

Some content is hidden

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

247 files changed

+3425
-1027
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

.git-blame-ignore-revs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ ef6b3c7877d5fc8031c08bb28b0ffafaeb01f501
1212

1313
# chore: Enforce formatting of MD files in repository root #10127
1414
aecf26f22dbf65ce2c0caadc4ce71b46266c9f45
15+
16+
# chore: Create dev-packages folder #9997
17+
35205b4cc5783237e69452c39ea001e461d9c84d

.github/workflows/build.yml

Lines changed: 12 additions & 3 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
@@ -776,8 +778,14 @@ jobs:
776778
strategy:
777779
fail-fast: false
778780
matrix:
779-
node: [14, 16, 18, 20, 21]
781+
node: [18, 20, 21]
780782
remix: [1, 2]
783+
# Remix v2 only supports Node 18+, so run Node 14, 16 tests separately
784+
include:
785+
- node: 14
786+
remix: 1
787+
- node: 16
788+
remix: 1
781789
steps:
782790
- name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }})
783791
uses: actions/checkout@v4
@@ -863,8 +871,9 @@ jobs:
863871
'node-express-app',
864872
'create-react-app',
865873
'create-next-app',
866-
'create-remix-app',
867-
'create-remix-app-v2',
874+
# disabling remix e2e tests because of flakes
875+
# 'create-remix-app',
876+
# 'create-remix-app-v2',
868877
'debug-id-sourcemaps',
869878
'nextjs-app-dir',
870879
'nextjs-14',

.size-limit.js

Lines changed: 14 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',
@@ -47,6 +54,13 @@ module.exports = [
4754
gzip: true,
4855
limit: '50 KB',
4956
},
57+
{
58+
name: '@sentry/browser (incl. sendFeedback) - Webpack (gzipped)',
59+
path: 'packages/browser/build/npm/esm/index.js',
60+
import: '{ init, sendFeedback }',
61+
gzip: true,
62+
limit: '50 KB',
63+
},
5064
{
5165
name: '@sentry/browser - Webpack (gzipped)',
5266
path: 'packages/browser/build/npm/esm/index.js',

MIGRATION.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,32 @@ npx @sentry/migr8@latest
1010
This will let you select which updates to run, and automatically update your code. Make sure to still review all code
1111
changes!
1212

13+
## Deprecate `getCurrentHub()`
14+
15+
In v8, you will no longer have a Hub, only Scopes as a concept. This also means that `getCurrentHub()` will eventually
16+
be removed.
17+
18+
Instead of `getCurrentHub()`, use the respective replacement API directly - see [Deprecate Hub](#deprecate-hub) for
19+
details.
20+
21+
## Deprecate class-based integrations
22+
23+
In v7, integrations are classes and can be added as e.g. `integrations: [new Sentry.Integrations.ContextLines()]`. In
24+
v8, integrations will not be classes anymore, but instead functions. Both the use as a class, as well as accessing
25+
integrations from the `Integrations.XXX` hash, is deprecated in favor of using the new functional integrations
26+
27+
- for example, `new Integrations.LinkedErrors()` becomes `linkedErrorsIntegration()`.
28+
29+
The following list shows how integrations should be migrated:
30+
31+
| Old | New |
32+
| ------------------------ | ------------------------------- |
33+
| `new InboundFilters()` | `inboundFiltersIntegrations()` |
34+
| `new FunctionToString()` | `functionToStringIntegration()` |
35+
| `new LinkedErrors()` | `linkedErrorsIntegration()` |
36+
| `new ModuleMetadata()` | `moduleMetadataIntegration()` |
37+
| `new RequestData()` | `requestDataIntegration()` |
38+
1339
## Deprecate `hub.bindClient()` and `makeMain()`
1440

1541
Instead, either directly use `initAndBind()`, or the new APIs `setCurrentClient()` and `client.init()`. See
@@ -54,7 +80,7 @@ If you are using the `Hub` right now, see the following table on how to migrate
5480
| ---------------------- | ------------------------------------------------------------------------------------ |
5581
| `new Hub()` | `withScope()`, `withIsolationScope()` or `new Scope()` |
5682
| hub.isOlderThan() | REMOVED - Was used to compare `Hub` instances, which are gonna be removed |
57-
| hub.bindClient() | A combination of `scope.setClient()` and `client.setupIntegrations()` |
83+
| hub.bindClient() | A combination of `scope.setClient()` and `client.init()` |
5884
| hub.pushScope() | `Sentry.withScope()` |
5985
| hub.popScope() | `Sentry.withScope()` |
6086
| hub.withScope() | `Sentry.withScope()` |
@@ -177,6 +203,10 @@ In v8, the Span class is heavily reworked. The following properties & methods ar
177203
- `span.setData()`: Use `span.setAttribute()` instead.
178204
- `span.instrumenter` This field was removed and will be replaced internally.
179205
- `span.transaction`: Use `getRootSpan` utility function instead.
206+
- `span.spanRecorder`: Span recording will be handled internally by the SDK.
207+
- `span.status`: Use `.setStatus` to set or update and `spanToJSON()` to read the span status.
208+
- `span.op`: Use `startSpan` functions to set, `setAttribute()` to update and `spanToJSON` to read the span operation.
209+
- `span.isSuccess`: Use `spanToJSON(span).status === 'ok'` instead.
180210
- `transaction.setMetadata()`: Use attributes instead, or set data on the scope.
181211
- `transaction.metadata`: Use attributes instead, or set data on the scope.
182212
- `transaction.setContext()`: Set context on the surrounding scope instead.

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.9.0",
4949
"@sentry/browser": "7.93.0",
5050
"@sentry/tracing": "7.93.0",
5151
"axios": "1.6.0",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
5+
Sentry.init({
6+
dsn: 'https://[email protected]/1337',
7+
beforeSend(event) {
8+
Sentry.captureUserFeedback({
9+
event_id: event.event_id,
10+
name: 'John Doe',
11+
12+
comments: 'This feedback should be attached associated with the captured error',
13+
});
14+
return event;
15+
},
16+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Sentry.captureException(new Error('Error with Feedback'));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { expect } from '@playwright/test';
2+
import type { Event, UserFeedback } from '@sentry/types';
3+
4+
import { sentryTest } from '../../../../utils/fixtures';
5+
import { getMultipleSentryEnvelopeRequests } from '../../../../utils/helpers';
6+
7+
sentryTest('capture user feedback when captureException is called', async ({ getLocalTestPath, page }) => {
8+
const url = await getLocalTestPath({ testDir: __dirname });
9+
10+
const data = (await getMultipleSentryEnvelopeRequests(page, 2, { url })) as (Event | UserFeedback)[];
11+
12+
expect(data).toHaveLength(2);
13+
14+
const errorEvent = ('exception' in data[0] ? data[0] : data[1]) as Event;
15+
const feedback = ('exception' in data[0] ? data[1] : data[0]) as UserFeedback;
16+
17+
expect(feedback).toEqual({
18+
comments: 'This feedback should be attached associated with the captured error',
19+
20+
event_id: errorEvent.event_id,
21+
name: 'John Doe',
22+
});
23+
});
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
5+
Sentry.init({
6+
dsn: 'https://[email protected]/1337',
7+
beforeSend(event) {
8+
Sentry.captureUserFeedback({
9+
event_id: event.event_id,
10+
name: 'John Doe',
11+
12+
comments: 'This feedback should be attached associated with the captured message',
13+
});
14+
return event;
15+
},
16+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Sentry.captureMessage('Message with Feedback');
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { expect } from '@playwright/test';
2+
import type { Event, UserFeedback } from '@sentry/types';
3+
4+
import { sentryTest } from '../../../../utils/fixtures';
5+
import { getMultipleSentryEnvelopeRequests } from '../../../../utils/helpers';
6+
7+
sentryTest('capture user feedback when captureMessage is called', async ({ getLocalTestPath, page }) => {
8+
const url = await getLocalTestPath({ testDir: __dirname });
9+
10+
const data = (await getMultipleSentryEnvelopeRequests(page, 2, { url })) as (Event | UserFeedback)[];
11+
12+
expect(data).toHaveLength(2);
13+
14+
const errorEvent = ('exception' in data[0] ? data[0] : data[1]) as Event;
15+
const feedback = ('exception' in data[0] ? data[1] : data[0]) as UserFeedback;
16+
17+
expect(feedback).toEqual({
18+
comments: 'This feedback should be attached associated with the captured message',
19+
20+
event_id: errorEvent.event_id,
21+
name: 'John Doe',
22+
});
23+
});

dev-packages/browser-integration-tests/suites/public-api/startTransaction/basic_usage/test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,20 @@ sentryTest('should report finished spans as children of the root transaction', a
2929
expect(transaction.spans).toHaveLength(3);
3030

3131
const span_1 = transaction.spans?.[0];
32+
33+
// eslint-disable-next-line deprecation/deprecation
3234
expect(span_1?.op).toBe('span_1');
3335
expect(span_1?.parentSpanId).toEqual(rootSpanId);
3436
// eslint-disable-next-line deprecation/deprecation
3537
expect(span_1?.data).toMatchObject({ foo: 'bar', baz: [1, 2, 3] });
3638

3739
const span_3 = transaction.spans?.[1];
40+
// eslint-disable-next-line deprecation/deprecation
3841
expect(span_3?.op).toBe('span_3');
3942
expect(span_3?.parentSpanId).toEqual(rootSpanId);
4043

4144
const span_5 = transaction.spans?.[2];
45+
// eslint-disable-next-line deprecation/deprecation
4246
expect(span_5?.op).toBe('span_5');
4347
// eslint-disable-next-line deprecation/deprecation
4448
expect(span_5?.parentSpanId).toEqual(span_3?.spanId);
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: 50,
6+
flushMaxDelay: 50,
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({ enableManualSnapshot: true })],
18+
});
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
</head>
6+
<body>
7+
<canvas id="canvas" width="150" height="150"></canvas>
8+
<button id="draw">Draw</button>
9+
</body>
10+
11+
12+
<script>
13+
function draw() {
14+
const canvas = document.getElementById("canvas");
15+
if (canvas.getContext) {
16+
console.log('has canvas')
17+
const ctx = canvas.getContext("2d");
18+
19+
ctx.fillRect(25, 25, 100, 100);
20+
ctx.clearRect(45, 45, 60, 60);
21+
ctx.strokeRect(50, 50, 50, 50);
22+
}
23+
}
24+
document.getElementById('draw').addEventListener('click', draw);
25+
</script>
26+
</html>
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { expect } from '@playwright/test';
2+
3+
import { sentryTest } from '../../../../utils/fixtures';
4+
import { getReplayRecordingContent, shouldSkipReplayTest, waitForReplayRequest } from '../../../../utils/replayHelpers';
5+
6+
sentryTest('can manually snapshot canvas', async ({ getLocalTestUrl, page, browserName }) => {
7+
if (shouldSkipReplayTest() || browserName === 'webkit' || (process.env.PW_BUNDLE || '').startsWith('bundle')) {
8+
sentryTest.skip();
9+
}
10+
11+
const reqPromise0 = waitForReplayRequest(page, 0);
12+
const reqPromise1 = waitForReplayRequest(page, 1);
13+
const reqPromise2 = waitForReplayRequest(page, 2);
14+
const reqPromise3 = waitForReplayRequest(page, 3);
15+
16+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
17+
return route.fulfill({
18+
status: 200,
19+
contentType: 'application/json',
20+
body: JSON.stringify({ id: 'test-id' }),
21+
});
22+
});
23+
24+
const url = await getLocalTestUrl({ testDir: __dirname });
25+
26+
await page.goto(url);
27+
await reqPromise0;
28+
await Promise.all([page.click('#draw'), reqPromise1]);
29+
30+
const { incrementalSnapshots } = getReplayRecordingContent(await reqPromise2);
31+
expect(incrementalSnapshots).toEqual([]);
32+
33+
await page.evaluate(() => {
34+
(window as any).Sentry.getClient().getIntegrationById('ReplayCanvas').snapshot();
35+
});
36+
37+
const { incrementalSnapshots: incrementalSnapshotsManual } = getReplayRecordingContent(await reqPromise3);
38+
expect(incrementalSnapshotsManual).toEqual(
39+
expect.arrayContaining([
40+
{
41+
data: {
42+
commands: [
43+
{
44+
args: [0, 0, 150, 150],
45+
property: 'clearRect',
46+
},
47+
{
48+
args: [
49+
{
50+
args: [
51+
{
52+
data: [
53+
{
54+
base64: expect.any(String),
55+
rr_type: 'ArrayBuffer',
56+
},
57+
],
58+
rr_type: 'Blob',
59+
type: 'image/webp',
60+
},
61+
],
62+
rr_type: 'ImageBitmap',
63+
},
64+
0,
65+
0,
66+
],
67+
property: 'drawImage',
68+
},
69+
],
70+
id: 9,
71+
source: 9,
72+
type: 0,
73+
},
74+
timestamp: 0,
75+
type: 3,
76+
},
77+
]),
78+
);
79+
});

0 commit comments

Comments
 (0)