@tracelog/lib 2.5.1 → 2.6.0-rc.91.5
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 +19 -0
- package/dist/browser/tracelog.esm.js +172 -113
- 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 +6 -0
- package/dist/public-api.d.ts +6 -0
- package/dist/public-api.js +2 -2
- package/dist/public-api.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -131,6 +131,7 @@ tracelog.destroy();
|
|
|
131
131
|
| `setCustomHeaders(provider)` | Add custom HTTP headers to requests (see [Custom Headers](#custom-headers)) |
|
|
132
132
|
| `removeCustomHeaders()` | Remove custom headers provider |
|
|
133
133
|
| `isInitialized()` | Check initialization status |
|
|
134
|
+
| `getSessionId()` | Get current session ID (or null) |
|
|
134
135
|
| `setQaMode(enabled)` | Enable/disable QA mode (console logging) |
|
|
135
136
|
| `destroy()` | Stop tracking and cleanup |
|
|
136
137
|
|
|
@@ -879,6 +880,24 @@ await tracelog.init({ /* same config */ });
|
|
|
879
880
|
|
|
880
881
|
**→ [Full Error Handling Reference](./API_REFERENCE.md#error-handling)**
|
|
881
882
|
|
|
883
|
+
### Session Continuity (External Redirects)
|
|
884
|
+
|
|
885
|
+
TraceLog automatically preserves sessions across external redirects (payment processors, OAuth flows, etc.) with zero developer action. Session data is mirrored to `sessionStorage` alongside `localStorage`, so when a user returns from an external site and `localStorage` is empty, the session is recovered from `sessionStorage` transparently.
|
|
886
|
+
|
|
887
|
+
```typescript
|
|
888
|
+
// No special handling needed before redirect
|
|
889
|
+
window.location.href = paymentUrl;
|
|
890
|
+
|
|
891
|
+
// On the confirmation page, init() automatically recovers the session
|
|
892
|
+
const { sessionId } = await tracelog.init({ /* same config */ });
|
|
893
|
+
tracelog.event('purchase', { orderId: '12345', amount: 99.99 });
|
|
894
|
+
// Same session as before the redirect
|
|
895
|
+
```
|
|
896
|
+
|
|
897
|
+
- Automatic: no API calls or developer action required
|
|
898
|
+
- `sessionStorage` mirror survives same-tab navigation (cleared on tab close)
|
|
899
|
+
- Session timeout still applies (expired sessions are not recovered)
|
|
900
|
+
|
|
882
901
|
---
|
|
883
902
|
|
|
884
903
|
## Privacy & Security
|
|
@@ -80,7 +80,7 @@ const m = {
|
|
|
80
80
|
/<embed\b[^>]*>/gi,
|
|
81
81
|
/<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi
|
|
82
82
|
], y = "tlog", G = `${y}:qa_mode`, Oe = `${y}:uid`, Je = "tlog_mode", Pe = "qa", De = "qa_off", It = (s) => s ? `${y}:${s}:queue` : `${y}:queue`, wt = (s) => s ? `${y}:${s}:session` : `${y}:session`, yt = (s) => s ? `${y}:${s}:broadcast` : `${y}:broadcast`, Ve = (s, e) => `${y}:${s}:session_counts:${e}`, ke = 10080 * 60 * 1e3, Ue = `${y}:session_counts_last_cleanup`, He = 3600 * 1e3;
|
|
83
|
-
var $ = /* @__PURE__ */ ((s) => (s.Localhost = "localhost:8080", s.Fail = "localhost:9999", s))($ || {}),
|
|
83
|
+
var $ = /* @__PURE__ */ ((s) => (s.Localhost = "localhost:8080", s.Fail = "localhost:9999", s))($ || {}), L = /* @__PURE__ */ ((s) => (s.Mobile = "mobile", s.Tablet = "tablet", s.Desktop = "desktop", s.Unknown = "unknown", s))(L || {}), me = /* @__PURE__ */ ((s) => (s.EVENT = "event", s.QUEUE = "queue", s))(me || {});
|
|
84
84
|
class N extends Error {
|
|
85
85
|
constructor(e, t) {
|
|
86
86
|
super(e), this.statusCode = t, this.name = "PermanentError", Error.captureStackTrace && Error.captureStackTrace(this, N);
|
|
@@ -123,7 +123,7 @@ class hs extends Q {
|
|
|
123
123
|
super(e, "INITIALIZATION_TIMEOUT", r), this.timeoutMs = t;
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
-
const Ze = "background: #ff9800; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;", et = "background: #9e9e9e; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;",
|
|
126
|
+
const Ze = "background: #ff9800; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;", et = "background: #9e9e9e; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;", At = "background: #d32f2f; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;", Lt = (s, e) => {
|
|
127
127
|
if (e) {
|
|
128
128
|
if (e instanceof Error) {
|
|
129
129
|
const t = e.message.replace(/\s+at\s+.*$/gm, "").replace(/\s*\([^()]+:\d+:\d+\)/g, "");
|
|
@@ -151,12 +151,12 @@ const Ze = "background: #ff9800; color: white; font-weight: bold; padding: 2px 8
|
|
|
151
151
|
return !1;
|
|
152
152
|
}
|
|
153
153
|
}, l = (s, e, t) => {
|
|
154
|
-
const { error: r, data: n, showToClient: i = !1, style: o, visibility: a } = t ?? {}, c = r ?
|
|
154
|
+
const { error: r, data: n, showToClient: i = !1, style: o, visibility: a } = t ?? {}, c = r ? Lt(e, r) : `[TraceLog] ${e}`, u = s === "error" ? "error" : s === "warn" ? "warn" : "log";
|
|
155
155
|
if (!Ct(a, i))
|
|
156
156
|
return;
|
|
157
|
-
const
|
|
158
|
-
Nt(u, c,
|
|
159
|
-
}, Ct = (s, e) => s === "critical" ? !0 : s === "qa" || e ? Mt() : !1, Rt = (s, e) => e !== void 0 && e !== "" ? e : s === "critical" ?
|
|
157
|
+
const E = Rt(a, o), p = n !== void 0 ? ge(n) : void 0;
|
|
158
|
+
Nt(u, c, E, p);
|
|
159
|
+
}, Ct = (s, e) => s === "critical" ? !0 : s === "qa" || e ? Mt() : !1, Rt = (s, e) => e !== void 0 && e !== "" ? e : s === "critical" ? At : "", Nt = (s, e, t, r) => {
|
|
160
160
|
const n = t !== void 0 && t !== "", i = n ? `%c${e}` : e;
|
|
161
161
|
r !== void 0 ? n ? console[s](i, t, r) : console[s](i, r) : n ? console[s](i, t) : console[s](i);
|
|
162
162
|
}, ge = (s) => {
|
|
@@ -204,13 +204,13 @@ const Ot = () => {
|
|
|
204
204
|
const s = navigator;
|
|
205
205
|
if (s.userAgentData != null && typeof s.userAgentData.mobile == "boolean") {
|
|
206
206
|
const c = s.userAgentData.platform;
|
|
207
|
-
return c != null && c !== "" && /ipad|tablet/i.test(c) ?
|
|
207
|
+
return c != null && c !== "" && /ipad|tablet/i.test(c) ? L.Tablet : s.userAgentData.mobile ? L.Mobile : L.Desktop;
|
|
208
208
|
}
|
|
209
209
|
Ot();
|
|
210
210
|
const e = window.innerWidth, t = Ee?.matches ?? !1, r = tt?.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);
|
|
211
|
-
return e <= 767 || o && n ?
|
|
211
|
+
return e <= 767 || o && n ? L.Mobile : e >= 768 && e <= 1024 || a || t && r && n ? L.Tablet : L.Desktop;
|
|
212
212
|
} catch (s) {
|
|
213
|
-
return l("debug", "Device detection failed, defaulting to desktop", { error: s }),
|
|
213
|
+
return l("debug", "Device detection failed, defaulting to desktop", { error: s }), L.Desktop;
|
|
214
214
|
}
|
|
215
215
|
}, kt = () => {
|
|
216
216
|
try {
|
|
@@ -222,7 +222,7 @@ const Ot = () => {
|
|
|
222
222
|
};
|
|
223
223
|
} catch (s) {
|
|
224
224
|
return l("debug", "Device info detection failed, using defaults", { error: s }), {
|
|
225
|
-
type:
|
|
225
|
+
type: L.Desktop,
|
|
226
226
|
os: se,
|
|
227
227
|
browser: se
|
|
228
228
|
};
|
|
@@ -290,7 +290,7 @@ const Ot = () => {
|
|
|
290
290
|
default:
|
|
291
291
|
return We;
|
|
292
292
|
}
|
|
293
|
-
}, Bt = 1e3, Wt = 50, Gt = "2.
|
|
293
|
+
}, Bt = 1e3, Wt = 50, Gt = "2.6.0", Xt = Gt, nt = () => typeof window < "u" && typeof sessionStorage < "u", Qt = () => {
|
|
294
294
|
try {
|
|
295
295
|
const s = new URLSearchParams(window.location.search);
|
|
296
296
|
s.delete(Je);
|
|
@@ -959,6 +959,15 @@ class ze extends w {
|
|
|
959
959
|
lastMetadataTimestamp = 0;
|
|
960
960
|
fetchCredentials;
|
|
961
961
|
pendingControllers = /* @__PURE__ */ new Set();
|
|
962
|
+
/**
|
|
963
|
+
* Counts consecutive fetch() rejections where no HTTP response was received
|
|
964
|
+
* (DNS failure, connection refused, etc.). Resets on success.
|
|
965
|
+
* When this reaches MAX_CONSECUTIVE_NETWORK_FAILURES the circuit opens and
|
|
966
|
+
* further send attempts are skipped until CIRCUIT_BREAKER_COOLDOWN_MS elapses,
|
|
967
|
+
* at which point a single probe request is allowed (half-open state).
|
|
968
|
+
*/
|
|
969
|
+
consecutiveNetworkFailures = 0;
|
|
970
|
+
circuitOpenedAt = 0;
|
|
962
971
|
/**
|
|
963
972
|
* Creates a SenderManager instance.
|
|
964
973
|
*
|
|
@@ -1181,8 +1190,16 @@ class ze extends w {
|
|
|
1181
1190
|
this.clearPersistedEvents();
|
|
1182
1191
|
return;
|
|
1183
1192
|
}
|
|
1184
|
-
const r =
|
|
1185
|
-
|
|
1193
|
+
const r = t.recoveryFailures, n = typeof r == "number" && Number.isFinite(r) && r >= 0 ? r : 0;
|
|
1194
|
+
if (n >= 3) {
|
|
1195
|
+
l(
|
|
1196
|
+
"debug",
|
|
1197
|
+
`Discarding persisted events after ${n} failed recovery attempts${this.integrationId ? ` [${this.integrationId}]` : ""}`
|
|
1198
|
+
), this.clearPersistedEvents(), e?.onFailure?.();
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
const i = this.createRecoveryBody(t);
|
|
1202
|
+
await this.send(i) ? (this.clearPersistedEvents(), e?.onSuccess?.(t.events.length, t.events, i)) : (this.persistEventsWithFailureCount(i, n + 1, !0), e?.onFailure?.());
|
|
1186
1203
|
} catch (t) {
|
|
1187
1204
|
if (t instanceof N) {
|
|
1188
1205
|
this.logPermanentError("Permanent error during recovery, clearing persisted events", t), this.clearPersistedEvents(), e?.onFailure?.();
|
|
@@ -1367,40 +1384,53 @@ class ze extends w {
|
|
|
1367
1384
|
return l("debug", `Success mode: simulating successful send${this.integrationId ? ` [${this.integrationId}]` : ""}`, {
|
|
1368
1385
|
data: { events: r.events.length }
|
|
1369
1386
|
}), !0;
|
|
1387
|
+
if (this.consecutiveNetworkFailures >= 3) {
|
|
1388
|
+
const c = Date.now() - this.circuitOpenedAt;
|
|
1389
|
+
if (c < 12e4)
|
|
1390
|
+
return l("debug", `Network circuit open, skipping send${this.integrationId ? ` [${this.integrationId}]` : ""}`, {
|
|
1391
|
+
data: {
|
|
1392
|
+
consecutiveNetworkFailures: this.consecutiveNetworkFailures,
|
|
1393
|
+
cooldownRemainingMs: 12e4 - c
|
|
1394
|
+
}
|
|
1395
|
+
}), !1;
|
|
1396
|
+
}
|
|
1370
1397
|
const { url: n, payload: i } = this.prepareRequest(r);
|
|
1371
|
-
let o = !0;
|
|
1372
|
-
for (let
|
|
1398
|
+
let o = !0, a = !1;
|
|
1399
|
+
for (let c = 1; c <= 3; c++)
|
|
1373
1400
|
try {
|
|
1374
|
-
return (await this.sendWithTimeout(n, i)).ok ? (
|
|
1401
|
+
return (await this.sendWithTimeout(n, i)).ok ? (c > 1 && l(
|
|
1375
1402
|
"info",
|
|
1376
|
-
`Send succeeded after ${
|
|
1403
|
+
`Send succeeded after ${c - 1} retry attempt(s)${this.integrationId ? ` [${this.integrationId}]` : ""}`,
|
|
1377
1404
|
{
|
|
1378
|
-
data: { events: r.events.length, attempt:
|
|
1405
|
+
data: { events: r.events.length, attempt: c }
|
|
1379
1406
|
}
|
|
1380
|
-
), !0) : !1;
|
|
1381
|
-
} catch (
|
|
1382
|
-
const
|
|
1383
|
-
if (
|
|
1384
|
-
throw
|
|
1385
|
-
if (
|
|
1386
|
-
|
|
1387
|
-
`Send attempt ${
|
|
1407
|
+
), this.consecutiveNetworkFailures = 0, this.circuitOpenedAt = 0, !0) : !1;
|
|
1408
|
+
} catch (u) {
|
|
1409
|
+
const g = c === 3;
|
|
1410
|
+
if (u instanceof N)
|
|
1411
|
+
throw this.consecutiveNetworkFailures = 0, this.circuitOpenedAt = 0, u;
|
|
1412
|
+
if (u instanceof O || (o = !1), u instanceof TypeError || (a = !0), l(
|
|
1413
|
+
g ? "error" : "warn",
|
|
1414
|
+
`Send attempt ${c} failed${this.integrationId ? ` [${this.integrationId}]` : ""}${g ? " (all retries exhausted)" : ", will retry"}`,
|
|
1388
1415
|
{
|
|
1389
|
-
error:
|
|
1416
|
+
error: u,
|
|
1390
1417
|
data: {
|
|
1391
1418
|
events: e.events.length,
|
|
1392
1419
|
url: n.replace(/\/\/[^/]+/, "//[DOMAIN]"),
|
|
1393
|
-
attempt:
|
|
1420
|
+
attempt: c,
|
|
1394
1421
|
maxAttempts: 3
|
|
1395
1422
|
}
|
|
1396
1423
|
}
|
|
1397
|
-
), !
|
|
1398
|
-
await this.backoffDelay(
|
|
1424
|
+
), !g) {
|
|
1425
|
+
await this.backoffDelay(c);
|
|
1399
1426
|
continue;
|
|
1400
1427
|
}
|
|
1401
1428
|
if (o)
|
|
1402
1429
|
throw new O("All retry attempts timed out (server likely received the request)");
|
|
1403
|
-
return
|
|
1430
|
+
return a ? (this.consecutiveNetworkFailures = 0, this.circuitOpenedAt = 0) : (this.consecutiveNetworkFailures = Math.min(
|
|
1431
|
+
this.consecutiveNetworkFailures + 1,
|
|
1432
|
+
3
|
|
1433
|
+
), this.consecutiveNetworkFailures >= 3 && (this.circuitOpenedAt = Date.now())), !1;
|
|
1404
1434
|
}
|
|
1405
1435
|
return !1;
|
|
1406
1436
|
}
|
|
@@ -1589,8 +1619,8 @@ class ze extends w {
|
|
|
1589
1619
|
* @private
|
|
1590
1620
|
*/
|
|
1591
1621
|
createRecoveryBody(e) {
|
|
1592
|
-
const { timestamp: t,
|
|
1593
|
-
return
|
|
1622
|
+
const { timestamp: t, recoveryFailures: r, ...n } = e;
|
|
1623
|
+
return n;
|
|
1594
1624
|
}
|
|
1595
1625
|
/**
|
|
1596
1626
|
* Persists failed events to localStorage for next-page-load recovery.
|
|
@@ -1610,26 +1640,44 @@ class ze extends w {
|
|
|
1610
1640
|
* @private
|
|
1611
1641
|
*/
|
|
1612
1642
|
persistEvents(e) {
|
|
1643
|
+
return this.persistEventsWithFailureCount(e, 0);
|
|
1644
|
+
}
|
|
1645
|
+
/**
|
|
1646
|
+
* Persists failed events to localStorage, recording how many consecutive
|
|
1647
|
+
* cross-session recovery attempts have already been made for this batch.
|
|
1648
|
+
*
|
|
1649
|
+
* When `recoveryFailures` reaches MAX_RECOVERY_FAILURES on the next page load,
|
|
1650
|
+
* the batch is discarded rather than retried, preventing an infinite persistence
|
|
1651
|
+
* loop caused by a permanently unreachable backend URL.
|
|
1652
|
+
*
|
|
1653
|
+
* @param body - EventsQueue to persist
|
|
1654
|
+
* @param recoveryFailures - Number of failed recovery attempts already made
|
|
1655
|
+
* @param skipThrottle - Bypass the multi-tab throttle (used during recovery re-persistence)
|
|
1656
|
+
* @returns `true` on successful persistence or throttled write, `false` on error
|
|
1657
|
+
* @private
|
|
1658
|
+
*/
|
|
1659
|
+
persistEventsWithFailureCount(e, t, r = !1) {
|
|
1613
1660
|
try {
|
|
1614
|
-
const
|
|
1615
|
-
if (
|
|
1616
|
-
const
|
|
1617
|
-
if (
|
|
1661
|
+
const n = this.getPersistedData();
|
|
1662
|
+
if (!r && n && n.timestamp) {
|
|
1663
|
+
const a = Date.now() - n.timestamp;
|
|
1664
|
+
if (a < 1e3)
|
|
1618
1665
|
return l(
|
|
1619
1666
|
"debug",
|
|
1620
1667
|
`Skipping persistence, another tab recently persisted events${this.integrationId ? ` [${this.integrationId}]` : ""}`,
|
|
1621
1668
|
{
|
|
1622
|
-
data: { timeSinceExisting:
|
|
1669
|
+
data: { timeSinceExisting: a }
|
|
1623
1670
|
}
|
|
1624
1671
|
), !0;
|
|
1625
1672
|
}
|
|
1626
|
-
const
|
|
1673
|
+
const i = {
|
|
1627
1674
|
...e,
|
|
1628
|
-
timestamp: Date.now()
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1675
|
+
timestamp: Date.now(),
|
|
1676
|
+
...t > 0 && { recoveryFailures: t }
|
|
1677
|
+
}, o = this.getQueueStorageKey();
|
|
1678
|
+
return this.storeManager.setItem(o, JSON.stringify(i)), !!this.storeManager.getItem(o);
|
|
1679
|
+
} catch (n) {
|
|
1680
|
+
return l("debug", `Failed to persist events${this.integrationId ? ` [${this.integrationId}]` : ""}`, { error: n }), !1;
|
|
1633
1681
|
}
|
|
1634
1682
|
}
|
|
1635
1683
|
clearPersistedEvents() {
|
|
@@ -1973,7 +2021,7 @@ class fr extends w {
|
|
|
1973
2021
|
web_vitals: a,
|
|
1974
2022
|
error_data: c,
|
|
1975
2023
|
viewport_data: u,
|
|
1976
|
-
page_view:
|
|
2024
|
+
page_view: g
|
|
1977
2025
|
}) {
|
|
1978
2026
|
if (!e) {
|
|
1979
2027
|
l("error", "Event type is required - event will be ignored");
|
|
@@ -1985,8 +2033,8 @@ class fr extends w {
|
|
|
1985
2033
|
});
|
|
1986
2034
|
return;
|
|
1987
2035
|
}
|
|
1988
|
-
const
|
|
1989
|
-
if (!
|
|
2036
|
+
const E = this.get("sessionId");
|
|
2037
|
+
if (!E) {
|
|
1990
2038
|
this.pendingEventsBuffer.length >= 100 && (this.pendingEventsBuffer.shift(), l("debug", "Pending events buffer full - dropping oldest event", {
|
|
1991
2039
|
data: { maxBufferSize: 100 }
|
|
1992
2040
|
})), this.pendingEventsBuffer.push({
|
|
@@ -1999,35 +2047,35 @@ class fr extends w {
|
|
|
1999
2047
|
web_vitals: a,
|
|
2000
2048
|
error_data: c,
|
|
2001
2049
|
viewport_data: u,
|
|
2002
|
-
page_view:
|
|
2050
|
+
page_view: g
|
|
2003
2051
|
});
|
|
2004
2052
|
return;
|
|
2005
2053
|
}
|
|
2006
|
-
this.lastSessionId !==
|
|
2054
|
+
this.lastSessionId !== E && (this.lastSessionId = E, this.sessionEventCounts = this.loadSessionCounts(E));
|
|
2007
2055
|
const p = e === d.SESSION_START;
|
|
2008
2056
|
if (p && l("debug", "Processing SESSION_START event", {
|
|
2009
|
-
data: { sessionId:
|
|
2057
|
+
data: { sessionId: E }
|
|
2010
2058
|
}), !p && !this.checkRateLimit())
|
|
2011
2059
|
return;
|
|
2012
|
-
const
|
|
2060
|
+
const S = e;
|
|
2013
2061
|
if (!p) {
|
|
2014
2062
|
if (this.sessionEventCounts.total >= 1e3) {
|
|
2015
2063
|
l("warn", "Session event limit reached", {
|
|
2016
2064
|
data: {
|
|
2017
|
-
type:
|
|
2065
|
+
type: S,
|
|
2018
2066
|
total: this.sessionEventCounts.total,
|
|
2019
2067
|
limit: 1e3
|
|
2020
2068
|
}
|
|
2021
2069
|
});
|
|
2022
2070
|
return;
|
|
2023
2071
|
}
|
|
2024
|
-
const T = this.getTypeLimitForEvent(
|
|
2072
|
+
const T = this.getTypeLimitForEvent(S);
|
|
2025
2073
|
if (T) {
|
|
2026
|
-
const le = this.sessionEventCounts[
|
|
2074
|
+
const le = this.sessionEventCounts[S];
|
|
2027
2075
|
if (le !== void 0 && le >= T) {
|
|
2028
2076
|
l("warn", "Session event type limit reached", {
|
|
2029
2077
|
data: {
|
|
2030
|
-
type:
|
|
2078
|
+
type: S,
|
|
2031
2079
|
count: le,
|
|
2032
2080
|
limit: T
|
|
2033
2081
|
}
|
|
@@ -2036,13 +2084,13 @@ class fr extends w {
|
|
|
2036
2084
|
}
|
|
2037
2085
|
}
|
|
2038
2086
|
}
|
|
2039
|
-
if (
|
|
2087
|
+
if (S === d.CUSTOM && o?.name) {
|
|
2040
2088
|
const T = this.get("config")?.maxSameEventPerMinute ?? 60;
|
|
2041
2089
|
if (!this.checkPerEventRateLimit(o.name, T))
|
|
2042
2090
|
return;
|
|
2043
2091
|
}
|
|
2044
|
-
const Ne =
|
|
2045
|
-
type:
|
|
2092
|
+
const Ne = S === d.SESSION_START, K = t || this.get("pageUrl"), F = this.buildEventPayload({
|
|
2093
|
+
type: S,
|
|
2046
2094
|
page_url: K,
|
|
2047
2095
|
from_page_url: r,
|
|
2048
2096
|
scroll_data: n,
|
|
@@ -2051,7 +2099,7 @@ class fr extends w {
|
|
|
2051
2099
|
web_vitals: a,
|
|
2052
2100
|
error_data: c,
|
|
2053
2101
|
viewport_data: u,
|
|
2054
|
-
page_view:
|
|
2102
|
+
page_view: g
|
|
2055
2103
|
});
|
|
2056
2104
|
if (F && !(!p && !this.shouldSample())) {
|
|
2057
2105
|
if (Ne) {
|
|
@@ -2070,7 +2118,7 @@ class fr extends w {
|
|
|
2070
2118
|
}
|
|
2071
2119
|
if (!this.isDuplicateEvent(F)) {
|
|
2072
2120
|
if (this.get("mode") === re.QA) {
|
|
2073
|
-
if (
|
|
2121
|
+
if (S === d.CUSTOM && o) {
|
|
2074
2122
|
l("info", `Custom Event: ${o.name}`, {
|
|
2075
2123
|
visibility: "qa",
|
|
2076
2124
|
data: {
|
|
@@ -2080,7 +2128,7 @@ class fr extends w {
|
|
|
2080
2128
|
}), this.emitEvent(F);
|
|
2081
2129
|
return;
|
|
2082
2130
|
}
|
|
2083
|
-
if (
|
|
2131
|
+
if (S === d.VIEWPORT_VISIBLE && u) {
|
|
2084
2132
|
const T = u.name || u.id || u.selector;
|
|
2085
2133
|
l("info", `Viewport Visible: ${T}`, {
|
|
2086
2134
|
visibility: "qa",
|
|
@@ -2096,7 +2144,7 @@ class fr extends w {
|
|
|
2096
2144
|
}
|
|
2097
2145
|
}
|
|
2098
2146
|
if (this.addToQueue(F), !p) {
|
|
2099
|
-
this.sessionEventCounts.total++, this.sessionEventCounts[
|
|
2147
|
+
this.sessionEventCounts.total++, this.sessionEventCounts[S] !== void 0 && this.sessionEventCounts[S]++;
|
|
2100
2148
|
const T = this.get("sessionId");
|
|
2101
2149
|
T && this.saveSessionCountsDebounced && this.saveSessionCountsDebounced(T);
|
|
2102
2150
|
}
|
|
@@ -2463,9 +2511,9 @@ class fr extends w {
|
|
|
2463
2511
|
...e.page_view && { page_view: e.page_view },
|
|
2464
2512
|
...o && { utm: o }
|
|
2465
2513
|
};
|
|
2466
|
-
const c = this.get("collectApiUrls"), u = !!c?.custom,
|
|
2467
|
-
if (
|
|
2468
|
-
const K = at(a,
|
|
2514
|
+
const c = this.get("collectApiUrls"), u = !!c?.custom, g = !!c?.saas, E = u || g, p = u && g, S = this.transformers.beforeSend;
|
|
2515
|
+
if (S && (!E || u && !p)) {
|
|
2516
|
+
const K = at(a, S, "EventManager");
|
|
2469
2517
|
if (K === null)
|
|
2470
2518
|
return null;
|
|
2471
2519
|
a = K;
|
|
@@ -2857,18 +2905,28 @@ class Er extends w {
|
|
|
2857
2905
|
}
|
|
2858
2906
|
loadStoredSession() {
|
|
2859
2907
|
const e = this.getSessionStorageKey(), t = this.storageManager.getItem(e);
|
|
2860
|
-
if (
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2908
|
+
if (t !== null)
|
|
2909
|
+
try {
|
|
2910
|
+
const n = JSON.parse(t);
|
|
2911
|
+
if (n.id && typeof n.lastActivity == "number")
|
|
2912
|
+
return n;
|
|
2913
|
+
} catch {
|
|
2914
|
+
this.storageManager.removeItem(e);
|
|
2915
|
+
}
|
|
2916
|
+
const r = this.storageManager.getSessionItem(e);
|
|
2917
|
+
if (r !== null)
|
|
2918
|
+
try {
|
|
2919
|
+
const n = JSON.parse(r);
|
|
2920
|
+
if (n.id && typeof n.lastActivity == "number")
|
|
2921
|
+
return n;
|
|
2922
|
+
} catch {
|
|
2923
|
+
this.storageManager.removeSessionItem(e);
|
|
2924
|
+
}
|
|
2925
|
+
return null;
|
|
2868
2926
|
}
|
|
2869
2927
|
saveStoredSession(e) {
|
|
2870
|
-
const t = this.getSessionStorageKey();
|
|
2871
|
-
this.storageManager.setItem(t,
|
|
2928
|
+
const t = this.getSessionStorageKey(), r = JSON.stringify(e);
|
|
2929
|
+
this.storageManager.setItem(t, r), this.storageManager.setSessionItem(t, r);
|
|
2872
2930
|
}
|
|
2873
2931
|
getSessionStorageKey() {
|
|
2874
2932
|
return wt(this.getProjectId());
|
|
@@ -2896,7 +2954,8 @@ class Er extends w {
|
|
|
2896
2954
|
* 11. Sets up lifecycle listeners (visibilitychange, beforeunload)
|
|
2897
2955
|
*
|
|
2898
2956
|
* **Session Recovery**:
|
|
2899
|
-
* - Checks localStorage for existing session
|
|
2957
|
+
* - Checks localStorage for existing session (primary)
|
|
2958
|
+
* - Falls back to sessionStorage mirror (survives external redirects)
|
|
2900
2959
|
* - Recovers if session exists and is recent (within timeout window)
|
|
2901
2960
|
* - NO SESSION_START event if session recovered
|
|
2902
2961
|
*
|
|
@@ -3309,14 +3368,14 @@ class Tr extends w {
|
|
|
3309
3368
|
return;
|
|
3310
3369
|
const o = this.findTrackingElement(n), a = this.getRelevantClickElement(n), c = this.calculateClickCoordinates(t, n);
|
|
3311
3370
|
if (o) {
|
|
3312
|
-
const
|
|
3313
|
-
if (
|
|
3314
|
-
const
|
|
3371
|
+
const g = this.extractTrackingData(o);
|
|
3372
|
+
if (g) {
|
|
3373
|
+
const E = this.createCustomEventData(g);
|
|
3315
3374
|
this.eventManager.track({
|
|
3316
3375
|
type: d.CUSTOM,
|
|
3317
3376
|
custom_event: {
|
|
3318
|
-
name:
|
|
3319
|
-
...
|
|
3377
|
+
name: E.name,
|
|
3378
|
+
...E.value && { metadata: { value: E.value } }
|
|
3320
3379
|
}
|
|
3321
3380
|
});
|
|
3322
3381
|
}
|
|
@@ -3654,8 +3713,8 @@ class vr extends w {
|
|
|
3654
3713
|
this.get("suppressNextScroll") || (a.firstScrollEventTime === null && (a.firstScrollEventTime = Date.now()), this.clearContainerTimer(a), a.debounceTimer = window.setTimeout(() => {
|
|
3655
3714
|
const u = this.calculateScrollData(a);
|
|
3656
3715
|
if (u) {
|
|
3657
|
-
const
|
|
3658
|
-
this.processScrollEvent(a, u,
|
|
3716
|
+
const g = Date.now();
|
|
3717
|
+
this.processScrollEvent(a, u, g);
|
|
3659
3718
|
}
|
|
3660
3719
|
a.debounceTimer = null;
|
|
3661
3720
|
}, 250));
|
|
@@ -3715,14 +3774,14 @@ class vr extends w {
|
|
|
3715
3774
|
const { element: t, lastScrollPos: r, lastEventTime: n } = e, i = this.getScrollTop(t), o = Date.now(), a = Math.abs(i - r);
|
|
3716
3775
|
if (a < 10 || t === window && !this.isWindowScrollable())
|
|
3717
3776
|
return null;
|
|
3718
|
-
const c = this.getViewportHeight(t), u = this.getScrollHeight(t),
|
|
3777
|
+
const c = this.getViewportHeight(t), u = this.getScrollHeight(t), g = this.getScrollDirection(i, r), E = this.calculateScrollDepth(i, u, c);
|
|
3719
3778
|
let p;
|
|
3720
3779
|
n > 0 ? p = o - n : e.firstScrollEventTime !== null ? p = o - e.firstScrollEventTime : p = 250;
|
|
3721
|
-
const
|
|
3722
|
-
return
|
|
3723
|
-
depth:
|
|
3724
|
-
direction:
|
|
3725
|
-
velocity:
|
|
3780
|
+
const S = Math.round(a / p * 1e3);
|
|
3781
|
+
return E > e.maxDepthReached && (e.maxDepthReached = E), e.lastScrollPos = i, {
|
|
3782
|
+
depth: E,
|
|
3783
|
+
direction: g,
|
|
3784
|
+
velocity: S,
|
|
3726
3785
|
max_depth_reached: e.maxDepthReached
|
|
3727
3786
|
};
|
|
3728
3787
|
}
|
|
@@ -4797,7 +4856,7 @@ class br extends w {
|
|
|
4797
4856
|
}
|
|
4798
4857
|
const V = [], M = [];
|
|
4799
4858
|
let D = null, h = null, R = !1, v = !1, P = null;
|
|
4800
|
-
const
|
|
4859
|
+
const Ar = async (s) => typeof window > "u" || typeof document > "u" ? { sessionId: "" } : (v = !1, window.__traceLogDisabled === !0 ? { sessionId: "" } : h ? { sessionId: h.getSessionId() ?? "" } : (R && P || (R = !0, P = (async () => {
|
|
4801
4860
|
try {
|
|
4802
4861
|
const e = ir(s ?? {}), t = new br();
|
|
4803
4862
|
try {
|
|
@@ -4825,7 +4884,7 @@ const Lr = async (s) => typeof window > "u" || typeof document > "u" ? { session
|
|
|
4825
4884
|
} finally {
|
|
4826
4885
|
R = !1, P = null;
|
|
4827
4886
|
}
|
|
4828
|
-
})()), P)),
|
|
4887
|
+
})()), P)), Lr = (s, e) => {
|
|
4829
4888
|
if (!(typeof window > "u" || typeof document > "u")) {
|
|
4830
4889
|
if (!h)
|
|
4831
4890
|
throw new Error("[TraceLog] TraceLog not initialized. Please call init() first.");
|
|
@@ -4932,8 +4991,8 @@ const Nr = (s) => {
|
|
|
4932
4991
|
h.mergeGlobalMetadata(s);
|
|
4933
4992
|
}
|
|
4934
4993
|
}, ms = {
|
|
4935
|
-
init:
|
|
4936
|
-
event:
|
|
4994
|
+
init: Ar,
|
|
4995
|
+
event: Lr,
|
|
4937
4996
|
on: Mr,
|
|
4938
4997
|
off: Cr,
|
|
4939
4998
|
setTransformer: Rr,
|
|
@@ -5032,8 +5091,8 @@ var _e, C, X, ct, ne, ut = -1, k = function(s) {
|
|
|
5032
5091
|
var t, r = _("CLS", 0), n = 0, i = [], o = function(c) {
|
|
5033
5092
|
c.forEach((function(u) {
|
|
5034
5093
|
if (!u.hadRecentInput) {
|
|
5035
|
-
var
|
|
5036
|
-
n && u.startTime -
|
|
5094
|
+
var g = i[0], E = i[i.length - 1];
|
|
5095
|
+
n && u.startTime - E.startTime < 1e3 && u.startTime - g.startTime < 5e3 ? (n += u.value, i.push(u)) : (n = u.value, i = [u]);
|
|
5037
5096
|
}
|
|
5038
5097
|
})), n > r.value && (r.value = n, r.entries = i, t());
|
|
5039
5098
|
}, a = x("layout-shift", o);
|
|
@@ -5053,23 +5112,23 @@ var _e, C, X, ct, ne, ut = -1, k = function(s) {
|
|
|
5053
5112
|
return _e ? ht : performance.interactionCount || 0;
|
|
5054
5113
|
}, Wr = function() {
|
|
5055
5114
|
"interactionCount" in performance || _e || (_e = x("event", Br, { type: "event", buffered: !0, durationThreshold: 0 }));
|
|
5056
|
-
},
|
|
5057
|
-
var s = Math.min(
|
|
5058
|
-
return
|
|
5115
|
+
}, A = [], te = /* @__PURE__ */ new Map(), mt = 0, Gr = function() {
|
|
5116
|
+
var s = Math.min(A.length - 1, Math.floor((ft() - mt) / 50));
|
|
5117
|
+
return A[s];
|
|
5059
5118
|
}, Xr = [], Qr = function(s) {
|
|
5060
5119
|
if (Xr.forEach((function(n) {
|
|
5061
5120
|
return n(s);
|
|
5062
5121
|
})), s.interactionId || s.entryType === "first-input") {
|
|
5063
|
-
var e =
|
|
5064
|
-
if (t ||
|
|
5122
|
+
var e = A[A.length - 1], t = te.get(s.interactionId);
|
|
5123
|
+
if (t || A.length < 10 || s.duration > e.latency) {
|
|
5065
5124
|
if (t) s.duration > t.latency ? (t.entries = [s], t.latency = s.duration) : s.duration === t.latency && s.startTime === t.entries[0].startTime && t.entries.push(s);
|
|
5066
5125
|
else {
|
|
5067
5126
|
var r = { id: s.interactionId, latency: s.duration, entries: [s] };
|
|
5068
|
-
te.set(r.id, r),
|
|
5127
|
+
te.set(r.id, r), A.push(r);
|
|
5069
5128
|
}
|
|
5070
|
-
|
|
5129
|
+
A.sort((function(n, i) {
|
|
5071
5130
|
return i.latency - n.latency;
|
|
5072
|
-
})),
|
|
5131
|
+
})), A.length > 10 && A.splice(10).forEach((function(n) {
|
|
5073
5132
|
return te.delete(n.id);
|
|
5074
5133
|
}));
|
|
5075
5134
|
}
|
|
@@ -5091,7 +5150,7 @@ var _e, C, X, ct, ne, ut = -1, k = function(s) {
|
|
|
5091
5150
|
r = I(s, n, ye, e.reportAllChanges), o && (o.observe({ type: "first-input", buffered: !0 }), j((function() {
|
|
5092
5151
|
i(o.takeRecords()), r(!0);
|
|
5093
5152
|
})), k((function() {
|
|
5094
|
-
mt = ft(),
|
|
5153
|
+
mt = ft(), A.length = 0, te.clear(), n = _("INP"), r = I(s, n, ye, e.reportAllChanges);
|
|
5095
5154
|
})));
|
|
5096
5155
|
})));
|
|
5097
5156
|
}, be = [2500, 4e3], fe = {}, zr = function(s, e) {
|
|
@@ -5117,7 +5176,7 @@ var _e, C, X, ct, ne, ut = -1, k = function(s) {
|
|
|
5117
5176
|
}));
|
|
5118
5177
|
}
|
|
5119
5178
|
}));
|
|
5120
|
-
},
|
|
5179
|
+
}, Ae = [800, 1800], Kr = function s(e) {
|
|
5121
5180
|
document.prerendering ? z((function() {
|
|
5122
5181
|
return s(e);
|
|
5123
5182
|
})) : document.readyState !== "complete" ? addEventListener("load", (function() {
|
|
@@ -5125,11 +5184,11 @@ var _e, C, X, ct, ne, ut = -1, k = function(s) {
|
|
|
5125
5184
|
}), !0) : setTimeout(e, 0);
|
|
5126
5185
|
}, Yr = function(s, e) {
|
|
5127
5186
|
e = e || {};
|
|
5128
|
-
var t = _("TTFB"), r = I(s, t,
|
|
5187
|
+
var t = _("TTFB"), r = I(s, t, Ae, e.reportAllChanges);
|
|
5129
5188
|
Kr((function() {
|
|
5130
5189
|
var n = Me();
|
|
5131
5190
|
n && (t.value = Math.max(n.responseStart - oe(), 0), t.entries = [n], r(!0), k((function() {
|
|
5132
|
-
t = _("TTFB", 0), (r = I(s, t,
|
|
5191
|
+
t = _("TTFB", 0), (r = I(s, t, Ae, e.reportAllChanges))(!0);
|
|
5133
5192
|
})));
|
|
5134
5193
|
}));
|
|
5135
5194
|
}, W = { passive: !0, capture: !0 }, qr = /* @__PURE__ */ new Date(), qe = function(s, e) {
|
|
@@ -5159,18 +5218,18 @@ var _e, C, X, ct, ne, ut = -1, k = function(s) {
|
|
|
5159
5218
|
["mousedown", "keydown", "touchstart", "pointerdown"].forEach((function(e) {
|
|
5160
5219
|
return s(e, Jr, W);
|
|
5161
5220
|
}));
|
|
5162
|
-
},
|
|
5221
|
+
}, Le = [100, 300], Zr = function(s, e) {
|
|
5163
5222
|
e = e || {}, z((function() {
|
|
5164
5223
|
var t, r = Re(), n = _("FID"), i = function(c) {
|
|
5165
5224
|
c.startTime < r.firstHiddenTime && (n.value = c.processingStart - c.startTime, n.entries.push(c), t(!0));
|
|
5166
5225
|
}, o = function(c) {
|
|
5167
5226
|
c.forEach(i);
|
|
5168
5227
|
}, a = x("first-input", o);
|
|
5169
|
-
t = I(s, n,
|
|
5228
|
+
t = I(s, n, Le, e.reportAllChanges), a && (j(ae((function() {
|
|
5170
5229
|
o(a.takeRecords()), a.disconnect();
|
|
5171
5230
|
}))), k((function() {
|
|
5172
5231
|
var c;
|
|
5173
|
-
n = _("FID"), t = I(s, n,
|
|
5232
|
+
n = _("FID"), t = I(s, n, Le, e.reportAllChanges), ne = [], X = -1, C = null, St(addEventListener), c = i, ne.push(c), Et();
|
|
5174
5233
|
})));
|
|
5175
5234
|
}));
|
|
5176
5235
|
};
|
|
@@ -5178,10 +5237,10 @@ const es = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
|
5178
5237
|
__proto__: null,
|
|
5179
5238
|
CLSThresholds: we,
|
|
5180
5239
|
FCPThresholds: Ie,
|
|
5181
|
-
FIDThresholds:
|
|
5240
|
+
FIDThresholds: Le,
|
|
5182
5241
|
INPThresholds: ye,
|
|
5183
5242
|
LCPThresholds: be,
|
|
5184
|
-
TTFBThresholds:
|
|
5243
|
+
TTFBThresholds: Ae,
|
|
5185
5244
|
onCLS: $r,
|
|
5186
5245
|
onFCP: dt,
|
|
5187
5246
|
onFID: Zr,
|
|
@@ -5193,7 +5252,7 @@ export {
|
|
|
5193
5252
|
f as AppConfigValidationError,
|
|
5194
5253
|
ts as DEFAULT_SESSION_TIMEOUT,
|
|
5195
5254
|
Se as DEFAULT_WEB_VITALS_MODE,
|
|
5196
|
-
|
|
5255
|
+
L as DeviceType,
|
|
5197
5256
|
me as EmitterEvent,
|
|
5198
5257
|
B as ErrorType,
|
|
5199
5258
|
d as EventType,
|