Skip to content

Commit

Permalink
Merge pull request #8118 from getsentry/prepare-release/7.52.0
Browse files Browse the repository at this point in the history
  • Loading branch information
lforst committed May 15, 2023
2 parents b624bff + 6d067dd commit 9652757
Show file tree
Hide file tree
Showing 43 changed files with 995 additions and 144 deletions.
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,41 @@

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


## 7.52.0

### Important Next.js SDK changes:

This release adds support Vercel Cron Jobs in the Next.js SDK.
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.

You can opt out of this functionality by setting the `automaticVercelMonitors` option to `false`:

```js
// next.config.js
const nextConfig = {
sentry: {
automaticVercelMonitors: false,
},
};
```

(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)

- feat(nextjs): Add API method to wrap API routes with crons instrumentation (#8084)
- feat(nextjs): Add automatic monitors for Vercel Cron Jobs (#8088)

### Other changes

- feat(replay): Capture keyboard presses for special characters (#8051)
- fix(build): Don't mangle away global debug ID map (#8096)
- fix(core): Return checkin id from client (#8116)
- fix(core): Use last error for `ignoreErrors` check (#8089)
- fix(docs): Change to `addTracingExtensions` was not documented in MIGRATION.md (#8101)
- fix(replay): Check relative URLs correctly (#8024)
- fix(tracing-internal): Avoid classifying protocol-relative URLs as same-origin urls (#8114)
- ref: Hoist `createCheckinEnvelope` to core package (#8082)

## 7.51.2

- fix(nextjs): Continue traces in data fetchers when there is an already active transaction on the hub (#8073)
Expand Down
28 changes: 28 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,34 @@

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

## `addTracingExtensions` replaces `addExtensionMethods` (since 7.46.0)

Since the deprecation of `@sentry/tracing`, tracing extensions are now added by calling `addTracingExtensions` which is
exported from all framework SDKs.

```js
// Before
import * as Sentry from "@sentry/browser";
import { addExtensionMethods } from "@sentry/tracing";

Sentry.init({
dsn: '__DSN__',
tracesSampleRate: 1.0,
});

addExtensionMethods()

// After
import * as Sentry from "@sentry/browser";

Sentry.init({
dsn: '__DSN__',
tracesSampleRate: 1.0,
});

Sentry.addTracingExtensions();
```

## Remove requirement for `@sentry/tracing` package (since 7.46.0)

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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ window.Replay = new Sentry.Replay({
flushMinDelay: 200,
flushMaxDelay: 200,

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,85 @@ sentryTest('captures non-text request body', async ({ getLocalTestPath, page, br
]);
});

sentryTest('captures text request body when matching relative URL', async ({ getLocalTestUrl, page, browserName }) => {
if (shouldSkipReplayTest()) {
sentryTest.skip();
}

const additionalHeaders = browserName === 'webkit' ? { 'content-type': 'text/plain' } : undefined;

await page.route('**/foo', route => {
return route.fulfill({
status: 200,
});
});

await page.route('https://dsn.ingest.sentry.io/**/*', route => {
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ id: 'test-id' }),
});
});

const requestPromise = waitForErrorRequest(page);
const replayRequestPromise1 = waitForReplayRequest(page, 0);

const url = await getLocalTestUrl({ testDir: __dirname });
await page.goto(url);

await page.evaluate(() => {
/* eslint-disable */
fetch('/foo', {
method: 'POST',
body: 'input body',
}).then(() => {
// @ts-ignore Sentry is a global
Sentry.captureException('test error');
});
/* eslint-enable */
});

const request = await requestPromise;
const eventData = envelopeRequestParser(request);

expect(eventData.exception?.values).toHaveLength(1);

expect(eventData?.breadcrumbs?.length).toBe(1);
expect(eventData!.breadcrumbs![0]).toEqual({
timestamp: expect.any(Number),
category: 'fetch',
type: 'http',
data: {
method: 'POST',
request_body_size: 10,
status_code: 200,
url: '/foo',
},
});

const replayReq1 = await replayRequestPromise1;
const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1);
expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([
{
data: {
method: 'POST',
statusCode: 200,
request: {
size: 10,
headers: {},
body: 'input body',
},
response: additionalHeaders ? { headers: additionalHeaders } : undefined,
},
description: '/foo',
endTimestamp: expect.any(Number),
op: 'resource.fetch',
startTimestamp: expect.any(Number),
},
]);
});

sentryTest('does not capture request body when URL does not match', async ({ getLocalTestPath, page }) => {
if (shouldSkipReplayTest()) {
sentryTest.skip();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ window.Replay = new Sentry.Replay({
flushMinDelay: 200,
flushMaxDelay: 200,

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,87 @@ sentryTest('captures non-text request body', async ({ getLocalTestPath, page, br
]);
});

sentryTest('captures text request body when matching relative URL', async ({ getLocalTestUrl, page, browserName }) => {
// These are a bit flaky on non-chromium browsers
if (shouldSkipReplayTest() || browserName !== 'chromium') {
sentryTest.skip();
}

await page.route('**/foo', route => {
return route.fulfill({
status: 200,
});
});

await page.route('https://dsn.ingest.sentry.io/**/*', route => {
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ id: 'test-id' }),
});
});

const requestPromise = waitForErrorRequest(page);
const replayRequestPromise1 = waitForReplayRequest(page, 0);

const url = await getLocalTestUrl({ testDir: __dirname });
await page.goto(url);

void page.evaluate(() => {
/* eslint-disable */
const xhr = new XMLHttpRequest();

xhr.open('POST', '/foo');
xhr.send('input body');

xhr.addEventListener('readystatechange', function () {
if (xhr.readyState === 4) {
// @ts-ignore Sentry is a global
setTimeout(() => Sentry.captureException('test error', 0));
}
});
/* eslint-enable */
});

const request = await requestPromise;
const eventData = envelopeRequestParser(request);

expect(eventData.exception?.values).toHaveLength(1);

expect(eventData?.breadcrumbs?.length).toBe(1);
expect(eventData!.breadcrumbs![0]).toEqual({
timestamp: expect.any(Number),
category: 'xhr',
type: 'http',
data: {
method: 'POST',
request_body_size: 10,
status_code: 200,
url: '/foo',
},
});

const replayReq1 = await replayRequestPromise1;
const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1);
expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([
{
data: {
method: 'POST',
statusCode: 200,
request: {
size: 10,
headers: {},
body: 'input body',
},
},
description: '/foo',
endTimestamp: expect.any(Number),
op: 'resource.xhr',
startTimestamp: expect.any(Number),
},
]);
});

sentryTest('does not capture request body when URL does not match', async ({ getLocalTestPath, page, browserName }) => {
// These are a bit flaky on non-chromium browsers
if (shouldSkipReplayTest() || browserName !== 'chromium') {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as Sentry from '@sentry/browser';

window.Sentry = Sentry;
window.Replay = new Sentry.Replay({
flushMinDelay: 1000,
flushMaxDelay: 1000,
});

Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
sampleRate: 0,
replaysSessionSampleRate: 1.0,
replaysOnErrorSampleRate: 0.0,

integrations: [window.Replay],
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<input id="input" />
</body>
</html>

0 comments on commit 9652757

Please sign in to comment.