@tracelog/lib 2.4.0 → 2.5.0
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/README.md +2 -1
- package/dist/browser/tracelog.esm.js +263 -252
- package/dist/browser/tracelog.esm.js.map +1 -1
- package/dist/browser/tracelog.js +1 -1
- package/dist/browser/tracelog.js.map +1 -1
- package/dist/public-api.cjs +2 -2
- package/dist/public-api.cjs.map +1 -1
- package/dist/public-api.d.mts +10 -1
- package/dist/public-api.d.ts +10 -1
- package/dist/public-api.js +2 -2
- package/dist/public-api.js.map +1 -1
- package/package.json +1 -1
|
@@ -81,9 +81,9 @@ const m = {
|
|
|
81
81
|
/<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi
|
|
82
82
|
], I = "tlog", F = `${I}:qa_mode`, be = `${I}:uid`, Ge = "tlog_mode", Le = "qa", Ae = "qa_off", ht = (s) => s ? `${I}:${s}:queue` : `${I}:queue`, ft = (s) => s ? `${I}:${s}:session` : `${I}:session`, mt = (s) => s ? `${I}:${s}:broadcast` : `${I}:broadcast`, Me = (s, e) => `${I}:${s}:session_counts:${e}`, Ce = 10080 * 60 * 1e3, Re = `${I}:session_counts_last_cleanup`, Ne = 3600 * 1e3;
|
|
83
83
|
var H = /* @__PURE__ */ ((s) => (s.Localhost = "localhost:8080", s.Fail = "localhost:9999", s))(H || {}), A = /* @__PURE__ */ ((s) => (s.Mobile = "mobile", s.Tablet = "tablet", s.Desktop = "desktop", s.Unknown = "unknown", s))(A || {}), le = /* @__PURE__ */ ((s) => (s.EVENT = "event", s.QUEUE = "queue", s))(le || {});
|
|
84
|
-
class
|
|
84
|
+
class D extends Error {
|
|
85
85
|
constructor(e, t) {
|
|
86
|
-
super(e), this.statusCode = t, this.name = "PermanentError", Error.captureStackTrace && Error.captureStackTrace(this,
|
|
86
|
+
super(e), this.statusCode = t, this.name = "PermanentError", Error.captureStackTrace && Error.captureStackTrace(this, D);
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
var d = /* @__PURE__ */ ((s) => (s.PAGE_VIEW = "page_view", s.CLICK = "click", s.SCROLL = "scroll", s.SESSION_START = "session_start", s.CUSTOM = "custom", s.WEB_VITALS = "web_vitals", s.ERROR = "error", s.VIEWPORT_VISIBLE = "viewport_visible", s))(d || {}), j = /* @__PURE__ */ ((s) => (s.UP = "up", s.DOWN = "down", s))(j || {}), x = /* @__PURE__ */ ((s) => (s.JS_ERROR = "js_error", s.PROMISE_REJECTION = "promise_rejection", s))(x || {}), Y = /* @__PURE__ */ ((s) => (s.QA = "qa", s))(Y || {});
|
|
@@ -108,7 +108,7 @@ class Oe extends $ {
|
|
|
108
108
|
super(e, "SAMPLING_RATE_INVALID", t);
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
-
class
|
|
111
|
+
class P extends $ {
|
|
112
112
|
constructor(e, t = "config") {
|
|
113
113
|
super(e, "INTEGRATION_INVALID", t);
|
|
114
114
|
}
|
|
@@ -145,11 +145,11 @@ const Xe = "background: #ff9800; color: white; font-weight: bold; padding: 2px 8
|
|
|
145
145
|
} catch {
|
|
146
146
|
return !1;
|
|
147
147
|
}
|
|
148
|
-
},
|
|
149
|
-
const { error: r, data: n, showToClient: i = !1, style: o, visibility:
|
|
150
|
-
if (!Tt(
|
|
148
|
+
}, l = (s, e, t) => {
|
|
149
|
+
const { error: r, data: n, showToClient: i = !1, style: o, visibility: a } = t ?? {}, c = r ? St(e, r) : `[TraceLog] ${e}`, u = s === "error" ? "error" : s === "warn" ? "warn" : "log";
|
|
150
|
+
if (!Tt(a, i))
|
|
151
151
|
return;
|
|
152
|
-
const g = _t(
|
|
152
|
+
const g = _t(a, o), p = n !== void 0 ? ce(n) : void 0;
|
|
153
153
|
vt(u, c, g, p);
|
|
154
154
|
}, Tt = (s, e) => s === "critical" ? !0 : s === "qa" || e ? pt() : !1, _t = (s, e) => e !== void 0 && e !== "" ? e : s === "critical" ? Et : "", vt = (s, e, t, r) => {
|
|
155
155
|
const n = t !== void 0 && t !== "", i = n ? `%c${e}` : e;
|
|
@@ -202,10 +202,10 @@ const It = () => {
|
|
|
202
202
|
return c != null && c !== "" && /ipad|tablet/i.test(c) ? A.Tablet : s.userAgentData.mobile ? A.Mobile : A.Desktop;
|
|
203
203
|
}
|
|
204
204
|
It();
|
|
205
|
-
const e = window.innerWidth, t = ue?.matches ?? !1, r = je?.matches ?? !1, n = "ontouchstart" in window || navigator.maxTouchPoints > 0, i = navigator.userAgent.toLowerCase(), o = /mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(i),
|
|
206
|
-
return e <= 767 || o && n ? A.Mobile : e >= 768 && e <= 1024 ||
|
|
205
|
+
const e = window.innerWidth, t = ue?.matches ?? !1, r = je?.matches ?? !1, n = "ontouchstart" in window || navigator.maxTouchPoints > 0, i = navigator.userAgent.toLowerCase(), o = /mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(i), a = /tablet|ipad|android(?!.*mobile)/.test(i);
|
|
206
|
+
return e <= 767 || o && n ? A.Mobile : e >= 768 && e <= 1024 || a || t && r && n ? A.Tablet : A.Desktop;
|
|
207
207
|
} catch (s) {
|
|
208
|
-
return
|
|
208
|
+
return l("debug", "Device detection failed, defaulting to desktop", { error: s }), A.Desktop;
|
|
209
209
|
}
|
|
210
210
|
}, Lt = () => {
|
|
211
211
|
try {
|
|
@@ -216,7 +216,7 @@ const It = () => {
|
|
|
216
216
|
browser: yt(s)
|
|
217
217
|
};
|
|
218
218
|
} catch (s) {
|
|
219
|
-
return
|
|
219
|
+
return l("debug", "Device info detection failed, using defaults", { error: s }), {
|
|
220
220
|
type: A.Desktop,
|
|
221
221
|
os: q,
|
|
222
222
|
browser: q
|
|
@@ -285,7 +285,7 @@ const It = () => {
|
|
|
285
285
|
default:
|
|
286
286
|
return ke;
|
|
287
287
|
}
|
|
288
|
-
}, Ot = 1e3, Pt = 50, Dt = "2.
|
|
288
|
+
}, Ot = 1e3, Pt = 50, Dt = "2.4.0", Vt = Dt, Ye = () => typeof window < "u" && typeof sessionStorage < "u", kt = () => {
|
|
289
289
|
try {
|
|
290
290
|
const s = new URLSearchParams(window.location.search);
|
|
291
291
|
s.delete(Ge);
|
|
@@ -299,10 +299,10 @@ const It = () => {
|
|
|
299
299
|
try {
|
|
300
300
|
const e = new URLSearchParams(window.location.search).get(Ge), t = sessionStorage.getItem(F);
|
|
301
301
|
let r = null;
|
|
302
|
-
return e === Le ? (r = !0, sessionStorage.setItem(F, "true"),
|
|
302
|
+
return e === Le ? (r = !0, sessionStorage.setItem(F, "true"), l("info", "QA Mode ACTIVE", {
|
|
303
303
|
visibility: "qa",
|
|
304
304
|
style: Xe
|
|
305
|
-
})) : e === Ae && (r = !1, sessionStorage.setItem(F, "false"),
|
|
305
|
+
})) : e === Ae && (r = !1, sessionStorage.setItem(F, "false"), l("info", "QA Mode DISABLED", {
|
|
306
306
|
visibility: "qa",
|
|
307
307
|
style: Qe
|
|
308
308
|
})), (e === Le || e === Ae) && kt(), r ?? t === "true";
|
|
@@ -312,12 +312,12 @@ const It = () => {
|
|
|
312
312
|
}, Ht = (s) => {
|
|
313
313
|
if (Ye())
|
|
314
314
|
try {
|
|
315
|
-
sessionStorage.setItem(F, s ? "true" : "false"),
|
|
315
|
+
sessionStorage.setItem(F, s ? "true" : "false"), l("info", s ? "QA Mode ACTIVE" : "QA Mode DISABLED", {
|
|
316
316
|
visibility: "qa",
|
|
317
317
|
style: s ? Xe : Qe
|
|
318
318
|
});
|
|
319
319
|
} catch {
|
|
320
|
-
|
|
320
|
+
l("debug", "Cannot set QA mode: sessionStorage unavailable");
|
|
321
321
|
}
|
|
322
322
|
}, xt = [
|
|
323
323
|
"co.uk",
|
|
@@ -345,7 +345,7 @@ const It = () => {
|
|
|
345
345
|
const e = new URL(s).hostname.toLowerCase(), t = window.location.hostname.toLowerCase();
|
|
346
346
|
return Ft(e, t) ? "Direct" : s;
|
|
347
347
|
} catch (e) {
|
|
348
|
-
return
|
|
348
|
+
return l("debug", "Failed to parse referrer URL, using raw value", { error: e, data: { referrer: s } }), s;
|
|
349
349
|
}
|
|
350
350
|
}, ne = () => {
|
|
351
351
|
const s = new URLSearchParams(window.location.search), e = {};
|
|
@@ -418,7 +418,7 @@ const Bt = () => {
|
|
|
418
418
|
return e;
|
|
419
419
|
}, he = (s, e = []) => {
|
|
420
420
|
if (!s || typeof s != "string")
|
|
421
|
-
return
|
|
421
|
+
return l("warn", "Invalid URL provided to normalizeUrl", { data: { type: typeof s } }), s || "";
|
|
422
422
|
try {
|
|
423
423
|
const t = new URL(s), r = t.searchParams, n = [.../* @__PURE__ */ new Set([...ut, ...e])];
|
|
424
424
|
let i = !1;
|
|
@@ -427,7 +427,7 @@ const Bt = () => {
|
|
|
427
427
|
r.has(c) && (r.delete(c), i = !0, o.push(c));
|
|
428
428
|
}), !i && s.includes("?") ? s : (t.search = r.toString(), t.toString());
|
|
429
429
|
} catch (t) {
|
|
430
|
-
return
|
|
430
|
+
return l("warn", "URL normalization failed, returning original", { error: t, data: { urlLength: s?.length } }), s;
|
|
431
431
|
}
|
|
432
432
|
}, xe = (s) => {
|
|
433
433
|
if (!s || typeof s != "string" || s.trim().length === 0)
|
|
@@ -439,7 +439,7 @@ const Bt = () => {
|
|
|
439
439
|
const i = e;
|
|
440
440
|
e = e.replace(n, ""), i !== e && t++;
|
|
441
441
|
}
|
|
442
|
-
return t > 0 &&
|
|
442
|
+
return t > 0 && l("warn", "XSS patterns detected and removed", {
|
|
443
443
|
data: {
|
|
444
444
|
patternMatches: t,
|
|
445
445
|
valueLength: s.length
|
|
@@ -461,10 +461,10 @@ const Bt = () => {
|
|
|
461
461
|
if (typeof s == "object") {
|
|
462
462
|
const t = {}, n = Object.entries(s).slice(0, 20);
|
|
463
463
|
for (const [i, o] of n) {
|
|
464
|
-
const
|
|
465
|
-
if (
|
|
464
|
+
const a = xe(i);
|
|
465
|
+
if (a) {
|
|
466
466
|
const c = fe(o, e + 1);
|
|
467
|
-
c !== null && (t[
|
|
467
|
+
c !== null && (t[a] = c);
|
|
468
468
|
}
|
|
469
469
|
}
|
|
470
470
|
return t;
|
|
@@ -584,20 +584,22 @@ const Bt = () => {
|
|
|
584
584
|
}, zt = (s) => {
|
|
585
585
|
if (s) {
|
|
586
586
|
if (s.tracelog && (!s.tracelog.projectId || typeof s.tracelog.projectId != "string" || s.tracelog.projectId.trim() === ""))
|
|
587
|
-
throw new
|
|
587
|
+
throw new P(m.INVALID_TRACELOG_PROJECT_ID, "config");
|
|
588
588
|
if (s.custom) {
|
|
589
589
|
if (!s.custom.collectApiUrl || typeof s.custom.collectApiUrl != "string" || s.custom.collectApiUrl.trim() === "")
|
|
590
|
-
throw new
|
|
590
|
+
throw new P(m.INVALID_CUSTOM_API_URL, "config");
|
|
591
591
|
if (s.custom.allowHttp !== void 0 && typeof s.custom.allowHttp != "boolean")
|
|
592
|
-
throw new
|
|
592
|
+
throw new P("allowHttp must be a boolean", "config");
|
|
593
593
|
const e = s.custom.collectApiUrl.trim();
|
|
594
594
|
if (!e.startsWith("http://") && !e.startsWith("https://"))
|
|
595
|
-
throw new
|
|
595
|
+
throw new P('Custom API URL must start with "http://" or "https://"', "config");
|
|
596
596
|
if (!(s.custom.allowHttp ?? !1) && e.startsWith("http://"))
|
|
597
|
-
throw new
|
|
597
|
+
throw new P(
|
|
598
598
|
"Custom API URL must use HTTPS in production. Set allowHttp: true in integration config to allow HTTP (not recommended)",
|
|
599
599
|
"config"
|
|
600
600
|
);
|
|
601
|
+
if (s.custom.fetchCredentials !== void 0 && !["include", "same-origin", "omit"].includes(s.custom.fetchCredentials))
|
|
602
|
+
throw new P('fetchCredentials must be "include", "same-origin", or "omit"', "config");
|
|
601
603
|
}
|
|
602
604
|
}
|
|
603
605
|
}, Kt = (s) => {
|
|
@@ -670,24 +672,24 @@ const Bt = () => {
|
|
|
670
672
|
valid: !1,
|
|
671
673
|
error: `${n}: object has too many keys (max 10 keys).`
|
|
672
674
|
};
|
|
673
|
-
for (const [
|
|
675
|
+
for (const [a, c] of Object.entries(r)) {
|
|
674
676
|
if (Array.isArray(c)) {
|
|
675
677
|
if (c.length > 10)
|
|
676
678
|
return {
|
|
677
679
|
valid: !1,
|
|
678
|
-
error: `${n}: array property "${
|
|
680
|
+
error: `${n}: array property "${a}" is too large (max 10 items).`
|
|
679
681
|
};
|
|
680
682
|
for (const u of c)
|
|
681
683
|
if (typeof u == "string" && u.length > 500)
|
|
682
684
|
return {
|
|
683
685
|
valid: !1,
|
|
684
|
-
error: `${n}: array property "${
|
|
686
|
+
error: `${n}: array property "${a}" contains strings that are too long (max 500 characters).`
|
|
685
687
|
};
|
|
686
688
|
}
|
|
687
689
|
if (typeof c == "string" && c.length > 1e3)
|
|
688
690
|
return {
|
|
689
691
|
valid: !1,
|
|
690
|
-
error: `${n}: property "${
|
|
692
|
+
error: `${n}: property "${a}" is too long (max 1000 characters).`
|
|
691
693
|
};
|
|
692
694
|
}
|
|
693
695
|
return {
|
|
@@ -704,13 +706,13 @@ const Bt = () => {
|
|
|
704
706
|
valid: !1,
|
|
705
707
|
error: `${n}: array item at index ${i} must be an object.`
|
|
706
708
|
};
|
|
707
|
-
const
|
|
708
|
-
if (!
|
|
709
|
+
const a = Fe(s, o, t);
|
|
710
|
+
if (!a.valid)
|
|
709
711
|
return {
|
|
710
712
|
valid: !1,
|
|
711
|
-
error: `${n}: array item at index ${i} is invalid: ${
|
|
713
|
+
error: `${n}: array item at index ${i} is invalid: ${a.error}`
|
|
712
714
|
};
|
|
713
|
-
|
|
715
|
+
a.sanitizedMetadata && r.push(a.sanitizedMetadata);
|
|
714
716
|
}
|
|
715
717
|
return {
|
|
716
718
|
valid: !0,
|
|
@@ -721,13 +723,13 @@ const Bt = () => {
|
|
|
721
723
|
}, Jt = (s, e) => {
|
|
722
724
|
const t = qt(s);
|
|
723
725
|
if (!t.valid)
|
|
724
|
-
return
|
|
726
|
+
return l("error", "Event name validation failed", {
|
|
725
727
|
data: { eventName: s, error: t.error }
|
|
726
728
|
}), t;
|
|
727
729
|
if (!e)
|
|
728
730
|
return { valid: !0 };
|
|
729
731
|
const r = Je(s, e, "customEvent");
|
|
730
|
-
return r.valid ||
|
|
732
|
+
return r.valid || l("error", "Event metadata validation failed", {
|
|
731
733
|
data: {
|
|
732
734
|
eventName: s,
|
|
733
735
|
error: r.error
|
|
@@ -854,9 +856,9 @@ class Zt {
|
|
|
854
856
|
function Ze(s, e, t) {
|
|
855
857
|
try {
|
|
856
858
|
const r = e(s);
|
|
857
|
-
return r === null ? null : typeof r == "object" && r !== null && "type" in r ? r : (
|
|
859
|
+
return r === null ? null : typeof r == "object" && r !== null && "type" in r ? r : (l("warn", `beforeSend transformer returned invalid data, using original [${t}]`), s);
|
|
858
860
|
} catch (r) {
|
|
859
|
-
return
|
|
861
|
+
return l("error", `beforeSend transformer threw error, using original event [${t}]`, {
|
|
860
862
|
error: r,
|
|
861
863
|
visibility: "critical"
|
|
862
864
|
}), s;
|
|
@@ -868,13 +870,13 @@ function er(s, e, t) {
|
|
|
868
870
|
function et(s, e, t) {
|
|
869
871
|
try {
|
|
870
872
|
const r = e(s);
|
|
871
|
-
return r === null ? (
|
|
873
|
+
return r === null ? (l("debug", `Batch filtered by beforeBatch transformer [${t}]`, {
|
|
872
874
|
data: { eventCount: s.events.length }
|
|
873
|
-
}), null) : typeof r == "object" && r !== null && Array.isArray(r.events) ? r : (
|
|
875
|
+
}), null) : typeof r == "object" && r !== null && Array.isArray(r.events) ? r : (l("warn", `beforeBatch transformer returned invalid data, using original [${t}]`, {
|
|
874
876
|
data: { eventCount: s.events.length }
|
|
875
877
|
}), s);
|
|
876
878
|
} catch (r) {
|
|
877
|
-
return
|
|
879
|
+
return l("error", `beforeBatch transformer threw error, using original batch [${t}]`, {
|
|
878
880
|
error: r,
|
|
879
881
|
data: { eventCount: s.events.length },
|
|
880
882
|
visibility: "critical"
|
|
@@ -950,6 +952,7 @@ class $e extends v {
|
|
|
950
952
|
lastPermanentErrorLog = null;
|
|
951
953
|
recoveryInProgress = !1;
|
|
952
954
|
lastMetadataTimestamp = 0;
|
|
955
|
+
fetchCredentials;
|
|
953
956
|
pendingControllers = /* @__PURE__ */ new Set();
|
|
954
957
|
/**
|
|
955
958
|
* Creates a SenderManager instance.
|
|
@@ -965,10 +968,10 @@ class $e extends v {
|
|
|
965
968
|
* @param customHeadersProvider - Optional callback for dynamic headers
|
|
966
969
|
* @throws Error if integrationId and apiUrl are not both provided or both undefined
|
|
967
970
|
*/
|
|
968
|
-
constructor(e, t, r, n = {}, i = {}, o) {
|
|
971
|
+
constructor(e, t, r, n = {}, i = {}, o, a = "include") {
|
|
969
972
|
if (super(), t && !r || !t && r)
|
|
970
973
|
throw new Error("SenderManager: integrationId and apiUrl must either both be provided or both be undefined");
|
|
971
|
-
this.storeManager = e, this.integrationId = t, this.apiUrl = r, this.transformers = n, this.staticHeaders = i, this.customHeadersProvider = o;
|
|
974
|
+
this.storeManager = e, this.integrationId = t, this.apiUrl = r, this.transformers = n, this.staticHeaders = i, this.customHeadersProvider = o, this.fetchCredentials = a;
|
|
972
975
|
}
|
|
973
976
|
/**
|
|
974
977
|
* Get the integration ID for this sender
|
|
@@ -1006,11 +1009,11 @@ class $e extends v {
|
|
|
1006
1009
|
if (this.customHeadersProvider)
|
|
1007
1010
|
try {
|
|
1008
1011
|
const t = this.customHeadersProvider();
|
|
1009
|
-
typeof t == "object" && t !== null && !Array.isArray(t) ? e = t :
|
|
1012
|
+
typeof t == "object" && t !== null && !Array.isArray(t) ? e = t : l("warn", "Custom headers provider returned invalid value, expected object", {
|
|
1010
1013
|
data: { received: typeof t }
|
|
1011
1014
|
});
|
|
1012
1015
|
} catch (t) {
|
|
1013
|
-
|
|
1016
|
+
l("warn", "Custom headers provider threw an error, using static headers only", { error: t });
|
|
1014
1017
|
}
|
|
1015
1018
|
return { ...this.staticHeaders, ...e };
|
|
1016
1019
|
}
|
|
@@ -1045,6 +1048,11 @@ class $e extends v {
|
|
|
1045
1048
|
* Content-Type header via Blob. For scenarios requiring custom headers, ensure async
|
|
1046
1049
|
* sends complete before page unload.
|
|
1047
1050
|
*
|
|
1051
|
+
* **Credentials Limitation**: The `fetchCredentials` config option is NOT applied to
|
|
1052
|
+
* sendBeacon requests. `sendBeacon()` always sends cookies (equivalent to `credentials: 'include'`)
|
|
1053
|
+
* regardless of the configured value. If `fetchCredentials` is set to `'omit'` or `'same-origin'`,
|
|
1054
|
+
* only async `fetch()` calls honor that setting.
|
|
1055
|
+
*
|
|
1048
1056
|
* @param body - Event queue to send
|
|
1049
1057
|
* @returns `true` if send succeeded or was skipped, `false` if failed
|
|
1050
1058
|
*
|
|
@@ -1052,13 +1060,13 @@ class $e extends v {
|
|
|
1052
1060
|
* @see src/managers/README.md (lines 82-139) for send details
|
|
1053
1061
|
*/
|
|
1054
1062
|
sendEventsQueueSync(e) {
|
|
1055
|
-
return this.shouldSkipSend() ? !0 : this.apiUrl?.includes(H.Fail) ? (
|
|
1063
|
+
return this.shouldSkipSend() ? !0 : this.apiUrl?.includes(H.Fail) ? (l(
|
|
1056
1064
|
"warn",
|
|
1057
1065
|
`Fail mode: simulating network failure (sync)${this.integrationId ? ` [${this.integrationId}]` : ""}`,
|
|
1058
1066
|
{
|
|
1059
1067
|
data: { events: e.events.length }
|
|
1060
1068
|
}
|
|
1061
|
-
), !1) : this.apiUrl?.includes(H.Localhost) ? (
|
|
1069
|
+
), !1) : this.apiUrl?.includes(H.Localhost) ? (l(
|
|
1062
1070
|
"debug",
|
|
1063
1071
|
`Success mode: simulating successful send (sync)${this.integrationId ? ` [${this.integrationId}]` : ""}`,
|
|
1064
1072
|
{
|
|
@@ -1100,7 +1108,7 @@ class $e extends v {
|
|
|
1100
1108
|
const r = await this.send(e);
|
|
1101
1109
|
return r ? (this.clearPersistedEvents(), t?.onSuccess?.(e.events.length, e.events, e)) : (this.persistEvents(e), t?.onFailure?.()), r;
|
|
1102
1110
|
} catch (r) {
|
|
1103
|
-
return r instanceof
|
|
1111
|
+
return r instanceof D ? (this.logPermanentError("Permanent error, not retrying", r), this.clearPersistedEvents(), t?.onFailure?.(), !1) : (this.persistEvents(e), t?.onFailure?.(), !1);
|
|
1104
1112
|
}
|
|
1105
1113
|
}
|
|
1106
1114
|
/**
|
|
@@ -1154,7 +1162,7 @@ class $e extends v {
|
|
|
1154
1162
|
*/
|
|
1155
1163
|
async recoverPersistedEvents(e) {
|
|
1156
1164
|
if (this.recoveryInProgress) {
|
|
1157
|
-
|
|
1165
|
+
l("debug", "Recovery already in progress, skipping duplicate attempt");
|
|
1158
1166
|
return;
|
|
1159
1167
|
}
|
|
1160
1168
|
this.recoveryInProgress = !0;
|
|
@@ -1167,11 +1175,11 @@ class $e extends v {
|
|
|
1167
1175
|
const r = this.createRecoveryBody(t);
|
|
1168
1176
|
await this.send(r) ? (this.clearPersistedEvents(), e?.onSuccess?.(t.events.length, t.events, r)) : e?.onFailure?.();
|
|
1169
1177
|
} catch (t) {
|
|
1170
|
-
if (t instanceof
|
|
1178
|
+
if (t instanceof D) {
|
|
1171
1179
|
this.logPermanentError("Permanent error during recovery, clearing persisted events", t), this.clearPersistedEvents(), e?.onFailure?.();
|
|
1172
1180
|
return;
|
|
1173
1181
|
}
|
|
1174
|
-
|
|
1182
|
+
l("error", "Failed to recover persisted events", { error: t });
|
|
1175
1183
|
} finally {
|
|
1176
1184
|
this.recoveryInProgress = !1;
|
|
1177
1185
|
}
|
|
@@ -1335,32 +1343,32 @@ class $e extends v {
|
|
|
1335
1343
|
if (!r)
|
|
1336
1344
|
return !0;
|
|
1337
1345
|
if (this.apiUrl?.includes(H.Fail))
|
|
1338
|
-
return
|
|
1346
|
+
return l("debug", `Fail mode: simulating network failure${this.integrationId ? ` [${this.integrationId}]` : ""}`, {
|
|
1339
1347
|
data: { events: r.events.length }
|
|
1340
1348
|
}), !1;
|
|
1341
1349
|
if (this.apiUrl?.includes(H.Localhost))
|
|
1342
|
-
return
|
|
1350
|
+
return l("debug", `Success mode: simulating successful send${this.integrationId ? ` [${this.integrationId}]` : ""}`, {
|
|
1343
1351
|
data: { events: r.events.length }
|
|
1344
1352
|
}), !0;
|
|
1345
1353
|
const { url: n, payload: i } = this.prepareRequest(r);
|
|
1346
1354
|
for (let o = 1; o <= 3; o++)
|
|
1347
1355
|
try {
|
|
1348
|
-
return (await this.sendWithTimeout(n, i)).ok ? (o > 1 &&
|
|
1356
|
+
return (await this.sendWithTimeout(n, i)).ok ? (o > 1 && l(
|
|
1349
1357
|
"info",
|
|
1350
1358
|
`Send succeeded after ${o - 1} retry attempt(s)${this.integrationId ? ` [${this.integrationId}]` : ""}`,
|
|
1351
1359
|
{
|
|
1352
1360
|
data: { events: r.events.length, attempt: o }
|
|
1353
1361
|
}
|
|
1354
1362
|
), !0) : !1;
|
|
1355
|
-
} catch (
|
|
1363
|
+
} catch (a) {
|
|
1356
1364
|
const c = o === 3;
|
|
1357
|
-
if (
|
|
1358
|
-
throw
|
|
1359
|
-
if (
|
|
1365
|
+
if (a instanceof D)
|
|
1366
|
+
throw a;
|
|
1367
|
+
if (l(
|
|
1360
1368
|
c ? "error" : "warn",
|
|
1361
1369
|
`Send attempt ${o} failed${this.integrationId ? ` [${this.integrationId}]` : ""}${c ? " (all retries exhausted)" : ", will retry"}`,
|
|
1362
1370
|
{
|
|
1363
|
-
error:
|
|
1371
|
+
error: a,
|
|
1364
1372
|
data: {
|
|
1365
1373
|
events: e.events.length,
|
|
1366
1374
|
url: n.replace(/\/\/[^/]+/, "//[DOMAIN]"),
|
|
@@ -1408,7 +1416,7 @@ class $e extends v {
|
|
|
1408
1416
|
method: "POST",
|
|
1409
1417
|
body: t,
|
|
1410
1418
|
keepalive: !0,
|
|
1411
|
-
credentials:
|
|
1419
|
+
credentials: this.fetchCredentials,
|
|
1412
1420
|
signal: r.signal,
|
|
1413
1421
|
headers: {
|
|
1414
1422
|
...i,
|
|
@@ -1416,7 +1424,7 @@ class $e extends v {
|
|
|
1416
1424
|
}
|
|
1417
1425
|
});
|
|
1418
1426
|
if (!o.ok)
|
|
1419
|
-
throw o.status >= 400 && o.status < 500 && o.status !== 408 && o.status !== 429 ? new
|
|
1427
|
+
throw o.status >= 400 && o.status < 500 && o.status !== 408 && o.status !== 429 ? new D(`HTTP ${o.status}: ${o.statusText}`, o.status) : new Error(`HTTP ${o.status}: ${o.statusText}`);
|
|
1420
1428
|
return o;
|
|
1421
1429
|
} finally {
|
|
1422
1430
|
clearTimeout(n), this.pendingControllers.delete(r);
|
|
@@ -1451,7 +1459,7 @@ class $e extends v {
|
|
|
1451
1459
|
return !0;
|
|
1452
1460
|
const { url: n, payload: i } = this.prepareRequest(r);
|
|
1453
1461
|
if (i.length > 65536)
|
|
1454
|
-
return
|
|
1462
|
+
return l(
|
|
1455
1463
|
"warn",
|
|
1456
1464
|
`Payload exceeds sendBeacon limit, persisting for recovery${this.integrationId ? ` [${this.integrationId}]` : ""}`,
|
|
1457
1465
|
{
|
|
@@ -1464,15 +1472,15 @@ class $e extends v {
|
|
|
1464
1472
|
), this.persistEvents(r), !1;
|
|
1465
1473
|
const o = new Blob([i], { type: "application/json" });
|
|
1466
1474
|
if (!this.isSendBeaconAvailable())
|
|
1467
|
-
return
|
|
1475
|
+
return l(
|
|
1468
1476
|
"warn",
|
|
1469
1477
|
`sendBeacon not available, persisting events for recovery${this.integrationId ? ` [${this.integrationId}]` : ""}`
|
|
1470
1478
|
), this.persistEvents(r), !1;
|
|
1471
|
-
const
|
|
1472
|
-
return
|
|
1479
|
+
const a = navigator.sendBeacon(n, o);
|
|
1480
|
+
return a || (l(
|
|
1473
1481
|
"warn",
|
|
1474
1482
|
`sendBeacon rejected request, persisting events for recovery${this.integrationId ? ` [${this.integrationId}]` : ""}`
|
|
1475
|
-
), this.persistEvents(r)),
|
|
1483
|
+
), this.persistEvents(r)), a;
|
|
1476
1484
|
}
|
|
1477
1485
|
/**
|
|
1478
1486
|
* Prepares request by enriching payload with metadata and serializing to JSON.
|
|
@@ -1526,7 +1534,7 @@ class $e extends v {
|
|
|
1526
1534
|
if (t)
|
|
1527
1535
|
return JSON.parse(t);
|
|
1528
1536
|
} catch (e) {
|
|
1529
|
-
|
|
1537
|
+
l("debug", `Failed to parse persisted data${this.integrationId ? ` [${this.integrationId}]` : ""}`, { error: e }), this.clearPersistedEvents();
|
|
1530
1538
|
}
|
|
1531
1539
|
return null;
|
|
1532
1540
|
}
|
|
@@ -1582,7 +1590,7 @@ class $e extends v {
|
|
|
1582
1590
|
if (t && t.timestamp) {
|
|
1583
1591
|
const i = Date.now() - t.timestamp;
|
|
1584
1592
|
if (i < 1e3)
|
|
1585
|
-
return
|
|
1593
|
+
return l(
|
|
1586
1594
|
"debug",
|
|
1587
1595
|
`Skipping persistence, another tab recently persisted events${this.integrationId ? ` [${this.integrationId}]` : ""}`,
|
|
1588
1596
|
{
|
|
@@ -1596,7 +1604,7 @@ class $e extends v {
|
|
|
1596
1604
|
}, n = this.getQueueStorageKey();
|
|
1597
1605
|
return this.storeManager.setItem(n, JSON.stringify(r)), !!this.storeManager.getItem(n);
|
|
1598
1606
|
} catch (t) {
|
|
1599
|
-
return
|
|
1607
|
+
return l("debug", `Failed to persist events${this.integrationId ? ` [${this.integrationId}]` : ""}`, { error: t }), !1;
|
|
1600
1608
|
}
|
|
1601
1609
|
}
|
|
1602
1610
|
clearPersistedEvents() {
|
|
@@ -1604,7 +1612,7 @@ class $e extends v {
|
|
|
1604
1612
|
const e = this.getQueueStorageKey();
|
|
1605
1613
|
this.storeManager.removeItem(e);
|
|
1606
1614
|
} catch (e) {
|
|
1607
|
-
|
|
1615
|
+
l("debug", `Failed to clear persisted events${this.integrationId ? ` [${this.integrationId}]` : ""}`, {
|
|
1608
1616
|
error: e
|
|
1609
1617
|
});
|
|
1610
1618
|
}
|
|
@@ -1621,7 +1629,7 @@ class $e extends v {
|
|
|
1621
1629
|
}
|
|
1622
1630
|
logPermanentError(e, t) {
|
|
1623
1631
|
const r = Date.now();
|
|
1624
|
-
(!this.lastPermanentErrorLog || this.lastPermanentErrorLog.statusCode !== t.statusCode || r - this.lastPermanentErrorLog.timestamp >= Rt) && (
|
|
1632
|
+
(!this.lastPermanentErrorLog || this.lastPermanentErrorLog.statusCode !== t.statusCode || r - this.lastPermanentErrorLog.timestamp >= Rt) && (l("error", `${e}${this.integrationId ? ` [${this.integrationId}]` : ""}`, {
|
|
1625
1633
|
data: { status: t.statusCode, message: t.message }
|
|
1626
1634
|
}), this.lastPermanentErrorLog = { statusCode: t.statusCode, timestamp: r });
|
|
1627
1635
|
}
|
|
@@ -1651,12 +1659,12 @@ class tr extends v {
|
|
|
1651
1659
|
this.hasPerformanceNow = !1, this.bootTime = 0, this.bootTimestamp = 0;
|
|
1652
1660
|
return;
|
|
1653
1661
|
}
|
|
1654
|
-
this.hasPerformanceNow = typeof performance < "u" && typeof performance.now == "function", this.hasPerformanceNow ? (this.bootTime = performance.now(), this.bootTimestamp = Date.now(),
|
|
1662
|
+
this.hasPerformanceNow = typeof performance < "u" && typeof performance.now == "function", this.hasPerformanceNow ? (this.bootTime = performance.now(), this.bootTimestamp = Date.now(), l("debug", "TimeManager initialized with monotonic clock", {
|
|
1655
1663
|
data: {
|
|
1656
1664
|
bootTime: this.bootTime.toFixed(3),
|
|
1657
1665
|
bootTimestamp: this.bootTimestamp
|
|
1658
1666
|
}
|
|
1659
|
-
})) : (this.bootTime = 0, this.bootTimestamp = Date.now(),
|
|
1667
|
+
})) : (this.bootTime = 0, this.bootTimestamp = Date.now(), l("debug", "performance.now() not available, falling back to Date.now()"));
|
|
1660
1668
|
}
|
|
1661
1669
|
/**
|
|
1662
1670
|
* Returns current timestamp in milliseconds since epoch.
|
|
@@ -1719,7 +1727,7 @@ class tr extends v {
|
|
|
1719
1727
|
return this.detectedSkew;
|
|
1720
1728
|
this.lastClockSkewCheck = e;
|
|
1721
1729
|
const t = this.now(), r = Date.now();
|
|
1722
|
-
return this.detectedSkew = r - t, Math.abs(this.detectedSkew) > 3e4 &&
|
|
1730
|
+
return this.detectedSkew = r - t, Math.abs(this.detectedSkew) > 3e4 && l("warn", "Significant clock skew detected", {
|
|
1723
1731
|
data: {
|
|
1724
1732
|
skewMs: this.detectedSkew,
|
|
1725
1733
|
skewMinutes: (this.detectedSkew / 1e3 / 60).toFixed(2),
|
|
@@ -1812,21 +1820,23 @@ class sr extends v {
|
|
|
1812
1820
|
* @param transformers - Optional event transformation hooks
|
|
1813
1821
|
* @param staticHeaders - Optional static HTTP headers for custom backend (from config)
|
|
1814
1822
|
* @param customHeadersProvider - Optional callback for dynamic headers
|
|
1823
|
+
* @param fetchCredentials - Fetch credentials mode for custom backend. @default 'include'
|
|
1815
1824
|
*/
|
|
1816
|
-
constructor(e, t = null, r = {}, n = {}, i) {
|
|
1825
|
+
constructor(e, t = null, r = {}, n = {}, i, o = "include") {
|
|
1817
1826
|
super(), this.emitter = t, this.transformers = r, this.timeManager = new tr(), this.dataSenders = [];
|
|
1818
|
-
const
|
|
1819
|
-
|
|
1827
|
+
const a = this.get("collectApiUrls");
|
|
1828
|
+
a?.saas && this.dataSenders.push(new $e(e, "saas", a.saas, r)), a?.custom && this.dataSenders.push(
|
|
1820
1829
|
new $e(
|
|
1821
1830
|
e,
|
|
1822
1831
|
"custom",
|
|
1823
|
-
|
|
1832
|
+
a.custom,
|
|
1824
1833
|
r,
|
|
1825
1834
|
n,
|
|
1826
|
-
i
|
|
1835
|
+
i,
|
|
1836
|
+
o
|
|
1827
1837
|
)
|
|
1828
|
-
), this.saveSessionCountsDebounced = this.debounce((
|
|
1829
|
-
this.saveSessionCounts(
|
|
1838
|
+
), this.saveSessionCountsDebounced = this.debounce((c) => {
|
|
1839
|
+
this.saveSessionCounts(c);
|
|
1830
1840
|
}, 500), this.cleanupExpiredSessionCounts();
|
|
1831
1841
|
}
|
|
1832
1842
|
/**
|
|
@@ -1858,12 +1868,12 @@ class sr extends v {
|
|
|
1858
1868
|
async (t) => t.recoverPersistedEvents({
|
|
1859
1869
|
onSuccess: (r, n, i) => {
|
|
1860
1870
|
if (n && n.length > 0) {
|
|
1861
|
-
const o = n.map((
|
|
1871
|
+
const o = n.map((a) => a.id);
|
|
1862
1872
|
this.removeProcessedEvents(o), i && this.emitEventsQueue(i);
|
|
1863
1873
|
}
|
|
1864
1874
|
},
|
|
1865
1875
|
onFailure: () => {
|
|
1866
|
-
|
|
1876
|
+
l("debug", "Failed to recover persisted events");
|
|
1867
1877
|
}
|
|
1868
1878
|
})
|
|
1869
1879
|
);
|
|
@@ -1935,24 +1945,24 @@ class sr extends v {
|
|
|
1935
1945
|
scroll_data: n,
|
|
1936
1946
|
click_data: i,
|
|
1937
1947
|
custom_event: o,
|
|
1938
|
-
web_vitals:
|
|
1948
|
+
web_vitals: a,
|
|
1939
1949
|
error_data: c,
|
|
1940
1950
|
viewport_data: u,
|
|
1941
1951
|
page_view: S
|
|
1942
1952
|
}) {
|
|
1943
1953
|
if (!e) {
|
|
1944
|
-
|
|
1954
|
+
l("error", "Event type is required - event will be ignored");
|
|
1945
1955
|
return;
|
|
1946
1956
|
}
|
|
1947
1957
|
if (!rr.has(e)) {
|
|
1948
|
-
|
|
1958
|
+
l("error", "Invalid event type - event will be ignored", {
|
|
1949
1959
|
data: { type: e }
|
|
1950
1960
|
});
|
|
1951
1961
|
return;
|
|
1952
1962
|
}
|
|
1953
1963
|
const g = this.get("sessionId");
|
|
1954
1964
|
if (!g) {
|
|
1955
|
-
this.pendingEventsBuffer.length >= 100 && (this.pendingEventsBuffer.shift(),
|
|
1965
|
+
this.pendingEventsBuffer.length >= 100 && (this.pendingEventsBuffer.shift(), l("debug", "Pending events buffer full - dropping oldest event", {
|
|
1956
1966
|
data: { maxBufferSize: 100 }
|
|
1957
1967
|
})), this.pendingEventsBuffer.push({
|
|
1958
1968
|
type: e,
|
|
@@ -1961,7 +1971,7 @@ class sr extends v {
|
|
|
1961
1971
|
scroll_data: n,
|
|
1962
1972
|
click_data: i,
|
|
1963
1973
|
custom_event: o,
|
|
1964
|
-
web_vitals:
|
|
1974
|
+
web_vitals: a,
|
|
1965
1975
|
error_data: c,
|
|
1966
1976
|
viewport_data: u,
|
|
1967
1977
|
page_view: S
|
|
@@ -1970,14 +1980,14 @@ class sr extends v {
|
|
|
1970
1980
|
}
|
|
1971
1981
|
this.lastSessionId !== g && (this.lastSessionId = g, this.sessionEventCounts = this.loadSessionCounts(g));
|
|
1972
1982
|
const p = e === d.SESSION_START;
|
|
1973
|
-
if (p &&
|
|
1983
|
+
if (p && l("debug", "Processing SESSION_START event", {
|
|
1974
1984
|
data: { sessionId: g }
|
|
1975
1985
|
}), !p && !this.checkRateLimit())
|
|
1976
1986
|
return;
|
|
1977
1987
|
const E = e;
|
|
1978
1988
|
if (!p) {
|
|
1979
1989
|
if (this.sessionEventCounts.total >= 1e3) {
|
|
1980
|
-
|
|
1990
|
+
l("warn", "Session event limit reached", {
|
|
1981
1991
|
data: {
|
|
1982
1992
|
type: E,
|
|
1983
1993
|
total: this.sessionEventCounts.total,
|
|
@@ -1990,7 +2000,7 @@ class sr extends v {
|
|
|
1990
2000
|
if (T) {
|
|
1991
2001
|
const re = this.sessionEventCounts[E];
|
|
1992
2002
|
if (re !== void 0 && re >= T) {
|
|
1993
|
-
|
|
2003
|
+
l("warn", "Session event type limit reached", {
|
|
1994
2004
|
data: {
|
|
1995
2005
|
type: E,
|
|
1996
2006
|
count: re,
|
|
@@ -2006,48 +2016,48 @@ class sr extends v {
|
|
|
2006
2016
|
if (!this.checkPerEventRateLimit(o.name, T))
|
|
2007
2017
|
return;
|
|
2008
2018
|
}
|
|
2009
|
-
const ye = E === d.SESSION_START, W = t || this.get("pageUrl"),
|
|
2019
|
+
const ye = E === d.SESSION_START, W = t || this.get("pageUrl"), U = this.buildEventPayload({
|
|
2010
2020
|
type: E,
|
|
2011
2021
|
page_url: W,
|
|
2012
2022
|
from_page_url: r,
|
|
2013
2023
|
scroll_data: n,
|
|
2014
2024
|
click_data: i,
|
|
2015
2025
|
custom_event: o,
|
|
2016
|
-
web_vitals:
|
|
2026
|
+
web_vitals: a,
|
|
2017
2027
|
error_data: c,
|
|
2018
2028
|
viewport_data: u,
|
|
2019
2029
|
page_view: S
|
|
2020
2030
|
});
|
|
2021
|
-
if (
|
|
2031
|
+
if (U && !(!p && !this.shouldSample())) {
|
|
2022
2032
|
if (ye) {
|
|
2023
2033
|
const T = this.get("sessionId");
|
|
2024
2034
|
if (!T) {
|
|
2025
|
-
|
|
2035
|
+
l("error", "Session start event requires sessionId - event will be ignored");
|
|
2026
2036
|
return;
|
|
2027
2037
|
}
|
|
2028
2038
|
if (this.get("hasStartSession")) {
|
|
2029
|
-
|
|
2039
|
+
l("debug", "Duplicate session_start detected", {
|
|
2030
2040
|
data: { sessionId: T }
|
|
2031
2041
|
});
|
|
2032
2042
|
return;
|
|
2033
2043
|
}
|
|
2034
2044
|
this.set("hasStartSession", !0);
|
|
2035
2045
|
}
|
|
2036
|
-
if (!this.isDuplicateEvent(
|
|
2046
|
+
if (!this.isDuplicateEvent(U)) {
|
|
2037
2047
|
if (this.get("mode") === Y.QA) {
|
|
2038
2048
|
if (E === d.CUSTOM && o) {
|
|
2039
|
-
|
|
2049
|
+
l("info", `Custom Event: ${o.name}`, {
|
|
2040
2050
|
visibility: "qa",
|
|
2041
2051
|
data: {
|
|
2042
2052
|
name: o.name,
|
|
2043
2053
|
...o.metadata && { metadata: o.metadata }
|
|
2044
2054
|
}
|
|
2045
|
-
}), this.emitEvent(
|
|
2055
|
+
}), this.emitEvent(U);
|
|
2046
2056
|
return;
|
|
2047
2057
|
}
|
|
2048
2058
|
if (E === d.VIEWPORT_VISIBLE && u) {
|
|
2049
2059
|
const T = u.name || u.id || u.selector;
|
|
2050
|
-
|
|
2060
|
+
l("info", `Viewport Visible: ${T}`, {
|
|
2051
2061
|
visibility: "qa",
|
|
2052
2062
|
data: {
|
|
2053
2063
|
selector: u.selector,
|
|
@@ -2056,11 +2066,11 @@ class sr extends v {
|
|
|
2056
2066
|
visibilityRatio: u.visibilityRatio,
|
|
2057
2067
|
dwellTime: u.dwellTime
|
|
2058
2068
|
}
|
|
2059
|
-
}), this.emitEvent(
|
|
2069
|
+
}), this.emitEvent(U);
|
|
2060
2070
|
return;
|
|
2061
2071
|
}
|
|
2062
2072
|
}
|
|
2063
|
-
if (this.addToQueue(
|
|
2073
|
+
if (this.addToQueue(U), !p) {
|
|
2064
2074
|
this.sessionEventCounts.total++, this.sessionEventCounts[E] !== void 0 && this.sessionEventCounts[E]++;
|
|
2065
2075
|
const T = this.get("sessionId");
|
|
2066
2076
|
T && this.saveSessionCountsDebounced && this.saveSessionCountsDebounced(T);
|
|
@@ -2306,7 +2316,7 @@ class sr extends v {
|
|
|
2306
2316
|
if (this.pendingEventsBuffer.length === 0)
|
|
2307
2317
|
return;
|
|
2308
2318
|
if (!this.get("sessionId")) {
|
|
2309
|
-
|
|
2319
|
+
l("debug", "Cannot flush pending events: session not initialized - keeping in buffer", {
|
|
2310
2320
|
data: { bufferedEventCount: this.pendingEventsBuffer.length }
|
|
2311
2321
|
});
|
|
2312
2322
|
return;
|
|
@@ -2329,8 +2339,8 @@ class sr extends v {
|
|
|
2329
2339
|
if (this.dataSenders.length === 0)
|
|
2330
2340
|
return this.removeProcessedEvents(n), this.clearSendTimeout(), this.emitEventsQueue(t), e ? !0 : Promise.resolve(!0);
|
|
2331
2341
|
if (e) {
|
|
2332
|
-
const o = this.dataSenders.map((
|
|
2333
|
-
return o ? (this.removeProcessedEvents(n), this.clearSendTimeout(), this.emitEventsQueue(t)) : (this.clearSendTimeout(),
|
|
2342
|
+
const o = this.dataSenders.map((a) => a.sendEventsQueueSync(t)).some((a) => a);
|
|
2343
|
+
return o ? (this.removeProcessedEvents(n), this.clearSendTimeout(), this.emitEventsQueue(t)) : (this.clearSendTimeout(), l("debug", "Sync flush complete failure, events kept in queue for retry", {
|
|
2334
2344
|
data: { eventCount: n.length }
|
|
2335
2345
|
})), o;
|
|
2336
2346
|
} else {
|
|
@@ -2343,10 +2353,10 @@ class sr extends v {
|
|
|
2343
2353
|
})
|
|
2344
2354
|
);
|
|
2345
2355
|
return Promise.allSettled(i).then((o) => {
|
|
2346
|
-
const
|
|
2347
|
-
return
|
|
2356
|
+
const a = o.some((c) => this.isSuccessfulResult(c));
|
|
2357
|
+
return a ? (this.removeProcessedEvents(n), this.clearSendTimeout(), this.emitEventsQueue(t)) : l("debug", "Async flush complete failure, events kept in queue for retry", {
|
|
2348
2358
|
data: { eventCount: r.length }
|
|
2349
|
-
}),
|
|
2359
|
+
}), a;
|
|
2350
2360
|
});
|
|
2351
2361
|
}
|
|
2352
2362
|
}
|
|
@@ -2359,22 +2369,22 @@ class sr extends v {
|
|
|
2359
2369
|
this.emitEventsQueue(e);
|
|
2360
2370
|
return;
|
|
2361
2371
|
}
|
|
2362
|
-
const t = [...this.eventsQueue], r = t.map((
|
|
2363
|
-
async (
|
|
2372
|
+
const t = [...this.eventsQueue], r = t.map((a) => a.id), n = this.dataSenders.map(
|
|
2373
|
+
async (a) => a.sendEventsQueue(e, {
|
|
2364
2374
|
onSuccess: () => {
|
|
2365
2375
|
},
|
|
2366
2376
|
onFailure: () => {
|
|
2367
2377
|
}
|
|
2368
2378
|
})
|
|
2369
2379
|
), i = await Promise.allSettled(n);
|
|
2370
|
-
if (i.some((
|
|
2380
|
+
if (i.some((a) => this.isSuccessfulResult(a))) {
|
|
2371
2381
|
this.consecutiveSendFailures = 0, this.removeProcessedEvents(r), this.emitEventsQueue(e);
|
|
2372
|
-
const
|
|
2373
|
-
|
|
2374
|
-
data: { eventCount: t.length, failedCount:
|
|
2382
|
+
const a = i.filter((c) => !this.isSuccessfulResult(c)).length;
|
|
2383
|
+
a > 0 && l("debug", "Periodic send completed with some failures, removed from queue and persisted per-integration", {
|
|
2384
|
+
data: { eventCount: t.length, failedCount: a }
|
|
2375
2385
|
});
|
|
2376
2386
|
} else
|
|
2377
|
-
this.consecutiveSendFailures++,
|
|
2387
|
+
this.consecutiveSendFailures++, l("debug", "Periodic send complete failure, events kept in queue for retry", {
|
|
2378
2388
|
data: { eventCount: t.length }
|
|
2379
2389
|
});
|
|
2380
2390
|
this.eventsQueue.length === 0 ? this.clearSendTimeout() : this.scheduleSendTimeout();
|
|
@@ -2397,20 +2407,20 @@ class sr extends v {
|
|
|
2397
2407
|
events: r,
|
|
2398
2408
|
...this.get("config")?.globalMetadata && { global_metadata: this.get("config")?.globalMetadata }
|
|
2399
2409
|
};
|
|
2400
|
-
const i = this.get("collectApiUrls"), o = !!(i?.custom || i?.saas),
|
|
2401
|
-
if (!o &&
|
|
2402
|
-
const c = et(n,
|
|
2410
|
+
const i = this.get("collectApiUrls"), o = !!(i?.custom || i?.saas), a = this.transformers.beforeBatch;
|
|
2411
|
+
if (!o && a) {
|
|
2412
|
+
const c = et(n, a, "EventManager");
|
|
2403
2413
|
c !== null && (n = c);
|
|
2404
2414
|
}
|
|
2405
2415
|
return n;
|
|
2406
2416
|
}
|
|
2407
2417
|
buildEventPayload(e) {
|
|
2408
2418
|
const t = e.page_url ?? this.get("pageUrl"), r = this.timeManager.now(), n = this.timeManager.validateTimestamp(r);
|
|
2409
|
-
n.valid ||
|
|
2419
|
+
n.valid || l("warn", "Event timestamp validation failed", {
|
|
2410
2420
|
data: { type: e.type, error: n.error }
|
|
2411
2421
|
});
|
|
2412
2422
|
const i = this.get("sessionReferrer"), o = this.get("sessionUtm");
|
|
2413
|
-
let
|
|
2423
|
+
let a = {
|
|
2414
2424
|
id: Bt(),
|
|
2415
2425
|
type: e.type,
|
|
2416
2426
|
page_url: t,
|
|
@@ -2428,16 +2438,16 @@ class sr extends v {
|
|
|
2428
2438
|
};
|
|
2429
2439
|
const c = this.get("collectApiUrls"), u = !!c?.custom, S = !!c?.saas, g = u || S, p = u && S, E = this.transformers.beforeSend;
|
|
2430
2440
|
if (E && (!g || u && !p)) {
|
|
2431
|
-
const W = Ze(
|
|
2441
|
+
const W = Ze(a, E, "EventManager");
|
|
2432
2442
|
if (W === null)
|
|
2433
2443
|
return null;
|
|
2434
|
-
|
|
2444
|
+
a = W;
|
|
2435
2445
|
}
|
|
2436
|
-
return
|
|
2446
|
+
return a;
|
|
2437
2447
|
}
|
|
2438
2448
|
isDuplicateEvent(e) {
|
|
2439
2449
|
const t = Date.now(), r = this.createEventFingerprint(e), n = this.recentEventFingerprints.get(r);
|
|
2440
|
-
return n && t - n < 1e3 ? (this.recentEventFingerprints.set(r, t), !0) : (this.recentEventFingerprints.set(r, t), this.recentEventFingerprints.size > 1500 && this.pruneOldFingerprints(), this.recentEventFingerprints.size > 3e3 && (this.recentEventFingerprints.clear(), this.recentEventFingerprints.set(r, t),
|
|
2450
|
+
return n && t - n < 1e3 ? (this.recentEventFingerprints.set(r, t), !0) : (this.recentEventFingerprints.set(r, t), this.recentEventFingerprints.size > 1500 && this.pruneOldFingerprints(), this.recentEventFingerprints.size > 3e3 && (this.recentEventFingerprints.clear(), this.recentEventFingerprints.set(r, t), l("debug", "Event fingerprint cache exceeded hard limit, cleared", {
|
|
2441
2451
|
data: { hardLimit: 3e3 }
|
|
2442
2452
|
})), !1);
|
|
2443
2453
|
}
|
|
@@ -2445,7 +2455,7 @@ class sr extends v {
|
|
|
2445
2455
|
const e = Date.now(), t = 1e3 * 10;
|
|
2446
2456
|
for (const [r, n] of this.recentEventFingerprints.entries())
|
|
2447
2457
|
e - n > t && this.recentEventFingerprints.delete(r);
|
|
2448
|
-
|
|
2458
|
+
l("debug", "Pruned old event fingerprints", {
|
|
2449
2459
|
data: {
|
|
2450
2460
|
remaining: this.recentEventFingerprints.size,
|
|
2451
2461
|
cutoffMs: t
|
|
@@ -2466,7 +2476,7 @@ class sr extends v {
|
|
|
2466
2476
|
addToQueue(e) {
|
|
2467
2477
|
if (this.emitEvent(e), this.eventsQueue.push(e), this.eventsQueue.length > 100) {
|
|
2468
2478
|
const t = this.eventsQueue.findIndex((n) => n.type !== d.SESSION_START), r = t >= 0 ? this.eventsQueue.splice(t, 1)[0] : this.eventsQueue.shift();
|
|
2469
|
-
|
|
2479
|
+
l("warn", "Event queue overflow, oldest non-critical event removed", {
|
|
2470
2480
|
data: {
|
|
2471
2481
|
maxLength: 100,
|
|
2472
2482
|
currentLength: this.eventsQueue.length,
|
|
@@ -2500,7 +2510,7 @@ class sr extends v {
|
|
|
2500
2510
|
}
|
|
2501
2511
|
checkPerEventRateLimit(e, t) {
|
|
2502
2512
|
const r = Date.now(), i = (this.perEventRateLimits.get(e) ?? []).filter((o) => r - o < 6e4);
|
|
2503
|
-
return i.length >= t ? (
|
|
2513
|
+
return i.length >= t ? (l("warn", "Per-event rate limit exceeded for custom event", {
|
|
2504
2514
|
data: {
|
|
2505
2515
|
eventName: e,
|
|
2506
2516
|
limit: t,
|
|
@@ -2607,7 +2617,7 @@ class sr extends v {
|
|
|
2607
2617
|
if (!n)
|
|
2608
2618
|
return this.getInitialCounts();
|
|
2609
2619
|
const i = JSON.parse(n);
|
|
2610
|
-
return i._timestamp && Date.now() - i._timestamp > Ce ? (
|
|
2620
|
+
return i._timestamp && Date.now() - i._timestamp > Ce ? (l("debug", "Session counts expired, clearing", {
|
|
2611
2621
|
data: { sessionId: e, age: Date.now() - i._timestamp }
|
|
2612
2622
|
}), localStorage.removeItem(r), this.getInitialCounts()) : typeof i.total == "number" && typeof i[d.CLICK] == "number" && typeof i[d.PAGE_VIEW] == "number" && typeof i[d.CUSTOM] == "number" && typeof i[d.VIEWPORT_VISIBLE] == "number" && typeof i[d.SCROLL] == "number" ? {
|
|
2613
2623
|
total: i.total,
|
|
@@ -2616,13 +2626,13 @@ class sr extends v {
|
|
|
2616
2626
|
[d.CUSTOM]: i[d.CUSTOM],
|
|
2617
2627
|
[d.VIEWPORT_VISIBLE]: i[d.VIEWPORT_VISIBLE],
|
|
2618
2628
|
[d.SCROLL]: i[d.SCROLL]
|
|
2619
|
-
} : (
|
|
2629
|
+
} : (l("warn", "Invalid session counts structure in localStorage, resetting", {
|
|
2620
2630
|
data: { sessionId: e, parsed: i }
|
|
2621
|
-
}), localStorage.removeItem(r),
|
|
2631
|
+
}), localStorage.removeItem(r), l("debug", "Session counts removed due to invalid/corrupted data", {
|
|
2622
2632
|
data: { sessionId: e, parsed: i }
|
|
2623
2633
|
}), this.getInitialCounts());
|
|
2624
2634
|
} catch (n) {
|
|
2625
|
-
return
|
|
2635
|
+
return l("warn", "Failed to load session counts from localStorage", {
|
|
2626
2636
|
error: n,
|
|
2627
2637
|
data: { sessionId: e }
|
|
2628
2638
|
}), this.getInitialCounts();
|
|
@@ -2656,7 +2666,7 @@ class sr extends v {
|
|
|
2656
2666
|
if (e) {
|
|
2657
2667
|
const i = Date.now() - parseInt(e, 10);
|
|
2658
2668
|
if (i < Ne) {
|
|
2659
|
-
|
|
2669
|
+
l("debug", "Skipping session counts cleanup (throttled)", {
|
|
2660
2670
|
data: { timeSinceLastCleanup: i, throttleMs: Ne }
|
|
2661
2671
|
});
|
|
2662
2672
|
return;
|
|
@@ -2667,19 +2677,19 @@ class sr extends v {
|
|
|
2667
2677
|
const o = localStorage.key(i);
|
|
2668
2678
|
if (o?.startsWith(r))
|
|
2669
2679
|
try {
|
|
2670
|
-
const
|
|
2671
|
-
if (
|
|
2672
|
-
const c = JSON.parse(
|
|
2680
|
+
const a = localStorage.getItem(o);
|
|
2681
|
+
if (a) {
|
|
2682
|
+
const c = JSON.parse(a);
|
|
2673
2683
|
c._timestamp && Date.now() - c._timestamp > Ce && n.push(o);
|
|
2674
2684
|
}
|
|
2675
2685
|
} catch {
|
|
2676
2686
|
}
|
|
2677
2687
|
}
|
|
2678
2688
|
n.forEach((i) => {
|
|
2679
|
-
localStorage.removeItem(i),
|
|
2680
|
-
}), n.length > 0 &&
|
|
2689
|
+
localStorage.removeItem(i), l("debug", "Cleaned up expired session counts", { data: { key: i } });
|
|
2690
|
+
}), n.length > 0 && l("info", `Cleaned up ${n.length} expired session counts entries`), localStorage.setItem(Re, Date.now().toString());
|
|
2681
2691
|
} catch (e) {
|
|
2682
|
-
|
|
2692
|
+
l("warn", "Failed to cleanup expired session counts", { error: e });
|
|
2683
2693
|
}
|
|
2684
2694
|
}
|
|
2685
2695
|
/**
|
|
@@ -2720,7 +2730,7 @@ class sr extends v {
|
|
|
2720
2730
|
};
|
|
2721
2731
|
localStorage.setItem(r, JSON.stringify(n));
|
|
2722
2732
|
} catch (n) {
|
|
2723
|
-
|
|
2733
|
+
l("warn", "Failed to persist session counts to localStorage", {
|
|
2724
2734
|
error: n,
|
|
2725
2735
|
data: { sessionId: e }
|
|
2726
2736
|
});
|
|
@@ -2775,13 +2785,13 @@ class or extends v {
|
|
|
2775
2785
|
}
|
|
2776
2786
|
initCrossTabSync() {
|
|
2777
2787
|
if (typeof BroadcastChannel > "u") {
|
|
2778
|
-
|
|
2788
|
+
l("debug", "BroadcastChannel not supported");
|
|
2779
2789
|
return;
|
|
2780
2790
|
}
|
|
2781
2791
|
const e = this.getProjectId();
|
|
2782
2792
|
this.broadcastChannel = new BroadcastChannel(mt(e)), this.broadcastChannel.onmessage = (t) => {
|
|
2783
2793
|
const { action: r, sessionId: n, timestamp: i, projectId: o } = t.data ?? {};
|
|
2784
|
-
o === e && (r === "session_start" && n && typeof i == "number" && i > Date.now() - 5e3 ? (this.set("sessionId", n), this.persistSession(n, i), this.isTracking && this.setupSessionTimeout()) : r && r !== "session_start" &&
|
|
2794
|
+
o === e && (r === "session_start" && n && typeof i == "number" && i > Date.now() - 5e3 ? (this.set("sessionId", n), this.persistSession(n, i), this.isTracking && this.setupSessionTimeout()) : r && r !== "session_start" && l("debug", "Ignored BroadcastChannel message with unknown action", { data: { action: r } }));
|
|
2785
2795
|
};
|
|
2786
2796
|
}
|
|
2787
2797
|
shareSession(e) {
|
|
@@ -2800,7 +2810,7 @@ class or extends v {
|
|
|
2800
2810
|
if (!e)
|
|
2801
2811
|
return null;
|
|
2802
2812
|
if (!ir.test(e.id))
|
|
2803
|
-
return
|
|
2813
|
+
return l("warn", "Invalid session ID format recovered from storage, clearing", {
|
|
2804
2814
|
data: { sessionId: e.id }
|
|
2805
2815
|
}), this.clearStoredSession(), null;
|
|
2806
2816
|
const t = this.get("config")?.sessionTimeout ?? 9e5;
|
|
@@ -2892,7 +2902,7 @@ class or extends v {
|
|
|
2892
2902
|
*/
|
|
2893
2903
|
startTracking() {
|
|
2894
2904
|
if (this.isTracking) {
|
|
2895
|
-
|
|
2905
|
+
l("debug", "Session tracking already active");
|
|
2896
2906
|
return;
|
|
2897
2907
|
}
|
|
2898
2908
|
const e = this.recoverSession(), t = e ?? this.generateSessionId();
|
|
@@ -2902,7 +2912,7 @@ class or extends v {
|
|
|
2902
2912
|
r = i?.referrer ?? se(), n = i?.utm ?? ne();
|
|
2903
2913
|
} else
|
|
2904
2914
|
r = se(), n = ne();
|
|
2905
|
-
|
|
2915
|
+
l("debug", "Session tracking initialized", {
|
|
2906
2916
|
data: {
|
|
2907
2917
|
sessionId: t,
|
|
2908
2918
|
wasRecovered: !!e,
|
|
@@ -2912,9 +2922,9 @@ class or extends v {
|
|
|
2912
2922
|
}
|
|
2913
2923
|
}), this.isTracking = !0;
|
|
2914
2924
|
try {
|
|
2915
|
-
this.set("sessionId", t), this.set("sessionReferrer", r), this.set("sessionUtm", n), this.persistSession(t, Date.now(), r, n), this.initCrossTabSync(), this.shareSession(t), e ?
|
|
2925
|
+
this.set("sessionId", t), this.set("sessionReferrer", r), this.set("sessionUtm", n), this.persistSession(t, Date.now(), r, n), this.initCrossTabSync(), this.shareSession(t), e ? l("debug", "Session recovered, skipping SESSION_START", {
|
|
2916
2926
|
data: { sessionId: t }
|
|
2917
|
-
}) : (
|
|
2927
|
+
}) : (l("debug", "Emitting SESSION_START event", {
|
|
2918
2928
|
data: { sessionId: t }
|
|
2919
2929
|
}), this.eventManager.track({
|
|
2920
2930
|
type: d.SESSION_START
|
|
@@ -2953,7 +2963,7 @@ class or extends v {
|
|
|
2953
2963
|
renewSession() {
|
|
2954
2964
|
this.needsRenewal = !1;
|
|
2955
2965
|
const e = this.generateSessionId(), t = se(), r = ne();
|
|
2956
|
-
|
|
2966
|
+
l("debug", "Renewing session after timeout", {
|
|
2957
2967
|
data: { newSessionId: e }
|
|
2958
2968
|
}), this.set("sessionId", e), this.set("sessionReferrer", t), this.set("sessionUtm", r), this.persistSession(e, Date.now(), t, r), this.cleanupCrossTabSync(), this.initCrossTabSync(), this.shareSession(e), this.eventManager.track({
|
|
2959
2969
|
type: d.SESSION_START
|
|
@@ -2968,7 +2978,7 @@ class or extends v {
|
|
|
2968
2978
|
this.clearSessionTimeout();
|
|
2969
2979
|
else {
|
|
2970
2980
|
if (this.isSessionStale()) {
|
|
2971
|
-
|
|
2981
|
+
l("debug", "Session expired during suspend, entering renewal mode"), this.enterRenewalMode();
|
|
2972
2982
|
return;
|
|
2973
2983
|
}
|
|
2974
2984
|
this.get("sessionId") && this.setupSessionTimeout();
|
|
@@ -2997,7 +3007,7 @@ class or extends v {
|
|
|
2997
3007
|
* Called by session timeout timer.
|
|
2998
3008
|
*/
|
|
2999
3009
|
enterRenewalMode() {
|
|
3000
|
-
this.clearSessionTimeout(), this.cleanupCrossTabSync(), this.clearStoredSession(), this.set("sessionId", null), this.set("hasStartSession", !1), this.set("sessionReferrer", void 0), this.set("sessionUtm", void 0), this.needsRenewal = !0,
|
|
3010
|
+
this.clearSessionTimeout(), this.cleanupCrossTabSync(), this.clearStoredSession(), this.set("sessionId", null), this.set("hasStartSession", !1), this.set("sessionReferrer", void 0), this.set("sessionUtm", void 0), this.needsRenewal = !0, l("debug", "Session timed out, entering renewal mode");
|
|
3001
3011
|
}
|
|
3002
3012
|
/**
|
|
3003
3013
|
* Fully resets session state and cleans up all resources.
|
|
@@ -3103,7 +3113,7 @@ class ar extends v {
|
|
|
3103
3113
|
if (this.isActive())
|
|
3104
3114
|
return;
|
|
3105
3115
|
if (this.destroyed) {
|
|
3106
|
-
|
|
3116
|
+
l("debug", "Cannot start tracking on destroyed handler");
|
|
3107
3117
|
return;
|
|
3108
3118
|
}
|
|
3109
3119
|
const t = this.get("config")?.integrations?.tracelog?.projectId ?? "custom";
|
|
@@ -3117,7 +3127,7 @@ class ar extends v {
|
|
|
3117
3127
|
}
|
|
3118
3128
|
this.sessionManager = null;
|
|
3119
3129
|
}
|
|
3120
|
-
throw
|
|
3130
|
+
throw l("error", "Failed to start session tracking", { error: r }), r;
|
|
3121
3131
|
}
|
|
3122
3132
|
}
|
|
3123
3133
|
isActive() {
|
|
@@ -3262,7 +3272,7 @@ class cr extends v {
|
|
|
3262
3272
|
this.clickHandler || (this.clickHandler = (e) => {
|
|
3263
3273
|
const t = e, r = t.target, n = typeof HTMLElement < "u" && r instanceof HTMLElement ? r : typeof HTMLElement < "u" && r instanceof Node && r.parentElement instanceof HTMLElement ? r.parentElement : null;
|
|
3264
3274
|
if (!n) {
|
|
3265
|
-
|
|
3275
|
+
l("debug", "Click target not found or not an element");
|
|
3266
3276
|
return;
|
|
3267
3277
|
}
|
|
3268
3278
|
if (this.shouldIgnoreElement(n))
|
|
@@ -3270,7 +3280,7 @@ class cr extends v {
|
|
|
3270
3280
|
const i = this.get("config")?.clickThrottleMs ?? 300;
|
|
3271
3281
|
if (i > 0 && !this.checkClickThrottle(n, i))
|
|
3272
3282
|
return;
|
|
3273
|
-
const o = this.findTrackingElement(n),
|
|
3283
|
+
const o = this.findTrackingElement(n), a = this.getRelevantClickElement(n), c = this.calculateClickCoordinates(t, n);
|
|
3274
3284
|
if (o) {
|
|
3275
3285
|
const S = this.extractTrackingData(o);
|
|
3276
3286
|
if (S) {
|
|
@@ -3284,7 +3294,7 @@ class cr extends v {
|
|
|
3284
3294
|
});
|
|
3285
3295
|
}
|
|
3286
3296
|
}
|
|
3287
|
-
const u = this.generateClickData(n,
|
|
3297
|
+
const u = this.generateClickData(n, a, c);
|
|
3288
3298
|
this.eventManager.track({
|
|
3289
3299
|
type: d.CLICK,
|
|
3290
3300
|
click_data: u
|
|
@@ -3311,7 +3321,7 @@ class cr extends v {
|
|
|
3311
3321
|
const r = this.getElementSignature(e), n = Date.now();
|
|
3312
3322
|
this.pruneThrottleCache(n);
|
|
3313
3323
|
const i = this.lastClickTimes.get(r);
|
|
3314
|
-
return i !== void 0 && n - i < t ? (
|
|
3324
|
+
return i !== void 0 && n - i < t ? (l("debug", "ClickHandler: Click suppressed by throttle", {
|
|
3315
3325
|
data: {
|
|
3316
3326
|
signature: r,
|
|
3317
3327
|
throttleRemaining: t - (n - i)
|
|
@@ -3331,10 +3341,10 @@ class cr extends v {
|
|
|
3331
3341
|
for (const [r, n] of this.lastClickTimes.entries())
|
|
3332
3342
|
n < t && this.lastClickTimes.delete(r);
|
|
3333
3343
|
if (this.lastClickTimes.size > 1e3) {
|
|
3334
|
-
const r = Array.from(this.lastClickTimes.entries()).sort((o,
|
|
3344
|
+
const r = Array.from(this.lastClickTimes.entries()).sort((o, a) => o[1] - a[1]), n = this.lastClickTimes.size - 1e3, i = r.slice(0, n);
|
|
3335
3345
|
for (const [o] of i)
|
|
3336
3346
|
this.lastClickTimes.delete(o);
|
|
3337
|
-
|
|
3347
|
+
l("debug", "ClickHandler: Pruned throttle cache", {
|
|
3338
3348
|
data: {
|
|
3339
3349
|
removed: i.length,
|
|
3340
3350
|
remaining: this.lastClickTimes.size
|
|
@@ -3383,7 +3393,7 @@ class cr extends v {
|
|
|
3383
3393
|
if (r)
|
|
3384
3394
|
return r;
|
|
3385
3395
|
} catch (r) {
|
|
3386
|
-
|
|
3396
|
+
l("debug", "Invalid selector in element search", { error: r, data: { selector: t } });
|
|
3387
3397
|
continue;
|
|
3388
3398
|
}
|
|
3389
3399
|
return e;
|
|
@@ -3403,8 +3413,8 @@ class cr extends v {
|
|
|
3403
3413
|
return Math.max(0, Math.min(1, Number(e.toFixed(3))));
|
|
3404
3414
|
}
|
|
3405
3415
|
calculateClickCoordinates(e, t) {
|
|
3406
|
-
const r = t.getBoundingClientRect(), n = e.clientX, i = e.clientY, o = r.width > 0 ? this.clamp((n - r.left) / r.width) : 0,
|
|
3407
|
-
return { x: n, y: i, relativeX: o, relativeY:
|
|
3416
|
+
const r = t.getBoundingClientRect(), n = e.clientX, i = e.clientY, o = r.width > 0 ? this.clamp((n - r.left) / r.width) : 0, a = r.height > 0 ? this.clamp((i - r.top) / r.height) : 0;
|
|
3417
|
+
return { x: n, y: i, relativeX: o, relativeY: a };
|
|
3408
3418
|
}
|
|
3409
3419
|
extractTrackingData(e) {
|
|
3410
3420
|
const t = e.getAttribute(`${w}-name`), r = e.getAttribute(`${w}-value`);
|
|
@@ -3416,12 +3426,12 @@ class cr extends v {
|
|
|
3416
3426
|
};
|
|
3417
3427
|
}
|
|
3418
3428
|
generateClickData(e, t, r) {
|
|
3419
|
-
const { x: n, y: i, relativeX: o, relativeY:
|
|
3429
|
+
const { x: n, y: i, relativeX: o, relativeY: a } = r, c = this.getRelevantText(e, t), u = this.extractElementAttributes(t);
|
|
3420
3430
|
return {
|
|
3421
3431
|
x: n,
|
|
3422
3432
|
y: i,
|
|
3423
3433
|
relativeX: o,
|
|
3424
|
-
relativeY:
|
|
3434
|
+
relativeY: a,
|
|
3425
3435
|
tag: t.tagName.toLowerCase(),
|
|
3426
3436
|
...t.id && { id: t.id },
|
|
3427
3437
|
...t.className && { class: t.className },
|
|
@@ -3601,7 +3611,7 @@ class ur extends v {
|
|
|
3601
3611
|
n,
|
|
3602
3612
|
this.getScrollHeight(e),
|
|
3603
3613
|
this.getViewportHeight(e)
|
|
3604
|
-
), o = this.determineIfPrimary(e),
|
|
3614
|
+
), o = this.determineIfPrimary(e), a = {
|
|
3605
3615
|
element: e,
|
|
3606
3616
|
selector: t,
|
|
3607
3617
|
isPrimary: o,
|
|
@@ -3614,16 +3624,16 @@ class ur extends v {
|
|
|
3614
3624
|
debounceTimer: null,
|
|
3615
3625
|
listener: null
|
|
3616
3626
|
}, c = () => {
|
|
3617
|
-
this.get("suppressNextScroll") || (
|
|
3618
|
-
const u = this.calculateScrollData(
|
|
3627
|
+
this.get("suppressNextScroll") || (a.firstScrollEventTime === null && (a.firstScrollEventTime = Date.now()), this.clearContainerTimer(a), a.debounceTimer = window.setTimeout(() => {
|
|
3628
|
+
const u = this.calculateScrollData(a);
|
|
3619
3629
|
if (u) {
|
|
3620
3630
|
const S = Date.now();
|
|
3621
|
-
this.processScrollEvent(
|
|
3631
|
+
this.processScrollEvent(a, u, S);
|
|
3622
3632
|
}
|
|
3623
|
-
|
|
3633
|
+
a.debounceTimer = null;
|
|
3624
3634
|
}, 250));
|
|
3625
3635
|
};
|
|
3626
|
-
|
|
3636
|
+
a.listener = c, this.containers.push(a), e === window ? window.addEventListener("scroll", c, { passive: !0 }) : e.addEventListener("scroll", c, { passive: !0 });
|
|
3627
3637
|
}
|
|
3628
3638
|
processScrollEvent(e, t, r) {
|
|
3629
3639
|
if (!this.shouldEmitScrollEvent(e, t, r))
|
|
@@ -3652,7 +3662,7 @@ class ur extends v {
|
|
|
3652
3662
|
return Math.abs(t - e.lastDepth) >= this.minDepthChange;
|
|
3653
3663
|
}
|
|
3654
3664
|
logLimitOnce() {
|
|
3655
|
-
this.limitWarningLogged || (this.limitWarningLogged = !0,
|
|
3665
|
+
this.limitWarningLogged || (this.limitWarningLogged = !0, l("debug", "Max scroll events per session reached", {
|
|
3656
3666
|
data: { limit: this.maxEventsPerSession }
|
|
3657
3667
|
}));
|
|
3658
3668
|
}
|
|
@@ -3675,13 +3685,13 @@ class ur extends v {
|
|
|
3675
3685
|
return Math.min(100, Math.max(0, Math.floor(e / n * 100)));
|
|
3676
3686
|
}
|
|
3677
3687
|
calculateScrollData(e) {
|
|
3678
|
-
const { element: t, lastScrollPos: r, lastEventTime: n } = e, i = this.getScrollTop(t), o = Date.now(),
|
|
3679
|
-
if (
|
|
3688
|
+
const { element: t, lastScrollPos: r, lastEventTime: n } = e, i = this.getScrollTop(t), o = Date.now(), a = Math.abs(i - r);
|
|
3689
|
+
if (a < 10 || t === window && !this.isWindowScrollable())
|
|
3680
3690
|
return null;
|
|
3681
3691
|
const c = this.getViewportHeight(t), u = this.getScrollHeight(t), S = this.getScrollDirection(i, r), g = this.calculateScrollDepth(i, u, c);
|
|
3682
3692
|
let p;
|
|
3683
3693
|
n > 0 ? p = o - n : e.firstScrollEventTime !== null ? p = o - e.firstScrollEventTime : p = 250;
|
|
3684
|
-
const E = Math.round(
|
|
3694
|
+
const E = Math.round(a / p * 1e3);
|
|
3685
3695
|
return g > e.maxDepthReached && (e.maxDepthReached = g), e.lastScrollPos = i, {
|
|
3686
3696
|
depth: g,
|
|
3687
3697
|
direction: S,
|
|
@@ -3709,7 +3719,7 @@ class ur extends v {
|
|
|
3709
3719
|
else {
|
|
3710
3720
|
const n = document.querySelector(e);
|
|
3711
3721
|
if (!(n instanceof HTMLElement)) {
|
|
3712
|
-
|
|
3722
|
+
l("debug", `Selector "${e}" did not match an HTMLElement`);
|
|
3713
3723
|
return;
|
|
3714
3724
|
}
|
|
3715
3725
|
t = n;
|
|
@@ -3741,15 +3751,15 @@ class dr extends v {
|
|
|
3741
3751
|
return;
|
|
3742
3752
|
const t = this.config.threshold ?? 0.5, r = this.config.minDwellTime ?? 1e3;
|
|
3743
3753
|
if (t < 0 || t > 1) {
|
|
3744
|
-
|
|
3754
|
+
l("debug", "ViewportHandler: Invalid threshold, must be between 0 and 1");
|
|
3745
3755
|
return;
|
|
3746
3756
|
}
|
|
3747
3757
|
if (r < 0) {
|
|
3748
|
-
|
|
3758
|
+
l("debug", "ViewportHandler: Invalid minDwellTime, must be non-negative");
|
|
3749
3759
|
return;
|
|
3750
3760
|
}
|
|
3751
3761
|
if (typeof IntersectionObserver > "u") {
|
|
3752
|
-
|
|
3762
|
+
l("debug", "ViewportHandler: IntersectionObserver not supported in this browser");
|
|
3753
3763
|
return;
|
|
3754
3764
|
}
|
|
3755
3765
|
this.observer = new IntersectionObserver(this.handleIntersection, {
|
|
@@ -3777,7 +3787,7 @@ class dr extends v {
|
|
|
3777
3787
|
const n = document.querySelectorAll(r.selector);
|
|
3778
3788
|
for (const i of Array.from(n)) {
|
|
3779
3789
|
if (t >= e) {
|
|
3780
|
-
|
|
3790
|
+
l("debug", "ViewportHandler: Maximum tracked elements reached", {
|
|
3781
3791
|
data: {
|
|
3782
3792
|
limit: e,
|
|
3783
3793
|
selector: r.selector,
|
|
@@ -3797,9 +3807,9 @@ class dr extends v {
|
|
|
3797
3807
|
}), this.observer?.observe(i), t++);
|
|
3798
3808
|
}
|
|
3799
3809
|
} catch (n) {
|
|
3800
|
-
|
|
3810
|
+
l("debug", `ViewportHandler: Invalid selector "${r.selector}"`, { error: n });
|
|
3801
3811
|
}
|
|
3802
|
-
|
|
3812
|
+
l("debug", "ViewportHandler: Elements tracked", {
|
|
3803
3813
|
data: { count: t, limit: e }
|
|
3804
3814
|
});
|
|
3805
3815
|
}
|
|
@@ -3827,7 +3837,7 @@ class dr extends v {
|
|
|
3827
3837
|
return;
|
|
3828
3838
|
const n = this.config?.cooldownPeriod ?? 6e4, i = Date.now();
|
|
3829
3839
|
if (e.lastFiredTime !== null && i - e.lastFiredTime < n) {
|
|
3830
|
-
|
|
3840
|
+
l("debug", "ViewportHandler: Event suppressed by cooldown period", {
|
|
3831
3841
|
data: {
|
|
3832
3842
|
selector: e.selector,
|
|
3833
3843
|
cooldownRemaining: n - (i - e.lastFiredTime)
|
|
@@ -3853,7 +3863,7 @@ class dr extends v {
|
|
|
3853
3863
|
setupMutationObserver() {
|
|
3854
3864
|
if (!(!this.config || typeof MutationObserver > "u")) {
|
|
3855
3865
|
if (!document.body) {
|
|
3856
|
-
|
|
3866
|
+
l("debug", "ViewportHandler: document.body not available, skipping MutationObserver setup");
|
|
3857
3867
|
return;
|
|
3858
3868
|
}
|
|
3859
3869
|
this.mutationObserver = new MutationObserver((e) => {
|
|
@@ -3877,8 +3887,8 @@ class dr extends v {
|
|
|
3877
3887
|
if (t.nodeType !== 1) return;
|
|
3878
3888
|
const r = t, n = this.trackedElements.get(r);
|
|
3879
3889
|
n && (n.timeoutId !== null && window.clearTimeout(n.timeoutId), this.observer?.unobserve(r), this.trackedElements.delete(r)), Array.from(this.trackedElements.keys()).filter((o) => r.contains(o)).forEach((o) => {
|
|
3880
|
-
const
|
|
3881
|
-
|
|
3890
|
+
const a = this.trackedElements.get(o);
|
|
3891
|
+
a && a.timeoutId !== null && window.clearTimeout(a.timeoutId), this.observer?.unobserve(o), this.trackedElements.delete(o);
|
|
3882
3892
|
});
|
|
3883
3893
|
});
|
|
3884
3894
|
}
|
|
@@ -3890,7 +3900,7 @@ class hr {
|
|
|
3890
3900
|
fallbackSessionStorage = /* @__PURE__ */ new Map();
|
|
3891
3901
|
hasQuotaExceededError = !1;
|
|
3892
3902
|
constructor() {
|
|
3893
|
-
this.storage = this.initializeStorage("localStorage"), this.sessionStorageRef = this.initializeStorage("sessionStorage"), this.storage ||
|
|
3903
|
+
this.storage = this.initializeStorage("localStorage"), this.sessionStorageRef = this.initializeStorage("sessionStorage"), this.storage || l("debug", "localStorage not available, using memory fallback"), this.sessionStorageRef || l("debug", "sessionStorage not available, using memory fallback");
|
|
3894
3904
|
}
|
|
3895
3905
|
/**
|
|
3896
3906
|
* Retrieves an item from localStorage.
|
|
@@ -3933,7 +3943,7 @@ class hr {
|
|
|
3933
3943
|
}
|
|
3934
3944
|
} catch (r) {
|
|
3935
3945
|
if (r instanceof DOMException && r.name === "QuotaExceededError" || r instanceof Error && r.name === "QuotaExceededError")
|
|
3936
|
-
if (this.hasQuotaExceededError = !0,
|
|
3946
|
+
if (this.hasQuotaExceededError = !0, l("warn", "localStorage quota exceeded, attempting cleanup", {
|
|
3937
3947
|
data: { key: e, valueSize: t.length }
|
|
3938
3948
|
}), this.cleanupOldData())
|
|
3939
3949
|
try {
|
|
@@ -3942,13 +3952,13 @@ class hr {
|
|
|
3942
3952
|
return;
|
|
3943
3953
|
}
|
|
3944
3954
|
} catch (o) {
|
|
3945
|
-
|
|
3955
|
+
l("error", "localStorage quota exceeded even after cleanup - data will not persist", {
|
|
3946
3956
|
error: o,
|
|
3947
3957
|
data: { key: e, valueSize: t.length }
|
|
3948
3958
|
});
|
|
3949
3959
|
}
|
|
3950
3960
|
else
|
|
3951
|
-
|
|
3961
|
+
l("error", "localStorage quota exceeded and no data to cleanup - data will not persist", {
|
|
3952
3962
|
error: r,
|
|
3953
3963
|
data: { key: e, valueSize: t.length }
|
|
3954
3964
|
});
|
|
@@ -3994,7 +4004,7 @@ class hr {
|
|
|
3994
4004
|
this.storage.removeItem(t);
|
|
3995
4005
|
}), this.fallbackStorage.clear();
|
|
3996
4006
|
} catch (e) {
|
|
3997
|
-
|
|
4007
|
+
l("error", "Failed to clear storage", { error: e }), this.fallbackStorage.clear();
|
|
3998
4008
|
}
|
|
3999
4009
|
}
|
|
4000
4010
|
/**
|
|
@@ -4071,7 +4081,7 @@ class hr {
|
|
|
4071
4081
|
}
|
|
4072
4082
|
}), !0) : !1;
|
|
4073
4083
|
} catch (e) {
|
|
4074
|
-
return
|
|
4084
|
+
return l("error", "Failed to cleanup old data", { error: e }), !1;
|
|
4075
4085
|
}
|
|
4076
4086
|
}
|
|
4077
4087
|
/**
|
|
@@ -4145,7 +4155,7 @@ class hr {
|
|
|
4145
4155
|
return;
|
|
4146
4156
|
}
|
|
4147
4157
|
} catch (r) {
|
|
4148
|
-
(r instanceof DOMException && r.name === "QuotaExceededError" || r instanceof Error && r.name === "QuotaExceededError") &&
|
|
4158
|
+
(r instanceof DOMException && r.name === "QuotaExceededError" || r instanceof Error && r.name === "QuotaExceededError") && l("error", "sessionStorage quota exceeded - data will not persist", {
|
|
4149
4159
|
error: r,
|
|
4150
4160
|
data: { key: e, valueSize: t.length }
|
|
4151
4161
|
});
|
|
@@ -4211,7 +4221,7 @@ class fr extends v {
|
|
|
4211
4221
|
try {
|
|
4212
4222
|
e.disconnect();
|
|
4213
4223
|
} catch (r) {
|
|
4214
|
-
|
|
4224
|
+
l("debug", "Failed to disconnect performance observer", { error: r, data: { observerIndex: t } });
|
|
4215
4225
|
}
|
|
4216
4226
|
}), this.observers.length = 0, this.reportedByNav.clear(), this.navigationHistory.length = 0;
|
|
4217
4227
|
}
|
|
@@ -4235,8 +4245,8 @@ class fr extends v {
|
|
|
4235
4245
|
for (const o of i) {
|
|
4236
4246
|
if (o.hadRecentInput === !0)
|
|
4237
4247
|
continue;
|
|
4238
|
-
const
|
|
4239
|
-
e +=
|
|
4248
|
+
const a = typeof o.value == "number" ? o.value : 0;
|
|
4249
|
+
e += a;
|
|
4240
4250
|
}
|
|
4241
4251
|
this.sendVital({ type: "CLS", value: Number(e.toFixed(2)) });
|
|
4242
4252
|
},
|
|
@@ -4255,8 +4265,8 @@ class fr extends v {
|
|
|
4255
4265
|
let n = 0;
|
|
4256
4266
|
const i = r.getEntries();
|
|
4257
4267
|
for (const o of i) {
|
|
4258
|
-
const
|
|
4259
|
-
n = Math.max(n,
|
|
4268
|
+
const a = (o.processingEnd ?? 0) - (o.startTime ?? 0);
|
|
4269
|
+
n = Math.max(n, a);
|
|
4260
4270
|
}
|
|
4261
4271
|
n > 0 && this.sendVital({ type: "INP", value: Number(n.toFixed(2)) });
|
|
4262
4272
|
},
|
|
@@ -4265,13 +4275,13 @@ class fr extends v {
|
|
|
4265
4275
|
}
|
|
4266
4276
|
async initWebVitals() {
|
|
4267
4277
|
try {
|
|
4268
|
-
const { onLCP: e, onCLS: t, onFCP: r, onTTFB: n, onINP: i } = await Promise.resolve().then(() => $r), o = (
|
|
4278
|
+
const { onLCP: e, onCLS: t, onFCP: r, onTTFB: n, onINP: i } = await Promise.resolve().then(() => $r), o = (a) => (c) => {
|
|
4269
4279
|
const u = Number(c.value.toFixed(2));
|
|
4270
|
-
this.sendVital({ type:
|
|
4280
|
+
this.sendVital({ type: a, value: u });
|
|
4271
4281
|
};
|
|
4272
4282
|
e(o("LCP"), { reportAllChanges: !1 }), t(o("CLS"), { reportAllChanges: !1 }), r(o("FCP"), { reportAllChanges: !1 }), n(o("TTFB"), { reportAllChanges: !1 }), i(o("INP"), { reportAllChanges: !1 });
|
|
4273
4283
|
} catch (e) {
|
|
4274
|
-
|
|
4284
|
+
l("debug", "Failed to load web-vitals library, using fallback", { error: e }), this.observeWebVitalsFallback();
|
|
4275
4285
|
}
|
|
4276
4286
|
}
|
|
4277
4287
|
reportTTFB() {
|
|
@@ -4282,7 +4292,7 @@ class fr extends v {
|
|
|
4282
4292
|
const t = e.responseStart;
|
|
4283
4293
|
typeof t == "number" && Number.isFinite(t) && this.sendVital({ type: "TTFB", value: Number(t.toFixed(2)) });
|
|
4284
4294
|
} catch (e) {
|
|
4285
|
-
|
|
4295
|
+
l("debug", "Failed to report TTFB", { error: e });
|
|
4286
4296
|
}
|
|
4287
4297
|
}
|
|
4288
4298
|
observeLongTasks() {
|
|
@@ -4317,7 +4327,7 @@ class fr extends v {
|
|
|
4317
4327
|
}
|
|
4318
4328
|
trackWebVital(e, t) {
|
|
4319
4329
|
if (!Number.isFinite(t)) {
|
|
4320
|
-
|
|
4330
|
+
l("debug", "Invalid web vital value", { data: { type: e, value: t } });
|
|
4321
4331
|
return;
|
|
4322
4332
|
}
|
|
4323
4333
|
this.eventManager.track({
|
|
@@ -4357,7 +4367,7 @@ class fr extends v {
|
|
|
4357
4367
|
const t = e.startTime || performance.now(), r = ++this.navigationCounter, n = `${t.toFixed(2)}_${window.location.pathname}`;
|
|
4358
4368
|
return r > 1 ? `${n}_${r}` : n;
|
|
4359
4369
|
} catch (e) {
|
|
4360
|
-
return
|
|
4370
|
+
return l("debug", "Failed to get navigation ID", { error: e }), null;
|
|
4361
4371
|
}
|
|
4362
4372
|
}
|
|
4363
4373
|
isObserverSupported(e) {
|
|
@@ -4369,24 +4379,24 @@ class fr extends v {
|
|
|
4369
4379
|
try {
|
|
4370
4380
|
if (!this.isObserverSupported(e))
|
|
4371
4381
|
return !1;
|
|
4372
|
-
const i = new PerformanceObserver((o,
|
|
4382
|
+
const i = new PerformanceObserver((o, a) => {
|
|
4373
4383
|
try {
|
|
4374
|
-
t(o,
|
|
4384
|
+
t(o, a);
|
|
4375
4385
|
} catch (c) {
|
|
4376
|
-
|
|
4386
|
+
l("debug", "Observer callback failed", {
|
|
4377
4387
|
error: c,
|
|
4378
4388
|
data: { type: e }
|
|
4379
4389
|
});
|
|
4380
4390
|
}
|
|
4381
4391
|
if (n)
|
|
4382
4392
|
try {
|
|
4383
|
-
|
|
4393
|
+
a.disconnect();
|
|
4384
4394
|
} catch {
|
|
4385
4395
|
}
|
|
4386
4396
|
});
|
|
4387
4397
|
return i.observe(r ?? { type: e, buffered: !0 }), n || this.observers.push(i), !0;
|
|
4388
4398
|
} catch (i) {
|
|
4389
|
-
return
|
|
4399
|
+
return l("debug", "Failed to create performance observer", {
|
|
4390
4400
|
error: i,
|
|
4391
4401
|
data: { type: e }
|
|
4392
4402
|
}), !1;
|
|
@@ -4394,7 +4404,7 @@ class fr extends v {
|
|
|
4394
4404
|
}
|
|
4395
4405
|
shouldSendVital(e, t) {
|
|
4396
4406
|
if (typeof t != "number" || !Number.isFinite(t))
|
|
4397
|
-
return
|
|
4407
|
+
return l("debug", "Invalid web vital value", { data: { type: e, value: t } }), !1;
|
|
4398
4408
|
const r = this.vitalThresholds[e];
|
|
4399
4409
|
return !(typeof r == "number" && t <= r);
|
|
4400
4410
|
}
|
|
@@ -4436,7 +4446,7 @@ class mr extends v {
|
|
|
4436
4446
|
if (e < this.burstBackoffUntil)
|
|
4437
4447
|
return !1;
|
|
4438
4448
|
if (e - this.burstWindowStart > Mt && (this.errorBurstCounter = 0, this.burstWindowStart = e), this.errorBurstCounter++, this.errorBurstCounter > Ct)
|
|
4439
|
-
return this.burstBackoffUntil = e + Ve,
|
|
4449
|
+
return this.burstBackoffUntil = e + Ve, l("debug", "Error burst detected - entering cooldown", {
|
|
4440
4450
|
data: {
|
|
4441
4451
|
errorsInWindow: this.errorBurstCounter,
|
|
4442
4452
|
cooldownMs: Ve
|
|
@@ -4535,15 +4545,16 @@ class gr extends v {
|
|
|
4535
4545
|
this.managers.storage = new hr();
|
|
4536
4546
|
try {
|
|
4537
4547
|
this.setupState(e);
|
|
4538
|
-
const t = e.integrations?.custom?.headers ?? {};
|
|
4548
|
+
const t = e.integrations?.custom?.headers ?? {}, r = e.integrations?.custom?.fetchCredentials ?? "include";
|
|
4539
4549
|
return this.managers.event = new sr(
|
|
4540
4550
|
this.managers.storage,
|
|
4541
4551
|
this.emitter,
|
|
4542
4552
|
this.transformers,
|
|
4543
4553
|
t,
|
|
4544
|
-
this.customHeadersProvider
|
|
4545
|
-
|
|
4546
|
-
|
|
4554
|
+
this.customHeadersProvider,
|
|
4555
|
+
r
|
|
4556
|
+
), this.initializeHandlers(), this.setupPageLifecycleListeners(), await this.managers.event.recoverPersistedEvents().catch((n) => {
|
|
4557
|
+
l("warn", "Failed to recover persisted events", { error: n });
|
|
4547
4558
|
}), this.isInitialized = !0, { sessionId: this.get("sessionId") ?? "" };
|
|
4548
4559
|
} catch (t) {
|
|
4549
4560
|
this.destroy(!0);
|
|
@@ -4560,7 +4571,7 @@ class gr extends v {
|
|
|
4560
4571
|
*/
|
|
4561
4572
|
sendCustomEvent(e, t) {
|
|
4562
4573
|
if (!this.managers.event) {
|
|
4563
|
-
|
|
4574
|
+
l("warn", "Cannot send custom event: TraceLog not initialized", { data: { name: e } });
|
|
4564
4575
|
return;
|
|
4565
4576
|
}
|
|
4566
4577
|
let r = t;
|
|
@@ -4569,7 +4580,7 @@ class gr extends v {
|
|
|
4569
4580
|
if (!n) {
|
|
4570
4581
|
if (this.get("mode") === Y.QA)
|
|
4571
4582
|
throw new Error(`[TraceLog] Custom event "${e}" validation failed: ${i}`);
|
|
4572
|
-
|
|
4583
|
+
l("warn", `Custom event "${e}" dropped: ${i}`);
|
|
4573
4584
|
return;
|
|
4574
4585
|
}
|
|
4575
4586
|
this.managers.event.track({
|
|
@@ -4629,7 +4640,7 @@ class gr extends v {
|
|
|
4629
4640
|
try {
|
|
4630
4641
|
t.stopTracking();
|
|
4631
4642
|
} catch (r) {
|
|
4632
|
-
|
|
4643
|
+
l("warn", "Failed to stop tracking", { error: r });
|
|
4633
4644
|
}
|
|
4634
4645
|
}), this.suppressNextScrollTimer && (clearTimeout(this.suppressNextScrollTimer), this.suppressNextScrollTimer = null), this.pageUnloadHandler && (window.removeEventListener("pagehide", this.pageUnloadHandler), window.removeEventListener("beforeunload", this.pageUnloadHandler), this.pageUnloadHandler = null), this.managers.event?.flushImmediatelySync(), this.managers.event?.stop(), this.emitter.removeAllListeners(), this.transformers.beforeSend = void 0, this.transformers.beforeBatch = void 0, this.customHeadersProvider = void 0, this.set("suppressNextScroll", !1), this.set("sessionId", null), this.isInitialized = !1, this.handlers = {}, this.managers = {});
|
|
4635
4646
|
}
|
|
@@ -4714,7 +4725,7 @@ class gr extends v {
|
|
|
4714
4725
|
...this.get("config"),
|
|
4715
4726
|
globalMetadata: e
|
|
4716
4727
|
};
|
|
4717
|
-
this.set("config", n),
|
|
4728
|
+
this.set("config", n), l("debug", "Global metadata updated (replaced)", { data: { keys: Object.keys(e) } });
|
|
4718
4729
|
}
|
|
4719
4730
|
/**
|
|
4720
4731
|
* Merges new metadata with existing global metadata.
|
|
@@ -4734,7 +4745,7 @@ class gr extends v {
|
|
|
4734
4745
|
...r,
|
|
4735
4746
|
globalMetadata: i
|
|
4736
4747
|
};
|
|
4737
|
-
this.set("config", o),
|
|
4748
|
+
this.set("config", o), l("debug", "Global metadata updated (merged)", { data: { keys: Object.keys(e) } });
|
|
4738
4749
|
}
|
|
4739
4750
|
setupPageLifecycleListeners() {
|
|
4740
4751
|
this.pageUnloadHandler = () => {
|
|
@@ -4753,7 +4764,7 @@ class gr extends v {
|
|
|
4753
4764
|
}, 500);
|
|
4754
4765
|
};
|
|
4755
4766
|
this.handlers.pageView = new lr(this.managers.event, t), this.handlers.pageView.startTracking(), this.handlers.click = new cr(this.managers.event), this.handlers.click.startTracking(), this.handlers.scroll = new ur(this.managers.event), this.handlers.scroll.startTracking(), this.handlers.performance = new fr(this.managers.event), this.handlers.performance.startTracking().catch((r) => {
|
|
4756
|
-
|
|
4767
|
+
l("warn", "Failed to start performance tracking", { error: r });
|
|
4757
4768
|
}), this.handlers.error = new mr(this.managers.event), this.handlers.error.startTracking(), e.viewport && (this.handlers.viewport = new dr(this.managers.event), this.handlers.viewport.startTracking());
|
|
4758
4769
|
}
|
|
4759
4770
|
}
|
|
@@ -4763,14 +4774,14 @@ const Er = async (s) => typeof window > "u" || typeof document > "u" ? { session
|
|
|
4763
4774
|
try {
|
|
4764
4775
|
const e = Kt(s ?? {}), t = new gr();
|
|
4765
4776
|
try {
|
|
4766
|
-
O.forEach(({ event: o, callback:
|
|
4767
|
-
t.on(o,
|
|
4768
|
-
}), O.length = 0, M.forEach(({ hook: o, fn:
|
|
4769
|
-
o === "beforeSend" ? t.setTransformer("beforeSend",
|
|
4777
|
+
O.forEach(({ event: o, callback: a }) => {
|
|
4778
|
+
t.on(o, a);
|
|
4779
|
+
}), O.length = 0, M.forEach(({ hook: o, fn: a }) => {
|
|
4780
|
+
o === "beforeSend" ? t.setTransformer("beforeSend", a) : t.setTransformer("beforeBatch", a);
|
|
4770
4781
|
}), M.length = 0, N && (t.setCustomHeaders(N), N = null);
|
|
4771
|
-
const r = t.init(e), n = new Promise((o,
|
|
4782
|
+
const r = t.init(e), n = new Promise((o, a) => {
|
|
4772
4783
|
setTimeout(() => {
|
|
4773
|
-
|
|
4784
|
+
a(new Error("[TraceLog] Initialization timeout after 10000ms"));
|
|
4774
4785
|
}, 1e4);
|
|
4775
4786
|
}), i = await Promise.race([r, n]);
|
|
4776
4787
|
return h = t, i;
|
|
@@ -4778,7 +4789,7 @@ const Er = async (s) => typeof window > "u" || typeof document > "u" ? { session
|
|
|
4778
4789
|
try {
|
|
4779
4790
|
t.destroy(!0);
|
|
4780
4791
|
} catch (n) {
|
|
4781
|
-
|
|
4792
|
+
l("error", "Failed to cleanup partially initialized app", { error: n });
|
|
4782
4793
|
}
|
|
4783
4794
|
throw r;
|
|
4784
4795
|
}
|
|
@@ -4872,7 +4883,7 @@ const vr = (s) => {
|
|
|
4872
4883
|
try {
|
|
4873
4884
|
h.destroy(), h = null, C = !1, R = null, O.length = 0, M.length = 0, N = null, _ = !1;
|
|
4874
4885
|
} catch (s) {
|
|
4875
|
-
h = null, C = !1, R = null, O.length = 0, M.length = 0, N = null, _ = !1,
|
|
4886
|
+
h = null, C = !1, R = null, O.length = 0, M.length = 0, N = null, _ = !1, l("warn", "Error during destroy, forced cleanup completed", { error: s });
|
|
4876
4887
|
}
|
|
4877
4888
|
}
|
|
4878
4889
|
}, Ar = (s) => {
|
|
@@ -4909,7 +4920,7 @@ const vr = (s) => {
|
|
|
4909
4920
|
updateGlobalMetadata: Mr,
|
|
4910
4921
|
mergeGlobalMetadata: Cr
|
|
4911
4922
|
};
|
|
4912
|
-
var ge, tt = -1,
|
|
4923
|
+
var ge, tt = -1, k = function(s) {
|
|
4913
4924
|
addEventListener("pageshow", (function(e) {
|
|
4914
4925
|
e.persisted && (tt = e.timeStamp, s(e));
|
|
4915
4926
|
}), !0);
|
|
@@ -4937,8 +4948,8 @@ var ge, tt = -1, V = function(s) {
|
|
|
4937
4948
|
}, L = function(s, e, t, r) {
|
|
4938
4949
|
var n, i;
|
|
4939
4950
|
return function(o) {
|
|
4940
|
-
e.value >= 0 && (o || r) && ((i = e.value - (n || 0)) || n === void 0) && (n = e.value, e.delta = i, e.rating = (function(
|
|
4941
|
-
return
|
|
4951
|
+
e.value >= 0 && (o || r) && ((i = e.value - (n || 0)) || n === void 0) && (n = e.value, e.delta = i, e.rating = (function(a, c) {
|
|
4952
|
+
return a > c[1] ? "poor" : a > c[0] ? "needs-improvement" : "good";
|
|
4942
4953
|
})(e.value, t), s(e));
|
|
4943
4954
|
};
|
|
4944
4955
|
}, Ie = function(s) {
|
|
@@ -4956,21 +4967,21 @@ var ge, tt = -1, V = function(s) {
|
|
|
4956
4967
|
return function() {
|
|
4957
4968
|
e || (s(), e = !0);
|
|
4958
4969
|
};
|
|
4959
|
-
},
|
|
4970
|
+
}, V = -1, Be = function() {
|
|
4960
4971
|
return document.visibilityState !== "hidden" || document.prerendering ? 1 / 0 : 0;
|
|
4961
4972
|
}, J = function(s) {
|
|
4962
|
-
document.visibilityState === "hidden" &&
|
|
4973
|
+
document.visibilityState === "hidden" && V > -1 && (V = s.type === "visibilitychange" ? s.timeStamp : 0, Rr());
|
|
4963
4974
|
}, We = function() {
|
|
4964
4975
|
addEventListener("visibilitychange", J, !0), addEventListener("prerenderingchange", J, !0);
|
|
4965
4976
|
}, Rr = function() {
|
|
4966
4977
|
removeEventListener("visibilitychange", J, !0), removeEventListener("prerenderingchange", J, !0);
|
|
4967
4978
|
}, rt = function() {
|
|
4968
|
-
return
|
|
4979
|
+
return V < 0 && (V = Be(), We(), k((function() {
|
|
4969
4980
|
setTimeout((function() {
|
|
4970
|
-
|
|
4981
|
+
V = Be(), We();
|
|
4971
4982
|
}), 0);
|
|
4972
4983
|
}))), { get firstHiddenTime() {
|
|
4973
|
-
return
|
|
4984
|
+
return V;
|
|
4974
4985
|
} };
|
|
4975
4986
|
}, te = function(s) {
|
|
4976
4987
|
document.prerendering ? addEventListener("prerenderingchange", (function() {
|
|
@@ -4979,11 +4990,11 @@ var ge, tt = -1, V = function(s) {
|
|
|
4979
4990
|
}, Ee = [1800, 3e3], st = function(s, e) {
|
|
4980
4991
|
e = e || {}, te((function() {
|
|
4981
4992
|
var t, r = rt(), n = b("FCP"), i = B("paint", (function(o) {
|
|
4982
|
-
o.forEach((function(
|
|
4983
|
-
|
|
4993
|
+
o.forEach((function(a) {
|
|
4994
|
+
a.name === "first-contentful-paint" && (i.disconnect(), a.startTime < r.firstHiddenTime && (n.value = Math.max(a.startTime - Z(), 0), n.entries.push(a), t(!0)));
|
|
4984
4995
|
}));
|
|
4985
4996
|
}));
|
|
4986
|
-
i && (t = L(s, n, Ee, e.reportAllChanges),
|
|
4997
|
+
i && (t = L(s, n, Ee, e.reportAllChanges), k((function(o) {
|
|
4987
4998
|
n = b("FCP"), t = L(s, n, Ee, e.reportAllChanges), Ie((function() {
|
|
4988
4999
|
n.value = performance.now() - o.timeStamp, t(!0);
|
|
4989
5000
|
}));
|
|
@@ -4998,10 +5009,10 @@ var ge, tt = -1, V = function(s) {
|
|
|
4998
5009
|
n && u.startTime - g.startTime < 1e3 && u.startTime - S.startTime < 5e3 ? (n += u.value, i.push(u)) : (n = u.value, i = [u]);
|
|
4999
5010
|
}
|
|
5000
5011
|
})), n > r.value && (r.value = n, r.entries = i, t());
|
|
5001
|
-
},
|
|
5002
|
-
|
|
5003
|
-
o(
|
|
5004
|
-
})),
|
|
5012
|
+
}, a = B("layout-shift", o);
|
|
5013
|
+
a && (t = L(s, r, Se, e.reportAllChanges), ee((function() {
|
|
5014
|
+
o(a.takeRecords()), t(!0);
|
|
5015
|
+
})), k((function() {
|
|
5005
5016
|
n = 0, r = b("CLS", 0), t = L(s, r, Se, e.reportAllChanges), Ie((function() {
|
|
5006
5017
|
return t();
|
|
5007
5018
|
}));
|
|
@@ -5043,16 +5054,16 @@ var ge, tt = -1, V = function(s) {
|
|
|
5043
5054
|
"PerformanceEventTiming" in self && "interactionId" in PerformanceEventTiming.prototype && (e = e || {}, te((function() {
|
|
5044
5055
|
var t;
|
|
5045
5056
|
Pr();
|
|
5046
|
-
var r, n = b("INP"), i = function(
|
|
5057
|
+
var r, n = b("INP"), i = function(a) {
|
|
5047
5058
|
at((function() {
|
|
5048
|
-
|
|
5059
|
+
a.forEach(kr);
|
|
5049
5060
|
var c = Dr();
|
|
5050
5061
|
c && c.latency !== n.value && (n.value = c.latency, n.entries = c.entries, r());
|
|
5051
5062
|
}));
|
|
5052
5063
|
}, o = B("event", i, { durationThreshold: (t = e.durationThreshold) !== null && t !== void 0 ? t : 40 });
|
|
5053
5064
|
r = L(s, n, pe, e.reportAllChanges), o && (o.observe({ type: "first-input", buffered: !0 }), ee((function() {
|
|
5054
5065
|
i(o.takeRecords()), r(!0);
|
|
5055
|
-
})),
|
|
5066
|
+
})), k((function() {
|
|
5056
5067
|
ot = it(), y.length = 0, K.clear(), n = b("INP"), r = L(s, n, pe, e.reportAllChanges);
|
|
5057
5068
|
})));
|
|
5058
5069
|
})));
|
|
@@ -5065,14 +5076,14 @@ var ge, tt = -1, V = function(s) {
|
|
|
5065
5076
|
}, o = B("largest-contentful-paint", i);
|
|
5066
5077
|
if (o) {
|
|
5067
5078
|
t = L(s, n, Te, e.reportAllChanges);
|
|
5068
|
-
var
|
|
5079
|
+
var a = we((function() {
|
|
5069
5080
|
ae[n.id] || (i(o.takeRecords()), o.disconnect(), ae[n.id] = !0, t(!0));
|
|
5070
5081
|
}));
|
|
5071
5082
|
["keydown", "click"].forEach((function(c) {
|
|
5072
5083
|
addEventListener(c, (function() {
|
|
5073
|
-
return at(
|
|
5084
|
+
return at(a);
|
|
5074
5085
|
}), { once: !0, capture: !0 });
|
|
5075
|
-
})), ee(
|
|
5086
|
+
})), ee(a), k((function(c) {
|
|
5076
5087
|
n = b("LCP"), t = L(s, n, Te, e.reportAllChanges), Ie((function() {
|
|
5077
5088
|
n.value = performance.now() - c.timeStamp, ae[n.id] = !0, t(!0);
|
|
5078
5089
|
}));
|
|
@@ -5090,7 +5101,7 @@ var ge, tt = -1, V = function(s) {
|
|
|
5090
5101
|
var t = b("TTFB"), r = L(s, t, _e, e.reportAllChanges);
|
|
5091
5102
|
xr((function() {
|
|
5092
5103
|
var n = ve();
|
|
5093
|
-
n && (t.value = Math.max(n.responseStart - Z(), 0), t.entries = [n], r(!0),
|
|
5104
|
+
n && (t.value = Math.max(n.responseStart - Z(), 0), t.entries = [n], r(!0), k((function() {
|
|
5094
5105
|
t = b("TTFB", 0), (r = L(s, t, _e, e.reportAllChanges))(!0);
|
|
5095
5106
|
})));
|
|
5096
5107
|
}));
|
|
@@ -5117,7 +5128,7 @@ export {
|
|
|
5117
5128
|
x as ErrorType,
|
|
5118
5129
|
d as EventType,
|
|
5119
5130
|
Zr as InitializationTimeoutError,
|
|
5120
|
-
|
|
5131
|
+
P as IntegrationValidationError,
|
|
5121
5132
|
Yr as MAX_ARRAY_LENGTH,
|
|
5122
5133
|
Qr as MAX_CUSTOM_EVENT_ARRAY_SIZE,
|
|
5123
5134
|
Xr as MAX_CUSTOM_EVENT_KEYS,
|
|
@@ -5128,7 +5139,7 @@ export {
|
|
|
5128
5139
|
Kr as MAX_STRING_LENGTH_IN_ARRAY,
|
|
5129
5140
|
Y as Mode,
|
|
5130
5141
|
ze as PII_PATTERNS,
|
|
5131
|
-
|
|
5142
|
+
D as PermanentError,
|
|
5132
5143
|
Oe as SamplingRateValidationError,
|
|
5133
5144
|
j as ScrollDirection,
|
|
5134
5145
|
gt as SessionTimeoutValidationError,
|