diff --git a/packages/browser/src/client.ts b/packages/browser/src/client.ts index 004f1359ffab..4f85103a86a6 100644 --- a/packages/browser/src/client.ts +++ b/packages/browser/src/client.ts @@ -1,8 +1,13 @@ -import { BaseClient, Scope, SDK_VERSION } from '@sentry/core'; +import { BaseClient, getEnvelopeEndpointWithUrlEncodedAuth, Scope, SDK_VERSION } from '@sentry/core'; import { ClientOptions, Event, EventHint, Options, Severity, SeverityLevel } from '@sentry/types'; +import { createClientReportEnvelope, dsnToString, getGlobalObject, logger, serializeEnvelope } from '@sentry/utils'; import { eventFromException, eventFromMessage } from './eventbuilder'; +import { IS_DEBUG_BUILD } from './flags'; import { Breadcrumbs } from './integrations'; +import { sendReport } from './transports/utils'; + +const globalObject = getGlobalObject(); export interface BaseBrowserOptions { /** @@ -56,7 +61,16 @@ export class BrowserClient extends BaseClient { ], version: SDK_VERSION, }; + super(options); + + if (options.sendClientReports && globalObject.document) { + globalObject.document.addEventListener('visibilitychange', () => { + if (globalObject.document.visibilityState === 'hidden') { + this._flushOutcomes(); + } + }); + } } /** @@ -96,4 +110,32 @@ export class BrowserClient extends BaseClient { } super._sendEvent(event); } + + /** + * Sends client reports as an envelope. + */ + private _flushOutcomes(): void { + const outcomes = this._clearOutcomes(); + + if (outcomes.length === 0) { + IS_DEBUG_BUILD && logger.log('No outcomes to send'); + return; + } + + if (!this._dsn) { + IS_DEBUG_BUILD && logger.log('No dsn provided, will not send outcomes'); + return; + } + + IS_DEBUG_BUILD && logger.log('Sending outcomes:', outcomes); + + const url = getEnvelopeEndpointWithUrlEncodedAuth(this._dsn, this._options.tunnel); + const envelope = createClientReportEnvelope(outcomes, this._options.tunnel && dsnToString(this._dsn)); + + try { + sendReport(url, serializeEnvelope(envelope)); + } catch (e) { + IS_DEBUG_BUILD && logger.error(e); + } + } } diff --git a/packages/browser/src/transports/utils.ts b/packages/browser/src/transports/utils.ts index 5a8e17b42019..b386557499c5 100644 --- a/packages/browser/src/transports/utils.ts +++ b/packages/browser/src/transports/utils.ts @@ -93,10 +93,8 @@ export function sendReport(url: string, body: string): void { if (hasSendBeacon) { // Prevent illegal invocations - https://xgwang.me/posts/you-may-not-know-beacon/#it-may-throw-error%2C-be-sure-to-catch const sendBeacon = global.navigator.sendBeacon.bind(global.navigator); - return sendBeacon(url, body); - } - - if (supportsFetch()) { + sendBeacon(url, body); + } else if (supportsFetch()) { const fetch = getNativeFetchImplementation(); fetch(url, { body,