From dc6106abd764cebf6f86f318f967492123fd009f Mon Sep 17 00:00:00 2001 From: Grzegorz Swatowski Date: Wed, 13 Mar 2024 16:33:56 +0100 Subject: [PATCH] feat(exporter-trace-otlp-http): fallback to XHR if sendBeacon fails --- .../browser/OTLPExporterBrowserBase.ts | 15 ++++----- .../src/platform/browser/util.ts | 32 ++++++++++++++----- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/experimental/packages/otlp-exporter-base/src/platform/browser/OTLPExporterBrowserBase.ts b/experimental/packages/otlp-exporter-base/src/platform/browser/OTLPExporterBrowserBase.ts index 1c3715055a..66edb8f2a9 100644 --- a/experimental/packages/otlp-exporter-base/src/platform/browser/OTLPExporterBrowserBase.ts +++ b/experimental/packages/otlp-exporter-base/src/platform/browser/OTLPExporterBrowserBase.ts @@ -69,7 +69,12 @@ export abstract class OTLPExporterBrowserBase< const body = JSON.stringify(serviceRequest); const promise = new Promise((resolve, reject) => { - if (this._useXHR) { + if ( + !this._useXHR && + sendWithBeacon(body, this.url, { type: 'application/json' }) + ) { + resolve(); + } else { sendWithXhr( body, this.url, @@ -78,14 +83,6 @@ export abstract class OTLPExporterBrowserBase< resolve, reject ); - } else { - sendWithBeacon( - body, - this.url, - { type: 'application/json' }, - resolve, - reject - ); } }).then(onSuccess, onError); diff --git a/experimental/packages/otlp-exporter-base/src/platform/browser/util.ts b/experimental/packages/otlp-exporter-base/src/platform/browser/util.ts index fade4afa88..f7d771f42a 100644 --- a/experimental/packages/otlp-exporter-base/src/platform/browser/util.ts +++ b/experimental/packages/otlp-exporter-base/src/platform/browser/util.ts @@ -24,6 +24,13 @@ import { parseRetryAfterToMills, } from '../../util'; +let minimumFailedSendBeaconPayloadSize = Infinity; + +// exported only for test files +export const resetSendWithBeacon = () => { + minimumFailedSendBeaconPayloadSize = Infinity; +}; + /** * Send metrics/spans using browser navigator.sendBeacon * @param body @@ -36,16 +43,25 @@ export function sendWithBeacon( body: string, url: string, blobPropertyBag: BlobPropertyBag, - onSuccess: () => void, - onError: (error: OTLPExporterError) => void -): void { - if (navigator.sendBeacon(url, new Blob([body], blobPropertyBag))) { +): boolean { + // navigator.sendBeacon returns 'false' if the given payload exceeds the user agent limit. + // See https://w3c.github.io/beacon/#return-value for specification. + // Because we don't know what the limit is and to keep user's console clean, we only try to send payloads that may suceed. + const blob = new Blob([body], blobPropertyBag); + if ( + blob.size < minimumFailedSendBeaconPayloadSize && + navigator.sendBeacon(url, blob) + ) { diag.debug('sendBeacon - can send', body); - onSuccess(); - } else { - const error = new OTLPExporterError(`sendBeacon - cannot send ${body}`); - onError(error); + return true; } + + minimumFailedSendBeaconPayloadSize = blob.size; + diag.info( + 'sendBeacon failed because the given payload was too big; try to lower your span processor limits', + ); + + return false; } /**