@scalebun/react-native 1.2.0 → 1.2.1
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/scalebun.full.js +103 -17
- package/dist/scalebun.full.js.map +1 -1
- package/dist/scalebun.slim.js +103 -17
- package/dist/scalebun.slim.js.map +1 -1
- package/lib/commonjs/features/performance/PerformanceFeature.js +121 -23
- package/lib/commonjs/features/performance/PerformanceFeature.js.map +1 -1
- package/lib/module/features/performance/PerformanceFeature.js +122 -23
- package/lib/module/features/performance/PerformanceFeature.js.map +1 -1
- package/lib/typescript/features/performance/PerformanceFeature.d.ts +31 -0
- package/lib/typescript/features/performance/PerformanceFeature.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/features/performance/PerformanceFeature.ts +130 -20
package/dist/scalebun.full.js
CHANGED
|
@@ -8369,7 +8369,31 @@ var init_PerformanceFeature = __esm({
|
|
|
8369
8369
|
static CAPTURE_MAX_RETRIES = 3;
|
|
8370
8370
|
/** Delay schedule for each attempt (ms) — escalating to let views settle */
|
|
8371
8371
|
static CAPTURE_DELAYS = [300, 600, 1200];
|
|
8372
|
-
//
|
|
8372
|
+
// ─── Early-metric buffering (backend) ───────────────────────────────
|
|
8373
|
+
//
|
|
8374
|
+
// Performance metrics reach the cloud via the SessionManager's backend
|
|
8375
|
+
// transport. But the first metrics — most importantly app_launch — fire
|
|
8376
|
+
// during PerformanceFeature.initialize() (appLaunchCollector.collect()),
|
|
8377
|
+
// which runs from featureRegistry.initializeAll() BEFORE the bootstrap
|
|
8378
|
+
// attaches the backend transport (SDKBootstrapper). In that window
|
|
8379
|
+
// getBackendTransport() is null, so without buffering the metric is sent
|
|
8380
|
+
// only to the desktop debugger and silently dropped from the cloud
|
|
8381
|
+
// ("App start = 0" in Insights). We buffer such metrics locally and drain
|
|
8382
|
+
// them the moment the transport appears (via subsequent events or a
|
|
8383
|
+
// bounded retry). The backend adapter itself buffers again until the
|
|
8384
|
+
// session row is ready, so ordering across the session boundary is safe.
|
|
8385
|
+
/** Metrics captured before the backend transport was available. */
|
|
8386
|
+
_pendingBackendMetrics = [];
|
|
8387
|
+
/** Retry timer that drains the buffer once the transport attaches. */
|
|
8388
|
+
_backendDrainTimer = null;
|
|
8389
|
+
/** Number of drain attempts made for the current buffered batch. */
|
|
8390
|
+
_backendDrainAttempts = 0;
|
|
8391
|
+
/** Hard cap on buffered metrics — bounds memory if a transport never attaches (non-SaaS). */
|
|
8392
|
+
static BACKEND_BUFFER_MAX = 64;
|
|
8393
|
+
/** Max drain retries before giving up (non-SaaS mode never attaches a transport). */
|
|
8394
|
+
static BACKEND_DRAIN_MAX_ATTEMPTS = 6;
|
|
8395
|
+
/** Escalating retry delays (ms); last value repeats. Covers the startup attach race. */
|
|
8396
|
+
static BACKEND_DRAIN_DELAYS = [250, 500, 1e3, 2e3, 4e3];
|
|
8373
8397
|
constructor(config) {
|
|
8374
8398
|
this.config = mergePerformanceConfig(config);
|
|
8375
8399
|
this.transport = new PerformanceTransport(this.config);
|
|
@@ -8504,6 +8528,9 @@ var init_PerformanceFeature = __esm({
|
|
|
8504
8528
|
clearTimeout(this._captureTimer);
|
|
8505
8529
|
this._captureTimer = null;
|
|
8506
8530
|
}
|
|
8531
|
+
this._clearBackendDrainTimer();
|
|
8532
|
+
this._backendDrainAttempts = 0;
|
|
8533
|
+
this._pendingBackendMetrics = [];
|
|
8507
8534
|
}
|
|
8508
8535
|
get isActive() {
|
|
8509
8536
|
return this.active;
|
|
@@ -8687,24 +8714,83 @@ var init_PerformanceFeature = __esm({
|
|
|
8687
8714
|
// ─── Internal ───────────────────────────────────────────────────────
|
|
8688
8715
|
_handleEvent(event) {
|
|
8689
8716
|
this.transport.sendEvent(event);
|
|
8717
|
+
this._forwardMetricToBackend(this._toBackendMetric(event));
|
|
8718
|
+
}
|
|
8719
|
+
/** Map a raw perf event onto the backend metric envelope. */
|
|
8720
|
+
_toBackendMetric(event) {
|
|
8721
|
+
const e = event;
|
|
8722
|
+
const metadata = {
|
|
8723
|
+
id: event.id
|
|
8724
|
+
};
|
|
8725
|
+
if (event.type === "app_launch") {
|
|
8726
|
+
if (e.launchType) metadata.launchType = e.launchType;
|
|
8727
|
+
if (e.breakdown) metadata.breakdown = e.breakdown;
|
|
8728
|
+
if (e.phaseLabels) metadata.phaseLabels = e.phaseLabels;
|
|
8729
|
+
}
|
|
8730
|
+
return {
|
|
8731
|
+
type: event.type,
|
|
8732
|
+
screenName: e.screenName ?? e.context?.screenKey,
|
|
8733
|
+
duration: e.durationMs,
|
|
8734
|
+
value: e.estimatedFps ?? e.value,
|
|
8735
|
+
metadata
|
|
8736
|
+
};
|
|
8737
|
+
}
|
|
8738
|
+
/**
|
|
8739
|
+
* Hand a metric to the backend transport, or buffer it until one attaches.
|
|
8740
|
+
* Every call first drains anything buffered, so a late-arriving transport
|
|
8741
|
+
* flushes the backlog in the order the metrics were produced.
|
|
8742
|
+
*/
|
|
8743
|
+
_forwardMetricToBackend(metric) {
|
|
8690
8744
|
const backendTransport = SessionManager.getExistingInstance()?.getBackendTransport();
|
|
8691
8745
|
if (backendTransport) {
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8697
|
-
|
|
8698
|
-
|
|
8699
|
-
|
|
8700
|
-
|
|
8701
|
-
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
|
|
8706
|
-
|
|
8707
|
-
|
|
8746
|
+
this._drainPendingBackendMetrics(backendTransport);
|
|
8747
|
+
backendTransport.queuePerformanceMetric(metric);
|
|
8748
|
+
return;
|
|
8749
|
+
}
|
|
8750
|
+
this._pendingBackendMetrics.push(metric);
|
|
8751
|
+
if (this._pendingBackendMetrics.length > _PerformanceFeature.BACKEND_BUFFER_MAX) {
|
|
8752
|
+
this._pendingBackendMetrics.shift();
|
|
8753
|
+
}
|
|
8754
|
+
this._scheduleBackendDrain();
|
|
8755
|
+
}
|
|
8756
|
+
/** Flush all buffered metrics into the transport, preserving order. */
|
|
8757
|
+
_drainPendingBackendMetrics(backendTransport) {
|
|
8758
|
+
if (this._pendingBackendMetrics.length === 0) return;
|
|
8759
|
+
const buffered = this._pendingBackendMetrics;
|
|
8760
|
+
this._pendingBackendMetrics = [];
|
|
8761
|
+
for (const metric of buffered) {
|
|
8762
|
+
backendTransport.queuePerformanceMetric(metric);
|
|
8763
|
+
}
|
|
8764
|
+
this._clearBackendDrainTimer();
|
|
8765
|
+
this._backendDrainAttempts = 0;
|
|
8766
|
+
}
|
|
8767
|
+
/**
|
|
8768
|
+
* Poll for the backend transport a bounded number of times so the sole
|
|
8769
|
+
* early metric (app_launch) still reaches the cloud even when no later
|
|
8770
|
+
* event arrives to trigger a drain. Gives up after BACKEND_DRAIN_MAX_ATTEMPTS
|
|
8771
|
+
* (non-SaaS mode never attaches a transport — the desktop path already has
|
|
8772
|
+
* the data), leaving the bounded buffer to be GC'd on teardown.
|
|
8773
|
+
*/
|
|
8774
|
+
_scheduleBackendDrain() {
|
|
8775
|
+
if (this._backendDrainTimer) return;
|
|
8776
|
+
if (this._backendDrainAttempts >= _PerformanceFeature.BACKEND_DRAIN_MAX_ATTEMPTS) return;
|
|
8777
|
+
const delays = _PerformanceFeature.BACKEND_DRAIN_DELAYS;
|
|
8778
|
+
const delay = delays[Math.min(this._backendDrainAttempts, delays.length - 1)];
|
|
8779
|
+
this._backendDrainAttempts++;
|
|
8780
|
+
this._backendDrainTimer = setTimeout(() => {
|
|
8781
|
+
this._backendDrainTimer = null;
|
|
8782
|
+
const backendTransport = SessionManager.getExistingInstance()?.getBackendTransport();
|
|
8783
|
+
if (backendTransport) {
|
|
8784
|
+
this._drainPendingBackendMetrics(backendTransport);
|
|
8785
|
+
} else if (this._pendingBackendMetrics.length > 0) {
|
|
8786
|
+
this._scheduleBackendDrain();
|
|
8787
|
+
}
|
|
8788
|
+
}, delay);
|
|
8789
|
+
}
|
|
8790
|
+
_clearBackendDrainTimer() {
|
|
8791
|
+
if (this._backendDrainTimer) {
|
|
8792
|
+
clearTimeout(this._backendDrainTimer);
|
|
8793
|
+
this._backendDrainTimer = null;
|
|
8708
8794
|
}
|
|
8709
8795
|
}
|
|
8710
8796
|
};
|