@firebase/performance 0.7.7 → 0.7.8-20250716004940

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -10,7 +10,7 @@ var component = require('@firebase/component');
10
10
  require('@firebase/installations');
11
11
 
12
12
  const name = "@firebase/performance";
13
- const version = "0.7.7";
13
+ const version = "0.7.8-20250716004940";
14
14
 
15
15
  /**
16
16
  * @license
@@ -331,6 +331,9 @@ class SettingsService {
331
331
  this.logNetworkAfterSampling = false;
332
332
  // TTL of config retrieved from remote config in hours.
333
333
  this.configTimeToLive = 12;
334
+ // The max number of events to send during a flush. This number is kept low to since Chrome has a
335
+ // shared payload limit for all sendBeacon calls in the same nav context.
336
+ this.logMaxFlushSize = 40;
334
337
  }
335
338
  getFlTransportFullUrl() {
336
339
  return this.flTransportEndpointUrl.concat('?key=', this.transportKey);
@@ -371,7 +374,7 @@ const MAX_ATTRIBUTE_NAME_LENGTH = 40;
371
374
  const MAX_ATTRIBUTE_VALUE_LENGTH = 100;
372
375
  function getServiceWorkerStatus() {
373
376
  const navigator = Api.getInstance().navigator;
374
- if (navigator === null || navigator === void 0 ? void 0 : navigator.serviceWorker) {
377
+ if (navigator?.serviceWorker) {
375
378
  if (navigator.serviceWorker.controller) {
376
379
  return 2 /* ServiceWorkerStatus.CONTROLLED */;
377
380
  }
@@ -440,24 +443,21 @@ function isValidCustomAttributeValue(value) {
440
443
  * limitations under the License.
441
444
  */
442
445
  function getAppId(firebaseApp) {
443
- var _a;
444
- const appId = (_a = firebaseApp.options) === null || _a === void 0 ? void 0 : _a.appId;
446
+ const appId = firebaseApp.options?.appId;
445
447
  if (!appId) {
446
448
  throw ERROR_FACTORY.create("no app id" /* ErrorCode.NO_APP_ID */);
447
449
  }
448
450
  return appId;
449
451
  }
450
452
  function getProjectId(firebaseApp) {
451
- var _a;
452
- const projectId = (_a = firebaseApp.options) === null || _a === void 0 ? void 0 : _a.projectId;
453
+ const projectId = firebaseApp.options?.projectId;
453
454
  if (!projectId) {
454
455
  throw ERROR_FACTORY.create("no project id" /* ErrorCode.NO_PROJECT_ID */);
455
456
  }
456
457
  return projectId;
457
458
  }
458
459
  function getApiKey(firebaseApp) {
459
- var _a;
460
- const apiKey = (_a = firebaseApp.options) === null || _a === void 0 ? void 0 : _a.apiKey;
460
+ const apiKey = firebaseApp.options?.apiKey;
461
461
  if (!apiKey) {
462
462
  throw ERROR_FACTORY.create("no api key" /* ErrorCode.NO_API_KEY */);
463
463
  }
@@ -516,7 +516,7 @@ function getStoredConfig() {
516
516
  const configResponse = JSON.parse(configStringified);
517
517
  return configResponse;
518
518
  }
519
- catch (_a) {
519
+ catch {
520
520
  return;
521
521
  }
522
522
  }
@@ -618,6 +618,12 @@ function processConfig(config) {
618
618
  settingsServiceInstance.tracesSamplingRate =
619
619
  DEFAULT_CONFIGS.tracesSamplingRate;
620
620
  }
621
+ if (entries.fpr_log_max_flush_size) {
622
+ settingsServiceInstance.logMaxFlushSize = Number(entries.fpr_log_max_flush_size);
623
+ }
624
+ else if (DEFAULT_CONFIGS.logMaxFlushSize) {
625
+ settingsServiceInstance.logMaxFlushSize = DEFAULT_CONFIGS.logMaxFlushSize;
626
+ }
621
627
  // Set the per session trace and network logging flags.
622
628
  settingsServiceInstance.logTraceAfterSampling = shouldLogAfterSampling(settingsServiceInstance.tracesSamplingRate);
623
629
  settingsServiceInstance.logNetworkAfterSampling = shouldLogAfterSampling(settingsServiceInstance.networkRequestsSamplingRate);
@@ -708,6 +714,9 @@ const DEFAULT_SEND_INTERVAL_MS = 10 * 1000;
708
714
  const INITIAL_SEND_TIME_DELAY_MS = 5.5 * 1000;
709
715
  const MAX_EVENT_COUNT_PER_REQUEST = 1000;
710
716
  const DEFAULT_REMAINING_TRIES = 3;
717
+ // Most browsers have a max payload of 64KB for sendbeacon/keep alive payload.
718
+ const MAX_SEND_BEACON_PAYLOAD_SIZE = 65536;
719
+ const TEXT_ENCODER = new TextEncoder();
711
720
  let remainingTries = DEFAULT_REMAINING_TRIES;
712
721
  /* eslint-enable camelcase */
713
722
  let queue = [];
@@ -735,13 +744,28 @@ function dispatchQueueEvents() {
735
744
  // The staged events will be used for current logRequest attempt, remaining events will be kept
736
745
  // for next attempt.
737
746
  const staged = queue.splice(0, MAX_EVENT_COUNT_PER_REQUEST);
747
+ const data = buildPayload(staged);
748
+ postToFlEndpoint(data)
749
+ .then(() => {
750
+ remainingTries = DEFAULT_REMAINING_TRIES;
751
+ })
752
+ .catch(() => {
753
+ // If the request fails for some reason, add the events that were attempted
754
+ // back to the primary queue to retry later.
755
+ queue = [...staged, ...queue];
756
+ remainingTries--;
757
+ consoleLogger.info(`Tries left: ${remainingTries}.`);
758
+ processQueue(DEFAULT_SEND_INTERVAL_MS);
759
+ });
760
+ }
761
+ function buildPayload(events) {
738
762
  /* eslint-disable camelcase */
739
763
  // We will pass the JSON serialized event to the backend.
740
- const log_event = staged.map(evt => ({
764
+ const log_event = events.map(evt => ({
741
765
  source_extension_json_proto3: evt.message,
742
766
  event_time_ms: String(evt.eventTime)
743
767
  }));
744
- const data = {
768
+ const transportBatchLog = {
745
769
  request_time_ms: String(Date.now()),
746
770
  client_info: {
747
771
  client_type: 1, // 1 is JS
@@ -751,29 +775,23 @@ function dispatchQueueEvents() {
751
775
  log_event
752
776
  };
753
777
  /* eslint-enable camelcase */
754
- postToFlEndpoint(data)
755
- .then(() => {
756
- remainingTries = DEFAULT_REMAINING_TRIES;
757
- })
758
- .catch(() => {
759
- // If the request fails for some reason, add the events that were attempted
760
- // back to the primary queue to retry later.
761
- queue = [...staged, ...queue];
762
- remainingTries--;
763
- consoleLogger.info(`Tries left: ${remainingTries}.`);
764
- processQueue(DEFAULT_SEND_INTERVAL_MS);
765
- });
778
+ return JSON.stringify(transportBatchLog);
766
779
  }
767
- function postToFlEndpoint(data) {
780
+ /** Sends to Firelog. Atempts to use sendBeacon otherwsise uses fetch. */
781
+ function postToFlEndpoint(body) {
768
782
  const flTransportFullUrl = SettingsService.getInstance().getFlTransportFullUrl();
769
- const body = JSON.stringify(data);
770
- return navigator.sendBeacon && navigator.sendBeacon(flTransportFullUrl, body)
771
- ? Promise.resolve()
772
- : fetch(flTransportFullUrl, {
783
+ const size = TEXT_ENCODER.encode(body).length;
784
+ if (size <= MAX_SEND_BEACON_PAYLOAD_SIZE &&
785
+ navigator.sendBeacon &&
786
+ navigator.sendBeacon(flTransportFullUrl, body)) {
787
+ return Promise.resolve();
788
+ }
789
+ else {
790
+ return fetch(flTransportFullUrl, {
773
791
  method: 'POST',
774
- body,
775
- keepalive: true
776
- }).then();
792
+ body
793
+ });
794
+ }
777
795
  }
778
796
  function addToQueue(evt) {
779
797
  if (!evt.eventTime || !evt.message) {
@@ -795,12 +813,33 @@ serializer) {
795
813
  };
796
814
  }
797
815
  /**
798
- * Force flush the queued events. Useful at page unload time to ensure all
799
- * events are uploaded.
816
+ * Force flush the queued events. Useful at page unload time to ensure all events are uploaded.
817
+ * Flush will attempt to use sendBeacon to send events async and defaults back to fetch as soon as a
818
+ * sendBeacon fails. Firefox
800
819
  */
801
820
  function flushQueuedEvents() {
821
+ const flTransportFullUrl = SettingsService.getInstance().getFlTransportFullUrl();
802
822
  while (queue.length > 0) {
803
- dispatchQueueEvents();
823
+ // Send the last events first to prioritize page load traces
824
+ const staged = queue.splice(-SettingsService.getInstance().logMaxFlushSize);
825
+ const body = buildPayload(staged);
826
+ if (navigator.sendBeacon &&
827
+ navigator.sendBeacon(flTransportFullUrl, body)) {
828
+ continue;
829
+ }
830
+ else {
831
+ queue = [...queue, ...staged];
832
+ break;
833
+ }
834
+ }
835
+ if (queue.length > 0) {
836
+ const body = buildPayload(queue);
837
+ fetch(flTransportFullUrl, {
838
+ method: 'POST',
839
+ body
840
+ }).catch(() => {
841
+ consoleLogger.info(`Failed flushing queued events.`);
842
+ });
804
843
  }
805
844
  }
806
845
 
@@ -1141,7 +1180,7 @@ class Trace {
1141
1180
  this.durationUs = Math.floor(duration * 1000);
1142
1181
  this.startTimeUs = Math.floor(startTime * 1000);
1143
1182
  if (options && options.attributes) {
1144
- this.customAttributes = Object.assign({}, options.attributes);
1183
+ this.customAttributes = { ...options.attributes };
1145
1184
  }
1146
1185
  if (options && options.metrics) {
1147
1186
  for (const metricName of Object.keys(options.metrics)) {
@@ -1175,7 +1214,7 @@ class Trace {
1175
1214
  */
1176
1215
  putMetric(counter, numAsInteger) {
1177
1216
  if (isValidMetricName(counter, this.name)) {
1178
- this.counters[counter] = convertMetricValueToInteger(numAsInteger !== null && numAsInteger !== void 0 ? numAsInteger : 0);
1217
+ this.counters[counter] = convertMetricValueToInteger(numAsInteger ?? 0);
1179
1218
  }
1180
1219
  else {
1181
1220
  throw ERROR_FACTORY.create("invalid custom metric name" /* ErrorCode.INVALID_CUSTOM_METRIC_NAME */, {
@@ -1229,7 +1268,7 @@ class Trace {
1229
1268
  delete this.customAttributes[attr];
1230
1269
  }
1231
1270
  getAttributes() {
1232
- return Object.assign({}, this.customAttributes);
1271
+ return { ...this.customAttributes };
1233
1272
  }
1234
1273
  setStartTime(startTime) {
1235
1274
  this.startTimeUs = startTime;
@@ -1366,24 +1405,21 @@ function setupOobTraces(performanceController) {
1366
1405
  });
1367
1406
  }
1368
1407
  api.onLCP((metric) => {
1369
- var _a;
1370
1408
  webVitalMetrics.lcp = {
1371
1409
  value: metric.value,
1372
- elementAttribution: (_a = metric.attribution) === null || _a === void 0 ? void 0 : _a.element
1410
+ elementAttribution: metric.attribution?.element
1373
1411
  };
1374
1412
  });
1375
1413
  api.onCLS((metric) => {
1376
- var _a;
1377
1414
  webVitalMetrics.cls = {
1378
1415
  value: metric.value,
1379
- elementAttribution: (_a = metric.attribution) === null || _a === void 0 ? void 0 : _a.largestShiftTarget
1416
+ elementAttribution: metric.attribution?.largestShiftTarget
1380
1417
  };
1381
1418
  });
1382
1419
  api.onINP((metric) => {
1383
- var _a;
1384
1420
  webVitalMetrics.inp = {
1385
1421
  value: metric.value,
1386
- elementAttribution: (_a = metric.attribution) === null || _a === void 0 ? void 0 : _a.interactionTarget
1422
+ elementAttribution: metric.attribution?.interactionTarget
1387
1423
  };
1388
1424
  });
1389
1425
  }
@@ -1456,10 +1492,10 @@ class PerformanceController {
1456
1492
  if (this.initialized) {
1457
1493
  return;
1458
1494
  }
1459
- if ((settings === null || settings === void 0 ? void 0 : settings.dataCollectionEnabled) !== undefined) {
1495
+ if (settings?.dataCollectionEnabled !== undefined) {
1460
1496
  this.dataCollectionEnabled = settings.dataCollectionEnabled;
1461
1497
  }
1462
- if ((settings === null || settings === void 0 ? void 0 : settings.instrumentationEnabled) !== undefined) {
1498
+ if (settings?.instrumentationEnabled !== undefined) {
1463
1499
  this.instrumentationEnabled = settings.instrumentationEnabled;
1464
1500
  }
1465
1501
  if (Api.getInstance().requiredApisAvailable()) {
@@ -1526,7 +1562,7 @@ function initializePerformance(app$1, settings) {
1526
1562
  if (provider.isInitialized()) {
1527
1563
  const existingInstance = provider.getImmediate();
1528
1564
  const initialSettings = provider.getOptions();
1529
- if (util.deepEqual(initialSettings, settings !== null && settings !== void 0 ? settings : {})) {
1565
+ if (util.deepEqual(initialSettings, settings ?? {})) {
1530
1566
  return existingInstance;
1531
1567
  }
1532
1568
  else {
@@ -1568,8 +1604,8 @@ const factory = (container, { options: settings }) => {
1568
1604
  function registerPerformance() {
1569
1605
  app._registerComponent(new component.Component('performance', factory, "PUBLIC" /* ComponentType.PUBLIC */));
1570
1606
  app.registerVersion(name, version);
1571
- // BUILD_TARGET will be replaced by values like esm2017, cjs2017, etc during the compilation
1572
- app.registerVersion(name, version, 'cjs2017');
1607
+ // BUILD_TARGET will be replaced by values like esm, cjs, etc during the compilation
1608
+ app.registerVersion(name, version, 'cjs2020');
1573
1609
  }
1574
1610
  registerPerformance();
1575
1611