From 974e6cdd2a17011a0919a684575507f75a9ad4e2 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Fri, 12 Jan 2024 12:53:50 +0000 Subject: [PATCH 1/2] ref: Clean up new integrations API and pave migration path --- packages/core/src/integration.ts | 8 +++ .../core/src/integrations/functiontostring.ts | 69 +++++++++++-------- .../core/src/integrations/inboundfilters.ts | 50 +++++++++----- packages/vercel-edge/src/sdk.ts | 2 + 4 files changed, 85 insertions(+), 44 deletions(-) diff --git a/packages/core/src/integration.ts b/packages/core/src/integration.ts index 4b4a3177c428..9be0599b0711 100644 --- a/packages/core/src/integration.ts +++ b/packages/core/src/integration.ts @@ -184,3 +184,11 @@ export function convertIntegrationFnToClass( new (...args: Parameters): Integration & ReturnType; }; } + +/** + * Utility function to aid with creating Sentry SDK integrations. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function defineSentryIntegration Integration>(integrationFactory: F): F { + return integrationFactory; +} diff --git a/packages/core/src/integrations/functiontostring.ts b/packages/core/src/integrations/functiontostring.ts index 124085c9c6c6..d09f508feefa 100644 --- a/packages/core/src/integrations/functiontostring.ts +++ b/packages/core/src/integrations/functiontostring.ts @@ -1,33 +1,48 @@ -import type { IntegrationFn, WrappedFunction } from '@sentry/types'; +import type { Integration, WrappedFunction } from '@sentry/types'; import { getOriginalFunction } from '@sentry/utils'; -import { convertIntegrationFnToClass } from '../integration'; +import { defineSentryIntegration } from '../integration'; let originalFunctionToString: () => void; const INTEGRATION_NAME = 'FunctionToString'; -const functionToStringIntegration: IntegrationFn = () => { - return { - name: INTEGRATION_NAME, - setupOnce() { - // eslint-disable-next-line @typescript-eslint/unbound-method - originalFunctionToString = Function.prototype.toString; - - // intrinsics (like Function.prototype) might be immutable in some environments - // e.g. Node with --frozen-intrinsics, XS (an embedded JavaScript engine) or SES (a JavaScript proposal) - try { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - Function.prototype.toString = function (this: WrappedFunction, ...args: any[]): string { - const context = getOriginalFunction(this) || this; - return originalFunctionToString.apply(context, args); - }; - } catch { - // ignore errors here, just don't patch this - } - }, - }; -}; - -/** Patch toString calls to return proper name for wrapped functions */ -// eslint-disable-next-line deprecation/deprecation -export const FunctionToString = convertIntegrationFnToClass(INTEGRATION_NAME, functionToStringIntegration); +/** + * Patch toString calls to return proper name for wrapped functions + */ +export const functionToStringIntegration = defineSentryIntegration(() => { + // eslint-disable-next-line deprecation/deprecation + return new FunctionToString(); +}); + +/** + * Patch toString calls to return proper name for wrapped functions + * + * @deprecated Use `functionToStringIntegration()` instead. + */ +export class FunctionToString implements Integration { + public static id = INTEGRATION_NAME; + + public name: typeof INTEGRATION_NAME; + + public constructor() { + this.name = INTEGRATION_NAME; + } + + // eslint-disable-next-line jsdoc/require-jsdoc + public setupOnce(): void { + // eslint-disable-next-line @typescript-eslint/unbound-method + originalFunctionToString = Function.prototype.toString; + + // intrinsics (like Function.prototype) might be immutable in some environments + // e.g. Node with --frozen-intrinsics, XS (an embedded JavaScript engine) or SES (a JavaScript proposal) + try { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + Function.prototype.toString = function (this: WrappedFunction, ...args: any[]): string { + const context = getOriginalFunction(this) || this; + return originalFunctionToString.apply(context, args); + }; + } catch { + // ignore errors here, just don't patch this + } + } +} diff --git a/packages/core/src/integrations/inboundfilters.ts b/packages/core/src/integrations/inboundfilters.ts index 6d2ec6dfc799..b766fc18a9d5 100644 --- a/packages/core/src/integrations/inboundfilters.ts +++ b/packages/core/src/integrations/inboundfilters.ts @@ -1,8 +1,9 @@ -import type { Event, IntegrationFn, StackFrame } from '@sentry/types'; +/* eslint-disable jsdoc/require-jsdoc */ +import type { Client, Event, EventHint, Integration, StackFrame } from '@sentry/types'; import { getEventDescription, logger, stringMatchesSomePattern } from '@sentry/utils'; import { DEBUG_BUILD } from '../debug-build'; -import { convertIntegrationFnToClass } from '../integration'; +import { defineSentryIntegration } from '../integration'; // "Script error." is hard coded into browsers for errors that it can't read. // this is the result of a script being pulled in from an external domain and CORS. @@ -30,22 +31,37 @@ export interface InboundFiltersOptions { } const INTEGRATION_NAME = 'InboundFilters'; -const inboundFiltersIntegration: IntegrationFn = (options: Partial) => { - return { - name: INTEGRATION_NAME, - // TODO v8: Remove this - setupOnce() {}, // eslint-disable-line @typescript-eslint/no-empty-function - processEvent(event, _hint, client) { - const clientOptions = client.getOptions(); - const mergedOptions = _mergeOptions(options, clientOptions); - return _shouldDropEvent(event, mergedOptions) ? null : event; - }, - }; -}; -/** Inbound filters configurable by the user */ -// eslint-disable-next-line deprecation/deprecation -export const InboundFilters = convertIntegrationFnToClass(INTEGRATION_NAME, inboundFiltersIntegration); +export const inboundFiltersIntegration = defineSentryIntegration((options?: Partial) => { + // eslint-disable-next-line deprecation/deprecation + return new InboundFilters(options); +}); + +/** + * Inbound filters configurable by the user + * + * @deprecated Use `inboundFiltersIntegration()` instead. + */ +export class InboundFilters implements Integration { + public static id = INTEGRATION_NAME; + + public name: string; + + public constructor(private _options?: Partial) { + this.name = INTEGRATION_NAME; + } + + // TODO v8: Remove this + public setupOnce(): void { + // noop + } + + public preprocessEvent(event: Event, hint: EventHint | undefined, client: Client): Event | null { + const clientOptions = client.getOptions(); + const mergedOptions = _mergeOptions(this._options, clientOptions); + return _shouldDropEvent(event, mergedOptions) ? null : event; + } +} function _mergeOptions( internalOptions: Partial = {}, diff --git a/packages/vercel-edge/src/sdk.ts b/packages/vercel-edge/src/sdk.ts index 9e85593e4b78..fa60f87ee268 100644 --- a/packages/vercel-edge/src/sdk.ts +++ b/packages/vercel-edge/src/sdk.ts @@ -16,7 +16,9 @@ declare const process: { const nodeStackParser = createStackParser(nodeStackLineParser()); export const defaultIntegrations = [ + // eslint-disable-next-line deprecation/deprecation new CoreIntegrations.InboundFilters(), + // eslint-disable-next-line deprecation/deprecation new CoreIntegrations.FunctionToString(), new CoreIntegrations.LinkedErrors(), new WinterCGFetch(), From 77f33b06ed3565c702c65183835fb8ddea697e7b Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Fri, 12 Jan 2024 15:45:53 +0000 Subject: [PATCH 2/2] Remove deprecations for now --- packages/core/src/integrations/functiontostring.ts | 6 ++---- packages/core/src/integrations/inboundfilters.ts | 4 +--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/core/src/integrations/functiontostring.ts b/packages/core/src/integrations/functiontostring.ts index d09f508feefa..ca406f31d0b5 100644 --- a/packages/core/src/integrations/functiontostring.ts +++ b/packages/core/src/integrations/functiontostring.ts @@ -7,7 +7,7 @@ let originalFunctionToString: () => void; const INTEGRATION_NAME = 'FunctionToString'; /** - * Patch toString calls to return proper name for wrapped functions + * Patch toString calls to return proper name for wrapped functions. */ export const functionToStringIntegration = defineSentryIntegration(() => { // eslint-disable-next-line deprecation/deprecation @@ -15,9 +15,7 @@ export const functionToStringIntegration = defineSentryIntegration(() => { }); /** - * Patch toString calls to return proper name for wrapped functions - * - * @deprecated Use `functionToStringIntegration()` instead. + * Patch toString calls to return proper name for wrapped functions. */ export class FunctionToString implements Integration { public static id = INTEGRATION_NAME; diff --git a/packages/core/src/integrations/inboundfilters.ts b/packages/core/src/integrations/inboundfilters.ts index b766fc18a9d5..aebe23c222f8 100644 --- a/packages/core/src/integrations/inboundfilters.ts +++ b/packages/core/src/integrations/inboundfilters.ts @@ -38,9 +38,7 @@ export const inboundFiltersIntegration = defineSentryIntegration((options?: Part }); /** - * Inbound filters configurable by the user - * - * @deprecated Use `inboundFiltersIntegration()` instead. + * Inbound filters configurable by the user. */ export class InboundFilters implements Integration { public static id = INTEGRATION_NAME;