From 2d43b64f5ffdc59bc12dd86e3ce812bbced3893e Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Tue, 30 Jul 2024 15:07:19 -0230 Subject: [PATCH] feat(replay): Capture exception when `internal_sdk_error` client report happens (#13072) We currently have no visibility when this client report happens. Lets capture the exception if our experimental flag is on. Also refactors `_handleException()` to be a public method instead of private. --- packages/replay-internal/src/replay.ts | 32 +++++++++---------- packages/replay-internal/src/types/replay.ts | 1 + packages/replay-internal/src/util/addEvent.ts | 2 +- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/packages/replay-internal/src/replay.ts b/packages/replay-internal/src/replay.ts index a0ef13276e1a..f42d6ef6964a 100644 --- a/packages/replay-internal/src/replay.ts +++ b/packages/replay-internal/src/replay.ts @@ -241,6 +241,15 @@ export class ReplayContainer implements ReplayContainerInterface { return this._options; } + /** A wrapper to conditionally capture exceptions. */ + public handleException(error: unknown): void { + DEBUG_BUILD && logger.error('[Replay]', error); + + if (DEBUG_BUILD && this._options._experiments && this._options._experiments.captureExceptions) { + captureException(error); + } + } + /** * Initializes the plugin based on sampling configuration. Should not be * called outside of constructor. @@ -264,7 +273,7 @@ export class ReplayContainer implements ReplayContainerInterface { if (!this.session) { // This should not happen, something wrong has occurred - this._handleException(new Error('Unable to initialize and create session')); + this.handleException(new Error('Unable to initialize and create session')); return; } @@ -389,7 +398,7 @@ export class ReplayContainer implements ReplayContainerInterface { : {}), }); } catch (err) { - this._handleException(err); + this.handleException(err); } } @@ -408,7 +417,7 @@ export class ReplayContainer implements ReplayContainerInterface { return true; } catch (err) { - this._handleException(err); + this.handleException(err); return false; } } @@ -450,7 +459,7 @@ export class ReplayContainer implements ReplayContainerInterface { // is started after, it will not have `previousSessionId` clearSession(this); } catch (err) { - this._handleException(err); + this.handleException(err); } } @@ -777,15 +786,6 @@ export class ReplayContainer implements ReplayContainerInterface { this.startRecording(); } - /** A wrapper to conditionally capture exceptions. */ - private _handleException(error: unknown): void { - DEBUG_BUILD && logger.error('[Replay]', error); - - if (DEBUG_BUILD && this._options._experiments && this._options._experiments.captureExceptions) { - captureException(error); - } - } - /** * Loads (or refreshes) the current session. */ @@ -873,7 +873,7 @@ export class ReplayContainer implements ReplayContainerInterface { this._hasInitializedCoreListeners = true; } } catch (err) { - this._handleException(err); + this.handleException(err); } this._performanceCleanupCallback = setupPerformanceObserver(this); @@ -898,7 +898,7 @@ export class ReplayContainer implements ReplayContainerInterface { this._performanceCleanupCallback(); } } catch (err) { - this._handleException(err); + this.handleException(err); } } @@ -1161,7 +1161,7 @@ export class ReplayContainer implements ReplayContainerInterface { timestamp, }); } catch (err) { - this._handleException(err); + this.handleException(err); // This means we retried 3 times and all of them failed, // or we ran into a problem we don't want to retry, like rate limiting. diff --git a/packages/replay-internal/src/types/replay.ts b/packages/replay-internal/src/types/replay.ts index 7ebacad9e100..1e510e2bc519 100644 --- a/packages/replay-internal/src/types/replay.ts +++ b/packages/replay-internal/src/types/replay.ts @@ -485,6 +485,7 @@ export interface ReplayContainer { checkAndHandleExpiredSession(): boolean | void; setInitialState(): void; getCurrentRoute(): string | undefined; + handleException(err: unknown): void; } type RequestBody = null | Blob | BufferSource | FormData | URLSearchParams | string; diff --git a/packages/replay-internal/src/util/addEvent.ts b/packages/replay-internal/src/util/addEvent.ts index b2a011687428..f397ea0564f6 100644 --- a/packages/replay-internal/src/util/addEvent.ts +++ b/packages/replay-internal/src/util/addEvent.ts @@ -79,8 +79,8 @@ async function _addEvent( return await replay.eventBuffer.addEvent(eventAfterPossibleCallback); } catch (error) { const reason = error && error instanceof EventBufferSizeExceededError ? 'addEventSizeExceeded' : 'addEvent'; + replay.handleException(error); - DEBUG_BUILD && logger.error(error); await replay.stop({ reason }); const client = getClient();