@amplitude/session-replay-browser 1.46.0 → 1.47.0-sr-trc-debug-log.0
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/lib/cjs/config/joined-config.d.ts +6 -1
- package/lib/cjs/config/joined-config.d.ts.map +1 -1
- package/lib/cjs/config/joined-config.js +58 -18
- package/lib/cjs/config/joined-config.js.map +1 -1
- package/lib/cjs/config/local-config.d.ts +5 -1
- package/lib/cjs/config/local-config.d.ts.map +1 -1
- package/lib/cjs/config/local-config.js +19 -1
- package/lib/cjs/config/local-config.js.map +1 -1
- package/lib/cjs/config/types.d.ts +19 -1
- package/lib/cjs/config/types.d.ts.map +1 -1
- package/lib/cjs/config/types.js.map +1 -1
- package/lib/cjs/diagnostics.d.ts +43 -0
- package/lib/cjs/diagnostics.d.ts.map +1 -0
- package/lib/cjs/diagnostics.js +54 -0
- package/lib/cjs/diagnostics.js.map +1 -0
- package/lib/cjs/session-replay.d.ts +25 -0
- package/lib/cjs/session-replay.d.ts.map +1 -1
- package/lib/cjs/session-replay.js +246 -51
- package/lib/cjs/session-replay.js.map +1 -1
- package/lib/cjs/targeting/targeting-manager.d.ts +4 -1
- package/lib/cjs/targeting/targeting-manager.d.ts.map +1 -1
- package/lib/cjs/targeting/targeting-manager.js +43 -10
- package/lib/cjs/targeting/targeting-manager.js.map +1 -1
- package/lib/cjs/version.d.ts +1 -1
- package/lib/cjs/version.d.ts.map +1 -1
- package/lib/cjs/version.js +1 -1
- package/lib/cjs/version.js.map +1 -1
- package/lib/esm/config/joined-config.d.ts +6 -1
- package/lib/esm/config/joined-config.d.ts.map +1 -1
- package/lib/esm/config/joined-config.js +58 -18
- package/lib/esm/config/joined-config.js.map +1 -1
- package/lib/esm/config/local-config.d.ts +5 -1
- package/lib/esm/config/local-config.d.ts.map +1 -1
- package/lib/esm/config/local-config.js +20 -2
- package/lib/esm/config/local-config.js.map +1 -1
- package/lib/esm/config/types.d.ts +19 -1
- package/lib/esm/config/types.d.ts.map +1 -1
- package/lib/esm/config/types.js.map +1 -1
- package/lib/esm/diagnostics.d.ts +43 -0
- package/lib/esm/diagnostics.d.ts.map +1 -0
- package/lib/esm/diagnostics.js +51 -0
- package/lib/esm/diagnostics.js.map +1 -0
- package/lib/esm/session-replay.d.ts +25 -0
- package/lib/esm/session-replay.d.ts.map +1 -1
- package/lib/esm/session-replay.js +246 -51
- package/lib/esm/session-replay.js.map +1 -1
- package/lib/esm/targeting/targeting-manager.d.ts +4 -1
- package/lib/esm/targeting/targeting-manager.d.ts.map +1 -1
- package/lib/esm/targeting/targeting-manager.js +43 -10
- package/lib/esm/targeting/targeting-manager.js.map +1 -1
- package/lib/esm/version.d.ts +1 -1
- package/lib/esm/version.d.ts.map +1 -1
- package/lib/esm/version.js +1 -1
- package/lib/esm/version.js.map +1 -1
- package/lib/scripts/index-min.js +1 -1
- package/lib/scripts/index-min.js.gz +0 -0
- package/lib/scripts/index-min.js.map +1 -1
- package/lib/scripts/observers-min.js +1 -1
- package/lib/scripts/observers-min.js.gz +0 -0
- package/lib/scripts/session-replay-browser-min.js +1 -1
- package/lib/scripts/session-replay-browser-min.js.gz +0 -0
- package/lib/scripts/session-replay-browser-min.js.map +1 -1
- package/lib/scripts/targeting-min.js +1 -1
- package/lib/scripts/targeting-min.js.gz +0 -0
- package/package.json +2 -2
package/lib/cjs/version.js
CHANGED
package/lib/cjs/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":";;;AAAA,oDAAoD;AACvC,QAAA,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":";;;AAAA,oDAAoD;AACvC,QAAA,OAAO,GAAG,2BAA2B,CAAC","sourcesContent":["// Autogenerated by `pnpm version-file`. DO NOT EDIT\nexport const VERSION = '1.47.0-sr-trc-debug-log.0';\n"]}
|
|
@@ -5,7 +5,12 @@ export declare const removeInvalidSelectorsFromPrivacyConfig: (privacyConfig: Pr
|
|
|
5
5
|
export declare class SessionReplayJoinedConfigGenerator {
|
|
6
6
|
private readonly localConfig;
|
|
7
7
|
private readonly remoteConfigClient;
|
|
8
|
-
|
|
8
|
+
private readonly sessionId?;
|
|
9
|
+
private readonly deviceId?;
|
|
10
|
+
constructor(remoteConfigClient: IRemoteConfigClient, localConfig: ISessionReplayLocalConfig, identity?: {
|
|
11
|
+
sessionId?: string | number;
|
|
12
|
+
deviceId?: string;
|
|
13
|
+
});
|
|
9
14
|
generateJoinedConfig(): Promise<SessionReplayConfigs>;
|
|
10
15
|
/**
|
|
11
16
|
* Defensive bounds for the remote-supplied min_session_duration_ms. A misconfigured
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"joined-config.d.ts","sourceRoot":"","sources":["../../../src/config/joined-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAA4C,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"joined-config.d.ts","sourceRoot":"","sources":["../../../src/config/joined-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAA4C,MAAM,2BAA2B,CAAC;AAGnH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,OAAO,EACL,wBAAwB,IAAI,yBAAyB,EACrD,aAAa,EACb,oBAAoB,EAGrB,MAAM,SAAS,CAAC;AAajB,eAAO,MAAM,uCAAuC,kBAAmB,aAAa,kBAAkB,OAAO,kBA0B5G,CAAC;AACF,qBAAa,kCAAkC;IAC7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA4B;IACxD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAsB;IAEzD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAkB;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;gBAGjC,kBAAkB,EAAE,mBAAmB,EACvC,WAAW,EAAE,yBAAyB,EACtC,QAAQ,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;IAQzD,oBAAoB,IAAI,OAAO,CAAC,oBAAoB,CAAC;IAoO3D;;;;;;OAMG;IACH,OAAO,CAAC,4BAA4B;CAmBrC;AAED;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAElD,eAAO,MAAM,wCAAwC,WAAkB,MAAM,WAAW,oBAAoB,gDAc3G,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { __assign, __awaiter, __generator, __read, __spreadArray, __values } from "tslib";
|
|
2
2
|
import { RemoteConfigClient } from '@amplitude/analytics-core';
|
|
3
3
|
import { getDebugConfig } from '../helpers';
|
|
4
|
+
import { SrDiagnostic } from '../diagnostics';
|
|
4
5
|
import { SessionReplayLocalConfig } from './local-config';
|
|
5
6
|
// Budget for waiting on the remote config response before falling back to the local cache.
|
|
6
7
|
// The inner fetch in analytics-core uses a 1000ms per-attempt AbortController timeout with
|
|
@@ -41,18 +42,20 @@ export var removeInvalidSelectorsFromPrivacyConfig = function (privacyConfig, lo
|
|
|
41
42
|
return privacyConfig;
|
|
42
43
|
};
|
|
43
44
|
var SessionReplayJoinedConfigGenerator = /** @class */ (function () {
|
|
44
|
-
function SessionReplayJoinedConfigGenerator(remoteConfigClient, localConfig) {
|
|
45
|
+
function SessionReplayJoinedConfigGenerator(remoteConfigClient, localConfig, identity) {
|
|
45
46
|
this.localConfig = localConfig;
|
|
46
47
|
this.remoteConfigClient = remoteConfigClient;
|
|
48
|
+
this.sessionId = identity === null || identity === void 0 ? void 0 : identity.sessionId;
|
|
49
|
+
this.deviceId = identity === null || identity === void 0 ? void 0 : identity.deviceId;
|
|
47
50
|
}
|
|
48
51
|
SessionReplayJoinedConfigGenerator.prototype.generateJoinedConfig = function () {
|
|
49
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
52
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
50
53
|
return __awaiter(this, void 0, void 0, function () {
|
|
51
|
-
var config, sessionReplayRemoteConfig, error_1, samplingConfig, remotePrivacyConfig, targetingConfig, localPrivacyConfig, joinedPrivacyConfig, privacyConfigSelectorMap, selectorMap,
|
|
52
|
-
var e_1,
|
|
54
|
+
var config, sessionReplayRemoteConfig, error_1, samplingConfig, remotePrivacyConfig, targetingConfig, localPrivacyConfig, joinedPrivacyConfig, privacyConfigSelectorMap, selectorMap, _j, _k, _l, selector, selectorType;
|
|
55
|
+
var e_1, _m;
|
|
53
56
|
var _this = this;
|
|
54
|
-
return __generator(this, function (
|
|
55
|
-
switch (
|
|
57
|
+
return __generator(this, function (_o) {
|
|
58
|
+
switch (_o.label) {
|
|
56
59
|
case 0:
|
|
57
60
|
config = __assign({}, this.localConfig);
|
|
58
61
|
// Special case here as optOut is implemented via getter/setter
|
|
@@ -60,9 +63,9 @@ var SessionReplayJoinedConfigGenerator = /** @class */ (function () {
|
|
|
60
63
|
// We always want captureEnabled to be true, unless there's an override
|
|
61
64
|
// in the remote config.
|
|
62
65
|
config.captureEnabled = true;
|
|
63
|
-
|
|
66
|
+
_o.label = 1;
|
|
64
67
|
case 1:
|
|
65
|
-
|
|
68
|
+
_o.trys.push([1, 3, , 4]);
|
|
66
69
|
// Subscribe with a timeout so the SDK prefers the remote response and only falls back
|
|
67
70
|
// to cache after the budget elapses. 'all' mode would race a synchronous cache read
|
|
68
71
|
// against the network and resolve on whichever fires first — cache always wins, so a
|
|
@@ -80,6 +83,10 @@ var SessionReplayJoinedConfigGenerator = /** @class */ (function () {
|
|
|
80
83
|
var samplingConfig = namespaceConfig.sr_sampling_config;
|
|
81
84
|
var privacyConfig = namespaceConfig.sr_privacy_config;
|
|
82
85
|
var targetingConfig = namespaceConfig.sr_targeting_config;
|
|
86
|
+
// Captured for the sr.trc.config.received diagnostics event below (remote vs cache is
|
|
87
|
+
// the crux of SR-4234 stale-cache reports).
|
|
88
|
+
var samplingForLog = samplingConfig;
|
|
89
|
+
var targetingSegments = targetingConfig === null || targetingConfig === void 0 ? void 0 : targetingConfig.segments;
|
|
83
90
|
var ugcFilterRules = (_a = config.interactionConfig) === null || _a === void 0 ? void 0 : _a.ugcFilterRules;
|
|
84
91
|
// This is intentionally forced to only be set through the remote config.
|
|
85
92
|
config.interactionConfig = namespaceConfig.sr_interaction_config;
|
|
@@ -88,6 +95,30 @@ var SessionReplayJoinedConfigGenerator = /** @class */ (function () {
|
|
|
88
95
|
}
|
|
89
96
|
// This is intentionally forced to only be set through the remote config.
|
|
90
97
|
config.loggingConfig = namespaceConfig.sr_logging_config;
|
|
98
|
+
// Team-visible diagnostics: which SOURCE the config came from (remote vs cache — the
|
|
99
|
+
// crux of SR-4234) and whether targeting was present. Counters aggregate across the
|
|
100
|
+
// customer's sessions; the event carries the full context (source, sample rate,
|
|
101
|
+
// segment count) as queryable log fields. No-op when diagnostics isn't configured.
|
|
102
|
+
try {
|
|
103
|
+
var diagnosticsClient = _this.localConfig.diagnosticsClient;
|
|
104
|
+
diagnosticsClient === null || diagnosticsClient === void 0 ? void 0 : diagnosticsClient.increment(SrDiagnostic.configSource(String(source)));
|
|
105
|
+
diagnosticsClient === null || diagnosticsClient === void 0 ? void 0 : diagnosticsClient.increment(targetingConfig ? SrDiagnostic.configHasTargeting : SrDiagnostic.configNoTargeting);
|
|
106
|
+
diagnosticsClient === null || diagnosticsClient === void 0 ? void 0 : diagnosticsClient.recordEvent(SrDiagnostic.configReceived, {
|
|
107
|
+
sessionId: _this.sessionId,
|
|
108
|
+
deviceId: _this.deviceId,
|
|
109
|
+
srId: _this.deviceId != null && _this.sessionId != null ? "".concat(_this.deviceId, "/").concat(_this.sessionId) : undefined,
|
|
110
|
+
source: String(source),
|
|
111
|
+
hasSampling: !!samplingConfig,
|
|
112
|
+
captureEnabled: samplingForLog === null || samplingForLog === void 0 ? void 0 : samplingForLog.capture_enabled,
|
|
113
|
+
sampleRate: samplingForLog === null || samplingForLog === void 0 ? void 0 : samplingForLog.sample_rate,
|
|
114
|
+
hasTargeting: !!targetingConfig,
|
|
115
|
+
targetingSegmentCount: Array.isArray(targetingSegments) ? targetingSegments.length : undefined,
|
|
116
|
+
hasPrivacy: !!privacyConfig,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
catch (_b) {
|
|
120
|
+
// diagnostics is best-effort
|
|
121
|
+
}
|
|
91
122
|
if (samplingConfig || privacyConfig || targetingConfig) {
|
|
92
123
|
sessionReplayRemoteConfig = {};
|
|
93
124
|
if (samplingConfig) {
|
|
@@ -108,11 +139,17 @@ var SessionReplayJoinedConfigGenerator = /** @class */ (function () {
|
|
|
108
139
|
// to cache after the budget elapses. 'all' mode would race a synchronous cache read
|
|
109
140
|
// against the network and resolve on whichever fires first — cache always wins, so a
|
|
110
141
|
// stale cache silently overrides the live config (SR-4234).
|
|
111
|
-
|
|
142
|
+
_o.sent();
|
|
112
143
|
return [3 /*break*/, 4];
|
|
113
144
|
case 3:
|
|
114
|
-
error_1 =
|
|
145
|
+
error_1 = _o.sent();
|
|
115
146
|
this.localConfig.loggerProvider.error('Failed to generate joined config: ', error_1);
|
|
147
|
+
try {
|
|
148
|
+
(_a = this.localConfig.diagnosticsClient) === null || _a === void 0 ? void 0 : _a.increment(SrDiagnostic.configFetchFailed);
|
|
149
|
+
}
|
|
150
|
+
catch (_p) {
|
|
151
|
+
// diagnostics is best-effort
|
|
152
|
+
}
|
|
116
153
|
config.captureEnabled = false;
|
|
117
154
|
return [2 /*return*/, {
|
|
118
155
|
localConfig: this.localConfig,
|
|
@@ -163,14 +200,14 @@ var SessionReplayJoinedConfigGenerator = /** @class */ (function () {
|
|
|
163
200
|
// ...remotePrivacyConfig,
|
|
164
201
|
// };
|
|
165
202
|
if (remotePrivacyConfig) {
|
|
166
|
-
localPrivacyConfig = (
|
|
203
|
+
localPrivacyConfig = (_b = config.privacyConfig) !== null && _b !== void 0 ? _b : {};
|
|
167
204
|
joinedPrivacyConfig = {
|
|
168
|
-
defaultMaskLevel: (
|
|
205
|
+
defaultMaskLevel: (_d = (_c = remotePrivacyConfig.defaultMaskLevel) !== null && _c !== void 0 ? _c : localPrivacyConfig.defaultMaskLevel) !== null && _d !== void 0 ? _d : 'medium',
|
|
169
206
|
blockSelector: [],
|
|
170
207
|
maskSelector: [],
|
|
171
208
|
unmaskSelector: [],
|
|
172
|
-
maskAttributes: __spreadArray([], __read(new Set(__spreadArray(__spreadArray([], __read(((
|
|
173
|
-
urlMaskLevels: __spreadArray(__spreadArray([], __read(((
|
|
209
|
+
maskAttributes: __spreadArray([], __read(new Set(__spreadArray(__spreadArray([], __read(((_e = localPrivacyConfig.maskAttributes) !== null && _e !== void 0 ? _e : [])), false), __read(((_f = remotePrivacyConfig.maskAttributes) !== null && _f !== void 0 ? _f : [])), false))), false),
|
|
210
|
+
urlMaskLevels: __spreadArray(__spreadArray([], __read(((_g = remotePrivacyConfig.urlMaskLevels) !== null && _g !== void 0 ? _g : [])), false), __read(((_h = localPrivacyConfig.urlMaskLevels) !== null && _h !== void 0 ? _h : [])), false),
|
|
174
211
|
};
|
|
175
212
|
privacyConfigSelectorMap = function (privacyConfig) {
|
|
176
213
|
var e_2, _a, e_3, _b, e_4, _c;
|
|
@@ -222,8 +259,8 @@ var SessionReplayJoinedConfigGenerator = /** @class */ (function () {
|
|
|
222
259
|
};
|
|
223
260
|
selectorMap = __assign(__assign({}, privacyConfigSelectorMap(localPrivacyConfig)), privacyConfigSelectorMap(remotePrivacyConfig));
|
|
224
261
|
try {
|
|
225
|
-
for (
|
|
226
|
-
|
|
262
|
+
for (_j = __values(Object.entries(selectorMap)), _k = _j.next(); !_k.done; _k = _j.next()) {
|
|
263
|
+
_l = __read(_k.value, 2), selector = _l[0], selectorType = _l[1];
|
|
227
264
|
if (selectorType === 'mask') {
|
|
228
265
|
joinedPrivacyConfig.maskSelector.push(selector);
|
|
229
266
|
}
|
|
@@ -238,7 +275,7 @@ var SessionReplayJoinedConfigGenerator = /** @class */ (function () {
|
|
|
238
275
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
239
276
|
finally {
|
|
240
277
|
try {
|
|
241
|
-
if (
|
|
278
|
+
if (_k && !_k.done && (_m = _j.return)) _m.call(_j);
|
|
242
279
|
}
|
|
243
280
|
finally { if (e_1) throw e_1.error; }
|
|
244
281
|
}
|
|
@@ -294,7 +331,10 @@ export var createSessionReplayJoinedConfigGenerator = function (apiKey, options)
|
|
|
294
331
|
return __generator(this, function (_a) {
|
|
295
332
|
localConfig = new SessionReplayLocalConfig(apiKey, options);
|
|
296
333
|
remoteConfigClient = new RemoteConfigClient(apiKey, localConfig.loggerProvider, localConfig.serverZone, options.configServerUrl);
|
|
297
|
-
return [2 /*return*/, new SessionReplayJoinedConfigGenerator(remoteConfigClient, localConfig
|
|
334
|
+
return [2 /*return*/, new SessionReplayJoinedConfigGenerator(remoteConfigClient, localConfig, {
|
|
335
|
+
sessionId: options.sessionId,
|
|
336
|
+
deviceId: options.deviceId,
|
|
337
|
+
})];
|
|
298
338
|
});
|
|
299
339
|
}); };
|
|
300
340
|
//# sourceMappingURL=joined-config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"joined-config.js","sourceRoot":"","sources":["../../../src/config/joined-config.ts"],"names":[],"mappings":"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","sourcesContent":["import { ILogger, IRemoteConfigClient, RemoteConfigClient, RemoteConfig, Source } from '@amplitude/analytics-core';\nimport { getDebugConfig } from '../helpers';\nimport { SessionReplayOptions } from '../typings/session-replay';\nimport { SessionReplayLocalConfig } from './local-config';\nimport {\n SessionReplayLocalConfig as ISessionReplayLocalConfig,\n PrivacyConfig,\n SessionReplayConfigs,\n SessionReplayJoinedConfig,\n SessionReplayRemoteConfig,\n} from './types';\n\n// Budget for waiting on the remote config response before falling back to the local cache.\n// The inner fetch in analytics-core uses a 1000ms per-attempt AbortController timeout with\n// up to 3 retries — but this outer timeout is the only thing the SR plugin waits on, so\n// only the first attempt can possibly complete in time (attempt 2 starts at ~1000-1333ms\n// after backoff jitter and runs to ~2000-2333ms, well past any reasonable outer budget).\n// 1500ms is set above the 1000ms inner abort to avoid a tie with the inner cutoff and\n// give the first attempt's resolution path room to finish; everything else falls through\n// to the cache fallback. See SR-4234: prefer remote over a stale cache that would\n// otherwise win the synchronous race in 'all' mode.\nconst REMOTE_CONFIG_TIMEOUT_MS = 1500;\n\nexport const removeInvalidSelectorsFromPrivacyConfig = (privacyConfig: PrivacyConfig, loggerProvider: ILogger) => {\n // This allows us to not search the DOM.\n const fragment = document.createDocumentFragment();\n\n const dropInvalidSelectors = (selectors: string[] | string = []): string[] | undefined => {\n if (typeof selectors === 'string') {\n selectors = [selectors];\n }\n selectors = selectors.filter((selector: string) => {\n try {\n fragment.querySelector(selector);\n } catch {\n loggerProvider.warn(`[session-replay-browser] omitting selector \"${selector}\" because it is invalid`);\n return false;\n }\n return true;\n });\n if (selectors.length === 0) {\n return undefined;\n }\n return selectors;\n };\n privacyConfig.blockSelector = dropInvalidSelectors(privacyConfig.blockSelector);\n privacyConfig.maskSelector = dropInvalidSelectors(privacyConfig.maskSelector);\n privacyConfig.unmaskSelector = dropInvalidSelectors(privacyConfig.unmaskSelector);\n return privacyConfig;\n};\nexport class SessionReplayJoinedConfigGenerator {\n private readonly localConfig: ISessionReplayLocalConfig;\n private readonly remoteConfigClient: IRemoteConfigClient;\n\n constructor(remoteConfigClient: IRemoteConfigClient, localConfig: ISessionReplayLocalConfig) {\n this.localConfig = localConfig;\n this.remoteConfigClient = remoteConfigClient;\n }\n\n async generateJoinedConfig(): Promise<SessionReplayConfigs> {\n const config: SessionReplayJoinedConfig = { ...this.localConfig };\n // Special case here as optOut is implemented via getter/setter\n config.optOut = this.localConfig.optOut;\n // We always want captureEnabled to be true, unless there's an override\n // in the remote config.\n config.captureEnabled = true;\n let sessionReplayRemoteConfig: SessionReplayRemoteConfig | undefined;\n\n try {\n // Subscribe with a timeout so the SDK prefers the remote response and only falls back\n // to cache after the budget elapses. 'all' mode would race a synchronous cache read\n // against the network and resolve on whichever fires first — cache always wins, so a\n // stale cache silently overrides the live config (SR-4234).\n await new Promise<void>((resolve, reject) => {\n this.remoteConfigClient.subscribe(\n 'configs.sessionReplay',\n { timeout: REMOTE_CONFIG_TIMEOUT_MS },\n (remoteConfig: RemoteConfig | null, source: Source) => {\n this.localConfig.loggerProvider.debug(\n `Session Replay remote configuration received from ${source}:`,\n JSON.stringify(remoteConfig, null, 2),\n );\n\n if (!remoteConfig) {\n reject(new Error('No remote config received'));\n return;\n }\n\n // remoteConfig is already filtered to 'configs.sessionReplay' namespace\n const namespaceConfig = remoteConfig as SessionReplayRemoteConfig;\n const samplingConfig = namespaceConfig.sr_sampling_config;\n const privacyConfig = namespaceConfig.sr_privacy_config;\n const targetingConfig = namespaceConfig.sr_targeting_config;\n\n const ugcFilterRules = config.interactionConfig?.ugcFilterRules;\n // This is intentionally forced to only be set through the remote config.\n config.interactionConfig = namespaceConfig.sr_interaction_config;\n if (config.interactionConfig && ugcFilterRules) {\n config.interactionConfig.ugcFilterRules = ugcFilterRules;\n }\n\n // This is intentionally forced to only be set through the remote config.\n config.loggingConfig = namespaceConfig.sr_logging_config;\n\n if (samplingConfig || privacyConfig || targetingConfig) {\n sessionReplayRemoteConfig = {};\n if (samplingConfig) {\n sessionReplayRemoteConfig.sr_sampling_config = samplingConfig;\n }\n if (privacyConfig) {\n sessionReplayRemoteConfig.sr_privacy_config = privacyConfig;\n }\n if (targetingConfig) {\n sessionReplayRemoteConfig.sr_targeting_config = targetingConfig;\n }\n }\n\n resolve();\n },\n );\n });\n } catch (error) {\n this.localConfig.loggerProvider.error('Failed to generate joined config: ', error);\n config.captureEnabled = false;\n return {\n localConfig: this.localConfig,\n joinedConfig: config,\n remoteConfig: undefined,\n };\n }\n\n if (!sessionReplayRemoteConfig) {\n return {\n localConfig: this.localConfig,\n joinedConfig: config,\n remoteConfig: sessionReplayRemoteConfig,\n };\n }\n\n const {\n sr_sampling_config: samplingConfig,\n sr_privacy_config: remotePrivacyConfig,\n sr_targeting_config: targetingConfig,\n } = sessionReplayRemoteConfig;\n if (samplingConfig && Object.keys(samplingConfig).length > 0) {\n if (Object.prototype.hasOwnProperty.call(samplingConfig, 'capture_enabled')) {\n config.captureEnabled = samplingConfig.capture_enabled;\n } else {\n config.captureEnabled = false;\n }\n\n if (Object.prototype.hasOwnProperty.call(samplingConfig, 'sample_rate')) {\n config.sampleRate = samplingConfig.sample_rate;\n }\n\n if (Object.prototype.hasOwnProperty.call(samplingConfig, 'min_session_duration_ms')) {\n config.minSessionDurationMs = this.sanitizeMinSessionDurationMs(samplingConfig.min_session_duration_ms);\n }\n } else {\n // If config API response was valid (ie 200), but no config returned, assume that\n // customer has not yet set up config, and use sample rate from SDK options,\n // allowing for immediate replay capture\n config.captureEnabled = true;\n this.localConfig.loggerProvider.debug(\n 'Remote config successfully fetched, but no values set for project, Session Replay capture enabled.',\n );\n }\n\n // Remote config join acts somewhat like a left join between the remote and the local\n // config. That is, remote config has precedence over local values as with sampling.\n // However, non conflicting values will be added to the lists.\n // Here's an example to illustrate:\n //\n // Remote config: {'.selector1': 'MASK', '.selector2': 'UNMASK'}\n // Local config: {'.selector1': 'UNMASK', '.selector3': 'MASK'}\n //\n // Resolved config: {'.selector1': 'MASK', '.selector2': 'UNMASK', '.selector3': 'MASK'}\n // config.privacyConfig = {\n // ...(config.privacyConfig ?? {}),\n // ...remotePrivacyConfig,\n // };\n\n if (remotePrivacyConfig) {\n const localPrivacyConfig: PrivacyConfig = config.privacyConfig ?? {};\n\n const joinedPrivacyConfig: Required<PrivacyConfig> & { blockSelector: string[] } = {\n defaultMaskLevel: remotePrivacyConfig.defaultMaskLevel ?? localPrivacyConfig.defaultMaskLevel ?? 'medium',\n blockSelector: [],\n maskSelector: [],\n unmaskSelector: [],\n maskAttributes: [\n ...new Set([...(localPrivacyConfig.maskAttributes ?? []), ...(remotePrivacyConfig.maskAttributes ?? [])]),\n ],\n urlMaskLevels: [...(remotePrivacyConfig.urlMaskLevels ?? []), ...(localPrivacyConfig.urlMaskLevels ?? [])],\n };\n\n const privacyConfigSelectorMap = (privacyConfig: PrivacyConfig): Record<string, 'mask' | 'unmask' | 'block'> => {\n const selectorMap: Record<string, 'mask' | 'unmask' | 'block'> = {};\n if (typeof privacyConfig.blockSelector === 'string') {\n privacyConfig.blockSelector = [privacyConfig.blockSelector];\n }\n\n for (const selector of privacyConfig.blockSelector ?? []) {\n selectorMap[selector] = 'block';\n }\n for (const selector of privacyConfig.maskSelector ?? []) {\n selectorMap[selector] = 'mask';\n }\n for (const selector of privacyConfig.unmaskSelector ?? []) {\n selectorMap[selector] = 'unmask';\n }\n return selectorMap;\n };\n\n const selectorMap: Record<string, 'mask' | 'unmask' | 'block'> = {\n ...privacyConfigSelectorMap(localPrivacyConfig),\n ...privacyConfigSelectorMap(remotePrivacyConfig),\n };\n\n for (const [selector, selectorType] of Object.entries(selectorMap)) {\n if (selectorType === 'mask') {\n joinedPrivacyConfig.maskSelector.push(selector);\n } else if (selectorType === 'block') {\n joinedPrivacyConfig.blockSelector.push(selector);\n } else if (selectorType === 'unmask') {\n joinedPrivacyConfig.unmaskSelector.push(selector);\n }\n }\n\n config.privacyConfig = removeInvalidSelectorsFromPrivacyConfig(\n joinedPrivacyConfig,\n this.localConfig.loggerProvider,\n );\n }\n\n if (targetingConfig && Object.keys(targetingConfig).length > 0) {\n config.targetingConfig = targetingConfig;\n }\n\n this.localConfig.loggerProvider.debug(\n JSON.stringify({ name: 'session replay joined config', config: getDebugConfig(config) }, null, 2),\n );\n\n return {\n localConfig: this.localConfig,\n joinedConfig: config,\n remoteConfig: sessionReplayRemoteConfig,\n };\n }\n\n /**\n * Defensive bounds for the remote-supplied min_session_duration_ms. A misconfigured\n * value (e.g. 30_000_000) would silently suppress every replay until the config is\n * pushed again, so we clamp to a sane ceiling and warn on out-of-range inputs.\n * Returns undefined for clearly invalid values so the gate falls back to disabled\n * rather than carrying a NaN through downstream comparisons.\n */\n private sanitizeMinSessionDurationMs(raw: unknown): number | undefined {\n if (typeof raw !== 'number' || !Number.isFinite(raw)) {\n this.localConfig.loggerProvider.warn(\n `min_session_duration_ms remote value is not a finite number (got ${String(raw)}); ignoring.`,\n );\n return undefined;\n }\n if (raw < 0) {\n this.localConfig.loggerProvider.warn(`min_session_duration_ms remote value is negative (${raw}); ignoring.`);\n return undefined;\n }\n if (raw > MAX_MIN_SESSION_DURATION_MS) {\n this.localConfig.loggerProvider.warn(\n `min_session_duration_ms remote value ${raw} exceeds ${MAX_MIN_SESSION_DURATION_MS}ms ceiling; clamping.`,\n );\n return MAX_MIN_SESSION_DURATION_MS;\n }\n return raw;\n }\n}\n\n/**\n * Upper bound for the remote-configured replay min duration. 60 seconds is well above\n * any reasonable bounce threshold; values higher than this are almost certainly typos\n * (e.g. seconds confused for milliseconds, or an extra zero) and would otherwise\n * suppress every replay until the config is corrected.\n */\nexport const MAX_MIN_SESSION_DURATION_MS = 60_000;\n\nexport const createSessionReplayJoinedConfigGenerator = async (apiKey: string, options: SessionReplayOptions) => {\n const localConfig = new SessionReplayLocalConfig(apiKey, options);\n\n const remoteConfigClient = new RemoteConfigClient(\n apiKey,\n localConfig.loggerProvider,\n localConfig.serverZone,\n options.configServerUrl,\n );\n\n return new SessionReplayJoinedConfigGenerator(remoteConfigClient, localConfig);\n};\n"]}
|
|
1
|
+
{"version":3,"file":"joined-config.js","sourceRoot":"","sources":["../../../src/config/joined-config.ts"],"names":[],"mappings":"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","sourcesContent":["import { ILogger, IRemoteConfigClient, RemoteConfigClient, RemoteConfig, Source } from '@amplitude/analytics-core';\nimport { getDebugConfig } from '../helpers';\nimport { SrDiagnostic } from '../diagnostics';\nimport { SessionReplayOptions } from '../typings/session-replay';\nimport { SessionReplayLocalConfig } from './local-config';\nimport {\n SessionReplayLocalConfig as ISessionReplayLocalConfig,\n PrivacyConfig,\n SessionReplayConfigs,\n SessionReplayJoinedConfig,\n SessionReplayRemoteConfig,\n} from './types';\n\n// Budget for waiting on the remote config response before falling back to the local cache.\n// The inner fetch in analytics-core uses a 1000ms per-attempt AbortController timeout with\n// up to 3 retries — but this outer timeout is the only thing the SR plugin waits on, so\n// only the first attempt can possibly complete in time (attempt 2 starts at ~1000-1333ms\n// after backoff jitter and runs to ~2000-2333ms, well past any reasonable outer budget).\n// 1500ms is set above the 1000ms inner abort to avoid a tie with the inner cutoff and\n// give the first attempt's resolution path room to finish; everything else falls through\n// to the cache fallback. See SR-4234: prefer remote over a stale cache that would\n// otherwise win the synchronous race in 'all' mode.\nconst REMOTE_CONFIG_TIMEOUT_MS = 1500;\n\nexport const removeInvalidSelectorsFromPrivacyConfig = (privacyConfig: PrivacyConfig, loggerProvider: ILogger) => {\n // This allows us to not search the DOM.\n const fragment = document.createDocumentFragment();\n\n const dropInvalidSelectors = (selectors: string[] | string = []): string[] | undefined => {\n if (typeof selectors === 'string') {\n selectors = [selectors];\n }\n selectors = selectors.filter((selector: string) => {\n try {\n fragment.querySelector(selector);\n } catch {\n loggerProvider.warn(`[session-replay-browser] omitting selector \"${selector}\" because it is invalid`);\n return false;\n }\n return true;\n });\n if (selectors.length === 0) {\n return undefined;\n }\n return selectors;\n };\n privacyConfig.blockSelector = dropInvalidSelectors(privacyConfig.blockSelector);\n privacyConfig.maskSelector = dropInvalidSelectors(privacyConfig.maskSelector);\n privacyConfig.unmaskSelector = dropInvalidSelectors(privacyConfig.unmaskSelector);\n return privacyConfig;\n};\nexport class SessionReplayJoinedConfigGenerator {\n private readonly localConfig: ISessionReplayLocalConfig;\n private readonly remoteConfigClient: IRemoteConfigClient;\n // Identity for diagnostics correlation (config fetch is per-session). Sourced from init options.\n private readonly sessionId?: string | number;\n private readonly deviceId?: string;\n\n constructor(\n remoteConfigClient: IRemoteConfigClient,\n localConfig: ISessionReplayLocalConfig,\n identity?: { sessionId?: string | number; deviceId?: string },\n ) {\n this.localConfig = localConfig;\n this.remoteConfigClient = remoteConfigClient;\n this.sessionId = identity?.sessionId;\n this.deviceId = identity?.deviceId;\n }\n\n async generateJoinedConfig(): Promise<SessionReplayConfigs> {\n const config: SessionReplayJoinedConfig = { ...this.localConfig };\n // Special case here as optOut is implemented via getter/setter\n config.optOut = this.localConfig.optOut;\n // We always want captureEnabled to be true, unless there's an override\n // in the remote config.\n config.captureEnabled = true;\n let sessionReplayRemoteConfig: SessionReplayRemoteConfig | undefined;\n\n try {\n // Subscribe with a timeout so the SDK prefers the remote response and only falls back\n // to cache after the budget elapses. 'all' mode would race a synchronous cache read\n // against the network and resolve on whichever fires first — cache always wins, so a\n // stale cache silently overrides the live config (SR-4234).\n await new Promise<void>((resolve, reject) => {\n this.remoteConfigClient.subscribe(\n 'configs.sessionReplay',\n { timeout: REMOTE_CONFIG_TIMEOUT_MS },\n (remoteConfig: RemoteConfig | null, source: Source) => {\n this.localConfig.loggerProvider.debug(\n `Session Replay remote configuration received from ${source}:`,\n JSON.stringify(remoteConfig, null, 2),\n );\n\n if (!remoteConfig) {\n reject(new Error('No remote config received'));\n return;\n }\n\n // remoteConfig is already filtered to 'configs.sessionReplay' namespace\n const namespaceConfig = remoteConfig as SessionReplayRemoteConfig;\n const samplingConfig = namespaceConfig.sr_sampling_config;\n const privacyConfig = namespaceConfig.sr_privacy_config;\n const targetingConfig = namespaceConfig.sr_targeting_config;\n\n // Captured for the sr.trc.config.received diagnostics event below (remote vs cache is\n // the crux of SR-4234 stale-cache reports).\n const samplingForLog = samplingConfig as { capture_enabled?: boolean; sample_rate?: number } | undefined;\n const targetingSegments = (targetingConfig as unknown as { segments?: unknown[] } | undefined)?.segments;\n\n const ugcFilterRules = config.interactionConfig?.ugcFilterRules;\n // This is intentionally forced to only be set through the remote config.\n config.interactionConfig = namespaceConfig.sr_interaction_config;\n if (config.interactionConfig && ugcFilterRules) {\n config.interactionConfig.ugcFilterRules = ugcFilterRules;\n }\n\n // This is intentionally forced to only be set through the remote config.\n config.loggingConfig = namespaceConfig.sr_logging_config;\n\n // Team-visible diagnostics: which SOURCE the config came from (remote vs cache — the\n // crux of SR-4234) and whether targeting was present. Counters aggregate across the\n // customer's sessions; the event carries the full context (source, sample rate,\n // segment count) as queryable log fields. No-op when diagnostics isn't configured.\n try {\n const diagnosticsClient = this.localConfig.diagnosticsClient;\n diagnosticsClient?.increment(SrDiagnostic.configSource(String(source)));\n diagnosticsClient?.increment(\n targetingConfig ? SrDiagnostic.configHasTargeting : SrDiagnostic.configNoTargeting,\n );\n diagnosticsClient?.recordEvent(SrDiagnostic.configReceived, {\n sessionId: this.sessionId,\n deviceId: this.deviceId,\n srId:\n this.deviceId != null && this.sessionId != null ? `${this.deviceId}/${this.sessionId}` : undefined,\n source: String(source),\n hasSampling: !!samplingConfig,\n captureEnabled: samplingForLog?.capture_enabled,\n sampleRate: samplingForLog?.sample_rate,\n hasTargeting: !!targetingConfig,\n targetingSegmentCount: Array.isArray(targetingSegments) ? targetingSegments.length : undefined,\n hasPrivacy: !!privacyConfig,\n });\n } catch {\n // diagnostics is best-effort\n }\n\n if (samplingConfig || privacyConfig || targetingConfig) {\n sessionReplayRemoteConfig = {};\n if (samplingConfig) {\n sessionReplayRemoteConfig.sr_sampling_config = samplingConfig;\n }\n if (privacyConfig) {\n sessionReplayRemoteConfig.sr_privacy_config = privacyConfig;\n }\n if (targetingConfig) {\n sessionReplayRemoteConfig.sr_targeting_config = targetingConfig;\n }\n }\n\n resolve();\n },\n );\n });\n } catch (error) {\n this.localConfig.loggerProvider.error('Failed to generate joined config: ', error);\n try {\n this.localConfig.diagnosticsClient?.increment(SrDiagnostic.configFetchFailed);\n } catch {\n // diagnostics is best-effort\n }\n config.captureEnabled = false;\n return {\n localConfig: this.localConfig,\n joinedConfig: config,\n remoteConfig: undefined,\n };\n }\n\n if (!sessionReplayRemoteConfig) {\n return {\n localConfig: this.localConfig,\n joinedConfig: config,\n remoteConfig: sessionReplayRemoteConfig,\n };\n }\n\n const {\n sr_sampling_config: samplingConfig,\n sr_privacy_config: remotePrivacyConfig,\n sr_targeting_config: targetingConfig,\n } = sessionReplayRemoteConfig;\n if (samplingConfig && Object.keys(samplingConfig).length > 0) {\n if (Object.prototype.hasOwnProperty.call(samplingConfig, 'capture_enabled')) {\n config.captureEnabled = samplingConfig.capture_enabled;\n } else {\n config.captureEnabled = false;\n }\n\n if (Object.prototype.hasOwnProperty.call(samplingConfig, 'sample_rate')) {\n config.sampleRate = samplingConfig.sample_rate;\n }\n\n if (Object.prototype.hasOwnProperty.call(samplingConfig, 'min_session_duration_ms')) {\n config.minSessionDurationMs = this.sanitizeMinSessionDurationMs(samplingConfig.min_session_duration_ms);\n }\n } else {\n // If config API response was valid (ie 200), but no config returned, assume that\n // customer has not yet set up config, and use sample rate from SDK options,\n // allowing for immediate replay capture\n config.captureEnabled = true;\n this.localConfig.loggerProvider.debug(\n 'Remote config successfully fetched, but no values set for project, Session Replay capture enabled.',\n );\n }\n\n // Remote config join acts somewhat like a left join between the remote and the local\n // config. That is, remote config has precedence over local values as with sampling.\n // However, non conflicting values will be added to the lists.\n // Here's an example to illustrate:\n //\n // Remote config: {'.selector1': 'MASK', '.selector2': 'UNMASK'}\n // Local config: {'.selector1': 'UNMASK', '.selector3': 'MASK'}\n //\n // Resolved config: {'.selector1': 'MASK', '.selector2': 'UNMASK', '.selector3': 'MASK'}\n // config.privacyConfig = {\n // ...(config.privacyConfig ?? {}),\n // ...remotePrivacyConfig,\n // };\n\n if (remotePrivacyConfig) {\n const localPrivacyConfig: PrivacyConfig = config.privacyConfig ?? {};\n\n const joinedPrivacyConfig: Required<PrivacyConfig> & { blockSelector: string[] } = {\n defaultMaskLevel: remotePrivacyConfig.defaultMaskLevel ?? localPrivacyConfig.defaultMaskLevel ?? 'medium',\n blockSelector: [],\n maskSelector: [],\n unmaskSelector: [],\n maskAttributes: [\n ...new Set([...(localPrivacyConfig.maskAttributes ?? []), ...(remotePrivacyConfig.maskAttributes ?? [])]),\n ],\n urlMaskLevels: [...(remotePrivacyConfig.urlMaskLevels ?? []), ...(localPrivacyConfig.urlMaskLevels ?? [])],\n };\n\n const privacyConfigSelectorMap = (privacyConfig: PrivacyConfig): Record<string, 'mask' | 'unmask' | 'block'> => {\n const selectorMap: Record<string, 'mask' | 'unmask' | 'block'> = {};\n if (typeof privacyConfig.blockSelector === 'string') {\n privacyConfig.blockSelector = [privacyConfig.blockSelector];\n }\n\n for (const selector of privacyConfig.blockSelector ?? []) {\n selectorMap[selector] = 'block';\n }\n for (const selector of privacyConfig.maskSelector ?? []) {\n selectorMap[selector] = 'mask';\n }\n for (const selector of privacyConfig.unmaskSelector ?? []) {\n selectorMap[selector] = 'unmask';\n }\n return selectorMap;\n };\n\n const selectorMap: Record<string, 'mask' | 'unmask' | 'block'> = {\n ...privacyConfigSelectorMap(localPrivacyConfig),\n ...privacyConfigSelectorMap(remotePrivacyConfig),\n };\n\n for (const [selector, selectorType] of Object.entries(selectorMap)) {\n if (selectorType === 'mask') {\n joinedPrivacyConfig.maskSelector.push(selector);\n } else if (selectorType === 'block') {\n joinedPrivacyConfig.blockSelector.push(selector);\n } else if (selectorType === 'unmask') {\n joinedPrivacyConfig.unmaskSelector.push(selector);\n }\n }\n\n config.privacyConfig = removeInvalidSelectorsFromPrivacyConfig(\n joinedPrivacyConfig,\n this.localConfig.loggerProvider,\n );\n }\n\n if (targetingConfig && Object.keys(targetingConfig).length > 0) {\n config.targetingConfig = targetingConfig;\n }\n\n this.localConfig.loggerProvider.debug(\n JSON.stringify({ name: 'session replay joined config', config: getDebugConfig(config) }, null, 2),\n );\n\n return {\n localConfig: this.localConfig,\n joinedConfig: config,\n remoteConfig: sessionReplayRemoteConfig,\n };\n }\n\n /**\n * Defensive bounds for the remote-supplied min_session_duration_ms. A misconfigured\n * value (e.g. 30_000_000) would silently suppress every replay until the config is\n * pushed again, so we clamp to a sane ceiling and warn on out-of-range inputs.\n * Returns undefined for clearly invalid values so the gate falls back to disabled\n * rather than carrying a NaN through downstream comparisons.\n */\n private sanitizeMinSessionDurationMs(raw: unknown): number | undefined {\n if (typeof raw !== 'number' || !Number.isFinite(raw)) {\n this.localConfig.loggerProvider.warn(\n `min_session_duration_ms remote value is not a finite number (got ${String(raw)}); ignoring.`,\n );\n return undefined;\n }\n if (raw < 0) {\n this.localConfig.loggerProvider.warn(`min_session_duration_ms remote value is negative (${raw}); ignoring.`);\n return undefined;\n }\n if (raw > MAX_MIN_SESSION_DURATION_MS) {\n this.localConfig.loggerProvider.warn(\n `min_session_duration_ms remote value ${raw} exceeds ${MAX_MIN_SESSION_DURATION_MS}ms ceiling; clamping.`,\n );\n return MAX_MIN_SESSION_DURATION_MS;\n }\n return raw;\n }\n}\n\n/**\n * Upper bound for the remote-configured replay min duration. 60 seconds is well above\n * any reasonable bounce threshold; values higher than this are almost certainly typos\n * (e.g. seconds confused for milliseconds, or an extra zero) and would otherwise\n * suppress every replay until the config is corrected.\n */\nexport const MAX_MIN_SESSION_DURATION_MS = 60_000;\n\nexport const createSessionReplayJoinedConfigGenerator = async (apiKey: string, options: SessionReplayOptions) => {\n const localConfig = new SessionReplayLocalConfig(apiKey, options);\n\n const remoteConfigClient = new RemoteConfigClient(\n apiKey,\n localConfig.loggerProvider,\n localConfig.serverZone,\n options.configServerUrl,\n );\n\n return new SessionReplayJoinedConfigGenerator(remoteConfigClient, localConfig, {\n sessionId: options.sessionId,\n deviceId: options.deviceId,\n });\n};\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Config, Logger, FetchTransport, LogLevel } from '@amplitude/analytics-core';
|
|
1
|
+
import { Config, Logger, FetchTransport, LogLevel, IDiagnosticsClient } from '@amplitude/analytics-core';
|
|
2
2
|
import { SessionReplayOptions, StoreType } from '../typings/session-replay';
|
|
3
3
|
import { SessionReplayLocalConfig as ISessionReplayLocalConfig, CrossOriginIframesConfig, FlushIntervalConfig, InteractionConfig, PrivacyConfig, SessionReplayPerformanceConfig, SessionReplayVersion } from './types';
|
|
4
4
|
export declare const getDefaultConfig: () => {
|
|
@@ -34,6 +34,10 @@ export declare class SessionReplayLocalConfig extends Config implements ISession
|
|
|
34
34
|
captureFullSnapshotOnFocus?: boolean;
|
|
35
35
|
maxPersistedEventsSizeBytes?: number;
|
|
36
36
|
maxSingleEventSizeBytes?: number;
|
|
37
|
+
diagnosticsClient?: IDiagnosticsClient;
|
|
38
|
+
diagnosticsEnabled?: boolean;
|
|
39
|
+
diagnosticsSampleRate?: number;
|
|
37
40
|
constructor(apiKey: string, options: SessionReplayOptions);
|
|
41
|
+
private createStandaloneDiagnosticsClient;
|
|
38
42
|
}
|
|
39
43
|
//# sourceMappingURL=local-config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-config.d.ts","sourceRoot":"","sources":["../../../src/config/local-config.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"local-config.d.ts","sourceRoot":"","sources":["../../../src/config/local-config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EAEN,MAAM,EACN,cAAc,EACd,QAAQ,EACR,kBAAkB,EAEnB,MAAM,2BAA2B,CAAC;AAYnC,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EACL,wBAAwB,IAAI,yBAAyB,EACrD,wBAAwB,EACxB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,8BAA8B,EAC9B,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAIjB,eAAO,MAAM,gBAAgB;;;;;CAK3B,CAAC;AAEH,qBAAa,wBAAyB,SAAQ,MAAO,YAAW,yBAAyB;IACvF,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,SAAS,EAAE,SAAS,CAAC;IACrB,iBAAiB,CAAC,EAAE,8BAA8B,CAAC;IACnD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qCAAqC,CAAC,EAAE,OAAO,CAAC;IAChD,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,kBAAkB,CAAC,EAAE,wBAAwB,CAAC;IAC9C,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,iBAAiB,CAAC,EAAE,kBAAkB,CAAC;IACvC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAC;gBAEnB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;IAyGzD,OAAO,CAAC,iCAAiC;CAe1C"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __assign, __extends, __read, __spreadArray } from "tslib";
|
|
2
|
-
import { Config, Logger, FetchTransport, LogLevel } from '@amplitude/analytics-core';
|
|
2
|
+
import { Config, Logger, FetchTransport, LogLevel, DiagnosticsClient, } from '@amplitude/analytics-core';
|
|
3
3
|
import { DEFAULT_FLUSH_MAX_INTERVAL_MS, DEFAULT_FLUSH_MIN_INTERVAL_MS, DEFAULT_PERFORMANCE_CONFIG, DEFAULT_SAMPLE_RATE, DEFAULT_SERVER_ZONE, DEFAULT_URL_CHANGE_POLLING_INTERVAL, MAX_INTERVAL, MIN_INTERVAL, UNMASK_TEXT_CLASS, } from '../constants';
|
|
4
4
|
import { SafeLoggerProvider } from '../logger';
|
|
5
5
|
import { validateUGCFilterRules } from '../helpers';
|
|
@@ -13,7 +13,7 @@ var SessionReplayLocalConfig = /** @class */ (function (_super) {
|
|
|
13
13
|
__extends(SessionReplayLocalConfig, _super);
|
|
14
14
|
function SessionReplayLocalConfig(apiKey, options) {
|
|
15
15
|
var _this = this;
|
|
16
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
16
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
17
17
|
var defaultConfig = getDefaultConfig();
|
|
18
18
|
_this = _super.call(this, __assign(__assign({ transportProvider: defaultConfig.transportProvider, loggerProvider: new SafeLoggerProvider(options.loggerProvider || defaultConfig.loggerProvider) }, options), { apiKey: apiKey })) || this;
|
|
19
19
|
_this.flushMaxRetries =
|
|
@@ -87,8 +87,26 @@ var SessionReplayLocalConfig = /** @class */ (function (_super) {
|
|
|
87
87
|
maxIntervalMs: DEFAULT_FLUSH_MAX_INTERVAL_MS,
|
|
88
88
|
};
|
|
89
89
|
}
|
|
90
|
+
_this.diagnosticsEnabled = options.diagnosticsEnabled;
|
|
91
|
+
_this.diagnosticsSampleRate = options.diagnosticsSampleRate;
|
|
92
|
+
// Single diagnostics client: in plugin mode the analytics SDK passes its own client in
|
|
93
|
+
// (reused, not duplicated). Standalone SR has no analytics SDK, so create one here — but only
|
|
94
|
+
// when explicitly opted in, to avoid imposing IndexedDB + flush-timer overhead on standalone
|
|
95
|
+
// users who don't want diagnostics.
|
|
96
|
+
_this.diagnosticsClient = (_q = options.diagnosticsClient) !== null && _q !== void 0 ? _q : _this.createStandaloneDiagnosticsClient(apiKey, options);
|
|
90
97
|
return _this;
|
|
91
98
|
}
|
|
99
|
+
SessionReplayLocalConfig.prototype.createStandaloneDiagnosticsClient = function (apiKey, options) {
|
|
100
|
+
var diagnosticsEnabled = options.diagnosticsEnabled, diagnosticsSampleRate = options.diagnosticsSampleRate;
|
|
101
|
+
var optedIn = diagnosticsEnabled === true || (typeof diagnosticsSampleRate === 'number' && diagnosticsSampleRate > 0);
|
|
102
|
+
if (!optedIn) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
return new DiagnosticsClient(apiKey, this.loggerProvider, this.serverZone, {
|
|
106
|
+
enabled: diagnosticsEnabled !== null && diagnosticsEnabled !== void 0 ? diagnosticsEnabled : true,
|
|
107
|
+
sampleRate: diagnosticsSampleRate !== null && diagnosticsSampleRate !== void 0 ? diagnosticsSampleRate : 0,
|
|
108
|
+
});
|
|
109
|
+
};
|
|
92
110
|
return SessionReplayLocalConfig;
|
|
93
111
|
}(Config));
|
|
94
112
|
export { SessionReplayLocalConfig };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-config.js","sourceRoot":"","sources":["../../../src/config/local-config.ts"],"names":[],"mappings":"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","sourcesContent":["import { Config, ILogger, Logger, FetchTransport, LogLevel } from '@amplitude/analytics-core';\nimport {\n DEFAULT_FLUSH_MAX_INTERVAL_MS,\n DEFAULT_FLUSH_MIN_INTERVAL_MS,\n DEFAULT_PERFORMANCE_CONFIG,\n DEFAULT_SAMPLE_RATE,\n DEFAULT_SERVER_ZONE,\n DEFAULT_URL_CHANGE_POLLING_INTERVAL,\n MAX_INTERVAL,\n MIN_INTERVAL,\n UNMASK_TEXT_CLASS,\n} from '../constants';\nimport { SessionReplayOptions, StoreType } from '../typings/session-replay';\nimport {\n SessionReplayLocalConfig as ISessionReplayLocalConfig,\n CrossOriginIframesConfig,\n FlushIntervalConfig,\n InteractionConfig,\n PrivacyConfig,\n SessionReplayPerformanceConfig,\n SessionReplayVersion,\n} from './types';\nimport { SafeLoggerProvider } from '../logger';\nimport { validateUGCFilterRules } from '../helpers';\n\nexport const getDefaultConfig = () => ({\n flushMaxRetries: 2,\n logLevel: LogLevel.Warn,\n loggerProvider: new Logger(),\n transportProvider: new FetchTransport(),\n});\n\nexport class SessionReplayLocalConfig extends Config implements ISessionReplayLocalConfig {\n apiKey: string;\n sampleRate: number;\n privacyConfig?: PrivacyConfig;\n interactionConfig?: InteractionConfig;\n debugMode?: boolean;\n configServerUrl?: string;\n trackServerUrl?: string;\n shouldInlineStylesheet?: boolean;\n version?: SessionReplayVersion;\n storeType: StoreType;\n performanceConfig?: SessionReplayPerformanceConfig;\n useWebWorker?: boolean;\n enableTransportCompression?: boolean;\n sendTimeoutMs?: number;\n applyBackgroundColorToBlockedElements?: boolean;\n enableUrlChangePolling?: boolean;\n urlChangePollingInterval?: number;\n captureDocumentTitle?: boolean;\n captureAdoptedStyleSheets?: boolean;\n crossOriginIframes?: CrossOriginIframesConfig;\n fullSnapshotIntervalMs?: number;\n flushIntervalConfig?: FlushIntervalConfig;\n eagerFullSnapshotSend?: boolean;\n captureFullSnapshotOnFocus?: boolean;\n maxPersistedEventsSizeBytes?: number;\n maxSingleEventSizeBytes?: number;\n\n constructor(apiKey: string, options: SessionReplayOptions) {\n const defaultConfig = getDefaultConfig();\n super({\n transportProvider: defaultConfig.transportProvider,\n loggerProvider: new SafeLoggerProvider(options.loggerProvider || defaultConfig.loggerProvider),\n ...options,\n apiKey,\n });\n this.flushMaxRetries =\n options.flushMaxRetries !== undefined && options.flushMaxRetries <= defaultConfig.flushMaxRetries\n ? options.flushMaxRetries\n : defaultConfig.flushMaxRetries;\n\n this.apiKey = apiKey;\n this.sampleRate = options.sampleRate || DEFAULT_SAMPLE_RATE;\n this.serverZone = options.serverZone || DEFAULT_SERVER_ZONE;\n this.configServerUrl = options.configServerUrl;\n this.trackServerUrl = options.trackServerUrl;\n this.shouldInlineStylesheet = options.shouldInlineStylesheet;\n this.version = options.version;\n this.performanceConfig = options.performanceConfig || DEFAULT_PERFORMANCE_CONFIG;\n this.storeType = options.storeType ?? 'memory';\n this.applyBackgroundColorToBlockedElements = options.applyBackgroundColorToBlockedElements ?? false;\n this.enableUrlChangePolling = options.enableUrlChangePolling ?? false;\n this.urlChangePollingInterval = options.urlChangePollingInterval ?? DEFAULT_URL_CHANGE_POLLING_INTERVAL;\n this.captureDocumentTitle = options.captureDocumentTitle ?? false;\n if (options.fullSnapshotIntervalMs !== undefined) {\n this.fullSnapshotIntervalMs = options.fullSnapshotIntervalMs;\n }\n if (options.eagerFullSnapshotSend !== undefined) {\n this.eagerFullSnapshotSend = options.eagerFullSnapshotSend;\n }\n // Defaults to false per the validated amp-on-amp perf config (SR-4646): the on-focus full\n // snapshot is off unless the consumer explicitly opts in. focusListener honors this by\n // skipping the snapshot whenever the value is not true.\n this.captureFullSnapshotOnFocus = options.captureFullSnapshotOnFocus ?? false;\n if (options.maxPersistedEventsSizeBytes !== undefined) {\n this.maxPersistedEventsSizeBytes = sanitizeByteSize(\n options.maxPersistedEventsSizeBytes,\n MIN_EVENT_BYTE_SIZE,\n MAX_PERSISTED_EVENTS_SIZE_CEILING,\n 'maxPersistedEventsSizeBytes',\n this.loggerProvider,\n );\n }\n if (options.maxSingleEventSizeBytes !== undefined) {\n this.maxSingleEventSizeBytes = sanitizeByteSize(\n options.maxSingleEventSizeBytes,\n MIN_EVENT_BYTE_SIZE,\n MAX_SINGLE_EVENT_SIZE_CEILING,\n 'maxSingleEventSizeBytes',\n this.loggerProvider,\n );\n }\n\n // Auto-include .amp-unmask as a default unmaskSelector entry so it works\n // symmetrically with amp-mask/amp-block without requiring explicit config (SR-2945).\n this.privacyConfig = {\n ...(options.privacyConfig ?? {}),\n unmaskSelector: Array.from(new Set([`.${UNMASK_TEXT_CLASS}`, ...(options.privacyConfig?.unmaskSelector ?? [])])),\n };\n if (options.interactionConfig) {\n this.interactionConfig = options.interactionConfig;\n\n // validate ugcFilterRules, throw error if invalid - throw error at the beginning of the config\n if (this.interactionConfig.ugcFilterRules) {\n validateUGCFilterRules(this.interactionConfig.ugcFilterRules);\n }\n }\n if (options.debugMode) {\n this.debugMode = options.debugMode;\n }\n // Support both new useWebWorker and legacy experimental.useWebWorker for backwards\n // compatibility. Defaults to true per the validated amp-on-amp perf config (SR-4646):\n // compression runs off the main thread unless the consumer explicitly sets either flag\n // to false. The top-level option wins over the legacy experimental one when both are set.\n const legacyOptions = options as { experimental?: { useWebWorker?: boolean } };\n this.useWebWorker = options.useWebWorker ?? legacyOptions.experimental?.useWebWorker ?? true;\n this.enableTransportCompression = options.enableTransportCompression ?? true;\n // Pass through undefined so the track destination applies its SEND_TIMEOUT_MS default;\n // an explicit 0 is preserved (disables the timeout).\n this.sendTimeoutMs = options.sendTimeoutMs;\n this.captureAdoptedStyleSheets = options.captureAdoptedStyleSheets ?? true;\n if (options.crossOriginIframes) {\n this.crossOriginIframes = options.crossOriginIframes;\n }\n if (options.flushIntervalConfig) {\n this.flushIntervalConfig = sanitizeFlushIntervalConfig(options.flushIntervalConfig, this.loggerProvider);\n } else {\n // Default to the validated amp-on-amp perf config (SR-4646). The values are known-valid\n // (min <= max, both above the floor), so no sanitization is required.\n this.flushIntervalConfig = {\n minIntervalMs: DEFAULT_FLUSH_MIN_INTERVAL_MS,\n maxIntervalMs: DEFAULT_FLUSH_MAX_INTERVAL_MS,\n };\n }\n }\n}\n\n// 100ms floor avoids degenerate configs (0/negative) that would split on every event.\n// Customers wanting fewer requests should be raising the value, not lowering it; the floor\n// is just a defensive guard against typos and unsigned-int rollovers.\nconst MIN_FLUSH_INTERVAL_FLOOR_MS = 100;\n\n// Shared 1 KB floor for the byte-size overrides — small enough to exercise splitting/drops\n// while debugging, large enough to avoid a 0/negative config that splits on every event.\nconst MIN_EVENT_BYTE_SIZE = 1_000;\n// Batch cap ceiling: stay under the SR ingest service's 10 MB decompressed split threshold\n// (above which the server splits the batch itself) with headroom for the request wrapper.\nconst MAX_PERSISTED_EVENTS_SIZE_CEILING = 8_000_000;\n// Single-event ceiling: the server rejects a single event above ~10 MB, so never allow an\n// override to exceed that.\nconst MAX_SINGLE_EVENT_SIZE_CEILING = 10_000_000;\n\n// Defensive bounds for the byte-size overrides. Non-finite inputs are ignored (fall back to\n// the SDK default); out-of-range values are clamped and logged so a typo can't silently\n// disable splitting or push past the server's limits.\nfunction sanitizeByteSize(\n raw: number,\n min: number,\n max: number,\n name: string,\n loggerProvider: ILogger,\n): number | undefined {\n if (!Number.isFinite(raw)) {\n loggerProvider.warn(`${name} value is not a finite number (got ${String(raw)}); ignoring.`);\n return undefined;\n }\n if (raw < min) {\n loggerProvider.warn(`${name} ${raw} is below floor ${min}; clamping.`);\n return min;\n }\n if (raw > max) {\n loggerProvider.warn(`${name} ${raw} exceeds ceiling ${max}; clamping.`);\n return max;\n }\n return raw;\n}\n\nfunction sanitizeFlushIntervalConfig(raw: FlushIntervalConfig, loggerProvider: ILogger): FlushIntervalConfig {\n const sanitized: FlushIntervalConfig = {};\n if (raw.minIntervalMs !== undefined) {\n if (!Number.isFinite(raw.minIntervalMs) || raw.minIntervalMs < MIN_FLUSH_INTERVAL_FLOOR_MS) {\n loggerProvider.warn(\n `flushIntervalConfig.minIntervalMs ${raw.minIntervalMs} is below floor ${MIN_FLUSH_INTERVAL_FLOOR_MS}ms; clamping.`,\n );\n sanitized.minIntervalMs = MIN_FLUSH_INTERVAL_FLOOR_MS;\n } else {\n sanitized.minIntervalMs = raw.minIntervalMs;\n }\n }\n if (raw.maxIntervalMs !== undefined) {\n // Unlike min, `Infinity` is a meaningful value here: it means \"no upper bound on interval\n // growth\" (Math.min(Infinity, x) === x in BaseEventsStore.shouldSplitEventsList). Reject\n // only NaN and sub-floor values; pass Infinity through.\n if (Number.isNaN(raw.maxIntervalMs) || raw.maxIntervalMs < MIN_FLUSH_INTERVAL_FLOOR_MS) {\n loggerProvider.warn(\n `flushIntervalConfig.maxIntervalMs ${raw.maxIntervalMs} is below floor ${MIN_FLUSH_INTERVAL_FLOOR_MS}ms; clamping.`,\n );\n sanitized.maxIntervalMs = MIN_FLUSH_INTERVAL_FLOOR_MS;\n } else {\n sanitized.maxIntervalMs = raw.maxIntervalMs;\n }\n }\n // Cross-validate against the SDK's effective defaults so that a partial config (only one of\n // {minIntervalMs, maxIntervalMs}) doesn't get silently clamped by the unspecified default.\n // Concrete failure mode without this: customer sets only `minIntervalMs: 30_000`, the store's\n // `maxInterval` falls back to `MAX_INTERVAL = 10_000`, and `shouldSplitEventsList` then\n // caps the effective interval at 10s — silently negating the customer's tune-up.\n // The user-supplied value always wins; we fill in the other side to match.\n if (sanitized.minIntervalMs !== undefined || sanitized.maxIntervalMs !== undefined) {\n const effectiveMin = sanitized.minIntervalMs ?? MIN_INTERVAL;\n const effectiveMax = sanitized.maxIntervalMs ?? MAX_INTERVAL;\n if (effectiveMax < effectiveMin) {\n if (sanitized.maxIntervalMs === undefined) {\n loggerProvider.warn(\n `flushIntervalConfig.minIntervalMs (${effectiveMin}) exceeds the default maxIntervalMs (${MAX_INTERVAL}); raising max to match min.`,\n );\n sanitized.maxIntervalMs = effectiveMin;\n } else if (sanitized.minIntervalMs === undefined) {\n loggerProvider.warn(\n `flushIntervalConfig.maxIntervalMs (${effectiveMax}) is below the default minIntervalMs (${MIN_INTERVAL}); lowering min to match max.`,\n );\n sanitized.minIntervalMs = effectiveMax;\n } else {\n loggerProvider.warn(\n `flushIntervalConfig.maxIntervalMs (${sanitized.maxIntervalMs}) is less than minIntervalMs (${sanitized.minIntervalMs}); raising max to match min.`,\n );\n sanitized.maxIntervalMs = sanitized.minIntervalMs;\n }\n }\n }\n return sanitized;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"local-config.js","sourceRoot":"","sources":["../../../src/config/local-config.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Config,\n ILogger,\n Logger,\n FetchTransport,\n LogLevel,\n IDiagnosticsClient,\n DiagnosticsClient,\n} from '@amplitude/analytics-core';\nimport {\n DEFAULT_FLUSH_MAX_INTERVAL_MS,\n DEFAULT_FLUSH_MIN_INTERVAL_MS,\n DEFAULT_PERFORMANCE_CONFIG,\n DEFAULT_SAMPLE_RATE,\n DEFAULT_SERVER_ZONE,\n DEFAULT_URL_CHANGE_POLLING_INTERVAL,\n MAX_INTERVAL,\n MIN_INTERVAL,\n UNMASK_TEXT_CLASS,\n} from '../constants';\nimport { SessionReplayOptions, StoreType } from '../typings/session-replay';\nimport {\n SessionReplayLocalConfig as ISessionReplayLocalConfig,\n CrossOriginIframesConfig,\n FlushIntervalConfig,\n InteractionConfig,\n PrivacyConfig,\n SessionReplayPerformanceConfig,\n SessionReplayVersion,\n} from './types';\nimport { SafeLoggerProvider } from '../logger';\nimport { validateUGCFilterRules } from '../helpers';\n\nexport const getDefaultConfig = () => ({\n flushMaxRetries: 2,\n logLevel: LogLevel.Warn,\n loggerProvider: new Logger(),\n transportProvider: new FetchTransport(),\n});\n\nexport class SessionReplayLocalConfig extends Config implements ISessionReplayLocalConfig {\n apiKey: string;\n sampleRate: number;\n privacyConfig?: PrivacyConfig;\n interactionConfig?: InteractionConfig;\n debugMode?: boolean;\n configServerUrl?: string;\n trackServerUrl?: string;\n shouldInlineStylesheet?: boolean;\n version?: SessionReplayVersion;\n storeType: StoreType;\n performanceConfig?: SessionReplayPerformanceConfig;\n useWebWorker?: boolean;\n enableTransportCompression?: boolean;\n sendTimeoutMs?: number;\n applyBackgroundColorToBlockedElements?: boolean;\n enableUrlChangePolling?: boolean;\n urlChangePollingInterval?: number;\n captureDocumentTitle?: boolean;\n captureAdoptedStyleSheets?: boolean;\n crossOriginIframes?: CrossOriginIframesConfig;\n fullSnapshotIntervalMs?: number;\n flushIntervalConfig?: FlushIntervalConfig;\n eagerFullSnapshotSend?: boolean;\n captureFullSnapshotOnFocus?: boolean;\n maxPersistedEventsSizeBytes?: number;\n maxSingleEventSizeBytes?: number;\n diagnosticsClient?: IDiagnosticsClient;\n diagnosticsEnabled?: boolean;\n diagnosticsSampleRate?: number;\n\n constructor(apiKey: string, options: SessionReplayOptions) {\n const defaultConfig = getDefaultConfig();\n super({\n transportProvider: defaultConfig.transportProvider,\n loggerProvider: new SafeLoggerProvider(options.loggerProvider || defaultConfig.loggerProvider),\n ...options,\n apiKey,\n });\n this.flushMaxRetries =\n options.flushMaxRetries !== undefined && options.flushMaxRetries <= defaultConfig.flushMaxRetries\n ? options.flushMaxRetries\n : defaultConfig.flushMaxRetries;\n\n this.apiKey = apiKey;\n this.sampleRate = options.sampleRate || DEFAULT_SAMPLE_RATE;\n this.serverZone = options.serverZone || DEFAULT_SERVER_ZONE;\n this.configServerUrl = options.configServerUrl;\n this.trackServerUrl = options.trackServerUrl;\n this.shouldInlineStylesheet = options.shouldInlineStylesheet;\n this.version = options.version;\n this.performanceConfig = options.performanceConfig || DEFAULT_PERFORMANCE_CONFIG;\n this.storeType = options.storeType ?? 'memory';\n this.applyBackgroundColorToBlockedElements = options.applyBackgroundColorToBlockedElements ?? false;\n this.enableUrlChangePolling = options.enableUrlChangePolling ?? false;\n this.urlChangePollingInterval = options.urlChangePollingInterval ?? DEFAULT_URL_CHANGE_POLLING_INTERVAL;\n this.captureDocumentTitle = options.captureDocumentTitle ?? false;\n if (options.fullSnapshotIntervalMs !== undefined) {\n this.fullSnapshotIntervalMs = options.fullSnapshotIntervalMs;\n }\n if (options.eagerFullSnapshotSend !== undefined) {\n this.eagerFullSnapshotSend = options.eagerFullSnapshotSend;\n }\n // Defaults to false per the validated amp-on-amp perf config (SR-4646): the on-focus full\n // snapshot is off unless the consumer explicitly opts in. focusListener honors this by\n // skipping the snapshot whenever the value is not true.\n this.captureFullSnapshotOnFocus = options.captureFullSnapshotOnFocus ?? false;\n if (options.maxPersistedEventsSizeBytes !== undefined) {\n this.maxPersistedEventsSizeBytes = sanitizeByteSize(\n options.maxPersistedEventsSizeBytes,\n MIN_EVENT_BYTE_SIZE,\n MAX_PERSISTED_EVENTS_SIZE_CEILING,\n 'maxPersistedEventsSizeBytes',\n this.loggerProvider,\n );\n }\n if (options.maxSingleEventSizeBytes !== undefined) {\n this.maxSingleEventSizeBytes = sanitizeByteSize(\n options.maxSingleEventSizeBytes,\n MIN_EVENT_BYTE_SIZE,\n MAX_SINGLE_EVENT_SIZE_CEILING,\n 'maxSingleEventSizeBytes',\n this.loggerProvider,\n );\n }\n\n // Auto-include .amp-unmask as a default unmaskSelector entry so it works\n // symmetrically with amp-mask/amp-block without requiring explicit config (SR-2945).\n this.privacyConfig = {\n ...(options.privacyConfig ?? {}),\n unmaskSelector: Array.from(new Set([`.${UNMASK_TEXT_CLASS}`, ...(options.privacyConfig?.unmaskSelector ?? [])])),\n };\n if (options.interactionConfig) {\n this.interactionConfig = options.interactionConfig;\n\n // validate ugcFilterRules, throw error if invalid - throw error at the beginning of the config\n if (this.interactionConfig.ugcFilterRules) {\n validateUGCFilterRules(this.interactionConfig.ugcFilterRules);\n }\n }\n if (options.debugMode) {\n this.debugMode = options.debugMode;\n }\n // Support both new useWebWorker and legacy experimental.useWebWorker for backwards\n // compatibility. Defaults to true per the validated amp-on-amp perf config (SR-4646):\n // compression runs off the main thread unless the consumer explicitly sets either flag\n // to false. The top-level option wins over the legacy experimental one when both are set.\n const legacyOptions = options as { experimental?: { useWebWorker?: boolean } };\n this.useWebWorker = options.useWebWorker ?? legacyOptions.experimental?.useWebWorker ?? true;\n this.enableTransportCompression = options.enableTransportCompression ?? true;\n // Pass through undefined so the track destination applies its SEND_TIMEOUT_MS default;\n // an explicit 0 is preserved (disables the timeout).\n this.sendTimeoutMs = options.sendTimeoutMs;\n this.captureAdoptedStyleSheets = options.captureAdoptedStyleSheets ?? true;\n if (options.crossOriginIframes) {\n this.crossOriginIframes = options.crossOriginIframes;\n }\n if (options.flushIntervalConfig) {\n this.flushIntervalConfig = sanitizeFlushIntervalConfig(options.flushIntervalConfig, this.loggerProvider);\n } else {\n // Default to the validated amp-on-amp perf config (SR-4646). The values are known-valid\n // (min <= max, both above the floor), so no sanitization is required.\n this.flushIntervalConfig = {\n minIntervalMs: DEFAULT_FLUSH_MIN_INTERVAL_MS,\n maxIntervalMs: DEFAULT_FLUSH_MAX_INTERVAL_MS,\n };\n }\n this.diagnosticsEnabled = options.diagnosticsEnabled;\n this.diagnosticsSampleRate = options.diagnosticsSampleRate;\n // Single diagnostics client: in plugin mode the analytics SDK passes its own client in\n // (reused, not duplicated). Standalone SR has no analytics SDK, so create one here — but only\n // when explicitly opted in, to avoid imposing IndexedDB + flush-timer overhead on standalone\n // users who don't want diagnostics.\n this.diagnosticsClient = options.diagnosticsClient ?? this.createStandaloneDiagnosticsClient(apiKey, options);\n }\n\n private createStandaloneDiagnosticsClient(\n apiKey: string,\n options: SessionReplayOptions,\n ): IDiagnosticsClient | undefined {\n const { diagnosticsEnabled, diagnosticsSampleRate } = options;\n const optedIn =\n diagnosticsEnabled === true || (typeof diagnosticsSampleRate === 'number' && diagnosticsSampleRate > 0);\n if (!optedIn) {\n return undefined;\n }\n return new DiagnosticsClient(apiKey, this.loggerProvider, this.serverZone, {\n enabled: diagnosticsEnabled ?? true,\n sampleRate: diagnosticsSampleRate ?? 0,\n });\n }\n}\n\n// 100ms floor avoids degenerate configs (0/negative) that would split on every event.\n// Customers wanting fewer requests should be raising the value, not lowering it; the floor\n// is just a defensive guard against typos and unsigned-int rollovers.\nconst MIN_FLUSH_INTERVAL_FLOOR_MS = 100;\n\n// Shared 1 KB floor for the byte-size overrides — small enough to exercise splitting/drops\n// while debugging, large enough to avoid a 0/negative config that splits on every event.\nconst MIN_EVENT_BYTE_SIZE = 1_000;\n// Batch cap ceiling: stay under the SR ingest service's 10 MB decompressed split threshold\n// (above which the server splits the batch itself) with headroom for the request wrapper.\nconst MAX_PERSISTED_EVENTS_SIZE_CEILING = 8_000_000;\n// Single-event ceiling: the server rejects a single event above ~10 MB, so never allow an\n// override to exceed that.\nconst MAX_SINGLE_EVENT_SIZE_CEILING = 10_000_000;\n\n// Defensive bounds for the byte-size overrides. Non-finite inputs are ignored (fall back to\n// the SDK default); out-of-range values are clamped and logged so a typo can't silently\n// disable splitting or push past the server's limits.\nfunction sanitizeByteSize(\n raw: number,\n min: number,\n max: number,\n name: string,\n loggerProvider: ILogger,\n): number | undefined {\n if (!Number.isFinite(raw)) {\n loggerProvider.warn(`${name} value is not a finite number (got ${String(raw)}); ignoring.`);\n return undefined;\n }\n if (raw < min) {\n loggerProvider.warn(`${name} ${raw} is below floor ${min}; clamping.`);\n return min;\n }\n if (raw > max) {\n loggerProvider.warn(`${name} ${raw} exceeds ceiling ${max}; clamping.`);\n return max;\n }\n return raw;\n}\n\nfunction sanitizeFlushIntervalConfig(raw: FlushIntervalConfig, loggerProvider: ILogger): FlushIntervalConfig {\n const sanitized: FlushIntervalConfig = {};\n if (raw.minIntervalMs !== undefined) {\n if (!Number.isFinite(raw.minIntervalMs) || raw.minIntervalMs < MIN_FLUSH_INTERVAL_FLOOR_MS) {\n loggerProvider.warn(\n `flushIntervalConfig.minIntervalMs ${raw.minIntervalMs} is below floor ${MIN_FLUSH_INTERVAL_FLOOR_MS}ms; clamping.`,\n );\n sanitized.minIntervalMs = MIN_FLUSH_INTERVAL_FLOOR_MS;\n } else {\n sanitized.minIntervalMs = raw.minIntervalMs;\n }\n }\n if (raw.maxIntervalMs !== undefined) {\n // Unlike min, `Infinity` is a meaningful value here: it means \"no upper bound on interval\n // growth\" (Math.min(Infinity, x) === x in BaseEventsStore.shouldSplitEventsList). Reject\n // only NaN and sub-floor values; pass Infinity through.\n if (Number.isNaN(raw.maxIntervalMs) || raw.maxIntervalMs < MIN_FLUSH_INTERVAL_FLOOR_MS) {\n loggerProvider.warn(\n `flushIntervalConfig.maxIntervalMs ${raw.maxIntervalMs} is below floor ${MIN_FLUSH_INTERVAL_FLOOR_MS}ms; clamping.`,\n );\n sanitized.maxIntervalMs = MIN_FLUSH_INTERVAL_FLOOR_MS;\n } else {\n sanitized.maxIntervalMs = raw.maxIntervalMs;\n }\n }\n // Cross-validate against the SDK's effective defaults so that a partial config (only one of\n // {minIntervalMs, maxIntervalMs}) doesn't get silently clamped by the unspecified default.\n // Concrete failure mode without this: customer sets only `minIntervalMs: 30_000`, the store's\n // `maxInterval` falls back to `MAX_INTERVAL = 10_000`, and `shouldSplitEventsList` then\n // caps the effective interval at 10s — silently negating the customer's tune-up.\n // The user-supplied value always wins; we fill in the other side to match.\n if (sanitized.minIntervalMs !== undefined || sanitized.maxIntervalMs !== undefined) {\n const effectiveMin = sanitized.minIntervalMs ?? MIN_INTERVAL;\n const effectiveMax = sanitized.maxIntervalMs ?? MAX_INTERVAL;\n if (effectiveMax < effectiveMin) {\n if (sanitized.maxIntervalMs === undefined) {\n loggerProvider.warn(\n `flushIntervalConfig.minIntervalMs (${effectiveMin}) exceeds the default maxIntervalMs (${MAX_INTERVAL}); raising max to match min.`,\n );\n sanitized.maxIntervalMs = effectiveMin;\n } else if (sanitized.minIntervalMs === undefined) {\n loggerProvider.warn(\n `flushIntervalConfig.maxIntervalMs (${effectiveMax}) is below the default minIntervalMs (${MIN_INTERVAL}); lowering min to match max.`,\n );\n sanitized.minIntervalMs = effectiveMax;\n } else {\n loggerProvider.warn(\n `flushIntervalConfig.maxIntervalMs (${sanitized.maxIntervalMs}) is less than minIntervalMs (${sanitized.minIntervalMs}); raising max to match min.`,\n );\n sanitized.maxIntervalMs = sanitized.minIntervalMs;\n }\n }\n }\n return sanitized;\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IConfig, LogLevel, ILogger } from '@amplitude/analytics-core';
|
|
1
|
+
import { IConfig, LogLevel, ILogger, IDiagnosticsClient } from '@amplitude/analytics-core';
|
|
2
2
|
import { StoreType, ConsoleLogLevel } from '../typings/session-replay';
|
|
3
3
|
import { TargetingFlag } from '@amplitude/targeting';
|
|
4
4
|
export interface SamplingConfig {
|
|
@@ -101,6 +101,24 @@ export interface CrossOriginIframesConfig {
|
|
|
101
101
|
export interface SessionReplayLocalConfig extends IConfig {
|
|
102
102
|
apiKey: string;
|
|
103
103
|
loggerProvider: ILogger;
|
|
104
|
+
/**
|
|
105
|
+
* Optional diagnostics client used to ship SR decision/targeting telemetry to Amplitude's
|
|
106
|
+
* diagnostics backend (independent of whether a replay is recorded). In plugin mode this is
|
|
107
|
+
* forwarded from the analytics SDK's already-initialized client. No-op when absent or when
|
|
108
|
+
* diagnostics is not sampled in. See DiagnosticsClient in @amplitude/analytics-core.
|
|
109
|
+
*/
|
|
110
|
+
diagnosticsClient?: IDiagnosticsClient;
|
|
111
|
+
/**
|
|
112
|
+
* Standalone SR only: when no `diagnosticsClient` is provided (i.e. SR is not running as the
|
|
113
|
+
* analytics plugin), opt in to having SR create its own client so TRC/recording diagnostics are
|
|
114
|
+
* still shipped. Ignored when a `diagnosticsClient` is supplied. @defaultValue false
|
|
115
|
+
*/
|
|
116
|
+
diagnosticsEnabled?: boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Standalone SR only: sample rate (0..1) for the diagnostics client SR creates when none is
|
|
119
|
+
* provided. A positive value also implies opting in. @defaultValue 0
|
|
120
|
+
*/
|
|
121
|
+
diagnosticsSampleRate?: number;
|
|
104
122
|
/**
|
|
105
123
|
* LogLevel.None or LogLevel.Error or LogLevel.Warn or LogLevel.Verbose or LogLevel.Debug.
|
|
106
124
|
* Sets the log level.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/config/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/config/types.ts"],"names":[],"mappings":"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"}
|