Skip to content

Commit 77d4204

Browse files
authored
Merge pull request #8271 from getsentry/prepare-release/7.54.0
meta: Update changelog for 7.54.0
2 parents 5273d49 + 95f8756 commit 77d4204

File tree

56 files changed

+1203
-169
lines changed

Some content is hidden

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

56 files changed

+1203
-169
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ jobs:
475475
needs: [job_get_metadata, job_build]
476476
if: needs.job_get_metadata.outputs.changed_browser_integration == 'true' || github.event_name != 'pull_request'
477477
runs-on: ubuntu-20.04
478-
timeout-minutes: 18
478+
timeout-minutes: 25
479479
strategy:
480480
fail-fast: false
481481
matrix:

.github/workflows/canary.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,14 @@ jobs:
5353
cd packages/e2e-tests
5454
yarn test:e2e
5555
- name: Create Issue
56-
if: failure()
56+
if: failure() && github.event_name == 'schedule'
5757
uses: JasonEtco/create-an-issue@e27dddc79c92bc6e4562f268fffa5ed752639abd
5858
env:
5959
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6060
RUN_LINK: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
6161
with:
6262
filename: .github/CANARY_FAILURE_TEMPLATE.md
63+
update_existing: true
6364

6465
job_ember_canary_test:
6566
name: Ember Canary Tests
@@ -92,10 +93,12 @@ jobs:
9293
yarn ember try:one ${{ matrix.scenario }} --skip-cleanup=true
9394
9495
- name: Create Issue
95-
if: failure()
96+
if: failure() && github.event_name == 'schedule'
9697
uses: JasonEtco/create-an-issue@e27dddc79c92bc6e4562f268fffa5ed752639abd
9798
env:
9899
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
99100
RUN_LINK: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
100101
with:
101102
filename: .github/CANARY_FAILURE_TEMPLATE.md
103+
update_existing: true
104+
title: 'Ember Canary tests failed'

CHANGELOG.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,69 @@
44

55
- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott
66

7+
## 7.54.0
8+
9+
### Important Changes
10+
11+
- **feat(core): Add default entries to `ignoreTransactions` for Healthchecks #8191**
12+
13+
All SDKs now filter out health check transactions by default.
14+
These are transactions where the transaction name matches typical API health check calls, such as `/^.*healthy.*$/` or `/^. *heartbeat.*$/`. Take a look at [this list](https://github.com/getsentry/sentry-javascript/blob/8c6ad156829f7c4eec34e4a67e6dd866ba482d5d/packages/core/src/integrations/inboundfilters.ts#L8C2-L16) to learn which regexes we currently use to match transaction names.
15+
We believe that these transactions do not provide value in most cases and we want to save you some of your quota by filtering them out by default.
16+
These filters are implemented as default values for the top level `ignoreTransactions` option.
17+
18+
You can disable this filtering by manually specifiying the `InboundFilters` integration and setting the `disableTransactionDefaults` option:
19+
```js
20+
Sentry.init({
21+
//...
22+
integrations: [new InboundFilters({ disableTransactionDefaults: true })],
23+
})
24+
```
25+
26+
- **feat(replay): Add `mutationBreadcrumbLimit` and `mutationLimit` to Replay Options (#8228)**
27+
28+
The previously experimental options `mutationBreadcumbLimit` and `mutationLimit` have been promoted to regular Replay integration options.
29+
30+
A high number of DOM mutations (in a single event loop) can cause performance regressions in end-users' browsers.
31+
Use `mutationBreadcrumbLimit` to send a breadcrumb along with your recording if the mutation limit was reached.
32+
Use `mutationLimit` to stop recording if the mutation limit was reached.
33+
34+
- **feat(sveltekit): Add source maps support for Vercel (lambda) (#8256)**
35+
- feat(sveltekit): Auto-detect SvelteKit adapters (#8193)
36+
37+
The SvelteKit SDK can now be used if you deploy your SvelteKit app to Vercel.
38+
By default, the SDK's Vite plugin will detect the used adapter and adjust the source map uploading config as necessary.
39+
If you want to override the default adapter detection, you can specify the `adapter` option in the `sentrySvelteKit` options:
40+
41+
```js
42+
// vite.config.js
43+
export default defineConfig({
44+
plugins: [
45+
sentrySvelteKit({
46+
adapter: 'vercel',
47+
}),
48+
sveltekit(),
49+
],
50+
});
51+
```
52+
53+
Currently, the Vite plugin will configure itself correctly for `@sveltejs/adapter-auto`, `@sveltejs/adapter-vercel` and `@sveltejs/adapter-node`.
54+
55+
**Important:** The SvelteKit SDK is not yet compatible with Vercel's edge runtime.
56+
It will only work for lambda functions.
57+
58+
### Other Changes
59+
60+
- feat(replay): Throttle breadcrumbs to max 300/5s (#8086)
61+
- feat(sveltekit): Add option to control handling of unknown server routes (#8201)
62+
- fix(node): Strip query and fragment from request URLs without route parameters (#8213)
63+
- fix(remix): Don't log missing parameters warning on server-side. (#8269)
64+
- fix(remix): Pass `loadContext` through wrapped document request function (#8268)
65+
- fix(replay): Guard against missing key (#8246)
66+
- fix(sveltekit): Avoid capturing redirects and 4xx Http errors in request Handlers (#8215)
67+
- fix(sveltekit): Bump `magicast` to support `satisfied` keyword (#8254)
68+
- fix(wasm): Avoid throwing an error when WASM modules are loaded from blobs (#8263)
69+
770
## 7.53.1
871

972
- chore(deps): bump socket.io-parser from 4.2.1 to 4.2.3 (#8196)

packages/browser-integration-tests/suites/replay/largeMutations/mutationLimit/init.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ window.Sentry = Sentry;
44
window.Replay = new Sentry.Replay({
55
flushMinDelay: 500,
66
flushMaxDelay: 500,
7-
_experiments: {
8-
mutationLimit: 250,
9-
},
7+
mutationLimit: 250,
108
});
119

1210
Sentry.init({

packages/browser-integration-tests/suites/replay/largeMutations/mutationLimit/test.ts

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
import { expect } from '@playwright/test';
22

33
import { sentryTest } from '../../../../utils/fixtures';
4-
import { getReplayRecordingContent, shouldSkipReplayTest, waitForReplayRequest } from '../../../../utils/replayHelpers';
4+
import {
5+
getReplayRecordingContent,
6+
getReplaySnapshot,
7+
shouldSkipReplayTest,
8+
waitForReplayRequest,
9+
} from '../../../../utils/replayHelpers';
510

611
sentryTest(
7-
'handles large mutations with _experiments.mutationLimit configured',
12+
'handles large mutations by stopping replay when `mutationLimit` configured',
813
async ({ getLocalTestPath, page, forceFlushReplay, browserName }) => {
914
if (shouldSkipReplayTest() || ['webkit', 'firefox'].includes(browserName)) {
1015
sentryTest.skip();
@@ -34,36 +39,29 @@ sentryTest(
3439
await forceFlushReplay();
3540
const res1 = await reqPromise1;
3641

37-
const reqPromise2 = waitForReplayRequest(page);
42+
// replay should be stopped due to mutation limit
43+
let replay = await getReplaySnapshot(page);
44+
expect(replay.session).toBe(undefined);
45+
expect(replay._isEnabled).toBe(false);
3846

3947
void page.click('#button-modify');
4048
await forceFlushReplay();
41-
const res2 = await reqPromise2;
4249

43-
const reqPromise3 = waitForReplayRequest(page);
44-
45-
void page.click('#button-remove');
50+
await page.click('#button-remove');
4651
await forceFlushReplay();
47-
const res3 = await reqPromise3;
4852

4953
const replayData0 = getReplayRecordingContent(res0);
50-
const replayData1 = getReplayRecordingContent(res1);
51-
const replayData2 = getReplayRecordingContent(res2);
52-
const replayData3 = getReplayRecordingContent(res3);
53-
5454
expect(replayData0.fullSnapshots.length).toBe(1);
5555
expect(replayData0.incrementalSnapshots.length).toBe(0);
5656

57-
// This includes both a full snapshot as well as some incremental snapshots
58-
expect(replayData1.fullSnapshots.length).toBe(1);
57+
// Breadcrumbs (click and mutation);
58+
const replayData1 = getReplayRecordingContent(res1);
59+
expect(replayData1.fullSnapshots.length).toBe(0);
5960
expect(replayData1.incrementalSnapshots.length).toBeGreaterThan(0);
61+
expect(replayData1.breadcrumbs.map(({ category }) => category).sort()).toEqual(['replay.mutations', 'ui.click']);
6062

61-
// This does not trigger mutations, for whatever reason - so no full snapshot either!
62-
expect(replayData2.fullSnapshots.length).toBe(0);
63-
expect(replayData2.incrementalSnapshots.length).toBeGreaterThan(0);
64-
65-
// This includes both a full snapshot as well as some incremental snapshots
66-
expect(replayData3.fullSnapshots.length).toBe(1);
67-
expect(replayData3.incrementalSnapshots.length).toBeGreaterThan(0);
63+
replay = await getReplaySnapshot(page);
64+
expect(replay.session).toBe(undefined);
65+
expect(replay._isEnabled).toBe(false);
6866
},
6967
);

packages/browser-integration-tests/suites/replay/sessionExpiry/test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ import {
1414
// Session should expire after 2s - keep in sync with init.js
1515
const SESSION_TIMEOUT = 2000;
1616

17-
sentryTest('handles an expired session', async ({ getLocalTestPath, page }) => {
18-
if (shouldSkipReplayTest()) {
17+
sentryTest('handles an expired session', async ({ browserName, getLocalTestPath, page }) => {
18+
// This test seems to only be flakey on firefox
19+
if (shouldSkipReplayTest() || ['firefox'].includes(browserName)) {
1920
sentryTest.skip();
2021
}
2122

packages/browser-integration-tests/suites/replay/slowClick/mutation/test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ sentryTest('mutation after threshold results in slow click', async ({ getLocalTe
6363
expect(slowClickBreadcrumbs[0]?.data?.timeAfterClickMs).toBeLessThan(2000);
6464
});
6565

66-
sentryTest('immediate mutation does not trigger slow click', async ({ getLocalTestUrl, page }) => {
67-
if (shouldSkipReplayTest()) {
66+
sentryTest('immediate mutation does not trigger slow click', async ({ browserName, getLocalTestUrl, page }) => {
67+
// This test seems to only be flakey on firefox
68+
if (shouldSkipReplayTest() || ['firefox'].includes(browserName)) {
6869
sentryTest.skip();
6970
}
7071

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
window.Replay = new Sentry.Replay({
5+
flushMinDelay: 5000,
6+
flushMaxDelay: 5000,
7+
useCompression: false,
8+
});
9+
10+
Sentry.init({
11+
dsn: 'https://[email protected]/1337',
12+
sampleRate: 0,
13+
replaysSessionSampleRate: 1.0,
14+
replaysOnErrorSampleRate: 0.0,
15+
16+
integrations: [window.Replay],
17+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const COUNT = 400;
2+
3+
document.querySelector('[data-console]').addEventListener('click', () => {
4+
// Call console.log() many times
5+
for (let i = 0; i < COUNT; i++) {
6+
console.log(`testing ${i}`);
7+
}
8+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
</head>
6+
<body>
7+
<button data-console>Trigger console.log</button>
8+
</body>
9+
</html>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { expect } from '@playwright/test';
2+
3+
import { sentryTest } from '../../../utils/fixtures';
4+
import { getCustomRecordingEvents, shouldSkipReplayTest, waitForReplayRequest } from '../../../utils/replayHelpers';
5+
6+
const THROTTLE_LIMIT = 300;
7+
8+
sentryTest(
9+
'throttles breadcrumbs when many `console.log` are made at the same time',
10+
async ({ getLocalTestUrl, page, forceFlushReplay, browserName }) => {
11+
if (shouldSkipReplayTest() || browserName !== 'chromium') {
12+
sentryTest.skip();
13+
}
14+
15+
const reqPromise0 = waitForReplayRequest(page, 0);
16+
const reqPromise1 = waitForReplayRequest(page, 1);
17+
18+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
19+
return route.fulfill({
20+
status: 200,
21+
contentType: 'application/json',
22+
body: JSON.stringify({ id: 'test-id' }),
23+
});
24+
});
25+
26+
const url = await getLocalTestUrl({ testDir: __dirname });
27+
28+
await page.goto(url);
29+
await reqPromise0;
30+
31+
await page.click('[data-console]');
32+
await forceFlushReplay();
33+
34+
const { breadcrumbs } = getCustomRecordingEvents(await reqPromise1);
35+
36+
// 1 click breadcrumb + 1 throttled breadcrumb is why console logs are less
37+
// than throttle limit
38+
expect(breadcrumbs.length).toBe(THROTTLE_LIMIT);
39+
expect(breadcrumbs.filter(breadcrumb => breadcrumb.category === 'replay.throttled').length).toBe(1);
40+
},
41+
);

packages/browser-integration-tests/utils/replayHelpers.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,25 @@ export type IncrementalRecordingSnapshot = eventWithTime & {
3434

3535
export type RecordingSnapshot = FullRecordingSnapshot | IncrementalRecordingSnapshot;
3636

37+
/** Returns the replay event from the given request, or undefined if this is not a replay request. */
38+
export function getReplayEventFromRequest(req: Request): ReplayEvent | undefined {
39+
const postData = req.postData();
40+
if (!postData) {
41+
return undefined;
42+
}
43+
44+
try {
45+
const event = envelopeRequestParser(req);
46+
47+
if (!isReplayEvent(event)) {
48+
return undefined;
49+
}
50+
51+
return event;
52+
} catch {
53+
return undefined;
54+
}
55+
}
3756
/**
3857
* Waits for a replay request to be sent by the page and returns it.
3958
*
@@ -58,18 +77,13 @@ export function waitForReplayRequest(
5877
res => {
5978
const req = res.request();
6079

61-
const postData = req.postData();
62-
if (!postData) {
80+
const event = getReplayEventFromRequest(req);
81+
82+
if (!event) {
6383
return false;
6484
}
6585

6686
try {
67-
const event = envelopeRequestParser(req);
68-
69-
if (!isReplayEvent(event)) {
70-
return false;
71-
}
72-
7387
if (callback) {
7488
return callback(event, res);
7589
}

packages/core/src/integrations/inboundfilters.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,25 @@ import { getEventDescription, logger, stringMatchesSomePattern } from '@sentry/u
55
// this is the result of a script being pulled in from an external domain and CORS.
66
const DEFAULT_IGNORE_ERRORS = [/^Script error\.?$/, /^Javascript error: Script error\.? on line 0$/];
77

8+
const DEFAULT_IGNORE_TRANSACTIONS = [
9+
/^.*healthcheck.*$/,
10+
/^.*healthy.*$/,
11+
/^.*live.*$/,
12+
/^.*ready.*$/,
13+
/^.*heartbeat.*$/,
14+
/^.*\/health$/,
15+
/^.*\/healthz$/,
16+
];
17+
818
/** Options for the InboundFilters integration */
919
export interface InboundFiltersOptions {
1020
allowUrls: Array<string | RegExp>;
1121
denyUrls: Array<string | RegExp>;
1222
ignoreErrors: Array<string | RegExp>;
1323
ignoreTransactions: Array<string | RegExp>;
1424
ignoreInternal: boolean;
25+
disableErrorDefaults: boolean;
26+
disableTransactionDefaults: boolean;
1527
}
1628

1729
/** Inbound filters configurable by the user */
@@ -62,9 +74,13 @@ export function _mergeOptions(
6274
ignoreErrors: [
6375
...(internalOptions.ignoreErrors || []),
6476
...(clientOptions.ignoreErrors || []),
65-
...DEFAULT_IGNORE_ERRORS,
77+
...(internalOptions.disableErrorDefaults ? [] : DEFAULT_IGNORE_ERRORS),
78+
],
79+
ignoreTransactions: [
80+
...(internalOptions.ignoreTransactions || []),
81+
...(clientOptions.ignoreTransactions || []),
82+
...(internalOptions.disableTransactionDefaults ? [] : DEFAULT_IGNORE_TRANSACTIONS),
6683
],
67-
ignoreTransactions: [...(internalOptions.ignoreTransactions || []), ...(clientOptions.ignoreTransactions || [])],
6884
ignoreInternal: internalOptions.ignoreInternal !== undefined ? internalOptions.ignoreInternal : true,
6985
};
7086
}

0 commit comments

Comments
 (0)