diff --git a/packages/integrations/src/contextlines.ts b/packages/integrations/src/contextlines.ts index 3bc483958b42..d528477718c1 100644 --- a/packages/integrations/src/contextlines.ts +++ b/packages/integrations/src/contextlines.ts @@ -1,4 +1,4 @@ -import type { Event, EventProcessor, Hub, Integration, StackFrame } from '@sentry/types'; +import type { Event, Integration, StackFrame } from '@sentry/types'; import { addContextToFrame, GLOBAL_OBJ, stripUrlQueryAndFragment } from '@sentry/utils'; const WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window; @@ -44,17 +44,20 @@ export class ContextLines implements Integration { /** * @inheritDoc */ - public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { - addGlobalEventProcessor(event => { - const self = getCurrentHub().getIntegration(ContextLines); - if (!self) { - return event; - } - return this.addSourceContext(event); - }); + public setupOnce(_addGlobaleventProcessor: unknown, _getCurrentHub: unknown): void { + // noop + } + + /** @inheritDoc */ + public processEvent(event: Event): Event { + return this.addSourceContext(event); } - /** Processes an event and adds context lines */ + /** + * Processes an event and adds context lines. + * + * TODO (v8): Make this internal/private + */ public addSourceContext(event: Event): Event { const doc = WINDOW.document; const htmlFilename = WINDOW.location && stripUrlQueryAndFragment(WINDOW.location.href); diff --git a/packages/integrations/src/dedupe.ts b/packages/integrations/src/dedupe.ts index 8f156e76784d..49865de3cd79 100644 --- a/packages/integrations/src/dedupe.ts +++ b/packages/integrations/src/dedupe.ts @@ -1,4 +1,4 @@ -import type { Event, EventProcessor, Exception, Hub, Integration, StackFrame } from '@sentry/types'; +import type { Event, Exception, Integration, StackFrame } from '@sentry/types'; import { logger } from '@sentry/utils'; /** Deduplication filter */ @@ -22,36 +22,32 @@ export class Dedupe implements Integration { this.name = Dedupe.id; } + /** @inheritDoc */ + public setupOnce(_addGlobaleventProcessor: unknown, _getCurrentHub: unknown): void { + // noop + } + /** * @inheritDoc */ - public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { - const eventProcessor: EventProcessor = currentEvent => { - // We want to ignore any non-error type events, e.g. transactions or replays - // These should never be deduped, and also not be compared against as _previousEvent. - if (currentEvent.type) { - return currentEvent; - } + public processEvent(currentEvent: Event): Event | null { + // We want to ignore any non-error type events, e.g. transactions or replays + // These should never be deduped, and also not be compared against as _previousEvent. + if (currentEvent.type) { + return currentEvent; + } - const self = getCurrentHub().getIntegration(Dedupe); - if (self) { - // Juuust in case something goes wrong - try { - if (_shouldDropEvent(currentEvent, self._previousEvent)) { - __DEBUG_BUILD__ && logger.warn('Event dropped due to being a duplicate of previously captured event.'); - return null; - } - } catch (_oO) { - return (self._previousEvent = currentEvent); - } - - return (self._previousEvent = currentEvent); + // Juuust in case something goes wrong + try { + if (_shouldDropEvent(currentEvent, this._previousEvent)) { + __DEBUG_BUILD__ && logger.warn('Event dropped due to being a duplicate of previously captured event.'); + return null; } - return currentEvent; - }; + } catch (_oO) { + return (this._previousEvent = currentEvent); + } - eventProcessor.id = this.name; - addGlobalEventProcessor(eventProcessor); + return (this._previousEvent = currentEvent); } } diff --git a/packages/integrations/src/extraerrordata.ts b/packages/integrations/src/extraerrordata.ts index 86d9343ef5e3..0ac2729e3baf 100644 --- a/packages/integrations/src/extraerrordata.ts +++ b/packages/integrations/src/extraerrordata.ts @@ -1,9 +1,9 @@ -import type { Contexts, Event, EventHint, EventProcessor, ExtendedError, Hub, Integration } from '@sentry/types'; +import type { Contexts, Event, EventHint, ExtendedError, Integration } from '@sentry/types'; import { addNonEnumerableProperty, isError, isPlainObject, logger, normalize } from '@sentry/utils'; /** JSDoc */ interface ExtraErrorDataOptions { - depth?: number; + depth: number; } /** Patch toString calls to return proper name for wrapped functions */ @@ -24,7 +24,7 @@ export class ExtraErrorData implements Integration { /** * @inheritDoc */ - public constructor(options?: ExtraErrorDataOptions) { + public constructor(options?: Partial) { this.name = ExtraErrorData.id; this._options = { @@ -36,94 +36,99 @@ export class ExtraErrorData implements Integration { /** * @inheritDoc */ - public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { - addGlobalEventProcessor((event: Event, hint: EventHint) => { - const self = getCurrentHub().getIntegration(ExtraErrorData); - if (!self) { - return event; - } - return self.enhanceEventWithErrorData(event, hint); - }); + public setupOnce(_addGlobaleventProcessor: unknown, _getCurrentHub: unknown): void { + // noop + } + + /** @inheritDoc */ + public processEvent(event: Event, hint: EventHint): Event { + return this.enhanceEventWithErrorData(event, hint); } /** - * Attaches extracted information from the Error object to extra field in the Event + * Attaches extracted information from the Error object to extra field in the Event. + * + * TODO (v8): Drop this public function. */ public enhanceEventWithErrorData(event: Event, hint: EventHint = {}): Event { - if (!hint.originalException || !isError(hint.originalException)) { - return event; - } - const exceptionName = (hint.originalException as ExtendedError).name || hint.originalException.constructor.name; + return _enhanceEventWithErrorData(event, hint, this._options.depth); + } +} - const errorData = this._extractErrorData(hint.originalException as ExtendedError); +function _enhanceEventWithErrorData(event: Event, hint: EventHint = {}, depth: number): Event { + if (!hint.originalException || !isError(hint.originalException)) { + return event; + } + const exceptionName = (hint.originalException as ExtendedError).name || hint.originalException.constructor.name; - if (errorData) { - const contexts: Contexts = { - ...event.contexts, - }; + const errorData = _extractErrorData(hint.originalException as ExtendedError); - const normalizedErrorData = normalize(errorData, this._options.depth); + if (errorData) { + const contexts: Contexts = { + ...event.contexts, + }; - if (isPlainObject(normalizedErrorData)) { - // We mark the error data as "already normalized" here, because we don't want other normalization procedures to - // potentially truncate the data we just already normalized, with a certain depth setting. - addNonEnumerableProperty(normalizedErrorData, '__sentry_skip_normalization__', true); - contexts[exceptionName] = normalizedErrorData; - } + const normalizedErrorData = normalize(errorData, depth); - return { - ...event, - contexts, - }; + if (isPlainObject(normalizedErrorData)) { + // We mark the error data as "already normalized" here, because we don't want other normalization procedures to + // potentially truncate the data we just already normalized, with a certain depth setting. + addNonEnumerableProperty(normalizedErrorData, '__sentry_skip_normalization__', true); + contexts[exceptionName] = normalizedErrorData; } - return event; + return { + ...event, + contexts, + }; } - /** - * Extract extra information from the Error object - */ - private _extractErrorData(error: ExtendedError): Record | null { - // We are trying to enhance already existing event, so no harm done if it won't succeed - try { - const nativeKeys = [ - 'name', - 'message', - 'stack', - 'line', - 'column', - 'fileName', - 'lineNumber', - 'columnNumber', - 'toJSON', - ]; - - const extraErrorInfo: Record = {}; - - // We want only enumerable properties, thus `getOwnPropertyNames` is redundant here, as we filter keys anyway. - for (const key of Object.keys(error)) { - if (nativeKeys.indexOf(key) !== -1) { - continue; - } - const value = error[key]; - extraErrorInfo[key] = isError(value) ? value.toString() : value; + return event; +} + +/** + * Extract extra information from the Error object + */ +function _extractErrorData(error: ExtendedError): Record | null { + // We are trying to enhance already existing event, so no harm done if it won't succeed + try { + const nativeKeys = [ + 'name', + 'message', + 'stack', + 'line', + 'column', + 'fileName', + 'lineNumber', + 'columnNumber', + 'toJSON', + ]; + + const extraErrorInfo: Record = {}; + + // We want only enumerable properties, thus `getOwnPropertyNames` is redundant here, as we filter keys anyway. + for (const key of Object.keys(error)) { + if (nativeKeys.indexOf(key) !== -1) { + continue; } + const value = error[key]; + extraErrorInfo[key] = isError(value) ? value.toString() : value; + } - // Check if someone attached `toJSON` method to grab even more properties (eg. axios is doing that) - if (typeof error.toJSON === 'function') { - const serializedError = error.toJSON() as Record; + // Check if someone attached `toJSON` method to grab even more properties (eg. axios is doing that) + if (typeof error.toJSON === 'function') { + const serializedError = error.toJSON() as Record; - for (const key of Object.keys(serializedError)) { - const value = serializedError[key]; - extraErrorInfo[key] = isError(value) ? value.toString() : value; - } + for (const key of Object.keys(serializedError)) { + const value = serializedError[key]; + extraErrorInfo[key] = isError(value) ? value.toString() : value; } - - return extraErrorInfo; - } catch (oO) { - __DEBUG_BUILD__ && logger.error('Unable to extract extra data from the Error object:', oO); } - return null; + return extraErrorInfo; + } catch (oO) { + __DEBUG_BUILD__ && logger.error('Unable to extract extra data from the Error object:', oO); } + + return null; } diff --git a/packages/integrations/src/rewriteframes.ts b/packages/integrations/src/rewriteframes.ts index 1564d54a4970..67f146e650bd 100644 --- a/packages/integrations/src/rewriteframes.ts +++ b/packages/integrations/src/rewriteframes.ts @@ -1,4 +1,4 @@ -import type { Event, EventProcessor, Hub, Integration, StackFrame, Stacktrace } from '@sentry/types'; +import type { Event, Integration, StackFrame, Stacktrace } from '@sentry/types'; import { basename, relative } from '@sentry/utils'; type StackFrameIteratee = (frame: StackFrame) => StackFrame; @@ -43,17 +43,18 @@ export class RewriteFrames implements Integration { /** * @inheritDoc */ - public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { - addGlobalEventProcessor(event => { - const self = getCurrentHub().getIntegration(RewriteFrames); - if (self) { - return self.process(event); - } - return event; - }); + public setupOnce(_addGlobaleventProcessor: unknown, _getCurrentHub: unknown): void { + // noop } - /** JSDoc */ + /** @inheritDoc */ + public processEvent(event: Event): Event { + return this.process(event); + } + + /** + * TODO (v8): Make this private/internal + */ public process(originalEvent: Event): Event { let processedEvent = originalEvent; diff --git a/packages/integrations/src/sessiontiming.ts b/packages/integrations/src/sessiontiming.ts index 584163ce008e..016d71f336e3 100644 --- a/packages/integrations/src/sessiontiming.ts +++ b/packages/integrations/src/sessiontiming.ts @@ -1,4 +1,4 @@ -import type { Event, EventProcessor, Hub, Integration } from '@sentry/types'; +import type { Event, Integration } from '@sentry/types'; /** This function adds duration since Sentry was initialized till the time event was sent */ export class SessionTiming implements Integration { @@ -23,18 +23,17 @@ export class SessionTiming implements Integration { /** * @inheritDoc */ - public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { - addGlobalEventProcessor(event => { - const self = getCurrentHub().getIntegration(SessionTiming); - if (self) { - return self.process(event); - } - return event; - }); + public setupOnce(_addGlobaleventProcessor: unknown, _getCurrentHub: unknown): void { + // noop + } + + /** @inheritDoc */ + public processEvent(event: Event): Event { + return this.process(event); } /** - * @inheritDoc + * TODO (v8): make this private/internal */ public process(event: Event): Event { const now = Date.now(); diff --git a/packages/integrations/src/transaction.ts b/packages/integrations/src/transaction.ts index 1bb3ebfa816d..ae9f826cba55 100644 --- a/packages/integrations/src/transaction.ts +++ b/packages/integrations/src/transaction.ts @@ -1,4 +1,4 @@ -import type { Event, EventProcessor, Hub, Integration, StackFrame } from '@sentry/types'; +import type { Event, Integration, StackFrame } from '@sentry/types'; /** Add node transaction to the event */ export class Transaction implements Integration { @@ -19,43 +19,40 @@ export class Transaction implements Integration { /** * @inheritDoc */ - public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { - addGlobalEventProcessor(event => { - const self = getCurrentHub().getIntegration(Transaction); - if (self) { - return self.process(event); - } - return event; - }); + public setupOnce(_addGlobaleventProcessor: unknown, _getCurrentHub: unknown): void { + // noop + } + + /** @inheritDoc */ + public processEvent(event: Event): Event { + return this.processEvent(event); } /** - * @inheritDoc + * TODO (v8): Make this private/internal */ public process(event: Event): Event { - const frames = this._getFramesFromEvent(event); + const frames = _getFramesFromEvent(event); // use for loop so we don't have to reverse whole frames array for (let i = frames.length - 1; i >= 0; i--) { const frame = frames[i]; if (frame.in_app === true) { - event.transaction = this._getTransaction(frame); + event.transaction = _getTransaction(frame); break; } } return event; } +} - /** JSDoc */ - private _getFramesFromEvent(event: Event): StackFrame[] { - const exception = event.exception && event.exception.values && event.exception.values[0]; - return (exception && exception.stacktrace && exception.stacktrace.frames) || []; - } +function _getFramesFromEvent(event: Event): StackFrame[] { + const exception = event.exception && event.exception.values && event.exception.values[0]; + return (exception && exception.stacktrace && exception.stacktrace.frames) || []; +} - /** JSDoc */ - private _getTransaction(frame: StackFrame): string { - return frame.module || frame.function ? `${frame.module || '?'}/${frame.function || '?'}` : ''; - } +function _getTransaction(frame: StackFrame): string { + return frame.module || frame.function ? `${frame.module || '?'}/${frame.function || '?'}` : ''; } diff --git a/packages/integrations/test/dedupe.test.ts b/packages/integrations/test/dedupe.test.ts index 7ffc30d1bdcf..f4a703662e0c 100644 --- a/packages/integrations/test/dedupe.test.ts +++ b/packages/integrations/test/dedupe.test.ts @@ -1,4 +1,4 @@ -import type { Event as SentryEvent, EventProcessor, Exception, Hub, StackFrame, Stacktrace } from '@sentry/types'; +import type { Event as SentryEvent, Exception, StackFrame, Stacktrace } from '@sentry/types'; import { _shouldDropEvent, Dedupe } from '../src/dedupe'; @@ -176,47 +176,29 @@ describe('Dedupe', () => { }); }); - describe('setupOnce', () => { - let dedupeFunc: EventProcessor; - - beforeEach(function () { + describe('processEvent', () => { + it('ignores consecutive errors', () => { const integration = new Dedupe(); - const addGlobalEventProcessor = (callback: EventProcessor) => { - dedupeFunc = callback; - }; - - const getCurrentHub = () => { - return { - getIntegration() { - return integration; - }, - } as unknown as Hub; - }; - - integration.setupOnce(addGlobalEventProcessor, getCurrentHub); - }); - it('ignores consecutive errors', () => { - expect(dedupeFunc(clone(exceptionEvent), {})).not.toBeNull(); - expect(dedupeFunc(clone(exceptionEvent), {})).toBeNull(); - expect(dedupeFunc(clone(exceptionEvent), {})).toBeNull(); + expect(integration.processEvent(clone(exceptionEvent))).not.toBeNull(); + expect(integration.processEvent(clone(exceptionEvent))).toBeNull(); + expect(integration.processEvent(clone(exceptionEvent))).toBeNull(); }); it('ignores transactions between errors', () => { - expect(dedupeFunc(clone(exceptionEvent), {})).not.toBeNull(); + const integration = new Dedupe(); + + expect(integration.processEvent(clone(exceptionEvent))).not.toBeNull(); expect( - dedupeFunc( - { - event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', - message: 'someMessage', - transaction: 'wat', - type: 'transaction', - }, - {}, - ), + integration.processEvent({ + event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', + message: 'someMessage', + transaction: 'wat', + type: 'transaction', + }), ).not.toBeNull(); - expect(dedupeFunc(clone(exceptionEvent), {})).toBeNull(); - expect(dedupeFunc(clone(exceptionEvent), {})).toBeNull(); + expect(integration.processEvent(clone(exceptionEvent))).toBeNull(); + expect(integration.processEvent(clone(exceptionEvent))).toBeNull(); }); }); });