@safaricom-mxl/web-sdk 0.0.19 → 0.0.21
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/DATA_EXPORT.md +11 -8
- package/dist/exporters/MXLLogExporter/MXLLogExporter.cjs +2 -2
- package/dist/exporters/MXLLogExporter/MXLLogExporter.cjs.map +1 -1
- package/dist/exporters/MXLLogExporter/MXLLogExporter.d.cts +1 -1
- package/dist/exporters/MXLLogExporter/MXLLogExporter.d.cts.map +1 -1
- package/dist/exporters/MXLLogExporter/MXLLogExporter.d.ts +1 -1
- package/dist/exporters/MXLLogExporter/MXLLogExporter.d.ts.map +1 -1
- package/dist/exporters/MXLLogExporter/MXLLogExporter.js +2 -2
- package/dist/exporters/MXLLogExporter/MXLLogExporter.js.map +1 -1
- package/dist/exporters/MXLLogExporter/types.d.cts +1 -1
- package/dist/exporters/MXLLogExporter/types.d.cts.map +1 -1
- package/dist/exporters/MXLLogExporter/types.d.ts +1 -1
- package/dist/exporters/MXLLogExporter/types.d.ts.map +1 -1
- package/dist/exporters/MXLLogExporter/utils.cjs +1 -1
- package/dist/exporters/MXLLogExporter/utils.cjs.map +1 -1
- package/dist/exporters/MXLLogExporter/utils.d.cts +1 -1
- package/dist/exporters/MXLLogExporter/utils.d.cts.map +1 -1
- package/dist/exporters/MXLLogExporter/utils.d.ts +1 -1
- package/dist/exporters/MXLLogExporter/utils.d.ts.map +1 -1
- package/dist/exporters/MXLLogExporter/utils.js +2 -2
- package/dist/exporters/MXLLogExporter/utils.js.map +1 -1
- package/dist/exporters/MXLTraceExporter/MXLTraceExporter.cjs +2 -2
- package/dist/exporters/MXLTraceExporter/MXLTraceExporter.cjs.map +1 -1
- package/dist/exporters/MXLTraceExporter/MXLTraceExporter.d.cts +1 -1
- package/dist/exporters/MXLTraceExporter/MXLTraceExporter.d.cts.map +1 -1
- package/dist/exporters/MXLTraceExporter/MXLTraceExporter.d.ts +1 -1
- package/dist/exporters/MXLTraceExporter/MXLTraceExporter.d.ts.map +1 -1
- package/dist/exporters/MXLTraceExporter/MXLTraceExporter.js +2 -2
- package/dist/exporters/MXLTraceExporter/MXLTraceExporter.js.map +1 -1
- package/dist/exporters/MXLTraceExporter/types.d.cts +1 -1
- package/dist/exporters/MXLTraceExporter/types.d.cts.map +1 -1
- package/dist/exporters/MXLTraceExporter/types.d.ts +1 -1
- package/dist/exporters/MXLTraceExporter/types.d.ts.map +1 -1
- package/dist/exporters/MXLTraceExporter/utils.cjs +1 -1
- package/dist/exporters/MXLTraceExporter/utils.cjs.map +1 -1
- package/dist/exporters/MXLTraceExporter/utils.d.cts +1 -1
- package/dist/exporters/MXLTraceExporter/utils.d.cts.map +1 -1
- package/dist/exporters/MXLTraceExporter/utils.d.ts +1 -1
- package/dist/exporters/MXLTraceExporter/utils.d.ts.map +1 -1
- package/dist/exporters/MXLTraceExporter/utils.js +2 -2
- package/dist/exporters/MXLTraceExporter/utils.js.map +1 -1
- package/dist/exporters/utils.cjs +2 -2
- package/dist/exporters/utils.cjs.map +1 -1
- package/dist/exporters/utils.d.cts +2 -2
- package/dist/exporters/utils.d.cts.map +1 -1
- package/dist/exporters/utils.d.ts +2 -2
- package/dist/exporters/utils.d.ts.map +1 -1
- package/dist/exporters/utils.js +2 -2
- package/dist/exporters/utils.js.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/instrumentations/replay/ReplayInstrumentation/ReplayInstrumentation.cjs +1 -0
- package/dist/instrumentations/replay/ReplayInstrumentation/ReplayInstrumentation.cjs.map +1 -1
- package/dist/instrumentations/replay/ReplayInstrumentation/ReplayInstrumentation.d.cts.map +1 -1
- package/dist/instrumentations/replay/ReplayInstrumentation/ReplayInstrumentation.d.ts.map +1 -1
- package/dist/instrumentations/replay/ReplayInstrumentation/ReplayInstrumentation.js +1 -0
- package/dist/instrumentations/replay/ReplayInstrumentation/ReplayInstrumentation.js.map +1 -1
- package/dist/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.cjs +32 -6
- package/dist/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.cjs.map +1 -1
- package/dist/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.d.cts +1 -2
- package/dist/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.d.cts.map +1 -1
- package/dist/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.d.ts +1 -2
- package/dist/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.d.ts.map +1 -1
- package/dist/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.js +32 -6
- package/dist/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.js.map +1 -1
- package/dist/instrumentations/replay/session-recording/SessionRecording.cjs +1 -0
- package/dist/instrumentations/replay/session-recording/SessionRecording.cjs.map +1 -1
- package/dist/instrumentations/replay/session-recording/SessionRecording.js +1 -0
- package/dist/instrumentations/replay/session-recording/SessionRecording.js.map +1 -1
- package/dist/instrumentations/replay/session-recording/config.cjs.map +1 -1
- package/dist/instrumentations/replay/session-recording/config.d.cts +1 -1
- package/dist/instrumentations/replay/session-recording/config.d.cts.map +1 -1
- package/dist/instrumentations/replay/session-recording/config.d.ts +1 -1
- package/dist/instrumentations/replay/session-recording/config.d.ts.map +1 -1
- package/dist/instrumentations/replay/session-recording/config.js.map +1 -1
- package/dist/instrumentations/replay/transport/replayTransport.cjs +31 -11
- package/dist/instrumentations/replay/transport/replayTransport.cjs.map +1 -1
- package/dist/instrumentations/replay/transport/replayTransport.d.cts +3 -2
- package/dist/instrumentations/replay/transport/replayTransport.d.cts.map +1 -1
- package/dist/instrumentations/replay/transport/replayTransport.d.ts +3 -2
- package/dist/instrumentations/replay/transport/replayTransport.d.ts.map +1 -1
- package/dist/instrumentations/replay/transport/replayTransport.js +31 -11
- package/dist/instrumentations/replay/transport/replayTransport.js.map +1 -1
- package/dist/instrumentations/replay/transport/types.d.cts +3 -1
- package/dist/instrumentations/replay/transport/types.d.cts.map +1 -1
- package/dist/instrumentations/replay/transport/types.d.ts +3 -1
- package/dist/instrumentations/replay/transport/types.d.ts.map +1 -1
- package/dist/managers/MXLConfigManager/MXLDynamicConfigManager.cjs +19 -11
- package/dist/managers/MXLConfigManager/MXLDynamicConfigManager.cjs.map +1 -1
- package/dist/managers/MXLConfigManager/MXLDynamicConfigManager.d.cts +3 -3
- package/dist/managers/MXLConfigManager/MXLDynamicConfigManager.d.cts.map +1 -1
- package/dist/managers/MXLConfigManager/MXLDynamicConfigManager.d.ts +3 -3
- package/dist/managers/MXLConfigManager/MXLDynamicConfigManager.d.ts.map +1 -1
- package/dist/managers/MXLConfigManager/MXLDynamicConfigManager.js +19 -11
- package/dist/managers/MXLConfigManager/MXLDynamicConfigManager.js.map +1 -1
- package/dist/managers/MXLConfigManager/resolveEffectiveReplayConfig.cjs +28 -0
- package/dist/managers/MXLConfigManager/resolveEffectiveReplayConfig.cjs.map +1 -0
- package/dist/managers/MXLConfigManager/resolveEffectiveReplayConfig.d.cts +23 -0
- package/dist/managers/MXLConfigManager/resolveEffectiveReplayConfig.d.cts.map +1 -0
- package/dist/managers/MXLConfigManager/resolveEffectiveReplayConfig.d.ts +23 -0
- package/dist/managers/MXLConfigManager/resolveEffectiveReplayConfig.d.ts.map +1 -0
- package/dist/managers/MXLConfigManager/resolveEffectiveReplayConfig.js +27 -0
- package/dist/managers/MXLConfigManager/resolveEffectiveReplayConfig.js.map +1 -0
- package/dist/managers/MXLConfigManager/types.d.cts +16 -6
- package/dist/managers/MXLConfigManager/types.d.cts.map +1 -1
- package/dist/managers/MXLConfigManager/types.d.ts +16 -6
- package/dist/managers/MXLConfigManager/types.d.ts.map +1 -1
- package/dist/managers/MXLConfigManager/utils.cjs +66 -1
- package/dist/managers/MXLConfigManager/utils.cjs.map +1 -1
- package/dist/managers/MXLConfigManager/utils.d.cts +10 -3
- package/dist/managers/MXLConfigManager/utils.d.cts.map +1 -1
- package/dist/managers/MXLConfigManager/utils.d.ts +10 -3
- package/dist/managers/MXLConfigManager/utils.d.ts.map +1 -1
- package/dist/managers/MXLConfigManager/utils.js +64 -2
- package/dist/managers/MXLConfigManager/utils.js.map +1 -1
- package/dist/managers/MXLSDKFeaturesManager/MXLSDKFeaturesManager.cjs +8 -0
- package/dist/managers/MXLSDKFeaturesManager/MXLSDKFeaturesManager.cjs.map +1 -1
- package/dist/managers/MXLSDKFeaturesManager/MXLSDKFeaturesManager.d.cts +2 -0
- package/dist/managers/MXLSDKFeaturesManager/MXLSDKFeaturesManager.d.cts.map +1 -1
- package/dist/managers/MXLSDKFeaturesManager/MXLSDKFeaturesManager.d.ts +2 -0
- package/dist/managers/MXLSDKFeaturesManager/MXLSDKFeaturesManager.d.ts.map +1 -1
- package/dist/managers/MXLSDKFeaturesManager/MXLSDKFeaturesManager.js +8 -0
- package/dist/managers/MXLSDKFeaturesManager/MXLSDKFeaturesManager.js.map +1 -1
- package/dist/managers/MXLSDKFeaturesManager/types.d.cts +2 -0
- package/dist/managers/MXLSDKFeaturesManager/types.d.cts.map +1 -1
- package/dist/managers/MXLSDKFeaturesManager/types.d.ts +2 -0
- package/dist/managers/MXLSDKFeaturesManager/types.d.ts.map +1 -1
- package/dist/mxl-web-sdk.js +2 -2
- package/dist/mxl-web-sdk.js.map +1 -1
- package/dist/processors/MXLSessionPartBatchedSpanProcessor/MXLSessionPartBatchedSpanProcessor.cjs +10 -1
- package/dist/processors/MXLSessionPartBatchedSpanProcessor/MXLSessionPartBatchedSpanProcessor.cjs.map +1 -1
- package/dist/processors/MXLSessionPartBatchedSpanProcessor/MXLSessionPartBatchedSpanProcessor.d.cts +3 -0
- package/dist/processors/MXLSessionPartBatchedSpanProcessor/MXLSessionPartBatchedSpanProcessor.d.cts.map +1 -1
- package/dist/processors/MXLSessionPartBatchedSpanProcessor/MXLSessionPartBatchedSpanProcessor.d.ts +3 -0
- package/dist/processors/MXLSessionPartBatchedSpanProcessor/MXLSessionPartBatchedSpanProcessor.d.ts.map +1 -1
- package/dist/processors/MXLSessionPartBatchedSpanProcessor/MXLSessionPartBatchedSpanProcessor.js +10 -1
- package/dist/processors/MXLSessionPartBatchedSpanProcessor/MXLSessionPartBatchedSpanProcessor.js.map +1 -1
- package/dist/processors/MXLSessionPartBatchedSpanProcessor/types.d.cts +1 -0
- package/dist/processors/MXLSessionPartBatchedSpanProcessor/types.d.cts.map +1 -1
- package/dist/processors/MXLSessionPartBatchedSpanProcessor/types.d.ts +1 -0
- package/dist/processors/MXLSessionPartBatchedSpanProcessor/types.d.ts.map +1 -1
- package/dist/resources/sdkConstants.cjs +1 -1
- package/dist/resources/sdkConstants.cjs.map +1 -1
- package/dist/resources/sdkConstants.d.cts +1 -1
- package/dist/resources/sdkConstants.d.ts +1 -1
- package/dist/resources/sdkConstants.js +1 -1
- package/dist/resources/sdkConstants.js.map +1 -1
- package/dist/sdk/initSDK.cjs +20 -12
- package/dist/sdk/initSDK.cjs.map +1 -1
- package/dist/sdk/initSDK.d.cts +3 -2
- package/dist/sdk/initSDK.d.cts.map +1 -1
- package/dist/sdk/initSDK.d.ts +3 -2
- package/dist/sdk/initSDK.d.ts.map +1 -1
- package/dist/sdk/initSDK.js +20 -12
- package/dist/sdk/initSDK.js.map +1 -1
- package/dist/sdk/types.d.cts +29 -7
- package/dist/sdk/types.d.cts.map +1 -1
- package/dist/sdk/types.d.ts +29 -7
- package/dist/sdk/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,25 +1,51 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
//#region src/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.ts
|
|
3
|
+
const RRWEB_URL = "https://unpkg.com/rrweb@2.0.0-alpha.20/dist/rrweb.umd.cjs";
|
|
3
4
|
let rrwebModulePromise;
|
|
4
5
|
let rrwebModuleLoaderOverride;
|
|
6
|
+
let rrwebScriptUrl = RRWEB_URL;
|
|
7
|
+
function setRrwebScriptUrl(url) {
|
|
8
|
+
rrwebScriptUrl = url;
|
|
9
|
+
rrwebModulePromise = void 0;
|
|
10
|
+
}
|
|
11
|
+
function loadRrwebScript(src) {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const s = document.createElement("script");
|
|
14
|
+
s.src = src;
|
|
15
|
+
s.async = true;
|
|
16
|
+
s.onload = () => resolve();
|
|
17
|
+
s.onerror = reject;
|
|
18
|
+
document.head.appendChild(s);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
async function loadRrwebFromScript() {
|
|
22
|
+
if (typeof window === "undefined") throw new Error("no browser");
|
|
23
|
+
if (window.rrweb) return window.rrweb;
|
|
24
|
+
await loadRrwebScript(rrwebScriptUrl);
|
|
25
|
+
if (!window.rrweb) throw new Error("no rrweb");
|
|
26
|
+
return window.rrweb;
|
|
27
|
+
}
|
|
28
|
+
async function loadRrwebModuleImpl() {
|
|
29
|
+
try {
|
|
30
|
+
return await import("rrweb");
|
|
31
|
+
} catch {
|
|
32
|
+
return loadRrwebFromScript();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
5
35
|
function loadRrwebModule() {
|
|
6
36
|
if (rrwebModuleLoaderOverride) return rrwebModuleLoaderOverride();
|
|
7
|
-
if (rrwebModulePromise === void 0) rrwebModulePromise =
|
|
8
|
-
/* @vite-ignore */
|
|
9
|
-
"rrweb"
|
|
10
|
-
);
|
|
37
|
+
if (rrwebModulePromise === void 0) rrwebModulePromise = loadRrwebModuleImpl();
|
|
11
38
|
return rrwebModulePromise;
|
|
12
39
|
}
|
|
13
40
|
function resetRrwebModuleCacheForTests() {
|
|
14
41
|
rrwebModulePromise = void 0;
|
|
15
42
|
rrwebModuleLoaderOverride = void 0;
|
|
43
|
+
rrwebScriptUrl = RRWEB_URL;
|
|
16
44
|
}
|
|
17
45
|
function setRrwebModuleLoaderForTests(loader) {
|
|
18
46
|
rrwebModuleLoaderOverride = loader;
|
|
19
47
|
rrwebModulePromise = void 0;
|
|
20
48
|
}
|
|
21
|
-
/** No-op for ESM/CJS builds that lazy-load rrweb via dynamic import. */
|
|
22
|
-
function setRrwebScriptUrl(_url) {}
|
|
23
49
|
//#endregion
|
|
24
50
|
exports.loadRrwebModule = loadRrwebModule;
|
|
25
51
|
exports.resetRrwebModuleCacheForTests = resetRrwebModuleCacheForTests;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadRrwebModule.esm.cjs","names":[],"sources":["../../../../src/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.ts"],"sourcesContent":["import type { RrwebModule } from './types.ts';\n\nlet rrwebModulePromise: Promise<RrwebModule> | undefined;\nlet rrwebModuleLoaderOverride: (() => Promise<RrwebModule>) | undefined;\n\nexport function loadRrwebModule(): Promise<RrwebModule> {\n if (rrwebModuleLoaderOverride) {\n return rrwebModuleLoaderOverride();\n }\n\n if (rrwebModulePromise === undefined) {\n rrwebModulePromise =
|
|
1
|
+
{"version":3,"file":"loadRrwebModule.esm.cjs","names":[],"sources":["../../../../src/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.ts"],"sourcesContent":["import type { RrwebModule } from './types.ts';\n\nconst RRWEB_URL =\n 'https://unpkg.com/rrweb@2.0.0-alpha.20/dist/rrweb.umd.cjs';\n\nlet rrwebModulePromise: Promise<RrwebModule> | undefined;\nlet rrwebModuleLoaderOverride: (() => Promise<RrwebModule>) | undefined;\nlet rrwebScriptUrl = RRWEB_URL;\n\nexport function setRrwebScriptUrl(url: string): void {\n rrwebScriptUrl = url;\n rrwebModulePromise = undefined;\n}\n\nfunction loadRrwebScript(src: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const s = document.createElement('script');\n s.src = src;\n s.async = true;\n s.onload = () => resolve();\n s.onerror = reject;\n document.head.appendChild(s);\n });\n}\n\nasync function loadRrwebFromScript(): Promise<RrwebModule> {\n if (typeof window === 'undefined') {\n throw new Error('no browser');\n }\n\n if (window.rrweb) {\n return window.rrweb;\n }\n\n await loadRrwebScript(rrwebScriptUrl);\n\n if (!window.rrweb) {\n throw new Error('no rrweb');\n }\n\n return window.rrweb;\n}\n\nasync function loadRrwebModuleImpl(): Promise<RrwebModule> {\n try {\n return await import('rrweb');\n } catch {\n return loadRrwebFromScript();\n }\n}\n\nexport function loadRrwebModule(): Promise<RrwebModule> {\n if (rrwebModuleLoaderOverride) {\n return rrwebModuleLoaderOverride();\n }\n\n if (rrwebModulePromise === undefined) {\n rrwebModulePromise = loadRrwebModuleImpl();\n }\n return rrwebModulePromise;\n}\n\nexport function resetRrwebModuleCacheForTests(): void {\n rrwebModulePromise = undefined;\n rrwebModuleLoaderOverride = undefined;\n rrwebScriptUrl = RRWEB_URL;\n}\n\nexport function setRrwebModuleLoaderForTests(\n loader: (() => Promise<RrwebModule>) | undefined,\n): void {\n rrwebModuleLoaderOverride = loader;\n rrwebModulePromise = undefined;\n}\n"],"mappings":";;AAEA,MAAM,YACJ;AAEF,IAAI;AACJ,IAAI;AACJ,IAAI,iBAAiB;AAErB,SAAgB,kBAAkB,KAAmB;AACnD,kBAAiB;AACjB,sBAAqB,KAAA;;AAGvB,SAAS,gBAAgB,KAA4B;AACnD,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,IAAI,SAAS,cAAc,SAAS;AAC1C,IAAE,MAAM;AACR,IAAE,QAAQ;AACV,IAAE,eAAe,SAAS;AAC1B,IAAE,UAAU;AACZ,WAAS,KAAK,YAAY,EAAE;GAC5B;;AAGJ,eAAe,sBAA4C;AACzD,KAAI,OAAO,WAAW,YACpB,OAAM,IAAI,MAAM,aAAa;AAG/B,KAAI,OAAO,MACT,QAAO,OAAO;AAGhB,OAAM,gBAAgB,eAAe;AAErC,KAAI,CAAC,OAAO,MACV,OAAM,IAAI,MAAM,WAAW;AAG7B,QAAO,OAAO;;AAGhB,eAAe,sBAA4C;AACzD,KAAI;AACF,SAAO,MAAM,OAAO;SACd;AACN,SAAO,qBAAqB;;;AAIhC,SAAgB,kBAAwC;AACtD,KAAI,0BACF,QAAO,2BAA2B;AAGpC,KAAI,uBAAuB,KAAA,EACzB,sBAAqB,qBAAqB;AAE5C,QAAO;;AAGT,SAAgB,gCAAsC;AACpD,sBAAqB,KAAA;AACrB,6BAA4B,KAAA;AAC5B,kBAAiB;;AAGnB,SAAgB,6BACd,QACM;AACN,6BAA4B;AAC5B,sBAAqB,KAAA"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { RrwebModule } from "./types.cjs";
|
|
2
2
|
|
|
3
3
|
//#region src/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.d.ts
|
|
4
|
+
declare function setRrwebScriptUrl(url: string): void;
|
|
4
5
|
declare function loadRrwebModule(): Promise<RrwebModule>;
|
|
5
6
|
declare function resetRrwebModuleCacheForTests(): void;
|
|
6
7
|
declare function setRrwebModuleLoaderForTests(loader: (() => Promise<RrwebModule>) | undefined): void;
|
|
7
|
-
/** No-op for ESM/CJS builds that lazy-load rrweb via dynamic import. */
|
|
8
|
-
declare function setRrwebScriptUrl(_url: string): void;
|
|
9
8
|
//#endregion
|
|
10
9
|
export { loadRrwebModule, resetRrwebModuleCacheForTests, setRrwebModuleLoaderForTests, setRrwebScriptUrl };
|
|
11
10
|
//# sourceMappingURL=loadRrwebModule.esm.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadRrwebModule.esm.d.cts","names":[],"sources":["../../../../src/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"loadRrwebModule.esm.d.cts","names":[],"sources":["../../../../src/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.ts"],"mappings":";;;iBASgB,iBAAA,CAAkB,GAAA;AAAA,iBA0ClB,eAAA,CAAA,GAAmB,OAAA,CAAQ,WAAA;AAAA,iBAW3B,6BAAA,CAAA;AAAA,iBAMA,4BAAA,CACd,MAAA,SAAe,OAAA,CAAQ,WAAA"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { RrwebModule } from "./types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.d.ts
|
|
4
|
+
declare function setRrwebScriptUrl(url: string): void;
|
|
4
5
|
declare function loadRrwebModule(): Promise<RrwebModule>;
|
|
5
6
|
declare function resetRrwebModuleCacheForTests(): void;
|
|
6
7
|
declare function setRrwebModuleLoaderForTests(loader: (() => Promise<RrwebModule>) | undefined): void;
|
|
7
|
-
/** No-op for ESM/CJS builds that lazy-load rrweb via dynamic import. */
|
|
8
|
-
declare function setRrwebScriptUrl(_url: string): void;
|
|
9
8
|
//#endregion
|
|
10
9
|
export { loadRrwebModule, resetRrwebModuleCacheForTests, setRrwebModuleLoaderForTests, setRrwebScriptUrl };
|
|
11
10
|
//# sourceMappingURL=loadRrwebModule.esm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadRrwebModule.esm.d.ts","names":[],"sources":["../../../../src/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"loadRrwebModule.esm.d.ts","names":[],"sources":["../../../../src/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.ts"],"mappings":";;;iBASgB,iBAAA,CAAkB,GAAA;AAAA,iBA0ClB,eAAA,CAAA,GAAmB,OAAA,CAAQ,WAAA;AAAA,iBAW3B,6BAAA,CAAA;AAAA,iBAMA,4BAAA,CACd,MAAA,SAAe,OAAA,CAAQ,WAAA"}
|
|
@@ -1,24 +1,50 @@
|
|
|
1
1
|
//#region src/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.ts
|
|
2
|
+
const RRWEB_URL = "https://unpkg.com/rrweb@2.0.0-alpha.20/dist/rrweb.umd.cjs";
|
|
2
3
|
let rrwebModulePromise;
|
|
3
4
|
let rrwebModuleLoaderOverride;
|
|
5
|
+
let rrwebScriptUrl = RRWEB_URL;
|
|
6
|
+
function setRrwebScriptUrl(url) {
|
|
7
|
+
rrwebScriptUrl = url;
|
|
8
|
+
rrwebModulePromise = void 0;
|
|
9
|
+
}
|
|
10
|
+
function loadRrwebScript(src) {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
const s = document.createElement("script");
|
|
13
|
+
s.src = src;
|
|
14
|
+
s.async = true;
|
|
15
|
+
s.onload = () => resolve();
|
|
16
|
+
s.onerror = reject;
|
|
17
|
+
document.head.appendChild(s);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
async function loadRrwebFromScript() {
|
|
21
|
+
if (typeof window === "undefined") throw new Error("no browser");
|
|
22
|
+
if (window.rrweb) return window.rrweb;
|
|
23
|
+
await loadRrwebScript(rrwebScriptUrl);
|
|
24
|
+
if (!window.rrweb) throw new Error("no rrweb");
|
|
25
|
+
return window.rrweb;
|
|
26
|
+
}
|
|
27
|
+
async function loadRrwebModuleImpl() {
|
|
28
|
+
try {
|
|
29
|
+
return await import("rrweb");
|
|
30
|
+
} catch {
|
|
31
|
+
return loadRrwebFromScript();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
4
34
|
function loadRrwebModule() {
|
|
5
35
|
if (rrwebModuleLoaderOverride) return rrwebModuleLoaderOverride();
|
|
6
|
-
if (rrwebModulePromise === void 0) rrwebModulePromise =
|
|
7
|
-
/* @vite-ignore */
|
|
8
|
-
"rrweb"
|
|
9
|
-
);
|
|
36
|
+
if (rrwebModulePromise === void 0) rrwebModulePromise = loadRrwebModuleImpl();
|
|
10
37
|
return rrwebModulePromise;
|
|
11
38
|
}
|
|
12
39
|
function resetRrwebModuleCacheForTests() {
|
|
13
40
|
rrwebModulePromise = void 0;
|
|
14
41
|
rrwebModuleLoaderOverride = void 0;
|
|
42
|
+
rrwebScriptUrl = RRWEB_URL;
|
|
15
43
|
}
|
|
16
44
|
function setRrwebModuleLoaderForTests(loader) {
|
|
17
45
|
rrwebModuleLoaderOverride = loader;
|
|
18
46
|
rrwebModulePromise = void 0;
|
|
19
47
|
}
|
|
20
|
-
/** No-op for ESM/CJS builds that lazy-load rrweb via dynamic import. */
|
|
21
|
-
function setRrwebScriptUrl(_url) {}
|
|
22
48
|
//#endregion
|
|
23
49
|
export { loadRrwebModule, resetRrwebModuleCacheForTests, setRrwebModuleLoaderForTests, setRrwebScriptUrl };
|
|
24
50
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadRrwebModule.esm.js","names":[],"sources":["../../../../src/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.ts"],"sourcesContent":["import type { RrwebModule } from './types.ts';\n\nlet rrwebModulePromise: Promise<RrwebModule> | undefined;\nlet rrwebModuleLoaderOverride: (() => Promise<RrwebModule>) | undefined;\n\nexport function loadRrwebModule(): Promise<RrwebModule> {\n if (rrwebModuleLoaderOverride) {\n return rrwebModuleLoaderOverride();\n }\n\n if (rrwebModulePromise === undefined) {\n rrwebModulePromise =
|
|
1
|
+
{"version":3,"file":"loadRrwebModule.esm.js","names":[],"sources":["../../../../src/instrumentations/replay/rrwebLoader/loadRrwebModule.esm.ts"],"sourcesContent":["import type { RrwebModule } from './types.ts';\n\nconst RRWEB_URL =\n 'https://unpkg.com/rrweb@2.0.0-alpha.20/dist/rrweb.umd.cjs';\n\nlet rrwebModulePromise: Promise<RrwebModule> | undefined;\nlet rrwebModuleLoaderOverride: (() => Promise<RrwebModule>) | undefined;\nlet rrwebScriptUrl = RRWEB_URL;\n\nexport function setRrwebScriptUrl(url: string): void {\n rrwebScriptUrl = url;\n rrwebModulePromise = undefined;\n}\n\nfunction loadRrwebScript(src: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const s = document.createElement('script');\n s.src = src;\n s.async = true;\n s.onload = () => resolve();\n s.onerror = reject;\n document.head.appendChild(s);\n });\n}\n\nasync function loadRrwebFromScript(): Promise<RrwebModule> {\n if (typeof window === 'undefined') {\n throw new Error('no browser');\n }\n\n if (window.rrweb) {\n return window.rrweb;\n }\n\n await loadRrwebScript(rrwebScriptUrl);\n\n if (!window.rrweb) {\n throw new Error('no rrweb');\n }\n\n return window.rrweb;\n}\n\nasync function loadRrwebModuleImpl(): Promise<RrwebModule> {\n try {\n return await import('rrweb');\n } catch {\n return loadRrwebFromScript();\n }\n}\n\nexport function loadRrwebModule(): Promise<RrwebModule> {\n if (rrwebModuleLoaderOverride) {\n return rrwebModuleLoaderOverride();\n }\n\n if (rrwebModulePromise === undefined) {\n rrwebModulePromise = loadRrwebModuleImpl();\n }\n return rrwebModulePromise;\n}\n\nexport function resetRrwebModuleCacheForTests(): void {\n rrwebModulePromise = undefined;\n rrwebModuleLoaderOverride = undefined;\n rrwebScriptUrl = RRWEB_URL;\n}\n\nexport function setRrwebModuleLoaderForTests(\n loader: (() => Promise<RrwebModule>) | undefined,\n): void {\n rrwebModuleLoaderOverride = loader;\n rrwebModulePromise = undefined;\n}\n"],"mappings":";AAEA,MAAM,YACJ;AAEF,IAAI;AACJ,IAAI;AACJ,IAAI,iBAAiB;AAErB,SAAgB,kBAAkB,KAAmB;AACnD,kBAAiB;AACjB,sBAAqB,KAAA;;AAGvB,SAAS,gBAAgB,KAA4B;AACnD,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,IAAI,SAAS,cAAc,SAAS;AAC1C,IAAE,MAAM;AACR,IAAE,QAAQ;AACV,IAAE,eAAe,SAAS;AAC1B,IAAE,UAAU;AACZ,WAAS,KAAK,YAAY,EAAE;GAC5B;;AAGJ,eAAe,sBAA4C;AACzD,KAAI,OAAO,WAAW,YACpB,OAAM,IAAI,MAAM,aAAa;AAG/B,KAAI,OAAO,MACT,QAAO,OAAO;AAGhB,OAAM,gBAAgB,eAAe;AAErC,KAAI,CAAC,OAAO,MACV,OAAM,IAAI,MAAM,WAAW;AAG7B,QAAO,OAAO;;AAGhB,eAAe,sBAA4C;AACzD,KAAI;AACF,SAAO,MAAM,OAAO;SACd;AACN,SAAO,qBAAqB;;;AAIhC,SAAgB,kBAAwC;AACtD,KAAI,0BACF,QAAO,2BAA2B;AAGpC,KAAI,uBAAuB,KAAA,EACzB,sBAAqB,qBAAqB;AAE5C,QAAO;;AAGT,SAAgB,gCAAsC;AACpD,sBAAqB,KAAA;AACrB,6BAA4B,KAAA;AAC5B,kBAAiB;;AAGnB,SAAgB,6BACd,QACM;AACN,6BAA4B;AAC5B,sBAAqB,KAAA"}
|
|
@@ -136,6 +136,7 @@ var SessionRecording = class {
|
|
|
136
136
|
sessionId,
|
|
137
137
|
transport: this._context.transport
|
|
138
138
|
});
|
|
139
|
+
this._context.transport.postReplay();
|
|
139
140
|
this._context.transport.postSessionMeta(require_instrumentations_replay_session_recording_lifecycle.sessionMetaRow(this._config, sessionId, startedAt, 1, "active", null));
|
|
140
141
|
const removeLifecycle = globalThis.__MXL_TEST_SKIP_REPLAY_LIFECYCLE__ === true ? () => void 0 : require_instrumentations_replay_session_recording_lifecycle.installReplayLifecycleHandlers({
|
|
141
142
|
config: this._config,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionRecording.cjs","names":["createChunkSeqStore","resolveReplayConfig","loadRrwebModule","getSessionStartedAt","startRecording","startEventCapture","sessionMetaRow","installReplayLifecycleHandlers"],"sources":["../../../../src/instrumentations/replay/session-recording/SessionRecording.ts"],"sourcesContent":["import type { DiagLogger } from '@opentelemetry/api';\nimport type { UserSessionManagerInternal } from '../../../managers/MXLUserSessionManager/types';\nimport type { NamespacedStorage } from '../../../utils/NamespacedStorage/NamespacedStorage';\nimport { startEventCapture } from '../events/startEventCapture';\nimport { loadRrwebModule } from '../rrwebLoader/loadRrwebModule';\nimport type { RrwebModule } from '../rrwebLoader/types';\nimport { startRecording } from '../recorder/startRecording';\nimport type { Recorder } from '../recorder/types';\nimport {\n clearObservedTraceIds,\n clearReplaySessionSink,\n publishReplaySessionSink,\n} from '../trace-sink/traceSink';\nimport { createChunkSeqStore } from './chunkSeq';\nimport {\n type ReplayContext,\n type ResolvedReplayConfig,\n resolveReplayConfig,\n} from './config';\nimport type { EventCapture } from '../events/startEventCapture';\nimport {\n getSessionStartedAt,\n installReplayLifecycleHandlers,\n sessionMetaRow,\n} from './lifecycle';\n\nexport interface SessionRecordingArgs {\n context: ReplayContext;\n userSessionManager: UserSessionManagerInternal;\n sessionStorage: NamespacedStorage;\n rrwebOptions?: ResolvedReplayConfig['rrwebOptions'] & {\n debug?: boolean;\n enabled?: boolean;\n sampleRate?: number;\n maskAllInputs?: boolean;\n maskAllText?: boolean;\n flushIntervalMs?: number;\n };\n recordUserSessions?: boolean;\n diag?: DiagLogger;\n}\n\ninterface ActiveRecording {\n recorder: Recorder;\n events: EventCapture;\n rrwebModule: RrwebModule;\n removeLifecycle: () => void;\n removeSessionEndListener?: () => void;\n}\n\nexport class SessionRecording {\n private readonly _context: ReplayContext;\n private readonly _userSessionManager: UserSessionManagerInternal;\n private readonly _chunkSeqStore: ReturnType<typeof createChunkSeqStore>;\n private readonly _config: ResolvedReplayConfig;\n private readonly _diag: DiagLogger;\n private readonly _recordUserSessions: boolean;\n\n private _active: ActiveRecording | undefined;\n private _paused = false;\n private _enableRequested = false;\n private _startInProgress = false;\n private _stopInProgress = false;\n private _removeSessionStartedListener?: () => void;\n\n public constructor({\n context,\n userSessionManager,\n sessionStorage,\n rrwebOptions,\n recordUserSessions = true,\n diag,\n }: SessionRecordingArgs) {\n this._context = context;\n this._userSessionManager = userSessionManager;\n this._chunkSeqStore = createChunkSeqStore(sessionStorage);\n this._recordUserSessions = recordUserSessions;\n this._config = resolveReplayConfig(\n context,\n rrwebOptions,\n recordUserSessions,\n );\n this._diag = diag ?? {\n debug: () => undefined,\n error: () => undefined,\n info: () => undefined,\n verbose: () => undefined,\n warn: () => undefined,\n };\n }\n\n public isRecording(): boolean {\n return Boolean(this._active) && !this._paused;\n }\n\n public enable(options?: { force?: boolean }): void {\n if (!this._recordUserSessions && !options?.force) {\n this._diag.debug(\n 'recordUserSessions disabled, waiting for manual enable',\n );\n return;\n }\n\n this._enableRequested = true;\n this._paused = false;\n void this._tryStart();\n }\n\n public pause(): void {\n if (!this._active) {\n return;\n }\n this._enableRequested = false;\n this._paused = true;\n this._active.recorder.pause();\n this._active.events.pause();\n }\n\n public resume(): void {\n if (!this._active) {\n this.enable();\n return;\n }\n\n const wasPaused = this._paused;\n this._enableRequested = true;\n this._paused = false;\n this._active.recorder.resume();\n this._active.events.resume();\n if (wasPaused) {\n this._active.rrwebModule.record.takeFullSnapshot();\n }\n }\n\n public async stop(): Promise<void> {\n this._enableRequested = false;\n this._paused = false;\n this._removeSessionStartedListener?.();\n this._removeSessionStartedListener = undefined;\n\n if (!this._active) {\n clearReplaySessionSink();\n clearObservedTraceIds();\n return;\n }\n\n if (this._stopInProgress) {\n return;\n }\n\n this._stopInProgress = true;\n\n const active = this._active;\n this._active = undefined;\n\n try {\n active.removeSessionEndListener?.();\n active.removeLifecycle();\n\n await active.recorder.flush(true);\n await active.events.flush(true);\n active.recorder.stop();\n active.events.stop();\n } finally {\n clearReplaySessionSink();\n clearObservedTraceIds();\n this._stopInProgress = false;\n }\n }\n\n private async _tryStart(): Promise<void> {\n if (\n !this._enableRequested ||\n this._active ||\n this._startInProgress ||\n this._stopInProgress\n ) {\n return;\n }\n\n if (typeof window === 'undefined') {\n this._diag.warn('session replay cannot run in non-browser environments');\n return;\n }\n\n const sessionId = this._userSessionManager.getUserSessionId();\n if (sessionId === null) {\n if (!this._removeSessionStartedListener) {\n this._removeSessionStartedListener =\n this._userSessionManager.addSessionPartStartedListener(() => {\n this._removeSessionStartedListener?.();\n this._removeSessionStartedListener = undefined;\n void this._tryStart();\n });\n }\n return;\n }\n\n if (!this._config.replayEnabled) {\n return;\n }\n\n if (Math.random() >= this._config.replaySampleRate) {\n this._diag.debug('session replay skipped by sample rate');\n return;\n }\n\n this._startInProgress = true;\n\n try {\n const rrwebModule = await loadRrwebModule();\n if (!this._enableRequested || this._active) {\n return;\n }\n\n publishReplaySessionSink(sessionId);\n clearObservedTraceIds();\n\n const startedAt = getSessionStartedAt(this._userSessionManager);\n const onActivity = () => {\n // Activity is tracked via MXL user session manager; no-op hook for now.\n };\n\n const recorder = startRecording({\n chunkSeqStore: this._chunkSeqStore,\n config: this._config,\n flushIntervalMs: this._config.flushIntervalMs,\n onActivity,\n rrwebModule,\n sessionId,\n transport: this._context.transport,\n });\n\n const events = startEventCapture({\n config: this._config,\n flushIntervalMs: this._config.flushIntervalMs,\n onActivity,\n sessionId,\n transport: this._context.transport,\n });\n\n void this._context.transport.postSessionMeta(\n sessionMetaRow(this._config, sessionId, startedAt, 1, 'active', null),\n );\n\n const skipLifecycle = (\n globalThis as Record<string, unknown>\n ).__MXL_TEST_SKIP_REPLAY_LIFECYCLE__;\n\n const removeLifecycle =\n skipLifecycle === true\n ? () => undefined\n : installReplayLifecycleHandlers({\n config: this._config,\n events,\n onFinalize: () => {\n this._active = undefined;\n clearReplaySessionSink();\n clearObservedTraceIds();\n },\n recorder,\n sessionId,\n startedAt,\n transport: this._context.transport,\n });\n\n const removeSessionEndListener =\n this._userSessionManager.addSessionPartEndedListener(() => {\n void recorder.flush(true);\n void events.flush(true);\n });\n\n this._active = {\n events,\n recorder,\n removeLifecycle,\n removeSessionEndListener,\n rrwebModule,\n };\n\n this._diag.debug('session recording started');\n } catch (error) {\n this._diag.error('failed to start session recording', error);\n } finally {\n this._startInProgress = false;\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionRecording.cjs","names":["createChunkSeqStore","resolveReplayConfig","loadRrwebModule","getSessionStartedAt","startRecording","startEventCapture","sessionMetaRow","installReplayLifecycleHandlers"],"sources":["../../../../src/instrumentations/replay/session-recording/SessionRecording.ts"],"sourcesContent":["import type { DiagLogger } from '@opentelemetry/api';\nimport type { UserSessionManagerInternal } from '../../../managers/MXLUserSessionManager/types';\nimport type { NamespacedStorage } from '../../../utils/NamespacedStorage/NamespacedStorage';\nimport { startEventCapture } from '../events/startEventCapture';\nimport { loadRrwebModule } from '../rrwebLoader/loadRrwebModule';\nimport type { RrwebModule } from '../rrwebLoader/types';\nimport { startRecording } from '../recorder/startRecording';\nimport type { Recorder } from '../recorder/types';\nimport {\n clearObservedTraceIds,\n clearReplaySessionSink,\n publishReplaySessionSink,\n} from '../trace-sink/traceSink';\nimport { createChunkSeqStore } from './chunkSeq';\nimport {\n type ReplayContext,\n type ResolvedReplayConfig,\n resolveReplayConfig,\n} from './config';\nimport type { EventCapture } from '../events/startEventCapture';\nimport {\n getSessionStartedAt,\n installReplayLifecycleHandlers,\n sessionMetaRow,\n} from './lifecycle';\n\nexport interface SessionRecordingArgs {\n context: ReplayContext;\n userSessionManager: UserSessionManagerInternal;\n sessionStorage: NamespacedStorage;\n rrwebOptions?: ResolvedReplayConfig['rrwebOptions'] & {\n debug?: boolean;\n enabled?: boolean;\n sampleRate?: number;\n maskAllInputs?: boolean;\n maskAllText?: boolean;\n flushIntervalMs?: number;\n };\n recordUserSessions?: boolean;\n diag?: DiagLogger;\n}\n\ninterface ActiveRecording {\n recorder: Recorder;\n events: EventCapture;\n rrwebModule: RrwebModule;\n removeLifecycle: () => void;\n removeSessionEndListener?: () => void;\n}\n\nexport class SessionRecording {\n private readonly _context: ReplayContext;\n private readonly _userSessionManager: UserSessionManagerInternal;\n private readonly _chunkSeqStore: ReturnType<typeof createChunkSeqStore>;\n private readonly _config: ResolvedReplayConfig;\n private readonly _diag: DiagLogger;\n private readonly _recordUserSessions: boolean;\n\n private _active: ActiveRecording | undefined;\n private _paused = false;\n private _enableRequested = false;\n private _startInProgress = false;\n private _stopInProgress = false;\n private _removeSessionStartedListener?: () => void;\n\n public constructor({\n context,\n userSessionManager,\n sessionStorage,\n rrwebOptions,\n recordUserSessions = true,\n diag,\n }: SessionRecordingArgs) {\n this._context = context;\n this._userSessionManager = userSessionManager;\n this._chunkSeqStore = createChunkSeqStore(sessionStorage);\n this._recordUserSessions = recordUserSessions;\n this._config = resolveReplayConfig(\n context,\n rrwebOptions,\n recordUserSessions,\n );\n this._diag = diag ?? {\n debug: () => undefined,\n error: () => undefined,\n info: () => undefined,\n verbose: () => undefined,\n warn: () => undefined,\n };\n }\n\n public isRecording(): boolean {\n return Boolean(this._active) && !this._paused;\n }\n\n public enable(options?: { force?: boolean }): void {\n if (!this._recordUserSessions && !options?.force) {\n this._diag.debug(\n 'recordUserSessions disabled, waiting for manual enable',\n );\n return;\n }\n\n this._enableRequested = true;\n this._paused = false;\n void this._tryStart();\n }\n\n public pause(): void {\n if (!this._active) {\n return;\n }\n this._enableRequested = false;\n this._paused = true;\n this._active.recorder.pause();\n this._active.events.pause();\n }\n\n public resume(): void {\n if (!this._active) {\n this.enable();\n return;\n }\n\n const wasPaused = this._paused;\n this._enableRequested = true;\n this._paused = false;\n this._active.recorder.resume();\n this._active.events.resume();\n if (wasPaused) {\n this._active.rrwebModule.record.takeFullSnapshot();\n }\n }\n\n public async stop(): Promise<void> {\n this._enableRequested = false;\n this._paused = false;\n this._removeSessionStartedListener?.();\n this._removeSessionStartedListener = undefined;\n\n if (!this._active) {\n clearReplaySessionSink();\n clearObservedTraceIds();\n return;\n }\n\n if (this._stopInProgress) {\n return;\n }\n\n this._stopInProgress = true;\n\n const active = this._active;\n this._active = undefined;\n\n try {\n active.removeSessionEndListener?.();\n active.removeLifecycle();\n\n await active.recorder.flush(true);\n await active.events.flush(true);\n active.recorder.stop();\n active.events.stop();\n } finally {\n clearReplaySessionSink();\n clearObservedTraceIds();\n this._stopInProgress = false;\n }\n }\n\n private async _tryStart(): Promise<void> {\n if (\n !this._enableRequested ||\n this._active ||\n this._startInProgress ||\n this._stopInProgress\n ) {\n return;\n }\n\n if (typeof window === 'undefined') {\n this._diag.warn('session replay cannot run in non-browser environments');\n return;\n }\n\n const sessionId = this._userSessionManager.getUserSessionId();\n if (sessionId === null) {\n if (!this._removeSessionStartedListener) {\n this._removeSessionStartedListener =\n this._userSessionManager.addSessionPartStartedListener(() => {\n this._removeSessionStartedListener?.();\n this._removeSessionStartedListener = undefined;\n void this._tryStart();\n });\n }\n return;\n }\n\n if (!this._config.replayEnabled) {\n return;\n }\n\n if (Math.random() >= this._config.replaySampleRate) {\n this._diag.debug('session replay skipped by sample rate');\n return;\n }\n\n this._startInProgress = true;\n\n try {\n const rrwebModule = await loadRrwebModule();\n if (!this._enableRequested || this._active) {\n return;\n }\n\n publishReplaySessionSink(sessionId);\n clearObservedTraceIds();\n\n const startedAt = getSessionStartedAt(this._userSessionManager);\n const onActivity = () => {\n // Activity is tracked via MXL user session manager; no-op hook for now.\n };\n\n const recorder = startRecording({\n chunkSeqStore: this._chunkSeqStore,\n config: this._config,\n flushIntervalMs: this._config.flushIntervalMs,\n onActivity,\n rrwebModule,\n sessionId,\n transport: this._context.transport,\n });\n\n const events = startEventCapture({\n config: this._config,\n flushIntervalMs: this._config.flushIntervalMs,\n onActivity,\n sessionId,\n transport: this._context.transport,\n });\n\n void this._context.transport.postReplay();\n void this._context.transport.postSessionMeta(\n sessionMetaRow(this._config, sessionId, startedAt, 1, 'active', null),\n );\n\n const skipLifecycle = (\n globalThis as Record<string, unknown>\n ).__MXL_TEST_SKIP_REPLAY_LIFECYCLE__;\n\n const removeLifecycle =\n skipLifecycle === true\n ? () => undefined\n : installReplayLifecycleHandlers({\n config: this._config,\n events,\n onFinalize: () => {\n this._active = undefined;\n clearReplaySessionSink();\n clearObservedTraceIds();\n },\n recorder,\n sessionId,\n startedAt,\n transport: this._context.transport,\n });\n\n const removeSessionEndListener =\n this._userSessionManager.addSessionPartEndedListener(() => {\n void recorder.flush(true);\n void events.flush(true);\n });\n\n this._active = {\n events,\n recorder,\n removeLifecycle,\n removeSessionEndListener,\n rrwebModule,\n };\n\n this._diag.debug('session recording started');\n } catch (error) {\n this._diag.error('failed to start session recording', error);\n } finally {\n this._startInProgress = false;\n }\n }\n}\n"],"mappings":";;;;;;;;;AAkDA,IAAa,mBAAb,MAA8B;CAC5B;CACA;CACA;CACA;CACA;CACA;CAEA;CACA,UAAkB;CAClB,mBAA2B;CAC3B,mBAA2B;CAC3B,kBAA0B;CAC1B;CAEA,YAAmB,EACjB,SACA,oBACA,gBACA,cACA,qBAAqB,MACrB,QACuB;AACvB,OAAK,WAAW;AAChB,OAAK,sBAAsB;AAC3B,OAAK,iBAAiBA,2DAAAA,oBAAoB,eAAe;AACzD,OAAK,sBAAsB;AAC3B,OAAK,UAAUC,yDAAAA,oBACb,SACA,cACA,mBACD;AACD,OAAK,QAAQ,QAAQ;GACnB,aAAa,KAAA;GACb,aAAa,KAAA;GACb,YAAY,KAAA;GACZ,eAAe,KAAA;GACf,YAAY,KAAA;GACb;;CAGH,cAA8B;AAC5B,SAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,KAAK;;CAGxC,OAAc,SAAqC;AACjD,MAAI,CAAC,KAAK,uBAAuB,CAAC,SAAS,OAAO;AAChD,QAAK,MAAM,MACT,yDACD;AACD;;AAGF,OAAK,mBAAmB;AACxB,OAAK,UAAU;AACV,OAAK,WAAW;;CAGvB,QAAqB;AACnB,MAAI,CAAC,KAAK,QACR;AAEF,OAAK,mBAAmB;AACxB,OAAK,UAAU;AACf,OAAK,QAAQ,SAAS,OAAO;AAC7B,OAAK,QAAQ,OAAO,OAAO;;CAG7B,SAAsB;AACpB,MAAI,CAAC,KAAK,SAAS;AACjB,QAAK,QAAQ;AACb;;EAGF,MAAM,YAAY,KAAK;AACvB,OAAK,mBAAmB;AACxB,OAAK,UAAU;AACf,OAAK,QAAQ,SAAS,QAAQ;AAC9B,OAAK,QAAQ,OAAO,QAAQ;AAC5B,MAAI,UACF,MAAK,QAAQ,YAAY,OAAO,kBAAkB;;CAItD,MAAa,OAAsB;AACjC,OAAK,mBAAmB;AACxB,OAAK,UAAU;AACf,OAAK,iCAAiC;AACtC,OAAK,gCAAgC,KAAA;AAErC,MAAI,CAAC,KAAK,SAAS;AACjB,wDAAA,wBAAwB;AACxB,wDAAA,uBAAuB;AACvB;;AAGF,MAAI,KAAK,gBACP;AAGF,OAAK,kBAAkB;EAEvB,MAAM,SAAS,KAAK;AACpB,OAAK,UAAU,KAAA;AAEf,MAAI;AACF,UAAO,4BAA4B;AACnC,UAAO,iBAAiB;AAExB,SAAM,OAAO,SAAS,MAAM,KAAK;AACjC,SAAM,OAAO,OAAO,MAAM,KAAK;AAC/B,UAAO,SAAS,MAAM;AACtB,UAAO,OAAO,MAAM;YACZ;AACR,wDAAA,wBAAwB;AACxB,wDAAA,uBAAuB;AACvB,QAAK,kBAAkB;;;CAI3B,MAAc,YAA2B;AACvC,MACE,CAAC,KAAK,oBACN,KAAK,WACL,KAAK,oBACL,KAAK,gBAEL;AAGF,MAAI,OAAO,WAAW,aAAa;AACjC,QAAK,MAAM,KAAK,wDAAwD;AACxE;;EAGF,MAAM,YAAY,KAAK,oBAAoB,kBAAkB;AAC7D,MAAI,cAAc,MAAM;AACtB,OAAI,CAAC,KAAK,8BACR,MAAK,gCACH,KAAK,oBAAoB,oCAAoC;AAC3D,SAAK,iCAAiC;AACtC,SAAK,gCAAgC,KAAA;AAChC,SAAK,WAAW;KACrB;AAEN;;AAGF,MAAI,CAAC,KAAK,QAAQ,cAChB;AAGF,MAAI,KAAK,QAAQ,IAAI,KAAK,QAAQ,kBAAkB;AAClD,QAAK,MAAM,MAAM,wCAAwC;AACzD;;AAGF,OAAK,mBAAmB;AAExB,MAAI;GACF,MAAM,cAAc,MAAMC,gEAAAA,iBAAiB;AAC3C,OAAI,CAAC,KAAK,oBAAoB,KAAK,QACjC;AAGF,wDAAA,yBAAyB,UAAU;AACnC,wDAAA,uBAAuB;GAEvB,MAAM,YAAYC,4DAAAA,oBAAoB,KAAK,oBAAoB;GAC/D,MAAM,mBAAmB;GAIzB,MAAM,WAAWC,wDAAAA,eAAe;IAC9B,eAAe,KAAK;IACpB,QAAQ,KAAK;IACb,iBAAiB,KAAK,QAAQ;IAC9B;IACA;IACA;IACA,WAAW,KAAK,SAAS;IAC1B,CAAC;GAEF,MAAM,SAASC,yDAAAA,kBAAkB;IAC/B,QAAQ,KAAK;IACb,iBAAiB,KAAK,QAAQ;IAC9B;IACA;IACA,WAAW,KAAK,SAAS;IAC1B,CAAC;AAEG,QAAK,SAAS,UAAU,YAAY;AACpC,QAAK,SAAS,UAAU,gBAC3BC,4DAAAA,eAAe,KAAK,SAAS,WAAW,WAAW,GAAG,UAAU,KAAK,CACtE;GAMD,MAAM,kBAHJ,WACA,uCAGkB,aACR,KAAA,IACNC,4DAAAA,+BAA+B;IAC7B,QAAQ,KAAK;IACb;IACA,kBAAkB;AAChB,UAAK,UAAU,KAAA;AACf,0DAAA,wBAAwB;AACxB,0DAAA,uBAAuB;;IAEzB;IACA;IACA;IACA,WAAW,KAAK,SAAS;IAC1B,CAAC;GAER,MAAM,2BACJ,KAAK,oBAAoB,kCAAkC;AACpD,aAAS,MAAM,KAAK;AACpB,WAAO,MAAM,KAAK;KACvB;AAEJ,QAAK,UAAU;IACb;IACA;IACA;IACA;IACA;IACD;AAED,QAAK,MAAM,MAAM,4BAA4B;WACtC,OAAO;AACd,QAAK,MAAM,MAAM,qCAAqC,MAAM;YACpD;AACR,QAAK,mBAAmB"}
|
|
@@ -135,6 +135,7 @@ var SessionRecording = class {
|
|
|
135
135
|
sessionId,
|
|
136
136
|
transport: this._context.transport
|
|
137
137
|
});
|
|
138
|
+
this._context.transport.postReplay();
|
|
138
139
|
this._context.transport.postSessionMeta(sessionMetaRow(this._config, sessionId, startedAt, 1, "active", null));
|
|
139
140
|
const removeLifecycle = globalThis.__MXL_TEST_SKIP_REPLAY_LIFECYCLE__ === true ? () => void 0 : installReplayLifecycleHandlers({
|
|
140
141
|
config: this._config,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionRecording.js","names":[],"sources":["../../../../src/instrumentations/replay/session-recording/SessionRecording.ts"],"sourcesContent":["import type { DiagLogger } from '@opentelemetry/api';\nimport type { UserSessionManagerInternal } from '../../../managers/MXLUserSessionManager/types';\nimport type { NamespacedStorage } from '../../../utils/NamespacedStorage/NamespacedStorage';\nimport { startEventCapture } from '../events/startEventCapture';\nimport { loadRrwebModule } from '../rrwebLoader/loadRrwebModule';\nimport type { RrwebModule } from '../rrwebLoader/types';\nimport { startRecording } from '../recorder/startRecording';\nimport type { Recorder } from '../recorder/types';\nimport {\n clearObservedTraceIds,\n clearReplaySessionSink,\n publishReplaySessionSink,\n} from '../trace-sink/traceSink';\nimport { createChunkSeqStore } from './chunkSeq';\nimport {\n type ReplayContext,\n type ResolvedReplayConfig,\n resolveReplayConfig,\n} from './config';\nimport type { EventCapture } from '../events/startEventCapture';\nimport {\n getSessionStartedAt,\n installReplayLifecycleHandlers,\n sessionMetaRow,\n} from './lifecycle';\n\nexport interface SessionRecordingArgs {\n context: ReplayContext;\n userSessionManager: UserSessionManagerInternal;\n sessionStorage: NamespacedStorage;\n rrwebOptions?: ResolvedReplayConfig['rrwebOptions'] & {\n debug?: boolean;\n enabled?: boolean;\n sampleRate?: number;\n maskAllInputs?: boolean;\n maskAllText?: boolean;\n flushIntervalMs?: number;\n };\n recordUserSessions?: boolean;\n diag?: DiagLogger;\n}\n\ninterface ActiveRecording {\n recorder: Recorder;\n events: EventCapture;\n rrwebModule: RrwebModule;\n removeLifecycle: () => void;\n removeSessionEndListener?: () => void;\n}\n\nexport class SessionRecording {\n private readonly _context: ReplayContext;\n private readonly _userSessionManager: UserSessionManagerInternal;\n private readonly _chunkSeqStore: ReturnType<typeof createChunkSeqStore>;\n private readonly _config: ResolvedReplayConfig;\n private readonly _diag: DiagLogger;\n private readonly _recordUserSessions: boolean;\n\n private _active: ActiveRecording | undefined;\n private _paused = false;\n private _enableRequested = false;\n private _startInProgress = false;\n private _stopInProgress = false;\n private _removeSessionStartedListener?: () => void;\n\n public constructor({\n context,\n userSessionManager,\n sessionStorage,\n rrwebOptions,\n recordUserSessions = true,\n diag,\n }: SessionRecordingArgs) {\n this._context = context;\n this._userSessionManager = userSessionManager;\n this._chunkSeqStore = createChunkSeqStore(sessionStorage);\n this._recordUserSessions = recordUserSessions;\n this._config = resolveReplayConfig(\n context,\n rrwebOptions,\n recordUserSessions,\n );\n this._diag = diag ?? {\n debug: () => undefined,\n error: () => undefined,\n info: () => undefined,\n verbose: () => undefined,\n warn: () => undefined,\n };\n }\n\n public isRecording(): boolean {\n return Boolean(this._active) && !this._paused;\n }\n\n public enable(options?: { force?: boolean }): void {\n if (!this._recordUserSessions && !options?.force) {\n this._diag.debug(\n 'recordUserSessions disabled, waiting for manual enable',\n );\n return;\n }\n\n this._enableRequested = true;\n this._paused = false;\n void this._tryStart();\n }\n\n public pause(): void {\n if (!this._active) {\n return;\n }\n this._enableRequested = false;\n this._paused = true;\n this._active.recorder.pause();\n this._active.events.pause();\n }\n\n public resume(): void {\n if (!this._active) {\n this.enable();\n return;\n }\n\n const wasPaused = this._paused;\n this._enableRequested = true;\n this._paused = false;\n this._active.recorder.resume();\n this._active.events.resume();\n if (wasPaused) {\n this._active.rrwebModule.record.takeFullSnapshot();\n }\n }\n\n public async stop(): Promise<void> {\n this._enableRequested = false;\n this._paused = false;\n this._removeSessionStartedListener?.();\n this._removeSessionStartedListener = undefined;\n\n if (!this._active) {\n clearReplaySessionSink();\n clearObservedTraceIds();\n return;\n }\n\n if (this._stopInProgress) {\n return;\n }\n\n this._stopInProgress = true;\n\n const active = this._active;\n this._active = undefined;\n\n try {\n active.removeSessionEndListener?.();\n active.removeLifecycle();\n\n await active.recorder.flush(true);\n await active.events.flush(true);\n active.recorder.stop();\n active.events.stop();\n } finally {\n clearReplaySessionSink();\n clearObservedTraceIds();\n this._stopInProgress = false;\n }\n }\n\n private async _tryStart(): Promise<void> {\n if (\n !this._enableRequested ||\n this._active ||\n this._startInProgress ||\n this._stopInProgress\n ) {\n return;\n }\n\n if (typeof window === 'undefined') {\n this._diag.warn('session replay cannot run in non-browser environments');\n return;\n }\n\n const sessionId = this._userSessionManager.getUserSessionId();\n if (sessionId === null) {\n if (!this._removeSessionStartedListener) {\n this._removeSessionStartedListener =\n this._userSessionManager.addSessionPartStartedListener(() => {\n this._removeSessionStartedListener?.();\n this._removeSessionStartedListener = undefined;\n void this._tryStart();\n });\n }\n return;\n }\n\n if (!this._config.replayEnabled) {\n return;\n }\n\n if (Math.random() >= this._config.replaySampleRate) {\n this._diag.debug('session replay skipped by sample rate');\n return;\n }\n\n this._startInProgress = true;\n\n try {\n const rrwebModule = await loadRrwebModule();\n if (!this._enableRequested || this._active) {\n return;\n }\n\n publishReplaySessionSink(sessionId);\n clearObservedTraceIds();\n\n const startedAt = getSessionStartedAt(this._userSessionManager);\n const onActivity = () => {\n // Activity is tracked via MXL user session manager; no-op hook for now.\n };\n\n const recorder = startRecording({\n chunkSeqStore: this._chunkSeqStore,\n config: this._config,\n flushIntervalMs: this._config.flushIntervalMs,\n onActivity,\n rrwebModule,\n sessionId,\n transport: this._context.transport,\n });\n\n const events = startEventCapture({\n config: this._config,\n flushIntervalMs: this._config.flushIntervalMs,\n onActivity,\n sessionId,\n transport: this._context.transport,\n });\n\n void this._context.transport.postSessionMeta(\n sessionMetaRow(this._config, sessionId, startedAt, 1, 'active', null),\n );\n\n const skipLifecycle = (\n globalThis as Record<string, unknown>\n ).__MXL_TEST_SKIP_REPLAY_LIFECYCLE__;\n\n const removeLifecycle =\n skipLifecycle === true\n ? () => undefined\n : installReplayLifecycleHandlers({\n config: this._config,\n events,\n onFinalize: () => {\n this._active = undefined;\n clearReplaySessionSink();\n clearObservedTraceIds();\n },\n recorder,\n sessionId,\n startedAt,\n transport: this._context.transport,\n });\n\n const removeSessionEndListener =\n this._userSessionManager.addSessionPartEndedListener(() => {\n void recorder.flush(true);\n void events.flush(true);\n });\n\n this._active = {\n events,\n recorder,\n removeLifecycle,\n removeSessionEndListener,\n rrwebModule,\n };\n\n this._diag.debug('session recording started');\n } catch (error) {\n this._diag.error('failed to start session recording', error);\n } finally {\n this._startInProgress = false;\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionRecording.js","names":[],"sources":["../../../../src/instrumentations/replay/session-recording/SessionRecording.ts"],"sourcesContent":["import type { DiagLogger } from '@opentelemetry/api';\nimport type { UserSessionManagerInternal } from '../../../managers/MXLUserSessionManager/types';\nimport type { NamespacedStorage } from '../../../utils/NamespacedStorage/NamespacedStorage';\nimport { startEventCapture } from '../events/startEventCapture';\nimport { loadRrwebModule } from '../rrwebLoader/loadRrwebModule';\nimport type { RrwebModule } from '../rrwebLoader/types';\nimport { startRecording } from '../recorder/startRecording';\nimport type { Recorder } from '../recorder/types';\nimport {\n clearObservedTraceIds,\n clearReplaySessionSink,\n publishReplaySessionSink,\n} from '../trace-sink/traceSink';\nimport { createChunkSeqStore } from './chunkSeq';\nimport {\n type ReplayContext,\n type ResolvedReplayConfig,\n resolveReplayConfig,\n} from './config';\nimport type { EventCapture } from '../events/startEventCapture';\nimport {\n getSessionStartedAt,\n installReplayLifecycleHandlers,\n sessionMetaRow,\n} from './lifecycle';\n\nexport interface SessionRecordingArgs {\n context: ReplayContext;\n userSessionManager: UserSessionManagerInternal;\n sessionStorage: NamespacedStorage;\n rrwebOptions?: ResolvedReplayConfig['rrwebOptions'] & {\n debug?: boolean;\n enabled?: boolean;\n sampleRate?: number;\n maskAllInputs?: boolean;\n maskAllText?: boolean;\n flushIntervalMs?: number;\n };\n recordUserSessions?: boolean;\n diag?: DiagLogger;\n}\n\ninterface ActiveRecording {\n recorder: Recorder;\n events: EventCapture;\n rrwebModule: RrwebModule;\n removeLifecycle: () => void;\n removeSessionEndListener?: () => void;\n}\n\nexport class SessionRecording {\n private readonly _context: ReplayContext;\n private readonly _userSessionManager: UserSessionManagerInternal;\n private readonly _chunkSeqStore: ReturnType<typeof createChunkSeqStore>;\n private readonly _config: ResolvedReplayConfig;\n private readonly _diag: DiagLogger;\n private readonly _recordUserSessions: boolean;\n\n private _active: ActiveRecording | undefined;\n private _paused = false;\n private _enableRequested = false;\n private _startInProgress = false;\n private _stopInProgress = false;\n private _removeSessionStartedListener?: () => void;\n\n public constructor({\n context,\n userSessionManager,\n sessionStorage,\n rrwebOptions,\n recordUserSessions = true,\n diag,\n }: SessionRecordingArgs) {\n this._context = context;\n this._userSessionManager = userSessionManager;\n this._chunkSeqStore = createChunkSeqStore(sessionStorage);\n this._recordUserSessions = recordUserSessions;\n this._config = resolveReplayConfig(\n context,\n rrwebOptions,\n recordUserSessions,\n );\n this._diag = diag ?? {\n debug: () => undefined,\n error: () => undefined,\n info: () => undefined,\n verbose: () => undefined,\n warn: () => undefined,\n };\n }\n\n public isRecording(): boolean {\n return Boolean(this._active) && !this._paused;\n }\n\n public enable(options?: { force?: boolean }): void {\n if (!this._recordUserSessions && !options?.force) {\n this._diag.debug(\n 'recordUserSessions disabled, waiting for manual enable',\n );\n return;\n }\n\n this._enableRequested = true;\n this._paused = false;\n void this._tryStart();\n }\n\n public pause(): void {\n if (!this._active) {\n return;\n }\n this._enableRequested = false;\n this._paused = true;\n this._active.recorder.pause();\n this._active.events.pause();\n }\n\n public resume(): void {\n if (!this._active) {\n this.enable();\n return;\n }\n\n const wasPaused = this._paused;\n this._enableRequested = true;\n this._paused = false;\n this._active.recorder.resume();\n this._active.events.resume();\n if (wasPaused) {\n this._active.rrwebModule.record.takeFullSnapshot();\n }\n }\n\n public async stop(): Promise<void> {\n this._enableRequested = false;\n this._paused = false;\n this._removeSessionStartedListener?.();\n this._removeSessionStartedListener = undefined;\n\n if (!this._active) {\n clearReplaySessionSink();\n clearObservedTraceIds();\n return;\n }\n\n if (this._stopInProgress) {\n return;\n }\n\n this._stopInProgress = true;\n\n const active = this._active;\n this._active = undefined;\n\n try {\n active.removeSessionEndListener?.();\n active.removeLifecycle();\n\n await active.recorder.flush(true);\n await active.events.flush(true);\n active.recorder.stop();\n active.events.stop();\n } finally {\n clearReplaySessionSink();\n clearObservedTraceIds();\n this._stopInProgress = false;\n }\n }\n\n private async _tryStart(): Promise<void> {\n if (\n !this._enableRequested ||\n this._active ||\n this._startInProgress ||\n this._stopInProgress\n ) {\n return;\n }\n\n if (typeof window === 'undefined') {\n this._diag.warn('session replay cannot run in non-browser environments');\n return;\n }\n\n const sessionId = this._userSessionManager.getUserSessionId();\n if (sessionId === null) {\n if (!this._removeSessionStartedListener) {\n this._removeSessionStartedListener =\n this._userSessionManager.addSessionPartStartedListener(() => {\n this._removeSessionStartedListener?.();\n this._removeSessionStartedListener = undefined;\n void this._tryStart();\n });\n }\n return;\n }\n\n if (!this._config.replayEnabled) {\n return;\n }\n\n if (Math.random() >= this._config.replaySampleRate) {\n this._diag.debug('session replay skipped by sample rate');\n return;\n }\n\n this._startInProgress = true;\n\n try {\n const rrwebModule = await loadRrwebModule();\n if (!this._enableRequested || this._active) {\n return;\n }\n\n publishReplaySessionSink(sessionId);\n clearObservedTraceIds();\n\n const startedAt = getSessionStartedAt(this._userSessionManager);\n const onActivity = () => {\n // Activity is tracked via MXL user session manager; no-op hook for now.\n };\n\n const recorder = startRecording({\n chunkSeqStore: this._chunkSeqStore,\n config: this._config,\n flushIntervalMs: this._config.flushIntervalMs,\n onActivity,\n rrwebModule,\n sessionId,\n transport: this._context.transport,\n });\n\n const events = startEventCapture({\n config: this._config,\n flushIntervalMs: this._config.flushIntervalMs,\n onActivity,\n sessionId,\n transport: this._context.transport,\n });\n\n void this._context.transport.postReplay();\n void this._context.transport.postSessionMeta(\n sessionMetaRow(this._config, sessionId, startedAt, 1, 'active', null),\n );\n\n const skipLifecycle = (\n globalThis as Record<string, unknown>\n ).__MXL_TEST_SKIP_REPLAY_LIFECYCLE__;\n\n const removeLifecycle =\n skipLifecycle === true\n ? () => undefined\n : installReplayLifecycleHandlers({\n config: this._config,\n events,\n onFinalize: () => {\n this._active = undefined;\n clearReplaySessionSink();\n clearObservedTraceIds();\n },\n recorder,\n sessionId,\n startedAt,\n transport: this._context.transport,\n });\n\n const removeSessionEndListener =\n this._userSessionManager.addSessionPartEndedListener(() => {\n void recorder.flush(true);\n void events.flush(true);\n });\n\n this._active = {\n events,\n recorder,\n removeLifecycle,\n removeSessionEndListener,\n rrwebModule,\n };\n\n this._diag.debug('session recording started');\n } catch (error) {\n this._diag.error('failed to start session recording', error);\n } finally {\n this._startInProgress = false;\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.cjs","names":[],"sources":["../../../../src/instrumentations/replay/session-recording/config.ts"],"sourcesContent":["import type { ReplayUserConfig } from '../ReplayInstrumentation/types';\nimport type { ReplayTransport } from '../transport/types';\n\nexport interface ResolvedReplayConfig {\n readonly appID: string;\n readonly userID: string;\n readonly appVersion?: string;\n readonly serviceName?: string;\n readonly environment?: string;\n readonly replayEnabled: boolean;\n readonly replaySampleRate: number;\n readonly maskAllInputs: boolean;\n readonly maskAllText: boolean;\n readonly debug: boolean;\n readonly flushIntervalMs: number;\n readonly rrwebOptions: Omit<\n ReplayUserConfig,\n | 'debug'\n | 'enabled'\n | 'sampleRate'\n | 'maskAllInputs'\n | 'maskAllText'\n | 'flushIntervalMs'\n | 'omitRedundantInstrumentations'\n >;\n userId?: string;\n}\n\nexport interface ReplayContext {\n readonly appID: string;\n readonly userID: string;\n readonly
|
|
1
|
+
{"version":3,"file":"config.cjs","names":[],"sources":["../../../../src/instrumentations/replay/session-recording/config.ts"],"sourcesContent":["import type { ReplayUserConfig } from '../ReplayInstrumentation/types';\nimport type { ReplayTransport } from '../transport/types';\n\nexport interface ResolvedReplayConfig {\n readonly appID: string;\n readonly userID: string;\n readonly appVersion?: string;\n readonly serviceName?: string;\n readonly environment?: string;\n readonly replayEnabled: boolean;\n readonly replaySampleRate: number;\n readonly maskAllInputs: boolean;\n readonly maskAllText: boolean;\n readonly debug: boolean;\n readonly flushIntervalMs: number;\n readonly rrwebOptions: Omit<\n ReplayUserConfig,\n | 'debug'\n | 'enabled'\n | 'sampleRate'\n | 'maskAllInputs'\n | 'maskAllText'\n | 'flushIntervalMs'\n | 'omitRedundantInstrumentations'\n >;\n userId?: string;\n}\n\nexport interface ReplayContext {\n readonly appID: string;\n readonly userID: string;\n readonly apiURL?: string;\n readonly appVersion?: string;\n readonly serviceName?: string;\n readonly transport: ReplayTransport;\n}\n\nexport function resolveReplayConfig(\n context: ReplayContext,\n options?: ReplayUserConfig,\n recordUserSessions = true,\n): ResolvedReplayConfig {\n const {\n debug = false,\n enabled,\n sampleRate,\n maskAllInputs = true,\n maskAllText = true,\n flushIntervalMs = 5_000,\n omitRedundantInstrumentations: _omitRedundantInstrumentations,\n ...rrwebOptions\n } = options ?? {};\n\n return {\n appID: context.appID,\n appVersion: context.appVersion,\n debug,\n environment: undefined,\n flushIntervalMs,\n maskAllInputs,\n maskAllText,\n replayEnabled: enabled ?? recordUserSessions,\n replaySampleRate: sampleRate ?? 1,\n rrwebOptions,\n serviceName: context.serviceName,\n userID: context.userID,\n };\n}\n"],"mappings":";;AAqCA,SAAgB,oBACd,SACA,SACA,qBAAqB,MACC;CACtB,MAAM,EACJ,QAAQ,OACR,SACA,YACA,gBAAgB,MAChB,cAAc,MACd,kBAAkB,KAClB,+BAA+B,gCAC/B,GAAG,iBACD,WAAW,EAAE;AAEjB,QAAO;EACL,OAAO,QAAQ;EACf,YAAY,QAAQ;EACpB;EACA,aAAa,KAAA;EACb;EACA;EACA;EACA,eAAe,WAAW;EAC1B,kBAAkB,cAAc;EAChC;EACA,aAAa,QAAQ;EACrB,QAAQ,QAAQ;EACjB"}
|
|
@@ -20,7 +20,7 @@ interface ResolvedReplayConfig {
|
|
|
20
20
|
interface ReplayContext {
|
|
21
21
|
readonly appID: string;
|
|
22
22
|
readonly userID: string;
|
|
23
|
-
readonly
|
|
23
|
+
readonly apiURL?: string;
|
|
24
24
|
readonly appVersion?: string;
|
|
25
25
|
readonly serviceName?: string;
|
|
26
26
|
readonly transport: ReplayTransport;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.cts","names":[],"sources":["../../../../src/instrumentations/replay/session-recording/config.ts"],"mappings":";;;;UAGiB,oBAAA;EAAA,SACN,KAAA;EAAA,SACA,MAAA;EAAA,SACA,UAAA;EAAA,SACA,WAAA;EAAA,SACA,WAAA;EAAA,SACA,aAAA;EAAA,SACA,gBAAA;EAAA,SACA,aAAA;EAAA,SACA,WAAA;EAAA,SACA,KAAA;EAAA,SACA,eAAA;EAAA,SACA,YAAA,EAAc,IAAA,CACrB,gBAAA;EASF,MAAA;AAAA;AAAA,UAGe,aAAA;EAAA,SACN,KAAA;EAAA,SACA,MAAA;EAAA,SACA,
|
|
1
|
+
{"version":3,"file":"config.d.cts","names":[],"sources":["../../../../src/instrumentations/replay/session-recording/config.ts"],"mappings":";;;;UAGiB,oBAAA;EAAA,SACN,KAAA;EAAA,SACA,MAAA;EAAA,SACA,UAAA;EAAA,SACA,WAAA;EAAA,SACA,WAAA;EAAA,SACA,aAAA;EAAA,SACA,gBAAA;EAAA,SACA,aAAA;EAAA,SACA,WAAA;EAAA,SACA,KAAA;EAAA,SACA,eAAA;EAAA,SACA,YAAA,EAAc,IAAA,CACrB,gBAAA;EASF,MAAA;AAAA;AAAA,UAGe,aAAA;EAAA,SACN,KAAA;EAAA,SACA,MAAA;EAAA,SACA,MAAA;EAAA,SACA,UAAA;EAAA,SACA,WAAA;EAAA,SACA,SAAA,EAAW,eAAA;AAAA;AAAA,iBAGN,mBAAA,CACd,OAAA,EAAS,aAAA,EACT,OAAA,GAAU,gBAAA,EACV,kBAAA,aACC,oBAAA"}
|
|
@@ -20,7 +20,7 @@ interface ResolvedReplayConfig {
|
|
|
20
20
|
interface ReplayContext {
|
|
21
21
|
readonly appID: string;
|
|
22
22
|
readonly userID: string;
|
|
23
|
-
readonly
|
|
23
|
+
readonly apiURL?: string;
|
|
24
24
|
readonly appVersion?: string;
|
|
25
25
|
readonly serviceName?: string;
|
|
26
26
|
readonly transport: ReplayTransport;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","names":[],"sources":["../../../../src/instrumentations/replay/session-recording/config.ts"],"mappings":";;;;UAGiB,oBAAA;EAAA,SACN,KAAA;EAAA,SACA,MAAA;EAAA,SACA,UAAA;EAAA,SACA,WAAA;EAAA,SACA,WAAA;EAAA,SACA,aAAA;EAAA,SACA,gBAAA;EAAA,SACA,aAAA;EAAA,SACA,WAAA;EAAA,SACA,KAAA;EAAA,SACA,eAAA;EAAA,SACA,YAAA,EAAc,IAAA,CACrB,gBAAA;EASF,MAAA;AAAA;AAAA,UAGe,aAAA;EAAA,SACN,KAAA;EAAA,SACA,MAAA;EAAA,SACA,
|
|
1
|
+
{"version":3,"file":"config.d.ts","names":[],"sources":["../../../../src/instrumentations/replay/session-recording/config.ts"],"mappings":";;;;UAGiB,oBAAA;EAAA,SACN,KAAA;EAAA,SACA,MAAA;EAAA,SACA,UAAA;EAAA,SACA,WAAA;EAAA,SACA,WAAA;EAAA,SACA,aAAA;EAAA,SACA,gBAAA;EAAA,SACA,aAAA;EAAA,SACA,WAAA;EAAA,SACA,KAAA;EAAA,SACA,eAAA;EAAA,SACA,YAAA,EAAc,IAAA,CACrB,gBAAA;EASF,MAAA;AAAA;AAAA,UAGe,aAAA;EAAA,SACN,KAAA;EAAA,SACA,MAAA;EAAA,SACA,MAAA;EAAA,SACA,UAAA;EAAA,SACA,WAAA;EAAA,SACA,SAAA,EAAW,eAAA;AAAA;AAAA,iBAGN,mBAAA,CACd,OAAA,EAAS,aAAA,EACT,OAAA,GAAU,gBAAA,EACV,kBAAA,aACC,oBAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","names":[],"sources":["../../../../src/instrumentations/replay/session-recording/config.ts"],"sourcesContent":["import type { ReplayUserConfig } from '../ReplayInstrumentation/types';\nimport type { ReplayTransport } from '../transport/types';\n\nexport interface ResolvedReplayConfig {\n readonly appID: string;\n readonly userID: string;\n readonly appVersion?: string;\n readonly serviceName?: string;\n readonly environment?: string;\n readonly replayEnabled: boolean;\n readonly replaySampleRate: number;\n readonly maskAllInputs: boolean;\n readonly maskAllText: boolean;\n readonly debug: boolean;\n readonly flushIntervalMs: number;\n readonly rrwebOptions: Omit<\n ReplayUserConfig,\n | 'debug'\n | 'enabled'\n | 'sampleRate'\n | 'maskAllInputs'\n | 'maskAllText'\n | 'flushIntervalMs'\n | 'omitRedundantInstrumentations'\n >;\n userId?: string;\n}\n\nexport interface ReplayContext {\n readonly appID: string;\n readonly userID: string;\n readonly
|
|
1
|
+
{"version":3,"file":"config.js","names":[],"sources":["../../../../src/instrumentations/replay/session-recording/config.ts"],"sourcesContent":["import type { ReplayUserConfig } from '../ReplayInstrumentation/types';\nimport type { ReplayTransport } from '../transport/types';\n\nexport interface ResolvedReplayConfig {\n readonly appID: string;\n readonly userID: string;\n readonly appVersion?: string;\n readonly serviceName?: string;\n readonly environment?: string;\n readonly replayEnabled: boolean;\n readonly replaySampleRate: number;\n readonly maskAllInputs: boolean;\n readonly maskAllText: boolean;\n readonly debug: boolean;\n readonly flushIntervalMs: number;\n readonly rrwebOptions: Omit<\n ReplayUserConfig,\n | 'debug'\n | 'enabled'\n | 'sampleRate'\n | 'maskAllInputs'\n | 'maskAllText'\n | 'flushIntervalMs'\n | 'omitRedundantInstrumentations'\n >;\n userId?: string;\n}\n\nexport interface ReplayContext {\n readonly appID: string;\n readonly userID: string;\n readonly apiURL?: string;\n readonly appVersion?: string;\n readonly serviceName?: string;\n readonly transport: ReplayTransport;\n}\n\nexport function resolveReplayConfig(\n context: ReplayContext,\n options?: ReplayUserConfig,\n recordUserSessions = true,\n): ResolvedReplayConfig {\n const {\n debug = false,\n enabled,\n sampleRate,\n maskAllInputs = true,\n maskAllText = true,\n flushIntervalMs = 5_000,\n omitRedundantInstrumentations: _omitRedundantInstrumentations,\n ...rrwebOptions\n } = options ?? {};\n\n return {\n appID: context.appID,\n appVersion: context.appVersion,\n debug,\n environment: undefined,\n flushIntervalMs,\n maskAllInputs,\n maskAllText,\n replayEnabled: enabled ?? recordUserSessions,\n replaySampleRate: sampleRate ?? 1,\n rrwebOptions,\n serviceName: context.serviceName,\n userID: context.userID,\n };\n}\n"],"mappings":";AAqCA,SAAgB,oBACd,SACA,SACA,qBAAqB,MACC;CACtB,MAAM,EACJ,QAAQ,OACR,SACA,YACA,gBAAgB,MAChB,cAAc,MACd,kBAAkB,KAClB,+BAA+B,gCAC/B,GAAG,iBACD,WAAW,EAAE;AAEjB,QAAO;EACL,OAAO,QAAQ;EACf,YAAY,QAAQ;EACpB;EACA,aAAa,KAAA;EACb;EACA;EACA;EACA,eAAe,WAAW;EAC1B,kBAAkB,cAAc;EAChC;EACA,aAAa,QAAQ;EACrB,QAAQ,QAAQ;EACjB"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_instrumentations_replay_transport_gzip = require("./gzip.cjs");
|
|
3
|
-
const
|
|
3
|
+
const require_managers_MXLConfigManager_utils = require("../../../managers/MXLConfigManager/utils.cjs");
|
|
4
4
|
//#region src/instrumentations/replay/transport/replayTransport.ts
|
|
5
5
|
/**
|
|
6
6
|
* Ported from Maple browser SDK (MIT), adapted for MXL auth and endpoints.
|
|
7
7
|
* @see https://github.com/Makisuo/maple/tree/main/packages/browser/src/replay/transport.ts
|
|
8
8
|
*/
|
|
9
|
+
const getReplayHeaders = (appID) => ({ "mxl-client-id": appID });
|
|
9
10
|
let lastWarnAt = 0;
|
|
10
11
|
function warnDropped(what, error) {
|
|
11
12
|
const now = Date.now();
|
|
@@ -14,18 +15,35 @@ function warnDropped(what, error) {
|
|
|
14
15
|
console.warn(`[mxl] session replay ${what} failed (dropping; will retry on next chunk):`, error);
|
|
15
16
|
}
|
|
16
17
|
function createReplayTransport(config) {
|
|
17
|
-
const headers =
|
|
18
|
+
const headers = getReplayHeaders(config.appID);
|
|
18
19
|
const baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
20
|
+
const otelCollectorURL = config.otelCollectorURL.replace(/\/$/, "");
|
|
19
21
|
const ignoredPathPrefixes = [
|
|
20
|
-
`${baseUrl}/
|
|
21
|
-
`${baseUrl}/
|
|
22
|
-
`${baseUrl}/
|
|
23
|
-
`${
|
|
22
|
+
`${baseUrl}/sessionReplays/`,
|
|
23
|
+
`${baseUrl}/sessionEvents`,
|
|
24
|
+
`${baseUrl}/replay`,
|
|
25
|
+
`${otelCollectorURL}/v1/logs`,
|
|
26
|
+
`${otelCollectorURL}/v1/traces`
|
|
24
27
|
];
|
|
25
28
|
const shouldIgnoreUrl = (url) => ignoredPathPrefixes.some((prefix) => url.startsWith(prefix));
|
|
29
|
+
const postReplay = async (keepalive = false) => {
|
|
30
|
+
if (!config.apiKey) return;
|
|
31
|
+
await fetch(`${baseUrl}/replay`, {
|
|
32
|
+
body: "null",
|
|
33
|
+
headers: {
|
|
34
|
+
...headers,
|
|
35
|
+
"content-type": "application/json",
|
|
36
|
+
"mxl-api-key": config.apiKey
|
|
37
|
+
},
|
|
38
|
+
keepalive,
|
|
39
|
+
method: "POST"
|
|
40
|
+
}).catch((error) => {
|
|
41
|
+
warnDropped("replay POST", error);
|
|
42
|
+
});
|
|
43
|
+
};
|
|
26
44
|
const postSessionMeta = async (row, keepalive = false) => {
|
|
27
45
|
const body = `${JSON.stringify(row)}\n`;
|
|
28
|
-
await fetch(`${baseUrl}/
|
|
46
|
+
await fetch(`${baseUrl}/sessionReplays/meta`, {
|
|
29
47
|
body,
|
|
30
48
|
headers: {
|
|
31
49
|
...headers,
|
|
@@ -40,7 +58,7 @@ function createReplayTransport(config) {
|
|
|
40
58
|
const postSessionEvents = async (rows, keepalive = false) => {
|
|
41
59
|
if (rows.length === 0) return;
|
|
42
60
|
const body = `${rows.map((row) => JSON.stringify(row)).join("\n")}\n`;
|
|
43
|
-
await fetch(`${baseUrl}/
|
|
61
|
+
await fetch(`${baseUrl}/sessionEvents`, {
|
|
44
62
|
body,
|
|
45
63
|
headers: {
|
|
46
64
|
...headers,
|
|
@@ -53,7 +71,7 @@ function createReplayTransport(config) {
|
|
|
53
71
|
});
|
|
54
72
|
};
|
|
55
73
|
const postSessionBlob = async (meta, gzipped, keepalive = false) => {
|
|
56
|
-
await fetch(`${baseUrl}/
|
|
74
|
+
await fetch(`${baseUrl}/sessionReplays/blob`, {
|
|
57
75
|
body: gzipped,
|
|
58
76
|
headers: {
|
|
59
77
|
...headers,
|
|
@@ -71,6 +89,7 @@ function createReplayTransport(config) {
|
|
|
71
89
|
});
|
|
72
90
|
};
|
|
73
91
|
return {
|
|
92
|
+
postReplay,
|
|
74
93
|
postSessionBlob,
|
|
75
94
|
postSessionEvents,
|
|
76
95
|
postSessionMeta,
|
|
@@ -79,9 +98,10 @@ function createReplayTransport(config) {
|
|
|
79
98
|
}
|
|
80
99
|
function createReplayTransportFromInit(args) {
|
|
81
100
|
return createReplayTransport({
|
|
101
|
+
apiKey: args.apiKey,
|
|
82
102
|
appID: args.appID,
|
|
83
|
-
baseUrl:
|
|
84
|
-
|
|
103
|
+
baseUrl: require_managers_MXLConfigManager_utils.getApiURL(args.apiURL),
|
|
104
|
+
otelCollectorURL: require_managers_MXLConfigManager_utils.getOtelCollectorURL(args.otelCollectorURL)
|
|
85
105
|
});
|
|
86
106
|
}
|
|
87
107
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replayTransport.cjs","names":["
|
|
1
|
+
{"version":3,"file":"replayTransport.cjs","names":["getApiURL","getOtelCollectorURL"],"sources":["../../../../src/instrumentations/replay/transport/replayTransport.ts"],"sourcesContent":["/**\n * Ported from Maple browser SDK (MIT), adapted for MXL auth and endpoints.\n * @see https://github.com/Makisuo/maple/tree/main/packages/browser/src/replay/transport.ts\n */\n\nimport {\n getApiURL,\n getOtelCollectorURL,\n} from '../../../managers/MXLConfigManager/utils';\nimport { gzip } from './gzip';\nimport type { ChunkMeta, ReplayTransport, ReplayTransportConfig } from './types';\n\nexport { gzip };\n\nconst getReplayHeaders = (appID: string): Record<string, string> => ({\n 'mxl-client-id': appID,\n});\n\nlet lastWarnAt = 0;\n\nfunction warnDropped(what: string, error: unknown): void {\n const now = Date.now();\n if (now - lastWarnAt < 30_000) {\n return;\n }\n lastWarnAt = now;\n // oxlint-disable-next-line no-console -- best-effort replay diagnostics\n console.warn(\n `[mxl] session replay ${what} failed (dropping; will retry on next chunk):`,\n error,\n );\n}\n\nexport function createReplayTransport(\n config: ReplayTransportConfig,\n): ReplayTransport {\n const headers = getReplayHeaders(config.appID);\n const baseUrl = config.baseUrl.replace(/\\/$/, '');\n const otelCollectorURL = config.otelCollectorURL.replace(/\\/$/, '');\n\n const ignoredPathPrefixes = [\n `${baseUrl}/sessionReplays/`,\n `${baseUrl}/sessionEvents`,\n `${baseUrl}/replay`,\n `${otelCollectorURL}/v1/logs`,\n `${otelCollectorURL}/v1/traces`,\n ];\n\n const shouldIgnoreUrl = (url: string): boolean =>\n ignoredPathPrefixes.some((prefix) => url.startsWith(prefix));\n\n const postReplay = async (keepalive = false): Promise<void> => {\n if (!config.apiKey) {\n return;\n }\n await fetch(`${baseUrl}/replay`, {\n body: 'null',\n headers: {\n ...headers,\n 'content-type': 'application/json',\n 'mxl-api-key': config.apiKey,\n },\n keepalive,\n method: 'POST',\n }).catch((error) => {\n warnDropped('replay POST', error);\n });\n };\n\n const postSessionMeta = async (\n row: Record<string, unknown>,\n keepalive = false,\n ): Promise<void> => {\n const body = `${JSON.stringify(row)}\\n`;\n await fetch(`${baseUrl}/sessionReplays/meta`, {\n body,\n headers: {\n ...headers,\n 'content-type': 'application/x-ndjson',\n },\n keepalive,\n method: 'POST',\n }).catch((error) => {\n warnDropped('metadata POST', error);\n });\n };\n\n const postSessionEvents = async (\n rows: ReadonlyArray<Record<string, unknown>>,\n keepalive = false,\n ): Promise<void> => {\n if (rows.length === 0) {\n return;\n }\n const body = `${rows.map((row) => JSON.stringify(row)).join('\\n')}\\n`;\n await fetch(`${baseUrl}/sessionEvents`, {\n body,\n headers: {\n ...headers,\n 'content-type': 'application/x-ndjson',\n },\n keepalive,\n method: 'POST',\n }).catch((error) => {\n warnDropped('events POST', error);\n });\n };\n\n const postSessionBlob = async (\n meta: ChunkMeta,\n gzipped: Uint8Array,\n keepalive = false,\n ): Promise<void> => {\n await fetch(`${baseUrl}/sessionReplays/blob`, {\n body: gzipped as unknown as BodyInit,\n headers: {\n ...headers,\n 'content-type': 'application/octet-stream',\n 'x-mxl-chunk-seq': String(meta.chunkSeq),\n 'x-mxl-duration-ms': String(meta.durationMs),\n 'x-mxl-event-count': String(meta.eventCount),\n 'x-mxl-is-checkpoint': meta.isCheckpoint ? '1' : '0',\n 'x-mxl-session-id': meta.sessionId,\n },\n keepalive,\n method: 'POST',\n }).catch((error) => {\n warnDropped('blob POST', error);\n });\n };\n\n return {\n postReplay,\n postSessionBlob,\n postSessionEvents,\n postSessionMeta,\n shouldIgnoreUrl,\n };\n}\n\nexport function createReplayTransportFromInit(args: {\n appID: string;\n apiKey?: string;\n apiURL?: string;\n otelCollectorURL?: string;\n}): ReplayTransport {\n return createReplayTransport({\n apiKey: args.apiKey,\n appID: args.appID,\n baseUrl: getApiURL(args.apiURL),\n otelCollectorURL: getOtelCollectorURL(args.otelCollectorURL),\n });\n}\n"],"mappings":";;;;;;;;AAcA,MAAM,oBAAoB,WAA2C,EACnE,iBAAiB,OAClB;AAED,IAAI,aAAa;AAEjB,SAAS,YAAY,MAAc,OAAsB;CACvD,MAAM,MAAM,KAAK,KAAK;AACtB,KAAI,MAAM,aAAa,IACrB;AAEF,cAAa;AAEb,SAAQ,KACN,wBAAwB,KAAK,gDAC7B,MACD;;AAGH,SAAgB,sBACd,QACiB;CACjB,MAAM,UAAU,iBAAiB,OAAO,MAAM;CAC9C,MAAM,UAAU,OAAO,QAAQ,QAAQ,OAAO,GAAG;CACjD,MAAM,mBAAmB,OAAO,iBAAiB,QAAQ,OAAO,GAAG;CAEnE,MAAM,sBAAsB;EAC1B,GAAG,QAAQ;EACX,GAAG,QAAQ;EACX,GAAG,QAAQ;EACX,GAAG,iBAAiB;EACpB,GAAG,iBAAiB;EACrB;CAED,MAAM,mBAAmB,QACvB,oBAAoB,MAAM,WAAW,IAAI,WAAW,OAAO,CAAC;CAE9D,MAAM,aAAa,OAAO,YAAY,UAAyB;AAC7D,MAAI,CAAC,OAAO,OACV;AAEF,QAAM,MAAM,GAAG,QAAQ,UAAU;GAC/B,MAAM;GACN,SAAS;IACP,GAAG;IACH,gBAAgB;IAChB,eAAe,OAAO;IACvB;GACD;GACA,QAAQ;GACT,CAAC,CAAC,OAAO,UAAU;AAClB,eAAY,eAAe,MAAM;IACjC;;CAGJ,MAAM,kBAAkB,OACtB,KACA,YAAY,UACM;EAClB,MAAM,OAAO,GAAG,KAAK,UAAU,IAAI,CAAC;AACpC,QAAM,MAAM,GAAG,QAAQ,uBAAuB;GAC5C;GACA,SAAS;IACP,GAAG;IACH,gBAAgB;IACjB;GACD;GACA,QAAQ;GACT,CAAC,CAAC,OAAO,UAAU;AAClB,eAAY,iBAAiB,MAAM;IACnC;;CAGJ,MAAM,oBAAoB,OACxB,MACA,YAAY,UACM;AAClB,MAAI,KAAK,WAAW,EAClB;EAEF,MAAM,OAAO,GAAG,KAAK,KAAK,QAAQ,KAAK,UAAU,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC;AAClE,QAAM,MAAM,GAAG,QAAQ,iBAAiB;GACtC;GACA,SAAS;IACP,GAAG;IACH,gBAAgB;IACjB;GACD;GACA,QAAQ;GACT,CAAC,CAAC,OAAO,UAAU;AAClB,eAAY,eAAe,MAAM;IACjC;;CAGJ,MAAM,kBAAkB,OACtB,MACA,SACA,YAAY,UACM;AAClB,QAAM,MAAM,GAAG,QAAQ,uBAAuB;GAC5C,MAAM;GACN,SAAS;IACP,GAAG;IACH,gBAAgB;IAChB,mBAAmB,OAAO,KAAK,SAAS;IACxC,qBAAqB,OAAO,KAAK,WAAW;IAC5C,qBAAqB,OAAO,KAAK,WAAW;IAC5C,uBAAuB,KAAK,eAAe,MAAM;IACjD,oBAAoB,KAAK;IAC1B;GACD;GACA,QAAQ;GACT,CAAC,CAAC,OAAO,UAAU;AAClB,eAAY,aAAa,MAAM;IAC/B;;AAGJ,QAAO;EACL;EACA;EACA;EACA;EACA;EACD;;AAGH,SAAgB,8BAA8B,MAK1B;AAClB,QAAO,sBAAsB;EAC3B,QAAQ,KAAK;EACb,OAAO,KAAK;EACZ,SAASA,wCAAAA,UAAU,KAAK,OAAO;EAC/B,kBAAkBC,wCAAAA,oBAAoB,KAAK,iBAAiB;EAC7D,CAAC"}
|
|
@@ -5,8 +5,9 @@ import { gzip } from "./gzip.cjs";
|
|
|
5
5
|
declare function createReplayTransport(config: ReplayTransportConfig): ReplayTransport;
|
|
6
6
|
declare function createReplayTransportFromInit(args: {
|
|
7
7
|
appID: string;
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
apiURL?: string;
|
|
10
|
+
otelCollectorURL?: string;
|
|
10
11
|
}): ReplayTransport;
|
|
11
12
|
//#endregion
|
|
12
13
|
export { createReplayTransport, createReplayTransportFromInit, gzip };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replayTransport.d.cts","names":[],"sources":["../../../../src/instrumentations/replay/transport/replayTransport.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"replayTransport.d.cts","names":[],"sources":["../../../../src/instrumentations/replay/transport/replayTransport.ts"],"mappings":";;;;iBAiCgB,qBAAA,CACd,MAAA,EAAQ,qBAAA,GACP,eAAA;AAAA,iBAyGa,6BAAA,CAA8B,IAAA;EAC5C,KAAA;EACA,MAAA;EACA,MAAA;EACA,gBAAA;AAAA,IACE,eAAA"}
|
|
@@ -5,8 +5,9 @@ import { gzip } from "./gzip.js";
|
|
|
5
5
|
declare function createReplayTransport(config: ReplayTransportConfig): ReplayTransport;
|
|
6
6
|
declare function createReplayTransportFromInit(args: {
|
|
7
7
|
appID: string;
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
apiURL?: string;
|
|
10
|
+
otelCollectorURL?: string;
|
|
10
11
|
}): ReplayTransport;
|
|
11
12
|
//#endregion
|
|
12
13
|
export { createReplayTransport, createReplayTransportFromInit, gzip };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replayTransport.d.ts","names":[],"sources":["../../../../src/instrumentations/replay/transport/replayTransport.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"replayTransport.d.ts","names":[],"sources":["../../../../src/instrumentations/replay/transport/replayTransport.ts"],"mappings":";;;;iBAiCgB,qBAAA,CACd,MAAA,EAAQ,qBAAA,GACP,eAAA;AAAA,iBAyGa,6BAAA,CAA8B,IAAA;EAC5C,KAAA;EACA,MAAA;EACA,MAAA;EACA,gBAAA;AAAA,IACE,eAAA"}
|