Skip to content

Commit

Permalink
Merge pull request #8941 from getsentry/prepare-release/7.67.0
Browse files Browse the repository at this point in the history
meta: Update CHANGELOG for 7.67.0
  • Loading branch information
Lms24 committed Sep 5, 2023
2 parents 9f190f8 + 09f7f7e commit a74fe81
Show file tree
Hide file tree
Showing 144 changed files with 1,954 additions and 803 deletions.
37 changes: 37 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,43 @@

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

## 7.67.0

### Important Changes

- **feat: Mark errors caught by the SDK as unhandled**
- feat(browser): Mark errors caught from `TryCatch` integration as unhandled (#8890)
- feat(integrations): Mark errors caught from `HttpClient` and `CaptureConsole` integrations as unhandled (#8891)
- feat(nextjs): Mark errors caught from NextJS wrappers as unhandled (#8893)
- feat(react): Mark errors captured from ErrorBoundary as unhandled (#8914)
- feat(remix): Add debugid injection and map deletion to sourcemaps script (#8814)
- feat(remix): Mark errors caught from Remix instrumentation as unhandled (#8894)
- feat(serverless): Mark errors caught in Serverless handlers as unhandled (#8907)
- feat(vue): Mark errors caught by Vue wrappers as unhandled (#8905)

This release fixes inconsistent behaviour of when our SDKs classify captured errors as unhandled.
Previously, some of our instrumentations correctly set unhandled, while others set handled.
Going forward, all errors caught automatically from our SDKs will be marked as unhandled.
If you manually capture errors (e.g. by calling `Sentry.captureException`), your errors will continue to be reported as handled.

This change might lead to a decrease in reported crash-free sessions and consequently in your release health score.
If you have concerns about this, feel free to open an issue.

### Other Changes

- feat(node-experimental): Implement new performance APIs (#8911)
- feat(node-experimental): Sync OTEL context with Sentry AsyncContext (#8797)
- feat(replay): Allow to configure `maxReplayDuration` (#8769)
- fix(browser): Add replay and profiling options to `BrowserClientOptions` (#8921)
- fix(browser): Check for existence of instrumentation targets (#8939)
- fix(nextjs): Don't re-export default in route handlers (#8924)
- fix(node): Improve mysql integration (#8923)
- fix(remix): Guard against missing default export for server instrument (#8909)
- ref(browser): Deprecate top-level `wrap` function (#8927)
- ref(node-otel): Avoid exporting internals & refactor attribute adding (#8920)

Work in this release contributed by @SorsOps. Thank you for your contribution!

## 7.66.0

- fix: Defer tracing decision to downstream SDKs when using SDK without performance (#8839)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ sentryTest(
value: 'HTTP Client Error with status code: 500',
mechanism: {
type: 'http.client',
handled: true,
handled: false,
},
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ sentryTest(
value: 'HTTP Client Error with status code: 500',
mechanism: {
type: 'http.client',
handled: true,
handled: false,
},
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ sentryTest('works with a Request passed in', async ({ getLocalTestPath, page })
value: 'HTTP Client Error with status code: 500',
mechanism: {
type: 'http.client',
handled: true,
handled: false,
},
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ sentryTest(
value: 'HTTP Client Error with status code: 500',
mechanism: {
type: 'http.client',
handled: true,
handled: false,
},
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ sentryTest('works with a Request (without body) & options passed in', async ({ g
value: 'HTTP Client Error with status code: 500',
mechanism: {
type: 'http.client',
handled: true,
handled: false,
},
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ sentryTest(
value: 'HTTP Client Error with status code: 500',
mechanism: {
type: 'http.client',
handled: true,
handled: false,
},
},
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as Sentry from '@sentry/browser';

window.Sentry = Sentry;

Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
debug: true,
});
41 changes: 41 additions & 0 deletions packages/browser-integration-tests/suites/public-api/debug/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* eslint-disable no-console */
import type { ConsoleMessage } from '@playwright/test';
import { expect } from '@playwright/test';

import { sentryTest } from '../../../utils/fixtures';

sentryTest('logs debug messages correctly', async ({ getLocalTestUrl, page }) => {
const bundleKey = process.env.PW_BUNDLE || '';
const hasDebug = !bundleKey.includes('_min');

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

const consoleMessages: string[] = [];

page.on('console', (msg: ConsoleMessage) => {
consoleMessages.push(msg.text());
});

await page.goto(url);

await page.evaluate(() => console.log('test log'));

expect(consoleMessages).toEqual(
hasDebug
? [
'Sentry Logger [log]: Integration installed: InboundFilters',
'Sentry Logger [log]: Integration installed: FunctionToString',
'Sentry Logger [log]: Integration installed: TryCatch',
'Sentry Logger [log]: Integration installed: Breadcrumbs',
'Sentry Logger [log]: Global Handler attached: onerror',
'Sentry Logger [log]: Global Handler attached: onunhandledrejection',
'Sentry Logger [log]: Integration installed: GlobalHandlers',
'Sentry Logger [log]: Integration installed: LinkedErrors',
'Sentry Logger [log]: Integration installed: Dedupe',
'Sentry Logger [log]: Integration installed: HttpContext',
'Sentry Logger [warn]: Discarded session because of missing or non-string release',
'test log',
]
: ['[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.', 'test log'],
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ sentryTest(
value: 'event_listener_error',
mechanism: {
type: 'instrument',
handled: true,
handled: false,
},
stacktrace: {
frames: expect.any(Array),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,4 @@ Sentry.init({
return event;
},
integrations: [window.Replay],
debug: true,
});
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ Sentry.init({
sampleRate: 0,
replaysSessionSampleRate: 1.0,
replaysOnErrorSampleRate: 0.0,
debug: true,

integrations: [window.Replay],
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ window.Replay = new Sentry.Replay({
flushMinDelay: 200,
flushMaxDelay: 200,
minReplayDuration: 0,
maxReplayDuration: 2000,
});

Sentry.init({
Expand All @@ -19,5 +20,4 @@ Sentry.init({
window.Replay._replay.timeouts = {
sessionIdlePause: 1000, // this is usually 5min, but we want to test this with shorter times
sessionIdleExpire: 2000, // this is usually 15min, but we want to test this with shorter times
maxSessionLife: 2000, // default: 60min
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { sentryTest } from '../../../utils/fixtures';
import { getExpectedReplayEvent } from '../../../utils/replayEventTemplates';
import { getReplayEvent, shouldSkipReplayTest, waitForReplayRequest } from '../../../utils/replayHelpers';

const SESSION_MAX_AGE = 2000;
const MAX_REPLAY_DURATION = 2000;

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

await page.goto(url);

await new Promise(resolve => setTimeout(resolve, SESSION_MAX_AGE / 2));
await new Promise(resolve => setTimeout(resolve, MAX_REPLAY_DURATION / 2));

await page.reload();
await page.click('#button1');

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

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

void page.click('#button1');
await page.evaluate(`Object.defineProperty(document, 'visibilityState', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ Sentry.init({
sampleRate: 0,
replaysSessionSampleRate: 1.0,
replaysOnErrorSampleRate: 0.0,
debug: true,

integrations: [window.Replay],
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@ Sentry.init({
sampleRate: 0,
replaysSessionSampleRate: 1.0,
replaysOnErrorSampleRate: 0.0,
debug: true,

integrations: [window.Replay],
});

window.Replay._replay.timeouts = {
sessionIdlePause: 1000, // this is usually 5min, but we want to test this with shorter times
sessionIdleExpire: 2000, // this is usually 15min, but we want to test this with shorter times
maxSessionLife: 3600000, // default: 60min
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@ Sentry.init({
sampleRate: 0,
replaysSessionSampleRate: 1.0,
replaysOnErrorSampleRate: 0.0,
debug: true,

integrations: [window.Replay],
});

window.Replay._replay.timeouts = {
sessionIdlePause: 1000, // this is usually 5min, but we want to test this with shorter times
sessionIdleExpire: 900000, // defayult: 15min
maxSessionLife: 3600000, // default: 60min
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,19 @@ window.Replay = new Sentry.Replay({
flushMinDelay: 200,
flushMaxDelay: 200,
minReplayDuration: 0,
maxReplayDuration: 4000,
});

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

integrations: [window.Replay],
});

window.Replay._replay.timeouts = {
sessionIdlePause: 300000, // default: 5min
sessionIdleExpire: 900000, // default: 15min
maxSessionLife: 4000, // this is usually 60min, but we want to test this with shorter times
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from '../../../utils/replayHelpers';

// Session should be max. 4s long
const SESSION_MAX_AGE = 4000;
const MAX_REPLAY_DURATION = 4000;

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

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

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

const req2 = await reqPromise2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ sentryTest('should update session when an error is thrown.', async ({ getLocalTe
expect(updatedSession).toBeDefined();
expect(updatedSession.init).toBe(false);
expect(updatedSession.errors).toBe(1);
expect(updatedSession.status).toBe('ok');
expect(updatedSession.status).toBe('crashed');
expect(pageloadSession.sid).toBe(updatedSession.sid);
});

Expand Down
8 changes: 4 additions & 4 deletions packages/browser-integration-tests/utils/replayHelpers.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { fullSnapshotEvent, incrementalSnapshotEvent } from '@sentry-internal/rrweb';
import { EventType } from '@sentry-internal/rrweb';
import type { ReplayEventWithTime } from '@sentry/browser';
import type {
InternalEventContext,
RecordingEvent,
ReplayContainer,
Session,
} from '@sentry/replay/build/npm/types/types';
import type { eventWithTime } from '@sentry/replay/build/npm/types/types/rrweb';
import type { Breadcrumb, Event, ReplayEvent, ReplayRecordingMode } from '@sentry/types';
import pako from 'pako';
import type { Page, Request, Response } from 'playwright';
Expand All @@ -22,12 +22,12 @@ export type PerformanceSpan = {
data: Record<string, number>;
};

export type FullRecordingSnapshot = eventWithTime & {
export type FullRecordingSnapshot = ReplayEventWithTime & {
timestamp: 0;
data: fullSnapshotEvent['data'];
};

export type IncrementalRecordingSnapshot = eventWithTime & {
export type IncrementalRecordingSnapshot = ReplayEventWithTime & {
timestamp: 0;
data: incrementalSnapshotEvent['data'];
};
Expand Down Expand Up @@ -270,7 +270,7 @@ function getOptionsEvents(replayRequest: Request): CustomRecordingEvent[] {
export function getDecompressedRecordingEvents(resOrReq: Request | Response): RecordingSnapshot[] {
const replayRequest = getRequest(resOrReq);
return (
(replayEnvelopeRequestParser(replayRequest, 5) as eventWithTime[])
(replayEnvelopeRequestParser(replayRequest, 5) as ReplayEventWithTime[])
.sort((a, b) => a.timestamp - b.timestamp)
// source 1 is MouseMove, which is a bit flaky and we don't care about
.filter(
Expand Down
4 changes: 3 additions & 1 deletion packages/browser/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ export type BrowserOptions = Options<BrowserTransportOptions> &
* Configuration options for the Sentry Browser SDK Client class
* @see BrowserClient for more information.
*/
export type BrowserClientOptions = ClientOptions<BrowserTransportOptions>;
export type BrowserClientOptions = ClientOptions<BrowserTransportOptions> &
BrowserClientReplayOptions &
BrowserClientProfilingOptions;

/**
* The Sentry Browser SDK Client.
Expand Down
11 changes: 10 additions & 1 deletion packages/browser/src/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,14 @@ export {
} from './stack-parsers';
export { eventFromException, eventFromMessage, exceptionFromError } from './eventbuilder';
export { createUserFeedbackEnvelope } from './userfeedback';
export { defaultIntegrations, forceLoad, init, onLoad, showReportDialog, wrap, captureUserFeedback } from './sdk';
export {
defaultIntegrations,
forceLoad,
init,
onLoad,
showReportDialog,
captureUserFeedback,
// eslint-disable-next-line deprecation/deprecation
wrap,
} from './sdk';
export { GlobalHandlers, TryCatch, Breadcrumbs, LinkedErrors, HttpContext, Dedupe } from './integrations';
12 changes: 12 additions & 0 deletions packages/browser/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ const INTEGRATIONS = {
export { INTEGRATIONS as Integrations };

export { Replay } from '@sentry/replay';
export type {
ReplayEventType,
ReplayEventWithTime,
ReplayBreadcrumbFrame,
ReplayBreadcrumbFrameEvent,
ReplayOptionFrameEvent,
ReplayFrame,
ReplayFrameEvent,
ReplaySpanFrame,
ReplaySpanFrameEvent,
} from '@sentry/replay';

export {
BrowserTracing,
defaultRequestInstrumentationOptions,
Expand Down
Loading

0 comments on commit a74fe81

Please sign in to comment.