From ee1a06a9620371c0127160e71b340811b9491d2b Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Wed, 7 Feb 2024 18:05:23 -0500 Subject: [PATCH 1/5] feat(v8): Remove deprecated configureScope call --- MIGRATION.md | 4 + .../configureScope/clear_scope/subject.js | 8 - .../configureScope/clear_scope/test.ts | 16 - .../suites/public-api/configureScope/init.js | 7 - .../configureScope/set_properties/subject.js | 7 - .../configureScope/set_properties/test.ts | 16 - .../backgroundtab-custom/subject.js | 2 +- .../backgroundtab-custom/subject.js | 2 +- packages/astro/src/index.server.ts | 2 - packages/browser/README.md | 9 +- packages/browser/src/exports.ts | 2 - packages/browser/src/loader.js | 1 + packages/browser/src/sdk.ts | 11 - packages/browser/test/package/test-code.js | 13 +- packages/bun/README.md | 9 +- packages/bun/src/index.ts | 2 - packages/bun/src/sdk.ts | 11 - packages/core/src/exports.ts | 11 - packages/core/src/hub.ts | 13 - packages/core/src/index.ts | 2 - packages/deno/README.md | 9 +- packages/deno/src/index.ts | 2 - packages/deno/src/sdk.ts | 11 - packages/hub/src/index.ts | 152 +++++ packages/hub/test/exports.test.ts | 251 ++++++++ packages/hub/test/hub.test.ts | 538 ++++++++++++++++++ packages/nextjs/README.md | 9 +- .../vercel/install-sentry-from-branch.sh | 14 +- packages/node-experimental/src/index.ts | 2 - packages/node-experimental/src/sdk/api.ts | 9 + packages/node-experimental/src/sdk/hub.ts | 3 - packages/node/README.md | 9 +- packages/node/src/index.ts | 2 - packages/node/src/sdk.ts | 11 - .../manual/express-scope-separation/start.js | 16 +- .../manual/memory-leak/express-patient.js | 4 +- .../manual/webpack-async-context/index.js | 9 +- packages/remix/README.md | 9 +- packages/remix/src/index.server.ts | 2 - packages/serverless/src/index.ts | 2 - packages/sveltekit/src/server/index.ts | 2 - packages/types/src/hub.ts | 8 - packages/vercel-edge/README.md | 9 +- packages/vercel-edge/src/index.ts | 2 - 44 files changed, 997 insertions(+), 236 deletions(-) delete mode 100644 dev-packages/browser-integration-tests/suites/public-api/configureScope/clear_scope/subject.js delete mode 100644 dev-packages/browser-integration-tests/suites/public-api/configureScope/clear_scope/test.ts delete mode 100644 dev-packages/browser-integration-tests/suites/public-api/configureScope/init.js delete mode 100644 dev-packages/browser-integration-tests/suites/public-api/configureScope/set_properties/subject.js delete mode 100644 dev-packages/browser-integration-tests/suites/public-api/configureScope/set_properties/test.ts create mode 100644 packages/hub/src/index.ts create mode 100644 packages/hub/test/exports.test.ts create mode 100644 packages/hub/test/hub.test.ts diff --git a/MIGRATION.md b/MIGRATION.md index 24ba1c079bdc..630a0af2d00d 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -33,6 +33,10 @@ The `enableAnrDetection` and `Anr` class have been removed. See the [docs](https://docs.sentry.io/platforms/node/configuration/application-not-responding/) for more details how to migrate to `anrIntegration`, the new integration for ANR detection. +## Removal of `Sentry.configureScope`. + +The top level `Sentry.configureScope` function has been removed. Instead, you should use the `Sentry.getCurrentScope()` to access and mutate the current scope. + ## Other changes - Remove `spanStatusfromHttpCode` in favour of `getSpanStatusFromHttpCode` (#10361) diff --git a/dev-packages/browser-integration-tests/suites/public-api/configureScope/clear_scope/subject.js b/dev-packages/browser-integration-tests/suites/public-api/configureScope/clear_scope/subject.js deleted file mode 100644 index ae65f9976267..000000000000 --- a/dev-packages/browser-integration-tests/suites/public-api/configureScope/clear_scope/subject.js +++ /dev/null @@ -1,8 +0,0 @@ -Sentry.configureScope(scope => { - scope.setTag('foo', 'bar'); - scope.setUser({ id: 'baz' }); - scope.setExtra('qux', 'quux'); - scope.clear(); -}); - -Sentry.captureMessage('cleared_scope'); diff --git a/dev-packages/browser-integration-tests/suites/public-api/configureScope/clear_scope/test.ts b/dev-packages/browser-integration-tests/suites/public-api/configureScope/clear_scope/test.ts deleted file mode 100644 index 02a82ffef26d..000000000000 --- a/dev-packages/browser-integration-tests/suites/public-api/configureScope/clear_scope/test.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { expect } from '@playwright/test'; -import type { Event } from '@sentry/types'; - -import { sentryTest } from '../../../../utils/fixtures'; -import { getFirstSentryEnvelopeRequest } from '../../../../utils/helpers'; - -sentryTest('should clear previously set properties of a scope', async ({ getLocalTestPath, page }) => { - const url = await getLocalTestPath({ testDir: __dirname }); - - const eventData = await getFirstSentryEnvelopeRequest(page, url); - - expect(eventData.message).toBe('cleared_scope'); - expect(eventData.user).toBeUndefined(); - expect(eventData.tags).toBeUndefined(); - expect(eventData.extra).toBeUndefined(); -}); diff --git a/dev-packages/browser-integration-tests/suites/public-api/configureScope/init.js b/dev-packages/browser-integration-tests/suites/public-api/configureScope/init.js deleted file mode 100644 index d8c94f36fdd0..000000000000 --- a/dev-packages/browser-integration-tests/suites/public-api/configureScope/init.js +++ /dev/null @@ -1,7 +0,0 @@ -import * as Sentry from '@sentry/browser'; - -window.Sentry = Sentry; - -Sentry.init({ - dsn: 'https://public@dsn.ingest.sentry.io/1337', -}); diff --git a/dev-packages/browser-integration-tests/suites/public-api/configureScope/set_properties/subject.js b/dev-packages/browser-integration-tests/suites/public-api/configureScope/set_properties/subject.js deleted file mode 100644 index db5d34977b1e..000000000000 --- a/dev-packages/browser-integration-tests/suites/public-api/configureScope/set_properties/subject.js +++ /dev/null @@ -1,7 +0,0 @@ -Sentry.configureScope(scope => { - scope.setTag('foo', 'bar'); - scope.setUser({ id: 'baz' }); - scope.setExtra('qux', 'quux'); -}); - -Sentry.captureMessage('configured_scope'); diff --git a/dev-packages/browser-integration-tests/suites/public-api/configureScope/set_properties/test.ts b/dev-packages/browser-integration-tests/suites/public-api/configureScope/set_properties/test.ts deleted file mode 100644 index ba31c0ca18e7..000000000000 --- a/dev-packages/browser-integration-tests/suites/public-api/configureScope/set_properties/test.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { expect } from '@playwright/test'; -import type { Event } from '@sentry/types'; - -import { sentryTest } from '../../../../utils/fixtures'; -import { getFirstSentryEnvelopeRequest } from '../../../../utils/helpers'; - -sentryTest('should set different properties of a scope', async ({ getLocalTestPath, page }) => { - const url = await getLocalTestPath({ testDir: __dirname }); - - const eventData = await getFirstSentryEnvelopeRequest(page, url); - - expect(eventData.message).toBe('configured_scope'); - expect(eventData.user).toMatchObject({ id: 'baz' }); - expect(eventData.tags).toMatchObject({ foo: 'bar' }); - expect(eventData.extra).toMatchObject({ qux: 'quux' }); -}); diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/backgroundtab-custom/subject.js b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/backgroundtab-custom/subject.js index 5355521f1655..7221e2302b21 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/backgroundtab-custom/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/backgroundtab-custom/subject.js @@ -7,5 +7,5 @@ document.getElementById('go-background').addEventListener('click', () => { document.getElementById('start-transaction').addEventListener('click', () => { window.transaction = Sentry.startTransaction({ name: 'test-transaction' }); - Sentry.getCurrentHub().configureScope(scope => scope.setSpan(window.transaction)); + Sentry.getCurrentScope().setSpan(window.transaction); }); diff --git a/dev-packages/browser-integration-tests/suites/tracing/browsertracing/backgroundtab-custom/subject.js b/dev-packages/browser-integration-tests/suites/tracing/browsertracing/backgroundtab-custom/subject.js index 5355521f1655..7221e2302b21 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browsertracing/backgroundtab-custom/subject.js +++ b/dev-packages/browser-integration-tests/suites/tracing/browsertracing/backgroundtab-custom/subject.js @@ -7,5 +7,5 @@ document.getElementById('go-background').addEventListener('click', () => { document.getElementById('start-transaction').addEventListener('click', () => { window.transaction = Sentry.startTransaction({ name: 'test-transaction' }); - Sentry.getCurrentHub().configureScope(scope => scope.setSpan(window.transaction)); + Sentry.getCurrentScope().setSpan(window.transaction); }); diff --git a/packages/astro/src/index.server.ts b/packages/astro/src/index.server.ts index ad22273818f7..5937aa6ad889 100644 --- a/packages/astro/src/index.server.ts +++ b/packages/astro/src/index.server.ts @@ -17,8 +17,6 @@ export { captureMessage, captureCheckIn, withMonitor, - // eslint-disable-next-line deprecation/deprecation - configureScope, createTransport, // eslint-disable-next-line deprecation/deprecation extractTraceparentData, diff --git a/packages/browser/README.md b/packages/browser/README.md index 63f90f784189..98bbf0cabca2 100644 --- a/packages/browser/README.md +++ b/packages/browser/README.md @@ -37,12 +37,9 @@ functions will not perform any action before you have called `Sentry.init()`: import * as Sentry from '@sentry/browser'; // Set user information, as well as tags and further extras -Sentry.configureScope(scope => { - scope.setExtra('battery', 0.7); - scope.setTag('user_mode', 'admin'); - scope.setUser({ id: '4711' }); - // scope.clear(); -}); +Sentry.setExtra('battery', 0.7); +Sentry.setTag('user_mode', 'admin'); +Sentry.setUser({ id: '4711' }); // Add a breadcrumb for future events Sentry.addBreadcrumb({ diff --git a/packages/browser/src/exports.ts b/packages/browser/src/exports.ts index 2394dd8013ea..eda89ac56b1c 100644 --- a/packages/browser/src/exports.ts +++ b/packages/browser/src/exports.ts @@ -30,8 +30,6 @@ export { captureEvent, captureMessage, close, - // eslint-disable-next-line deprecation/deprecation - configureScope, createTransport, flush, getHubFromCarrier, diff --git a/packages/browser/src/loader.js b/packages/browser/src/loader.js index 19d7bfb5a7e9..c80d5a1a4129 100644 --- a/packages/browser/src/loader.js +++ b/packages/browser/src/loader.js @@ -184,6 +184,7 @@ 'captureMessage', 'captureException', 'captureEvent', + // TODO: Remove configureScope from loader 'configureScope', 'withScope', 'showReportDialog' diff --git a/packages/browser/src/sdk.ts b/packages/browser/src/sdk.ts index 4095a8a8c2ba..39fabc92c8ec 100644 --- a/packages/browser/src/sdk.ts +++ b/packages/browser/src/sdk.ts @@ -79,17 +79,6 @@ declare const __SENTRY_RELEASE__: string | undefined; * @example * ``` * - * import { configureScope } from '@sentry/browser'; - * configureScope((scope: Scope) => { - * scope.setExtra({ battery: 0.7 }); - * scope.setTag({ user_mode: 'admin' }); - * scope.setUser({ id: '4711' }); - * }); - * ``` - * - * @example - * ``` - * * import { addBreadcrumb } from '@sentry/browser'; * addBreadcrumb({ * message: 'My Breadcrumb', diff --git a/packages/browser/test/package/test-code.js b/packages/browser/test/package/test-code.js index 3a3811eebb89..309391bf68c1 100644 --- a/packages/browser/test/package/test-code.js +++ b/packages/browser/test/package/test-code.js @@ -17,13 +17,12 @@ Sentry.init({ }); // Configure -Sentry.configureScope(scope => { - scope.setExtra('foo', 'bar'); - scope.setFingerprint('foo'); - scope.setLevel('warning'); - scope.setTag('foo', 'bar'); - scope.setUser('foo', 'bar'); -}); +const scope = Sentry.getCurrentScope() +scope.setExtra('foo', 'bar'); +scope.setFingerprint('foo'); +scope.setLevel('warning'); +scope.setTag('foo', 'bar'); +scope.setUser('foo', 'bar'); // Breadcrumbs integration window.console.log('Console', 'Breadcrumb'); diff --git a/packages/bun/README.md b/packages/bun/README.md index 56c795793532..d9c99350a613 100644 --- a/packages/bun/README.md +++ b/packages/bun/README.md @@ -39,12 +39,9 @@ functions will not perform any action before you have called `init()`: ```javascript // Set user information, as well as tags and further extras -Sentry.configureScope(scope => { - scope.setExtra('battery', 0.7); - scope.setTag('user_mode', 'admin'); - scope.setUser({ id: '4711' }); - // scope.clear(); -}); +Sentry.setExtra('battery', 0.7); +Sentry.setTag('user_mode', 'admin'); +Sentry.setUser({ id: '4711' }); // Add a breadcrumb for future events Sentry.addBreadcrumb({ diff --git a/packages/bun/src/index.ts b/packages/bun/src/index.ts index 295bad3271ea..e295d4632fe3 100644 --- a/packages/bun/src/index.ts +++ b/packages/bun/src/index.ts @@ -31,8 +31,6 @@ export { captureEvent, captureMessage, close, - // eslint-disable-next-line deprecation/deprecation - configureScope, createTransport, // eslint-disable-next-line deprecation/deprecation extractTraceparentData, diff --git a/packages/bun/src/sdk.ts b/packages/bun/src/sdk.ts index 2054c833fd01..1db72246178f 100644 --- a/packages/bun/src/sdk.ts +++ b/packages/bun/src/sdk.ts @@ -73,17 +73,6 @@ export function getDefaultIntegrations(_options: Options): Integration[] { * @example * ``` * - * const { configureScope } = require('@sentry/node'); - * configureScope((scope: Scope) => { - * scope.setExtra({ battery: 0.7 }); - * scope.setTag({ user_mode: 'admin' }); - * scope.setUser({ id: '4711' }); - * }); - * ``` - * - * @example - * ``` - * * const { addBreadcrumb } = require('@sentry/node'); * addBreadcrumb({ * message: 'My Breadcrumb', diff --git a/packages/core/src/exports.ts b/packages/core/src/exports.ts index 8691aa9e70cd..6c18aa0ec9ba 100644 --- a/packages/core/src/exports.ts +++ b/packages/core/src/exports.ts @@ -76,17 +76,6 @@ export function captureEvent(event: Event, hint?: EventHint): string { return getCurrentHub().captureEvent(event, hint); } -/** - * Callback to set context information onto the scope. - * @param callback Callback function that receives Scope. - * - * @deprecated Use getCurrentScope() directly. - */ -export function configureScope(callback: (scope: Scope) => void): ReturnType { - // eslint-disable-next-line deprecation/deprecation - getCurrentHub().configureScope(callback); -} - /** * Records a new breadcrumb which will be attached to future events. * diff --git a/packages/core/src/hub.ts b/packages/core/src/hub.ts index e729a5c8f763..be06ca0c8185 100644 --- a/packages/core/src/hub.ts +++ b/packages/core/src/hub.ts @@ -507,19 +507,6 @@ export class Hub implements HubInterface { this.getIsolationScope().setContext(name, context); } - /** - * @inheritDoc - * - * @deprecated Use `getScope()` directly. - */ - public configureScope(callback: (scope: Scope) => void): void { - // eslint-disable-next-line deprecation/deprecation - const { scope, client } = this.getStackTop(); - if (client) { - callback(scope); - } - } - /** * @inheritDoc */ diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 992de9f60739..f42a411802e7 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -16,8 +16,6 @@ export { captureEvent, captureMessage, close, - // eslint-disable-next-line deprecation/deprecation - configureScope, flush, // eslint-disable-next-line deprecation/deprecation startTransaction, diff --git a/packages/deno/README.md b/packages/deno/README.md index 4246a367ad81..67ac88fedc6e 100644 --- a/packages/deno/README.md +++ b/packages/deno/README.md @@ -41,12 +41,9 @@ functions will not perform any action before you have called `init()`: ```javascript // Set user information, as well as tags and further extras -Sentry.configureScope(scope => { - scope.setExtra('battery', 0.7); - scope.setTag('user_mode', 'admin'); - scope.setUser({ id: '4711' }); - // scope.clear(); -}); +Sentry.setExtra('battery', 0.7); +Sentry.setTag('user_mode', 'admin'); +Sentry.setUser({ id: '4711' }); // Add a breadcrumb for future events Sentry.addBreadcrumb({ diff --git a/packages/deno/src/index.ts b/packages/deno/src/index.ts index 579bad78c869..2139767a5397 100644 --- a/packages/deno/src/index.ts +++ b/packages/deno/src/index.ts @@ -29,8 +29,6 @@ export { captureEvent, captureMessage, close, - // eslint-disable-next-line deprecation/deprecation - configureScope, createTransport, // eslint-disable-next-line deprecation/deprecation extractTraceparentData, diff --git a/packages/deno/src/sdk.ts b/packages/deno/src/sdk.ts index c5bd3a1d002f..b9e3cdab1ebb 100644 --- a/packages/deno/src/sdk.ts +++ b/packages/deno/src/sdk.ts @@ -65,17 +65,6 @@ const defaultStackParser: StackParser = createStackParser(nodeStackLineParser()) * @example * ``` * - * import { configureScope } from 'npm:@sentry/deno'; - * configureScope((scope: Scope) => { - * scope.setExtra({ battery: 0.7 }); - * scope.setTag({ user_mode: 'admin' }); - * scope.setUser({ id: '4711' }); - * }); - * ``` - * - * @example - * ``` - * * import { addBreadcrumb } from 'npm:@sentry/deno'; * addBreadcrumb({ * message: 'My Breadcrumb', diff --git a/packages/hub/src/index.ts b/packages/hub/src/index.ts new file mode 100644 index 000000000000..f54256ee2a64 --- /dev/null +++ b/packages/hub/src/index.ts @@ -0,0 +1,152 @@ +export type { Carrier, Layer } from '@sentry/core'; + +import { + Hub as HubCore, + Scope as ScopeCore, + SessionFlusher as SessionFlusherCore, + addBreadcrumb as addBreadcrumbCore, + addGlobalEventProcessor as addGlobalEventProcessorCore, + captureEvent as captureEventCore, + captureException as captureExceptionCore, + captureMessage as captureMessageCore, + closeSession as closeSessionCore, + getCurrentHub as getCurrentHubCore, + getHubFromCarrier as getHubFromCarrierCore, + getMainCarrier as getMainCarrierCore, + makeMain as makeMainCore, + makeSession as makeSessionCore, + setContext as setContextCore, + setExtra as setExtraCore, + setExtras as setExtrasCore, + setHubOnCarrier as setHubOnCarrierCore, + setTag as setTagCore, + setTags as setTagsCore, + setUser as setUserCore, + startTransaction as startTransactionCore, + updateSession as updateSessionCore, + withScope as withScopeCore, +} from '@sentry/core'; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8 + */ +export class Hub extends HubCore {} + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8 + */ +export class Scope extends ScopeCore {} + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +// eslint-disable-next-line deprecation/deprecation +export const getCurrentHub = getCurrentHubCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ + +export const addGlobalEventProcessor = addGlobalEventProcessorCore; // eslint-disable-line deprecation/deprecation + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const getHubFromCarrier = getHubFromCarrierCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const getMainCarrier = getMainCarrierCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +// eslint-disable-next-line deprecation/deprecation +export const makeMain = makeMainCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const setHubOnCarrier = setHubOnCarrierCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const SessionFlusher = SessionFlusherCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const closeSession = closeSessionCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const makeSession = makeSessionCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const updateSession = updateSessionCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const addBreadcrumb = addBreadcrumbCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const captureException = captureExceptionCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const captureEvent = captureEventCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const captureMessage = captureMessageCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +// eslint-disable-next-line deprecation/deprecation +export const startTransaction = startTransactionCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const setContext = setContextCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const setExtra = setExtraCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const setExtras = setExtrasCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const setTag = setTagCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const setTags = setTagsCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const setUser = setUserCore; + +/** + * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. + */ +export const withScope = withScopeCore; diff --git a/packages/hub/test/exports.test.ts b/packages/hub/test/exports.test.ts new file mode 100644 index 000000000000..15b85c376062 --- /dev/null +++ b/packages/hub/test/exports.test.ts @@ -0,0 +1,251 @@ +/* eslint-disable deprecation/deprecation */ + +import { getCurrentScope } from '@sentry/core'; +import type { Scope } from '../src'; +import { + captureEvent, + captureException, + captureMessage, + getCurrentHub, + getHubFromCarrier, + setContext, + setExtra, + setExtras, + setTag, + setTags, + setUser, + withScope, +} from '../src'; + +export class TestClient { + public static instance?: TestClient; + + public constructor(public options: Record) { + TestClient.instance = this; + } + + public mySecretPublicMethod(str: string): string { + return `secret: ${str}`; + } +} + +export class TestClient2 {} + +export function init(options: Record): void { + getCurrentHub().bindClient(new TestClient(options) as any); +} + +// eslint-disable-next-line no-var +declare var global: any; + +describe('Top Level API', () => { + beforeEach(() => { + global.__SENTRY__ = { + hub: undefined, + }; + }); + + describe('Capture', () => { + test('Return an event_id', () => { + const client: any = { + captureException: jest.fn(async () => Promise.resolve()), + }; + getCurrentHub().withScope(() => { + getCurrentHub().bindClient(client); + const e = new Error('test exception'); + const eventId = captureException(e); + expect(eventId).toBeTruthy(); + }); + }); + + test('Exception', () => { + const client: any = { + captureException: jest.fn(async () => Promise.resolve()), + }; + getCurrentHub().withScope(() => { + getCurrentHub().bindClient(client); + const e = new Error('test exception'); + captureException(e); + expect(client.captureException.mock.calls[0][0]).toBe(e); + }); + }); + + test('Exception with explicit scope', () => { + const client: any = { + captureException: jest.fn(async () => Promise.resolve()), + }; + getCurrentHub().withScope(() => { + getCurrentHub().bindClient(client); + const e = new Error('test exception'); + const captureContext = { extra: { foo: 'wat' } }; + captureException(e, captureContext); + expect(client.captureException.mock.calls[0][0]).toBe(e); + expect(client.captureException.mock.calls[0][1].captureContext).toEqual(captureContext); + }); + }); + + test('Message', () => { + const client: any = { captureMessage: jest.fn(async () => Promise.resolve()) }; + getCurrentHub().withScope(() => { + getCurrentHub().bindClient(client); + const message = 'yo'; + captureMessage(message); + expect(client.captureMessage.mock.calls[0][0]).toBe(message); + }); + }); + + test('Message with explicit scope', () => { + const client: any = { captureMessage: jest.fn(async () => Promise.resolve()) }; + getCurrentHub().withScope(() => { + getCurrentHub().bindClient(client); + const message = 'yo'; + const captureContext = { extra: { foo: 'wat' } }; + captureMessage(message, captureContext); + expect(client.captureMessage.mock.calls[0][0]).toBe(message); + // Skip the level if explicit content is provided + expect(client.captureMessage.mock.calls[0][1]).toBe(undefined); + expect(client.captureMessage.mock.calls[0][2].captureContext).toBe(captureContext); + }); + }); + + // NOTE: We left custom level as 2nd argument to not break the API. Should be removed and unified in v6. + // TODO: Before we release v8, check if this is still a thing + test('Message with custom level', () => { + const client: any = { captureMessage: jest.fn(async () => Promise.resolve()) }; + getCurrentHub().withScope(() => { + getCurrentHub().bindClient(client); + const message = 'yo'; + const level = 'warning'; + captureMessage(message, level); + expect(client.captureMessage.mock.calls[0][0]).toBe(message); + expect(client.captureMessage.mock.calls[0][1]).toBe('warning'); + }); + }); + + test('Event', () => { + const client: any = { captureEvent: jest.fn(async () => Promise.resolve()) }; + getCurrentHub().withScope(() => { + getCurrentHub().bindClient(client); + const e = { message: 'test' }; + captureEvent(e); + expect(client.captureEvent.mock.calls[0][0]).toBe(e); + }); + }); + }); + + test('Clear Scope', () => { + const client: any = new TestClient({}); + getCurrentHub().withScope(() => { + getCurrentHub().bindClient(client); + expect(global.__SENTRY__.hub._stack.length).toBe(2); + getCurrentScope().setUser({ id: '1234' }); + expect(global.__SENTRY__.hub._stack[1].scope._user).toEqual({ + id: '1234', + }); + getCurrentScope().clear(); + expect(global.__SENTRY__.hub._stack[1].scope._user).toEqual({}); + }); + }); + + test('returns undefined before binding a client', () => { + expect(getCurrentHub().getClient()).toBeUndefined(); + }); + + test('returns the bound client', () => { + init({}); + expect(getCurrentHub().getClient()).toBe(TestClient.instance); + }); + + test('does not throw an error when pushing different clients', () => { + init({}); + expect(() => { + getCurrentHub().withScope(() => { + getCurrentHub().bindClient(new TestClient2() as any); + }); + }).not.toThrow(); + }); + + test('does not throw an error when pushing same clients', () => { + init({}); + expect(() => { + getCurrentHub().withScope(() => { + getCurrentHub().bindClient(new TestClient({}) as any); + }); + }).not.toThrow(); + }); + + test('custom carrier', () => { + const iAmSomeGlobalVarTheUserHasToManage = { + state: {}, + }; + const hub = getHubFromCarrier(iAmSomeGlobalVarTheUserHasToManage.state); + hub.pushScope(); + hub.bindClient(new TestClient({}) as any); + hub.getScope().setUser({ id: '1234' }); + expect((iAmSomeGlobalVarTheUserHasToManage.state as any).__SENTRY__.hub._stack[1].scope._user).toEqual({ + id: '1234', + }); + hub.popScope(); + expect((iAmSomeGlobalVarTheUserHasToManage.state as any).__SENTRY__.hub._stack[1]).toBeUndefined(); + }); + + test('withScope', () => { + withScope(scope => { + scope.setLevel('warning'); + scope.setFingerprint(['1']); + withScope(scope2 => { + scope2.setLevel('info'); + scope2.setFingerprint(['2']); + withScope(scope3 => { + scope3.clear(); + expect(global.__SENTRY__.hub._stack[1].scope._level).toEqual('warning'); + expect(global.__SENTRY__.hub._stack[1].scope._fingerprint).toEqual(['1']); + expect(global.__SENTRY__.hub._stack[2].scope._level).toEqual('info'); + expect(global.__SENTRY__.hub._stack[2].scope._fingerprint).toEqual(['2']); + expect(global.__SENTRY__.hub._stack[3].scope._level).toBeUndefined(); + }); + expect(global.__SENTRY__.hub._stack).toHaveLength(3); + }); + expect(global.__SENTRY__.hub._stack).toHaveLength(2); + }); + expect(global.__SENTRY__.hub._stack).toHaveLength(1); + }); + + test('setExtras', () => { + init({}); + setExtras({ a: 'b' }); + expect(global.__SENTRY__.hub._stack[0].scope._extra).toEqual({ a: 'b' }); + }); + + test('setTags', () => { + init({}); + setTags({ a: 'b' }); + expect(global.__SENTRY__.hub._stack[0].scope._tags).toEqual({ a: 'b' }); + }); + + test('setExtra', () => { + init({}); + setExtra('a', 'b'); + // biome-ignore format: Follow-up for prettier + expect(global.__SENTRY__.hub._stack[0].scope._extra).toEqual({ 'a': 'b' }); + }); + + test('setTag', () => { + init({}); + setTag('a', 'b'); + // biome-ignore format: Follow-up for prettier + expect(global.__SENTRY__.hub._stack[0].scope._tags).toEqual({ 'a': 'b' }); + }); + + test('setUser', () => { + init({}); + setUser({ id: 'b' }); + expect(global.__SENTRY__.hub._stack[0].scope._user).toEqual({ id: 'b' }); + }); + + test('setContext', () => { + init({}); + setContext('test', { id: 'b' }); + expect(global.__SENTRY__.hub._stack[0].scope._contexts).toEqual({ test: { id: 'b' } }); + }); +}); diff --git a/packages/hub/test/hub.test.ts b/packages/hub/test/hub.test.ts new file mode 100644 index 000000000000..e320d95c0f0f --- /dev/null +++ b/packages/hub/test/hub.test.ts @@ -0,0 +1,538 @@ +/* eslint-disable @typescript-eslint/unbound-method */ +/* eslint-disable deprecation/deprecation */ + +import type { Client, Event, EventType } from '@sentry/types'; + +import { getCurrentScope, makeMain } from '@sentry/core'; +import { Hub, Scope, getCurrentHub } from '../src'; + +const clientFn: any = jest.fn(); + +function makeClient() { + return { + getOptions: jest.fn(), + captureEvent: jest.fn(), + captureException: jest.fn(), + close: jest.fn(), + flush: jest.fn(), + getDsn: jest.fn(), + getIntegration: jest.fn(), + setupIntegrations: jest.fn(), + captureMessage: jest.fn(), + captureSession: jest.fn(), + } as unknown as Client; +} + +/** + * Return an array containing the arguments passed to the given mocked or spied-upon function. + * + * By default, the args passed to the first call of the function are returned, but it is also possible to retrieve the + * nth call by passing `callIndex`. If the function wasn't called, an error message is returned instead. + */ +function getPassedArgs(mock: (...args: any[]) => any, callIndex: number = 0): any[] { + const asMock = mock as jest.MockedFunction<(...args: any[]) => any>; + return asMock.mock.calls[callIndex] || ["Error: Function wasn't called."]; +} + +describe('Hub', () => { + afterEach(() => { + jest.restoreAllMocks(); + jest.useRealTimers(); + }); + + test('call bindClient with provided client when constructing new instance', () => { + const testClient = makeClient(); + const hub = new Hub(testClient); + expect(hub.getClient()).toBe(testClient); + }); + + test('push process into stack', () => { + const hub = new Hub(); + expect(hub.getStack()).toHaveLength(1); + }); + + test('pass in filled layer', () => { + const hub = new Hub(clientFn); + expect(hub.getStack()).toHaveLength(1); + }); + + test('isOlderThan', () => { + const hub = new Hub(); + expect(hub.isOlderThan(0)).toBeFalsy(); + }); + + describe('pushScope', () => { + test('simple', () => { + const localScope = new Scope(); + localScope.setExtra('a', 'b'); + const hub = new Hub(undefined, localScope); + hub.pushScope(); + expect(hub.getStack()).toHaveLength(2); + expect(hub.getStack()[1].scope).not.toBe(localScope); + expect((hub.getStack()[1].scope as Scope as any)._extra).toEqual({ a: 'b' }); + }); + + test('inherit client', () => { + const testClient: any = { bla: 'a' }; + const hub = new Hub(testClient); + hub.pushScope(); + expect(hub.getStack()).toHaveLength(2); + expect(hub.getStack()[1].client).toBe(testClient); + }); + + describe('bindClient', () => { + test('should override current client', () => { + const testClient = makeClient(); + const nextClient = makeClient(); + const hub = new Hub(testClient); + hub.bindClient(nextClient); + expect(hub.getStack()).toHaveLength(1); + expect(hub.getStack()[0].client).toBe(nextClient); + }); + + test('should bind client to the top-most layer', () => { + const testClient: any = { bla: 'a' }; + const nextClient: any = { foo: 'bar' }; + const hub = new Hub(testClient); + hub.pushScope(); + hub.bindClient(nextClient); + expect(hub.getStack()).toHaveLength(2); + expect(hub.getStack()[0].client).toBe(testClient); + expect(hub.getStack()[1].client).toBe(nextClient); + }); + + test('should call setupIntegration method of passed client', () => { + const testClient = makeClient(); + const nextClient = makeClient(); + const hub = new Hub(testClient); + hub.bindClient(nextClient); + expect(testClient.setupIntegrations).toHaveBeenCalled(); + expect(nextClient.setupIntegrations).toHaveBeenCalled(); + }); + }); + + test('inherit processors', async () => { + expect.assertions(1); + const event: Event = { + extra: { b: 3 }, + }; + const localScope = new Scope(); + localScope.setExtra('a', 'b'); + const hub = new Hub({ a: 'b' } as any, localScope); + + localScope.addEventProcessor(async (processedEvent: Event) => { + processedEvent.dist = '1'; + return processedEvent; + }); + + hub.pushScope(); + const pushedScope = hub.getStackTop().scope; + + return pushedScope!.applyToEvent(event).then(final => { + expect(final!.dist).toEqual('1'); + }); + }); + }); + + test('popScope', () => { + const hub = new Hub(); + hub.pushScope(); + expect(hub.getStack()).toHaveLength(2); + hub.popScope(); + expect(hub.getStack()).toHaveLength(1); + }); + + describe('withScope', () => { + let hub: Hub; + + beforeEach(() => { + hub = new Hub(); + }); + + test('simple', () => { + hub.withScope(() => { + expect(hub.getStack()).toHaveLength(2); + }); + expect(hub.getStack()).toHaveLength(1); + }); + + test('bindClient', () => { + const testClient: any = { bla: 'a' }; + hub.withScope(() => { + hub.bindClient(testClient); + expect(hub.getStack()).toHaveLength(2); + expect(hub.getStack()[1].client).toBe(testClient); + }); + expect(hub.getStack()).toHaveLength(1); + }); + + test('should bubble up exceptions', () => { + const error = new Error('test'); + expect(() => { + hub.withScope(() => { + throw error; + }); + }).toThrow(error); + }); + }); + + test('getCurrentClient', () => { + const testClient: any = { bla: 'a' }; + const hub = new Hub(testClient); + expect(hub.getClient()).toBe(testClient); + }); + + test('getStack', () => { + const client: any = { a: 'b' }; + const hub = new Hub(client); + expect(hub.getStack()[0].client).toBe(client); + }); + + test('getStackTop', () => { + const testClient: any = { bla: 'a' }; + const hub = new Hub(); + hub.pushScope(); + hub.pushScope(); + hub.bindClient(testClient); + expect(hub.getStackTop().client).toEqual({ bla: 'a' }); + }); + + describe('captureException', () => { + test('simple', () => { + const testClient = makeClient(); + const hub = new Hub(testClient); + + hub.captureException('a'); + const args = getPassedArgs(testClient.captureException); + + expect(args[0]).toBe('a'); + }); + + test('should set event_id in hint', () => { + const testClient = makeClient(); + const hub = new Hub(testClient); + + hub.captureException('a'); + const args = getPassedArgs(testClient.captureException); + + expect(args[1].event_id).toBeTruthy(); + }); + + test('should keep event_id from hint', () => { + const testClient = makeClient(); + const hub = new Hub(testClient); + const id = Math.random().toString(); + + hub.captureException('a', { event_id: id }); + const args = getPassedArgs(testClient.captureException); + + expect(args[1].event_id).toBe(id); + }); + + test('should generate hint if not provided in the call', () => { + const testClient = makeClient(); + const hub = new Hub(testClient); + const ex = new Error('foo'); + + hub.captureException(ex); + const args = getPassedArgs(testClient.captureException); + + expect(args[1].originalException).toBe(ex); + expect(args[1].syntheticException).toBeInstanceOf(Error); + expect(args[1].syntheticException.message).toBe('Sentry syntheticException'); + }); + }); + + describe('captureMessage', () => { + test('simple', () => { + const testClient = makeClient(); + const hub = new Hub(testClient); + + hub.captureMessage('a'); + const args = getPassedArgs(testClient.captureMessage); + + expect(args[0]).toBe('a'); + }); + + test('should set event_id in hint', () => { + const testClient = makeClient(); + const hub = new Hub(testClient); + + hub.captureMessage('a'); + const args = getPassedArgs(testClient.captureMessage); + + expect(args[2].event_id).toBeTruthy(); + }); + + test('should keep event_id from hint', () => { + const testClient = makeClient(); + const hub = new Hub(testClient); + const id = Math.random().toString(); + + hub.captureMessage('a', undefined, { event_id: id }); + const args = getPassedArgs(testClient.captureMessage); + + expect(args[2].event_id).toBe(id); + }); + + test('should generate hint if not provided in the call', () => { + const testClient = makeClient(); + const hub = new Hub(testClient); + + hub.captureMessage('foo'); + const args = getPassedArgs(testClient.captureMessage); + + expect(args[2].originalException).toBe('foo'); + expect(args[2].syntheticException).toBeInstanceOf(Error); + expect(args[2].syntheticException.message).toBe('foo'); + }); + }); + + describe('captureEvent', () => { + test('simple', () => { + const event: Event = { + extra: { b: 3 }, + }; + const testClient = makeClient(); + const hub = new Hub(testClient); + + hub.captureEvent(event); + const args = getPassedArgs(testClient.captureEvent); + + expect(args[0]).toBe(event); + }); + + test('should set event_id in hint', () => { + const event: Event = { + extra: { b: 3 }, + }; + const testClient = makeClient(); + const hub = new Hub(testClient); + + hub.captureEvent(event); + const args = getPassedArgs(testClient.captureEvent); + + expect(args[1].event_id).toBeTruthy(); + }); + + test('should keep event_id from hint', () => { + const event: Event = { + extra: { b: 3 }, + }; + const testClient = makeClient(); + const hub = new Hub(testClient); + const id = Math.random().toString(); + + hub.captureEvent(event, { event_id: id }); + const args = getPassedArgs(testClient.captureEvent); + + expect(args[1].event_id).toBe(id); + }); + + test('sets lastEventId', () => { + const event: Event = { + extra: { b: 3 }, + }; + const testClient = makeClient(); + const hub = new Hub(testClient); + + hub.captureEvent(event); + const args = getPassedArgs(testClient.captureEvent); + + expect(args[1].event_id).toEqual(hub.lastEventId()); + }); + + const eventTypesToIgnoreLastEventId: EventType[] = ['transaction', 'replay_event']; + it.each(eventTypesToIgnoreLastEventId)('eventType %s does not set lastEventId', eventType => { + const event: Event = { + extra: { b: 3 }, + type: eventType, + }; + const testClient = makeClient(); + const hub = new Hub(testClient); + + hub.captureEvent(event); + const args = getPassedArgs(testClient.captureEvent); + + expect(args[1].event_id).not.toEqual(hub.lastEventId()); + }); + }); + + test('lastEventId should be the same as last created', () => { + const event: Event = { + extra: { b: 3 }, + }; + const hub = new Hub(); + const eventId = hub.captureEvent(event); + expect(eventId).toBe(hub.lastEventId()); + }); + + describe('run', () => { + test('simple', () => { + const currentHub = getCurrentHub(); + const myScope = new Scope(); + const myClient: any = { a: 'b' }; + myScope.setExtra('a', 'b'); + const myHub = new Hub(myClient, myScope); + myHub.run(hub => { + expect(hub.getScope()).toBe(myScope); + expect(hub.getClient()).toBe(myClient); + expect(hub).toBe(getCurrentHub()); + }); + expect(currentHub).toBe(getCurrentHub()); + }); + + test('should bubble up exceptions', () => { + const hub = new Hub(); + const error = new Error('test'); + expect(() => { + hub.run(() => { + throw error; + }); + }).toThrow(error); + }); + }); + + describe('breadcrumbs', () => { + test('withScope', () => { + expect.assertions(6); + const hub = new Hub(clientFn); + hub.addBreadcrumb({ message: 'My Breadcrumb' }); + hub.withScope(scope => { + scope.addBreadcrumb({ message: 'scope breadcrumb' }); + const event: Event = {}; + void scope + .applyToEvent(event) + .then((appliedEvent: Event | null) => { + expect(appliedEvent).toBeTruthy(); + expect(appliedEvent!.breadcrumbs).toHaveLength(2); + expect(appliedEvent!.breadcrumbs![0].message).toEqual('My Breadcrumb'); + expect(appliedEvent!.breadcrumbs![0]).toHaveProperty('timestamp'); + expect(appliedEvent!.breadcrumbs![1].message).toEqual('scope breadcrumb'); + expect(appliedEvent!.breadcrumbs![1]).toHaveProperty('timestamp'); + }) + .then(null, e => { + // eslint-disable-next-line no-console + console.error(e); + }); + }); + }); + }); + + describe('shouldSendDefaultPii()', () => { + test('return false if sendDefaultPii is not set', () => { + const testClient = makeClient(); + const hub = new Hub(testClient); + expect(hub.shouldSendDefaultPii()).toBe(false); + }); + + test('return true if sendDefaultPii is set in the client options', () => { + const testClient = makeClient(); + testClient.getOptions = () => { + return { + sendDefaultPii: true, + } as unknown as any; + }; + const hub = new Hub(testClient); + expect(hub.shouldSendDefaultPii()).toBe(true); + }); + }); + + describe('session APIs', () => { + beforeEach(() => { + const testClient = makeClient(); + const hub = new Hub(testClient); + makeMain(hub); + }); + + describe('startSession', () => { + it('starts a session', () => { + const testClient = makeClient(); + const hub = new Hub(testClient); + makeMain(hub); + const session = hub.startSession(); + + expect(session).toMatchObject({ + status: 'ok', + errors: 0, + init: true, + environment: 'production', + ignoreDuration: false, + sid: expect.any(String), + did: undefined, + timestamp: expect.any(Number), + started: expect.any(Number), + duration: expect.any(Number), + toJSON: expect.any(Function), + }); + }); + + it('ends a previously active session and removes it from the scope', () => { + const testClient = makeClient(); + const hub = new Hub(testClient); + makeMain(hub); + + const session1 = hub.startSession(); + + expect(session1.status).toBe('ok'); + expect(getCurrentScope().getSession()).toBe(session1); + + const session2 = hub.startSession(); + + expect(session2.status).toBe('ok'); + expect(session1.status).toBe('exited'); + expect(getCurrentHub().getScope().getSession()).toBe(session2); + }); + }); + + describe('endSession', () => { + it('ends a session and removes it from the scope', () => { + const testClient = makeClient(); + const hub = new Hub(testClient); + makeMain(hub); + + const session = hub.startSession(); + + expect(session.status).toBe('ok'); + expect(getCurrentScope().getSession()).toBe(session); + + hub.endSession(); + + expect(session.status).toBe('exited'); + expect(getCurrentHub().getScope().getSession()).toBe(undefined); + }); + }); + + describe('captureSession', () => { + it('captures a session without ending it by default', () => { + const testClient = makeClient(); + const hub = new Hub(testClient); + makeMain(hub); + + const session = hub.startSession(); + + expect(session.status).toBe('ok'); + expect(getCurrentScope().getSession()).toBe(session); + + hub.captureSession(); + + expect(testClient.captureSession).toHaveBeenCalledWith(expect.objectContaining({ status: 'ok' })); + }); + + it('captures a session and ends it if end is `true`', () => { + const testClient = makeClient(); + const hub = new Hub(testClient); + makeMain(hub); + + const session = hub.startSession(); + + expect(session.status).toBe('ok'); + expect(hub.getScope().getSession()).toBe(session); + + hub.captureSession(true); + + expect(testClient.captureSession).toHaveBeenCalledWith(expect.objectContaining({ status: 'exited' })); + }); + }); + }); +}); diff --git a/packages/nextjs/README.md b/packages/nextjs/README.md index f4da13beb8b8..26322828afe4 100644 --- a/packages/nextjs/README.md +++ b/packages/nextjs/README.md @@ -53,12 +53,9 @@ To set context information or send manual events, use the exported functions of import * as Sentry from '@sentry/nextjs'; // Set user information, as well as tags and further extras -Sentry.configureScope(scope => { - scope.setExtra('battery', 0.7); - scope.setTag('user_mode', 'admin'); - scope.setUser({ id: '4711' }); - // scope.clear(); -}); +Sentry.setExtra('battery', 0.7); +Sentry.setTag('user_mode', 'admin'); +Sentry.setUser({ id: '4711' }); // Add a breadcrumb for future events Sentry.addBreadcrumb({ diff --git a/packages/nextjs/vercel/install-sentry-from-branch.sh b/packages/nextjs/vercel/install-sentry-from-branch.sh index 84a0f59eb7c3..b36983b898dc 100644 --- a/packages/nextjs/vercel/install-sentry-from-branch.sh +++ b/packages/nextjs/vercel/install-sentry-from-branch.sh @@ -71,14 +71,12 @@ Error.stackTraceLimit = Infinity; SDK_COMMIT_MESSAGE=$(cd sentry-javascript && git log --format="%C(auto)%s" | head -n 1) CONFIGURE_SCOPE_CODE=" -Sentry.configureScope(scope => { - if (process.env.VERCEL) { - scope.setTag('vercel', true); - } - scope.setTag('commitMessage', process.env.VERCEL_GIT_COMMIT_MESSAGE); - scope.setTag('sdkCommitMessage', \"$SDK_COMMIT_MESSAGE\"); -}); - " +if (process.env.VERCEL) { + Sentry.setTag('vercel', true); +} +Sentry.setTag('commitMessage', process.env.VERCEL_GIT_COMMIT_MESSAGE); +Sentry.setTag('sdkCommitMessage', \"$SDK_COMMIT_MESSAGE\"); +" echo "$INFINITE_STACKTRACE_CODE" "$CONFIGURE_SCOPE_CODE" >>sentry.server.config.js echo "$INFINITE_STACKTRACE_CODE" "$CONFIGURE_SCOPE_CODE" >>sentry.client.config.js diff --git a/packages/node-experimental/src/index.ts b/packages/node-experimental/src/index.ts index 5b19697732a8..1f2870f287f9 100644 --- a/packages/node-experimental/src/index.ts +++ b/packages/node-experimental/src/index.ts @@ -45,8 +45,6 @@ export { withScope, withIsolationScope, withActiveSpan, - // eslint-disable-next-line deprecation/deprecation - configureScope, getCurrentScope, getGlobalScope, getIsolationScope, diff --git a/packages/node-experimental/src/sdk/api.ts b/packages/node-experimental/src/sdk/api.ts index f1958ba883b4..be8867dcd8f0 100644 --- a/packages/node-experimental/src/sdk/api.ts +++ b/packages/node-experimental/src/sdk/api.ts @@ -97,11 +97,20 @@ export function withIsolationScope(callback: (isolationScope: Scope) => T): T } /** +<<<<<<< HEAD * Configure the current scope. * @deprecated Use `getCurrentScope()` instead. */ export function configureScope(callback: (scope: Scope) => void): void { callback(getCurrentScope()); +======= + * Get the ID of the last sent error event. + * @deprecated This function will be removed in the next major version of the Sentry SDK. + */ +export function lastEventId(): string | undefined { + // eslint-disable-next-line deprecation/deprecation + return getCurrentScope().lastEventId(); +>>>>>>> 63597e2af (feat(v8): Remove deprecated configureScope call) } /** Record an exception and send it to Sentry. */ diff --git a/packages/node-experimental/src/sdk/hub.ts b/packages/node-experimental/src/sdk/hub.ts index 0a5da5c09e0c..f3cd1f2a7d13 100644 --- a/packages/node-experimental/src/sdk/hub.ts +++ b/packages/node-experimental/src/sdk/hub.ts @@ -13,7 +13,6 @@ import { endSession, startSession } from '@sentry/core'; import { addBreadcrumb, captureEvent, - configureScope, getClient, getCurrentScope, setContext, @@ -77,8 +76,6 @@ export function getCurrentHub(): Hub { setExtra, setExtras, setContext, - // eslint-disable-next-line deprecation/deprecation - configureScope: configureScope, run(callback: (hub: Hub) => void): void { // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/packages/node/README.md b/packages/node/README.md index 0fdf96a4aa34..bd588bbbc34e 100644 --- a/packages/node/README.md +++ b/packages/node/README.md @@ -37,12 +37,9 @@ functions will not perform any action before you have called `init()`: ```javascript // Set user information, as well as tags and further extras -Sentry.configureScope(scope => { - scope.setExtra('battery', 0.7); - scope.setTag('user_mode', 'admin'); - scope.setUser({ id: '4711' }); - // scope.clear(); -}); +Sentry.setExtra('battery', 0.7); +Sentry.setTag('user_mode', 'admin'); +Sentry.setUser({ id: '4711' }); // Add a breadcrumb for future events Sentry.addBreadcrumb({ diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index ac7c54a0cf60..d555afee3e1d 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -30,8 +30,6 @@ export { captureEvent, captureMessage, close, - // eslint-disable-next-line deprecation/deprecation - configureScope, createTransport, // eslint-disable-next-line deprecation/deprecation extractTraceparentData, diff --git a/packages/node/src/sdk.ts b/packages/node/src/sdk.ts index 01825a404e20..14aff2fef1fe 100644 --- a/packages/node/src/sdk.ts +++ b/packages/node/src/sdk.ts @@ -93,17 +93,6 @@ export function getDefaultIntegrations(_options: Options): Integration[] { * @example * ``` * - * const { configureScope } = require('@sentry/node'); - * configureScope((scope: Scope) => { - * scope.setExtra({ battery: 0.7 }); - * scope.setTag({ user_mode: 'admin' }); - * scope.setUser({ id: '4711' }); - * }); - * ``` - * - * @example - * ``` - * * const { addBreadcrumb } = require('@sentry/node'); * addBreadcrumb({ * message: 'My Breadcrumb', diff --git a/packages/node/test/manual/express-scope-separation/start.js b/packages/node/test/manual/express-scope-separation/start.js index 63a73eba2dd2..cfe8df9d2427 100644 --- a/packages/node/test/manual/express-scope-separation/start.js +++ b/packages/node/test/manual/express-scope-separation/start.js @@ -64,32 +64,24 @@ Sentry.init({ }, }); -Sentry.configureScope(scope => { - scope.setTag('global', 'wat'); -}); +Sentry.setTag('global', 'wat'); app.use(Sentry.Handlers.requestHandler()); app.get('/foo', req => { - Sentry.configureScope(scope => { - scope.setTag('foo', 'wat'); - }); + Sentry.setTag('foo', 'wat'); throw new Error('foo'); }); app.get('/bar', req => { - Sentry.configureScope(scope => { - scope.setTag('bar', 'wat'); - }); + Sentry.setTag('bar', 'wat'); throw new Error('bar'); }); app.get('/baz', req => { - Sentry.configureScope(scope => { - scope.setTag('baz', 'wat'); - }); + Sentry.setTag('baz', 'wat'); throw new Error('baz'); }); diff --git a/packages/node/test/manual/memory-leak/express-patient.js b/packages/node/test/manual/memory-leak/express-patient.js index 7a677a442972..ad9ed267bde4 100644 --- a/packages/node/test/manual/memory-leak/express-patient.js +++ b/packages/node/test/manual/memory-leak/express-patient.js @@ -41,9 +41,7 @@ app.use((req, res, next) => { }); app.get('/context/basic', (req, res, next) => { - Sentry.configureScope(scope => { - scope.setExtra('example', 'hey look we set some example context data yay'); - }); + Sentry.setExtra('example', 'hey look we set some example context data yay'); res.textToSend = 'hello there! we set some stuff to the context'; next(); diff --git a/packages/node/test/manual/webpack-async-context/index.js b/packages/node/test/manual/webpack-async-context/index.js index 27f3fe0376ef..c8a9de6e7d41 100644 --- a/packages/node/test/manual/webpack-async-context/index.js +++ b/packages/node/test/manual/webpack-async-context/index.js @@ -43,15 +43,10 @@ Sentry.init({ }, }); -Sentry.configureScope(scope => { - scope.setTag('a', 'b'); -}); +Sentry.setTag('a', 'b'); Sentry.runWithAsyncContext(() => { - Sentry.configureScope(scope => { - scope.setTag('a', 'x'); - scope.setTag('b', 'c'); - }); + Sentry.setTag('a', 'x'); Sentry.captureMessage('inside'); }); diff --git a/packages/remix/README.md b/packages/remix/README.md index ae2dfbeff53a..7914555728f1 100644 --- a/packages/remix/README.md +++ b/packages/remix/README.md @@ -113,12 +113,9 @@ To set context information or send manual events, use the exported functions of import * as Sentry from '@sentry/remix'; // Set user information, as well as tags and further extras -Sentry.configureScope(scope => { - scope.setExtra('battery', 0.7); - scope.setTag('user_mode', 'admin'); - scope.setUser({ id: '4711' }); - // scope.clear(); -}); +Sentry.setExtra('battery', 0.7); +Sentry.setTag('user_mode', 'admin'); +Sentry.setUser({ id: '4711' }); // Add a breadcrumb for future events Sentry.addBreadcrumb({ diff --git a/packages/remix/src/index.server.ts b/packages/remix/src/index.server.ts index 6d5a117f965f..cbcb9533ec95 100644 --- a/packages/remix/src/index.server.ts +++ b/packages/remix/src/index.server.ts @@ -21,8 +21,6 @@ export { captureException, captureEvent, captureMessage, - // eslint-disable-next-line deprecation/deprecation - configureScope, createTransport, // eslint-disable-next-line deprecation/deprecation extractTraceparentData, diff --git a/packages/serverless/src/index.ts b/packages/serverless/src/index.ts index 0c6c5b7864ba..74edc639d49b 100644 --- a/packages/serverless/src/index.ts +++ b/packages/serverless/src/index.ts @@ -25,8 +25,6 @@ export { captureMessage, captureCheckIn, withMonitor, - // eslint-disable-next-line deprecation/deprecation - configureScope, createTransport, // eslint-disable-next-line deprecation/deprecation getActiveTransaction, diff --git a/packages/sveltekit/src/server/index.ts b/packages/sveltekit/src/server/index.ts index 9115d3008ad9..b85ee1923752 100644 --- a/packages/sveltekit/src/server/index.ts +++ b/packages/sveltekit/src/server/index.ts @@ -14,8 +14,6 @@ export { captureMessage, captureCheckIn, withMonitor, - // eslint-disable-next-line deprecation/deprecation - configureScope, createTransport, // eslint-disable-next-line deprecation/deprecation extractTraceparentData, diff --git a/packages/types/src/hub.ts b/packages/types/src/hub.ts index 346cba7e77b0..36c7403af2d5 100644 --- a/packages/types/src/hub.ts +++ b/packages/types/src/hub.ts @@ -197,14 +197,6 @@ export interface Hub { */ setContext(name: string, context: { [key: string]: any } | null): void; - /** - * Callback to set context information onto the scope. - * - * @param callback Callback function that receives Scope. - * @deprecated Use `getScope()` directly. - */ - configureScope(callback: (scope: Scope) => void): void; - /** * For the duration of the callback, this hub will be set as the global current Hub. * This function is useful if you want to run your own client and hook into an already initialized one diff --git a/packages/vercel-edge/README.md b/packages/vercel-edge/README.md index e6e893bc5044..5f4744ac3c9d 100644 --- a/packages/vercel-edge/README.md +++ b/packages/vercel-edge/README.md @@ -39,12 +39,9 @@ functions will not perform any action before you have called `init()`: ```javascript // Set user information, as well as tags and further extras -Sentry.configureScope(scope => { - scope.setExtra('battery', 0.7); - scope.setTag('user_mode', 'admin'); - scope.setUser({ id: '4711' }); - // scope.clear(); -}); +Sentry.setExtra('battery', 0.7); +Sentry.setTag('user_mode', 'admin'); +Sentry.setUser({ id: '4711' }); // Add a breadcrumb for future events Sentry.addBreadcrumb({ diff --git a/packages/vercel-edge/src/index.ts b/packages/vercel-edge/src/index.ts index dcd6686d0562..97d5ceb6b730 100644 --- a/packages/vercel-edge/src/index.ts +++ b/packages/vercel-edge/src/index.ts @@ -30,8 +30,6 @@ export { captureEvent, captureMessage, close, - // eslint-disable-next-line deprecation/deprecation - configureScope, createTransport, // eslint-disable-next-line deprecation/deprecation extractTraceparentData, From b3a5d1ee5a32f7c586b177105dd2dc412714ea1d Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Wed, 7 Feb 2024 18:34:08 -0500 Subject: [PATCH 2/5] lint fix --- MIGRATION.md | 3 ++- packages/browser/test/package/test-code.js | 2 +- packages/hub/test/exports.test.ts | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index 630a0af2d00d..bee9b99087b4 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -35,7 +35,8 @@ to `anrIntegration`, the new integration for ANR detection. ## Removal of `Sentry.configureScope`. -The top level `Sentry.configureScope` function has been removed. Instead, you should use the `Sentry.getCurrentScope()` to access and mutate the current scope. +The top level `Sentry.configureScope` function has been removed. Instead, you should use the `Sentry.getCurrentScope()` +to access and mutate the current scope. ## Other changes diff --git a/packages/browser/test/package/test-code.js b/packages/browser/test/package/test-code.js index 309391bf68c1..513009e945b5 100644 --- a/packages/browser/test/package/test-code.js +++ b/packages/browser/test/package/test-code.js @@ -17,7 +17,7 @@ Sentry.init({ }); // Configure -const scope = Sentry.getCurrentScope() +const scope = Sentry.getCurrentScope(); scope.setExtra('foo', 'bar'); scope.setFingerprint('foo'); scope.setLevel('warning'); diff --git a/packages/hub/test/exports.test.ts b/packages/hub/test/exports.test.ts index 15b85c376062..4c7e37468845 100644 --- a/packages/hub/test/exports.test.ts +++ b/packages/hub/test/exports.test.ts @@ -1,7 +1,6 @@ /* eslint-disable deprecation/deprecation */ import { getCurrentScope } from '@sentry/core'; -import type { Scope } from '../src'; import { captureEvent, captureException, From ac907839a22c91f438aa7f2e020be7888886883b Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Thu, 8 Feb 2024 09:07:18 -0500 Subject: [PATCH 3/5] delete hub for real --- packages/hub/src/index.ts | 152 --------- packages/hub/test/exports.test.ts | 250 -------------- packages/hub/test/hub.test.ts | 538 ------------------------------ 3 files changed, 940 deletions(-) delete mode 100644 packages/hub/src/index.ts delete mode 100644 packages/hub/test/exports.test.ts delete mode 100644 packages/hub/test/hub.test.ts diff --git a/packages/hub/src/index.ts b/packages/hub/src/index.ts deleted file mode 100644 index f54256ee2a64..000000000000 --- a/packages/hub/src/index.ts +++ /dev/null @@ -1,152 +0,0 @@ -export type { Carrier, Layer } from '@sentry/core'; - -import { - Hub as HubCore, - Scope as ScopeCore, - SessionFlusher as SessionFlusherCore, - addBreadcrumb as addBreadcrumbCore, - addGlobalEventProcessor as addGlobalEventProcessorCore, - captureEvent as captureEventCore, - captureException as captureExceptionCore, - captureMessage as captureMessageCore, - closeSession as closeSessionCore, - getCurrentHub as getCurrentHubCore, - getHubFromCarrier as getHubFromCarrierCore, - getMainCarrier as getMainCarrierCore, - makeMain as makeMainCore, - makeSession as makeSessionCore, - setContext as setContextCore, - setExtra as setExtraCore, - setExtras as setExtrasCore, - setHubOnCarrier as setHubOnCarrierCore, - setTag as setTagCore, - setTags as setTagsCore, - setUser as setUserCore, - startTransaction as startTransactionCore, - updateSession as updateSessionCore, - withScope as withScopeCore, -} from '@sentry/core'; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8 - */ -export class Hub extends HubCore {} - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8 - */ -export class Scope extends ScopeCore {} - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -// eslint-disable-next-line deprecation/deprecation -export const getCurrentHub = getCurrentHubCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ - -export const addGlobalEventProcessor = addGlobalEventProcessorCore; // eslint-disable-line deprecation/deprecation - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const getHubFromCarrier = getHubFromCarrierCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const getMainCarrier = getMainCarrierCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -// eslint-disable-next-line deprecation/deprecation -export const makeMain = makeMainCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const setHubOnCarrier = setHubOnCarrierCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const SessionFlusher = SessionFlusherCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const closeSession = closeSessionCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const makeSession = makeSessionCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const updateSession = updateSessionCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const addBreadcrumb = addBreadcrumbCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const captureException = captureExceptionCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const captureEvent = captureEventCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const captureMessage = captureMessageCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -// eslint-disable-next-line deprecation/deprecation -export const startTransaction = startTransactionCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const setContext = setContextCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const setExtra = setExtraCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const setExtras = setExtrasCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const setTag = setTagCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const setTags = setTagsCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const setUser = setUserCore; - -/** - * @deprecated This export has moved to @sentry/core. The @sentry/hub package will be removed in v8. - */ -export const withScope = withScopeCore; diff --git a/packages/hub/test/exports.test.ts b/packages/hub/test/exports.test.ts deleted file mode 100644 index 4c7e37468845..000000000000 --- a/packages/hub/test/exports.test.ts +++ /dev/null @@ -1,250 +0,0 @@ -/* eslint-disable deprecation/deprecation */ - -import { getCurrentScope } from '@sentry/core'; -import { - captureEvent, - captureException, - captureMessage, - getCurrentHub, - getHubFromCarrier, - setContext, - setExtra, - setExtras, - setTag, - setTags, - setUser, - withScope, -} from '../src'; - -export class TestClient { - public static instance?: TestClient; - - public constructor(public options: Record) { - TestClient.instance = this; - } - - public mySecretPublicMethod(str: string): string { - return `secret: ${str}`; - } -} - -export class TestClient2 {} - -export function init(options: Record): void { - getCurrentHub().bindClient(new TestClient(options) as any); -} - -// eslint-disable-next-line no-var -declare var global: any; - -describe('Top Level API', () => { - beforeEach(() => { - global.__SENTRY__ = { - hub: undefined, - }; - }); - - describe('Capture', () => { - test('Return an event_id', () => { - const client: any = { - captureException: jest.fn(async () => Promise.resolve()), - }; - getCurrentHub().withScope(() => { - getCurrentHub().bindClient(client); - const e = new Error('test exception'); - const eventId = captureException(e); - expect(eventId).toBeTruthy(); - }); - }); - - test('Exception', () => { - const client: any = { - captureException: jest.fn(async () => Promise.resolve()), - }; - getCurrentHub().withScope(() => { - getCurrentHub().bindClient(client); - const e = new Error('test exception'); - captureException(e); - expect(client.captureException.mock.calls[0][0]).toBe(e); - }); - }); - - test('Exception with explicit scope', () => { - const client: any = { - captureException: jest.fn(async () => Promise.resolve()), - }; - getCurrentHub().withScope(() => { - getCurrentHub().bindClient(client); - const e = new Error('test exception'); - const captureContext = { extra: { foo: 'wat' } }; - captureException(e, captureContext); - expect(client.captureException.mock.calls[0][0]).toBe(e); - expect(client.captureException.mock.calls[0][1].captureContext).toEqual(captureContext); - }); - }); - - test('Message', () => { - const client: any = { captureMessage: jest.fn(async () => Promise.resolve()) }; - getCurrentHub().withScope(() => { - getCurrentHub().bindClient(client); - const message = 'yo'; - captureMessage(message); - expect(client.captureMessage.mock.calls[0][0]).toBe(message); - }); - }); - - test('Message with explicit scope', () => { - const client: any = { captureMessage: jest.fn(async () => Promise.resolve()) }; - getCurrentHub().withScope(() => { - getCurrentHub().bindClient(client); - const message = 'yo'; - const captureContext = { extra: { foo: 'wat' } }; - captureMessage(message, captureContext); - expect(client.captureMessage.mock.calls[0][0]).toBe(message); - // Skip the level if explicit content is provided - expect(client.captureMessage.mock.calls[0][1]).toBe(undefined); - expect(client.captureMessage.mock.calls[0][2].captureContext).toBe(captureContext); - }); - }); - - // NOTE: We left custom level as 2nd argument to not break the API. Should be removed and unified in v6. - // TODO: Before we release v8, check if this is still a thing - test('Message with custom level', () => { - const client: any = { captureMessage: jest.fn(async () => Promise.resolve()) }; - getCurrentHub().withScope(() => { - getCurrentHub().bindClient(client); - const message = 'yo'; - const level = 'warning'; - captureMessage(message, level); - expect(client.captureMessage.mock.calls[0][0]).toBe(message); - expect(client.captureMessage.mock.calls[0][1]).toBe('warning'); - }); - }); - - test('Event', () => { - const client: any = { captureEvent: jest.fn(async () => Promise.resolve()) }; - getCurrentHub().withScope(() => { - getCurrentHub().bindClient(client); - const e = { message: 'test' }; - captureEvent(e); - expect(client.captureEvent.mock.calls[0][0]).toBe(e); - }); - }); - }); - - test('Clear Scope', () => { - const client: any = new TestClient({}); - getCurrentHub().withScope(() => { - getCurrentHub().bindClient(client); - expect(global.__SENTRY__.hub._stack.length).toBe(2); - getCurrentScope().setUser({ id: '1234' }); - expect(global.__SENTRY__.hub._stack[1].scope._user).toEqual({ - id: '1234', - }); - getCurrentScope().clear(); - expect(global.__SENTRY__.hub._stack[1].scope._user).toEqual({}); - }); - }); - - test('returns undefined before binding a client', () => { - expect(getCurrentHub().getClient()).toBeUndefined(); - }); - - test('returns the bound client', () => { - init({}); - expect(getCurrentHub().getClient()).toBe(TestClient.instance); - }); - - test('does not throw an error when pushing different clients', () => { - init({}); - expect(() => { - getCurrentHub().withScope(() => { - getCurrentHub().bindClient(new TestClient2() as any); - }); - }).not.toThrow(); - }); - - test('does not throw an error when pushing same clients', () => { - init({}); - expect(() => { - getCurrentHub().withScope(() => { - getCurrentHub().bindClient(new TestClient({}) as any); - }); - }).not.toThrow(); - }); - - test('custom carrier', () => { - const iAmSomeGlobalVarTheUserHasToManage = { - state: {}, - }; - const hub = getHubFromCarrier(iAmSomeGlobalVarTheUserHasToManage.state); - hub.pushScope(); - hub.bindClient(new TestClient({}) as any); - hub.getScope().setUser({ id: '1234' }); - expect((iAmSomeGlobalVarTheUserHasToManage.state as any).__SENTRY__.hub._stack[1].scope._user).toEqual({ - id: '1234', - }); - hub.popScope(); - expect((iAmSomeGlobalVarTheUserHasToManage.state as any).__SENTRY__.hub._stack[1]).toBeUndefined(); - }); - - test('withScope', () => { - withScope(scope => { - scope.setLevel('warning'); - scope.setFingerprint(['1']); - withScope(scope2 => { - scope2.setLevel('info'); - scope2.setFingerprint(['2']); - withScope(scope3 => { - scope3.clear(); - expect(global.__SENTRY__.hub._stack[1].scope._level).toEqual('warning'); - expect(global.__SENTRY__.hub._stack[1].scope._fingerprint).toEqual(['1']); - expect(global.__SENTRY__.hub._stack[2].scope._level).toEqual('info'); - expect(global.__SENTRY__.hub._stack[2].scope._fingerprint).toEqual(['2']); - expect(global.__SENTRY__.hub._stack[3].scope._level).toBeUndefined(); - }); - expect(global.__SENTRY__.hub._stack).toHaveLength(3); - }); - expect(global.__SENTRY__.hub._stack).toHaveLength(2); - }); - expect(global.__SENTRY__.hub._stack).toHaveLength(1); - }); - - test('setExtras', () => { - init({}); - setExtras({ a: 'b' }); - expect(global.__SENTRY__.hub._stack[0].scope._extra).toEqual({ a: 'b' }); - }); - - test('setTags', () => { - init({}); - setTags({ a: 'b' }); - expect(global.__SENTRY__.hub._stack[0].scope._tags).toEqual({ a: 'b' }); - }); - - test('setExtra', () => { - init({}); - setExtra('a', 'b'); - // biome-ignore format: Follow-up for prettier - expect(global.__SENTRY__.hub._stack[0].scope._extra).toEqual({ 'a': 'b' }); - }); - - test('setTag', () => { - init({}); - setTag('a', 'b'); - // biome-ignore format: Follow-up for prettier - expect(global.__SENTRY__.hub._stack[0].scope._tags).toEqual({ 'a': 'b' }); - }); - - test('setUser', () => { - init({}); - setUser({ id: 'b' }); - expect(global.__SENTRY__.hub._stack[0].scope._user).toEqual({ id: 'b' }); - }); - - test('setContext', () => { - init({}); - setContext('test', { id: 'b' }); - expect(global.__SENTRY__.hub._stack[0].scope._contexts).toEqual({ test: { id: 'b' } }); - }); -}); diff --git a/packages/hub/test/hub.test.ts b/packages/hub/test/hub.test.ts deleted file mode 100644 index e320d95c0f0f..000000000000 --- a/packages/hub/test/hub.test.ts +++ /dev/null @@ -1,538 +0,0 @@ -/* eslint-disable @typescript-eslint/unbound-method */ -/* eslint-disable deprecation/deprecation */ - -import type { Client, Event, EventType } from '@sentry/types'; - -import { getCurrentScope, makeMain } from '@sentry/core'; -import { Hub, Scope, getCurrentHub } from '../src'; - -const clientFn: any = jest.fn(); - -function makeClient() { - return { - getOptions: jest.fn(), - captureEvent: jest.fn(), - captureException: jest.fn(), - close: jest.fn(), - flush: jest.fn(), - getDsn: jest.fn(), - getIntegration: jest.fn(), - setupIntegrations: jest.fn(), - captureMessage: jest.fn(), - captureSession: jest.fn(), - } as unknown as Client; -} - -/** - * Return an array containing the arguments passed to the given mocked or spied-upon function. - * - * By default, the args passed to the first call of the function are returned, but it is also possible to retrieve the - * nth call by passing `callIndex`. If the function wasn't called, an error message is returned instead. - */ -function getPassedArgs(mock: (...args: any[]) => any, callIndex: number = 0): any[] { - const asMock = mock as jest.MockedFunction<(...args: any[]) => any>; - return asMock.mock.calls[callIndex] || ["Error: Function wasn't called."]; -} - -describe('Hub', () => { - afterEach(() => { - jest.restoreAllMocks(); - jest.useRealTimers(); - }); - - test('call bindClient with provided client when constructing new instance', () => { - const testClient = makeClient(); - const hub = new Hub(testClient); - expect(hub.getClient()).toBe(testClient); - }); - - test('push process into stack', () => { - const hub = new Hub(); - expect(hub.getStack()).toHaveLength(1); - }); - - test('pass in filled layer', () => { - const hub = new Hub(clientFn); - expect(hub.getStack()).toHaveLength(1); - }); - - test('isOlderThan', () => { - const hub = new Hub(); - expect(hub.isOlderThan(0)).toBeFalsy(); - }); - - describe('pushScope', () => { - test('simple', () => { - const localScope = new Scope(); - localScope.setExtra('a', 'b'); - const hub = new Hub(undefined, localScope); - hub.pushScope(); - expect(hub.getStack()).toHaveLength(2); - expect(hub.getStack()[1].scope).not.toBe(localScope); - expect((hub.getStack()[1].scope as Scope as any)._extra).toEqual({ a: 'b' }); - }); - - test('inherit client', () => { - const testClient: any = { bla: 'a' }; - const hub = new Hub(testClient); - hub.pushScope(); - expect(hub.getStack()).toHaveLength(2); - expect(hub.getStack()[1].client).toBe(testClient); - }); - - describe('bindClient', () => { - test('should override current client', () => { - const testClient = makeClient(); - const nextClient = makeClient(); - const hub = new Hub(testClient); - hub.bindClient(nextClient); - expect(hub.getStack()).toHaveLength(1); - expect(hub.getStack()[0].client).toBe(nextClient); - }); - - test('should bind client to the top-most layer', () => { - const testClient: any = { bla: 'a' }; - const nextClient: any = { foo: 'bar' }; - const hub = new Hub(testClient); - hub.pushScope(); - hub.bindClient(nextClient); - expect(hub.getStack()).toHaveLength(2); - expect(hub.getStack()[0].client).toBe(testClient); - expect(hub.getStack()[1].client).toBe(nextClient); - }); - - test('should call setupIntegration method of passed client', () => { - const testClient = makeClient(); - const nextClient = makeClient(); - const hub = new Hub(testClient); - hub.bindClient(nextClient); - expect(testClient.setupIntegrations).toHaveBeenCalled(); - expect(nextClient.setupIntegrations).toHaveBeenCalled(); - }); - }); - - test('inherit processors', async () => { - expect.assertions(1); - const event: Event = { - extra: { b: 3 }, - }; - const localScope = new Scope(); - localScope.setExtra('a', 'b'); - const hub = new Hub({ a: 'b' } as any, localScope); - - localScope.addEventProcessor(async (processedEvent: Event) => { - processedEvent.dist = '1'; - return processedEvent; - }); - - hub.pushScope(); - const pushedScope = hub.getStackTop().scope; - - return pushedScope!.applyToEvent(event).then(final => { - expect(final!.dist).toEqual('1'); - }); - }); - }); - - test('popScope', () => { - const hub = new Hub(); - hub.pushScope(); - expect(hub.getStack()).toHaveLength(2); - hub.popScope(); - expect(hub.getStack()).toHaveLength(1); - }); - - describe('withScope', () => { - let hub: Hub; - - beforeEach(() => { - hub = new Hub(); - }); - - test('simple', () => { - hub.withScope(() => { - expect(hub.getStack()).toHaveLength(2); - }); - expect(hub.getStack()).toHaveLength(1); - }); - - test('bindClient', () => { - const testClient: any = { bla: 'a' }; - hub.withScope(() => { - hub.bindClient(testClient); - expect(hub.getStack()).toHaveLength(2); - expect(hub.getStack()[1].client).toBe(testClient); - }); - expect(hub.getStack()).toHaveLength(1); - }); - - test('should bubble up exceptions', () => { - const error = new Error('test'); - expect(() => { - hub.withScope(() => { - throw error; - }); - }).toThrow(error); - }); - }); - - test('getCurrentClient', () => { - const testClient: any = { bla: 'a' }; - const hub = new Hub(testClient); - expect(hub.getClient()).toBe(testClient); - }); - - test('getStack', () => { - const client: any = { a: 'b' }; - const hub = new Hub(client); - expect(hub.getStack()[0].client).toBe(client); - }); - - test('getStackTop', () => { - const testClient: any = { bla: 'a' }; - const hub = new Hub(); - hub.pushScope(); - hub.pushScope(); - hub.bindClient(testClient); - expect(hub.getStackTop().client).toEqual({ bla: 'a' }); - }); - - describe('captureException', () => { - test('simple', () => { - const testClient = makeClient(); - const hub = new Hub(testClient); - - hub.captureException('a'); - const args = getPassedArgs(testClient.captureException); - - expect(args[0]).toBe('a'); - }); - - test('should set event_id in hint', () => { - const testClient = makeClient(); - const hub = new Hub(testClient); - - hub.captureException('a'); - const args = getPassedArgs(testClient.captureException); - - expect(args[1].event_id).toBeTruthy(); - }); - - test('should keep event_id from hint', () => { - const testClient = makeClient(); - const hub = new Hub(testClient); - const id = Math.random().toString(); - - hub.captureException('a', { event_id: id }); - const args = getPassedArgs(testClient.captureException); - - expect(args[1].event_id).toBe(id); - }); - - test('should generate hint if not provided in the call', () => { - const testClient = makeClient(); - const hub = new Hub(testClient); - const ex = new Error('foo'); - - hub.captureException(ex); - const args = getPassedArgs(testClient.captureException); - - expect(args[1].originalException).toBe(ex); - expect(args[1].syntheticException).toBeInstanceOf(Error); - expect(args[1].syntheticException.message).toBe('Sentry syntheticException'); - }); - }); - - describe('captureMessage', () => { - test('simple', () => { - const testClient = makeClient(); - const hub = new Hub(testClient); - - hub.captureMessage('a'); - const args = getPassedArgs(testClient.captureMessage); - - expect(args[0]).toBe('a'); - }); - - test('should set event_id in hint', () => { - const testClient = makeClient(); - const hub = new Hub(testClient); - - hub.captureMessage('a'); - const args = getPassedArgs(testClient.captureMessage); - - expect(args[2].event_id).toBeTruthy(); - }); - - test('should keep event_id from hint', () => { - const testClient = makeClient(); - const hub = new Hub(testClient); - const id = Math.random().toString(); - - hub.captureMessage('a', undefined, { event_id: id }); - const args = getPassedArgs(testClient.captureMessage); - - expect(args[2].event_id).toBe(id); - }); - - test('should generate hint if not provided in the call', () => { - const testClient = makeClient(); - const hub = new Hub(testClient); - - hub.captureMessage('foo'); - const args = getPassedArgs(testClient.captureMessage); - - expect(args[2].originalException).toBe('foo'); - expect(args[2].syntheticException).toBeInstanceOf(Error); - expect(args[2].syntheticException.message).toBe('foo'); - }); - }); - - describe('captureEvent', () => { - test('simple', () => { - const event: Event = { - extra: { b: 3 }, - }; - const testClient = makeClient(); - const hub = new Hub(testClient); - - hub.captureEvent(event); - const args = getPassedArgs(testClient.captureEvent); - - expect(args[0]).toBe(event); - }); - - test('should set event_id in hint', () => { - const event: Event = { - extra: { b: 3 }, - }; - const testClient = makeClient(); - const hub = new Hub(testClient); - - hub.captureEvent(event); - const args = getPassedArgs(testClient.captureEvent); - - expect(args[1].event_id).toBeTruthy(); - }); - - test('should keep event_id from hint', () => { - const event: Event = { - extra: { b: 3 }, - }; - const testClient = makeClient(); - const hub = new Hub(testClient); - const id = Math.random().toString(); - - hub.captureEvent(event, { event_id: id }); - const args = getPassedArgs(testClient.captureEvent); - - expect(args[1].event_id).toBe(id); - }); - - test('sets lastEventId', () => { - const event: Event = { - extra: { b: 3 }, - }; - const testClient = makeClient(); - const hub = new Hub(testClient); - - hub.captureEvent(event); - const args = getPassedArgs(testClient.captureEvent); - - expect(args[1].event_id).toEqual(hub.lastEventId()); - }); - - const eventTypesToIgnoreLastEventId: EventType[] = ['transaction', 'replay_event']; - it.each(eventTypesToIgnoreLastEventId)('eventType %s does not set lastEventId', eventType => { - const event: Event = { - extra: { b: 3 }, - type: eventType, - }; - const testClient = makeClient(); - const hub = new Hub(testClient); - - hub.captureEvent(event); - const args = getPassedArgs(testClient.captureEvent); - - expect(args[1].event_id).not.toEqual(hub.lastEventId()); - }); - }); - - test('lastEventId should be the same as last created', () => { - const event: Event = { - extra: { b: 3 }, - }; - const hub = new Hub(); - const eventId = hub.captureEvent(event); - expect(eventId).toBe(hub.lastEventId()); - }); - - describe('run', () => { - test('simple', () => { - const currentHub = getCurrentHub(); - const myScope = new Scope(); - const myClient: any = { a: 'b' }; - myScope.setExtra('a', 'b'); - const myHub = new Hub(myClient, myScope); - myHub.run(hub => { - expect(hub.getScope()).toBe(myScope); - expect(hub.getClient()).toBe(myClient); - expect(hub).toBe(getCurrentHub()); - }); - expect(currentHub).toBe(getCurrentHub()); - }); - - test('should bubble up exceptions', () => { - const hub = new Hub(); - const error = new Error('test'); - expect(() => { - hub.run(() => { - throw error; - }); - }).toThrow(error); - }); - }); - - describe('breadcrumbs', () => { - test('withScope', () => { - expect.assertions(6); - const hub = new Hub(clientFn); - hub.addBreadcrumb({ message: 'My Breadcrumb' }); - hub.withScope(scope => { - scope.addBreadcrumb({ message: 'scope breadcrumb' }); - const event: Event = {}; - void scope - .applyToEvent(event) - .then((appliedEvent: Event | null) => { - expect(appliedEvent).toBeTruthy(); - expect(appliedEvent!.breadcrumbs).toHaveLength(2); - expect(appliedEvent!.breadcrumbs![0].message).toEqual('My Breadcrumb'); - expect(appliedEvent!.breadcrumbs![0]).toHaveProperty('timestamp'); - expect(appliedEvent!.breadcrumbs![1].message).toEqual('scope breadcrumb'); - expect(appliedEvent!.breadcrumbs![1]).toHaveProperty('timestamp'); - }) - .then(null, e => { - // eslint-disable-next-line no-console - console.error(e); - }); - }); - }); - }); - - describe('shouldSendDefaultPii()', () => { - test('return false if sendDefaultPii is not set', () => { - const testClient = makeClient(); - const hub = new Hub(testClient); - expect(hub.shouldSendDefaultPii()).toBe(false); - }); - - test('return true if sendDefaultPii is set in the client options', () => { - const testClient = makeClient(); - testClient.getOptions = () => { - return { - sendDefaultPii: true, - } as unknown as any; - }; - const hub = new Hub(testClient); - expect(hub.shouldSendDefaultPii()).toBe(true); - }); - }); - - describe('session APIs', () => { - beforeEach(() => { - const testClient = makeClient(); - const hub = new Hub(testClient); - makeMain(hub); - }); - - describe('startSession', () => { - it('starts a session', () => { - const testClient = makeClient(); - const hub = new Hub(testClient); - makeMain(hub); - const session = hub.startSession(); - - expect(session).toMatchObject({ - status: 'ok', - errors: 0, - init: true, - environment: 'production', - ignoreDuration: false, - sid: expect.any(String), - did: undefined, - timestamp: expect.any(Number), - started: expect.any(Number), - duration: expect.any(Number), - toJSON: expect.any(Function), - }); - }); - - it('ends a previously active session and removes it from the scope', () => { - const testClient = makeClient(); - const hub = new Hub(testClient); - makeMain(hub); - - const session1 = hub.startSession(); - - expect(session1.status).toBe('ok'); - expect(getCurrentScope().getSession()).toBe(session1); - - const session2 = hub.startSession(); - - expect(session2.status).toBe('ok'); - expect(session1.status).toBe('exited'); - expect(getCurrentHub().getScope().getSession()).toBe(session2); - }); - }); - - describe('endSession', () => { - it('ends a session and removes it from the scope', () => { - const testClient = makeClient(); - const hub = new Hub(testClient); - makeMain(hub); - - const session = hub.startSession(); - - expect(session.status).toBe('ok'); - expect(getCurrentScope().getSession()).toBe(session); - - hub.endSession(); - - expect(session.status).toBe('exited'); - expect(getCurrentHub().getScope().getSession()).toBe(undefined); - }); - }); - - describe('captureSession', () => { - it('captures a session without ending it by default', () => { - const testClient = makeClient(); - const hub = new Hub(testClient); - makeMain(hub); - - const session = hub.startSession(); - - expect(session.status).toBe('ok'); - expect(getCurrentScope().getSession()).toBe(session); - - hub.captureSession(); - - expect(testClient.captureSession).toHaveBeenCalledWith(expect.objectContaining({ status: 'ok' })); - }); - - it('captures a session and ends it if end is `true`', () => { - const testClient = makeClient(); - const hub = new Hub(testClient); - makeMain(hub); - - const session = hub.startSession(); - - expect(session.status).toBe('ok'); - expect(hub.getScope().getSession()).toBe(session); - - hub.captureSession(true); - - expect(testClient.captureSession).toHaveBeenCalledWith(expect.objectContaining({ status: 'exited' })); - }); - }); - }); -}); From 5760c1ca74578076b4339b0c7ad951880c09e693 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Thu, 8 Feb 2024 09:24:20 -0500 Subject: [PATCH 4/5] add more to migration --- MIGRATION.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index bee9b99087b4..2c9a352010fd 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -33,14 +33,20 @@ The `enableAnrDetection` and `Anr` class have been removed. See the [docs](https://docs.sentry.io/platforms/node/configuration/application-not-responding/) for more details how to migrate to `anrIntegration`, the new integration for ANR detection. -## Removal of `Sentry.configureScope`. +## Removal of `Sentry.configureScope` (#10565) The top level `Sentry.configureScope` function has been removed. Instead, you should use the `Sentry.getCurrentScope()` to access and mutate the current scope. -## Other changes +## Deletion of `@sentry/hub` package (#10530) + +`@sentry/hub` has been removed. All exports from `@sentry.hub` should be available in `@sentry/core`. + +## General API Changes - Remove `spanStatusfromHttpCode` in favour of `getSpanStatusFromHttpCode` (#10361) +- Remove deprecated `deepReadDirSync` export from `@sentry/node` (#10564) +- Remove `_eventFromIncompleteOnError` usage (#10553) # Deprecations in 7.x From 3f8ca67fa38643190522c9112ccb0743e4944cd0 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Fri, 9 Feb 2024 17:30:27 -0500 Subject: [PATCH 5/5] fix merge conflict --- packages/node-experimental/src/sdk/api.ts | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/packages/node-experimental/src/sdk/api.ts b/packages/node-experimental/src/sdk/api.ts index be8867dcd8f0..83685fe6d987 100644 --- a/packages/node-experimental/src/sdk/api.ts +++ b/packages/node-experimental/src/sdk/api.ts @@ -96,23 +96,6 @@ export function withIsolationScope(callback: (isolationScope: Scope) => T): T }); } -/** -<<<<<<< HEAD - * Configure the current scope. - * @deprecated Use `getCurrentScope()` instead. - */ -export function configureScope(callback: (scope: Scope) => void): void { - callback(getCurrentScope()); -======= - * Get the ID of the last sent error event. - * @deprecated This function will be removed in the next major version of the Sentry SDK. - */ -export function lastEventId(): string | undefined { - // eslint-disable-next-line deprecation/deprecation - return getCurrentScope().lastEventId(); ->>>>>>> 63597e2af (feat(v8): Remove deprecated configureScope call) -} - /** Record an exception and send it to Sentry. */ export function captureException(exception: unknown, hint?: ExclusiveEventHintOrCaptureContext): string { return getCurrentScope().captureException(exception, parseEventHintOrCaptureContext(hint));