Skip to content

Commit 8647499

Browse files
committed
Merge branch 'develop' into beta
2 parents cd247f2 + ab28544 commit 8647499

File tree

51 files changed

+1798
-290
lines changed

Some content is hidden

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

51 files changed

+1798
-290
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,7 @@ jobs:
921921
'tanstack-router',
922922
'generic-ts3.8',
923923
'node-fastify',
924+
'node-fastify-5',
924925
'node-hapi',
925926
'node-nestjs-basic',
926927
'node-nestjs-distributed-tracing',

.github/workflows/release-comment-issues.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ jobs:
2020
run: echo "version=${{ github.event.inputs.version || github.event.release.tag_name }}" >> $GITHUB_OUTPUT
2121

2222
- name: Comment on linked issues that are mentioned in release
23-
if: steps.get_version.outputs.version != ''
23+
if: |
24+
steps.get_version.outputs.version != ''
25+
&& !contains(steps.get_version.outputs.version, '-beta.')
26+
&& !contains(steps.get_version.outputs.version, '-alpha.')
27+
&& !contains(steps.get_version.outputs.version, '-rc.')
28+
2429
uses: getsentry/release-comment-issues-gh-action@v1
2530
with:
2631
github_token: ${{ secrets.GITHUB_TOKEN }}

.size-limit.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ module.exports = [
138138
import: createImport('init', 'ErrorBoundary', 'reactRouterV6BrowserTracingIntegration'),
139139
ignore: ['react/jsx-runtime'],
140140
gzip: true,
141-
limit: '39 KB',
141+
limit: '39.05 KB',
142142
},
143143
// Vue SDK (ESM)
144144
{

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

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,125 @@ sentryTest(
287287
},
288288
);
289289

290+
sentryTest(
291+
'[buffer-mode] manually starting replay ignores earlier performance entries',
292+
async ({ getLocalTestUrl, page, browserName }) => {
293+
// This was sometimes flaky on webkit, so skipping for now
294+
if (shouldSkipReplayTest() || browserName === 'webkit') {
295+
sentryTest.skip();
296+
}
297+
298+
const reqPromise0 = waitForReplayRequest(page, 0);
299+
300+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
301+
return route.fulfill({
302+
status: 200,
303+
contentType: 'application/json',
304+
body: JSON.stringify({ id: 'test-id' }),
305+
});
306+
});
307+
308+
const url = await getLocalTestUrl({ testDir: __dirname });
309+
310+
await page.goto(url);
311+
312+
// Wait for everything to be initialized - Replay is not running yet
313+
await page.waitForFunction('!!window.Replay');
314+
315+
// Wait for a second, then start replay
316+
await new Promise(resolve => setTimeout(resolve, 1000));
317+
await page.evaluate('window.Replay.start()');
318+
319+
const req0 = await reqPromise0;
320+
321+
const event0 = getReplayEvent(req0);
322+
const content0 = getReplayRecordingContent(req0);
323+
324+
expect(event0).toEqual(
325+
getExpectedReplayEvent({
326+
replay_type: 'session',
327+
}),
328+
);
329+
330+
const { performanceSpans } = content0;
331+
332+
// Here, we test that this does not contain any web-vital etc. performance spans
333+
// as these have been emitted _before_ the replay was manually started
334+
expect(performanceSpans).toEqual([
335+
{
336+
op: 'memory',
337+
description: 'memory',
338+
startTimestamp: expect.any(Number),
339+
endTimestamp: expect.any(Number),
340+
data: {
341+
memory: {
342+
jsHeapSizeLimit: expect.any(Number),
343+
totalJSHeapSize: expect.any(Number),
344+
usedJSHeapSize: expect.any(Number),
345+
},
346+
},
347+
},
348+
]);
349+
},
350+
);
351+
352+
sentryTest(
353+
'[buffer-mode] manually starting replay ignores earlier performance entries when starting immediately',
354+
async ({ getLocalTestUrl, page, browserName }) => {
355+
// This was sometimes flaky on webkit, so skipping for now
356+
if (shouldSkipReplayTest() || browserName === 'webkit') {
357+
sentryTest.skip();
358+
}
359+
360+
const reqPromise0 = waitForReplayRequest(page, 0);
361+
362+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
363+
return route.fulfill({
364+
status: 200,
365+
contentType: 'application/json',
366+
body: JSON.stringify({ id: 'test-id' }),
367+
});
368+
});
369+
370+
const url = await getLocalTestUrl({ testDir: __dirname });
371+
372+
page.goto(url);
373+
374+
// Wait for everything to be initialized, then start replay as soon as possible
375+
await page.waitForFunction('!!window.Replay');
376+
await page.evaluate('window.Replay.start()');
377+
378+
const req0 = await reqPromise0;
379+
380+
const event0 = getReplayEvent(req0);
381+
const content0 = getReplayRecordingContent(req0);
382+
383+
expect(event0).toEqual(
384+
getExpectedReplayEvent({
385+
replay_type: 'session',
386+
}),
387+
);
388+
389+
const { performanceSpans } = content0;
390+
391+
expect(performanceSpans).toEqual([
392+
{
393+
op: 'memory',
394+
description: 'memory',
395+
startTimestamp: expect.any(Number),
396+
endTimestamp: expect.any(Number),
397+
data: {
398+
memory: {
399+
jsHeapSizeLimit: expect.any(Number),
400+
totalJSHeapSize: expect.any(Number),
401+
usedJSHeapSize: expect.any(Number),
402+
},
403+
},
404+
},
405+
]);
406+
},
407+
);
408+
290409
// Doing this in buffer mode to test changing error sample rate after first
291410
// error happens.
292411
sentryTest(
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
5+
Sentry.init({
6+
dsn: 'https://[email protected]/1337',
7+
integrations: [Sentry.browserTracingIntegration()],
8+
tracePropagationTargets: ['http://example.com'],
9+
tracesSampleRate: 1,
10+
});
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
fetchPojo.addEventListener('click', () => {
2+
const fetchOptions = {
3+
headers: {
4+
'sentry-trace': '12312012123120121231201212312012-1121201211212012-1',
5+
baggage: 'sentry-release=4.2.0',
6+
},
7+
};
8+
9+
// Make two fetch requests that reuse the same fetch object
10+
Sentry.startSpan({ name: 'does-not-matter-1' }, () =>
11+
fetch('http://example.com/fetch-pojo', fetchOptions)
12+
.then(res => res.text())
13+
.then(() =>
14+
Sentry.startSpan({ name: 'does-not-matter-2' }, () => fetch('http://example.com/fetch-pojo', fetchOptions)),
15+
),
16+
);
17+
});
18+
19+
fetchArray.addEventListener('click', () => {
20+
const fetchOptions = {
21+
headers: [
22+
['sentry-trace', '12312012123120121231201212312012-1121201211212012-1'],
23+
['baggage', 'sentry-release=4.2.0'],
24+
],
25+
};
26+
27+
// Make two fetch requests that reuse the same fetch object
28+
Sentry.startSpan({ name: 'does-not-matter-1' }, () =>
29+
fetch('http://example.com/fetch-array', fetchOptions)
30+
.then(res => res.text())
31+
.then(() =>
32+
Sentry.startSpan({ name: 'does-not-matter-2' }, () => fetch('http://example.com/fetch-array', fetchOptions)),
33+
),
34+
);
35+
});
36+
37+
fetchHeaders.addEventListener('click', () => {
38+
const fetchOptions = {
39+
headers: new Headers({
40+
'sentry-trace': '12312012123120121231201212312012-1121201211212012-1',
41+
baggage: 'sentry-release=4.2.0',
42+
}),
43+
};
44+
45+
// Make two fetch requests that reuse the same fetch object
46+
Sentry.startSpan({ name: 'does-not-matter-1' }, () =>
47+
fetch('http://example.com/fetch-headers', fetchOptions)
48+
.then(res => res.text())
49+
.then(() =>
50+
Sentry.startSpan({ name: 'does-not-matter-2' }, () => fetch('http://example.com/fetch-headers', fetchOptions)),
51+
),
52+
);
53+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
</head>
6+
<body>
7+
<button id="fetchPojo">Fetch POJO</button>
8+
<button id="fetchArray">Fetch array</button>
9+
<button id="fetchHeaders">Fetch Headers</button>
10+
</body>
11+
</html>
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import type { Page, Request } from '@playwright/test';
2+
import { expect } from '@playwright/test';
3+
import { sentryTest } from '../../../../utils/fixtures';
4+
import { shouldSkipTracingTest } from '../../../../utils/helpers';
5+
6+
async function assertRequests({
7+
page,
8+
buttonSelector,
9+
requestMatcher,
10+
}: { page: Page; buttonSelector: string; requestMatcher: string }) {
11+
const requests = await new Promise<Request[]>(resolve => {
12+
const requests: Request[] = [];
13+
page
14+
.route(requestMatcher, (route, request) => {
15+
requests.push(request);
16+
if (requests.length === 2) {
17+
resolve(requests);
18+
}
19+
20+
return route.fulfill({
21+
status: 200,
22+
contentType: 'application/json',
23+
body: JSON.stringify({}),
24+
});
25+
})
26+
.then(() => {
27+
page.click(buttonSelector);
28+
});
29+
});
30+
31+
requests.forEach(request => {
32+
const headers = request.headers();
33+
34+
// No merged sentry trace headers
35+
expect(headers['sentry-trace']).not.toContain(',');
36+
37+
// No multiple baggage entries
38+
expect(headers['baggage'].match(/sentry-trace_id/g) ?? []).toHaveLength(1);
39+
});
40+
}
41+
42+
sentryTest(
43+
'Ensure the SDK does not infinitely append tracing headers to outgoing requests',
44+
async ({ getLocalTestUrl, page }) => {
45+
if (shouldSkipTracingTest()) {
46+
sentryTest.skip();
47+
}
48+
49+
const url = await getLocalTestUrl({ testDir: __dirname });
50+
await page.goto(url);
51+
52+
await sentryTest.step('fetch with POJO', () =>
53+
assertRequests({ page, buttonSelector: '#fetchPojo', requestMatcher: 'http://example.com/fetch-pojo' }),
54+
);
55+
56+
await sentryTest.step('fetch with array', () =>
57+
assertRequests({ page, buttonSelector: '#fetchArray', requestMatcher: 'http://example.com/fetch-array' }),
58+
);
59+
60+
await sentryTest.step('fetch with Headers instance', () =>
61+
assertRequests({ page, buttonSelector: '#fetchHeaders', requestMatcher: 'http://example.com/fetch-headers' }),
62+
);
63+
},
64+
);

dev-packages/e2e-tests/test-applications/cloudflare-astro/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"dependencies": {
2020
"@astrojs/cloudflare": "8.1.0",
2121
"@sentry/astro": "latest || *",
22-
"astro": "4.1.1"
22+
"astro": "4.16.1"
2323
},
2424
"volta": {
2525
"extends": "../../package.json"

dev-packages/e2e-tests/test-applications/nextjs-15/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"test:dev": "TEST_ENV=development playwright test",
1010
"test:build": "pnpm install && npx playwright install && pnpm build",
1111
"test:build-canary": "pnpm install && pnpm add next@canary && pnpm add react@beta && pnpm add react-dom@beta && npx playwright install && pnpm build",
12-
"test:build-latest": "pnpm install && pnpm add next@rc && pnpm add react@beta && pnpm add react-dom@beta && npx playwright install && pnpm build",
12+
"//": "15.0.0-canary.194 is the canary release attached to Next.js RC 1. We need to use the canary version instead of the RC because PPR will not work without. The specific react version is also attached to RC 1.",
13+
"test:build-latest": "pnpm install && pnpm add [email protected] && pnpm add [email protected] && pnpm add [email protected] && npx playwright install && pnpm build",
1314
"test:assert": "pnpm test:prod && pnpm test:dev"
1415
},
1516
"dependencies": {

0 commit comments

Comments
 (0)