From 4b5c873034845d3129dec2298bd22a2ba614e154 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Thu, 1 Feb 2024 17:20:40 +0100 Subject: [PATCH 01/19] enable deprecations for SDK code --- .eslintrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index 17fa5b5422..d5e2603e98 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -39,6 +39,7 @@ module.exports = { '@typescript-eslint/no-empty-function': 'off', '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/unbound-method': 'off', + 'deprecation/deprecation': 'off', }, }, { @@ -66,6 +67,5 @@ module.exports = { '@sentry-internal/sdk/no-nullish-coalescing': 'off', '@sentry-internal/sdk/no-unsupported-es6-methods': 'off', '@sentry-internal/sdk/no-class-field-initializers': 'off', - 'deprecation/deprecation': 'off', }, }; From 5d51b7ad1d5deef8d95c7073bbb5450e05648f07 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Thu, 1 Feb 2024 17:40:42 +0100 Subject: [PATCH 02/19] fix client --- src/js/client.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/js/client.ts b/src/js/client.ts index c896939295..c219939358 100644 --- a/src/js/client.ts +++ b/src/js/client.ts @@ -18,7 +18,7 @@ import { Alert } from 'react-native'; import { createIntegration } from './integrations/factory'; import { defaultSdkInfo } from './integrations/sdkinfo'; import type { ReactNativeClientOptions } from './options'; -import { ReactNativeTracing } from './tracing'; +import type { ReactNativeTracing } from './tracing'; import { createUserFeedbackEnvelope, items } from './utils/envelope'; import { ignoreRequireCycleLogs } from './utils/ignorerequirecyclelogs'; import { mergeOutcomes } from './utils/outcome'; @@ -107,12 +107,12 @@ export class ReactNativeClient extends BaseClient { } /** - * Sets up the integrations + * @inheritdoc */ - public setupIntegrations(): void { - super.setupIntegrations(); - const tracing = this.getIntegration(ReactNativeTracing); - const routingName = tracing?.options.routingInstrumentation?.name; + protected _setupIntegrations(): void { + super._setupIntegrations(); + const tracing = this.getIntegrationByName('ReactNativeTracing') as ReactNativeTracing; + const routingName = tracing?.options?.routingInstrumentation?.name; if (routingName) { this.addIntegration(createIntegration(routingName)); } From 8a3db3b4cd847e628678934e65f19603eaeed40f Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Thu, 1 Feb 2024 17:47:21 +0100 Subject: [PATCH 03/19] fix index --- src/js/index.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/js/index.ts b/src/js/index.ts index 3997cca234..6918f8d5bd 100644 --- a/src/js/index.ts +++ b/src/js/index.ts @@ -12,12 +12,14 @@ export type { } from '@sentry/types'; export { + // eslint-disable-next-line deprecation/deprecation addGlobalEventProcessor, addBreadcrumb, captureException, captureEvent, captureMessage, getHubFromCarrier, + // eslint-disable-next-line deprecation/deprecation getCurrentHub, Hub, Scope, @@ -27,6 +29,7 @@ export { setTag, setTags, setUser, + // eslint-disable-next-line deprecation/deprecation startTransaction, startInactiveSpan, startSpan, @@ -38,6 +41,7 @@ import { _addTracingExtensions } from './tracing/addTracingExtensions'; _addTracingExtensions(); export { + // eslint-disable-next-line deprecation/deprecation Integrations as BrowserIntegrations, ErrorBoundary, withErrorBoundary, @@ -47,6 +51,7 @@ export { withProfiler, } from '@sentry/react'; +// eslint-disable-next-line deprecation/deprecation export { lastEventId } from '@sentry/browser'; import * as Integrations from './integrations'; From d4bcb49a48b5a58e865472b746979bac01ec1260 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Thu, 1 Feb 2024 17:47:33 +0100 Subject: [PATCH 04/19] fix debugsymbolicator --- src/js/integrations/debugsymbolicator.ts | 56 ++++++++++++------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/js/integrations/debugsymbolicator.ts b/src/js/integrations/debugsymbolicator.ts index 4ab109f4fe..e6493ddd79 100644 --- a/src/js/integrations/debugsymbolicator.ts +++ b/src/js/integrations/debugsymbolicator.ts @@ -32,40 +32,40 @@ export class DebugSymbolicator implements Integration { /** * @inheritDoc + * @deprecated */ - public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { - addGlobalEventProcessor(async (event: Event, hint: EventHint) => { - const self = getCurrentHub().getIntegration(DebugSymbolicator); + public setupOnce(_addGlobalEventProcessor: (callback: EventProcessor) => void, _getCurrentHub: () => Hub): void { + // nothing to do here + } - if (!self) { - return event; - } + /** + * @inheritdoc + */ + public async processEvent(event: Event, hint: EventHint): Promise { + if (event.exception && isErrorLike(hint.originalException)) { + // originalException is ErrorLike object + const symbolicatedFrames = await this._symbolicate( + hint.originalException.stack, + getFramesToPop(hint.originalException as Error), + ); + symbolicatedFrames && this._replaceExceptionFramesInEvent(event, symbolicatedFrames); + } else if (hint.syntheticException && isErrorLike(hint.syntheticException)) { + // syntheticException is Error object + const symbolicatedFrames = await this._symbolicate( + hint.syntheticException.stack, + getFramesToPop(hint.syntheticException), + ); - if (event.exception && isErrorLike(hint.originalException)) { - // originalException is ErrorLike object - const symbolicatedFrames = await this._symbolicate( - hint.originalException.stack, - getFramesToPop(hint.originalException as Error), - ); + if (event.exception) { symbolicatedFrames && this._replaceExceptionFramesInEvent(event, symbolicatedFrames); - } else if (hint.syntheticException && isErrorLike(hint.syntheticException)) { - // syntheticException is Error object - const symbolicatedFrames = await this._symbolicate( - hint.syntheticException.stack, - getFramesToPop(hint.syntheticException), - ); - - if (event.exception) { - symbolicatedFrames && this._replaceExceptionFramesInEvent(event, symbolicatedFrames); - } else if (event.threads) { - // RN JS doesn't have threads - // syntheticException is used for Sentry.captureMessage() threads - symbolicatedFrames && this._replaceThreadFramesInEvent(event, symbolicatedFrames); - } + } else if (event.threads) { + // RN JS doesn't have threads + // syntheticException is used for Sentry.captureMessage() threads + symbolicatedFrames && this._replaceThreadFramesInEvent(event, symbolicatedFrames); } + } - return event; - }); + return event; } /** From 7457d6dfb6a997ddf8b531be924044dcaef8025e Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Fri, 2 Feb 2024 15:42:14 +0100 Subject: [PATCH 05/19] fix tests --- test/integrations/debugsymbolicator.test.ts | 26 +++++-------------- .../integrationsexecutionorder.test.ts | 4 +-- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/test/integrations/debugsymbolicator.test.ts b/test/integrations/debugsymbolicator.test.ts index ab1465d8a0..b49cafbfc4 100644 --- a/test/integrations/debugsymbolicator.test.ts +++ b/test/integrations/debugsymbolicator.test.ts @@ -1,4 +1,4 @@ -import type { Event, EventHint, Hub, Integration, StackFrame } from '@sentry/types'; +import type { Client, Event, EventHint, Integration, StackFrame } from '@sentry/types'; import { DebugSymbolicator } from '../../src/js/integrations/debugsymbolicator'; import type * as ReactNative from '../../src/js/vendor/react-native'; @@ -15,10 +15,6 @@ interface MockDebugSymbolicator extends Integration { describe('Debug Symbolicator Integration', () => { let integration: MockDebugSymbolicator; - const mockGetCurrentHub = () => - ({ - getIntegration: () => integration, - } as unknown as Hub); beforeEach(() => { integration = new DebugSymbolicator() as unknown as MockDebugSymbolicator; @@ -341,20 +337,12 @@ describe('Debug Symbolicator Integration', () => { }); }); - function executeIntegrationFor(mockedEvent: Event, hint: EventHint): Promise { - return new Promise((resolve, reject) => { - if (!integration) { - throw new Error('Setup integration before executing the test.'); - } + async function executeIntegrationFor(mockedEvent: Event, mockedHint: EventHint): Promise { + if (!integration) { + throw new Error('Setup integration before executing the test.'); + } - integration.setupOnce(async eventProcessor => { - try { - const processedEvent = await eventProcessor(mockedEvent, hint); - resolve(processedEvent); - } catch (e) { - reject(e); - } - }, mockGetCurrentHub); - }); + const actualEvent = await integration.processEvent!(mockedEvent, mockedHint, {} as Client); + return actualEvent; } }); diff --git a/test/integrations/integrationsexecutionorder.test.ts b/test/integrations/integrationsexecutionorder.test.ts index 7a9e9f5def..bd003eae7a 100644 --- a/test/integrations/integrationsexecutionorder.test.ts +++ b/test/integrations/integrationsexecutionorder.test.ts @@ -31,7 +31,7 @@ describe('Integration execution order', () => { client.setupIntegrations(); client.captureException(new Error('test')); - jest.runAllTimers(); + await client.flush(); expect(nativeLinkedErrors.preprocessEvent).toHaveBeenCalledBefore(rewriteFrames.processEvent!); }); @@ -56,7 +56,7 @@ describe('Integration execution order', () => { client.setupIntegrations(); client.captureException(new Error('test')); - jest.runAllTimers(); + await client.flush(); expect(linkedErrors.preprocessEvent).toHaveBeenCalledBefore(rewriteFrames.processEvent!); }); From d9727847a6eefc45495830dbadc210d9ef070691 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Thu, 1 Feb 2024 17:56:10 +0100 Subject: [PATCH 06/19] fix default integrations --- src/js/integrations/default.ts | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/js/integrations/default.ts b/src/js/integrations/default.ts index 4dc16bfae1..6b34dcf766 100644 --- a/src/js/integrations/default.ts +++ b/src/js/integrations/default.ts @@ -1,5 +1,12 @@ -import { HttpClient } from '@sentry/integrations'; -import { Integrations as BrowserReactIntegrations } from '@sentry/react'; +import { + breadcrumbsIntegration, + browserApiErrorsIntegration, + dedupeIntegration, + functionToStringIntegration, + globalHandlersIntegration as browserGlobalHandlersIntegration, + httpContextIntegration, inboundFiltersIntegration, + linkedErrorsIntegration as browserLinkedErrorsIntegration, +} from '@sentry/react'; import type { Integration } from '@sentry/types'; import type { ReactNativeClientOptions } from '../options'; @@ -39,17 +46,17 @@ export function getDefaultIntegrations(options: ReactNativeClientOptions): Integ ); integrations.push(new NativeLinkedErrors()); } else { - integrations.push(new BrowserReactIntegrations.TryCatch()); - integrations.push(new BrowserReactIntegrations.GlobalHandlers()); - integrations.push(new BrowserReactIntegrations.LinkedErrors()); + integrations.push(browserApiErrorsIntegration()); + integrations.push(browserGlobalHandlersIntegration()); + integrations.push(browserLinkedErrorsIntegration()); } // @sentry/react default integrations - integrations.push(new BrowserReactIntegrations.InboundFilters()); - integrations.push(new BrowserReactIntegrations.FunctionToString()); - integrations.push(new BrowserReactIntegrations.Breadcrumbs()); - integrations.push(new BrowserReactIntegrations.Dedupe()); - integrations.push(new BrowserReactIntegrations.HttpContext()); + integrations.push(inboundFiltersIntegration()); + integrations.push(functionToStringIntegration()); + integrations.push(breadcrumbsIntegration()); + integrations.push(dedupeIntegration()); + integrations.push(httpContextIntegration()); // end @sentry/react-native default integrations integrations.push(new Release()); @@ -88,7 +95,7 @@ export function getDefaultIntegrations(options: ReactNativeClientOptions): Integ integrations.push(new ReactNativeTracing()); } if (options.enableCaptureFailedRequests) { - integrations.push(new HttpClient()); + integrations.push(httpContextIntegration()); } if (isExpoGo()) { From cc93c4b62034c571cf0101dcb1cc7825191adf0f Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Fri, 2 Feb 2024 15:44:32 +0100 Subject: [PATCH 07/19] fix httpclient integration --- src/js/integrations/default.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/js/integrations/default.ts b/src/js/integrations/default.ts index 6b34dcf766..474d0ab512 100644 --- a/src/js/integrations/default.ts +++ b/src/js/integrations/default.ts @@ -1,3 +1,4 @@ +import { httpClientIntegration } from '@sentry/integrations'; import { breadcrumbsIntegration, browserApiErrorsIntegration, @@ -95,7 +96,7 @@ export function getDefaultIntegrations(options: ReactNativeClientOptions): Integ integrations.push(new ReactNativeTracing()); } if (options.enableCaptureFailedRequests) { - integrations.push(httpContextIntegration()); + integrations.push(httpClientIntegration()); } if (isExpoGo()) { From 0b1d5eef68464824f53bf21b905686c0594a70e8 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Thu, 1 Feb 2024 17:56:18 +0100 Subject: [PATCH 08/19] fix device context --- src/js/integrations/devicecontext.ts | 125 ++++++++++++++------------- 1 file changed, 63 insertions(+), 62 deletions(-) diff --git a/src/js/integrations/devicecontext.ts b/src/js/integrations/devicecontext.ts index df2834a727..9b9aee491c 100644 --- a/src/js/integrations/devicecontext.ts +++ b/src/js/integrations/devicecontext.ts @@ -21,80 +21,81 @@ export class DeviceContext implements Integration { /** * @inheritDoc + * @deprecated */ - public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { - addGlobalEventProcessor(async (event: Event) => { - const self = getCurrentHub().getIntegration(DeviceContext); - if (!self) { - return event; - } + public setupOnce(_addGlobalEventProcessor: (callback: EventProcessor) => void, _getCurrentHub: () => Hub): void { + // nothing to do here + } - let native: NativeDeviceContextsResponse | null = null; - try { - native = await NATIVE.fetchNativeDeviceContexts(); - } catch (e) { - logger.log(`Failed to get device context from native: ${e}`); - } + /** + * @inheritDoc + */ + public async processEvent(event: Event): Promise { + let native: NativeDeviceContextsResponse | null = null; + try { + native = await NATIVE.fetchNativeDeviceContexts(); + } catch (e) { + logger.log(`Failed to get device context from native: ${e}`); + } - if (!native) { - return event; - } + if (!native) { + return event; + } - const nativeUser = native.user; - if (!event.user && nativeUser) { - event.user = nativeUser; - } + const nativeUser = native.user; + if (!event.user && nativeUser) { + event.user = nativeUser; + } - let nativeContexts = native.contexts; - if (AppState.currentState !== 'unknown') { - nativeContexts = nativeContexts || {}; - nativeContexts.app = { - ...nativeContexts.app, - in_foreground: AppState.currentState === 'active', - }; - } - if (nativeContexts) { - event.contexts = { ...nativeContexts, ...event.contexts }; - if (nativeContexts.app) { - event.contexts.app = { ...nativeContexts.app, ...event.contexts.app }; - } + let nativeContexts = native.contexts; + if (AppState.currentState !== 'unknown') { + nativeContexts = nativeContexts || {}; + nativeContexts.app = { + ...nativeContexts.app, + in_foreground: AppState.currentState === 'active', + }; + } + if (nativeContexts) { + event.contexts = { ...nativeContexts, ...event.contexts }; + if (nativeContexts.app) { + event.contexts.app = { ...nativeContexts.app, ...event.contexts.app }; } + } - const nativeTags = native.tags; - if (nativeTags) { - event.tags = { ...nativeTags, ...event.tags }; - } + const nativeTags = native.tags; + if (nativeTags) { + event.tags = { ...nativeTags, ...event.tags }; + } - const nativeExtra = native.extra; - if (nativeExtra) { - event.extra = { ...nativeExtra, ...event.extra }; - } + const nativeExtra = native.extra; + if (nativeExtra) { + event.extra = { ...nativeExtra, ...event.extra }; + } - const nativeFingerprint = native.fingerprint; - if (nativeFingerprint) { - event.fingerprint = (event.fingerprint ?? []).concat( - nativeFingerprint.filter(item => (event.fingerprint ?? []).indexOf(item) < 0), - ); - } + const nativeFingerprint = native.fingerprint; + if (nativeFingerprint) { + event.fingerprint = (event.fingerprint ?? []).concat( + nativeFingerprint.filter(item => (event.fingerprint ?? []).indexOf(item) < 0), + ); + } - const nativeLevel = typeof native['level'] === 'string' ? severityLevelFromString(native['level']) : undefined; - if (!event.level && nativeLevel) { - event.level = nativeLevel; - } + const nativeLevel = typeof native['level'] === 'string' ? severityLevelFromString(native['level']) : undefined; + if (!event.level && nativeLevel) { + event.level = nativeLevel; + } - const nativeEnvironment = native['environment']; - if (!event.environment && nativeEnvironment) { - event.environment = nativeEnvironment; - } + const nativeEnvironment = native['environment']; + if (!event.environment && nativeEnvironment) { + event.environment = nativeEnvironment; + } - const nativeBreadcrumbs = Array.isArray(native['breadcrumbs']) - ? native['breadcrumbs'].map(breadcrumbFromObject) - : undefined; - if (nativeBreadcrumbs) { - event.breadcrumbs = nativeBreadcrumbs; - } + const nativeBreadcrumbs = Array.isArray(native['breadcrumbs']) + ? native['breadcrumbs'].map(breadcrumbFromObject) + : undefined; + if (nativeBreadcrumbs) { + event.breadcrumbs = nativeBreadcrumbs; + } - return event; - }); + return event; } } From 20af1b7097fb3016603ad9c1b8ef821a5a5f45a3 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Fri, 2 Feb 2024 15:48:19 +0100 Subject: [PATCH 09/19] fix device context test --- test/integrations/devicecontext.test.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/test/integrations/devicecontext.test.ts b/test/integrations/devicecontext.test.ts index a2644ca58a..80420c737e 100644 --- a/test/integrations/devicecontext.test.ts +++ b/test/integrations/devicecontext.test.ts @@ -253,15 +253,6 @@ describe('Device Context Integration', () => { } function executeIntegrationFor(mockedEvent: Event): Promise { - return new Promise((resolve, reject) => { - integration.setupOnce(async eventProcessor => { - try { - const processedEvent = await eventProcessor(mockedEvent, {}); - resolve(processedEvent); - } catch (e) { - reject(e); - } - }, mockGetCurrentHub); - }); + return integration.processEvent(mockedEvent); } }); From 5f42cdf2ba1a2de75a9500d33895267069b24d87 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Fri, 2 Feb 2024 10:23:31 +0100 Subject: [PATCH 10/19] fix rn error handlers --- src/js/integrations/reactnativeerrorhandlers.ts | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/js/integrations/reactnativeerrorhandlers.ts b/src/js/integrations/reactnativeerrorhandlers.ts index 934c201ad7..6ff3a912ce 100644 --- a/src/js/integrations/reactnativeerrorhandlers.ts +++ b/src/js/integrations/reactnativeerrorhandlers.ts @@ -1,8 +1,7 @@ -import { getCurrentHub } from '@sentry/core'; +import { captureException, getClient, getCurrentScope } from '@sentry/core'; import type { EventHint, Integration, SeverityLevel } from '@sentry/types'; import { addExceptionMechanism, logger } from '@sentry/utils'; -import type { ReactNativeClient } from '../client'; import { createSyntheticError, isErrorLike } from '../utils/error'; import { ReactNativeLibraries } from '../utils/rnlibraries'; import { RN_GLOBAL_OBJ } from '../utils/worldwide'; @@ -129,7 +128,7 @@ export class ReactNativeErrorHandlers implements Integration { promiseRejectionTrackingOptions.onUnhandled(id, error); } - getCurrentHub().captureException(error, { + captureException(error, { data: { id }, originalException: error, syntheticException: isErrorLike(error) ? undefined : createSyntheticError(), @@ -208,9 +207,7 @@ export class ReactNativeErrorHandlers implements Integration { handlingFatal = true; } - const currentHub = getCurrentHub(); - const client = currentHub.getClient(); - const scope = currentHub.getScope(); + const client = getClient(); if (!client) { logger.error('Sentry client is missing, the error event might be lost.', error); @@ -221,11 +218,9 @@ export class ReactNativeErrorHandlers implements Integration { return; } - const options = client.getOptions(); - const hint: EventHint = { originalException: error, - attachments: scope?.getAttachments(), + attachments: getCurrentScope().getScopeData().attachments, }; const event = await client.eventFromException(error, hint); @@ -238,10 +233,10 @@ export class ReactNativeErrorHandlers implements Integration { }); } - currentHub.captureEvent(event, hint); + client.captureEvent(event, hint); if (!__DEV__) { - void client.flush(options.shutdownTimeout || 2000).then( + void client.flush(client.getOptions().shutdownTimeout || 2000).then( () => { defaultHandler(error, isFatal); }, From d4f0ddb09cdb108a876bde418fb1f0c8ba66b087 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Fri, 2 Feb 2024 17:18:59 +0100 Subject: [PATCH 11/19] fix react native error handlers tests --- .../reactnativeerrorhandlers.test.ts | 31 +++++++------------ 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/test/integrations/reactnativeerrorhandlers.test.ts b/test/integrations/reactnativeerrorhandlers.test.ts index 3a4285f3e0..5c9ac6f4a7 100644 --- a/test/integrations/reactnativeerrorhandlers.test.ts +++ b/test/integrations/reactnativeerrorhandlers.test.ts @@ -1,4 +1,7 @@ import { BrowserClient, defaultIntegrations, defaultStackParser } from '@sentry/browser'; +import type { Event, EventHint, ExtendedError, Integration, SeverityLevel } from '@sentry/types'; + +import { ReactNativeErrorHandlers } from '../../src/js/integrations/reactnativeerrorhandlers'; const mockBrowserClient: BrowserClient = new BrowserClient({ stackParser: defaultStackParser, @@ -6,34 +9,32 @@ const mockBrowserClient: BrowserClient = new BrowserClient({ transport: jest.fn(), }); + let mockHubCaptureException: jest.Mock; jest.mock('@sentry/core', () => { const core = jest.requireActual('@sentry/core'); const scope = { - getAttachments: jest.fn(), + getScopeData: jest.fn().mockReturnValue({ attachments: [] }), }; + mockHubCaptureException = jest.fn(); + const client = { getOptions: () => ({}), eventFromException: (_exception: any, _hint?: EventHint): PromiseLike => mockBrowserClient.eventFromException(_exception, _hint), + captureEvent: mockHubCaptureException, }; - const hub = { - getClient: () => client, - getScope: () => scope, - captureEvent: jest.fn(), - captureException: jest.fn(), - }; - - mockHubCaptureException = hub.captureException; return { ...core, addGlobalEventProcessor: jest.fn(), - getCurrentHub: () => hub, + getClient: () => client, + getCurrentScope: () => scope, + captureException: mockHubCaptureException, }; }); @@ -49,11 +50,6 @@ jest.mock('@sentry/utils', () => { }; }); -import { getCurrentHub } from '@sentry/core'; -import type { Event, EventHint, ExtendedError, Integration, SeverityLevel } from '@sentry/types'; - -import { ReactNativeErrorHandlers } from '../../src/js/integrations/reactnativeerrorhandlers'; - interface MockTrackingOptions { allRejections: boolean; onUnhandled: jest.Mock; @@ -183,8 +179,5 @@ describe('ReactNativeErrorHandlers', () => { }); function getActualCaptureEventArgs() { - const hub = getCurrentHub(); - const mockCall = (hub.captureEvent as jest.MockedFunction).mock.calls[0]; - - return mockCall; + return mockHubCaptureException.mock.calls[0]; } From 02a6d2b5583bb4634787c79ad0d591d202ececf2 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Fri, 2 Feb 2024 10:28:56 +0100 Subject: [PATCH 12/19] fix release --- src/js/integrations/release.ts | 76 +++++++++++++++++----------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/js/integrations/release.ts b/src/js/integrations/release.ts index 0ca52c12e2..2f8caf2634 100644 --- a/src/js/integrations/release.ts +++ b/src/js/integrations/release.ts @@ -1,5 +1,4 @@ -import { addGlobalEventProcessor, getCurrentHub } from '@sentry/core'; -import type { Event, Integration } from '@sentry/types'; +import type { BaseTransportOptions, Client, ClientOptions, Event, EventHint, Integration } from '@sentry/types'; import { NATIVE } from '../wrapper'; @@ -16,51 +15,52 @@ export class Release implements Integration { /** * @inheritDoc + * @deprecated */ public setupOnce(): void { - addGlobalEventProcessor(async (event: Event) => { - const self = getCurrentHub().getIntegration(Release); - if (!self) { - return event; - } + // nothing to do here + } - const options = getCurrentHub().getClient()?.getOptions(); + /** + * @inheritDoc + */ + public async processEvent(event: Event, _: EventHint, client: Client>): Promise { + const options = client.getOptions(); - /* - __sentry_release and __sentry_dist is set by the user with setRelease and setDist. If this is used then this is the strongest. - Otherwise we check for the release and dist in the options passed on init, as this is stronger than the release/dist from the native build. - */ - if (typeof event.extra?.__sentry_release === 'string') { - event.release = `${event.extra.__sentry_release}`; - } else if (typeof options?.release === 'string') { - event.release = options.release; - } + /* + __sentry_release and __sentry_dist is set by the user with setRelease and setDist. If this is used then this is the strongest. + Otherwise we check for the release and dist in the options passed on init, as this is stronger than the release/dist from the native build. + */ + if (typeof event.extra?.__sentry_release === 'string') { + event.release = `${event.extra.__sentry_release}`; + } else if (typeof options?.release === 'string') { + event.release = options.release; + } - if (typeof event.extra?.__sentry_dist === 'string') { - event.dist = `${event.extra.__sentry_dist}`; - } else if (typeof options?.dist === 'string') { - event.dist = options.dist; - } + if (typeof event.extra?.__sentry_dist === 'string') { + event.dist = `${event.extra.__sentry_dist}`; + } else if (typeof options?.dist === 'string') { + event.dist = options.dist; + } - if (event.release && event.dist) { - return event; - } + if (event.release && event.dist) { + return event; + } - try { - const nativeRelease = await NATIVE.fetchNativeRelease(); - if (nativeRelease) { - if (!event.release) { - event.release = `${nativeRelease.id}@${nativeRelease.version}+${nativeRelease.build}`; - } - if (!event.dist) { - event.dist = `${nativeRelease.build}`; - } + try { + const nativeRelease = await NATIVE.fetchNativeRelease(); + if (nativeRelease) { + if (!event.release) { + event.release = `${nativeRelease.id}@${nativeRelease.version}+${nativeRelease.build}`; + } + if (!event.dist) { + event.dist = `${nativeRelease.build}`; } - } catch (_Oo) { - // Something went wrong, we just continue } + } catch (_Oo) { + // Something went wrong, we just continue + } - return event; - }); + return event; } } From 591ab2a6e6a3e28639d28cea245c7dc5edde68d7 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Fri, 2 Feb 2024 17:28:01 +0100 Subject: [PATCH 13/19] fix release tests --- src/js/integrations/default.ts | 3 +- src/js/integrations/release.ts | 6 +- .../reactnativeerrorhandlers.test.ts | 2 - test/integrations/release.test.ts | 95 ++++--------------- 4 files changed, 23 insertions(+), 83 deletions(-) diff --git a/src/js/integrations/default.ts b/src/js/integrations/default.ts index 474d0ab512..e0ac2a6392 100644 --- a/src/js/integrations/default.ts +++ b/src/js/integrations/default.ts @@ -5,7 +5,8 @@ import { dedupeIntegration, functionToStringIntegration, globalHandlersIntegration as browserGlobalHandlersIntegration, - httpContextIntegration, inboundFiltersIntegration, + httpContextIntegration, + inboundFiltersIntegration, linkedErrorsIntegration as browserLinkedErrorsIntegration, } from '@sentry/react'; import type { Integration } from '@sentry/types'; diff --git a/src/js/integrations/release.ts b/src/js/integrations/release.ts index 2f8caf2634..285e2d81c8 100644 --- a/src/js/integrations/release.ts +++ b/src/js/integrations/release.ts @@ -24,7 +24,11 @@ export class Release implements Integration { /** * @inheritDoc */ - public async processEvent(event: Event, _: EventHint, client: Client>): Promise { + public async processEvent( + event: Event, + _: EventHint, + client: Client>, + ): Promise { const options = client.getOptions(); /* diff --git a/test/integrations/reactnativeerrorhandlers.test.ts b/test/integrations/reactnativeerrorhandlers.test.ts index 5c9ac6f4a7..8a12822a66 100644 --- a/test/integrations/reactnativeerrorhandlers.test.ts +++ b/test/integrations/reactnativeerrorhandlers.test.ts @@ -9,7 +9,6 @@ const mockBrowserClient: BrowserClient = new BrowserClient({ transport: jest.fn(), }); - let mockHubCaptureException: jest.Mock; jest.mock('@sentry/core', () => { @@ -28,7 +27,6 @@ jest.mock('@sentry/core', () => { captureEvent: mockHubCaptureException, }; - return { ...core, addGlobalEventProcessor: jest.fn(), diff --git a/test/integrations/release.test.ts b/test/integrations/release.test.ts index fc543a9ad1..66d804ab0f 100644 --- a/test/integrations/release.test.ts +++ b/test/integrations/release.test.ts @@ -1,5 +1,4 @@ -import { addGlobalEventProcessor, getCurrentHub } from '@sentry/core'; -import type { EventProcessor } from '@sentry/types'; +import type { Client } from '@sentry/types'; import { Release } from '../../src/js/integrations/release'; @@ -24,7 +23,7 @@ jest.mock('@sentry/core', () => { jest.mock('../../src/js/wrapper', () => ({ NATIVE: { - fetchNativeRelease: async () => ({ + fetchNativeRelease: () => ({ build: 'native_build', id: 'native_id', version: 'native_version', @@ -36,20 +35,7 @@ describe('Tests the Release integration', () => { test('Uses release from native SDK if release/dist are not present in options.', async () => { const releaseIntegration = new Release(); - let eventProcessor: EventProcessor = () => null; - - // @ts-expect-error Mock - addGlobalEventProcessor.mockImplementation(e => (eventProcessor = e)); - releaseIntegration.setupOnce(); - - expect(addGlobalEventProcessor).toBeCalled(); - - const client = getCurrentHub().getClient(); - - // @ts-expect-error Mock - client.getOptions.mockImplementation(() => ({})); - - const event = await eventProcessor({}, {}); + const event = await releaseIntegration.processEvent({}, {}, { getOptions: () => ({}) } as Client); expect(event?.release).toBe('native_id@native_version+native_build'); expect(event?.dist).toBe('native_build'); @@ -58,20 +44,9 @@ describe('Tests the Release integration', () => { test('Uses release from native SDK if release is not present in options.', async () => { const releaseIntegration = new Release(); - let eventProcessor: EventProcessor = () => null; - - // @ts-expect-error Mock - addGlobalEventProcessor.mockImplementation(e => (eventProcessor = e)); - releaseIntegration.setupOnce(); - - const client = getCurrentHub().getClient(); - - // @ts-expect-error Mock - client.getOptions.mockImplementation(() => ({ - dist: 'options_dist', - })); - - const event = await eventProcessor({}, {}); + const event = await releaseIntegration.processEvent({}, {}, { + getOptions: () => ({ dist: 'options_dist' }), + } as Client); expect(event?.release).toBe('native_id@native_version+native_build'); expect(event?.dist).toBe('options_dist'); @@ -80,20 +55,9 @@ describe('Tests the Release integration', () => { test('Uses dist from native SDK if dist is not present in options.', async () => { const releaseIntegration = new Release(); - let eventProcessor: EventProcessor = () => null; - - // @ts-expect-error Mock - addGlobalEventProcessor.mockImplementation(e => (eventProcessor = e)); - releaseIntegration.setupOnce(); - - const client = getCurrentHub().getClient(); - - // @ts-expect-error Mock - client.getOptions.mockImplementation(() => ({ - release: 'options_release', - })); - - const event = await eventProcessor({}, {}); + const event = await releaseIntegration.processEvent({}, {}, { + getOptions: () => ({ release: 'options_release' }), + } as Client); expect(event?.release).toBe('options_release'); expect(event?.dist).toBe('native_build'); @@ -102,23 +66,9 @@ describe('Tests the Release integration', () => { test('Uses release and dist from options', async () => { const releaseIntegration = new Release(); - let eventProcessor: EventProcessor = () => null; - - // @ts-expect-error Mock - addGlobalEventProcessor.mockImplementation(e => (eventProcessor = e)); - releaseIntegration.setupOnce(); - - expect(addGlobalEventProcessor).toBeCalled(); - - const client = getCurrentHub().getClient(); - - // @ts-expect-error Mock - client.getOptions.mockImplementation(() => ({ - dist: 'options_dist', - release: 'options_release', - })); - - const event = await eventProcessor({}, {}); + const event = await releaseIntegration.processEvent({}, {}, { + getOptions: () => ({ dist: 'options_dist', release: 'options_release' }), + } as Client); expect(event?.release).toBe('options_release'); expect(event?.dist).toBe('options_dist'); @@ -127,23 +77,7 @@ describe('Tests the Release integration', () => { test('Uses __sentry_release and __sentry_dist over everything else.', async () => { const releaseIntegration = new Release(); - let eventProcessor: EventProcessor = () => null; - - // @ts-expect-error Mock - addGlobalEventProcessor.mockImplementation(e => (eventProcessor = e)); - releaseIntegration.setupOnce(); - - expect(addGlobalEventProcessor).toBeCalled(); - - const client = getCurrentHub().getClient(); - - // @ts-expect-error Mock - client.getOptions.mockImplementation(() => ({ - dist: 'options_dist', - release: 'options_release', - })); - - const event = await eventProcessor( + const event = await releaseIntegration.processEvent( { extra: { __sentry_dist: 'sentry_dist', @@ -151,6 +85,9 @@ describe('Tests the Release integration', () => { }, }, {}, + { + getOptions: () => ({ dist: 'options_dist' }), + } as Client, ); expect(event?.release).toBe('sentry_release'); From bb8f49a1a9b8a0d5dc3b37d85785f3a02c42f9cc Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Fri, 2 Feb 2024 17:34:01 +0100 Subject: [PATCH 14/19] fix expo context --- src/js/integrations/expocontext.ts | 37 ++++++++++++++------------- test/integrations/expocontext.test.ts | 20 +++------------ 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/src/js/integrations/expocontext.ts b/src/js/integrations/expocontext.ts index 04944b53bc..619c1a32a0 100644 --- a/src/js/integrations/expocontext.ts +++ b/src/js/integrations/expocontext.ts @@ -16,28 +16,29 @@ export class ExpoContext implements Integration { /** * @inheritDoc + * @deprecated */ - public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { - addGlobalEventProcessor(async (event: Event) => { - const self = getCurrentHub().getIntegration(ExpoContext); - if (!self) { - return event; - } + public setupOnce(_addGlobalEventProcessor: (callback: EventProcessor) => void, _getCurrentHub: () => Hub): void { + // nothing to do here + } - const expoDeviceContext = getExpoDeviceContext(); - if (expoDeviceContext) { - event.contexts = event.contexts || {}; - event.contexts.device = { ...expoDeviceContext, ...event.contexts.device }; - } + /** + * @inheritDoc + */ + public processEvent(event: Event): Event { + const expoDeviceContext = getExpoDeviceContext(); + if (expoDeviceContext) { + event.contexts = event.contexts || {}; + event.contexts.device = { ...expoDeviceContext, ...event.contexts.device }; + } - const expoOsContext = getExpoOsContext(); - if (expoOsContext) { - event.contexts = event.contexts || {}; - event.contexts.os = { ...expoOsContext, ...event.contexts.os }; - } + const expoOsContext = getExpoOsContext(); + if (expoOsContext) { + event.contexts = event.contexts || {}; + event.contexts.os = { ...expoOsContext, ...event.contexts.os }; + } - return event; - }); + return event; } } diff --git a/test/integrations/expocontext.test.ts b/test/integrations/expocontext.test.ts index 95f24095d5..f101ec45b7 100644 --- a/test/integrations/expocontext.test.ts +++ b/test/integrations/expocontext.test.ts @@ -1,4 +1,3 @@ -import type { Hub } from '@sentry/core'; import type { Event } from '@sentry/types'; import { ExpoContext } from '../../src/js/integrations/expocontext'; @@ -9,11 +8,6 @@ jest.mock('../../src/js/utils/expomodules'); describe('Expo Context Integration', () => { let integration: ExpoContext; - const mockGetCurrentHub = () => - ({ - getIntegration: () => integration, - } as unknown as Hub); - beforeEach(() => { integration = new ExpoContext(); }); @@ -112,16 +106,8 @@ describe('Expo Context Integration', () => { }); }); - function executeIntegrationFor(mockedEvent: Event): Promise { - return new Promise((resolve, reject) => { - integration.setupOnce(async eventProcessor => { - try { - const processedEvent = await eventProcessor(mockedEvent, {}); - resolve(processedEvent); - } catch (e) { - reject(e); - } - }, mockGetCurrentHub); - }); + function executeIntegrationFor(mockedEvent: Event): Event { + return integration.processEvent(mockedEvent); } + }); From f0522edbbc347606dac686b7e9358bb70e5be930 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Fri, 2 Feb 2024 17:36:06 +0100 Subject: [PATCH 15/19] fix rewrite frames --- src/js/integrations/rewriteframes.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/integrations/rewriteframes.ts b/src/js/integrations/rewriteframes.ts index 844d55b221..04170d088a 100644 --- a/src/js/integrations/rewriteframes.ts +++ b/src/js/integrations/rewriteframes.ts @@ -1,4 +1,4 @@ -import { RewriteFrames } from '@sentry/integrations'; +import { rewriteFramesIntegration } from '@sentry/integrations'; import type { Integration, StackFrame } from '@sentry/types'; import { Platform } from 'react-native'; @@ -14,7 +14,7 @@ export const IOS_DEFAULT_BUNDLE_NAME = 'app:///main.jsbundle'; * and Expo bundle postfix. */ export function createReactNativeRewriteFrames(): Integration { - return new RewriteFrames({ + return rewriteFramesIntegration({ iteratee: (frame: StackFrame) => { if (frame.platform === 'java' || frame.platform === 'cocoa') { // Because platform is not required in StackFrame type From d8fd6e0efcbc04495f4a80000d9208468ac75f83 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Fri, 2 Feb 2024 17:42:32 +0100 Subject: [PATCH 16/19] fix spotlight --- src/js/integrations/spotlight.ts | 15 +++++++-------- test/integrations/spotlight.test.ts | 26 +++++++++----------------- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/src/js/integrations/spotlight.ts b/src/js/integrations/spotlight.ts index 156c975490..ea1f51214a 100644 --- a/src/js/integrations/spotlight.ts +++ b/src/js/integrations/spotlight.ts @@ -1,4 +1,4 @@ -import type { Client, Envelope, EventProcessor, Integration } from '@sentry/types'; +import type { BaseTransportOptions, Client, ClientOptions, Envelope, Integration } from '@sentry/types'; import { logger, serializeEnvelope } from '@sentry/utils'; import { makeUtf8TextEncoder } from '../transports/TextEncoder'; @@ -28,13 +28,12 @@ export function Spotlight({ return { name: 'Spotlight', - setupOnce(_: (callback: EventProcessor) => void, getCurrentHub) { - const client = getCurrentHub().getClient(); - if (client) { - setup(client, sidecarUrl); - } else { - logger.warn('[Spotlight] Could not initialize Sidecar integration due to missing Client'); - } + setupOnce(): void { + // nothing to do here + }, + + setup(client: Client>): void { + setup(client, sidecarUrl); }, }; } diff --git a/test/integrations/spotlight.test.ts b/test/integrations/spotlight.test.ts index 4afe47891c..4430983fb8 100644 --- a/test/integrations/spotlight.test.ts +++ b/test/integrations/spotlight.test.ts @@ -1,6 +1,6 @@ import type { HttpRequestEventMap } from '@mswjs/interceptors'; import { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'; -import type { Envelope, Hub } from '@sentry/types'; +import type { Client, Envelope } from '@sentry/types'; import { XMLHttpRequest } from 'xmlhttprequest'; import { Spotlight } from '../../src/js/integrations/spotlight'; @@ -20,15 +20,12 @@ describe('spotlight', () => { }); it('should not change the original envelope', () => { - const mockHub = createMockHub(); + const mockClient = createMockClient(); const spotlight = Spotlight(); - spotlight.setupOnce( - () => {}, - () => mockHub as unknown as Hub, - ); + spotlight.setup?.(mockClient as unknown as Client); - const spotlightBeforeEnvelope = mockHub.getClient().on.mock.calls[0]?.[1] as + const spotlightBeforeEnvelope = mockClient.on.mock.calls[0]?.[1] as | ((envelope: Envelope) => void) | undefined; @@ -40,15 +37,12 @@ describe('spotlight', () => { }); it('should remove image attachments from spotlight envelope', async () => { - const mockHub = createMockHub(); + const mockClient = createMockClient(); const spotlight = Spotlight(); - spotlight.setupOnce( - () => {}, - () => mockHub as unknown as Hub, - ); + spotlight.setup?.(mockClient as unknown as Client); - const spotlightBeforeEnvelope = mockHub.getClient().on.mock.calls[0]?.[1] as + const spotlightBeforeEnvelope = mockClient.on.mock.calls[0]?.[1] as | ((envelope: Envelope) => void) | undefined; @@ -60,14 +54,12 @@ describe('spotlight', () => { }); }); -function createMockHub() { +function createMockClient() { const client = { on: jest.fn(), }; - return { - getClient: jest.fn().mockReturnValue(client), - }; + return client; } function createMockEnvelope(): Envelope { From 9c0ec5dd8bd7723f22a2b26dfa64589e11ae96f9 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Fri, 2 Feb 2024 18:42:27 +0100 Subject: [PATCH 17/19] fix profiling integration --- src/js/profiling/integration.ts | 26 +++++++++++++++++++------- test/integrations/expocontext.test.ts | 1 - test/integrations/spotlight.test.ts | 8 ++------ test/profiling/integration.test.ts | 8 -------- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/js/profiling/integration.ts b/src/js/profiling/integration.ts index 1923a5a997..387e8fa35a 100644 --- a/src/js/profiling/integration.ts +++ b/src/js/profiling/integration.ts @@ -1,7 +1,10 @@ /* eslint-disable complexity */ import type { Hub } from '@sentry/core'; -import { getActiveTransaction } from '@sentry/core'; +import { getActiveTransaction, spanIsSampled } from '@sentry/core'; import type { + BaseTransportOptions, + Client, + ClientOptions, Envelope, Event, EventProcessor, @@ -46,6 +49,7 @@ export class HermesProfiling implements Integration { public name: string = HermesProfiling.id; private _getCurrentHub?: () => Hub; + private _client?: Client; private _currentProfile: | { @@ -58,19 +62,25 @@ export class HermesProfiling implements Integration { /** * @inheritDoc + * @deprecated */ public setupOnce(_: (e: EventProcessor) => void, getCurrentHub: () => Hub): void { + this._getCurrentHub = getCurrentHub; + } + + /** + * @inheritDoc + */ + public setup(client: Client>): void { if (!isHermesEnabled()) { logger.log('[Profiling] Hermes is not enabled, not adding profiling integration.'); return; } - this._getCurrentHub = getCurrentHub; - const client = getCurrentHub().getClient(); - if (!client || typeof client.on !== 'function') { return; } + this._client = client; this._startCurrentProfileForActiveTransaction(); client.on('startTransaction', this._startCurrentProfile); @@ -103,6 +113,7 @@ export class HermesProfiling implements Integration { if (this._currentProfile) { return; } + // eslint-disable-next-line deprecation/deprecation const transaction = this._getCurrentHub && getActiveTransaction(this._getCurrentHub()); transaction && this._startCurrentProfile(transaction); }; @@ -120,13 +131,12 @@ export class HermesProfiling implements Integration { }; private _shouldStartProfiling = (transaction: Transaction): boolean => { - if (!transaction.sampled) { + if (!spanIsSampled(transaction)) { logger.log('[Profiling] Transaction is not sampled, skipping profiling'); return false; } - const client = this._getCurrentHub && this._getCurrentHub().getClient(); - const options = client && client.getOptions(); + const options = this._client && this._client.getOptions(); const profilesSampleRate = options && options._experiments && typeof options._experiments.profilesSampleRate === 'number' @@ -159,8 +169,10 @@ export class HermesProfiling implements Integration { profile_id: uuid4(), startTimestampNs: profileStartTimestampNs, }; + // eslint-disable-next-line deprecation/deprecation transaction.setContext('profile', { profile_id: this._currentProfile.profile_id }); // @ts-expect-error profile_id is not part of the metadata type + // eslint-disable-next-line deprecation/deprecation transaction.setMetadata({ profile_id: this._currentProfile.profile_id }); logger.log('[Profiling] started profiling: ', this._currentProfile.profile_id); }; diff --git a/test/integrations/expocontext.test.ts b/test/integrations/expocontext.test.ts index f101ec45b7..d1ebd284e3 100644 --- a/test/integrations/expocontext.test.ts +++ b/test/integrations/expocontext.test.ts @@ -109,5 +109,4 @@ describe('Expo Context Integration', () => { function executeIntegrationFor(mockedEvent: Event): Event { return integration.processEvent(mockedEvent); } - }); diff --git a/test/integrations/spotlight.test.ts b/test/integrations/spotlight.test.ts index 4430983fb8..8c3f0c27a2 100644 --- a/test/integrations/spotlight.test.ts +++ b/test/integrations/spotlight.test.ts @@ -25,9 +25,7 @@ describe('spotlight', () => { const spotlight = Spotlight(); spotlight.setup?.(mockClient as unknown as Client); - const spotlightBeforeEnvelope = mockClient.on.mock.calls[0]?.[1] as - | ((envelope: Envelope) => void) - | undefined; + const spotlightBeforeEnvelope = mockClient.on.mock.calls[0]?.[1] as ((envelope: Envelope) => void) | undefined; const originalEnvelopeReference = createMockEnvelope(); spotlightBeforeEnvelope?.(originalEnvelopeReference); @@ -42,9 +40,7 @@ describe('spotlight', () => { const spotlight = Spotlight(); spotlight.setup?.(mockClient as unknown as Client); - const spotlightBeforeEnvelope = mockClient.on.mock.calls[0]?.[1] as - | ((envelope: Envelope) => void) - | undefined; + const spotlightBeforeEnvelope = mockClient.on.mock.calls[0]?.[1] as ((envelope: Envelope) => void) | undefined; spotlightBeforeEnvelope?.(createMockEnvelope()); diff --git a/test/profiling/integration.test.ts b/test/profiling/integration.test.ts index 949831131d..7154205511 100644 --- a/test/profiling/integration.test.ts +++ b/test/profiling/integration.test.ts @@ -354,14 +354,6 @@ function initTestClient( } Sentry.init(options); - // In production integrations are setup only once, but in the tests we want them to setup on every init - const integrations = Sentry.getCurrentHub().getClient()?.getOptions().integrations; - if (integrations) { - for (const integration of integrations) { - integration.setupOnce(Sentry.addGlobalEventProcessor, Sentry.getCurrentHub); - } - } - return { transportSendMock, }; From 84b1f5cb16bbb7a520cc4614a1af682ef3aaabac Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Fri, 2 Feb 2024 19:21:03 +0100 Subject: [PATCH 18/19] fix sdk main file --- src/js/sdk.tsx | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/js/sdk.tsx b/src/js/sdk.tsx index 4a753d1dad..adefddf1e4 100644 --- a/src/js/sdk.tsx +++ b/src/js/sdk.tsx @@ -1,6 +1,6 @@ /* eslint-disable complexity */ import type { Scope } from '@sentry/core'; -import { getIntegrationsToSetup, Hub, initAndBind, makeMain, setExtra } from '@sentry/core'; +import { getClient, getIntegrationsToSetup, Hub, initAndBind, makeMain, setExtra, withScope as coreWithScope } from '@sentry/core'; import { defaultStackParser, getCurrentHub, @@ -16,7 +16,8 @@ import type { ReactNativeClientOptions, ReactNativeOptions, ReactNativeWrapperOp import { shouldEnableNativeNagger } from './options'; import { ReactNativeScope } from './scope'; import { TouchEventBoundary } from './touchevents'; -import { ReactNativeProfiler, ReactNativeTracing } from './tracing'; +import type { ReactNativeTracing } from './tracing'; +import { ReactNativeProfiler } from './tracing'; import { DEFAULT_BUFFER_SIZE, makeNativeTransportFactory } from './transports/native'; import { makeUtf8TextEncoder } from './transports/TextEncoder'; import { getDefaultEnvironment, isExpoGo } from './utils/environment'; @@ -45,6 +46,7 @@ const DEFAULT_OPTIONS: ReactNativeOptions = { */ export function init(passedOptions: ReactNativeOptions): void { const reactNativeHub = new Hub(undefined, new ReactNativeScope()); + // eslint-disable-next-line deprecation/deprecation makeMain(reactNativeHub); const maxQueueSize = passedOptions.maxQueueSize @@ -108,7 +110,7 @@ export function wrap

>( RootComponent: React.ComponentType

, options?: ReactNativeWrapperOptions ): React.ComponentType

{ - const tracingIntegration = getCurrentHub().getIntegration(ReactNativeTracing); + const tracingIntegration = getClient()?.getIntegrationByName?.('ReactNativeTracing') as ReactNativeTracing | undefined; if (tracingIntegration) { tracingIntegration.useAppStartWithProfiler = true; } @@ -154,10 +156,7 @@ export function setDist(dist: string): void { * Use this only for testing purposes. */ export function nativeCrash(): void { - const client = getCurrentHub().getClient(); - if (client) { - client.nativeCrash(); - } + NATIVE.nativeCrash(); } /** @@ -166,7 +165,7 @@ export function nativeCrash(): void { */ export async function flush(): Promise { try { - const client = getCurrentHub().getClient(); + const client = getClient(); if (client) { const result = await client.flush(); @@ -186,7 +185,7 @@ export async function flush(): Promise { */ export async function close(): Promise { try { - const client = getCurrentHub().getClient(); + const client = getClient(); if (client) { await client.close(); @@ -200,7 +199,7 @@ export async function close(): Promise { * Captures user feedback and sends it to Sentry. */ export function captureUserFeedback(feedback: UserFeedback): void { - getCurrentHub().getClient()?.captureUserFeedback(feedback); + getClient()?.captureUserFeedback(feedback); } /** @@ -225,12 +224,14 @@ export function withScope(callback: (scope: Scope) => T): T | undefined { return undefined; } }; - return getCurrentHub().withScope(safeCallback); + return coreWithScope(safeCallback); } /** * Callback to set context information onto the scope. * @param callback Callback function that receives Scope. + * + * @deprecated Use `getScope()` directly. */ export function configureScope(callback: (scope: Scope) => void): ReturnType { const safeCallback = (scope: Scope): void => { @@ -240,5 +241,6 @@ export function configureScope(callback: (scope: Scope) => void): ReturnType Date: Fri, 2 Feb 2024 19:40:12 +0100 Subject: [PATCH 19/19] more fixes --- src/js/index.ts | 1 + src/js/touchevents.tsx | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/js/index.ts b/src/js/index.ts index 6918f8d5bd..907eedabda 100644 --- a/src/js/index.ts +++ b/src/js/index.ts @@ -71,6 +71,7 @@ export { close, captureUserFeedback, withScope, + // eslint-disable-next-line deprecation/deprecation configureScope, } from './sdk'; export { TouchEventBoundary, withTouchEventBoundary } from './touchevents'; diff --git a/src/js/touchevents.tsx b/src/js/touchevents.tsx index fa58273baf..b3fa77aeb1 100644 --- a/src/js/touchevents.tsx +++ b/src/js/touchevents.tsx @@ -1,4 +1,4 @@ -import { addBreadcrumb, getCurrentHub } from '@sentry/core'; +import { addBreadcrumb, getClient } from '@sentry/core'; import type { SeverityLevel } from '@sentry/types'; import { logger } from '@sentry/utils'; import * as React from 'react'; @@ -6,7 +6,7 @@ import type { GestureResponderEvent} from 'react-native'; import { StyleSheet, View } from 'react-native'; import { createIntegration } from './integrations/factory'; -import { ReactNativeTracing } from './tracing'; +import type { ReactNativeTracing } from './tracing'; import { UI_ACTION_TOUCH } from './tracing/ops'; export type TouchEventBoundaryProps = { @@ -88,10 +88,10 @@ class TouchEventBoundary extends React.Component { * Registers the TouchEventBoundary as a Sentry Integration. */ public componentDidMount(): void { - const client = getCurrentHub().getClient(); + const client = getClient(); client?.addIntegration?.(createIntegration(this.name)); if (!this._tracingIntegration && client) { - this._tracingIntegration = client.getIntegration(ReactNativeTracing); + this._tracingIntegration = client.getIntegrationByName?.('ReactNativeTracing') as ReactNativeTracing|| null; } }