From d8689c3f4e2e8dbc326df111781e5118476109eb Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Fri, 10 Dec 2021 16:21:51 -0500 Subject: [PATCH 1/4] ref(browser): Update addInstrumentationHandler type --- packages/browser/src/client.ts | 5 - .../browser/src/integrations/breadcrumbs.ts | 225 ++++++++---------- .../src/integrations/globalhandlers.ts | 19 +- packages/browser/src/sdk.ts | 19 +- packages/tracing/src/browser/request.ts | 18 +- packages/tracing/src/browser/router.ts | 49 ++-- packages/tracing/src/errors.ts | 10 +- packages/utils/src/instrument.ts | 19 +- 8 files changed, 156 insertions(+), 208 deletions(-) diff --git a/packages/browser/src/client.ts b/packages/browser/src/client.ts index aeb1539e2a7d..0c8f98f9da32 100644 --- a/packages/browser/src/client.ts +++ b/packages/browser/src/client.ts @@ -4,7 +4,6 @@ import { getGlobalObject, logger } from '@sentry/utils'; import { BrowserBackend, BrowserOptions } from './backend'; import { injectReportDialog, ReportDialogOptions } from './helpers'; -import { Breadcrumbs } from './integrations'; /** * The Sentry Browser SDK Client. @@ -69,10 +68,6 @@ export class BrowserClient extends BaseClient { * @inheritDoc */ protected _sendEvent(event: Event): void { - const integration = this.getIntegration(Breadcrumbs); - if (integration) { - integration.addSentryBreadcrumb(event); - } super._sendEvent(event); } } diff --git a/packages/browser/src/integrations/breadcrumbs.ts b/packages/browser/src/integrations/breadcrumbs.ts index 49a52ac5a7bf..74d1b2cf3fa6 100644 --- a/packages/browser/src/integrations/breadcrumbs.ts +++ b/packages/browser/src/integrations/breadcrumbs.ts @@ -1,7 +1,6 @@ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable max-lines */ -import { getCurrentHub } from '@sentry/core'; -import { Event, Integration, Severity } from '@sentry/types'; +import { BreadcrumbHint, EventProcessor, Hub, Integration, Severity } from '@sentry/types'; import { addInstrumentationHandler, getEventDescription, @@ -11,6 +10,12 @@ import { safeJoin, } from '@sentry/utils'; +const CONSOLE = 'console'; +const FETCH = 'fetch'; +const HISTORY = 'history'; +const DOM = 'dom'; +const XHR = 'xhr'; + /** JSDoc */ interface BreadcrumbsOptions { console: boolean; @@ -21,9 +26,10 @@ interface BreadcrumbsOptions { xhr: boolean; } +const global = getGlobalObject(); + /** * Default Breadcrumbs instrumentations - * TODO: Deprecated - with v6, this will be renamed to `Instrument` */ export class Breadcrumbs implements Integration { /** @@ -54,26 +60,6 @@ export class Breadcrumbs implements Integration { }; } - /** - * Create a breadcrumb of `sentry` from the events themselves - */ - public addSentryBreadcrumb(event: Event): void { - if (!this._options.sentry) { - return; - } - getCurrentHub().addBreadcrumb( - { - category: `sentry.${event.type === 'transaction' ? 'transaction' : 'event'}`, - event_id: event.event_id, - level: event.level, - message: getEventDescription(event), - }, - { - event, - }, - ); - } - /** * Instrument browser built-ins w/ breadcrumb capturing * - Console API @@ -82,59 +68,55 @@ export class Breadcrumbs implements Integration { * - Fetch API * - History API */ - public setupOnce(): void { + public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { + const hub = getCurrentHub(); + + addGlobalEventProcessor(event => { + if (this._options.sentry) { + hub.addBreadcrumb( + { + category: `sentry.${event.type === 'transaction' ? 'transaction' : 'event'}`, + event_id: event.event_id, + level: event.level, + message: getEventDescription(event), + }, + { + event, + }, + ); + } + return event; + }); + if (this._options.console) { - addInstrumentationHandler({ - callback: (...args) => { - this._consoleBreadcrumb(...args); - }, - type: 'console', - }); + _addConsoleBreadcrumbs(hub); } if (this._options.dom) { - addInstrumentationHandler({ - callback: (...args) => { - this._domBreadcrumb(...args); - }, - type: 'dom', - }); + _addDomBreadcrumbs(hub, this._options.dom); } if (this._options.xhr) { - addInstrumentationHandler({ - callback: (...args) => { - this._xhrBreadcrumb(...args); - }, - type: 'xhr', - }); + _addXhrBreadcrumbs(hub); } if (this._options.fetch) { - addInstrumentationHandler({ - callback: (...args) => { - this._fetchBreadcrumb(...args); - }, - type: 'fetch', - }); + _addFetchBreadcrumbs(hub); } if (this._options.history) { - addInstrumentationHandler({ - callback: (...args) => { - this._historyBreadcrumb(...args); - }, - type: 'history', - }); + _addHistoryBreadcrumbs(hub); } } +} - /** - * Creates breadcrumbs from console API calls - */ +/** + * Creates breadcrumbs from console API calls + */ +function _addConsoleBreadcrumbs(hub: Hub): void { // eslint-disable-next-line @typescript-eslint/no-explicit-any - private _consoleBreadcrumb(handlerData: { [key: string]: any }): void { + addInstrumentationHandler((handlerData: { [key: string]: any }): void => { const breadcrumb = { - category: 'console', + category: CONSOLE, data: { arguments: handlerData.args, - logger: 'console', + logger: CONSOLE, }, level: Severity.fromString(handlerData.level), message: safeJoin(handlerData.args, ' '), @@ -150,19 +132,21 @@ export class Breadcrumbs implements Integration { } } - getCurrentHub().addBreadcrumb(breadcrumb, { + hub.addBreadcrumb(breadcrumb, { input: handlerData.args, level: handlerData.level, }); - } + }, CONSOLE); +} - /** - * Creates breadcrumbs from DOM API calls - */ +/** + * Creates breadcrumbs from DOM API calls + */ +function _addDomBreadcrumbs(hub: Hub, dom: BreadcrumbsOptions['dom']): void { // eslint-disable-next-line @typescript-eslint/no-explicit-any - private _domBreadcrumb(handlerData: { [key: string]: any }): void { + addInstrumentationHandler((handlerData: { [key: string]: any }): void => { let target; - let keyAttrs = typeof this._options.dom === 'object' ? this._options.dom.serializeAttribute : undefined; + let keyAttrs = typeof dom === 'object' ? dom.serializeAttribute : undefined; if (typeof keyAttrs === 'string') { keyAttrs = [keyAttrs]; @@ -181,7 +165,7 @@ export class Breadcrumbs implements Integration { return; } - getCurrentHub().addBreadcrumb( + hub.addBreadcrumb( { category: `ui.${handlerData.name}`, message: target, @@ -192,13 +176,15 @@ export class Breadcrumbs implements Integration { global: handlerData.global, }, ); - } + }, DOM); +} - /** - * Creates breadcrumbs from XHR API calls - */ +/** + * Creates breadcrumbs from XHR API calls + */ +function _addXhrBreadcrumbs(hub: Hub): void { // eslint-disable-next-line @typescript-eslint/no-explicit-any - private _xhrBreadcrumb(handlerData: { [key: string]: any }): void { + addInstrumentationHandler((handlerData: { [key: string]: any }): void => { if (handlerData.endTimestamp) { // We only capture complete, non-sentry requests if (handlerData.xhr.__sentry_own_request__) { @@ -207,9 +193,9 @@ export class Breadcrumbs implements Integration { const { method, url, status_code, body } = handlerData.xhr.__sentry_xhr__ || {}; - getCurrentHub().addBreadcrumb( + hub.addBreadcrumb( { - category: 'xhr', + category: XHR, data: { method, url, @@ -222,65 +208,53 @@ export class Breadcrumbs implements Integration { input: body, }, ); - - return; } - } + }, XHR); +} - /** - * Creates breadcrumbs from fetch API calls - */ +/** + * Creates breadcrumbs from fetch API calls + */ +function _addFetchBreadcrumbs(hub: Hub): void { // eslint-disable-next-line @typescript-eslint/no-explicit-any - private _fetchBreadcrumb(handlerData: { [key: string]: any }): void { + addInstrumentationHandler((handlerData: { [key: string]: any }): void => { // We only capture complete fetch requests - if (!handlerData.endTimestamp) { + // We will not create breadcrumbs for fetch requests that contain `sentry_key` (internal sentry requests) + if ( + !handlerData.endTimestamp || + (handlerData.fetchData.url.match(/sentry_key/) && handlerData.fetchData.method === 'POST') + ) { return; } - if (handlerData.fetchData.url.match(/sentry_key/) && handlerData.fetchData.method === 'POST') { - // We will not create breadcrumbs for fetch requests that contain `sentry_key` (internal sentry requests) - return; - } + const breadcrumb = { + category: FETCH, + data: handlerData.fetchData, + level: Severity.Error, + type: 'http', + }; + const breadcrumbHint = { + input: handlerData.args, + } as BreadcrumbHint; if (handlerData.error) { - getCurrentHub().addBreadcrumb( - { - category: 'fetch', - data: handlerData.fetchData, - level: Severity.Error, - type: 'http', - }, - { - data: handlerData.error, - input: handlerData.args, - }, - ); + breadcrumbHint.data = handlerData.error; + hub.addBreadcrumb(breadcrumb, breadcrumbHint); } else { - getCurrentHub().addBreadcrumb( - { - category: 'fetch', - data: { - ...handlerData.fetchData, - status_code: handlerData.response.status, - }, - type: 'http', - }, - { - input: handlerData.args, - response: handlerData.response, - }, - ); + breadcrumb.data.status_code = handlerData.response.status; + breadcrumbHint.response = handlerData.response; + hub.addBreadcrumb(breadcrumb, breadcrumbHint); } - } + }, FETCH); +} - /** - * Creates breadcrumbs from history API calls - */ +/** + * Creates breadcrumbs from history API calls + */ +function _addHistoryBreadcrumbs(hub: Hub): void { // eslint-disable-next-line @typescript-eslint/no-explicit-any - private _historyBreadcrumb(handlerData: { [key: string]: any }): void { - const global = getGlobalObject(); - let from = handlerData.from; - let to = handlerData.to; + addInstrumentationHandler((handlerData: { [key: string]: any }): void => { + let { from, to } = handlerData; const parsedLoc = parseUrl(global.location.href); let parsedFrom = parseUrl(from); const parsedTo = parseUrl(to); @@ -292,19 +266,20 @@ export class Breadcrumbs implements Integration { // Use only the path component of the URL if the URL matches the current // document (almost all the time when using pushState) - if (parsedLoc.protocol === parsedTo.protocol && parsedLoc.host === parsedTo.host) { + const parsedLocProtocol = parsedLoc.protocol; + if (parsedLocProtocol === parsedTo.protocol && parsedLoc.host === parsedTo.host) { to = parsedTo.relative; } - if (parsedLoc.protocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host) { + if (parsedLocProtocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host) { from = parsedFrom.relative; } - getCurrentHub().addBreadcrumb({ + hub.addBreadcrumb({ category: 'navigation', data: { from, to, }, }); - } + }, HISTORY); } diff --git a/packages/browser/src/integrations/globalhandlers.ts b/packages/browser/src/integrations/globalhandlers.ts index 5911bbeac285..37fe0e4677ff 100644 --- a/packages/browser/src/integrations/globalhandlers.ts +++ b/packages/browser/src/integrations/globalhandlers.ts @@ -72,9 +72,9 @@ export class GlobalHandlers implements Integration { return; } - addInstrumentationHandler({ + addInstrumentationHandler( // eslint-disable-next-line @typescript-eslint/no-explicit-any - callback: (data: { msg: any; url: any; line: any; column: any; error: any }) => { + (data: { msg: any; url: any; line: any; column: any; error: any }) => { const error = data.error; const currentHub = getCurrentHub(); const hasIntegration = currentHub.getIntegration(GlobalHandlers); @@ -107,8 +107,8 @@ export class GlobalHandlers implements Integration { originalException: error, }); }, - type: 'error', - }); + 'error', + ); this._onErrorHandlerInstalled = true; } @@ -119,9 +119,9 @@ export class GlobalHandlers implements Integration { return; } - addInstrumentationHandler({ + addInstrumentationHandler( // eslint-disable-next-line @typescript-eslint/no-explicit-any - callback: (e: any) => { + (e: any) => { let error = e; // dig the object of the rejection out of known event types @@ -172,8 +172,8 @@ export class GlobalHandlers implements Integration { return; }, - type: 'unhandledrejection', - }); + 'unhandledrejection', + ); this._onUnhandledRejectionHandlerInstalled = true; } @@ -183,7 +183,8 @@ export class GlobalHandlers implements Integration { */ // eslint-disable-next-line @typescript-eslint/no-explicit-any private _eventFromIncompleteOnError(msg: any, url: any, line: any, column: any): Event { - const ERROR_TYPES_RE = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/i; + const ERROR_TYPES_RE = + /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/i; // If 'message' is ErrorEvent, get real message from inside let message = isErrorEvent(msg) ? msg.message : msg; diff --git a/packages/browser/src/sdk.ts b/packages/browser/src/sdk.ts index 518052ac71ad..39180d5c26a4 100644 --- a/packages/browser/src/sdk.ts +++ b/packages/browser/src/sdk.ts @@ -226,15 +226,12 @@ function startSessionTracking(): void { hub.captureSession(); // We want to create a session for every navigation as well - addInstrumentationHandler({ - callback: ({ from, to }) => { - // Don't create an additional session for the initial route or if the location did not change - if (from === undefined || from === to) { - return; - } - hub.startSession({ ignoreDuration: true }); - hub.captureSession(); - }, - type: 'history', - }); + addInstrumentationHandler(({ from, to }) => { + // Don't create an additional session for the initial route or if the location did not change + if (from === undefined || from === to) { + return; + } + hub.startSession({ ignoreDuration: true }); + hub.captureSession(); + }, 'history'); } diff --git a/packages/tracing/src/browser/request.ts b/packages/tracing/src/browser/request.ts index 885d381017dc..2aba5263a0ee 100644 --- a/packages/tracing/src/browser/request.ts +++ b/packages/tracing/src/browser/request.ts @@ -118,21 +118,15 @@ export function instrumentOutgoingRequests(_options?: Partial = {}; if (traceFetch) { - addInstrumentationHandler({ - callback: (handlerData: FetchData) => { - fetchCallback(handlerData, shouldCreateSpan, spans); - }, - type: 'fetch', - }); + addInstrumentationHandler((handlerData: FetchData) => { + fetchCallback(handlerData, shouldCreateSpan, spans); + }, 'fetch'); } if (traceXHR) { - addInstrumentationHandler({ - callback: (handlerData: XHRData) => { - xhrCallback(handlerData, shouldCreateSpan, spans); - }, - type: 'xhr', - }); + addInstrumentationHandler((handlerData: XHRData) => { + xhrCallback(handlerData, shouldCreateSpan, spans); + }, 'xhr'); } } diff --git a/packages/tracing/src/browser/router.ts b/packages/tracing/src/browser/router.ts index 172a11592279..e10f974c475b 100644 --- a/packages/tracing/src/browser/router.ts +++ b/packages/tracing/src/browser/router.ts @@ -24,33 +24,30 @@ export function instrumentRoutingWithDefaults( } if (startTransactionOnLocationChange) { - addInstrumentationHandler({ - callback: ({ to, from }: { to: string; from?: string }) => { - /** - * This early return is there to account for some cases where a navigation transaction starts right after - * long-running pageload. We make sure that if `from` is undefined and a valid `startingURL` exists, we don't - * create an uneccessary navigation transaction. - * - * This was hard to duplicate, but this behavior stopped as soon as this fix was applied. This issue might also - * only be caused in certain development environments where the usage of a hot module reloader is causing - * errors. - */ - if (from === undefined && startingUrl && startingUrl.indexOf(to) !== -1) { - startingUrl = undefined; - return; - } + addInstrumentationHandler(({ to, from }: { to: string; from?: string }) => { + /** + * This early return is there to account for some cases where a navigation transaction starts right after + * long-running pageload. We make sure that if `from` is undefined and a valid `startingURL` exists, we don't + * create an uneccessary navigation transaction. + * + * This was hard to duplicate, but this behavior stopped as soon as this fix was applied. This issue might also + * only be caused in certain development environments where the usage of a hot module reloader is causing + * errors. + */ + if (from === undefined && startingUrl && startingUrl.indexOf(to) !== -1) { + startingUrl = undefined; + return; + } - if (from !== to) { - startingUrl = undefined; - if (activeTransaction) { - logger.log(`[Tracing] Finishing current transaction with op: ${activeTransaction.op}`); - // If there's an open transaction on the scope, we need to finish it before creating an new one. - activeTransaction.finish(); - } - activeTransaction = customStartTransaction({ name: global.location.pathname, op: 'navigation' }); + if (from !== to) { + startingUrl = undefined; + if (activeTransaction) { + logger.log(`[Tracing] Finishing current transaction with op: ${activeTransaction.op}`); + // If there's an open transaction on the scope, we need to finish it before creating an new one. + activeTransaction.finish(); } - }, - type: 'history', - }); + activeTransaction = customStartTransaction({ name: global.location.pathname, op: 'navigation' }); + } + }, 'history'); } } diff --git a/packages/tracing/src/errors.ts b/packages/tracing/src/errors.ts index eb15d592cb7c..c703bae09092 100644 --- a/packages/tracing/src/errors.ts +++ b/packages/tracing/src/errors.ts @@ -7,14 +7,8 @@ import { getActiveTransaction } from './utils'; * Configures global error listeners */ export function registerErrorInstrumentation(): void { - addInstrumentationHandler({ - callback: errorCallback, - type: 'error', - }); - addInstrumentationHandler({ - callback: errorCallback, - type: 'unhandledrejection', - }); + addInstrumentationHandler(errorCallback, 'error'); + addInstrumentationHandler(errorCallback, 'unhandledrejection'); } /** diff --git a/packages/utils/src/instrument.ts b/packages/utils/src/instrument.ts index 18dce47726f9..2e2989dcd97c 100644 --- a/packages/utils/src/instrument.ts +++ b/packages/utils/src/instrument.ts @@ -12,11 +12,6 @@ import { supportsHistory, supportsNativeFetch } from './supports'; const global = getGlobalObject(); -/** Object describing handler that will be triggered for a given `type` of instrumentation */ -interface InstrumentHandler { - type: InstrumentHandlerType; - callback: InstrumentHandlerCallback; -} type InstrumentHandlerType = | 'console' | 'dom' @@ -81,14 +76,14 @@ function instrument(type: InstrumentHandlerType): void { * Add handler that will be called when given type of instrumentation triggers. * Use at your own risk, this might break without changelog notice, only used internally. * @hidden + * + * TODO(abhi): Improve typescript typing for InstrumentHandlerCallback */ -export function addInstrumentationHandler(handler: InstrumentHandler): void { - if (!handler || typeof handler.type !== 'string' || typeof handler.callback !== 'function') { - return; - } - handlers[handler.type] = handlers[handler.type] || []; - (handlers[handler.type] as InstrumentHandlerCallback[]).push(handler.callback); - instrument(handler.type); +export function addInstrumentationHandler(callback: InstrumentHandlerCallback, type: InstrumentHandlerType): void { + handlers[type] = handlers[type] || []; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + handlers[type]!.push(callback); + instrument(type); } /** JSDoc */ From 655f433af74a025723e7e1f670e74bda7bffe04b Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Fri, 10 Dec 2021 16:30:59 -0500 Subject: [PATCH 2/4] dont mess up size bot --- packages/browser/src/integrations/globalhandlers.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/browser/src/integrations/globalhandlers.ts b/packages/browser/src/integrations/globalhandlers.ts index 37fe0e4677ff..330daab073b0 100644 --- a/packages/browser/src/integrations/globalhandlers.ts +++ b/packages/browser/src/integrations/globalhandlers.ts @@ -183,8 +183,7 @@ export class GlobalHandlers implements Integration { */ // eslint-disable-next-line @typescript-eslint/no-explicit-any private _eventFromIncompleteOnError(msg: any, url: any, line: any, column: any): Event { - const ERROR_TYPES_RE = - /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/i; + const ERROR_TYPES_RE = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/i; // If 'message' is ErrorEvent, get real message from inside let message = isErrorEvent(msg) ? msg.message : msg; From aaa3339953d95f6476720f24a685c334bf630b3e Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Fri, 10 Dec 2021 16:54:26 -0500 Subject: [PATCH 3/4] Don't repeat addBreadcrumb --- .../browser/src/integrations/breadcrumbs.ts | 78 +++++++++++-------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/packages/browser/src/integrations/breadcrumbs.ts b/packages/browser/src/integrations/breadcrumbs.ts index 74d1b2cf3fa6..8c771b242174 100644 --- a/packages/browser/src/integrations/breadcrumbs.ts +++ b/packages/browser/src/integrations/breadcrumbs.ts @@ -16,6 +16,9 @@ const HISTORY = 'history'; const DOM = 'dom'; const XHR = 'xhr'; +type AddBreadcrumb = Hub['addBreadcrumb']; +type AddBreadcrumbParams = Parameters; + /** JSDoc */ interface BreadcrumbsOptions { console: boolean; @@ -71,9 +74,17 @@ export class Breadcrumbs implements Integration { public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { const hub = getCurrentHub(); + // Alias the addBreadcrumb function to save on bundle size + function addBreadcrumb( + breadcrumb: AddBreadcrumbParams[0], + breadcrumbHint: AddBreadcrumbParams[1], + ): ReturnType { + hub.addBreadcrumb(breadcrumb, breadcrumbHint); + } + addGlobalEventProcessor(event => { if (this._options.sentry) { - hub.addBreadcrumb( + addBreadcrumb( { category: `sentry.${event.type === 'transaction' ? 'transaction' : 'event'}`, event_id: event.event_id, @@ -89,19 +100,19 @@ export class Breadcrumbs implements Integration { }); if (this._options.console) { - _addConsoleBreadcrumbs(hub); + _addConsoleBreadcrumbs(addBreadcrumb); } if (this._options.dom) { - _addDomBreadcrumbs(hub, this._options.dom); + _addDomBreadcrumbs(addBreadcrumb, this._options.dom); } if (this._options.xhr) { - _addXhrBreadcrumbs(hub); + _addXhrBreadcrumbs(addBreadcrumb); } if (this._options.fetch) { - _addFetchBreadcrumbs(hub); + _addFetchBreadcrumbs(addBreadcrumb); } if (this._options.history) { - _addHistoryBreadcrumbs(hub); + _addHistoryBreadcrumbs(addBreadcrumb); } } } @@ -109,7 +120,7 @@ export class Breadcrumbs implements Integration { /** * Creates breadcrumbs from console API calls */ -function _addConsoleBreadcrumbs(hub: Hub): void { +function _addConsoleBreadcrumbs(addBreadcrumb: AddBreadcrumb): void { // eslint-disable-next-line @typescript-eslint/no-explicit-any addInstrumentationHandler((handlerData: { [key: string]: any }): void => { const breadcrumb = { @@ -132,7 +143,7 @@ function _addConsoleBreadcrumbs(hub: Hub): void { } } - hub.addBreadcrumb(breadcrumb, { + addBreadcrumb(breadcrumb, { input: handlerData.args, level: handlerData.level, }); @@ -142,10 +153,10 @@ function _addConsoleBreadcrumbs(hub: Hub): void { /** * Creates breadcrumbs from DOM API calls */ -function _addDomBreadcrumbs(hub: Hub, dom: BreadcrumbsOptions['dom']): void { +function _addDomBreadcrumbs(addBreadcrumb: AddBreadcrumb, dom: BreadcrumbsOptions['dom']): void { // eslint-disable-next-line @typescript-eslint/no-explicit-any addInstrumentationHandler((handlerData: { [key: string]: any }): void => { - let target; + const { event, name, global } = handlerData; let keyAttrs = typeof dom === 'object' ? dom.serializeAttribute : undefined; if (typeof keyAttrs === 'string') { @@ -153,36 +164,35 @@ function _addDomBreadcrumbs(hub: Hub, dom: BreadcrumbsOptions['dom']): void { } // Accessing event.target can throw (see getsentry/raven-js#838, #768) + let target; try { - target = handlerData.event.target - ? htmlTreeAsString(handlerData.event.target as Node, keyAttrs) - : htmlTreeAsString((handlerData.event as unknown) as Node, keyAttrs); + target = event.target + ? htmlTreeAsString(event.target as Node, keyAttrs) + : htmlTreeAsString((event as unknown) as Node, keyAttrs); } catch (e) { target = ''; } - if (target.length === 0) { - return; + if (target) { + addBreadcrumb( + { + category: `ui.${name}`, + message: target, + }, + { + event, + name, + global, + }, + ); } - - hub.addBreadcrumb( - { - category: `ui.${handlerData.name}`, - message: target, - }, - { - event: handlerData.event, - name: handlerData.name, - global: handlerData.global, - }, - ); }, DOM); } /** * Creates breadcrumbs from XHR API calls */ -function _addXhrBreadcrumbs(hub: Hub): void { +function _addXhrBreadcrumbs(addBreadcrumb: AddBreadcrumb): void { // eslint-disable-next-line @typescript-eslint/no-explicit-any addInstrumentationHandler((handlerData: { [key: string]: any }): void => { if (handlerData.endTimestamp) { @@ -193,7 +203,7 @@ function _addXhrBreadcrumbs(hub: Hub): void { const { method, url, status_code, body } = handlerData.xhr.__sentry_xhr__ || {}; - hub.addBreadcrumb( + addBreadcrumb( { category: XHR, data: { @@ -215,7 +225,7 @@ function _addXhrBreadcrumbs(hub: Hub): void { /** * Creates breadcrumbs from fetch API calls */ -function _addFetchBreadcrumbs(hub: Hub): void { +function _addFetchBreadcrumbs(addBreadcrumb: AddBreadcrumb): void { // eslint-disable-next-line @typescript-eslint/no-explicit-any addInstrumentationHandler((handlerData: { [key: string]: any }): void => { // We only capture complete fetch requests @@ -239,11 +249,11 @@ function _addFetchBreadcrumbs(hub: Hub): void { if (handlerData.error) { breadcrumbHint.data = handlerData.error; - hub.addBreadcrumb(breadcrumb, breadcrumbHint); + addBreadcrumb(breadcrumb, breadcrumbHint); } else { breadcrumb.data.status_code = handlerData.response.status; breadcrumbHint.response = handlerData.response; - hub.addBreadcrumb(breadcrumb, breadcrumbHint); + addBreadcrumb(breadcrumb, breadcrumbHint); } }, FETCH); } @@ -251,7 +261,7 @@ function _addFetchBreadcrumbs(hub: Hub): void { /** * Creates breadcrumbs from history API calls */ -function _addHistoryBreadcrumbs(hub: Hub): void { +function _addHistoryBreadcrumbs(addBreadcrumb: AddBreadcrumb): void { // eslint-disable-next-line @typescript-eslint/no-explicit-any addInstrumentationHandler((handlerData: { [key: string]: any }): void => { let { from, to } = handlerData; @@ -274,7 +284,7 @@ function _addHistoryBreadcrumbs(hub: Hub): void { from = parsedFrom.relative; } - hub.addBreadcrumb({ + addBreadcrumb({ category: 'navigation', data: { from, From 3c91f6f4d5d2bcedefa68bc02f2c9c0a3b88e346 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Fri, 10 Dec 2021 16:56:21 -0500 Subject: [PATCH 4/4] Extract --- .../browser/src/integrations/breadcrumbs.ts | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/packages/browser/src/integrations/breadcrumbs.ts b/packages/browser/src/integrations/breadcrumbs.ts index 8c771b242174..d963d15656ae 100644 --- a/packages/browser/src/integrations/breadcrumbs.ts +++ b/packages/browser/src/integrations/breadcrumbs.ts @@ -197,27 +197,25 @@ function _addXhrBreadcrumbs(addBreadcrumb: AddBreadcrumb): void { addInstrumentationHandler((handlerData: { [key: string]: any }): void => { if (handlerData.endTimestamp) { // We only capture complete, non-sentry requests - if (handlerData.xhr.__sentry_own_request__) { - return; - } + if (!handlerData.xhr.__sentry_own_request__) { + const { method, url, status_code, body } = handlerData.xhr.__sentry_xhr__ || {}; - const { method, url, status_code, body } = handlerData.xhr.__sentry_xhr__ || {}; - - addBreadcrumb( - { - category: XHR, - data: { - method, - url, - status_code, + addBreadcrumb( + { + category: XHR, + data: { + method, + url, + status_code, + }, + type: 'http', }, - type: 'http', - }, - { - xhr: handlerData.xhr, - input: body, - }, - ); + { + xhr: handlerData.xhr, + input: body, + }, + ); + } } }, XHR); }