Skip to content

Commit 28884c0

Browse files
authored
Merge branch 'develop' into sig/sveltekit-sourcemaps-enabled
2 parents f896f36 + c347dae commit 28884c0

File tree

47 files changed

+374
-1394
lines changed

Some content is hidden

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

47 files changed

+374
-1394
lines changed

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

+10-7
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ import { expect } from '@playwright/test';
22
import type { SessionContext } from '@sentry/core';
33

44
import { sentryTest } from '../../../utils/fixtures';
5-
import { getFirstSentryEnvelopeRequest } from '../../../utils/helpers';
5+
import { getFirstSentryEnvelopeRequest, waitForSession } from '../../../utils/helpers';
66

77
sentryTest('should update session when an error is thrown.', async ({ getLocalTestUrl, page }) => {
88
const url = await getLocalTestUrl({ testDir: __dirname });
9+
910
const pageloadSession = await getFirstSentryEnvelopeRequest<SessionContext>(page, url);
10-
const updatedSession = (
11-
await Promise.all([page.locator('#throw-error').click(), getFirstSentryEnvelopeRequest<SessionContext>(page)])
12-
)[1];
11+
12+
const updatedSessionPromise = waitForSession(page);
13+
await page.locator('#throw-error').click();
14+
const updatedSession = await updatedSessionPromise;
1315

1416
expect(pageloadSession).toBeDefined();
1517
expect(pageloadSession.init).toBe(true);
@@ -25,9 +27,10 @@ sentryTest('should update session when an exception is captured.', async ({ getL
2527
const url = await getLocalTestUrl({ testDir: __dirname });
2628

2729
const pageloadSession = await getFirstSentryEnvelopeRequest<SessionContext>(page, url);
28-
const updatedSession = (
29-
await Promise.all([page.locator('#capture-exception').click(), getFirstSentryEnvelopeRequest<SessionContext>(page)])
30-
)[1];
30+
31+
const updatedSessionPromise = waitForSession(page);
32+
await page.locator('#capture-exception').click();
33+
const updatedSession = await updatedSessionPromise;
3134

3235
expect(pageloadSession).toBeDefined();
3336
expect(pageloadSession.init).toBe(true);

dev-packages/browser-integration-tests/utils/helpers.ts

+24-6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type {
77
Event,
88
EventEnvelope,
99
EventEnvelopeHeaders,
10+
SessionContext,
1011
TransactionEvent,
1112
} from '@sentry/core';
1213

@@ -157,7 +158,7 @@ export const countEnvelopes = async (
157158
* @param {{ path?: string; content?: string }} impl
158159
* @return {*} {Promise<void>}
159160
*/
160-
async function runScriptInSandbox(
161+
export async function runScriptInSandbox(
161162
page: Page,
162163
impl: {
163164
path?: string;
@@ -178,7 +179,7 @@ async function runScriptInSandbox(
178179
* @param {string} [url]
179180
* @return {*} {Promise<Array<Event>>}
180181
*/
181-
async function getSentryEvents(page: Page, url?: string): Promise<Array<Event>> {
182+
export async function getSentryEvents(page: Page, url?: string): Promise<Array<Event>> {
182183
if (url) {
183184
await page.goto(url);
184185
}
@@ -250,6 +251,25 @@ export function waitForTransactionRequest(
250251
});
251252
}
252253

254+
export async function waitForSession(page: Page): Promise<SessionContext> {
255+
const req = await page.waitForRequest(req => {
256+
const postData = req.postData();
257+
if (!postData) {
258+
return false;
259+
}
260+
261+
try {
262+
const event = envelopeRequestParser<SessionContext>(req);
263+
264+
return typeof event.init === 'boolean' && event.started !== undefined;
265+
} catch {
266+
return false;
267+
}
268+
});
269+
270+
return envelopeRequestParser<SessionContext>(req);
271+
}
272+
253273
/**
254274
* We can only test tracing tests in certain bundles/packages:
255275
* - NPM (ESM, CJS)
@@ -353,7 +373,7 @@ async function getMultipleRequests<T>(
353373
/**
354374
* Wait and get multiple envelope requests at the given URL, or the current page
355375
*/
356-
async function getMultipleSentryEnvelopeRequests<T>(
376+
export async function getMultipleSentryEnvelopeRequests<T>(
357377
page: Page,
358378
count: number,
359379
options?: {
@@ -374,7 +394,7 @@ async function getMultipleSentryEnvelopeRequests<T>(
374394
* @param {string} [url]
375395
* @return {*} {Promise<T>}
376396
*/
377-
async function getFirstSentryEnvelopeRequest<T>(
397+
export async function getFirstSentryEnvelopeRequest<T>(
378398
page: Page,
379399
url?: string,
380400
requestParser: (req: Request) => T = envelopeRequestParser as (req: Request) => T,
@@ -388,5 +408,3 @@ async function getFirstSentryEnvelopeRequest<T>(
388408

389409
return req;
390410
}
391-
392-
export { runScriptInSandbox, getMultipleSentryEnvelopeRequests, getFirstSentryEnvelopeRequest, getSentryEvents };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const { loggingTransport } = require('@sentry-internal/node-integration-tests');
2+
const Sentry = require('@sentry/node');
3+
4+
Sentry.init({
5+
dsn: 'https://[email protected]/1337',
6+
release: '1.0',
7+
transport: loggingTransport,
8+
tracesSampler: samplingContext => {
9+
// The sampling decision is based on whether the data in `normalizedRequest` is available --> this is what we want to test for
10+
return (
11+
samplingContext.normalizedRequest.url.includes('/test-normalized-request?query=123') &&
12+
samplingContext.normalizedRequest.method &&
13+
samplingContext.normalizedRequest.query_string === 'query=123' &&
14+
!!samplingContext.normalizedRequest.headers
15+
);
16+
},
17+
});
18+
19+
// express must be required after Sentry is initialized
20+
const express = require('express');
21+
const cors = require('cors');
22+
const { startExpressServerAndSendPortToRunner } = require('@sentry-internal/node-integration-tests');
23+
24+
const app = express();
25+
26+
app.use(cors());
27+
28+
app.get('/test-normalized-request', (_req, res) => {
29+
res.send('Success');
30+
});
31+
32+
Sentry.setupExpressErrorHandler(app);
33+
34+
startExpressServerAndSendPortToRunner(app);

dev-packages/node-integration-tests/suites/express/tracing/tracesSampler/server.js

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ Sentry.init({
1515
samplingContext.attributes['http.method'] === 'GET'
1616
);
1717
},
18-
debug: true,
1918
});
2019

2120
// express must be required after Sentry is initialized

dev-packages/node-integration-tests/suites/express/tracing/tracesSampler/test.ts

+20
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,23 @@ describe('express tracesSampler', () => {
2222
});
2323
});
2424
});
25+
26+
describe('express tracesSampler includes normalizedRequest data', () => {
27+
afterAll(() => {
28+
cleanupChildProcesses();
29+
});
30+
31+
describe('CJS', () => {
32+
test('correctly samples & passes data to tracesSampler', done => {
33+
const runner = createRunner(__dirname, 'scenario-normalizedRequest.js')
34+
.expect({
35+
transaction: {
36+
transaction: 'GET /test-normalized-request',
37+
},
38+
})
39+
.start(done);
40+
41+
runner.makeRequest('get', '/test-normalized-request?query=123');
42+
});
43+
});
44+
});

docs/migration/v8-to-v9.md

+15-1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ Sentry.init({
7878

7979
In v9, an `undefined` value will be treated the same as if the value is not defined at all. You'll need to set `tracesSampleRate: 0` if you want to enable tracing without performance.
8080

81+
- The `getCurrentHub().getIntegration(IntegrationClass)` method will always return `null` in v9. This has already stopped working mostly in v8, because we stopped exposing integration classes. In v9, the fallback behavior has been removed. Note that this does not change the type signature and is thus not technically breaking, but still worth pointing out.
82+
8183
### `@sentry/node`
8284

8385
- When `skipOpenTelemetrySetup: true` is configured, `httpIntegration({ spans: false })` will be configured by default. This means that you no longer have to specify this yourself in this scenario. With this change, no spans are emitted once `skipOpenTelemetrySetup: true` is configured, without any further configuration being needed.
@@ -141,8 +143,16 @@ Sentry.init({
141143
- The `flatten` export has been removed. There is no replacement.
142144
- The `urlEncode` method has been removed. There is no replacement.
143145
- The `getDomElement` method has been removed. There is no replacement.
144-
- The `Request` type has been removed. Use `RequestEventData` type instead.
145146
- The `memoBuilder` method has been removed. There is no replacement.
147+
- The `extractRequestData` method has been removed. Manually extract relevant data off request instead.
148+
- The `addRequestDataToEvent` method has been removed. Use `addNormalizedRequestDataToEvent` instead.
149+
- The `extractPathForTransaction` method has been removed. There is no replacement.
150+
151+
#### Other/Internal Changes
152+
153+
The following changes are unlikely to affect users of the SDK. They are listed here only for completion sake, and to alert users that may be relying on internal behavior.
154+
155+
- `client._prepareEvent()` now requires a currentScope & isolationScope to be passed as last arugments
146156

147157
### `@sentry/browser`
148158

@@ -207,6 +217,10 @@ This led to some duplication, where we had to keep an interface in `@sentry/type
207217
Since v9, the types have been merged into `@sentry/core`, which removed some of this duplication. This means that certain things that used to be a separate interface, will not expect an actual instance of the class/concrete implementation. This should not affect most users, unless you relied on passing things with a similar shape to internal methods. The following types are affected:
208218

209219
- `Scope` now always expects the `Scope` class
220+
- The `TransactionNamingScheme` type has been removed. There is no replacement.
221+
- The `Request` type has been removed. Use `RequestEventData` type instead.
222+
- The `IntegrationClass` type is no longer exported - it was not used anymore. Instead, use `Integration` or `IntegrationFn`.
223+
- The `samplingContext.request` attribute in the `tracesSampler` has been removed. Use `samplingContext.normalizedRequest` instead. Note that the type of `normalizedRequest` differs from `request`.
210224

211225
# No Version Support Timeline
212226

packages/angular/.eslintrc.cjs

+4
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@ module.exports = {
44
},
55
extends: ['../../.eslintrc.js'],
66
ignorePatterns: ['setup-test.ts', 'patch-vitest.ts'],
7+
rules: {
8+
// Angular transpiles this correctly/relies on this
9+
'@sentry-internal/sdk/no-class-field-initializers': 'off',
10+
},
711
};

packages/astro/src/index.server.ts

-4
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ export {
1111
addBreadcrumb,
1212
addEventProcessor,
1313
addIntegration,
14-
// eslint-disable-next-line deprecation/deprecation
15-
addRequestDataToEvent,
1614
amqplibIntegration,
1715
anrIntegration,
1816
disableAnrDetectionForCallback,
@@ -38,8 +36,6 @@ export {
3836
endSession,
3937
expressErrorHandler,
4038
expressIntegration,
41-
// eslint-disable-next-line deprecation/deprecation
42-
extractRequestData,
4339
extraErrorDataIntegration,
4440
fastifyIntegration,
4541
flush,

packages/aws-serverless/src/index.ts

-4
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,7 @@ export {
4242
flush,
4343
close,
4444
getSentryRelease,
45-
// eslint-disable-next-line deprecation/deprecation
46-
addRequestDataToEvent,
4745
DEFAULT_USER_INCLUDES,
48-
// eslint-disable-next-line deprecation/deprecation
49-
extractRequestData,
5046
createGetModuleFromFilename,
5147
anrIntegration,
5248
disableAnrDetectionForCallback,

packages/aws-serverless/src/sdk.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export interface WrapperOptions {
5151
captureAllSettledReasons: boolean;
5252
/**
5353
* Automatically trace all handler invocations.
54-
* You may want to disable this if you use express within Lambda (use tracingHandler instead).
54+
* You may want to disable this if you use express within Lambda.
5555
* @default true
5656
*/
5757
startTrace: boolean;

packages/browser/src/client.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,13 @@ export class BrowserClient extends BaseClient<BrowserClientOptions> {
105105
/**
106106
* @inheritDoc
107107
*/
108-
protected _prepareEvent(event: Event, hint: EventHint, scope?: Scope): PromiseLike<Event | null> {
108+
protected _prepareEvent(
109+
event: Event,
110+
hint: EventHint,
111+
currentScope: Scope,
112+
isolationScope: Scope,
113+
): PromiseLike<Event | null> {
109114
event.platform = event.platform || 'javascript';
110-
return super._prepareEvent(event, hint, scope);
115+
return super._prepareEvent(event, hint, currentScope, isolationScope);
111116
}
112117
}

packages/browser/src/feedbackSync.ts

-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ import {
33
feedbackModalIntegration,
44
feedbackScreenshotIntegration,
55
} from '@sentry-internal/feedback';
6-
import { lazyLoadIntegration } from './utils/lazyLoadIntegration';
76

87
/** Add a widget to capture user feedback to your application. */
98
export const feedbackSyncIntegration = buildFeedbackIntegration({
10-
lazyLoadIntegration,
119
getModalIntegration: () => feedbackModalIntegration,
1210
getScreenshotIntegration: () => feedbackScreenshotIntegration,
1311
});

packages/bun/src/index.ts

-4
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,7 @@ export {
6262
flush,
6363
close,
6464
getSentryRelease,
65-
// eslint-disable-next-line deprecation/deprecation
66-
addRequestDataToEvent,
6765
DEFAULT_USER_INCLUDES,
68-
// eslint-disable-next-line deprecation/deprecation
69-
extractRequestData,
7066
createGetModuleFromFilename,
7167
anrIntegration,
7268
disableAnrDetectionForCallback,

packages/core/src/baseclient.ts

+23-13
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,11 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
216216

217217
const sdkProcessingMetadata = event.sdkProcessingMetadata || {};
218218
const capturedSpanScope: Scope | undefined = sdkProcessingMetadata.capturedSpanScope;
219+
const capturedSpanIsolationScope: Scope | undefined = sdkProcessingMetadata.capturedSpanIsolationScope;
219220

220-
this._process(this._captureEvent(event, hintWithEventId, capturedSpanScope || currentScope));
221+
this._process(
222+
this._captureEvent(event, hintWithEventId, capturedSpanScope || currentScope, capturedSpanIsolationScope),
223+
);
221224

222225
return hintWithEventId.event_id;
223226
}
@@ -676,8 +679,8 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
676679
protected _prepareEvent(
677680
event: Event,
678681
hint: EventHint,
679-
currentScope = getCurrentScope(),
680-
isolationScope = getIsolationScope(),
682+
currentScope: Scope,
683+
isolationScope: Scope,
681684
): PromiseLike<Event | null> {
682685
const options = this.getOptions();
683686
const integrations = Object.keys(this._integrations);
@@ -718,12 +721,17 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
718721
* @param hint
719722
* @param scope
720723
*/
721-
protected _captureEvent(event: Event, hint: EventHint = {}, scope?: Scope): PromiseLike<string | undefined> {
724+
protected _captureEvent(
725+
event: Event,
726+
hint: EventHint = {},
727+
currentScope = getCurrentScope(),
728+
isolationScope = getIsolationScope(),
729+
): PromiseLike<string | undefined> {
722730
if (DEBUG_BUILD && isErrorEvent(event)) {
723731
logger.log(`Captured error event \`${getPossibleEventMessages(event)[0] || '<unknown>'}\``);
724732
}
725733

726-
return this._processEvent(event, hint, scope).then(
734+
return this._processEvent(event, hint, currentScope, isolationScope).then(
727735
finalEvent => {
728736
return finalEvent.event_id;
729737
},
@@ -756,7 +764,12 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
756764
* @param currentScope A scope containing event metadata.
757765
* @returns A SyncPromise that resolves with the event or rejects in case event was/will not be send.
758766
*/
759-
protected _processEvent(event: Event, hint: EventHint, currentScope?: Scope): PromiseLike<Event> {
767+
protected _processEvent(
768+
event: Event,
769+
hint: EventHint,
770+
currentScope: Scope,
771+
isolationScope: Scope,
772+
): PromiseLike<Event> {
760773
const options = this.getOptions();
761774
const { sampleRate } = options;
762775

@@ -779,12 +792,9 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
779792
);
780793
}
781794

782-
const dataCategory: DataCategory = eventType === 'replay_event' ? 'replay' : eventType;
783-
784-
const sdkProcessingMetadata = event.sdkProcessingMetadata || {};
785-
const capturedSpanIsolationScope: Scope | undefined = sdkProcessingMetadata.capturedSpanIsolationScope;
795+
const dataCategory = (eventType === 'replay_event' ? 'replay' : eventType) satisfies DataCategory;
786796

787-
return this._prepareEvent(event, hint, currentScope, capturedSpanIsolationScope)
797+
return this._prepareEvent(event, hint, currentScope, isolationScope)
788798
.then(prepared => {
789799
if (prepared === null) {
790800
this.recordDroppedEvent('event_processor', dataCategory, event);
@@ -811,8 +821,8 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
811821
throw new SentryError(`${beforeSendLabel} returned \`null\`, will not send event.`, 'log');
812822
}
813823

814-
const session = currentScope && currentScope.getSession();
815-
if (!isTransaction && session) {
824+
const session = currentScope.getSession() || isolationScope.getSession();
825+
if (isError && session) {
816826
this._updateSessionFromEvent(session, processedEvent);
817827
}
818828

0 commit comments

Comments
 (0)