@cloudcare/cocos-session-replay 0.1.0-alpha.6 → 0.1.0-alpha.8
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 +64 -1
- package/dist/creator2/core/client.d.ts +57 -0
- package/dist/creator2/core/client.d.ts.map +1 -1
- package/dist/creator2/core/client.js +58 -2
- package/dist/creator2/core/client.js.map +1 -1
- package/dist/creator2/core/replay-diagnostics.d.ts +3 -5
- package/dist/creator2/core/replay-diagnostics.d.ts.map +1 -1
- package/dist/creator2/core/replay-diagnostics.js.map +1 -1
- package/dist/creator2/core/replay-encoding.d.ts +2 -0
- package/dist/creator2/core/replay-encoding.d.ts.map +1 -1
- package/dist/creator2/core/replay-encoding.js +4 -1
- package/dist/creator2/core/replay-encoding.js.map +1 -1
- package/dist/creator2/core/replay.d.ts +3 -2
- package/dist/creator2/core/replay.d.ts.map +1 -1
- package/dist/creator2/core/replay.js +56 -50
- package/dist/creator2/core/replay.js.map +1 -1
- package/dist/creator2/core/types.d.ts +17 -11
- package/dist/creator2/core/types.d.ts.map +1 -1
- package/dist/creator2/core/validation.d.ts +2 -2
- package/dist/creator2/core/validation.d.ts.map +1 -1
- package/dist/creator2/core/validation.js +40 -14
- package/dist/creator2/core/validation.js.map +1 -1
- package/dist/creator2/core/version.d.ts +1 -1
- package/dist/creator2/core/version.js +1 -1
- package/dist/creator3/core/client.d.ts +57 -0
- package/dist/creator3/core/client.d.ts.map +1 -1
- package/dist/creator3/core/client.js +59 -3
- package/dist/creator3/core/client.js.map +1 -1
- package/dist/creator3/core/replay-diagnostics.d.ts +3 -5
- package/dist/creator3/core/replay-diagnostics.d.ts.map +1 -1
- package/dist/creator3/core/replay-diagnostics.js.map +1 -1
- package/dist/creator3/core/replay-encoding.d.ts +2 -0
- package/dist/creator3/core/replay-encoding.d.ts.map +1 -1
- package/dist/creator3/core/replay-encoding.js +4 -1
- package/dist/creator3/core/replay-encoding.js.map +1 -1
- package/dist/creator3/core/replay.d.ts +3 -2
- package/dist/creator3/core/replay.d.ts.map +1 -1
- package/dist/creator3/core/replay.js +76 -65
- package/dist/creator3/core/replay.js.map +1 -1
- package/dist/creator3/core/types.d.ts +17 -11
- package/dist/creator3/core/types.d.ts.map +1 -1
- package/dist/creator3/core/validation.d.ts +2 -2
- package/dist/creator3/core/validation.d.ts.map +1 -1
- package/dist/creator3/core/validation.js +26 -14
- package/dist/creator3/core/validation.js.map +1 -1
- package/dist/creator3/core/version.d.ts +1 -1
- package/dist/creator3/core/version.js +1 -1
- package/dist/creator3/creator3/capture.d.ts +8 -0
- package/dist/creator3/creator3/capture.d.ts.map +1 -1
- package/dist/creator3/creator3/capture.js +171 -40
- package/dist/creator3/creator3/capture.js.map +1 -1
- package/dist/creator3/creator3/pointer.d.ts +3 -1
- package/dist/creator3/creator3/pointer.d.ts.map +1 -1
- package/dist/creator3/creator3/pointer.js +63 -8
- package/dist/creator3/creator3/pointer.js.map +1 -1
- package/native/android/src/main/java/com/ft/sdk/cocos/FTCocosReplayBridge.java +13 -2
- package/native/ios/FTCocosReplayBridge.m +18 -2
- package/native/ios/FTCocosReplayBridge.podspec +4 -4
- package/native/ios/Package.swift +3 -3
- package/native-integration.json +4 -4
- package/package.json +2 -2
- package/dist/creator2/core/replay-budget.d.ts +0 -28
- package/dist/creator2/core/replay-budget.d.ts.map +0 -1
- package/dist/creator2/core/replay-budget.js +0 -126
- package/dist/creator2/core/replay-budget.js.map +0 -1
- package/dist/creator3/core/replay-budget.d.ts +0 -28
- package/dist/creator3/core/replay-budget.d.ts.map +0 -1
- package/dist/creator3/core/replay-budget.js +0 -118
- package/dist/creator3/core/replay-budget.js.map +0 -1
|
@@ -15,11 +15,68 @@ export declare class FTCocosReplaySDK {
|
|
|
15
15
|
readonly logger: FTCocosSDK['logger'];
|
|
16
16
|
readonly trace: FTCocosSDK['trace'];
|
|
17
17
|
constructor(base: FTCocosSDK, replay: FTSessionReplay, capture: FTReplayCapture, configure: (config: FTSessionReplayConfig | undefined) => void);
|
|
18
|
+
/**
|
|
19
|
+
* Initializes the base SDK and configured modules for a standalone Cocos app.
|
|
20
|
+
* Supplying `config.replay` also enables native Session Replay and starts
|
|
21
|
+
* canvas capture. Omitting it does not start Replay.
|
|
22
|
+
*
|
|
23
|
+
* Call once during application startup, after composing with withSessionReplay.
|
|
24
|
+
* Do not combine with {@link attach}, which requires a native host-owned SDK.
|
|
25
|
+
*
|
|
26
|
+
* @param config - Base SDK settings, optional modules, and Replay settings.
|
|
27
|
+
* @throws If the SDK is already started or attached, Replay settings are
|
|
28
|
+
* invalid, or the required native Replay integration is unavailable.
|
|
29
|
+
*/
|
|
18
30
|
start(config: FTCocosReplayConfig): void;
|
|
31
|
+
/**
|
|
32
|
+
* Attaches Cocos tracking to an SDK initialized by the native Hybrid host.
|
|
33
|
+
* Supplying `config.replay` prepares canvas capture for {@link enterCocos};
|
|
34
|
+
* capture does not start until that method is called. The native host owns
|
|
35
|
+
* native SDK and Replay initialization, including sampling settings.
|
|
36
|
+
*
|
|
37
|
+
* Call before the first {@link enterCocos}. Repeated calls after attachment
|
|
38
|
+
* have no effect and do not update the configuration.
|
|
39
|
+
*
|
|
40
|
+
* @param config - Optional Cocos automatic tracking and Hybrid Replay settings.
|
|
41
|
+
* @throws If standalone initialization has already started, Replay settings
|
|
42
|
+
* are invalid, or the required native Replay integration is unavailable.
|
|
43
|
+
*/
|
|
19
44
|
attach(config?: FTCocosHybridReplayConfig): void;
|
|
45
|
+
/**
|
|
46
|
+
* Selects the Cocos camera used for subsequent Session Replay captures.
|
|
47
|
+
* Update it when changing scenes if the selected camera belongs to the old
|
|
48
|
+
* scene. Selecting a camera does not start Replay capture.
|
|
49
|
+
*
|
|
50
|
+
* @param camera - A Camera component from the matching Creator engine in the
|
|
51
|
+
* active scene, or null/undefined to restore automatic camera selection.
|
|
52
|
+
*/
|
|
20
53
|
setReplayCamera(camera: unknown): void;
|
|
54
|
+
/**
|
|
55
|
+
* Starts Cocos automatic tracking and any Replay capture enabled by
|
|
56
|
+
* {@link attach} in Hybrid mode. Repeated calls while entered have no effect.
|
|
57
|
+
*
|
|
58
|
+
* @param options - Options for the Cocos view being entered. Supply `viewName`
|
|
59
|
+
* when automatic scene tracking is disabled.
|
|
60
|
+
* @throws If the SDK is not attached in Hybrid mode, the required view name
|
|
61
|
+
* is missing, or tracking or Replay startup fails.
|
|
62
|
+
*/
|
|
21
63
|
enterCocos(options?: FTCocosEnterOptions): void;
|
|
64
|
+
/**
|
|
65
|
+
* Stops Cocos automatic tracking and Hybrid Replay capture while keeping the
|
|
66
|
+
* native host SDK running. Call {@link enterCocos} to resume Cocos tracking.
|
|
67
|
+
* Has no effect before attachment or when Cocos has already been left.
|
|
68
|
+
*
|
|
69
|
+
* @throws If the SDK was started in standalone mode, or tracking or Replay
|
|
70
|
+
* cleanup fails.
|
|
71
|
+
*/
|
|
22
72
|
leaveCocos(): void;
|
|
73
|
+
/**
|
|
74
|
+
* Stops standalone Cocos tracking, Session Replay, and the base native SDK.
|
|
75
|
+
* Has no effect if the base SDK is idle. Hybrid applications must use
|
|
76
|
+
* {@link leaveCocos} because the native host owns SDK shutdown.
|
|
77
|
+
*
|
|
78
|
+
* @throws If the SDK is attached in Hybrid mode or shutdown cleanup fails.
|
|
79
|
+
*/
|
|
23
80
|
shutdown(): void;
|
|
24
81
|
}
|
|
25
82
|
export declare function composeSessionReplay(base: FTCocosSDK, engine: 'creator2' | 'creator3', create: () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../../src/session-replay/core/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAC1G,OAAO,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAChG,OAAO,KAAK,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,qBAAqB,EAA+B,MAAM,YAAY,CAAC;AAIrI,MAAM,WAAW,eAAgB,SAAQ,eAAe;IAAG,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;CAAE;AAE9F,mFAAmF;AACnF,qBAAa,gBAAgB;IAOzB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,QAAQ,CAAC,MAAM,EAAE,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAT5B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IACtC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;gBAGjB,IAAI,EAAE,UAAU,EACxB,MAAM,EAAE,eAAe,EACf,OAAO,EAAE,eAAe,EACxB,SAAS,EAAE,CAAC,MAAM,EAAE,qBAAqB,GAAG,SAAS,KAAK,IAAI;IAQjF,KAAK,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI;IAMxC,MAAM,CAAC,MAAM,GAAE,yBAA8B,GAAG,IAAI;IAMpD,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../../src/session-replay/core/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAC1G,OAAO,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAChG,OAAO,KAAK,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,qBAAqB,EAA+B,MAAM,YAAY,CAAC;AAIrI,MAAM,WAAW,eAAgB,SAAQ,eAAe;IAAG,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;CAAE;AAE9F,mFAAmF;AACnF,qBAAa,gBAAgB;IAOzB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,QAAQ,CAAC,MAAM,EAAE,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAT5B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IACtC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;gBAGjB,IAAI,EAAE,UAAU,EACxB,MAAM,EAAE,eAAe,EACf,OAAO,EAAE,eAAe,EACxB,SAAS,EAAE,CAAC,MAAM,EAAE,qBAAqB,GAAG,SAAS,KAAK,IAAI;IAQjF;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI;IAMxC;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,MAAM,GAAE,yBAA8B,GAAG,IAAI;IAMpD;;;;;;;OAOG;IACH,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAEtC;;;;;;;;OAQG;IACH,UAAU,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,IAAI;IAE/C;;;;;;;OAOG;IACH,UAAU,IAAI,IAAI;IAElB;;;;;;OAMG;IACH,QAAQ,IAAI,IAAI;CACjB;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,UAAU,GAAG,UAAU,EAC/B,MAAM,EAAE,MAAM;IAAE,SAAS,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,qBAAqB,CAAA;CAAE,GACxG,gBAAgB,CAiClB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FTSessionReplay } from './replay.js';
|
|
2
2
|
import { FT_COCOS_REPLAY_VERSION } from './version.js';
|
|
3
|
-
import { replayImagePolicy, captureFps,
|
|
3
|
+
import { replayImagePolicy, captureFps, validatedReplaySamplingConfig } from './validation.js';
|
|
4
4
|
/** Typed Replay facade; the supplied base SDK continues to own lifecycle state. */
|
|
5
5
|
export class FTCocosReplaySDK {
|
|
6
6
|
constructor(base, replay, capture, configure) {
|
|
@@ -13,6 +13,18 @@ export class FTCocosReplaySDK {
|
|
|
13
13
|
this.logger = base.logger;
|
|
14
14
|
this.trace = base.trace;
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Initializes the base SDK and configured modules for a standalone Cocos app.
|
|
18
|
+
* Supplying `config.replay` also enables native Session Replay and starts
|
|
19
|
+
* canvas capture. Omitting it does not start Replay.
|
|
20
|
+
*
|
|
21
|
+
* Call once during application startup, after composing with withSessionReplay.
|
|
22
|
+
* Do not combine with {@link attach}, which requires a native host-owned SDK.
|
|
23
|
+
*
|
|
24
|
+
* @param config - Base SDK settings, optional modules, and Replay settings.
|
|
25
|
+
* @throws If the SDK is already started or attached, Replay settings are
|
|
26
|
+
* invalid, or the required native Replay integration is unavailable.
|
|
27
|
+
*/
|
|
16
28
|
start(config) {
|
|
17
29
|
const { replay, ...base } = config;
|
|
18
30
|
this.configure(replay);
|
|
@@ -23,6 +35,19 @@ export class FTCocosReplaySDK {
|
|
|
23
35
|
this.configure(undefined);
|
|
24
36
|
}
|
|
25
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Attaches Cocos tracking to an SDK initialized by the native Hybrid host.
|
|
40
|
+
* Supplying `config.replay` prepares canvas capture for {@link enterCocos};
|
|
41
|
+
* capture does not start until that method is called. The native host owns
|
|
42
|
+
* native SDK and Replay initialization, including sampling settings.
|
|
43
|
+
*
|
|
44
|
+
* Call before the first {@link enterCocos}. Repeated calls after attachment
|
|
45
|
+
* have no effect and do not update the configuration.
|
|
46
|
+
*
|
|
47
|
+
* @param config - Optional Cocos automatic tracking and Hybrid Replay settings.
|
|
48
|
+
* @throws If standalone initialization has already started, Replay settings
|
|
49
|
+
* are invalid, or the required native Replay integration is unavailable.
|
|
50
|
+
*/
|
|
26
51
|
attach(config = {}) {
|
|
27
52
|
const { replay, ...base } = config;
|
|
28
53
|
this.configure(replay);
|
|
@@ -33,9 +58,41 @@ export class FTCocosReplaySDK {
|
|
|
33
58
|
this.configure(undefined);
|
|
34
59
|
}
|
|
35
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Selects the Cocos camera used for subsequent Session Replay captures.
|
|
63
|
+
* Update it when changing scenes if the selected camera belongs to the old
|
|
64
|
+
* scene. Selecting a camera does not start Replay capture.
|
|
65
|
+
*
|
|
66
|
+
* @param camera - A Camera component from the matching Creator engine in the
|
|
67
|
+
* active scene, or null/undefined to restore automatic camera selection.
|
|
68
|
+
*/
|
|
36
69
|
setReplayCamera(camera) { this.capture.setCamera(camera); }
|
|
70
|
+
/**
|
|
71
|
+
* Starts Cocos automatic tracking and any Replay capture enabled by
|
|
72
|
+
* {@link attach} in Hybrid mode. Repeated calls while entered have no effect.
|
|
73
|
+
*
|
|
74
|
+
* @param options - Options for the Cocos view being entered. Supply `viewName`
|
|
75
|
+
* when automatic scene tracking is disabled.
|
|
76
|
+
* @throws If the SDK is not attached in Hybrid mode, the required view name
|
|
77
|
+
* is missing, or tracking or Replay startup fails.
|
|
78
|
+
*/
|
|
37
79
|
enterCocos(options) { this.base.enterCocos(options); }
|
|
80
|
+
/**
|
|
81
|
+
* Stops Cocos automatic tracking and Hybrid Replay capture while keeping the
|
|
82
|
+
* native host SDK running. Call {@link enterCocos} to resume Cocos tracking.
|
|
83
|
+
* Has no effect before attachment or when Cocos has already been left.
|
|
84
|
+
*
|
|
85
|
+
* @throws If the SDK was started in standalone mode, or tracking or Replay
|
|
86
|
+
* cleanup fails.
|
|
87
|
+
*/
|
|
38
88
|
leaveCocos() { this.base.leaveCocos(); }
|
|
89
|
+
/**
|
|
90
|
+
* Stops standalone Cocos tracking, Session Replay, and the base native SDK.
|
|
91
|
+
* Has no effect if the base SDK is idle. Hybrid applications must use
|
|
92
|
+
* {@link leaveCocos} because the native host owns SDK shutdown.
|
|
93
|
+
*
|
|
94
|
+
* @throws If the SDK is attached in Hybrid mode or shutdown cleanup fails.
|
|
95
|
+
*/
|
|
39
96
|
shutdown() { this.base.shutdown(); }
|
|
40
97
|
}
|
|
41
98
|
export function composeSessionReplay(base, engine, create) {
|
|
@@ -54,8 +111,7 @@ export function composeSessionReplay(base, engine, create) {
|
|
|
54
111
|
if (pending === undefined)
|
|
55
112
|
return;
|
|
56
113
|
validateConfig(pending);
|
|
57
|
-
|
|
58
|
-
samplingRate(pending.sessionOnErrorSampleRate, 'replay.sessionOnErrorSampleRate');
|
|
114
|
+
validatedReplaySamplingConfig(pending);
|
|
59
115
|
validateNativeReplay(transport, false);
|
|
60
116
|
},
|
|
61
117
|
afterStart: () => { if (pending !== undefined)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../../../src/session-replay/core/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAoD,MAAM,aAAa,CAAC;AAEhG,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../../../src/session-replay/core/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
export type FTReplaySkipReason = 'dedupe' | 'approx_static' | '
|
|
1
|
+
export type FTReplaySkipReason = 'dedupe' | 'approx_static' | 'image_rejected' | 'busy' | 'error';
|
|
2
2
|
export type FTReplayDiagnosticEvent = {
|
|
3
3
|
type: 'capture_attempt';
|
|
4
4
|
timestamp: number;
|
|
5
|
-
usedBytes: number;
|
|
6
|
-
maxBytesPerMinute: number;
|
|
7
5
|
} | {
|
|
8
6
|
type: 'capture_skipped';
|
|
9
7
|
timestamp: number;
|
|
@@ -11,12 +9,12 @@ export type FTReplayDiagnosticEvent = {
|
|
|
11
9
|
} | {
|
|
12
10
|
type: 'image_saved';
|
|
13
11
|
timestamp: number;
|
|
14
|
-
byteSize
|
|
12
|
+
byteSize?: number;
|
|
15
13
|
width: number;
|
|
16
14
|
height: number;
|
|
17
15
|
mimeType?: string;
|
|
18
16
|
priority: boolean;
|
|
19
|
-
byteSizeSource: 'native' | '
|
|
17
|
+
byteSizeSource: 'native' | 'unavailable';
|
|
20
18
|
} | {
|
|
21
19
|
type: 'segment_encoded';
|
|
22
20
|
timestamp: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-diagnostics.d.ts","sourceRoot":"","sources":["../../../../../src/session-replay/core/replay-diagnostics.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAC1B,QAAQ,GACR,eAAe,GACf,
|
|
1
|
+
{"version":3,"file":"replay-diagnostics.d.ts","sourceRoot":"","sources":["../../../../../src/session-replay/core/replay-diagnostics.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAC1B,QAAQ,GACR,eAAe,GACf,gBAAgB,GAChB,MAAM,GACN,OAAO,CAAC;AAEZ,MAAM,MAAM,uBAAuB,GAC/B;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,GAC1E;IACA,IAAI,EAAE,aAAa,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,QAAQ,GAAG,aAAa,CAAC;CAC1C,GACC;IACA,IAAI,EAAE,iBAAiB,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;CACnB,GACC;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAA;CAAE,GAClF;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAmBlD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiB1D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-diagnostics.js","sourceRoot":"","sources":["../../../../../src/session-replay/core/replay-diagnostics.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"replay-diagnostics.js","sourceRoot":"","sources":["../../../../../src/session-replay/core/replay-diagnostics.ts"],"names":[],"mappings":"AAqCA,gFAAgF;AAChF,MAAM,UAAU,oBAAoB,CAAC,KAA8B;IACjE,MAAM,QAAQ,GAAI,UAAuC,CAAC,sCAAsC,CAAC;IACjG,IAAI,OAAO,QAAQ,KAAK,UAAU;QAAE,OAAO;IAC3C,IAAI,CAAC;QACH,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC;IAAC,WAAM,CAAC;QACP,sEAAsE;IACxE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,IAAI,GAAG,IAAI;YAAE,KAAK,IAAI,CAAC,CAAC;aACvB,IAAI,IAAI,GAAG,KAAK;YAAE,KAAK,IAAI,CAAC,CAAC;aAC7B,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,IAAI,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YACtE,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YACxC,IAAI,GAAG,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,EAAE,CAAC;gBACnC,KAAK,IAAI,CAAC,CAAC;gBACX,KAAK,IAAI,CAAC,CAAC;YACb,CAAC;iBAAM,CAAC;gBACN,KAAK,IAAI,CAAC,CAAC;YACb,CAAC;QACH,CAAC;;YAAM,KAAK,IAAI,CAAC,CAAC;IACpB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -2,11 +2,13 @@ import type { FTRUMContext } from './types.js';
|
|
|
2
2
|
export interface FTReplayImageRecord {
|
|
3
3
|
context: FTRUMContext;
|
|
4
4
|
resourceId: string;
|
|
5
|
+
/** Logical display bounds, independent of the resource's encoded pixels. */
|
|
5
6
|
width: number;
|
|
6
7
|
height: number;
|
|
7
8
|
mimeType?: `image/${string}`;
|
|
8
9
|
timestamp: number;
|
|
9
10
|
contextChanged: boolean;
|
|
11
|
+
viewportChanged?: boolean;
|
|
10
12
|
pointerEvents?: FTReplayPointerRecord[];
|
|
11
13
|
}
|
|
12
14
|
export interface FTReplayPointerRecord {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-encoding.d.ts","sourceRoot":"","sources":["../../../../../src/session-replay/core/replay-encoding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,YAAY,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,qBAAqB,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,YAAY,CAAC;IACtB,aAAa,EAAE,qBAAqB,EAAE,CAAC;CACxC;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,mBAAmB,GAAG;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,CAiCA;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,sBAAsB,GAAG;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,CAMA"}
|
|
1
|
+
{"version":3,"file":"replay-encoding.d.ts","sourceRoot":"","sources":["../../../../../src/session-replay/core/replay-encoding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,YAAY,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,qBAAqB,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,YAAY,CAAC;IACtB,aAAa,EAAE,qBAAqB,EAAE,CAAC;CACxC;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,mBAAmB,GAAG;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,CAiCA;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,sBAAsB,GAAG;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,CAMA"}
|
|
@@ -16,8 +16,11 @@ export function encodeReplayImageRecord(input) {
|
|
|
16
16
|
shapeStyle: null,
|
|
17
17
|
};
|
|
18
18
|
const records = [];
|
|
19
|
+
if (input.contextChanged || input.viewportChanged) {
|
|
20
|
+
records.push({ type: 4, data: { width: input.width, height: input.height }, timestamp: input.timestamp });
|
|
21
|
+
}
|
|
19
22
|
if (input.contextChanged) {
|
|
20
|
-
records.push({ type:
|
|
23
|
+
records.push({ type: 6, data: { has_focus: true }, timestamp: input.timestamp });
|
|
21
24
|
}
|
|
22
25
|
records.push({
|
|
23
26
|
type: 10,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-encoding.js","sourceRoot":"","sources":["../../../../../src/session-replay/core/replay-encoding.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"replay-encoding.js","sourceRoot":"","sources":["../../../../../src/session-replay/core/replay-encoding.ts"],"names":[],"mappings":"AA4BA,MAAM,UAAU,uBAAuB,CAAC,KAA0B;;IAIhE,MAAM,SAAS,GAAG;QAChB,EAAE,EAAE,CAAC;QACL,IAAI,EAAE,OAAO;QACb,CAAC,EAAE,CAAC;QACJ,CAAC,EAAE,CAAC;QACJ,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,MAAM,EAAE,IAAI;QACZ,MAAM,EAAE,IAAI;QACZ,IAAI,EAAE,IAAI;QACV,OAAO,EAAE,KAAK;QACd,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,UAAU,EAAE,IAAI;KACjB,CAAC;IACF,MAAM,OAAO,GAAc,EAAE,CAAC;IAC9B,IAAI,KAAK,CAAC,cAAc,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IAC5G,CAAC;IACD,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,CAAC,IAAI,CAAC;QACX,IAAI,EAAE,EAAE;QACR,IAAI,EAAE,EAAE,UAAU,EAAE,CAAC,SAAS,CAAC,EAAE;QACjC,SAAS,EAAE,KAAK,CAAC,SAAS;KAC3B,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,GAAG,CAAA,MAAA,KAAK,CAAC,aAAa,0CAAE,GAAG,CAAC,aAAa,CAAC,KAAI,EAAE,CAAC,CAAC;IAC/D,OAAO;QACL,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC;QAC/C,WAAW,EAAE,OAAO,CAAC,MAAM;KAC5B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,KAA6B;IAItE,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACvD,OAAO;QACL,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC;QAC/C,WAAW,EAAE,OAAO,CAAC,MAAM;KAC5B,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,OAA8B;IACnD,OAAO;QACL,IAAI,EAAE,EAAE;QACR,IAAI,EAAE;YACJ,MAAM,EAAE,CAAC;YACT,gBAAgB,EAAE,OAAO,CAAC,SAAS;YACnC,WAAW,EAAE,OAAO;YACpB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,CAAC,EAAE,OAAO,CAAC,CAAC;YACZ,CAAC,EAAE,OAAO,CAAC,CAAC;SACb;QACD,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,OAAqB,EAAE,OAAkB;IAC/D,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,OAAO;QACP,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -8,6 +8,8 @@ export interface FTCanvasCapture {
|
|
|
8
8
|
capture(maxImageDimension: number): Promise<FTCapturedFrame | undefined>;
|
|
9
9
|
persist(frame: FTCapturedFrame, fingerprint: string): Promise<FTStoredFrame>;
|
|
10
10
|
disposeStoredFrame(frame: FTStoredFrame): void | Promise<void>;
|
|
11
|
+
/** Cancel pending GPU capture and release reusable capture resources. */
|
|
12
|
+
dispose?(): void;
|
|
11
13
|
setPrivacy(node: unknown, mode: 'mask' | 'hide' | 'unmask'): void;
|
|
12
14
|
}
|
|
13
15
|
export interface FTReplayPointerEvent {
|
|
@@ -47,13 +49,12 @@ export declare class FTSessionReplay {
|
|
|
47
49
|
private captureGeneration;
|
|
48
50
|
private config;
|
|
49
51
|
private imagePolicy;
|
|
50
|
-
private budget;
|
|
51
52
|
private lastFingerprint;
|
|
52
53
|
private lastContextKey;
|
|
53
54
|
private lastPrivacyKey;
|
|
54
55
|
private lastFrameSample;
|
|
55
56
|
private lastImageTimestamp;
|
|
56
|
-
private
|
|
57
|
+
private lastDisplaySize;
|
|
57
58
|
private lastViewportSize;
|
|
58
59
|
private imagePolicyEnabled;
|
|
59
60
|
private supportsSaveImageV2;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../../../../src/session-replay/core/replay.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../../../../src/session-replay/core/replay.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,KAAK,EACV,eAAe,EAEf,eAAe,EAEf,qBAAqB,EACrB,aAAa,EACd,MAAM,YAAY,CAAC;AAQpB,MAAM,WAAW,eAAe;IAC9B,eAAe,CAAC,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAClE,OAAO,CAAC,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC;IACzE,OAAO,CAAC,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC7E,kBAAkB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,yEAAyE;IACzE,OAAO,CAAC,IAAI,IAAI,CAAC;IACjB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;CACnE;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,eAAe,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAC9E;AAOD,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B;AAOD,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,UAAU,CAAC;IACtB,GAAG,EAAE,UAAU,CAAC;CACjB;AAED,4CAA4C;AAC5C,qBAAa,eAAe;IAwBxB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;IAC/B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;IA1BlC,OAAO,CAAC,KAAK,CAA4C;IACzD,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,IAAI,CAA4C;IACxD,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,MAAM,CAA0E;IACxF,OAAO,CAAC,WAAW,CAAsD;IACzE,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,cAAc,CAAqB;IAC3C,OAAO,CAAC,cAAc,CAAqB;IAC3C,OAAO,CAAC,eAAe,CAAkC;IACzD,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,eAAe,CAAgD;IACvE,OAAO,CAAC,gBAAgB,CAAgD;IACxE,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,mBAAmB,CAAsB;IACjD,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,oBAAoB,CAA8B;IAC1D,OAAO,CAAC,mBAAmB,CAA2B;gBAGnC,SAAS,EAAE,iBAAiB,EAC5B,OAAO,EAAE,eAAe,EACxB,aAAa,CAAC,EAAE,qBAAqB,YAAA,EACrC,cAAc,CAAC,GAAE,MAAM,IAAI,aAAA;IAG9C;;;;;OAKG;IACH,KAAK,CAAC,MAAM,GAAE,qBAA0B,GAAG,IAAI;IAiD/C,OAAO,CAAC,gBAAgB;IAYxB,uEAAuE;IACvE,IAAI,IAAI,IAAI;IAUZ;;;;;;;;;;OAUG;IACH,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,IAAI;IAgJjE,OAAO,CAAC,YAAY;IA4BpB,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,QAAQ;IAsBhB,OAAO,CAAC,WAAW;YAKL,SAAS;IAmDvB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,oBAAoB;IAqB5B,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,iBAAiB;CAK1B;AAgCD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,yBAAyB,CAqBpF;AAkBD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,cAAc,SAAO,GACpB,mBAAmB,CAmBrB;AAED,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,mBAAmB,GAAG,SAAS,EACzC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAoCT;AAQD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAiB1D;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,eAAe,EAAE,GACzB,IAAI,CAiBN"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { encodeReplayImageRecord, encodeReplayPointerRecords, } from './replay-encoding.js';
|
|
2
|
-
import { FTReplayBudget } from './replay-budget.js';
|
|
3
2
|
import { emitReplayDiagnostic, replayUtf8ByteLength } from './replay-diagnostics.js';
|
|
4
|
-
import { captureFps, replayImagePolicy,
|
|
3
|
+
import { captureFps, replayImagePolicy, validatedReplaySamplingConfig, } from './validation.js';
|
|
5
4
|
const MAX_PENDING_POINTER_EVENTS = 512;
|
|
6
5
|
// Approximate comparisons must not hide small animations indefinitely.
|
|
7
6
|
const MAX_APPROXIMATE_STATIC_MS = 2000;
|
|
@@ -20,7 +19,6 @@ export class FTSessionReplay {
|
|
|
20
19
|
this.captureGeneration = 0;
|
|
21
20
|
this.config = { captureFps: 1 };
|
|
22
21
|
this.imagePolicy = replayImagePolicy({});
|
|
23
|
-
this.budget = new FTReplayBudget(this.imagePolicy);
|
|
24
22
|
this.imagePolicyEnabled = false;
|
|
25
23
|
this.recordCounts = new Map();
|
|
26
24
|
this.recordTouches = false;
|
|
@@ -39,11 +37,10 @@ export class FTSessionReplay {
|
|
|
39
37
|
}
|
|
40
38
|
if (this.mode === 'standalone')
|
|
41
39
|
return;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
this.configureCapture(config);
|
|
40
|
+
const payload = validatedReplaySamplingConfig(config);
|
|
41
|
+
this.configureCapture(payload);
|
|
45
42
|
(_a = this.validateNative) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
46
|
-
this.transport.invoke('replay.configure',
|
|
43
|
+
this.transport.invoke('replay.configure', payload);
|
|
47
44
|
this.mode = 'standalone';
|
|
48
45
|
this.startCapture();
|
|
49
46
|
}
|
|
@@ -89,7 +86,6 @@ export class FTSessionReplay {
|
|
|
89
86
|
}
|
|
90
87
|
this.config = { captureFps: captureFps(config.captureFps) };
|
|
91
88
|
this.imagePolicy = replayImagePolicy(config);
|
|
92
|
-
this.budget = new FTReplayBudget(this.imagePolicy);
|
|
93
89
|
// Lossy image MIME must be validated against the deployed player before
|
|
94
90
|
// becoming an implicit default. Supplying imagePolicy opts into V2 now.
|
|
95
91
|
this.imagePolicyEnabled = config.imagePolicy !== undefined;
|
|
@@ -131,7 +127,7 @@ export class FTSessionReplay {
|
|
|
131
127
|
this.busy = true;
|
|
132
128
|
let stored;
|
|
133
129
|
let context;
|
|
134
|
-
let pointerSize = this.
|
|
130
|
+
let pointerSize = this.lastDisplaySize;
|
|
135
131
|
try {
|
|
136
132
|
context = this.readContext();
|
|
137
133
|
if (!context)
|
|
@@ -143,33 +139,28 @@ export class FTSessionReplay {
|
|
|
143
139
|
&& viewportSize !== undefined
|
|
144
140
|
&& (viewportSize.width !== this.lastViewportSize.width
|
|
145
141
|
|| viewportSize.height !== this.lastViewportSize.height);
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
: undefined;
|
|
142
|
+
// Do not send coordinates for a new viewport before its image and
|
|
143
|
+
// metadata have been accepted. Keep pending touches for that capture.
|
|
144
|
+
if (contextChanged || viewportChanged)
|
|
145
|
+
pointerSize = undefined;
|
|
151
146
|
const now = Date.now();
|
|
152
|
-
const decision = this.budget.decide(now, priorityKey);
|
|
153
147
|
emitReplayDiagnostic({
|
|
154
148
|
type: 'capture_attempt',
|
|
155
149
|
timestamp: now,
|
|
156
|
-
usedBytes: decision.usedBytes,
|
|
157
|
-
maxBytesPerMinute: this.imagePolicy.maxBytesPerMinute,
|
|
158
150
|
});
|
|
159
|
-
|
|
160
|
-
emitReplayDiagnostic({
|
|
161
|
-
type: 'capture_skipped',
|
|
162
|
-
timestamp: now,
|
|
163
|
-
reason: decision.reason || 'budget',
|
|
164
|
-
});
|
|
165
|
-
return pointerSize ? this.writePendingPointers(context, pointerSize.width, pointerSize.height) : false;
|
|
166
|
-
}
|
|
167
|
-
const frame = await this.capture.capture(decision.maxImageDimension);
|
|
151
|
+
const frame = await this.capture.capture(this.imagePolicy.maxImageDimension);
|
|
168
152
|
if (generation !== this.captureGeneration)
|
|
169
153
|
return false;
|
|
170
154
|
if (!frame)
|
|
171
155
|
return false;
|
|
172
|
-
|
|
156
|
+
// Native encoding may shrink the resource to meet the per-image limit, but
|
|
157
|
+
// the replay canvas, image bounds and touch coordinates stay in one
|
|
158
|
+
// logical space based on the configured maximum size.
|
|
159
|
+
const displaySize = viewportSize
|
|
160
|
+
? scaledReplayViewport(viewportSize, this.imagePolicy.maxImageDimension)
|
|
161
|
+
: this.lastDisplaySize
|
|
162
|
+
? this.lastDisplaySize
|
|
163
|
+
: { width: frame.width, height: frame.height };
|
|
173
164
|
applyPrivacyRegions(frame.rgba, frame.width, frame.height, frame.privacyRegions || []);
|
|
174
165
|
const fingerprint = frameFingerprint(frame.rgba);
|
|
175
166
|
const privacyKey = privacyRegionsKey(frame.privacyRegions || []);
|
|
@@ -191,27 +182,28 @@ export class FTSessionReplay {
|
|
|
191
182
|
timestamp: now,
|
|
192
183
|
reason: duplicate ? 'dedupe' : 'approx_static',
|
|
193
184
|
});
|
|
194
|
-
return this.writePendingPointers(context,
|
|
185
|
+
return pointerSize ? this.writePendingPointers(context, pointerSize.width, pointerSize.height) : false;
|
|
195
186
|
}
|
|
196
187
|
stored = await this.capture.persist(frame, fingerprint);
|
|
197
188
|
if (generation !== this.captureGeneration)
|
|
198
189
|
return false;
|
|
199
|
-
const saved = await this.saveImage(stored,
|
|
190
|
+
const saved = await this.saveImage(stored, this.imagePolicy.compressionQuality, this.imagePolicy.maxFrameBytes);
|
|
200
191
|
if (generation !== this.captureGeneration)
|
|
201
192
|
return false;
|
|
202
193
|
if (!saved) {
|
|
203
|
-
emitReplayDiagnostic({ type: 'capture_skipped', timestamp: now, reason: '
|
|
204
|
-
return this.writePendingPointers(context,
|
|
194
|
+
emitReplayDiagnostic({ type: 'capture_skipped', timestamp: now, reason: 'image_rejected' });
|
|
195
|
+
return pointerSize ? this.writePendingPointers(context, pointerSize.width, pointerSize.height) : false;
|
|
205
196
|
}
|
|
206
|
-
const pendingPointers = this.scaledPendingPointers(
|
|
197
|
+
const pendingPointers = this.scaledPendingPointers(displaySize.width, displaySize.height);
|
|
207
198
|
const encoded = encodeReplayImageRecord({
|
|
208
199
|
context,
|
|
209
200
|
resourceId: saved.resourceId,
|
|
210
|
-
width:
|
|
211
|
-
height:
|
|
201
|
+
width: displaySize.width,
|
|
202
|
+
height: displaySize.height,
|
|
212
203
|
...(saved.mimeType ? { mimeType: saved.mimeType } : {}),
|
|
213
204
|
timestamp: stored.timestamp,
|
|
214
205
|
contextChanged,
|
|
206
|
+
viewportChanged,
|
|
215
207
|
pointerEvents: pendingPointers,
|
|
216
208
|
});
|
|
217
209
|
this.transport.invoke('replay.writeSegment', {
|
|
@@ -228,7 +220,6 @@ export class FTSessionReplay {
|
|
|
228
220
|
});
|
|
229
221
|
this.updateRecordCount(context.viewId, encoded.recordCount);
|
|
230
222
|
this.pendingPointerEvents.splice(0, pendingPointers.length);
|
|
231
|
-
this.budget.record(now, saved.byteSize, priorityKey);
|
|
232
223
|
emitReplayDiagnostic({
|
|
233
224
|
type: 'image_saved',
|
|
234
225
|
timestamp: now,
|
|
@@ -236,7 +227,7 @@ export class FTSessionReplay {
|
|
|
236
227
|
width: saved.width,
|
|
237
228
|
height: saved.height,
|
|
238
229
|
...(saved.mimeType ? { mimeType: saved.mimeType } : {}),
|
|
239
|
-
priority:
|
|
230
|
+
priority: contextChanged || viewportChanged,
|
|
240
231
|
byteSizeSource: saved.byteSizeSource,
|
|
241
232
|
});
|
|
242
233
|
this.lastFingerprint = fingerprint;
|
|
@@ -244,7 +235,7 @@ export class FTSessionReplay {
|
|
|
244
235
|
this.lastPrivacyKey = privacyKey;
|
|
245
236
|
this.lastFrameSample = sample;
|
|
246
237
|
this.lastImageTimestamp = now;
|
|
247
|
-
this.
|
|
238
|
+
this.lastDisplaySize = displaySize;
|
|
248
239
|
this.lastViewportSize = viewportSize;
|
|
249
240
|
return true;
|
|
250
241
|
}
|
|
@@ -281,9 +272,8 @@ export class FTSessionReplay {
|
|
|
281
272
|
this.lastPrivacyKey = undefined;
|
|
282
273
|
this.lastFrameSample = undefined;
|
|
283
274
|
this.lastImageTimestamp = undefined;
|
|
284
|
-
this.
|
|
275
|
+
this.lastDisplaySize = undefined;
|
|
285
276
|
this.lastViewportSize = undefined;
|
|
286
|
-
this.budget.reset();
|
|
287
277
|
this.recordCounts.clear();
|
|
288
278
|
this.pendingPointerEvents = [];
|
|
289
279
|
if (this.recordTouches && this.pointerSource) {
|
|
@@ -302,7 +292,7 @@ export class FTSessionReplay {
|
|
|
302
292
|
this.schedule(0, this.captureGeneration);
|
|
303
293
|
}
|
|
304
294
|
stopCapture() {
|
|
305
|
-
var _a;
|
|
295
|
+
var _a, _b, _c;
|
|
306
296
|
const wasRunning = this.running;
|
|
307
297
|
this.captureGeneration += 1;
|
|
308
298
|
this.running = false;
|
|
@@ -312,6 +302,7 @@ export class FTSessionReplay {
|
|
|
312
302
|
if (this.timer !== undefined)
|
|
313
303
|
clearTimeout(this.timer);
|
|
314
304
|
this.timer = undefined;
|
|
305
|
+
(_c = (_b = this.capture).dispose) === null || _c === void 0 ? void 0 : _c.call(_b);
|
|
315
306
|
if (wasRunning)
|
|
316
307
|
emitReplayDiagnostic({ type: 'replay_stopped', timestamp: Date.now() });
|
|
317
308
|
}
|
|
@@ -321,6 +312,7 @@ export class FTSessionReplay {
|
|
|
321
312
|
this.timer = setTimeout(async () => {
|
|
322
313
|
if (!this.running || generation !== this.captureGeneration)
|
|
323
314
|
return;
|
|
315
|
+
const startedAt = Date.now();
|
|
324
316
|
try {
|
|
325
317
|
await this.captureNow();
|
|
326
318
|
}
|
|
@@ -329,7 +321,12 @@ export class FTSessionReplay {
|
|
|
329
321
|
}
|
|
330
322
|
finally {
|
|
331
323
|
if (this.running && generation === this.captureGeneration) {
|
|
332
|
-
|
|
324
|
+
// Encoding and file cleanup are part of the frame interval. Keep one
|
|
325
|
+
// frame in flight and skip missed slots instead of accumulating work.
|
|
326
|
+
const interval = 1000 / this.config.captureFps;
|
|
327
|
+
const elapsed = Math.max(0, Date.now() - startedAt);
|
|
328
|
+
const slots = Math.max(1, Math.ceil(elapsed / interval));
|
|
329
|
+
this.schedule(Math.max(0, slots * interval - elapsed), generation);
|
|
333
330
|
}
|
|
334
331
|
}
|
|
335
332
|
}, delay);
|
|
@@ -339,28 +336,37 @@ export class FTSessionReplay {
|
|
|
339
336
|
return normalizeRumContext(value);
|
|
340
337
|
}
|
|
341
338
|
async saveImage(stored, compressionQuality, maxFrameBytes) {
|
|
342
|
-
if (this.imagePolicyEnabled
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
339
|
+
if (this.imagePolicyEnabled) {
|
|
340
|
+
if (this.supportsSaveImageV2 !== false) {
|
|
341
|
+
try {
|
|
342
|
+
const value = await this.invokeSaveImage('replay.saveImageV2', {
|
|
343
|
+
path: stored.path,
|
|
344
|
+
width: stored.width,
|
|
345
|
+
height: stored.height,
|
|
346
|
+
quality: compressionQuality,
|
|
347
|
+
maxFrameBytes,
|
|
348
|
+
});
|
|
349
|
+
if (value !== undefined) {
|
|
350
|
+
this.supportsSaveImageV2 = true;
|
|
351
|
+
if (isRejectedSaveImageV2(value))
|
|
352
|
+
return undefined;
|
|
353
|
+
const result = normalizeSaveImageV2Result(value);
|
|
354
|
+
if (result.byteSize > maxFrameBytes) {
|
|
355
|
+
throw new RangeError('Native replay image exceeded imagePolicy.maxFrameBytes');
|
|
356
|
+
}
|
|
357
|
+
return { ...result, byteSizeSource: 'native' };
|
|
358
|
+
}
|
|
359
|
+
this.supportsSaveImageV2 = false;
|
|
360
|
+
}
|
|
361
|
+
catch (error) {
|
|
362
|
+
if (!isUnknownBridgeMethod(error))
|
|
363
|
+
throw error;
|
|
364
|
+
this.supportsSaveImageV2 = false;
|
|
356
365
|
}
|
|
357
|
-
this.supportsSaveImageV2 = false;
|
|
358
|
-
}
|
|
359
|
-
catch (error) {
|
|
360
|
-
if (!isUnknownBridgeMethod(error))
|
|
361
|
-
throw error;
|
|
362
|
-
this.supportsSaveImageV2 = false;
|
|
363
366
|
}
|
|
367
|
+
// V1 cannot enforce encoded size. Never silently discard a caller's
|
|
368
|
+
// explicit image policy by falling back to unbounded image storage.
|
|
369
|
+
throw new Error('Replay imagePolicy requires replay.saveImageV2. Upgrade the native Replay SDK and rebuild the native project.');
|
|
364
370
|
}
|
|
365
371
|
const resourceId = await this.invokeSaveImage('replay.saveImage', {
|
|
366
372
|
path: stored.path,
|
|
@@ -371,12 +377,10 @@ export class FTSessionReplay {
|
|
|
371
377
|
return undefined;
|
|
372
378
|
return {
|
|
373
379
|
resourceId,
|
|
374
|
-
// V1 cannot report encoded size. A conservative frame-limit estimate
|
|
375
|
-
// still prevents configured captureFps from multiplying traffic freely.
|
|
376
|
-
byteSize: maxFrameBytes,
|
|
377
380
|
width: stored.width,
|
|
378
381
|
height: stored.height,
|
|
379
|
-
|
|
382
|
+
// Legacy storage does not report actual bytes; do not invent traffic.
|
|
383
|
+
byteSizeSource: 'unavailable',
|
|
380
384
|
...(this.transport.platform === 'ios' ? { mimeType: 'image/png' } : {}),
|
|
381
385
|
};
|
|
382
386
|
}
|
|
@@ -421,6 +425,13 @@ export class FTSessionReplay {
|
|
|
421
425
|
this.transport.invoke('replay.setRecordCount', { viewId, count });
|
|
422
426
|
}
|
|
423
427
|
}
|
|
428
|
+
function scaledReplayViewport(size, maxDimension) {
|
|
429
|
+
const scale = Math.min(1, maxDimension / Math.max(size.width, size.height));
|
|
430
|
+
return {
|
|
431
|
+
width: Math.max(1, Math.round(size.width * scale)),
|
|
432
|
+
height: Math.max(1, Math.round(size.height * scale)),
|
|
433
|
+
};
|
|
434
|
+
}
|
|
424
435
|
function normalizeRumContext(value) {
|
|
425
436
|
if (!value || typeof value !== 'object')
|
|
426
437
|
return undefined;
|