Skip to content

Commit a74fe81

Browse files
authored
Merge pull request #8941 from getsentry/prepare-release/7.67.0
meta: Update CHANGELOG for 7.67.0
2 parents 9f190f8 + 09f7f7e commit a74fe81

File tree

144 files changed

+1954
-803
lines changed

Some content is hidden

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

144 files changed

+1954
-803
lines changed

CHANGELOG.md

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

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

7+
## 7.67.0
8+
9+
### Important Changes
10+
11+
- **feat: Mark errors caught by the SDK as unhandled**
12+
- feat(browser): Mark errors caught from `TryCatch` integration as unhandled (#8890)
13+
- feat(integrations): Mark errors caught from `HttpClient` and `CaptureConsole` integrations as unhandled (#8891)
14+
- feat(nextjs): Mark errors caught from NextJS wrappers as unhandled (#8893)
15+
- feat(react): Mark errors captured from ErrorBoundary as unhandled (#8914)
16+
- feat(remix): Add debugid injection and map deletion to sourcemaps script (#8814)
17+
- feat(remix): Mark errors caught from Remix instrumentation as unhandled (#8894)
18+
- feat(serverless): Mark errors caught in Serverless handlers as unhandled (#8907)
19+
- feat(vue): Mark errors caught by Vue wrappers as unhandled (#8905)
20+
21+
This release fixes inconsistent behaviour of when our SDKs classify captured errors as unhandled.
22+
Previously, some of our instrumentations correctly set unhandled, while others set handled.
23+
Going forward, all errors caught automatically from our SDKs will be marked as unhandled.
24+
If you manually capture errors (e.g. by calling `Sentry.captureException`), your errors will continue to be reported as handled.
25+
26+
This change might lead to a decrease in reported crash-free sessions and consequently in your release health score.
27+
If you have concerns about this, feel free to open an issue.
28+
29+
### Other Changes
30+
31+
- feat(node-experimental): Implement new performance APIs (#8911)
32+
- feat(node-experimental): Sync OTEL context with Sentry AsyncContext (#8797)
33+
- feat(replay): Allow to configure `maxReplayDuration` (#8769)
34+
- fix(browser): Add replay and profiling options to `BrowserClientOptions` (#8921)
35+
- fix(browser): Check for existence of instrumentation targets (#8939)
36+
- fix(nextjs): Don't re-export default in route handlers (#8924)
37+
- fix(node): Improve mysql integration (#8923)
38+
- fix(remix): Guard against missing default export for server instrument (#8909)
39+
- ref(browser): Deprecate top-level `wrap` function (#8927)
40+
- ref(node-otel): Avoid exporting internals & refactor attribute adding (#8920)
41+
42+
Work in this release contributed by @SorsOps. Thank you for your contribution!
43+
744
## 7.66.0
845

946
- fix: Defer tracing decision to downstream SDKs when using SDK without performance (#8839)

packages/browser-integration-tests/suites/integrations/httpclient/axios/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ sentryTest(
3838
value: 'HTTP Client Error with status code: 500',
3939
mechanism: {
4040
type: 'http.client',
41-
handled: true,
41+
handled: false,
4242
},
4343
},
4444
],

packages/browser-integration-tests/suites/integrations/httpclient/fetch/simple/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ sentryTest(
3838
value: 'HTTP Client Error with status code: 500',
3939
mechanism: {
4040
type: 'http.client',
41-
handled: true,
41+
handled: false,
4242
},
4343
},
4444
],

packages/browser-integration-tests/suites/integrations/httpclient/fetch/withRequest/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ sentryTest('works with a Request passed in', async ({ getLocalTestPath, page })
3636
value: 'HTTP Client Error with status code: 500',
3737
mechanism: {
3838
type: 'http.client',
39-
handled: true,
39+
handled: false,
4040
},
4141
},
4242
],

packages/browser-integration-tests/suites/integrations/httpclient/fetch/withRequestAndBodyAndOptions/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ sentryTest(
3838
value: 'HTTP Client Error with status code: 500',
3939
mechanism: {
4040
type: 'http.client',
41-
handled: true,
41+
handled: false,
4242
},
4343
},
4444
],

packages/browser-integration-tests/suites/integrations/httpclient/fetch/withRequestAndOptions/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ sentryTest('works with a Request (without body) & options passed in', async ({ g
3636
value: 'HTTP Client Error with status code: 500',
3737
mechanism: {
3838
type: 'http.client',
39-
handled: true,
39+
handled: false,
4040
},
4141
},
4242
],

packages/browser-integration-tests/suites/integrations/httpclient/xhr/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ sentryTest(
3838
value: 'HTTP Client Error with status code: 500',
3939
mechanism: {
4040
type: 'http.client',
41-
handled: true,
41+
handled: false,
4242
},
4343
},
4444
],
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
5+
Sentry.init({
6+
dsn: 'https://[email protected]/1337',
7+
debug: true,
8+
});
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* eslint-disable no-console */
2+
import type { ConsoleMessage } from '@playwright/test';
3+
import { expect } from '@playwright/test';
4+
5+
import { sentryTest } from '../../../utils/fixtures';
6+
7+
sentryTest('logs debug messages correctly', async ({ getLocalTestUrl, page }) => {
8+
const bundleKey = process.env.PW_BUNDLE || '';
9+
const hasDebug = !bundleKey.includes('_min');
10+
11+
const url = await getLocalTestUrl({ testDir: __dirname });
12+
13+
const consoleMessages: string[] = [];
14+
15+
page.on('console', (msg: ConsoleMessage) => {
16+
consoleMessages.push(msg.text());
17+
});
18+
19+
await page.goto(url);
20+
21+
await page.evaluate(() => console.log('test log'));
22+
23+
expect(consoleMessages).toEqual(
24+
hasDebug
25+
? [
26+
'Sentry Logger [log]: Integration installed: InboundFilters',
27+
'Sentry Logger [log]: Integration installed: FunctionToString',
28+
'Sentry Logger [log]: Integration installed: TryCatch',
29+
'Sentry Logger [log]: Integration installed: Breadcrumbs',
30+
'Sentry Logger [log]: Global Handler attached: onerror',
31+
'Sentry Logger [log]: Global Handler attached: onunhandledrejection',
32+
'Sentry Logger [log]: Integration installed: GlobalHandlers',
33+
'Sentry Logger [log]: Integration installed: LinkedErrors',
34+
'Sentry Logger [log]: Integration installed: Dedupe',
35+
'Sentry Logger [log]: Integration installed: HttpContext',
36+
'Sentry Logger [warn]: Discarded session because of missing or non-string release',
37+
'test log',
38+
]
39+
: ['[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.', 'test log'],
40+
);
41+
});

packages/browser-integration-tests/suites/public-api/instrumentation/eventListener/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ sentryTest(
1717
value: 'event_listener_error',
1818
mechanism: {
1919
type: 'instrument',
20-
handled: true,
20+
handled: false,
2121
},
2222
stacktrace: {
2323
frames: expect.any(Array),

packages/browser-integration-tests/suites/replay/errors/errorsInSession/init.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,4 @@ Sentry.init({
1919
return event;
2020
},
2121
integrations: [window.Replay],
22-
debug: true,
2322
});

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ Sentry.init({
1313
sampleRate: 0,
1414
replaysSessionSampleRate: 1.0,
1515
replaysOnErrorSampleRate: 0.0,
16-
debug: true,
1716

1817
integrations: [window.Replay],
1918
});

packages/browser-integration-tests/suites/replay/maxReplayDuration/init.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ window.Replay = new Sentry.Replay({
55
flushMinDelay: 200,
66
flushMaxDelay: 200,
77
minReplayDuration: 0,
8+
maxReplayDuration: 2000,
89
});
910

1011
Sentry.init({
@@ -19,5 +20,4 @@ Sentry.init({
1920
window.Replay._replay.timeouts = {
2021
sessionIdlePause: 1000, // this is usually 5min, but we want to test this with shorter times
2122
sessionIdleExpire: 2000, // this is usually 15min, but we want to test this with shorter times
22-
maxSessionLife: 2000, // default: 60min
2323
};

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { sentryTest } from '../../../utils/fixtures';
44
import { getExpectedReplayEvent } from '../../../utils/replayEventTemplates';
55
import { getReplayEvent, shouldSkipReplayTest, waitForReplayRequest } from '../../../utils/replayHelpers';
66

7-
const SESSION_MAX_AGE = 2000;
7+
const MAX_REPLAY_DURATION = 2000;
88

99
sentryTest('keeps track of max duration across reloads', async ({ getLocalTestPath, page }) => {
1010
if (shouldSkipReplayTest()) {
@@ -26,15 +26,15 @@ sentryTest('keeps track of max duration across reloads', async ({ getLocalTestPa
2626

2727
await page.goto(url);
2828

29-
await new Promise(resolve => setTimeout(resolve, SESSION_MAX_AGE / 2));
29+
await new Promise(resolve => setTimeout(resolve, MAX_REPLAY_DURATION / 2));
3030

3131
await page.reload();
3232
await page.click('#button1');
3333

3434
// After the second reload, we should have a new session (because we exceeded max age)
3535
const reqPromise3 = waitForReplayRequest(page, 0);
3636

37-
await new Promise(resolve => setTimeout(resolve, SESSION_MAX_AGE / 2 + 100));
37+
await new Promise(resolve => setTimeout(resolve, MAX_REPLAY_DURATION / 2 + 100));
3838

3939
void page.click('#button1');
4040
await page.evaluate(`Object.defineProperty(document, 'visibilityState', {

packages/browser-integration-tests/suites/replay/minReplayDuration/init.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ Sentry.init({
1212
sampleRate: 0,
1313
replaysSessionSampleRate: 1.0,
1414
replaysOnErrorSampleRate: 0.0,
15-
debug: true,
1615

1716
integrations: [window.Replay],
1817
});

packages/browser-integration-tests/suites/replay/sessionExpiry/init.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,11 @@ Sentry.init({
1212
sampleRate: 0,
1313
replaysSessionSampleRate: 1.0,
1414
replaysOnErrorSampleRate: 0.0,
15-
debug: true,
1615

1716
integrations: [window.Replay],
1817
});
1918

2019
window.Replay._replay.timeouts = {
2120
sessionIdlePause: 1000, // this is usually 5min, but we want to test this with shorter times
2221
sessionIdleExpire: 2000, // this is usually 15min, but we want to test this with shorter times
23-
maxSessionLife: 3600000, // default: 60min
2422
};

packages/browser-integration-tests/suites/replay/sessionInactive/init.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,11 @@ Sentry.init({
1212
sampleRate: 0,
1313
replaysSessionSampleRate: 1.0,
1414
replaysOnErrorSampleRate: 0.0,
15-
debug: true,
1615

1716
integrations: [window.Replay],
1817
});
1918

2019
window.Replay._replay.timeouts = {
2120
sessionIdlePause: 1000, // this is usually 5min, but we want to test this with shorter times
2221
sessionIdleExpire: 900000, // defayult: 15min
23-
maxSessionLife: 3600000, // default: 60min
2422
};

packages/browser-integration-tests/suites/replay/sessionMaxAge/init.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,19 @@ window.Replay = new Sentry.Replay({
55
flushMinDelay: 200,
66
flushMaxDelay: 200,
77
minReplayDuration: 0,
8+
maxReplayDuration: 4000,
89
});
910

1011
Sentry.init({
1112
dsn: 'https://[email protected]/1337',
1213
sampleRate: 0,
1314
replaysSessionSampleRate: 1.0,
1415
replaysOnErrorSampleRate: 0.0,
15-
debug: true,
1616

1717
integrations: [window.Replay],
1818
});
1919

2020
window.Replay._replay.timeouts = {
2121
sessionIdlePause: 300000, // default: 5min
2222
sessionIdleExpire: 900000, // default: 15min
23-
maxSessionLife: 4000, // this is usually 60min, but we want to test this with shorter times
2423
};

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
} from '../../../utils/replayHelpers';
1313

1414
// Session should be max. 4s long
15-
const SESSION_MAX_AGE = 4000;
15+
const MAX_REPLAY_DURATION = 4000;
1616

1717
/*
1818
The main difference between this and sessionExpiry test, is that here we wait for the overall time (4s)
@@ -58,7 +58,7 @@ sentryTest('handles session that exceeds max age', async ({ getLocalTestPath, pa
5858
// Wait for an incremental snapshot
5959
// Wait half of the session max age (after initial flush), but account for potentially slow runners
6060
const timePassed1 = Date.now() - startTimestamp;
61-
await new Promise(resolve => setTimeout(resolve, Math.max(SESSION_MAX_AGE / 2 - timePassed1, 0)));
61+
await new Promise(resolve => setTimeout(resolve, Math.max(MAX_REPLAY_DURATION / 2 - timePassed1, 0)));
6262
await page.click('#button1');
6363

6464
const req1 = await reqPromise1;
@@ -71,7 +71,7 @@ sentryTest('handles session that exceeds max age', async ({ getLocalTestPath, pa
7171

7272
// Wait for session to expire
7373
const timePassed2 = Date.now() - startTimestamp;
74-
await new Promise(resolve => setTimeout(resolve, Math.max(SESSION_MAX_AGE - timePassed2, 0)));
74+
await new Promise(resolve => setTimeout(resolve, Math.max(MAX_REPLAY_DURATION - timePassed2, 0)));
7575
await page.click('#button2');
7676

7777
const req2 = await reqPromise2;

packages/browser-integration-tests/suites/sessions/update-session/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ sentryTest('should update session when an error is thrown.', async ({ getLocalTe
1717
expect(updatedSession).toBeDefined();
1818
expect(updatedSession.init).toBe(false);
1919
expect(updatedSession.errors).toBe(1);
20-
expect(updatedSession.status).toBe('ok');
20+
expect(updatedSession.status).toBe('crashed');
2121
expect(pageloadSession.sid).toBe(updatedSession.sid);
2222
});
2323

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import type { fullSnapshotEvent, incrementalSnapshotEvent } from '@sentry-internal/rrweb';
22
import { EventType } from '@sentry-internal/rrweb';
3+
import type { ReplayEventWithTime } from '@sentry/browser';
34
import type {
45
InternalEventContext,
56
RecordingEvent,
67
ReplayContainer,
78
Session,
89
} from '@sentry/replay/build/npm/types/types';
9-
import type { eventWithTime } from '@sentry/replay/build/npm/types/types/rrweb';
1010
import type { Breadcrumb, Event, ReplayEvent, ReplayRecordingMode } from '@sentry/types';
1111
import pako from 'pako';
1212
import type { Page, Request, Response } from 'playwright';
@@ -22,12 +22,12 @@ export type PerformanceSpan = {
2222
data: Record<string, number>;
2323
};
2424

25-
export type FullRecordingSnapshot = eventWithTime & {
25+
export type FullRecordingSnapshot = ReplayEventWithTime & {
2626
timestamp: 0;
2727
data: fullSnapshotEvent['data'];
2828
};
2929

30-
export type IncrementalRecordingSnapshot = eventWithTime & {
30+
export type IncrementalRecordingSnapshot = ReplayEventWithTime & {
3131
timestamp: 0;
3232
data: incrementalSnapshotEvent['data'];
3333
};
@@ -270,7 +270,7 @@ function getOptionsEvents(replayRequest: Request): CustomRecordingEvent[] {
270270
export function getDecompressedRecordingEvents(resOrReq: Request | Response): RecordingSnapshot[] {
271271
const replayRequest = getRequest(resOrReq);
272272
return (
273-
(replayEnvelopeRequestParser(replayRequest, 5) as eventWithTime[])
273+
(replayEnvelopeRequestParser(replayRequest, 5) as ReplayEventWithTime[])
274274
.sort((a, b) => a.timestamp - b.timestamp)
275275
// source 1 is MouseMove, which is a bit flaky and we don't care about
276276
.filter(

packages/browser/src/client.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ export type BrowserOptions = Options<BrowserTransportOptions> &
3030
* Configuration options for the Sentry Browser SDK Client class
3131
* @see BrowserClient for more information.
3232
*/
33-
export type BrowserClientOptions = ClientOptions<BrowserTransportOptions>;
33+
export type BrowserClientOptions = ClientOptions<BrowserTransportOptions> &
34+
BrowserClientReplayOptions &
35+
BrowserClientProfilingOptions;
3436

3537
/**
3638
* The Sentry Browser SDK Client.

packages/browser/src/exports.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,14 @@ export {
6363
} from './stack-parsers';
6464
export { eventFromException, eventFromMessage, exceptionFromError } from './eventbuilder';
6565
export { createUserFeedbackEnvelope } from './userfeedback';
66-
export { defaultIntegrations, forceLoad, init, onLoad, showReportDialog, wrap, captureUserFeedback } from './sdk';
66+
export {
67+
defaultIntegrations,
68+
forceLoad,
69+
init,
70+
onLoad,
71+
showReportDialog,
72+
captureUserFeedback,
73+
// eslint-disable-next-line deprecation/deprecation
74+
wrap,
75+
} from './sdk';
6776
export { GlobalHandlers, TryCatch, Breadcrumbs, LinkedErrors, HttpContext, Dedupe } from './integrations';

packages/browser/src/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@ const INTEGRATIONS = {
2121
export { INTEGRATIONS as Integrations };
2222

2323
export { Replay } from '@sentry/replay';
24+
export type {
25+
ReplayEventType,
26+
ReplayEventWithTime,
27+
ReplayBreadcrumbFrame,
28+
ReplayBreadcrumbFrameEvent,
29+
ReplayOptionFrameEvent,
30+
ReplayFrame,
31+
ReplayFrameEvent,
32+
ReplaySpanFrame,
33+
ReplaySpanFrameEvent,
34+
} from '@sentry/replay';
35+
2436
export {
2537
BrowserTracing,
2638
defaultRequestInstrumentationOptions,

0 commit comments

Comments
 (0)