@cloudcare/cocos-session-replay 0.1.0-alpha.6 → 0.1.0-alpha.7
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 +51 -0
- 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 +57 -0
- 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 +53 -46
- package/dist/creator2/core/replay.js.map +1 -1
- package/dist/creator2/core/types.d.ts +5 -9
- package/dist/creator2/core/types.d.ts.map +1 -1
- package/dist/creator2/core/validation.d.ts +0 -2
- package/dist/creator2/core/validation.d.ts.map +1 -1
- package/dist/creator2/core/validation.js +1 -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 +57 -0
- 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 +72 -60
- package/dist/creator3/core/replay.js.map +1 -1
- package/dist/creator3/core/types.d.ts +5 -9
- package/dist/creator3/core/types.d.ts.map +1 -1
- package/dist/creator3/core/validation.d.ts +0 -2
- package/dist/creator3/core/validation.d.ts.map +1 -1
- package/dist/creator3/core/validation.js +1 -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/ios/FTCocosReplayBridge.podspec +1 -1
- package/native-integration.json +2 -2
- 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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudcare/cocos-session-replay",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.7",
|
|
4
4
|
"description": "Optional Session Replay for the Guance Cocos Creator SDK",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Guance Cloud",
|
|
@@ -53,6 +53,6 @@
|
|
|
53
53
|
"access": "public"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@cloudcare/cocos-sdk": "0.1.0-alpha.
|
|
56
|
+
"@cloudcare/cocos-sdk": "0.1.0-alpha.7"
|
|
57
57
|
}
|
|
58
58
|
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { FTResolvedReplayImagePolicy } from './validation.js';
|
|
2
|
-
export declare const REPLAY_KEY_FRAME_BURST_BYTES: number;
|
|
3
|
-
export interface FTReplayCaptureDecision {
|
|
4
|
-
allowed: boolean;
|
|
5
|
-
compressionQuality: number;
|
|
6
|
-
maxImageDimension: number;
|
|
7
|
-
maxFrameBytes: number;
|
|
8
|
-
usedBytes: number;
|
|
9
|
-
priority: boolean;
|
|
10
|
-
reason?: 'budget' | 'throttle';
|
|
11
|
-
}
|
|
12
|
-
/** Rolling image budget. Segment and pointer bytes intentionally remain outside this controller. */
|
|
13
|
-
export declare class FTReplayBudget {
|
|
14
|
-
private readonly policy;
|
|
15
|
-
private entries;
|
|
16
|
-
private lastCaptureAttempt;
|
|
17
|
-
private burstKeys;
|
|
18
|
-
private pressure;
|
|
19
|
-
constructor(policy: FTResolvedReplayImagePolicy);
|
|
20
|
-
reset(): void;
|
|
21
|
-
decide(timestamp: number, priorityKey?: string): FTReplayCaptureDecision;
|
|
22
|
-
record(timestamp: number, byteSize: number, priorityKey?: string): void;
|
|
23
|
-
usedBytes(timestamp: number): number;
|
|
24
|
-
private prune;
|
|
25
|
-
private decision;
|
|
26
|
-
private updatePressure;
|
|
27
|
-
}
|
|
28
|
-
//# sourceMappingURL=replay-budget.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"replay-budget.d.ts","sourceRoot":"","sources":["../../../../../src/session-replay/core/replay-budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AAInE,eAAO,MAAM,4BAA4B,QAAa,CAAC;AAOvD,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;CAChC;AAED,oGAAoG;AACpG,qBAAa,cAAc;IAMb,OAAO,CAAC,QAAQ,CAAC,MAAM;IALnC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,QAAQ,CAA4D;gBAE/C,MAAM,EAAE,2BAA2B;IAEhE,KAAK,IAAI,IAAI;IAOb,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,uBAAuB;IA6CxE,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAUvE,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAKpC,OAAO,CAAC,KAAK;IAKb,OAAO,CAAC,QAAQ;IA2BhB,OAAO,CAAC,cAAc;CA0BvB"}
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.FTReplayBudget = exports.REPLAY_KEY_FRAME_BURST_BYTES = void 0;
|
|
15
|
-
var WINDOW_MS = 60000;
|
|
16
|
-
var THROTTLED_CAPTURE_INTERVAL_MS = 2000;
|
|
17
|
-
exports.REPLAY_KEY_FRAME_BURST_BYTES = 100 * 1024;
|
|
18
|
-
/** Rolling image budget. Segment and pointer bytes intentionally remain outside this controller. */
|
|
19
|
-
var FTReplayBudget = /** @class */ (function () {
|
|
20
|
-
function FTReplayBudget(policy) {
|
|
21
|
-
this.policy = policy;
|
|
22
|
-
this.entries = [];
|
|
23
|
-
this.burstKeys = [];
|
|
24
|
-
this.pressure = 'normal';
|
|
25
|
-
}
|
|
26
|
-
FTReplayBudget.prototype.reset = function () {
|
|
27
|
-
this.entries = [];
|
|
28
|
-
this.lastCaptureAttempt = undefined;
|
|
29
|
-
this.burstKeys = [];
|
|
30
|
-
this.pressure = 'normal';
|
|
31
|
-
};
|
|
32
|
-
FTReplayBudget.prototype.decide = function (timestamp, priorityKey) {
|
|
33
|
-
var used = this.usedBytes(timestamp);
|
|
34
|
-
var ratio = used / this.policy.maxBytesPerMinute;
|
|
35
|
-
this.updatePressure(ratio);
|
|
36
|
-
var hasBurst = priorityKey !== undefined && !this.burstKeys.includes(priorityKey);
|
|
37
|
-
if (ratio >= 1 && !hasBurst)
|
|
38
|
-
return this.decision(false, 0, used, hasBurst, 'budget');
|
|
39
|
-
var lastImage = this.entries[this.entries.length - 1];
|
|
40
|
-
// Pace successful images from the start instead of spending most of the
|
|
41
|
-
// minute's budget in its first seconds. Reserve 10% for size variation and
|
|
42
|
-
// key frames; their existing burst allowance remains independent.
|
|
43
|
-
var sustainableInterval = lastImage
|
|
44
|
-
? Math.min(lastImage.byteSize, this.policy.maxFrameBytes) * WINDOW_MS
|
|
45
|
-
/ (this.policy.maxBytesPerMinute * 0.9)
|
|
46
|
-
: 0;
|
|
47
|
-
if (this.policy.adaptiveCapture
|
|
48
|
-
&& lastImage
|
|
49
|
-
&& timestamp - lastImage.timestamp < sustainableInterval
|
|
50
|
-
&& !hasBurst)
|
|
51
|
-
return this.decision(false, 0, used, hasBurst, 'throttle');
|
|
52
|
-
if (this.policy.adaptiveCapture
|
|
53
|
-
&& this.pressure !== 'normal'
|
|
54
|
-
&& this.lastCaptureAttempt !== undefined
|
|
55
|
-
&& timestamp - this.lastCaptureAttempt < THROTTLED_CAPTURE_INTERVAL_MS
|
|
56
|
-
&& !hasBurst) {
|
|
57
|
-
return this.decision(false, 0, used, hasBurst, 'throttle');
|
|
58
|
-
}
|
|
59
|
-
this.lastCaptureAttempt = timestamp;
|
|
60
|
-
var normalRemaining = Math.max(0, this.policy.maxBytesPerMinute - used);
|
|
61
|
-
var available = normalRemaining + (hasBurst ? exports.REPLAY_KEY_FRAME_BURST_BYTES : 0);
|
|
62
|
-
var frameLimit = hasBurst
|
|
63
|
-
? Math.min(Math.max(this.policy.maxFrameBytes, exports.REPLAY_KEY_FRAME_BURST_BYTES), available)
|
|
64
|
-
: Math.min(this.policy.maxFrameBytes, available);
|
|
65
|
-
return this.decision(frameLimit >= 1024, frameLimit, used, hasBurst, frameLimit >= 1024 ? undefined : 'budget');
|
|
66
|
-
};
|
|
67
|
-
FTReplayBudget.prototype.record = function (timestamp, byteSize, priorityKey) {
|
|
68
|
-
if (!Number.isFinite(byteSize) || byteSize <= 0)
|
|
69
|
-
return;
|
|
70
|
-
this.prune(timestamp);
|
|
71
|
-
this.entries.push({ timestamp: timestamp, byteSize: Math.round(byteSize) });
|
|
72
|
-
if (priorityKey && !this.burstKeys.includes(priorityKey)) {
|
|
73
|
-
this.burstKeys.push(priorityKey);
|
|
74
|
-
if (this.burstKeys.length > 64)
|
|
75
|
-
this.burstKeys.shift();
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
FTReplayBudget.prototype.usedBytes = function (timestamp) {
|
|
79
|
-
this.prune(timestamp);
|
|
80
|
-
return this.entries.reduce(function (total, entry) { return total + entry.byteSize; }, 0);
|
|
81
|
-
};
|
|
82
|
-
FTReplayBudget.prototype.prune = function (timestamp) {
|
|
83
|
-
var cutoff = timestamp - WINDOW_MS;
|
|
84
|
-
while (this.entries.length > 0 && this.entries[0].timestamp <= cutoff)
|
|
85
|
-
this.entries.shift();
|
|
86
|
-
};
|
|
87
|
-
FTReplayBudget.prototype.decision = function (allowed, maxFrameBytes, usedBytes, priority, reason) {
|
|
88
|
-
var degraded = this.policy.adaptiveCapture
|
|
89
|
-
&& (this.pressure === 'degraded' || this.pressure === 'paused');
|
|
90
|
-
return __assign({ allowed: allowed, compressionQuality: degraded
|
|
91
|
-
? Math.max(0.25, Math.round(this.policy.compressionQuality * 0.75 * 100) / 100)
|
|
92
|
-
: this.policy.compressionQuality, maxImageDimension: degraded
|
|
93
|
-
? Math.min(this.policy.maxImageDimension, Math.max(240, Math.floor(this.policy.maxImageDimension * 0.75)))
|
|
94
|
-
: this.policy.maxImageDimension, maxFrameBytes: Math.max(0, Math.floor(maxFrameBytes)), usedBytes: usedBytes, priority: priority }, (reason ? { reason: reason } : {}));
|
|
95
|
-
};
|
|
96
|
-
FTReplayBudget.prototype.updatePressure = function (ratio) {
|
|
97
|
-
if (!this.policy.adaptiveCapture) {
|
|
98
|
-
this.pressure = 'normal';
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
if (ratio >= 1) {
|
|
102
|
-
this.pressure = 'paused';
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
if (ratio >= 0.9) {
|
|
106
|
-
this.pressure = 'degraded';
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
if (this.pressure === 'paused' || this.pressure === 'degraded') {
|
|
110
|
-
if (ratio >= 0.8) {
|
|
111
|
-
this.pressure = 'degraded';
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
if (ratio >= 0.75) {
|
|
116
|
-
this.pressure = 'throttled';
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
if (this.pressure === 'throttled' && ratio >= 0.65)
|
|
120
|
-
return;
|
|
121
|
-
this.pressure = 'normal';
|
|
122
|
-
};
|
|
123
|
-
return FTReplayBudget;
|
|
124
|
-
}());
|
|
125
|
-
exports.FTReplayBudget = FTReplayBudget;
|
|
126
|
-
//# sourceMappingURL=replay-budget.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"replay-budget.js","sourceRoot":"","sources":["../../../../../src/session-replay/core/replay-budget.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { FTResolvedReplayImagePolicy } from './validation.js';
|
|
2
|
-
export declare const REPLAY_KEY_FRAME_BURST_BYTES: number;
|
|
3
|
-
export interface FTReplayCaptureDecision {
|
|
4
|
-
allowed: boolean;
|
|
5
|
-
compressionQuality: number;
|
|
6
|
-
maxImageDimension: number;
|
|
7
|
-
maxFrameBytes: number;
|
|
8
|
-
usedBytes: number;
|
|
9
|
-
priority: boolean;
|
|
10
|
-
reason?: 'budget' | 'throttle';
|
|
11
|
-
}
|
|
12
|
-
/** Rolling image budget. Segment and pointer bytes intentionally remain outside this controller. */
|
|
13
|
-
export declare class FTReplayBudget {
|
|
14
|
-
private readonly policy;
|
|
15
|
-
private entries;
|
|
16
|
-
private lastCaptureAttempt;
|
|
17
|
-
private burstKeys;
|
|
18
|
-
private pressure;
|
|
19
|
-
constructor(policy: FTResolvedReplayImagePolicy);
|
|
20
|
-
reset(): void;
|
|
21
|
-
decide(timestamp: number, priorityKey?: string): FTReplayCaptureDecision;
|
|
22
|
-
record(timestamp: number, byteSize: number, priorityKey?: string): void;
|
|
23
|
-
usedBytes(timestamp: number): number;
|
|
24
|
-
private prune;
|
|
25
|
-
private decision;
|
|
26
|
-
private updatePressure;
|
|
27
|
-
}
|
|
28
|
-
//# sourceMappingURL=replay-budget.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"replay-budget.d.ts","sourceRoot":"","sources":["../../../../../src/session-replay/core/replay-budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AAInE,eAAO,MAAM,4BAA4B,QAAa,CAAC;AAOvD,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;CAChC;AAED,oGAAoG;AACpG,qBAAa,cAAc;IAMb,OAAO,CAAC,QAAQ,CAAC,MAAM;IALnC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,QAAQ,CAA4D;gBAE/C,MAAM,EAAE,2BAA2B;IAEhE,KAAK,IAAI,IAAI;IAOb,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,uBAAuB;IA6CxE,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAUvE,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAKpC,OAAO,CAAC,KAAK;IAKb,OAAO,CAAC,QAAQ;IA2BhB,OAAO,CAAC,cAAc;CA0BvB"}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
const WINDOW_MS = 60000;
|
|
2
|
-
const THROTTLED_CAPTURE_INTERVAL_MS = 2000;
|
|
3
|
-
export const REPLAY_KEY_FRAME_BURST_BYTES = 100 * 1024;
|
|
4
|
-
/** Rolling image budget. Segment and pointer bytes intentionally remain outside this controller. */
|
|
5
|
-
export class FTReplayBudget {
|
|
6
|
-
constructor(policy) {
|
|
7
|
-
this.policy = policy;
|
|
8
|
-
this.entries = [];
|
|
9
|
-
this.burstKeys = [];
|
|
10
|
-
this.pressure = 'normal';
|
|
11
|
-
}
|
|
12
|
-
reset() {
|
|
13
|
-
this.entries = [];
|
|
14
|
-
this.lastCaptureAttempt = undefined;
|
|
15
|
-
this.burstKeys = [];
|
|
16
|
-
this.pressure = 'normal';
|
|
17
|
-
}
|
|
18
|
-
decide(timestamp, priorityKey) {
|
|
19
|
-
const used = this.usedBytes(timestamp);
|
|
20
|
-
const ratio = used / this.policy.maxBytesPerMinute;
|
|
21
|
-
this.updatePressure(ratio);
|
|
22
|
-
const hasBurst = priorityKey !== undefined && !this.burstKeys.includes(priorityKey);
|
|
23
|
-
if (ratio >= 1 && !hasBurst)
|
|
24
|
-
return this.decision(false, 0, used, hasBurst, 'budget');
|
|
25
|
-
const lastImage = this.entries[this.entries.length - 1];
|
|
26
|
-
// Pace successful images from the start instead of spending most of the
|
|
27
|
-
// minute's budget in its first seconds. Reserve 10% for size variation and
|
|
28
|
-
// key frames; their existing burst allowance remains independent.
|
|
29
|
-
const sustainableInterval = lastImage
|
|
30
|
-
? Math.min(lastImage.byteSize, this.policy.maxFrameBytes) * WINDOW_MS
|
|
31
|
-
/ (this.policy.maxBytesPerMinute * 0.9)
|
|
32
|
-
: 0;
|
|
33
|
-
if (this.policy.adaptiveCapture
|
|
34
|
-
&& lastImage
|
|
35
|
-
&& timestamp - lastImage.timestamp < sustainableInterval
|
|
36
|
-
&& !hasBurst)
|
|
37
|
-
return this.decision(false, 0, used, hasBurst, 'throttle');
|
|
38
|
-
if (this.policy.adaptiveCapture
|
|
39
|
-
&& this.pressure !== 'normal'
|
|
40
|
-
&& this.lastCaptureAttempt !== undefined
|
|
41
|
-
&& timestamp - this.lastCaptureAttempt < THROTTLED_CAPTURE_INTERVAL_MS
|
|
42
|
-
&& !hasBurst) {
|
|
43
|
-
return this.decision(false, 0, used, hasBurst, 'throttle');
|
|
44
|
-
}
|
|
45
|
-
this.lastCaptureAttempt = timestamp;
|
|
46
|
-
const normalRemaining = Math.max(0, this.policy.maxBytesPerMinute - used);
|
|
47
|
-
const available = normalRemaining + (hasBurst ? REPLAY_KEY_FRAME_BURST_BYTES : 0);
|
|
48
|
-
const frameLimit = hasBurst
|
|
49
|
-
? Math.min(Math.max(this.policy.maxFrameBytes, REPLAY_KEY_FRAME_BURST_BYTES), available)
|
|
50
|
-
: Math.min(this.policy.maxFrameBytes, available);
|
|
51
|
-
return this.decision(frameLimit >= 1024, frameLimit, used, hasBurst, frameLimit >= 1024 ? undefined : 'budget');
|
|
52
|
-
}
|
|
53
|
-
record(timestamp, byteSize, priorityKey) {
|
|
54
|
-
if (!Number.isFinite(byteSize) || byteSize <= 0)
|
|
55
|
-
return;
|
|
56
|
-
this.prune(timestamp);
|
|
57
|
-
this.entries.push({ timestamp, byteSize: Math.round(byteSize) });
|
|
58
|
-
if (priorityKey && !this.burstKeys.includes(priorityKey)) {
|
|
59
|
-
this.burstKeys.push(priorityKey);
|
|
60
|
-
if (this.burstKeys.length > 64)
|
|
61
|
-
this.burstKeys.shift();
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
usedBytes(timestamp) {
|
|
65
|
-
this.prune(timestamp);
|
|
66
|
-
return this.entries.reduce((total, entry) => total + entry.byteSize, 0);
|
|
67
|
-
}
|
|
68
|
-
prune(timestamp) {
|
|
69
|
-
const cutoff = timestamp - WINDOW_MS;
|
|
70
|
-
while (this.entries.length > 0 && this.entries[0].timestamp <= cutoff)
|
|
71
|
-
this.entries.shift();
|
|
72
|
-
}
|
|
73
|
-
decision(allowed, maxFrameBytes, usedBytes, priority, reason) {
|
|
74
|
-
const degraded = this.policy.adaptiveCapture
|
|
75
|
-
&& (this.pressure === 'degraded' || this.pressure === 'paused');
|
|
76
|
-
return {
|
|
77
|
-
allowed,
|
|
78
|
-
compressionQuality: degraded
|
|
79
|
-
? Math.max(0.25, Math.round(this.policy.compressionQuality * 0.75 * 100) / 100)
|
|
80
|
-
: this.policy.compressionQuality,
|
|
81
|
-
maxImageDimension: degraded
|
|
82
|
-
? Math.min(this.policy.maxImageDimension, Math.max(240, Math.floor(this.policy.maxImageDimension * 0.75)))
|
|
83
|
-
: this.policy.maxImageDimension,
|
|
84
|
-
maxFrameBytes: Math.max(0, Math.floor(maxFrameBytes)),
|
|
85
|
-
usedBytes,
|
|
86
|
-
priority,
|
|
87
|
-
...(reason ? { reason } : {}),
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
updatePressure(ratio) {
|
|
91
|
-
if (!this.policy.adaptiveCapture) {
|
|
92
|
-
this.pressure = 'normal';
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
if (ratio >= 1) {
|
|
96
|
-
this.pressure = 'paused';
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
if (ratio >= 0.9) {
|
|
100
|
-
this.pressure = 'degraded';
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
if (this.pressure === 'paused' || this.pressure === 'degraded') {
|
|
104
|
-
if (ratio >= 0.8) {
|
|
105
|
-
this.pressure = 'degraded';
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
if (ratio >= 0.75) {
|
|
110
|
-
this.pressure = 'throttled';
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
if (this.pressure === 'throttled' && ratio >= 0.65)
|
|
114
|
-
return;
|
|
115
|
-
this.pressure = 'normal';
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
//# sourceMappingURL=replay-budget.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"replay-budget.js","sourceRoot":"","sources":["../../../../../src/session-replay/core/replay-budget.ts"],"names":[],"mappings":"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"}
|