Skip to content

Commit 9652757

Browse files
author
Luca Forstner
authored
Merge pull request #8118 from getsentry/prepare-release/7.52.0
2 parents b624bff + 6d067dd commit 9652757

File tree

43 files changed

+995
-144
lines changed

Some content is hidden

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

43 files changed

+995
-144
lines changed

CHANGELOG.md

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

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

7+
8+
## 7.52.0
9+
10+
### Important Next.js SDK changes:
11+
12+
This release adds support Vercel Cron Jobs in the Next.js SDK.
13+
The SDK will automatically create [Sentry Cron Monitors](https://docs.sentry.io/product/crons/) for your [Vercel Cron Jobs](https://vercel.com/docs/cron-jobs) configured via `vercel.json` when deployed on Vercel.
14+
15+
You can opt out of this functionality by setting the `automaticVercelMonitors` option to `false`:
16+
17+
```js
18+
// next.config.js
19+
const nextConfig = {
20+
sentry: {
21+
automaticVercelMonitors: false,
22+
},
23+
};
24+
```
25+
26+
(Note: Sentry Cron Monitoring is currently in beta and subject to change. Help us make it better by letting us know what you think. Respond on [GitHub](https://github.com/getsentry/sentry/discussions/42283) or write to us at crons-feedback@sentry.io)
27+
28+
- feat(nextjs): Add API method to wrap API routes with crons instrumentation (#8084)
29+
- feat(nextjs): Add automatic monitors for Vercel Cron Jobs (#8088)
30+
31+
### Other changes
32+
33+
- feat(replay): Capture keyboard presses for special characters (#8051)
34+
- fix(build): Don't mangle away global debug ID map (#8096)
35+
- fix(core): Return checkin id from client (#8116)
36+
- fix(core): Use last error for `ignoreErrors` check (#8089)
37+
- fix(docs): Change to `addTracingExtensions` was not documented in MIGRATION.md (#8101)
38+
- fix(replay): Check relative URLs correctly (#8024)
39+
- fix(tracing-internal): Avoid classifying protocol-relative URLs as same-origin urls (#8114)
40+
- ref: Hoist `createCheckinEnvelope` to core package (#8082)
41+
742
## 7.51.2
843

944
- fix(nextjs): Continue traces in data fetchers when there is an already active transaction on the hub (#8073)

MIGRATION.md

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

55
The `timestampWithMs` util is deprecated in favor of using `timestampInSeconds`.
66

7+
## `addTracingExtensions` replaces `addExtensionMethods` (since 7.46.0)
8+
9+
Since the deprecation of `@sentry/tracing`, tracing extensions are now added by calling `addTracingExtensions` which is
10+
exported from all framework SDKs.
11+
12+
```js
13+
// Before
14+
import * as Sentry from "@sentry/browser";
15+
import { addExtensionMethods } from "@sentry/tracing";
16+
17+
Sentry.init({
18+
dsn: '__DSN__',
19+
tracesSampleRate: 1.0,
20+
});
21+
22+
addExtensionMethods()
23+
24+
// After
25+
import * as Sentry from "@sentry/browser";
26+
27+
Sentry.init({
28+
dsn: '__DSN__',
29+
tracesSampleRate: 1.0,
30+
});
31+
32+
Sentry.addTracingExtensions();
33+
```
34+
735
## Remove requirement for `@sentry/tracing` package (since 7.46.0)
836

937
With `7.46.0` you no longer require the `@sentry/tracing` package to use tracing and performance monitoring with the Sentry JavaScript SDKs. The `@sentry/tracing` package will be removed in a future major release, but can still be used in the meantime.

packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureRequestBody/init.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ window.Replay = new Sentry.Replay({
55
flushMinDelay: 200,
66
flushMaxDelay: 200,
77

8-
networkDetailAllowUrls: ['http://localhost:7654/foo'],
8+
networkDetailAllowUrls: ['http://localhost:7654/foo', 'http://sentry-test.io/foo'],
99
networkCaptureBodies: true,
1010
});
1111

packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureRequestBody/test.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,85 @@ sentryTest('captures non-text request body', async ({ getLocalTestPath, page, br
249249
]);
250250
});
251251

252+
sentryTest('captures text request body when matching relative URL', async ({ getLocalTestUrl, page, browserName }) => {
253+
if (shouldSkipReplayTest()) {
254+
sentryTest.skip();
255+
}
256+
257+
const additionalHeaders = browserName === 'webkit' ? { 'content-type': 'text/plain' } : undefined;
258+
259+
await page.route('**/foo', route => {
260+
return route.fulfill({
261+
status: 200,
262+
});
263+
});
264+
265+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
266+
return route.fulfill({
267+
status: 200,
268+
contentType: 'application/json',
269+
body: JSON.stringify({ id: 'test-id' }),
270+
});
271+
});
272+
273+
const requestPromise = waitForErrorRequest(page);
274+
const replayRequestPromise1 = waitForReplayRequest(page, 0);
275+
276+
const url = await getLocalTestUrl({ testDir: __dirname });
277+
await page.goto(url);
278+
279+
await page.evaluate(() => {
280+
/* eslint-disable */
281+
fetch('/foo', {
282+
method: 'POST',
283+
body: 'input body',
284+
}).then(() => {
285+
// @ts-ignore Sentry is a global
286+
Sentry.captureException('test error');
287+
});
288+
/* eslint-enable */
289+
});
290+
291+
const request = await requestPromise;
292+
const eventData = envelopeRequestParser(request);
293+
294+
expect(eventData.exception?.values).toHaveLength(1);
295+
296+
expect(eventData?.breadcrumbs?.length).toBe(1);
297+
expect(eventData!.breadcrumbs![0]).toEqual({
298+
timestamp: expect.any(Number),
299+
category: 'fetch',
300+
type: 'http',
301+
data: {
302+
method: 'POST',
303+
request_body_size: 10,
304+
status_code: 200,
305+
url: '/foo',
306+
},
307+
});
308+
309+
const replayReq1 = await replayRequestPromise1;
310+
const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1);
311+
expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([
312+
{
313+
data: {
314+
method: 'POST',
315+
statusCode: 200,
316+
request: {
317+
size: 10,
318+
headers: {},
319+
body: 'input body',
320+
},
321+
response: additionalHeaders ? { headers: additionalHeaders } : undefined,
322+
},
323+
description: '/foo',
324+
endTimestamp: expect.any(Number),
325+
op: 'resource.fetch',
326+
startTimestamp: expect.any(Number),
327+
},
328+
]);
329+
});
330+
252331
sentryTest('does not capture request body when URL does not match', async ({ getLocalTestPath, page }) => {
253332
if (shouldSkipReplayTest()) {
254333
sentryTest.skip();

packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureRequestBody/init.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ window.Replay = new Sentry.Replay({
55
flushMinDelay: 200,
66
flushMaxDelay: 200,
77

8-
networkDetailAllowUrls: ['http://localhost:7654/foo'],
8+
networkDetailAllowUrls: ['http://localhost:7654/foo', 'http://sentry-test.io/foo'],
99
networkCaptureBodies: true,
1010
});
1111

packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureRequestBody/test.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,87 @@ sentryTest('captures non-text request body', async ({ getLocalTestPath, page, br
255255
]);
256256
});
257257

258+
sentryTest('captures text request body when matching relative URL', async ({ getLocalTestUrl, page, browserName }) => {
259+
// These are a bit flaky on non-chromium browsers
260+
if (shouldSkipReplayTest() || browserName !== 'chromium') {
261+
sentryTest.skip();
262+
}
263+
264+
await page.route('**/foo', route => {
265+
return route.fulfill({
266+
status: 200,
267+
});
268+
});
269+
270+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
271+
return route.fulfill({
272+
status: 200,
273+
contentType: 'application/json',
274+
body: JSON.stringify({ id: 'test-id' }),
275+
});
276+
});
277+
278+
const requestPromise = waitForErrorRequest(page);
279+
const replayRequestPromise1 = waitForReplayRequest(page, 0);
280+
281+
const url = await getLocalTestUrl({ testDir: __dirname });
282+
await page.goto(url);
283+
284+
void page.evaluate(() => {
285+
/* eslint-disable */
286+
const xhr = new XMLHttpRequest();
287+
288+
xhr.open('POST', '/foo');
289+
xhr.send('input body');
290+
291+
xhr.addEventListener('readystatechange', function () {
292+
if (xhr.readyState === 4) {
293+
// @ts-ignore Sentry is a global
294+
setTimeout(() => Sentry.captureException('test error', 0));
295+
}
296+
});
297+
/* eslint-enable */
298+
});
299+
300+
const request = await requestPromise;
301+
const eventData = envelopeRequestParser(request);
302+
303+
expect(eventData.exception?.values).toHaveLength(1);
304+
305+
expect(eventData?.breadcrumbs?.length).toBe(1);
306+
expect(eventData!.breadcrumbs![0]).toEqual({
307+
timestamp: expect.any(Number),
308+
category: 'xhr',
309+
type: 'http',
310+
data: {
311+
method: 'POST',
312+
request_body_size: 10,
313+
status_code: 200,
314+
url: '/foo',
315+
},
316+
});
317+
318+
const replayReq1 = await replayRequestPromise1;
319+
const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1);
320+
expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([
321+
{
322+
data: {
323+
method: 'POST',
324+
statusCode: 200,
325+
request: {
326+
size: 10,
327+
headers: {},
328+
body: 'input body',
329+
},
330+
},
331+
description: '/foo',
332+
endTimestamp: expect.any(Number),
333+
op: 'resource.xhr',
334+
startTimestamp: expect.any(Number),
335+
},
336+
]);
337+
});
338+
258339
sentryTest('does not capture request body when URL does not match', async ({ getLocalTestPath, page, browserName }) => {
259340
// These are a bit flaky on non-chromium browsers
260341
if (shouldSkipReplayTest() || browserName !== 'chromium') {
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+
window.Replay = new Sentry.Replay({
5+
flushMinDelay: 1000,
6+
flushMaxDelay: 1000,
7+
});
8+
9+
Sentry.init({
10+
dsn: 'https://public@dsn.ingest.sentry.io/1337',
11+
sampleRate: 0,
12+
replaysSessionSampleRate: 1.0,
13+
replaysOnErrorSampleRate: 0.0,
14+
15+
integrations: [window.Replay],
16+
});
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+
<input id="input" />
8+
</body>
9+
</html>

0 commit comments

Comments
 (0)