From 9dbe87e425a13457cb406c6c12614aede3109784 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 17 Jan 2024 16:11:02 +0100 Subject: [PATCH] feat(integrations): Deprecate pluggable integration classes (#10211) Instead, users should import & use the integration functions. --- packages/integrations/src/captureconsole.ts | 18 ++++++-- packages/integrations/src/contextlines.ts | 8 +++- packages/integrations/src/debug.ts | 10 ++-- packages/integrations/src/dedupe.ts | 11 +++-- packages/integrations/src/extraerrordata.ts | 11 +++-- packages/integrations/src/httpclient.ts | 17 +++++-- packages/integrations/src/index.ts | 21 ++++----- .../integrations/src/reportingobserver.ts | 11 +++-- packages/integrations/src/rewriteframes.ts | 11 +++-- packages/integrations/src/sessiontiming.ts | 11 +++-- .../integrations/test/captureconsole.test.ts | 46 +++++++++++-------- packages/integrations/test/debug.test.ts | 14 ++++-- packages/integrations/test/dedupe.test.ts | 10 +++- .../integrations/test/extraerrordata.test.ts | 12 +++-- .../test/reportingobserver.test.ts | 40 +++++++++------- .../integrations/test/rewriteframes.test.ts | 26 +++++++---- .../integrations/test/sessiontiming.test.ts | 1 + packages/nextjs/src/client/index.ts | 1 + packages/nextjs/src/edge/index.ts | 1 + packages/nextjs/src/server/index.ts | 1 + packages/sveltekit/src/server/sdk.ts | 1 + packages/sveltekit/test/server/utils.test.ts | 2 + 22 files changed, 191 insertions(+), 93 deletions(-) diff --git a/packages/integrations/src/captureconsole.ts b/packages/integrations/src/captureconsole.ts index ece89c0ac38c..9bd6c45c8851 100644 --- a/packages/integrations/src/captureconsole.ts +++ b/packages/integrations/src/captureconsole.ts @@ -1,4 +1,11 @@ -import { captureException, captureMessage, convertIntegrationFnToClass, getClient, withScope } from '@sentry/core'; +import { + captureException, + captureMessage, + convertIntegrationFnToClass, + defineIntegration, + getClient, + withScope, +} from '@sentry/core'; import type { CaptureContext, Client, Integration, IntegrationClass, IntegrationFn } from '@sentry/types'; import { CONSOLE_LEVELS, @@ -15,7 +22,7 @@ interface CaptureConsoleOptions { const INTEGRATION_NAME = 'CaptureConsole'; -const captureConsoleIntegration = ((options: CaptureConsoleOptions = {}) => { +const _captureConsoleIntegration = ((options: CaptureConsoleOptions = {}) => { const levels = options.levels || CONSOLE_LEVELS; return { @@ -38,7 +45,12 @@ const captureConsoleIntegration = ((options: CaptureConsoleOptions = {}) => { }; }) satisfies IntegrationFn; -/** Send Console API calls as Sentry Events */ +export const captureConsoleIntegration = defineIntegration(_captureConsoleIntegration); + +/** + * Send Console API calls as Sentry Events. + * @deprecated Use `captureConsoleIntegration()` instead. + */ // eslint-disable-next-line deprecation/deprecation export const CaptureConsole = convertIntegrationFnToClass( INTEGRATION_NAME, diff --git a/packages/integrations/src/contextlines.ts b/packages/integrations/src/contextlines.ts index 86647fd8a769..f9835ad2f0f5 100644 --- a/packages/integrations/src/contextlines.ts +++ b/packages/integrations/src/contextlines.ts @@ -1,4 +1,4 @@ -import { convertIntegrationFnToClass } from '@sentry/core'; +import { convertIntegrationFnToClass, defineIntegration } from '@sentry/core'; import type { Event, Integration, IntegrationClass, IntegrationFn, StackFrame } from '@sentry/types'; import { GLOBAL_OBJ, addContextToFrame, stripUrlQueryAndFragment } from '@sentry/utils'; @@ -18,7 +18,7 @@ interface ContextLinesOptions { frameContextLines?: number; } -const contextLinesIntegration = ((options: ContextLinesOptions = {}) => { +const _contextLinesIntegration = ((options: ContextLinesOptions = {}) => { const contextLines = options.frameContextLines != null ? options.frameContextLines : DEFAULT_LINES_OF_CONTEXT; return { @@ -31,6 +31,8 @@ const contextLinesIntegration = ((options: ContextLinesOptions = {}) => { }; }) satisfies IntegrationFn; +export const contextLinesIntegration = defineIntegration(_contextLinesIntegration); + /** * Collects source context lines around the lines of stackframes pointing to JS embedded in * the current page's HTML. @@ -41,6 +43,8 @@ const contextLinesIntegration = ((options: ContextLinesOptions = {}) => { * * Use this integration if you have inline JS code in HTML pages that can't be accessed * by our backend (e.g. due to a login-protected page). + * + * @deprecated Use `contextLinesIntegration()` instead. */ // eslint-disable-next-line deprecation/deprecation export const ContextLines = convertIntegrationFnToClass(INTEGRATION_NAME, contextLinesIntegration) as IntegrationClass< diff --git a/packages/integrations/src/debug.ts b/packages/integrations/src/debug.ts index 159d8a462bea..3e76353688d3 100644 --- a/packages/integrations/src/debug.ts +++ b/packages/integrations/src/debug.ts @@ -1,4 +1,4 @@ -import { convertIntegrationFnToClass } from '@sentry/core'; +import { convertIntegrationFnToClass, defineIntegration } from '@sentry/core'; import type { Client, Event, EventHint, Integration, IntegrationClass, IntegrationFn } from '@sentry/types'; import { consoleSandbox } from '@sentry/utils'; @@ -11,7 +11,7 @@ interface DebugOptions { debugger?: boolean; } -const debugIntegration = ((options: DebugOptions = {}) => { +const _debugIntegration = ((options: DebugOptions = {}) => { const _options = { debugger: false, stringify: false, @@ -53,9 +53,13 @@ const debugIntegration = ((options: DebugOptions = {}) => { }; }) satisfies IntegrationFn; +export const debugIntegration = defineIntegration(_debugIntegration); + /** * Integration to debug sent Sentry events. - * This integration should not be used in production + * This integration should not be used in production. + * + * @deprecated Use `debugIntegration()` instead. */ // eslint-disable-next-line deprecation/deprecation export const Debug = convertIntegrationFnToClass(INTEGRATION_NAME, debugIntegration) as IntegrationClass< diff --git a/packages/integrations/src/dedupe.ts b/packages/integrations/src/dedupe.ts index 996fd6161f9f..f230bc4f0621 100644 --- a/packages/integrations/src/dedupe.ts +++ b/packages/integrations/src/dedupe.ts @@ -1,4 +1,4 @@ -import { convertIntegrationFnToClass } from '@sentry/core'; +import { convertIntegrationFnToClass, defineIntegration } from '@sentry/core'; import type { Event, Exception, Integration, IntegrationClass, IntegrationFn, StackFrame } from '@sentry/types'; import { logger } from '@sentry/utils'; @@ -6,7 +6,7 @@ import { DEBUG_BUILD } from './debug-build'; const INTEGRATION_NAME = 'Dedupe'; -const dedupeIntegration = (() => { +const _dedupeIntegration = (() => { let previousEvent: Event | undefined; return { @@ -33,7 +33,12 @@ const dedupeIntegration = (() => { }; }) satisfies IntegrationFn; -/** Deduplication filter */ +export const dedupeIntegration = defineIntegration(_dedupeIntegration); + +/** + * Deduplication filter. + * @deprecated Use `dedupeIntegration()` instead. + */ // eslint-disable-next-line deprecation/deprecation export const Dedupe = convertIntegrationFnToClass(INTEGRATION_NAME, dedupeIntegration) as IntegrationClass< Integration & { processEvent: (event: Event) => Event } diff --git a/packages/integrations/src/extraerrordata.ts b/packages/integrations/src/extraerrordata.ts index 41c4668f49de..d1d6ae5f0b5d 100644 --- a/packages/integrations/src/extraerrordata.ts +++ b/packages/integrations/src/extraerrordata.ts @@ -1,4 +1,4 @@ -import { convertIntegrationFnToClass } from '@sentry/core'; +import { convertIntegrationFnToClass, defineIntegration } from '@sentry/core'; import type { Contexts, Event, @@ -28,7 +28,7 @@ interface ExtraErrorDataOptions { captureErrorCause: boolean; } -const extraErrorDataIntegration = ((options: Partial = {}) => { +const _extraErrorDataIntegration = ((options: Partial = {}) => { const depth = options.depth || 3; // TODO(v8): Flip the default for this option to true @@ -44,7 +44,12 @@ const extraErrorDataIntegration = ((options: Partial = {} }; }) satisfies IntegrationFn; -/** Extract additional data for from original exceptions. */ +export const extraErrorDataIntegration = defineIntegration(_extraErrorDataIntegration); + +/** + * Extract additional data for from original exceptions. + * @deprecated Use `extraErrorDataIntegration()` instead. + */ // eslint-disable-next-line deprecation/deprecation export const ExtraErrorData = convertIntegrationFnToClass( INTEGRATION_NAME, diff --git a/packages/integrations/src/httpclient.ts b/packages/integrations/src/httpclient.ts index 4368beab8364..0ae0b2d41184 100644 --- a/packages/integrations/src/httpclient.ts +++ b/packages/integrations/src/httpclient.ts @@ -1,4 +1,10 @@ -import { captureEvent, convertIntegrationFnToClass, getClient, isSentryRequestUrl } from '@sentry/core'; +import { + captureEvent, + convertIntegrationFnToClass, + defineIntegration, + getClient, + isSentryRequestUrl, +} from '@sentry/core'; import type { Client, Event as SentryEvent, @@ -45,7 +51,7 @@ interface HttpClientOptions { failedRequestTargets: HttpRequestTarget[]; } -const httpClientIntegration = ((options: Partial = {}) => { +const _httpClientIntegration = ((options: Partial = {}) => { const _options: HttpClientOptions = { failedRequestStatusCodes: [[500, 599]], failedRequestTargets: [/.*/], @@ -63,7 +69,12 @@ const httpClientIntegration = ((options: Partial = {}) => { }; }) satisfies IntegrationFn; -/** HTTPClient integration creates events for failed client side HTTP requests. */ +export const httpClientIntegration = defineIntegration(_httpClientIntegration); + +/** + * Create events for failed client side HTTP requests. + * @deprecated Use `httpClientIntegration()` instead. + */ // eslint-disable-next-line deprecation/deprecation export const HttpClient = convertIntegrationFnToClass(INTEGRATION_NAME, httpClientIntegration) as IntegrationClass< Integration & { setup: (client: Client) => void } diff --git a/packages/integrations/src/index.ts b/packages/integrations/src/index.ts index 2b7b986345ec..445e10fa463e 100644 --- a/packages/integrations/src/index.ts +++ b/packages/integrations/src/index.ts @@ -1,13 +1,12 @@ -export { CaptureConsole } from './captureconsole'; -export { Debug } from './debug'; -export { Dedupe } from './dedupe'; -export { ExtraErrorData } from './extraerrordata'; -// eslint-disable-next-line deprecation/deprecation +/* eslint-disable deprecation/deprecation */ +export { CaptureConsole, captureConsoleIntegration } from './captureconsole'; +export { Debug, debugIntegration } from './debug'; +export { Dedupe, dedupeIntegration } from './dedupe'; +export { ExtraErrorData, extraErrorDataIntegration } from './extraerrordata'; export { Offline } from './offline'; -export { ReportingObserver } from './reportingobserver'; -export { RewriteFrames } from './rewriteframes'; -export { SessionTiming } from './sessiontiming'; -// eslint-disable-next-line deprecation/deprecation +export { ReportingObserver, reportingObserverIntegration } from './reportingobserver'; +export { RewriteFrames, rewriteFramesIntegration } from './rewriteframes'; +export { SessionTiming, sessionTimingIntegration } from './sessiontiming'; export { Transaction } from './transaction'; -export { HttpClient } from './httpclient'; -export { ContextLines } from './contextlines'; +export { HttpClient, httpClientIntegration } from './httpclient'; +export { ContextLines, contextLinesIntegration } from './contextlines'; diff --git a/packages/integrations/src/reportingobserver.ts b/packages/integrations/src/reportingobserver.ts index 39c7da5ce97c..b22133d771fe 100644 --- a/packages/integrations/src/reportingobserver.ts +++ b/packages/integrations/src/reportingobserver.ts @@ -1,4 +1,4 @@ -import { captureMessage, convertIntegrationFnToClass, getClient, withScope } from '@sentry/core'; +import { captureMessage, convertIntegrationFnToClass, defineIntegration, getClient, withScope } from '@sentry/core'; import type { Client, Integration, IntegrationClass, IntegrationFn } from '@sentry/types'; import { GLOBAL_OBJ, supportsReportingObserver } from '@sentry/utils'; @@ -48,7 +48,7 @@ interface ReportingObserverOptions { const SETUP_CLIENTS = new WeakMap(); -const reportingObserverIntegration = ((options: ReportingObserverOptions = {}) => { +const _reportingObserverIntegration = ((options: ReportingObserverOptions = {}) => { const types = options.types || ['crash', 'deprecation', 'intervention']; /** Handler for the reporting observer. */ @@ -115,7 +115,12 @@ const reportingObserverIntegration = ((options: ReportingObserverOptions = {}) = }; }) satisfies IntegrationFn; -/** Reporting API integration - https://w3c.github.io/reporting/ */ +export const reportingObserverIntegration = defineIntegration(_reportingObserverIntegration); + +/** + * Reporting API integration - https://w3c.github.io/reporting/ + * @deprecated Use `reportingObserverIntegration()` instead. + */ // eslint-disable-next-line deprecation/deprecation export const ReportingObserver = convertIntegrationFnToClass( INTEGRATION_NAME, diff --git a/packages/integrations/src/rewriteframes.ts b/packages/integrations/src/rewriteframes.ts index 31e9691df261..8d6441649e3d 100644 --- a/packages/integrations/src/rewriteframes.ts +++ b/packages/integrations/src/rewriteframes.ts @@ -1,4 +1,4 @@ -import { convertIntegrationFnToClass } from '@sentry/core'; +import { convertIntegrationFnToClass, defineIntegration } from '@sentry/core'; import type { Event, Integration, IntegrationClass, IntegrationFn, StackFrame, Stacktrace } from '@sentry/types'; import { basename, relative } from '@sentry/utils'; @@ -12,7 +12,7 @@ interface RewriteFramesOptions { iteratee?: StackFrameIteratee; } -const rewriteFramesIntegration = ((options: RewriteFramesOptions = {}) => { +const _rewriteFramesIntegration = ((options: RewriteFramesOptions = {}) => { const root = options.root; const prefix = options.prefix || 'app:///'; @@ -85,7 +85,12 @@ const rewriteFramesIntegration = ((options: RewriteFramesOptions = {}) => { }; }) satisfies IntegrationFn; -/** Rewrite event frames paths */ +export const rewriteFramesIntegration = defineIntegration(_rewriteFramesIntegration); + +/** + * Rewrite event frames paths. + * @deprecated Use `rewriteFramesIntegration()` instead. + */ // eslint-disable-next-line deprecation/deprecation export const RewriteFrames = convertIntegrationFnToClass( INTEGRATION_NAME, diff --git a/packages/integrations/src/sessiontiming.ts b/packages/integrations/src/sessiontiming.ts index 0a316ca02381..81ef3f2627be 100644 --- a/packages/integrations/src/sessiontiming.ts +++ b/packages/integrations/src/sessiontiming.ts @@ -1,9 +1,9 @@ -import { convertIntegrationFnToClass } from '@sentry/core'; +import { convertIntegrationFnToClass, defineIntegration } from '@sentry/core'; import type { Event, Integration, IntegrationClass, IntegrationFn } from '@sentry/types'; const INTEGRATION_NAME = 'SessionTiming'; -const sessionTimingIntegration = (() => { +const _sessionTimingIntegration = (() => { const startTime = Date.now(); return { @@ -26,7 +26,12 @@ const sessionTimingIntegration = (() => { }; }) satisfies IntegrationFn; -/** This function adds duration since Sentry was initialized till the time event was sent */ +export const sessionTimingIntegration = defineIntegration(_sessionTimingIntegration); + +/** + * This function adds duration since Sentry was initialized till the time event was sent. + * @deprecated Use `sessionTimingIntegration()` instead. + */ // eslint-disable-next-line deprecation/deprecation export const SessionTiming = convertIntegrationFnToClass( INTEGRATION_NAME, diff --git a/packages/integrations/test/captureconsole.test.ts b/packages/integrations/test/captureconsole.test.ts index 23a410f0bb33..8452f2fe6e27 100644 --- a/packages/integrations/test/captureconsole.test.ts +++ b/packages/integrations/test/captureconsole.test.ts @@ -10,6 +10,7 @@ import { resetInstrumentationHandlers, } from '@sentry/utils'; +import type { captureConsoleIntegration } from '../src/captureconsole'; import { CaptureConsole } from '../src/captureconsole'; const mockConsole: { [key in ConsoleLevel]: jest.Mock } = { @@ -22,6 +23,11 @@ const mockConsole: { [key in ConsoleLevel]: jest.Mock } = { trace: jest.fn(), }; +function getIntegration(...args: Parameters) { + // eslint-disable-next-line deprecation/deprecation + return new CaptureConsole(...args); +} + describe('CaptureConsole setup', () => { // Ensure we've initialized the instrumentation so we can get the original one addConsoleInstrumentationHandler(() => {}); @@ -65,7 +71,7 @@ describe('CaptureConsole setup', () => { describe('monkeypatching', () => { it('should patch user-configured console levels', () => { - const captureConsoleIntegration = new CaptureConsole({ levels: ['log', 'warn'] }); + const captureConsoleIntegration = getIntegration({ levels: ['log', 'warn'] }); captureConsoleIntegration.setup(mockClient); GLOBAL_OBJ.console.error('msg 1'); @@ -76,7 +82,7 @@ describe('CaptureConsole setup', () => { }); it('should fall back to default console levels if none are provided', () => { - const captureConsoleIntegration = new CaptureConsole(); + const captureConsoleIntegration = getIntegration(); captureConsoleIntegration.setup(mockClient); // Assert has a special handling @@ -90,7 +96,7 @@ describe('CaptureConsole setup', () => { }); it('should not wrap any functions with an empty levels option', () => { - const captureConsoleIntegration = new CaptureConsole({ levels: [] }); + const captureConsoleIntegration = getIntegration({ levels: [] }); captureConsoleIntegration.setup(mockClient); CONSOLE_LEVELS.forEach(key => { @@ -106,7 +112,7 @@ describe('CaptureConsole setup', () => { // @ts-expect-error remove console delete GLOBAL_OBJ.console; - const captureConsoleIntegration = new CaptureConsole(); + const captureConsoleIntegration = getIntegration(); expect(() => { captureConsoleIntegration.setup(mockClient); }).not.toThrow(); @@ -116,7 +122,7 @@ describe('CaptureConsole setup', () => { }); it('should send empty arguments as extra data', () => { - const captureConsoleIntegration = new CaptureConsole({ levels: ['log'] }); + const captureConsoleIntegration = getIntegration({ levels: ['log'] }); captureConsoleIntegration.setup(mockClient); GLOBAL_OBJ.console.log(); @@ -126,7 +132,7 @@ describe('CaptureConsole setup', () => { }); it('should add an event processor that sets the `logger` field of events', () => { - const captureConsoleIntegration = new CaptureConsole({ levels: ['log'] }); + const captureConsoleIntegration = getIntegration({ levels: ['log'] }); captureConsoleIntegration.setup(mockClient); // call a wrapped function @@ -142,7 +148,7 @@ describe('CaptureConsole setup', () => { }); it('should capture message on a failed assertion', () => { - const captureConsoleIntegration = new CaptureConsole({ levels: ['assert'] }); + const captureConsoleIntegration = getIntegration({ levels: ['assert'] }); captureConsoleIntegration.setup(mockClient); GLOBAL_OBJ.console.assert(1 + 1 === 3); @@ -156,7 +162,7 @@ describe('CaptureConsole setup', () => { }); it('should capture correct message on a failed assertion with message', () => { - const captureConsoleIntegration = new CaptureConsole({ levels: ['assert'] }); + const captureConsoleIntegration = getIntegration({ levels: ['assert'] }); captureConsoleIntegration.setup(mockClient); GLOBAL_OBJ.console.assert(1 + 1 === 3, 'expression is false'); @@ -170,14 +176,14 @@ describe('CaptureConsole setup', () => { }); it('should not capture message on a successful assertion', () => { - const captureConsoleIntegration = new CaptureConsole({ levels: ['assert'] }); + const captureConsoleIntegration = getIntegration({ levels: ['assert'] }); captureConsoleIntegration.setup(mockClient); GLOBAL_OBJ.console.assert(1 + 1 === 2); }); it('should capture exception when console logs an error object with level set to "error"', () => { - const captureConsoleIntegration = new CaptureConsole({ levels: ['error'] }); + const captureConsoleIntegration = getIntegration({ levels: ['error'] }); captureConsoleIntegration.setup(mockClient); const someError = new Error('some error'); @@ -191,7 +197,7 @@ describe('CaptureConsole setup', () => { }); it('should capture exception on `console.error` when no levels are provided in constructor', () => { - const captureConsoleIntegration = new CaptureConsole(); + const captureConsoleIntegration = getIntegration(); captureConsoleIntegration.setup(mockClient); const someError = new Error('some error'); @@ -205,7 +211,7 @@ describe('CaptureConsole setup', () => { }); it('should capture exception when console logs an error object in any of the args when level set to "error"', () => { - const captureConsoleIntegration = new CaptureConsole({ levels: ['error'] }); + const captureConsoleIntegration = getIntegration({ levels: ['error'] }); captureConsoleIntegration.setup(mockClient); const someError = new Error('some error'); @@ -219,7 +225,7 @@ describe('CaptureConsole setup', () => { }); it('should capture message on `console.log` when no levels are provided in constructor', () => { - const captureConsoleIntegration = new CaptureConsole(); + const captureConsoleIntegration = getIntegration(); captureConsoleIntegration.setup(mockClient); GLOBAL_OBJ.console.error('some message'); @@ -232,7 +238,7 @@ describe('CaptureConsole setup', () => { }); it('should capture message when console logs a non-error object with level set to "error"', () => { - const captureConsoleIntegration = new CaptureConsole({ levels: ['error'] }); + const captureConsoleIntegration = getIntegration({ levels: ['error'] }); captureConsoleIntegration.setup(mockClient); GLOBAL_OBJ.console.error('some non-error message'); @@ -246,7 +252,7 @@ describe('CaptureConsole setup', () => { }); it('should capture a message for non-error log levels', () => { - const captureConsoleIntegration = new CaptureConsole({ levels: ['info'] }); + const captureConsoleIntegration = getIntegration({ levels: ['info'] }); captureConsoleIntegration.setup(mockClient); GLOBAL_OBJ.console.info('some message'); @@ -264,7 +270,7 @@ describe('CaptureConsole setup', () => { const mockConsoleLog = jest.fn(); GLOBAL_OBJ.console.log = mockConsoleLog; - const captureConsoleIntegration = new CaptureConsole({ levels: ['log'] }); + const captureConsoleIntegration = getIntegration({ levels: ['log'] }); captureConsoleIntegration.setup(mockClient); GLOBAL_OBJ.console.log('some message 1', 'some message 2'); @@ -277,7 +283,7 @@ describe('CaptureConsole setup', () => { }); it('should not wrap any levels that are not members of console', () => { - const captureConsoleIntegration = new CaptureConsole({ levels: ['log', 'someNonExistingLevel', 'error'] }); + const captureConsoleIntegration = getIntegration({ levels: ['log', 'someNonExistingLevel', 'error'] }); captureConsoleIntegration.setup(mockClient); // The provided level should not be created @@ -285,7 +291,7 @@ describe('CaptureConsole setup', () => { }); it('should wrap the console when the client does not have a registered captureconsole integration, but not capture any messages', () => { - const captureConsoleIntegration = new CaptureConsole({ levels: ['log', 'error'] }); + const captureConsoleIntegration = getIntegration({ levels: ['log', 'error'] }); // when `setup` is not called on the current client, it will not trigger captureConsoleIntegration.setup({} as Client); @@ -297,7 +303,7 @@ describe('CaptureConsole setup', () => { it("should not crash when the original console methods don't exist at time of invocation", () => { originalConsoleMethods.log = undefined; - const captureConsoleIntegration = new CaptureConsole({ levels: ['log'] }); + const captureConsoleIntegration = getIntegration({ levels: ['log'] }); captureConsoleIntegration.setup(mockClient); expect(() => { @@ -308,7 +314,7 @@ describe('CaptureConsole setup', () => { it("marks captured exception's mechanism as unhandled", () => { // const addExceptionMechanismSpy = jest.spyOn(utils, 'addExceptionMechanism'); - const captureConsoleIntegration = new CaptureConsole({ levels: ['error'] }); + const captureConsoleIntegration = getIntegration({ levels: ['error'] }); captureConsoleIntegration.setup(mockClient); const someError = new Error('some error'); diff --git a/packages/integrations/test/debug.test.ts b/packages/integrations/test/debug.test.ts index 1cb952f26a5a..b0d922b6de9f 100644 --- a/packages/integrations/test/debug.test.ts +++ b/packages/integrations/test/debug.test.ts @@ -1,11 +1,17 @@ import type { Client, Event, EventHint, Integration } from '@sentry/types'; +import type { debugIntegration } from '../src/debug'; import { Debug } from '../src/debug'; interface IntegrationWithSetup extends Integration { setup: (client: Client) => void; } +function getIntegration(...args: Parameters) { + // eslint-disable-next-line deprecation/deprecation + return new Debug(...args); +} + function testEventLogged(integration: IntegrationWithSetup, testEvent?: Event, testEventHint?: EventHint) { const callbacks: ((event: Event, hint?: EventHint) => void)[] = []; @@ -42,7 +48,7 @@ describe('Debug integration setup should register an event processor that', () = }); it('logs an event', () => { - const debugIntegration = new Debug(); + const debugIntegration = getIntegration(); const testEvent = { event_id: 'some event' }; testEventLogged(debugIntegration, testEvent); @@ -52,7 +58,7 @@ describe('Debug integration setup should register an event processor that', () = }); it('logs an event hint if available', () => { - const debugIntegration = new Debug(); + const debugIntegration = getIntegration(); const testEvent = { event_id: 'some event' }; const testEventHint = { event_id: 'some event hint' }; @@ -65,7 +71,7 @@ describe('Debug integration setup should register an event processor that', () = }); it('logs events in stringified format when `stringify` option was set', () => { - const debugIntegration = new Debug({ stringify: true }); + const debugIntegration = getIntegration({ stringify: true }); const testEvent = { event_id: 'some event' }; testEventLogged(debugIntegration, testEvent); @@ -75,7 +81,7 @@ describe('Debug integration setup should register an event processor that', () = }); it('logs event hints in stringified format when `stringify` option was set', () => { - const debugIntegration = new Debug({ stringify: true }); + const debugIntegration = getIntegration({ stringify: true }); const testEvent = { event_id: 'some event' }; const testEventHint = { event_id: 'some event hint' }; diff --git a/packages/integrations/test/dedupe.test.ts b/packages/integrations/test/dedupe.test.ts index bb996fa45960..65bf7a5bbfb9 100644 --- a/packages/integrations/test/dedupe.test.ts +++ b/packages/integrations/test/dedupe.test.ts @@ -1,5 +1,6 @@ import type { Event as SentryEvent, Exception, StackFrame, Stacktrace } from '@sentry/types'; +import type { dedupeIntegration } from '../src/dedupe'; import { Dedupe, _shouldDropEvent } from '../src/dedupe'; type EventWithException = SentryEvent & { @@ -14,6 +15,11 @@ function clone(data: T): T { return JSON.parse(JSON.stringify(data)); } +function getIntegration(...args: Parameters) { + // eslint-disable-next-line deprecation/deprecation + return new Dedupe(...args); +} + const messageEvent: EventWithException = { fingerprint: ['MrSnuffles'], message: 'PickleRick', @@ -177,7 +183,7 @@ describe('Dedupe', () => { describe('processEvent', () => { it('ignores consecutive errors', () => { - const integration = new Dedupe(); + const integration = getIntegration(); expect(integration.processEvent(clone(exceptionEvent))).not.toBeNull(); expect(integration.processEvent(clone(exceptionEvent))).toBeNull(); @@ -185,7 +191,7 @@ describe('Dedupe', () => { }); it('ignores transactions between errors', () => { - const integration = new Dedupe(); + const integration = getIntegration(); expect(integration.processEvent(clone(exceptionEvent))).not.toBeNull(); expect( diff --git a/packages/integrations/test/extraerrordata.test.ts b/packages/integrations/test/extraerrordata.test.ts index d72a43c57f8b..b53b98885357 100644 --- a/packages/integrations/test/extraerrordata.test.ts +++ b/packages/integrations/test/extraerrordata.test.ts @@ -1,8 +1,14 @@ import type { Event as SentryEvent, ExtendedError } from '@sentry/types'; +import type { extraErrorDataIntegration } from '../src/extraerrordata'; import { ExtraErrorData } from '../src/extraerrordata'; -const extraErrorData = new ExtraErrorData(); +function getIntegration(...args: Parameters) { + // eslint-disable-next-line deprecation/deprecation + return new ExtraErrorData(...args); +} + +const extraErrorData = getIntegration(); let event: SentryEvent; describe('ExtraErrorData()', () => { @@ -186,7 +192,7 @@ describe('ExtraErrorData()', () => { return; } - const extraErrorDataWithCauseCapture = new ExtraErrorData({ captureErrorCause: true }); + const extraErrorDataWithCauseCapture = getIntegration({ captureErrorCause: true }); // @ts-expect-error The typing .d.ts library we have installed isn't aware of Error.cause yet const error = new Error('foo', { cause: { woot: 'foo' } }) as ExtendedError; @@ -211,7 +217,7 @@ describe('ExtraErrorData()', () => { return; } - const extraErrorDataWithoutCauseCapture = new ExtraErrorData(); + const extraErrorDataWithoutCauseCapture = getIntegration(); // @ts-expect-error The typing .d.ts library we have installed isn't aware of Error.cause yet const error = new Error('foo', { cause: { woot: 'foo' } }) as ExtendedError; diff --git a/packages/integrations/test/reportingobserver.test.ts b/packages/integrations/test/reportingobserver.test.ts index 275e63c82ea9..c699b0d7f8dc 100644 --- a/packages/integrations/test/reportingobserver.test.ts +++ b/packages/integrations/test/reportingobserver.test.ts @@ -1,6 +1,7 @@ import * as SentryCore from '@sentry/core'; import type { Client, Hub } from '@sentry/types'; +import type { reportingObserverIntegration } from '../src/reportingobserver'; import { ReportingObserver } from '../src/reportingobserver'; const mockScope = { @@ -26,6 +27,11 @@ class MockReportingObserver { } } +function getIntegration(...args: Parameters) { + // eslint-disable-next-line deprecation/deprecation + return new ReportingObserver(...args); +} + describe('ReportingObserver', () => { let mockClient: Client; @@ -49,7 +55,7 @@ describe('ReportingObserver', () => { // Act like ReportingObserver is unavailable delete (global as any).ReportingObserver; - const reportingObserverIntegration = new ReportingObserver(); + const reportingObserverIntegration = getIntegration(); expect(() => { reportingObserverIntegration.setupOnce( @@ -63,7 +69,7 @@ describe('ReportingObserver', () => { }); it('should use default report types', () => { - const reportingObserverIntegration = new ReportingObserver(); + const reportingObserverIntegration = getIntegration(); reportingObserverIntegration.setupOnce( () => undefined, () => mockHub, @@ -78,7 +84,7 @@ describe('ReportingObserver', () => { }); it('should use user-provided report types', () => { - const reportingObserverIntegration = new ReportingObserver({ types: ['crash'] }); + const reportingObserverIntegration = getIntegration({ types: ['crash'] }); reportingObserverIntegration.setupOnce( () => undefined, () => mockHub, @@ -93,7 +99,7 @@ describe('ReportingObserver', () => { }); it('should use `buffered` option', () => { - const reportingObserverIntegration = new ReportingObserver(); + const reportingObserverIntegration = getIntegration(); reportingObserverIntegration.setupOnce( () => undefined, () => mockHub, @@ -108,7 +114,7 @@ describe('ReportingObserver', () => { }); it('should call `observe` function', () => { - const reportingObserverIntegration = new ReportingObserver(); + const reportingObserverIntegration = getIntegration(); reportingObserverIntegration.setupOnce( () => undefined, () => mockHub, @@ -121,7 +127,7 @@ describe('ReportingObserver', () => { describe('handler', () => { it('should abort gracefully and not do anything when integration is not installed', () => { - const reportingObserverIntegration = new ReportingObserver(); + const reportingObserverIntegration = getIntegration(); reportingObserverIntegration.setupOnce( () => undefined, () => mockHub, @@ -138,7 +144,7 @@ describe('ReportingObserver', () => { }); it('should capture messages', () => { - const reportingObserverIntegration = new ReportingObserver(); + const reportingObserverIntegration = getIntegration(); reportingObserverIntegration.setupOnce( () => undefined, () => mockHub, @@ -155,7 +161,7 @@ describe('ReportingObserver', () => { }); it('should set extra including the url of a report', () => { - const reportingObserverIntegration = new ReportingObserver(); + const reportingObserverIntegration = getIntegration(); reportingObserverIntegration.setupOnce( () => undefined, () => mockHub, @@ -173,7 +179,7 @@ describe('ReportingObserver', () => { }); it('should set extra including the report body if available', () => { - const reportingObserverIntegration = new ReportingObserver(); + const reportingObserverIntegration = getIntegration(); reportingObserverIntegration.setupOnce( () => undefined, () => mockHub, @@ -191,7 +197,7 @@ describe('ReportingObserver', () => { }); it('should not set extra report body extra when no body is set', () => { - const reportingObserverIntegration = new ReportingObserver(); + const reportingObserverIntegration = getIntegration(); reportingObserverIntegration.setupOnce( () => undefined, () => mockHub, @@ -205,7 +211,7 @@ describe('ReportingObserver', () => { }); it('should capture report details from body on crash report', () => { - const reportingObserverIntegration = new ReportingObserver(); + const reportingObserverIntegration = getIntegration(); reportingObserverIntegration.setupOnce( () => undefined, () => mockHub, @@ -226,7 +232,7 @@ describe('ReportingObserver', () => { }); it('should capture report message from body on deprecation report', () => { - const reportingObserverIntegration = new ReportingObserver(); + const reportingObserverIntegration = getIntegration(); reportingObserverIntegration.setupOnce( () => undefined, () => mockHub, @@ -246,7 +252,7 @@ describe('ReportingObserver', () => { }); it('should capture report message from body on intervention report', () => { - const reportingObserverIntegration = new ReportingObserver(); + const reportingObserverIntegration = getIntegration(); reportingObserverIntegration.setupOnce( () => undefined, () => mockHub, @@ -266,7 +272,7 @@ describe('ReportingObserver', () => { }); it('should use fallback message when no body is available', () => { - const reportingObserverIntegration = new ReportingObserver(); + const reportingObserverIntegration = getIntegration(); reportingObserverIntegration.setupOnce( () => undefined, () => mockHub, @@ -285,7 +291,7 @@ describe('ReportingObserver', () => { }); it('should use fallback message when no body details are available for crash report', () => { - const reportingObserverIntegration = new ReportingObserver(); + const reportingObserverIntegration = getIntegration(); reportingObserverIntegration.setupOnce( () => undefined, () => mockHub, @@ -301,7 +307,7 @@ describe('ReportingObserver', () => { }); it('should use fallback message when no body message is available for deprecation report', () => { - const reportingObserverIntegration = new ReportingObserver(); + const reportingObserverIntegration = getIntegration(); reportingObserverIntegration.setupOnce( () => undefined, () => mockHub, @@ -321,7 +327,7 @@ describe('ReportingObserver', () => { }); it('should use fallback message when no body message is available for intervention report', () => { - const reportingObserverIntegration = new ReportingObserver(); + const reportingObserverIntegration = getIntegration(); reportingObserverIntegration.setupOnce( () => undefined, () => mockHub, diff --git a/packages/integrations/test/rewriteframes.test.ts b/packages/integrations/test/rewriteframes.test.ts index 7a65ff129aca..7dc051c478cb 100644 --- a/packages/integrations/test/rewriteframes.test.ts +++ b/packages/integrations/test/rewriteframes.test.ts @@ -1,11 +1,17 @@ import type { Event, Integration, StackFrame } from '@sentry/types'; +import type { rewriteFramesIntegration } from '../src/rewriteframes'; import { RewriteFrames } from '../src/rewriteframes'; interface IntegrationWithProcessEvent extends Integration { processEvent(event: Event): Event; } +function getIntegration(...args: Parameters) { + // eslint-disable-next-line deprecation/deprecation + return new RewriteFrames(...args); +} + let rewriteFrames: IntegrationWithProcessEvent; let exceptionEvent: Event; let exceptionWithoutStackTrace: Event; @@ -102,7 +108,7 @@ describe('RewriteFrames', () => { describe('default iteratee appends basename to `app:///` if frame starts with `/`', () => { beforeEach(() => { - rewriteFrames = new RewriteFrames(); + rewriteFrames = getIntegration(); }); it('transforms exceptionEvent frames', () => { @@ -121,7 +127,7 @@ describe('RewriteFrames', () => { describe('default iteratee prepends custom prefix to basename if frame starts with `/`', () => { beforeEach(() => { - rewriteFrames = new RewriteFrames({ + rewriteFrames = getIntegration({ prefix: 'foobar/', }); }); @@ -135,7 +141,7 @@ describe('RewriteFrames', () => { describe('default iteratee appends basename to `app:///` if frame starts with Windows path prefix', () => { beforeEach(() => { - rewriteFrames = new RewriteFrames(); + rewriteFrames = getIntegration(); }); it('transforms windowsExceptionEvent frames (C:\\)', () => { @@ -165,7 +171,7 @@ describe('RewriteFrames', () => { describe('can use custom root to perform `relative` on filepaths', () => { beforeEach(() => { - rewriteFrames = new RewriteFrames({ + rewriteFrames = getIntegration({ root: '/www', }); }); @@ -203,7 +209,7 @@ describe('RewriteFrames', () => { describe('can use custom iteratee', () => { beforeEach(() => { - rewriteFrames = new RewriteFrames({ + rewriteFrames = getIntegration({ iteratee: (frame: StackFrame) => ({ ...frame, function: 'whoops', @@ -222,7 +228,7 @@ describe('RewriteFrames', () => { describe('can process events that contain multiple stacktraces', () => { it('with defaults', () => { - rewriteFrames = new RewriteFrames(); + rewriteFrames = getIntegration(); const event = rewriteFrames.processEvent(multipleStacktracesEvent); // first stacktrace expect(event.exception!.values![0].stacktrace!.frames![0].filename).toEqual('app:///file1.js'); @@ -236,7 +242,7 @@ describe('RewriteFrames', () => { }); it('with custom root', () => { - rewriteFrames = new RewriteFrames({ + rewriteFrames = getIntegration({ root: '/www', }); const event = rewriteFrames.processEvent(multipleStacktracesEvent); @@ -252,7 +258,7 @@ describe('RewriteFrames', () => { }); it('with custom iteratee', () => { - rewriteFrames = new RewriteFrames({ + rewriteFrames = getIntegration({ iteratee: (frame: StackFrame) => ({ ...frame, function: 'whoops', @@ -279,7 +285,7 @@ describe('RewriteFrames', () => { describe('bails when unable to extract frames', () => { it('no exception values', () => { - rewriteFrames = new RewriteFrames({}); + rewriteFrames = getIntegration({}); const brokenEvent = { exception: { values: undefined, @@ -289,7 +295,7 @@ describe('RewriteFrames', () => { }); it('no frames', () => { - rewriteFrames = new RewriteFrames({}); + rewriteFrames = getIntegration({}); const brokenEvent = { exception: { values: [ diff --git a/packages/integrations/test/sessiontiming.test.ts b/packages/integrations/test/sessiontiming.test.ts index 3eba2b906134..85855324a6dc 100644 --- a/packages/integrations/test/sessiontiming.test.ts +++ b/packages/integrations/test/sessiontiming.test.ts @@ -1,5 +1,6 @@ import { SessionTiming } from '../src/sessiontiming'; +// eslint-disable-next-line deprecation/deprecation const sessionTiming = new SessionTiming(); describe('SessionTiming', () => { diff --git a/packages/nextjs/src/client/index.ts b/packages/nextjs/src/client/index.ts index 0c10a8344bd7..46719e47f4f7 100644 --- a/packages/nextjs/src/client/index.ts +++ b/packages/nextjs/src/client/index.ts @@ -75,6 +75,7 @@ function addClientIntegrations(options: BrowserOptions): void { // is set there, we set it here as well, just in case something has gone wrong with the injection. const assetPrefixPath = globalWithInjectedValues.__rewriteFramesAssetPrefixPath__ || ''; + // eslint-disable-next-line deprecation/deprecation const defaultRewriteFramesIntegration = new RewriteFrames({ // Turn `//_next/static/...` into `app:///_next/static/...` iteratee: frame => { diff --git a/packages/nextjs/src/edge/index.ts b/packages/nextjs/src/edge/index.ts index 310d308837d2..fa0e49f7ab59 100644 --- a/packages/nextjs/src/edge/index.ts +++ b/packages/nextjs/src/edge/index.ts @@ -51,6 +51,7 @@ export function init(options: VercelEdgeOptions = {}): void { // eslint-disable-next-line @sentry-internal/sdk/no-regexp-constructor -- user input is escaped const SOURCEMAP_FILENAME_REGEX = new RegExp(`.*${escapeStringForRegex(distDirAbsPath)}`); + // eslint-disable-next-line deprecation/deprecation const defaultRewriteFramesIntegration = new RewriteFrames({ iteratee: frame => { frame.filename = frame.filename?.replace(SOURCEMAP_FILENAME_REGEX, 'app:///_next'); diff --git a/packages/nextjs/src/server/index.ts b/packages/nextjs/src/server/index.ts index 6aa9d1a0cb0e..fed85cb3adb8 100644 --- a/packages/nextjs/src/server/index.ts +++ b/packages/nextjs/src/server/index.ts @@ -134,6 +134,7 @@ function addServerIntegrations(options: NodeOptions): void { // eslint-disable-next-line @sentry-internal/sdk/no-regexp-constructor -- user input is escaped const SOURCEMAP_FILENAME_REGEX = new RegExp(escapeStringForRegex(distDirAbsPath)); + // eslint-disable-next-line deprecation/deprecation const defaultRewriteFramesIntegration = new RewriteFrames({ iteratee: frame => { frame.filename = frame.filename?.replace(SOURCEMAP_FILENAME_REGEX, 'app:///_next'); diff --git a/packages/sveltekit/src/server/sdk.ts b/packages/sveltekit/src/server/sdk.ts index 03847d6cc4e4..b4e216b271ca 100644 --- a/packages/sveltekit/src/server/sdk.ts +++ b/packages/sveltekit/src/server/sdk.ts @@ -23,6 +23,7 @@ export function init(options: NodeOptions): void { function addServerIntegrations(options: NodeOptions): void { options.integrations = addOrUpdateIntegration( + // eslint-disable-next-line deprecation/deprecation new RewriteFrames({ iteratee: rewriteFramesIteratee }), options.integrations || [], ); diff --git a/packages/sveltekit/test/server/utils.test.ts b/packages/sveltekit/test/server/utils.test.ts index cad2051c2c14..aa2f9be62f94 100644 --- a/packages/sveltekit/test/server/utils.test.ts +++ b/packages/sveltekit/test/server/utils.test.ts @@ -79,7 +79,9 @@ describe('rewriteFramesIteratee', () => { module: '3-ab34d22f.js', }; + // eslint-disable-next-line deprecation/deprecation const originalRewriteFrames = new RewriteFrames(); + // eslint-disable-next-line deprecation/deprecation const rewriteFrames = new RewriteFrames({ iteratee: rewriteFramesIteratee }); const event: Event = {