diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d3ba436c532..17a5f8edae40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - [core] feat: Send transactions in envelopes (#2553) - [core] fix: Send event timestamp (#2575) +- [browser] feat: Allow for configuring TryCatch integration (#2601) - [browser] fix: Call wrapped `RequestAnimationFrame` with correct context (#2570) - [node] fix: Prevent reading the same source file multiple times (#2569) - [integrations] feat: Vue performance monitoring (#2571) diff --git a/packages/browser/src/integrations/breadcrumbs.ts b/packages/browser/src/integrations/breadcrumbs.ts index 182789cf73aa..528baa92df41 100644 --- a/packages/browser/src/integrations/breadcrumbs.ts +++ b/packages/browser/src/integrations/breadcrumbs.ts @@ -25,13 +25,13 @@ export interface SentryWrappedXMLHttpRequest extends XMLHttpRequest { } /** JSDoc */ -interface BreadcrumbIntegrations { - console?: boolean; - dom?: boolean; - fetch?: boolean; - history?: boolean; - sentry?: boolean; - xhr?: boolean; +interface BreadcrumbsOptions { + console: boolean; + dom: boolean; + fetch: boolean; + history: boolean; + sentry: boolean; + xhr: boolean; } /** @@ -50,12 +50,12 @@ export class Breadcrumbs implements Integration { public static id: string = 'Breadcrumbs'; /** JSDoc */ - private readonly _options: BreadcrumbIntegrations; + private readonly _options: BreadcrumbsOptions; /** * @inheritDoc */ - public constructor(options?: BreadcrumbIntegrations) { + public constructor(options?: Partial) { this._options = { console: true, dom: true, diff --git a/packages/browser/src/integrations/trycatch.ts b/packages/browser/src/integrations/trycatch.ts index 13e6f99ac523..8c60cdcf0cec 100644 --- a/packages/browser/src/integrations/trycatch.ts +++ b/packages/browser/src/integrations/trycatch.ts @@ -3,13 +3,51 @@ import { fill, getFunctionName, getGlobalObject } from '@sentry/utils'; import { wrap } from '../helpers'; +const DEFAULT_EVENT_TARGET = [ + 'EventTarget', + 'Window', + 'Node', + 'ApplicationCache', + 'AudioTrackList', + 'ChannelMergerNode', + 'CryptoOperation', + 'EventSource', + 'FileReader', + 'HTMLUnknownElement', + 'IDBDatabase', + 'IDBRequest', + 'IDBTransaction', + 'KeyOperation', + 'MediaController', + 'MessagePort', + 'ModalWindow', + 'Notification', + 'SVGElementInstance', + 'Screen', + 'TextTrack', + 'TextTrackCue', + 'TextTrackList', + 'WebSocket', + 'WebSocketWorker', + 'Worker', + 'XMLHttpRequest', + 'XMLHttpRequestEventTarget', + 'XMLHttpRequestUpload', +]; + type XMLHttpRequestProp = 'onload' | 'onerror' | 'onprogress' | 'onreadystatechange'; +/** JSDoc */ +interface TryCatchOptions { + setTimeout: boolean; + setInterval: boolean; + requestAnimationFrame: boolean; + XMLHttpRequest: boolean; + eventTarget: boolean | string[]; +} + /** Wrap timer functions and event targets to catch errors and provide better meta data */ export class TryCatch implements Integration { - /** JSDoc */ - private _ignoreOnError: number = 0; - /** * @inheritDoc */ @@ -20,6 +58,23 @@ export class TryCatch implements Integration { */ public static id: string = 'TryCatch'; + /** JSDoc */ + private readonly _options: TryCatchOptions; + + /** + * @inheritDoc + */ + public constructor(options?: Partial) { + this._options = { + XMLHttpRequest: true, + eventTarget: true, + requestAnimationFrame: true, + setInterval: true, + setTimeout: true, + ...options, + }; + } + /** JSDoc */ private _wrapTimeFunction(original: () => void): () => number { return function(this: any, ...args: any[]): number { @@ -170,48 +225,27 @@ export class TryCatch implements Integration { * and provide better metadata. */ public setupOnce(): void { - this._ignoreOnError = this._ignoreOnError; - const global = getGlobalObject(); - fill(global, 'setTimeout', this._wrapTimeFunction.bind(this)); - fill(global, 'setInterval', this._wrapTimeFunction.bind(this)); - fill(global, 'requestAnimationFrame', this._wrapRAF.bind(this)); + if (this._options.setTimeout) { + fill(global, 'setTimeout', this._wrapTimeFunction.bind(this)); + } + + if (this._options.setInterval) { + fill(global, 'setInterval', this._wrapTimeFunction.bind(this)); + } - if ('XMLHttpRequest' in global) { + if (this._options.requestAnimationFrame) { + fill(global, 'requestAnimationFrame', this._wrapRAF.bind(this)); + } + + if (this._options.XMLHttpRequest && 'XMLHttpRequest' in global) { fill(XMLHttpRequest.prototype, 'send', this._wrapXHR.bind(this)); } - [ - 'EventTarget', - 'Window', - 'Node', - 'ApplicationCache', - 'AudioTrackList', - 'ChannelMergerNode', - 'CryptoOperation', - 'EventSource', - 'FileReader', - 'HTMLUnknownElement', - 'IDBDatabase', - 'IDBRequest', - 'IDBTransaction', - 'KeyOperation', - 'MediaController', - 'MessagePort', - 'ModalWindow', - 'Notification', - 'SVGElementInstance', - 'Screen', - 'TextTrack', - 'TextTrackCue', - 'TextTrackList', - 'WebSocket', - 'WebSocketWorker', - 'Worker', - 'XMLHttpRequest', - 'XMLHttpRequestEventTarget', - 'XMLHttpRequestUpload', - ].forEach(this._wrapEventTarget.bind(this)); + if (this._options.eventTarget) { + const eventTarget = Array.isArray(this._options.eventTarget) ? this._options.eventTarget : DEFAULT_EVENT_TARGET; + eventTarget.forEach(this._wrapEventTarget.bind(this)); + } } }