@sailfish-ai/recorder 1.11.1 → 1.11.3
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 +94 -0
- package/dist/chunks/{chunkSerializer-BiemuRlf.js → chunkSerializer-CV4nkb5-.js} +1 -1
- package/dist/chunks/chunkSerializer-CV4nkb5-.js.br +0 -0
- package/dist/chunks/chunkSerializer-CV4nkb5-.js.gz +0 -0
- package/dist/chunks/{chunkSerializer-CJQCxiLD.js → chunkSerializer-jzbHv2wf.js} +1 -1
- package/dist/chunks/chunkSerializer-jzbHv2wf.js.br +0 -0
- package/dist/chunks/chunkSerializer-jzbHv2wf.js.gz +0 -0
- package/dist/chunks/{index-Cfj4Epfd.js → index-BP-kNUGS.js} +80 -66
- package/dist/chunks/index-BP-kNUGS.js.br +0 -0
- package/dist/chunks/index-BP-kNUGS.js.gz +0 -0
- package/dist/chunks/{index-CuXHImrI.js → index-BynFTRFv.js} +51 -36
- package/dist/chunks/index-BynFTRFv.js.br +0 -0
- package/dist/chunks/index-BynFTRFv.js.gz +0 -0
- package/dist/chunks/rrweb-plugin-performance-record-BYWkWb25.js +188 -0
- package/dist/chunks/rrweb-plugin-performance-record-BYWkWb25.js.br +0 -0
- package/dist/chunks/rrweb-plugin-performance-record-BYWkWb25.js.gz +0 -0
- package/dist/chunks/rrweb-plugin-performance-record-Dekf6xUi.js +186 -0
- package/dist/chunks/rrweb-plugin-performance-record-Dekf6xUi.js.br +0 -0
- package/dist/chunks/rrweb-plugin-performance-record-Dekf6xUi.js.gz +0 -0
- package/dist/constants.js +1 -0
- package/dist/constants.js.br +0 -0
- package/dist/constants.js.gz +0 -0
- package/dist/index.js +14 -3
- package/dist/index.js.br +0 -0
- package/dist/index.js.gz +0 -0
- package/dist/recorder.cjs +2 -2
- package/dist/recorder.cjs.br +0 -0
- package/dist/recorder.cjs.gz +0 -0
- package/dist/recorder.js +19 -18
- package/dist/recorder.js.br +0 -0
- package/dist/recorder.js.gz +0 -0
- package/dist/recorder.umd.cjs +4980 -4788
- package/dist/recorder.umd.cjs.br +0 -0
- package/dist/recorder.umd.cjs.gz +0 -0
- package/dist/recording.js +31 -1
- package/dist/recording.js.br +0 -0
- package/dist/recording.js.gz +0 -0
- package/dist/types/constants.d.ts +1 -0
- package/dist/types/index.d.ts +21 -1
- package/dist/types/recording.d.ts +1 -0
- package/package.json +7 -4
- package/dist/chunks/chunkSerializer-BiemuRlf.js.br +0 -0
- package/dist/chunks/chunkSerializer-BiemuRlf.js.gz +0 -0
- package/dist/chunks/chunkSerializer-CJQCxiLD.js.br +0 -0
- package/dist/chunks/chunkSerializer-CJQCxiLD.js.gz +0 -0
- package/dist/chunks/index-Cfj4Epfd.js.br +0 -0
- package/dist/chunks/index-Cfj4Epfd.js.gz +0 -0
- package/dist/chunks/index-CuXHImrI.js.br +0 -0
- package/dist/chunks/index-CuXHImrI.js.gz +0 -0
package/README.md
CHANGED
|
@@ -140,6 +140,7 @@ await initRecorder({
|
|
|
140
140
|
| `deferRecording` | `boolean` | `true` | Defers the initial DOM snapshot until after first paint / idle. |
|
|
141
141
|
| `chunkSnapshot` | `boolean` | `false` | Yield to the browser every 500 nodes during the initial snapshot (smoother on very large pages). |
|
|
142
142
|
| `useWsWorker` | `boolean` | `true` | Run the WebSocket sender in a Web Worker. Disable if your CSP blocks `worker-src blob:`. |
|
|
143
|
+
| `capturePerformanceMetrics` | `boolean` | `true` | Capture FCP / LCP / TBT / DCL / LOAD per `page_visit_uuid` via the performance plugin. Set `false` to skip — the plugin is dynamically imported, so opting out also skips loading `web-vitals` and the observers. |
|
|
143
144
|
| `reportIssueShortcuts` | `ShortcutsConfig` | — | Custom keyboard shortcuts for the report-issue modal. |
|
|
144
145
|
| `showEngTicketFieldsInReportIssueModalDefault` | `boolean` | `false` | Pre-expand Jira / Linear fields in the in-app issue modal. |
|
|
145
146
|
|
|
@@ -185,6 +186,98 @@ if (isFunctionSpanTrackingEnabled()) disableFunctionSpanTracking();
|
|
|
185
186
|
enableFunctionSpanTracking();
|
|
186
187
|
```
|
|
187
188
|
|
|
189
|
+
## Performance metrics
|
|
190
|
+
|
|
191
|
+
The recorder automatically captures real-user performance metrics per page visit and emits them through the same WebSocket pipeline as everything else. No additional configuration is required; capture is skipped in Lighthouse / headless / WebDriver environments to avoid polluting synthetic audits.
|
|
192
|
+
|
|
193
|
+
| Metric | Meaning | Source |
|
|
194
|
+
|---|---|---|
|
|
195
|
+
| **FCP** — First Contentful Paint | Time to first text/image paint. | `web-vitals` `onFCP` |
|
|
196
|
+
| **LCP** — Largest Contentful Paint | Time to the largest above-the-fold element. Closest proxy for "content is visible". | `web-vitals` `onLCP` |
|
|
197
|
+
| **TBT** — Total Blocking Time | Sum of blocking time from long tasks, emitted at `load`. | `PerformanceObserver({type:'longtask', buffered:true})` summing `max(0, duration − 50)` |
|
|
198
|
+
| **DCL** — DOMContentLoaded | `navigation.domContentLoadedEventEnd` (ms since `timeOrigin`). | Navigation Timing Level 2 |
|
|
199
|
+
| **LOAD** — load event | `navigation.loadEventEnd` (ms since `timeOrigin`). | Navigation Timing Level 2 |
|
|
200
|
+
|
|
201
|
+
FCP and LCP re-emit on SPA soft-navigations (via `web-vitals`' native history-API / BFCache support) — each emission is keyed to the current `page_visit_uuid`. TBT, DCL, and LOAD fire once per hard load.
|
|
202
|
+
|
|
203
|
+
Events arrive on the recorder WebSocket with `type: 28` (the numeric id reserved for performance metrics — see `backend/sailfish/rrweb/enums.py` on the Sailfish backend) and the shape:
|
|
204
|
+
|
|
205
|
+
```json
|
|
206
|
+
{
|
|
207
|
+
"type": 28,
|
|
208
|
+
"timestamp": 1700000000000,
|
|
209
|
+
"sessionId": "<session_id>",
|
|
210
|
+
"page_visit_uuid": "<uuid>",
|
|
211
|
+
"href": "https://example.com/path",
|
|
212
|
+
"data": {
|
|
213
|
+
"plugin": "@sailfish-rrweb/rrweb/performance@1",
|
|
214
|
+
"payload": {
|
|
215
|
+
"metric": "FCP" | "LCP" | "TBT" | "DCL" | "LOAD",
|
|
216
|
+
"value": 1234.5,
|
|
217
|
+
"rating": "good" | "needs-improvement" | "poor",
|
|
218
|
+
"navigationType": "navigate" | "reload" | "back-forward" | "back-forward-cache" | "prerender" | "restore",
|
|
219
|
+
"pageVisitUuid": "<uuid>",
|
|
220
|
+
"href": "https://example.com/path",
|
|
221
|
+
"timestamp": 1700000000000
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Disabling capture
|
|
228
|
+
|
|
229
|
+
Pass `capturePerformanceMetrics: false` to `initRecorder` to skip the plugin entirely. Because the plugin code is dynamically imported, this also avoids loading `web-vitals` and the long-task observer:
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
initRecorder({
|
|
233
|
+
apiKey: "YOUR_API_KEY",
|
|
234
|
+
capturePerformanceMetrics: false,
|
|
235
|
+
});
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Benchmarking the plugin's overhead
|
|
239
|
+
|
|
240
|
+
`scripts/bench-perf.js` loads the same page twice — once with capture on, once with capture off — under headless Chrome, and reports CPU, JS heap, FCP/LCP, long-task time, and total load time side-by-side.
|
|
241
|
+
|
|
242
|
+
#### One-time app change (required before running the bench)
|
|
243
|
+
|
|
244
|
+
The bench needs a way to flip capture on/off without rebuilding your app between variants. Wire `?sf_perf=off` in your `initRecorder` call so the URL controls the option — paste this where you call `initRecorder`:
|
|
245
|
+
|
|
246
|
+
```ts
|
|
247
|
+
const capturePerformanceMetrics =
|
|
248
|
+
new URLSearchParams(window.location.search).get("sf_perf") !== "off";
|
|
249
|
+
|
|
250
|
+
initRecorder({
|
|
251
|
+
apiKey: "YOUR_API_KEY",
|
|
252
|
+
// …your other options…
|
|
253
|
+
capturePerformanceMetrics,
|
|
254
|
+
});
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Anything other than `?sf_perf=off` (including the param being absent) leaves capture enabled, so day-to-day usage is unaffected. The toggle exists only so the bench can switch variants by URL.
|
|
258
|
+
|
|
259
|
+
#### Run the bench
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
# 1. Start your app's dev server (separate terminal). Default port 3000.
|
|
263
|
+
npm run start
|
|
264
|
+
|
|
265
|
+
# 2. Run the bench (defaults to http://localhost:3000, 5 runs/variant):
|
|
266
|
+
cd veritas/jsts-frontend
|
|
267
|
+
npm install # first time only — installs puppeteer
|
|
268
|
+
npm run bench-perf
|
|
269
|
+
|
|
270
|
+
# Override URL or sample count:
|
|
271
|
+
npm run bench-perf -- --url http://localhost:3000/some/page --runs 10
|
|
272
|
+
|
|
273
|
+
# Watch the runs in a real browser window (slower, useful for sanity-checking):
|
|
274
|
+
npm run bench-perf -- --headed
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Output is a table of medians, p95, and Δ% between the two variants for: wall load time, DCL, load event, FCP, LCP, long-task total, long-task blocking (the TBT proxy), CDP `TaskDuration` / `ScriptDuration` / `LayoutDuration`, and `usedJSHeapSize` (MB).
|
|
278
|
+
|
|
279
|
+
Sample interpretation: a Δ ≤ noise (typically ±5% on the smaller numbers, ±2 MB on heap) means the plugin is essentially free; anything larger is a regression worth profiling.
|
|
280
|
+
|
|
188
281
|
## Framework examples
|
|
189
282
|
|
|
190
283
|
### React / Vite
|
|
@@ -311,4 +404,5 @@ ReferenceError: localStorage is not defined
|
|
|
311
404
|
|
|
312
405
|
## License
|
|
313
406
|
|
|
407
|
+
|
|
314
408
|
Proprietary. See [sailfishqa.com/terms](https://sailfishqa.com) for terms of service.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { y as e } from "./index-
|
|
1
|
+
import { y as e } from "./index-BynFTRFv.js";
|
|
2
2
|
async function chunkedSnapshot(t, n, o = {}) {
|
|
3
3
|
const s = o.chunkSize ?? 500, r = o.maxChunkMs ?? 16, { blockClass: c, blockSelector: a, maskTextClass: i, maskTextSelector: d } = o;
|
|
4
4
|
let u = 100001, l = 0, N = performance.now();
|
|
Binary file
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const e = require("./index-
|
|
3
|
+
const e = require("./index-BP-kNUGS.js");
|
|
4
4
|
exports.chunkedSnapshot = async function chunkedSnapshot(t, n, o = {}) {
|
|
5
5
|
const s = o.chunkSize ?? 500, r = o.maxChunkMs ?? 16, { blockClass: c, blockSelector: a, maskTextClass: i, maskTextSelector: d } = o;
|
|
6
6
|
let u = 100001, l = 0, N = performance.now();
|
|
Binary file
|
|
Binary file
|
|
@@ -178,7 +178,7 @@ function withAppUrlMetadata(e2) {
|
|
|
178
178
|
return { ...e2 ?? {}, appUrl: (e2 == null ? void 0 : e2.appUrl) ?? ((_a = window == null ? void 0 : window.location) == null ? void 0 : _a.href) };
|
|
179
179
|
}
|
|
180
180
|
exports.nowTimestamp = Date.now, /[1-9][0-9]{12}/.test(Date.now().toString()) || (exports.nowTimestamp = () => (/* @__PURE__ */ new Date()).getTime());
|
|
181
|
-
const
|
|
181
|
+
const w = readDebugFlag(), S = "per_session";
|
|
182
182
|
let v = null, k = null, x = false, I = null, T = null, E = "", C = "", $ = false;
|
|
183
183
|
const F = [];
|
|
184
184
|
function onNavigationChange(e2) {
|
|
@@ -222,8 +222,8 @@ function _flushIDBQueue() {
|
|
|
222
222
|
});
|
|
223
223
|
})(L.splice(0));
|
|
224
224
|
}
|
|
225
|
-
let A = false, R = null, D = null,
|
|
226
|
-
const
|
|
225
|
+
let A = false, R = null, D = null, P = false;
|
|
226
|
+
const _ = "sailfish_funcspan_global_state";
|
|
227
227
|
function wsSendPayload(e2) {
|
|
228
228
|
if (!isWebSocketOpen(k)) return false;
|
|
229
229
|
if (v) try {
|
|
@@ -254,21 +254,21 @@ function saveGlobalFuncSpanState(e2, t2) {
|
|
|
254
254
|
try {
|
|
255
255
|
if ("undefined" == typeof localStorage) return;
|
|
256
256
|
const n2 = { enabled: e2, expirationTimestampMs: t2, savedAt: Date.now() };
|
|
257
|
-
localStorage.setItem(
|
|
257
|
+
localStorage.setItem(_, JSON.stringify(n2)), w && console.log("[Sailfish] Saved funcSpan state to localStorage:", n2);
|
|
258
258
|
} catch (e3) {
|
|
259
|
-
|
|
259
|
+
w && console.warn("[Sailfish] Failed to save funcSpan state to localStorage:", e3);
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
262
|
function clearGlobalFuncSpanState() {
|
|
263
263
|
try {
|
|
264
264
|
if ("undefined" == typeof localStorage) return;
|
|
265
|
-
localStorage.removeItem(
|
|
265
|
+
localStorage.removeItem(_), w && console.log("[Sailfish] Cleared funcSpan state from localStorage");
|
|
266
266
|
} catch (e2) {
|
|
267
|
-
|
|
267
|
+
w && console.warn("[Sailfish] Failed to clear funcSpan state from localStorage:", e2);
|
|
268
268
|
}
|
|
269
269
|
}
|
|
270
270
|
function clearStaleFuncSpanState() {
|
|
271
|
-
A = false, D = null,
|
|
271
|
+
A = false, D = null, P = false, clearGlobalFuncSpanState(), w && console.log("[Sailfish] Cleared stale function span tracking state (backend validation failed)");
|
|
272
272
|
}
|
|
273
273
|
let B = false;
|
|
274
274
|
function restoreFuncSpanState() {
|
|
@@ -277,17 +277,17 @@ function restoreFuncSpanState() {
|
|
|
277
277
|
const e2 = (function loadGlobalFuncSpanState() {
|
|
278
278
|
try {
|
|
279
279
|
if ("undefined" == typeof localStorage) return null;
|
|
280
|
-
const e3 = localStorage.getItem(
|
|
280
|
+
const e3 = localStorage.getItem(_);
|
|
281
281
|
if (!e3) return null;
|
|
282
282
|
const t2 = JSON.parse(e3);
|
|
283
|
-
return
|
|
283
|
+
return w && console.log("[Sailfish] Loaded funcSpan state from localStorage:", t2), t2;
|
|
284
284
|
} catch (e3) {
|
|
285
|
-
return
|
|
285
|
+
return w && console.warn("[Sailfish] Failed to load funcSpan state from localStorage:", e3), null;
|
|
286
286
|
}
|
|
287
287
|
})();
|
|
288
|
-
if (e2 && e2.enabled) if (A = true, D = e2.expirationTimestampMs,
|
|
289
|
-
Date.now() >= D ? (A = false, D = null, clearGlobalFuncSpanState(),
|
|
290
|
-
} else
|
|
288
|
+
if (e2 && e2.enabled) if (A = true, D = e2.expirationTimestampMs, P = false, w && console.log("[Sailfish] Restored global function span tracking from localStorage:", { enabled: true, expirationTime: D }), null !== D) {
|
|
289
|
+
Date.now() >= D ? (A = false, D = null, clearGlobalFuncSpanState(), w && console.log("[Sailfish] Persisted tracking already expired, cleared state")) : w && console.log("[Sailfish] Function span tracking is active and valid (temporary until WebSocket confirms)");
|
|
290
|
+
} else w && console.log("[Sailfish] Function span tracking is active (no expiration, temporary until WebSocket confirms)");
|
|
291
291
|
}
|
|
292
292
|
function isWebSocketOpen(e2) {
|
|
293
293
|
return (e2 == null ? void 0 : e2.readyState) === WebSocket.OPEN;
|
|
@@ -345,7 +345,7 @@ function sendEvent(e2) {
|
|
|
345
345
|
e2.app_url || (e2.app_url = getCachedHref()), !x && isWebSocketOpen(k) && wsSendPayload({ type: "event", event: e2, mapUuid: window.sfMapUuid }) || queueEventForIDB(e2);
|
|
346
346
|
}
|
|
347
347
|
function handleWsOpen() {
|
|
348
|
-
|
|
348
|
+
w && (console.log("[Sailfish] WebSocket connection opened"), console.log("[Sailfish] Function span tracking state: " + (A ? "ENABLED" : "DISABLED"))), (async () => {
|
|
349
349
|
try {
|
|
350
350
|
x = true, await flushNotifyQueue(), await flushBufferedEvents();
|
|
351
351
|
} finally {
|
|
@@ -357,29 +357,29 @@ function handleWsOpen() {
|
|
|
357
357
|
})();
|
|
358
358
|
}
|
|
359
359
|
function handleWsClose() {
|
|
360
|
-
null != T && (clearInterval(T), T = null),
|
|
360
|
+
null != T && (clearInterval(T), T = null), w && console.log("[Sailfish] WebSocket closed");
|
|
361
361
|
}
|
|
362
362
|
function handleWsMessage(e2) {
|
|
363
363
|
try {
|
|
364
364
|
const t2 = JSON.parse(e2);
|
|
365
|
-
if ("funcSpanTrackingControl" === t2.type) if (
|
|
365
|
+
if ("funcSpanTrackingControl" === t2.type) if (w && console.log("[Sailfish] Received funcSpanTrackingControl message:", { enabled: t2.enabled, timeoutSeconds: t2.timeoutSeconds, expirationTimestampMs: t2.expirationTimestampMs }), null !== R && (window.clearTimeout(R), R = null), A = t2.enabled, P = false, w && console.log("[Sailfish] Function span tracking " + (t2.enabled ? "ENABLED (GLOBAL)" : "DISABLED (GLOBAL)")), t2.enabled) {
|
|
366
366
|
if (t2.expirationTimestampMs) {
|
|
367
367
|
D = t2.expirationTimestampMs;
|
|
368
368
|
const e3 = Date.now(), n2 = D - e3;
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
}, n2)) : (A = false, D = null, clearGlobalFuncSpanState(),
|
|
369
|
+
w && console.log(`[Sailfish] Server expiration timestamp: ${D}, ms until expiration: ${n2}`), n2 > 0 ? (saveGlobalFuncSpanState(true, D), R = window.setTimeout(() => {
|
|
370
|
+
P || (A = false, D = null, clearGlobalFuncSpanState(), w && console.log("[Sailfish] GLOBAL function span tracking auto-disabled at server expiration time"), wsSendPayload({ type: "funcSpanTrackingExpired", sessionId: getOrSetSessionId(), expiredAt: Date.now() }), w && console.log("[Sailfish] Notified backend that function span tracking expired"));
|
|
371
|
+
}, n2)) : (A = false, D = null, clearGlobalFuncSpanState(), w && console.log("[Sailfish] Tracking already expired, not enabling"));
|
|
372
372
|
} else {
|
|
373
373
|
const e3 = t2.timeoutSeconds || 3600;
|
|
374
374
|
e3 > 0 && (D = Date.now() + 1e3 * e3, saveGlobalFuncSpanState(true, D), R = window.setTimeout(() => {
|
|
375
|
-
|
|
375
|
+
P || (A = false, D = null, clearGlobalFuncSpanState(), w && console.log(`[Sailfish] GLOBAL function span tracking auto-disabled after ${e3}s (legacy)`), wsSendPayload({ type: "funcSpanTrackingExpired", sessionId: getOrSetSessionId(), expiredAt: Date.now() }), w && console.log("[Sailfish] Notified backend that function span tracking expired (legacy timeout)"));
|
|
376
376
|
}, 1e3 * e3));
|
|
377
377
|
}
|
|
378
378
|
try {
|
|
379
379
|
const e3 = getOrSetSessionId();
|
|
380
|
-
wsSendPayload({ type: "funcSpanTrackingSessionReport", sessionId: e3, enabled: true, configurationType: "global" }),
|
|
380
|
+
wsSendPayload({ type: "funcSpanTrackingSessionReport", sessionId: e3, enabled: true, configurationType: "global" }), w && console.log(`[Sailfish] GLOBAL tracking session report sent for session: ${e3}`);
|
|
381
381
|
} catch (e3) {
|
|
382
|
-
|
|
382
|
+
w && console.warn("[Sailfish] Failed to send GLOBAL tracking session report:", e3);
|
|
383
383
|
}
|
|
384
384
|
} else D = null, clearGlobalFuncSpanState();
|
|
385
385
|
} catch (e3) {
|
|
@@ -391,7 +391,7 @@ function initializeWebSocket(t2, n2, i2, o2, s2 = false) {
|
|
|
391
391
|
const t3 = new URL(e2);
|
|
392
392
|
return `${t3.hostname}${t3.port ? `:${t3.port}` : ""}`;
|
|
393
393
|
})(t2);
|
|
394
|
-
let a2 = `${"https:" === new URL(t2).protocol ? "wss" : "ws"}://${r2}/ws/notify/?apiKey=${n2}&sessionId=${i2}&sender=JS%2FTS&version=1.11.
|
|
394
|
+
let a2 = `${"https:" === new URL(t2).protocol ? "wss" : "ws"}://${r2}/ws/notify/?apiKey=${n2}&sessionId=${i2}&sender=JS%2FTS&version=1.11.3`;
|
|
395
395
|
if (o2 && (a2 += `&envValue=${encodeURIComponent(o2)}`), v = s2 ? (function tryCreateWsWorker() {
|
|
396
396
|
if ("undefined" == typeof Worker) return null;
|
|
397
397
|
try {
|
|
@@ -408,10 +408,10 @@ function initializeWebSocket(t2, n2, i2, o2, s2 = false) {
|
|
|
408
408
|
const n3 = e3.data;
|
|
409
409
|
"open" === n3.type ? (t3.readyState = WebSocket.OPEN, handleWsOpen()) : "close" === n3.type ? (t3.readyState = WebSocket.CLOSED, handleWsClose()) : "message" === n3.type && handleWsMessage(n3.data);
|
|
410
410
|
}, v.onerror = () => {
|
|
411
|
-
|
|
412
|
-
}, v.postMessage({ type: "init", wsUrl: a2 }),
|
|
411
|
+
w && console.warn("[Sailfish] WebSocket worker error");
|
|
412
|
+
}, v.postMessage({ type: "init", wsUrl: a2 }), w && console.log("[Sailfish] WebSocket running in Web Worker (off main thread)"), t3;
|
|
413
413
|
}
|
|
414
|
-
|
|
414
|
+
w && console.log("[Sailfish] WebSocket running on main thread (Worker unavailable)");
|
|
415
415
|
const l2 = new e(a2, [], { connectionTimeout: 3e4 }), c2 = { get readyState() {
|
|
416
416
|
return l2.readyState;
|
|
417
417
|
}, close: () => {
|
|
@@ -423,26 +423,26 @@ function sendMessage(e2) {
|
|
|
423
423
|
"sessionId" in e2 || (e2.sessionId = getOrSetSessionId()), e2.app_url || (e2.app_url = getCachedHref()), x || !isWebSocketOpen(k) ? saveNotifyMessageToIDB(JSON.stringify(e2)) : wsSendPayload(e2) || saveNotifyMessageToIDB(JSON.stringify(e2));
|
|
424
424
|
}
|
|
425
425
|
function enableFunctionSpanTracking() {
|
|
426
|
-
if (
|
|
427
|
-
wsSendPayload({ type: "funcSpanTrackingSessionReport", sessionId: getOrSetSessionId(), enabled: true, configurationType:
|
|
428
|
-
} else
|
|
426
|
+
if (w && console.log("[Sailfish] enableFunctionSpanTracking() called - Report Issue recording started (LOCAL MODE)"), A = true, P = true, D = null, null !== R && (window.clearTimeout(R), R = null), isWebSocketOpen(k)) {
|
|
427
|
+
wsSendPayload({ type: "funcSpanTrackingSessionReport", sessionId: getOrSetSessionId(), enabled: true, configurationType: S });
|
|
428
|
+
} else w && console.warn("[Sailfish] WebSocket not open, cannot report LOCAL tracking session");
|
|
429
429
|
}
|
|
430
430
|
function disableFunctionSpanTracking() {
|
|
431
|
-
if (
|
|
432
|
-
wsSendPayload({ type: "funcSpanTrackingSessionReport", sessionId: getOrSetSessionId(), enabled: false, configurationType:
|
|
431
|
+
if (w && console.log("[Sailfish] disableFunctionSpanTracking() called - Report Issue recording stopped"), isWebSocketOpen(k)) {
|
|
432
|
+
wsSendPayload({ type: "funcSpanTrackingSessionReport", sessionId: getOrSetSessionId(), enabled: false, configurationType: S });
|
|
433
433
|
} else console.warn("[FUNCSPAN STOP] ✗ WebSocket not open, cannot notify tracking end");
|
|
434
|
-
|
|
434
|
+
P && (A = false, P = false, D = null, w && console.log("[Sailfish] LOCAL tracking mode disabled")), null !== R && (window.clearTimeout(R), R = null);
|
|
435
435
|
}
|
|
436
436
|
function isFunctionSpanTrackingEnabled() {
|
|
437
437
|
return A;
|
|
438
438
|
}
|
|
439
439
|
function initializeFunctionSpanTrackingFromApi(e2) {
|
|
440
|
-
e2 && !A ? (A = true,
|
|
440
|
+
e2 && !A ? (A = true, P = false, D = null, w && console.log("[Sailfish] Function span tracking initialized as ENABLED from API check")) : !e2 && A && (A = false, P = false, D = null, w && console.log("[Sailfish] Function span tracking initialized as DISABLED from API check"));
|
|
441
441
|
}
|
|
442
442
|
function getFuncSpanHeader() {
|
|
443
443
|
if (!A) return null;
|
|
444
444
|
if (null !== D) {
|
|
445
|
-
if (Date.now() >= D) return A = false, D = null, clearGlobalFuncSpanState(),
|
|
445
|
+
if (Date.now() >= D) return A = false, D = null, clearGlobalFuncSpanState(), w && console.log("[Sailfish] Function span tracking expired on header check - disabling now"), null;
|
|
446
446
|
}
|
|
447
447
|
return { name: "X-Sf3-FunctionSpanCaptureOverride", value: "1-1-10-10-1-1.0-1-0-0" };
|
|
448
448
|
}
|
|
@@ -671,6 +671,20 @@ function initializeDomContentEvents(e2) {
|
|
|
671
671
|
sendEvent({ type: 24, data: { source: r }, timestamp: Date.now(), sessionId: e2, ...getUrlAndStoredUuids() });
|
|
672
672
|
});
|
|
673
673
|
}
|
|
674
|
+
async function initializePerformancePlugin(e2) {
|
|
675
|
+
var _a;
|
|
676
|
+
try {
|
|
677
|
+
const { getRecordPerformancePlugin: t2 } = await Promise.resolve().then(() => require("./rrweb-plugin-performance-record-Dekf6xUi.js"));
|
|
678
|
+
await yieldToMain();
|
|
679
|
+
const n2 = t2({ getPageVisitUuid: () => sessionStorage.getItem("pageVisitUUID") });
|
|
680
|
+
(_a = n2.observer) == null ? void 0 : _a.call(n2, (t3) => {
|
|
681
|
+
const i2 = t3;
|
|
682
|
+
sendEvent({ type: 28, timestamp: i2.timestamp, sessionId: e2, data: { plugin: n2.name, payload: i2 }, ...getUrlAndStoredUuids() });
|
|
683
|
+
}, window, n2.options);
|
|
684
|
+
} catch (e3) {
|
|
685
|
+
console.warn("[Sailfish] Performance plugin failed to initialize:", e3);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
674
688
|
async function initializeConsolePlugin(e2, n2) {
|
|
675
689
|
const { getRecordConsolePlugin: i2 } = await import("@sailfish-rrweb/rrweb-plugin-console-record");
|
|
676
690
|
await yieldToMain();
|
|
@@ -714,7 +728,7 @@ async function initializeRecording(e2, n2, i2, o2, s2, r2 = true, a2 = false, l2
|
|
|
714
728
|
}
|
|
715
729
|
const { record: n4 } = await import("@sailfish-rrweb/rrweb-record-only");
|
|
716
730
|
if (Q = n4, await yieldToMain(), l2) {
|
|
717
|
-
const { chunkedSnapshot: i3 } = await Promise.resolve().then(() => require("./chunkSerializer-
|
|
731
|
+
const { chunkedSnapshot: i3 } = await Promise.resolve().then(() => require("./chunkSerializer-jzbHv2wf.js")), o3 = n4.mirror;
|
|
718
732
|
let s3 = true;
|
|
719
733
|
const r3 = [];
|
|
720
734
|
n4({ emit(e3) {
|
|
@@ -1044,7 +1058,7 @@ function renderCustomMultiSelect(e2, t2, n2, i2, o2 = false) {
|
|
|
1044
1058
|
}
|
|
1045
1059
|
const he = { enabled: false, openModalExistingMode: { key: "e", requireCmdCtrl: false }, openModalCaptureNewMode: { key: "n", requireCmdCtrl: false }, closeModal: { key: "escape", requireCmdCtrl: false }, submitReport: { key: "enter", requireCmdCtrl: true }, startRecording: { key: "r", requireCmdCtrl: false }, stopRecording: { key: "escape", requireCmdCtrl: true } }, ye = { shortcuts: { ...he }, resolveSessionId: null, apiKey: null, backendApi: null, triageBaseUrl: "https://app.sailfishqa.com", deactivateIsolation: () => {
|
|
1046
1060
|
}, integrationData: null, showEngTicketFieldsDefault: false };
|
|
1047
|
-
let be = null,
|
|
1061
|
+
let be = null, we = false;
|
|
1048
1062
|
function setupCustomMultiSelectListeners(e2, t2) {
|
|
1049
1063
|
const n2 = document.getElementById(`${e2}-container`), i2 = document.getElementById(`${e2}-dropdown`);
|
|
1050
1064
|
if (!n2 || !i2) return;
|
|
@@ -1293,7 +1307,7 @@ function getSessionIdSafely() {
|
|
|
1293
1307
|
return ye.resolveSessionId();
|
|
1294
1308
|
}
|
|
1295
1309
|
function openReportIssueModal(e2) {
|
|
1296
|
-
me ? stopRecording() : (
|
|
1310
|
+
me ? stopRecording() : (we = (e2 == null ? void 0 : e2.showEngTicketFields) ?? ye.showEngTicketFieldsDefault, injectModalHTML(), be && document.body.appendChild(be));
|
|
1297
1311
|
}
|
|
1298
1312
|
function closeModal() {
|
|
1299
1313
|
ye.deactivateIsolation(), document.activeElement instanceof HTMLElement && document.activeElement.blur(), (be == null ? void 0 : be.parentNode) && be.parentNode.removeChild(be), be = null, me || (function resetState() {
|
|
@@ -1485,7 +1499,7 @@ function injectModalHTML(e2 = "lookback") {
|
|
|
1485
1499
|
Create an Issue
|
|
1486
1500
|
</label>
|
|
1487
1501
|
|
|
1488
|
-
<label id="sf-create-eng-ticket-label" style="display:${ye.integrationData &&
|
|
1502
|
+
<label id="sf-create-eng-ticket-label" style="display:${ye.integrationData && we ? "flex" : "none"}; align-items:center; gap:8px; font-size:14px; font-weight:500; cursor:pointer;">
|
|
1489
1503
|
<input type="checkbox" id="sf-create-eng-ticket-checkbox" ${ue.createEngTicket ? "checked" : ""}
|
|
1490
1504
|
style="width:16px; height:16px; accent-color:#295DBF; cursor:pointer;">
|
|
1491
1505
|
Create an Eng Ticket
|
|
@@ -1713,7 +1727,7 @@ function injectModalHTML(e2 = "lookback") {
|
|
|
1713
1727
|
const e4 = generateEngTicketFieldsHTML();
|
|
1714
1728
|
e4 && (t3.innerHTML = e4, initializeEngTicketForm(), bindEngTicketListeners(), updateFormWithIntegrationData(ue), renderDynamicFields(ue.engTicketProject, ue.engTicketIssueType));
|
|
1715
1729
|
}
|
|
1716
|
-
if (
|
|
1730
|
+
if (we) {
|
|
1717
1731
|
const e4 = document.getElementById("sf-create-eng-ticket-label");
|
|
1718
1732
|
e4 && (e4.style.display = "flex");
|
|
1719
1733
|
}
|
|
@@ -1910,7 +1924,7 @@ function showStatusModal(e2, t2, n2) {
|
|
|
1910
1924
|
function fadeCardAndRemove(e2, t2, n2 = 300) {
|
|
1911
1925
|
t2.style.opacity = "0", t2.addEventListener("transitionend", () => e2.remove(), { once: true }), setTimeout(() => e2.remove(), n2 + 100);
|
|
1912
1926
|
}
|
|
1913
|
-
const
|
|
1927
|
+
const Se = Object.freeze(Object.defineProperty({ __proto__: null, ReportIssueContext: ye, openReportIssueModal, setupIssueReporting: function setupIssueReporting(e2) {
|
|
1914
1928
|
ye.apiKey = e2.apiKey, ye.backendApi = e2.backendApi, ye.resolveSessionId = e2.getSessionId, ye.integrationData = e2.integrationData || null, ye.showEngTicketFieldsDefault = e2.showEngTicketFieldsInReportIssueModalDefault ?? false, e2.customBaseUrl && (ye.triageBaseUrl = e2.customBaseUrl), ye.shortcuts = (function mergeShortcutsConfig(e3) {
|
|
1915
1929
|
const t3 = { ...he };
|
|
1916
1930
|
if (!e3) return t3;
|
|
@@ -2094,8 +2108,8 @@ function setupFetchInterceptor(e2 = [], t2 = { captureStreamingResponseBody: tru
|
|
|
2094
2108
|
delete h2[n];
|
|
2095
2109
|
const b2 = getFuncSpanHeader();
|
|
2096
2110
|
b2 && delete h2[b2.name];
|
|
2097
|
-
const
|
|
2098
|
-
h2[n] =
|
|
2111
|
+
const w2 = `${c3}/${p2.page_visit_uuid}/${u3}`;
|
|
2112
|
+
h2[n] = w2, b2 && (h2[b2.name] = b2.value);
|
|
2099
2113
|
maskAuthorizationHeader(h2);
|
|
2100
2114
|
try {
|
|
2101
2115
|
let b3 = await (async function injectHeader(e5, t3, i5, o5, s4, r4, a3) {
|
|
@@ -2110,7 +2124,7 @@ function setupFetchInterceptor(e2 = [], t2 = { captureStreamingResponseBody: tru
|
|
|
2110
2124
|
const c4 = { ...o5 }, d4 = new Headers(o5.headers || {});
|
|
2111
2125
|
return d4.set(n, `${s4}/${r4}/${a3}`), l3 && (d4.set(l3.name, l3.value), ve && console.log("[Sailfish] Added funcspan header to HTTP fetch:", { url: "string" == typeof i5 ? i5 : i5.href, header: l3.name })), c4.headers = d4, await e5.call(t3, i5, c4);
|
|
2112
2126
|
}
|
|
2113
|
-
})(e4, i4, s3, r3, c3, p2.page_visit_uuid, u3),
|
|
2127
|
+
})(e4, i4, s3, r3, c3, p2.page_visit_uuid, u3), w3 = false;
|
|
2114
2128
|
Te.includes(b3.status) && (ve && console.log("Perform retry as status was fail:", b3), delete h2[n], b3 = await (async function retryWithoutPropagateHeaders(e5, t3, i5, o5) {
|
|
2115
2129
|
try {
|
|
2116
2130
|
let o6 = i5[0], s4 = i5[1] || {};
|
|
@@ -2129,8 +2143,8 @@ function setupFetchInterceptor(e2 = [], t2 = { captureStreamingResponseBody: tru
|
|
|
2129
2143
|
} catch (e6) {
|
|
2130
2144
|
throw ve && console.log(`Retry without ${n} for ${o5} also failed:`, e6), e6;
|
|
2131
2145
|
}
|
|
2132
|
-
})(e4, i4, o4, d3),
|
|
2133
|
-
const
|
|
2146
|
+
})(e4, i4, o4, d3), w3 = true);
|
|
2147
|
+
const S2 = Date.now(), v2 = b3.status, k2 = b3.ok, x2 = k2 ? "" : `Request Error: ${b3.statusText}`;
|
|
2134
2148
|
let I2 = null;
|
|
2135
2149
|
try {
|
|
2136
2150
|
I2 = {}, b3.headers.forEach((e5, t3) => {
|
|
@@ -2139,7 +2153,7 @@ function setupFetchInterceptor(e2 = [], t2 = { captureStreamingResponseBody: tru
|
|
|
2139
2153
|
} catch (e5) {
|
|
2140
2154
|
ve && console.warn("[Sailfish] Failed to capture response headers:", e5), I2 = null;
|
|
2141
2155
|
}
|
|
2142
|
-
const T2 = { type: 27, timestamp:
|
|
2156
|
+
const T2 = { type: 27, timestamp: S2, sessionId: c3, data: { request_id: u3, session_id: c3, timestamp_start: g2, timestamp_end: S2, response_code: v2, success: k2, error: x2, method: f2, url: d3, retry_without_trace_id: w3, request_headers: h2, request_body: m2, response_headers: I2, response_body: null }, ...p2 }, sendEventWithBody = (e5) => {
|
|
2143
2157
|
T2.data.response_body = e5, y2 ? y2.text().then((e6) => {
|
|
2144
2158
|
T2.data.request_body = e6, sendEvent(T2);
|
|
2145
2159
|
}, () => {
|
|
@@ -2227,9 +2241,9 @@ function setupFetchInterceptor(e2 = [], t2 = { captureStreamingResponseBody: tru
|
|
|
2227
2241
|
})(e3, i3, o3, d2, u2, s2, c2);
|
|
2228
2242
|
} });
|
|
2229
2243
|
}
|
|
2230
|
-
async function startRecording({ apiKey: e2, backendApi: t2 = "https://api-service.sailfishqa.com", domainsToPropagateHeaderTo: i2 = ["*"], domainsToNotPropagateHeaderTo: o2 = [], serviceVersion: s2, serviceIdentifier: r2, gitSha: a2, serviceAdditionalMetadata: l2, enableIpTracking: c2, captureStreamingResponseBody: d2 = true, captureResponseBodyMaxMb: u2 = 10, captureStreamPrefixKb: p2 = 64, captureStreamTimeoutMs: f2 = 1e4, enableFiberTracking: m2 = false, deferRecording: h2, deferRecordingStart: y2, chunkSnapshot: b2, useWsWorker: S2 = true, maskTextClass:
|
|
2244
|
+
async function startRecording({ apiKey: e2, backendApi: t2 = "https://api-service.sailfishqa.com", domainsToPropagateHeaderTo: i2 = ["*"], domainsToNotPropagateHeaderTo: o2 = [], serviceVersion: s2, serviceIdentifier: r2, gitSha: a2, serviceAdditionalMetadata: l2, enableIpTracking: c2, captureStreamingResponseBody: d2 = true, captureResponseBodyMaxMb: u2 = 10, captureStreamPrefixKb: p2 = 64, captureStreamTimeoutMs: f2 = 1e4, enableFiberTracking: m2 = false, deferRecording: h2, deferRecordingStart: y2, chunkSnapshot: b2, useWsWorker: w2 = true, capturePerformanceMetrics: S2 = true, maskTextClass: v2, library: k2, headlessRecording: x2 = false }) {
|
|
2231
2245
|
var _a, _b;
|
|
2232
|
-
if ((function isHeadlessOrLighthouse() {
|
|
2246
|
+
if (!x2 && (function isHeadlessOrLighthouse() {
|
|
2233
2247
|
try {
|
|
2234
2248
|
if ("undefined" == typeof navigator) return false;
|
|
2235
2249
|
const e3 = navigator;
|
|
@@ -2240,10 +2254,10 @@ async function startRecording({ apiKey: e2, backendApi: t2 = "https://api-servic
|
|
|
2240
2254
|
return false;
|
|
2241
2255
|
}
|
|
2242
2256
|
})()) return;
|
|
2243
|
-
const
|
|
2244
|
-
if (
|
|
2245
|
-
const
|
|
2246
|
-
sessionStorage.getItem("pageVisitUUID") || (sessionStorage.setItem("pageVisitUUID", uuidv4()), invalidateUrlCache()),
|
|
2257
|
+
const I2 = h2 ?? y2 ?? true, T2 = getOrSetSessionId(), E2 = window.__sailfish_recorder || (window.__sailfish_recorder = {});
|
|
2258
|
+
if (E2.sessionId = T2, E2.apiKey = e2, E2.backendApi = t2, E2.serviceAdditionalMetadata = l2, E2.initialized && E2.sessionId === T2 && E2.ws && 1 === E2.ws.readyState) return void trackDomainChangesOnce();
|
|
2259
|
+
const C2 = { captureStreamingResponseBody: d2, captureResponseBodyMaxMb: u2, captureStreamPrefixKb: p2, captureStreamTimeoutMs: f2 };
|
|
2260
|
+
sessionStorage.getItem("pageVisitUUID") || (sessionStorage.setItem("pageVisitUUID", uuidv4()), invalidateUrlCache()), E2.xhrPatched || (!(function setupXMLHttpRequestInterceptor(e3 = [], t3 = { captureStreamingResponseBody: true, captureResponseBodyMaxMb: 10, captureStreamPrefixKb: 64, captureStreamTimeoutMs: 1e4 }, i3 = []) {
|
|
2247
2261
|
const o3 = XMLHttpRequest.prototype.open, s3 = XMLHttpRequest.prototype.send, r3 = XMLHttpRequest.prototype.setRequestHeader, a3 = getOrSetSessionId(), l3 = createSkipHeadersPropagationChecker(e3, i3);
|
|
2248
2262
|
XMLHttpRequest.prototype.setRequestHeader = function(e4, t4) {
|
|
2249
2263
|
return this._capturedRequestHeaders || (this._capturedRequestHeaders = {}), this._capturedRequestHeaders[e4] = t4, r3.call(this, e4, t4);
|
|
@@ -2308,22 +2322,22 @@ async function startRecording({ apiKey: e2, backendApi: t2 = "https://api-servic
|
|
|
2308
2322
|
emitFinished(false, e5, t4);
|
|
2309
2323
|
}, { once: true }), s3.apply(this, e4);
|
|
2310
2324
|
};
|
|
2311
|
-
})(o2,
|
|
2325
|
+
})(o2, C2, i2), E2.xhrPatched = true), E2.fetchPatched || (setupFetchInterceptor(o2, C2, i2), E2.fetchPatched = true), await yieldToMain(), E2.domEventsInit || (initializeDomContentEvents(T2), E2.domEventsInit = true), await yieldToMain(), E2.consoleInit || (initializeConsolePlugin(Le, T2), E2.consoleInit = true), await yieldToMain(), E2.errorInit || (!(function initializeErrorInterceptor() {
|
|
2312
2326
|
window.addEventListener("error", (e3) => {
|
|
2313
2327
|
captureError(e3.error || e3.message);
|
|
2314
2328
|
}), window.addEventListener("unhandledrejection", (e3) => {
|
|
2315
2329
|
captureError(e3.reason, true);
|
|
2316
2330
|
});
|
|
2317
|
-
})(),
|
|
2331
|
+
})(), E2.errorInit = true), await yieldToMain(), !E2.perfInit && S2 && (initializePerformancePlugin(T2), E2.perfInit = true), await yieldToMain(), _ensureModuleSideEffects(), (function storeCredentialsAndConnection({ apiKey: e3, backendApi: t3 }) {
|
|
2318
2332
|
g && (sessionStorage.setItem("sailfishApiKey", e3), sessionStorage.setItem("sailfishBackendApi", t3));
|
|
2319
|
-
})({ apiKey: e2, backendApi: t2 }), !isFunctionSpanTrackingEnabled() ||
|
|
2333
|
+
})({ apiKey: e2, backendApi: t2 }), !isFunctionSpanTrackingEnabled() || E2.ws && 1 === E2.ws.readyState || fetchFunctionSpanTrackingEnabled(e2, t2).then((e3) => {
|
|
2320
2334
|
var _a2;
|
|
2321
2335
|
((_a2 = e3.data) == null ? void 0 : _a2.isFunctionSpanTrackingEnabledFromApiKey) ?? false ? ve && console.log("[Sailfish] Function span tracking state validated with backend: ACTIVE") : (clearStaleFuncSpanState(), ve && console.log("[Sailfish] Cleared stale function span tracking state - backend validation shows tracking is not active"));
|
|
2322
2336
|
}).catch((e3) => {
|
|
2323
2337
|
ve && console.warn("[Sailfish] Failed to validate function span tracking status with backend:", e3);
|
|
2324
|
-
}),
|
|
2338
|
+
}), E2.sentDoNotPropagateOnce || (sendDomainsToNotPropagateHeaderTo(e2, [...o2, ...Ie], t2).catch((e3) => console.error("Failed to send domains to not propagate header to:", e3)), E2.sentDoNotPropagateOnce = true), (async function gatherAndCacheDeviceInfo() {
|
|
2325
2339
|
sendMessage({ type: "deviceInfo", data: { deviceInfo: { language: navigator.language, userAgent: navigator.userAgent } } });
|
|
2326
|
-
})(), c2 && fetchAndSendIp(
|
|
2340
|
+
})(), c2 && fetchAndSendIp(T2);
|
|
2327
2341
|
try {
|
|
2328
2342
|
const n2 = a2 ?? (function readGitSha() {
|
|
2329
2343
|
var _a2;
|
|
@@ -2342,7 +2356,7 @@ async function startRecording({ apiKey: e2, backendApi: t2 = "https://api-servic
|
|
|
2342
2356
|
if ("string" == typeof e3 && e3) return e3;
|
|
2343
2357
|
} catch {
|
|
2344
2358
|
}
|
|
2345
|
-
})(), i3 = r2 ?? "", o3 = s2 ?? "", c3 =
|
|
2359
|
+
})(), i3 = r2 ?? "", o3 = s2 ?? "", c3 = k2 ?? "JS/TS", d3 = (function getMapUuidFromWindow() {
|
|
2346
2360
|
try {
|
|
2347
2361
|
const e3 = window;
|
|
2348
2362
|
if (e3 && "string" == typeof e3.sfMapUuid && e3.sfMapUuid) return e3.sfMapUuid;
|
|
@@ -2362,15 +2376,15 @@ async function startRecording({ apiKey: e2, backendApi: t2 = "https://api-servic
|
|
|
2362
2376
|
return { framework: i4[0] ?? null, additionalFrameworks: i4.slice(1), serviceRole: "frontend" };
|
|
2363
2377
|
})(), f3 = { ...u3, serviceRole: p3.serviceRole, ...null !== p3.framework && { framework: p3.framework }, ...p3.additionalFrameworks.length > 0 && { additionalFrameworks: p3.additionalFrameworks } };
|
|
2364
2378
|
await yieldToMain();
|
|
2365
|
-
const [g2, h3] = await Promise.all([fetchCaptureSettings(e2, t2), startRecordingSession(e2,
|
|
2366
|
-
if (
|
|
2379
|
+
const [g2, h3] = await Promise.all([fetchCaptureSettings(e2, t2), startRecordingSession(e2, T2, t2, i3, o3, d3, n2, c3, f3)]), y3 = { ...Fe, ...(_a = g2.data) == null ? void 0 : _a.captureSettingsFromApiKey, enableFiberTracking: m2, ...void 0 !== v2 ? { maskTextClass: v2 } : {} };
|
|
2380
|
+
if (E2.ws && 1 === E2.ws.readyState) return;
|
|
2367
2381
|
if ((_b = h3.data) == null ? void 0 : _b.startRecordingSession) {
|
|
2368
2382
|
const n3 = (l2 == null ? void 0 : l2.env) || (l2 == null ? void 0 : l2.environment);
|
|
2369
2383
|
await yieldToMain();
|
|
2370
|
-
const i4 = await initializeRecording(y3, t2, e2,
|
|
2371
|
-
|
|
2384
|
+
const i4 = await initializeRecording(y3, t2, e2, T2, n3, I2, w2, b2 ?? false);
|
|
2385
|
+
E2.ws = i4, E2.initialized = true, trackDomainChangesOnce(), E2.sentMapUuidOnce || (!(function sendMapUuidIfAvailable(e3 = "", t3 = "") {
|
|
2372
2386
|
window.sfMapUuid && sendMessage({ type: "mapUuid", data: { mapUuid: window.sfMapUuid, serviceIdentifier: e3, serviceVersion: t3 } });
|
|
2373
|
-
})(r2, s2),
|
|
2387
|
+
})(r2, s2), E2.sentMapUuidOnce = true);
|
|
2374
2388
|
} else console.error("Failed to start recording session:", h3.errors || h3);
|
|
2375
2389
|
} catch (e3) {
|
|
2376
2390
|
console.error("Error starting recording:", e3);
|
|
@@ -2388,7 +2402,7 @@ exports.DEFAULT_CAPTURE_SETTINGS = Fe, exports.DEFAULT_CONSOLE_RECORDING_SETTING
|
|
|
2388
2402
|
return clearPageVisitDataFromSessionStorage(), t2.initialized && t2.sessionId === n2 && t2.ws && 1 === t2.ws.readyState ? void 0 : (t2.initPromise || (t2.initPromise = (async () => {
|
|
2389
2403
|
try {
|
|
2390
2404
|
if (t2.hasLoggedInitOnce || (console.log("Initializing Sailfish Recorder (first run) …"), t2.hasLoggedInitOnce = true), await startRecording(e2), !t2.issueReportingInit) {
|
|
2391
|
-
const n3 = e2.backendApi ?? "https://api-service.sailfishqa.com", [{ setupIssueReporting: i2 }, { fetchIntegrationData: o2, getIntegrationData: s2 }] = await Promise.all([Promise.resolve().then(() =>
|
|
2405
|
+
const n3 = e2.backendApi ?? "https://api-service.sailfishqa.com", [{ setupIssueReporting: i2 }, { fetchIntegrationData: o2, getIntegrationData: s2 }] = await Promise.all([Promise.resolve().then(() => Se), Promise.resolve().then(() => le)]);
|
|
2392
2406
|
let r2 = null;
|
|
2393
2407
|
try {
|
|
2394
2408
|
await o2(e2.apiKey, n3), r2 = s2();
|
|
@@ -2403,7 +2417,7 @@ exports.DEFAULT_CAPTURE_SETTINGS = Fe, exports.DEFAULT_CONSOLE_RECORDING_SETTING
|
|
|
2403
2417
|
})().finally(() => {
|
|
2404
2418
|
delete t2.initPromise;
|
|
2405
2419
|
})), t2.initPromise);
|
|
2406
|
-
}, exports.initializeConsolePlugin = initializeConsolePlugin, exports.initializeDomContentEvents = initializeDomContentEvents, exports.initializeFunctionSpanTrackingFromApi = initializeFunctionSpanTrackingFromApi, exports.initializeRecording = initializeRecording, exports.initializeWebSocket = initializeWebSocket, exports.invalidateUrlCache = invalidateUrlCache, exports.isFunctionSpanTrackingEnabled = isFunctionSpanTrackingEnabled, exports.matchUrlWithWildcard = function matchUrlWithWildcard(e2, t2) {
|
|
2420
|
+
}, exports.initializeConsolePlugin = initializeConsolePlugin, exports.initializeDomContentEvents = initializeDomContentEvents, exports.initializeFunctionSpanTrackingFromApi = initializeFunctionSpanTrackingFromApi, exports.initializePerformancePlugin = initializePerformancePlugin, exports.initializeRecording = initializeRecording, exports.initializeWebSocket = initializeWebSocket, exports.invalidateUrlCache = invalidateUrlCache, exports.isFunctionSpanTrackingEnabled = isFunctionSpanTrackingEnabled, exports.matchUrlWithWildcard = function matchUrlWithWildcard(e2, t2) {
|
|
2407
2421
|
let n2, i2;
|
|
2408
2422
|
if ("string" == typeof e2 ? n2 = e2 : "undefined" != typeof URL && e2 instanceof URL ? n2 = e2.href : "undefined" != typeof Request && e2 instanceof Request ? n2 = e2.url : null != e2 && "function" == typeof e2.toString && (n2 = e2.toString()), !n2) return false;
|
|
2409
2423
|
try {
|
|
Binary file
|
|
Binary file
|