@amplitude/session-replay-browser 1.47.0-sr-trc-debug-log.3 → 1.47.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/README.md +203 -0
- package/lib/cjs/beacon-transport.d.ts +2 -0
- package/lib/cjs/beacon-transport.d.ts.map +1 -1
- package/lib/cjs/beacon-transport.js +39 -1
- package/lib/cjs/beacon-transport.js.map +1 -1
- package/lib/cjs/config/joined-config.d.ts +1 -6
- package/lib/cjs/config/joined-config.d.ts.map +1 -1
- package/lib/cjs/config/joined-config.js +23 -64
- package/lib/cjs/config/joined-config.js.map +1 -1
- package/lib/cjs/config/local-config.d.ts +4 -6
- package/lib/cjs/config/local-config.d.ts.map +1 -1
- package/lib/cjs/config/local-config.js +3 -19
- package/lib/cjs/config/local-config.js.map +1 -1
- package/lib/cjs/config/types.d.ts +74 -19
- package/lib/cjs/config/types.d.ts.map +1 -1
- package/lib/cjs/config/types.js.map +1 -1
- package/lib/cjs/index.d.ts +1 -0
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/plugins/url-tracking-plugin.d.ts +0 -13
- package/lib/cjs/plugins/url-tracking-plugin.d.ts.map +1 -1
- package/lib/cjs/plugins/url-tracking-plugin.js +2 -6
- package/lib/cjs/plugins/url-tracking-plugin.js.map +1 -1
- package/lib/cjs/session-replay.d.ts +0 -33
- package/lib/cjs/session-replay.d.ts.map +1 -1
- package/lib/cjs/session-replay.js +40 -335
- package/lib/cjs/session-replay.js.map +1 -1
- package/lib/cjs/targeting/targeting-manager.d.ts +1 -4
- package/lib/cjs/targeting/targeting-manager.d.ts.map +1 -1
- package/lib/cjs/targeting/targeting-manager.js +10 -56
- package/lib/cjs/targeting/targeting-manager.js.map +1 -1
- package/lib/cjs/track-destination.d.ts +5 -1
- package/lib/cjs/track-destination.d.ts.map +1 -1
- package/lib/cjs/track-destination.js +212 -55
- package/lib/cjs/track-destination.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/cjs/worker/index.js +1 -1
- package/lib/esm/beacon-transport.d.ts +2 -0
- package/lib/esm/beacon-transport.d.ts.map +1 -1
- package/lib/esm/beacon-transport.js +39 -1
- package/lib/esm/beacon-transport.js.map +1 -1
- package/lib/esm/config/joined-config.d.ts +1 -6
- package/lib/esm/config/joined-config.d.ts.map +1 -1
- package/lib/esm/config/joined-config.js +23 -64
- package/lib/esm/config/joined-config.js.map +1 -1
- package/lib/esm/config/local-config.d.ts +4 -6
- package/lib/esm/config/local-config.d.ts.map +1 -1
- package/lib/esm/config/local-config.js +4 -20
- package/lib/esm/config/local-config.js.map +1 -1
- package/lib/esm/config/types.d.ts +74 -19
- package/lib/esm/config/types.d.ts.map +1 -1
- package/lib/esm/config/types.js.map +1 -1
- package/lib/esm/index.d.ts +1 -0
- package/lib/esm/index.d.ts.map +1 -1
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/plugins/url-tracking-plugin.d.ts +0 -13
- package/lib/esm/plugins/url-tracking-plugin.d.ts.map +1 -1
- package/lib/esm/plugins/url-tracking-plugin.js +2 -6
- package/lib/esm/plugins/url-tracking-plugin.js.map +1 -1
- package/lib/esm/session-replay.d.ts +0 -33
- package/lib/esm/session-replay.d.ts.map +1 -1
- package/lib/esm/session-replay.js +40 -335
- package/lib/esm/session-replay.js.map +1 -1
- package/lib/esm/targeting/targeting-manager.d.ts +1 -4
- package/lib/esm/targeting/targeting-manager.d.ts.map +1 -1
- package/lib/esm/targeting/targeting-manager.js +10 -56
- package/lib/esm/targeting/targeting-manager.js.map +1 -1
- package/lib/esm/track-destination.d.ts +5 -1
- package/lib/esm/track-destination.d.ts.map +1 -1
- package/lib/esm/track-destination.js +212 -55
- package/lib/esm/track-destination.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/esm/worker/index.js +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/lib/scripts/worker-min.js +1 -1
- package/lib/scripts/worker-min.js.gz +0 -0
- package/package.json +4 -4
- package/lib/cjs/diagnostics.d.ts +0 -50
- package/lib/cjs/diagnostics.d.ts.map +0 -1
- package/lib/cjs/diagnostics.js +0 -67
- package/lib/cjs/diagnostics.js.map +0 -1
- package/lib/esm/diagnostics.d.ts +0 -50
- package/lib/esm/diagnostics.d.ts.map +0 -1
- package/lib/esm/diagnostics.js +0 -64
- package/lib/esm/diagnostics.js.map +0 -1
|
@@ -17,7 +17,6 @@ var identifiers_1 = require("./identifiers");
|
|
|
17
17
|
var logger_1 = require("./logger");
|
|
18
18
|
var replay_start_time_store_1 = require("./replay-start-time-store");
|
|
19
19
|
var targeting_manager_1 = require("./targeting/targeting-manager");
|
|
20
|
-
var diagnostics_1 = require("./diagnostics");
|
|
21
20
|
var sampling_1 = require("./sampling");
|
|
22
21
|
var version_1 = require("./version");
|
|
23
22
|
var url_tracking_plugin_1 = require("./plugins/url-tracking-plugin");
|
|
@@ -29,10 +28,6 @@ var SessionReplay = /** @class */ (function () {
|
|
|
29
28
|
this.recordCancelCallback = null;
|
|
30
29
|
this.eventCount = 0;
|
|
31
30
|
this.sessionTargetingMatch = false;
|
|
32
|
-
// Session for which the one-per-session TRC diagnostic event was already emitted. The
|
|
33
|
-
// diagnostics client caps in-memory events, so per-call signals go through counters and only
|
|
34
|
-
// a single rich snapshot event is recorded per session.
|
|
35
|
-
this.trcDiagnosticSessionId = undefined;
|
|
36
31
|
// Public on purpose. `pageLeaveFns` is iterated by `pageLeaveListener`,
|
|
37
32
|
// `rrwebEventManager` is dereferenced in `asyncSetSessionId` to drop the beacon buffer
|
|
38
33
|
// at a session boundary, and `sessionStartTime` drives `isBelowMinSessionDuration()`.
|
|
@@ -55,9 +50,6 @@ var SessionReplay = /** @class */ (function () {
|
|
|
55
50
|
this.recordEventsPendingShouldLogMetadata = null;
|
|
56
51
|
/** Cleanup for URL change listener used to re-evaluate targeting on SPA route changes */
|
|
57
52
|
this.urlChangeCleanup = null;
|
|
58
|
-
// Ensures the url_poll.first_tick diagnostic event is emitted at most once per listener setup
|
|
59
|
-
// (the per-tick counter still increments every tick; only the rich event is one-shot).
|
|
60
|
-
this.urlPollFirstTickRecorded = false;
|
|
61
53
|
this.crossOriginIframeCoordinator = null;
|
|
62
54
|
this.crossOriginParentSignalCleanup = null;
|
|
63
55
|
/** Monotonic counter to ignore stale URL-change targeting results */
|
|
@@ -126,23 +118,12 @@ var SessionReplay = /** @class */ (function () {
|
|
|
126
118
|
if (forceRestart === void 0) { forceRestart = false; }
|
|
127
119
|
if (forceTargetingReevaluation === void 0) { forceTargetingReevaluation = false; }
|
|
128
120
|
return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
129
|
-
var targetingConfig, shouldReEvaluate, urlChangeEvaluationId, eventForTargeting, pageUrl, pageForTargeting,
|
|
130
|
-
var _a, _b, _c, _d, _e, _f
|
|
131
|
-
return tslib_1.__generator(this, function (
|
|
132
|
-
switch (
|
|
121
|
+
var targetingConfig, shouldReEvaluate, urlChangeEvaluationId, eventForTargeting, pageUrl, pageForTargeting, targetingMatch;
|
|
122
|
+
var _a, _b, _c, _d, _e, _f;
|
|
123
|
+
return tslib_1.__generator(this, function (_g) {
|
|
124
|
+
switch (_g.label) {
|
|
133
125
|
case 0:
|
|
134
|
-
// What triggered this evaluation (init vs SPA URL change vs analytics event) — shows in
|
|
135
|
-
// DataDog how often re-evaluation actually runs.
|
|
136
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.evalTrigger(isInit ? 'init' : forceTargetingReevaluation ? 'urlchange' : 'event'));
|
|
137
126
|
if (!this.identifiers || !this.identifiers.sessionId || !this.config) {
|
|
138
|
-
// Q4: eval can't run because a prerequisite is missing — record exactly which one.
|
|
139
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.evalMissingPrereq);
|
|
140
|
-
this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.evalMissingPrereq, {
|
|
141
|
-
hasIdentifiers: !!this.identifiers,
|
|
142
|
-
hasSessionId: !!((_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId),
|
|
143
|
-
hasConfig: !!this.config,
|
|
144
|
-
hasDeviceId: !!this.getDeviceId(),
|
|
145
|
-
});
|
|
146
127
|
if (this.identifiers && !this.identifiers.sessionId) {
|
|
147
128
|
this.loggerProvider.log('Session ID has not been set yet, cannot evaluate targeting for Session Replay.');
|
|
148
129
|
}
|
|
@@ -153,7 +134,6 @@ var SessionReplay = /** @class */ (function () {
|
|
|
153
134
|
}
|
|
154
135
|
// Handle cases where there's no targeting config
|
|
155
136
|
if (!this.config.targetingConfig) {
|
|
156
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.evalNoConfig);
|
|
157
137
|
if (isInit) {
|
|
158
138
|
this.loggerProvider.log('Targeting config has not been set yet, cannot evaluate targeting.');
|
|
159
139
|
}
|
|
@@ -173,20 +153,8 @@ var SessionReplay = /** @class */ (function () {
|
|
|
173
153
|
Object.values(analytics_core_1.SpecialEventType).includes(eventForTargeting.event_type)) {
|
|
174
154
|
eventForTargeting = undefined;
|
|
175
155
|
}
|
|
176
|
-
pageUrl = (
|
|
177
|
-
pageForTargeting = (
|
|
178
|
-
// Record the targeting trigger event
|
|
179
|
-
this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.targetingTrigger, {
|
|
180
|
-
sessionId: this.identifiers.sessionId,
|
|
181
|
-
deviceId: this.getDeviceId(),
|
|
182
|
-
targetingConfig: this.config.targetingConfig,
|
|
183
|
-
targetingParams: {
|
|
184
|
-
userProperties: targetingParams.userProperties,
|
|
185
|
-
event: eventForTargeting,
|
|
186
|
-
page: pageForTargeting,
|
|
187
|
-
},
|
|
188
|
-
});
|
|
189
|
-
evalStart = Date.now();
|
|
156
|
+
pageUrl = (_e = (_b = (_a = targetingParams.page) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : (_d = (_c = (0, analytics_core_1.getGlobalScope)()) === null || _c === void 0 ? void 0 : _c.location) === null || _d === void 0 ? void 0 : _d.href) !== null && _e !== void 0 ? _e : '';
|
|
157
|
+
pageForTargeting = (_f = targetingParams.page) !== null && _f !== void 0 ? _f : (pageUrl !== '' ? { url: pageUrl } : undefined);
|
|
190
158
|
return [4 /*yield*/, (0, targeting_manager_1.evaluateTargetingAndStore)({
|
|
191
159
|
sessionId: this.identifiers.sessionId,
|
|
192
160
|
targetingConfig: targetingConfig,
|
|
@@ -198,76 +166,38 @@ var SessionReplay = /** @class */ (function () {
|
|
|
198
166
|
page: pageForTargeting,
|
|
199
167
|
},
|
|
200
168
|
urlChange: forceTargetingReevaluation,
|
|
201
|
-
diagnosticsClient: this.config.diagnosticsClient,
|
|
202
|
-
deviceId: this.getDeviceId(),
|
|
203
169
|
})];
|
|
204
170
|
case 1:
|
|
205
|
-
targetingMatch =
|
|
206
|
-
evalDurationMs = Date.now() - evalStart;
|
|
207
|
-
trigger = isInit ? 'init' : forceTargetingReevaluation ? 'urlchange' : 'event';
|
|
208
|
-
// Evaluation latency — surfaces the slow-network residual gap (SR-4234) in DataDog as
|
|
209
|
-
// sdk.diagnostics.sr.trc.eval.duration_ms.{avg,max,...}.
|
|
210
|
-
this.recordDiagnosticHistogram(diagnostics_1.SrDiagnostic.evalDurationMs, evalDurationMs);
|
|
171
|
+
targetingMatch = _g.sent();
|
|
211
172
|
if (forceTargetingReevaluation &&
|
|
212
173
|
urlChangeEvaluationId !== undefined &&
|
|
213
174
|
urlChangeEvaluationId !== this.latestUrlChangeTargetingEvaluationId) {
|
|
214
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.evalStaleDiscarded);
|
|
215
|
-
this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.evalStaleDiscarded, {
|
|
216
|
-
sessionId: this.identifiers.sessionId,
|
|
217
|
-
pageUrl: pageForTargeting === null || pageForTargeting === void 0 ? void 0 : pageForTargeting.url,
|
|
218
|
-
evaluationId: urlChangeEvaluationId,
|
|
219
|
-
latestEvaluationId: this.latestUrlChangeTargetingEvaluationId,
|
|
220
|
-
evalDurationMs: evalDurationMs,
|
|
221
|
-
});
|
|
222
175
|
this.loggerProvider.debug("Ignoring stale URL-change targeting result #".concat(urlChangeEvaluationId, "; latest is #").concat(this.latestUrlChangeTargetingEvaluationId, "."));
|
|
223
176
|
return [2 /*return*/];
|
|
224
177
|
}
|
|
225
|
-
// Per-evaluation outcome (distinct from the per-session sr.gate.* gate counters).
|
|
226
|
-
this.incrementDiagnostic(targetingMatch ? diagnostics_1.SrDiagnostic.evalMatch : diagnostics_1.SrDiagnostic.evalNoMatch);
|
|
227
178
|
// Keep targeting match monotonic within a session: once true, always true.
|
|
228
179
|
// This avoids races where an older in-flight evaluation resolves false after
|
|
229
180
|
// a newer evaluation already resolved true.
|
|
230
181
|
this.sessionTargetingMatch = this.sessionTargetingMatch || targetingMatch;
|
|
231
|
-
// Q5: record ALL evaluation params (→ DataDog Logs) so a single evaluation can be fully
|
|
232
|
-
// reconstructed by URL, identifiers, inputs, outcome, trigger and latency. userProperties
|
|
233
|
-
// values are intentionally reduced to keys to avoid logging PII.
|
|
234
|
-
this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.evalEvent, {
|
|
235
|
-
// sessionId + deviceId are stamped by recordDiagnosticEvent.
|
|
236
|
-
trigger: trigger,
|
|
237
|
-
matched: targetingMatch,
|
|
238
|
-
sessionTargetingMatch: this.sessionTargetingMatch,
|
|
239
|
-
pageUrl: pageForTargeting === null || pageForTargeting === void 0 ? void 0 : pageForTargeting.url,
|
|
240
|
-
hasDeviceId: !!this.getDeviceId(),
|
|
241
|
-
hasEvent: !!eventForTargeting,
|
|
242
|
-
eventType: eventForTargeting === null || eventForTargeting === void 0 ? void 0 : eventForTargeting.event_type,
|
|
243
|
-
userPropertyKeys: targetingParams.userProperties ? Object.keys(targetingParams.userProperties) : [],
|
|
244
|
-
evalDurationMs: evalDurationMs,
|
|
245
|
-
});
|
|
246
182
|
this.loggerProvider.debug(JSON.stringify({
|
|
247
183
|
name: 'targeted replay capture config',
|
|
248
184
|
sessionTargetingMatch: this.sessionTargetingMatch,
|
|
249
185
|
event: eventForTargeting,
|
|
250
186
|
targetingParams: targetingParams,
|
|
251
187
|
}, null, 2));
|
|
252
|
-
|
|
188
|
+
_g.label = 2;
|
|
253
189
|
case 2:
|
|
254
|
-
if (
|
|
255
|
-
// Already matched earlier this session — recording continues without re-evaluation.
|
|
256
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.evalSkippedAlreadyMatched);
|
|
257
|
-
}
|
|
258
|
-
_h.label = 3;
|
|
259
|
-
case 3:
|
|
260
|
-
if (!isInit) return [3 /*break*/, 4];
|
|
190
|
+
if (!isInit) return [3 /*break*/, 3];
|
|
261
191
|
void this.initialize(true);
|
|
262
|
-
return [3 /*break*/,
|
|
263
|
-
case
|
|
264
|
-
if (!(forceRestart || !this.recordCancelCallback)) return [3 /*break*/,
|
|
192
|
+
return [3 /*break*/, 5];
|
|
193
|
+
case 3:
|
|
194
|
+
if (!(forceRestart || !this.recordCancelCallback)) return [3 /*break*/, 5];
|
|
265
195
|
this.loggerProvider.log('Recording events for session due to forceRestart or no ongoing recording.');
|
|
266
196
|
return [4 /*yield*/, this.recordEvents()];
|
|
267
|
-
case
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
case
|
|
197
|
+
case 4:
|
|
198
|
+
_g.sent();
|
|
199
|
+
_g.label = 5;
|
|
200
|
+
case 5: return [2 /*return*/];
|
|
271
201
|
}
|
|
272
202
|
});
|
|
273
203
|
});
|
|
@@ -343,31 +273,17 @@ var SessionReplay = /** @class */ (function () {
|
|
|
343
273
|
*/
|
|
344
274
|
SessionReplay.prototype.setupUrlChangeListener = function () {
|
|
345
275
|
var _this = this;
|
|
346
|
-
var _a, _b
|
|
276
|
+
var _a, _b;
|
|
347
277
|
// If init() runs multiple times, remove the previous URL-change subscription first
|
|
348
278
|
// so we don't leak callbacks and trigger duplicate targeting evaluations.
|
|
349
279
|
(_a = this.urlChangeCleanup) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
350
280
|
var globalScope = (0, analytics_core_1.getGlobalScope)();
|
|
351
281
|
if (!(globalScope === null || globalScope === void 0 ? void 0 : globalScope.location)) {
|
|
352
|
-
// No window/location (SSR, worker, or pre-render) — the listener can't attach, so TRC will
|
|
353
|
-
// never re-evaluate on navigation. Surface it rather than failing silently.
|
|
354
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.urlListenerSkipped);
|
|
355
|
-
this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.urlListenerSkipped, { reason: 'no_global_scope' });
|
|
356
|
-
this.loggerProvider.debug('URL-change listener not attached: no global scope/location.');
|
|
357
282
|
return;
|
|
358
283
|
}
|
|
359
284
|
var hasTargeting = !!((_b = this.config) === null || _b === void 0 ? void 0 : _b.targetingConfig);
|
|
360
285
|
var onUrlChange = function (href) {
|
|
361
286
|
_this.currentPageUrl = href;
|
|
362
|
-
// Team-visible signal that an SPA navigation was detected at all (covers the "is the SDK
|
|
363
|
-
// even seeing route changes in this framework?" question — counter + a log with the href
|
|
364
|
-
// and whether it triggered a targeting re-eval).
|
|
365
|
-
_this.incrementDiagnostic(diagnostics_1.SrDiagnostic.urlChange);
|
|
366
|
-
_this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.urlChangeEvent, {
|
|
367
|
-
href: href,
|
|
368
|
-
hasTargeting: hasTargeting,
|
|
369
|
-
alreadyMatched: _this.sessionTargetingMatch,
|
|
370
|
-
});
|
|
371
287
|
if (hasTargeting) {
|
|
372
288
|
var evaluationId = ++_this.latestUrlChangeTargetingEvaluationId;
|
|
373
289
|
void _this.evaluateTargetingAndCapture({
|
|
@@ -378,39 +294,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
378
294
|
_this.loggerProvider.debug("Queued URL-change targeting re-evaluation #".concat(evaluationId, " for ").concat(href, "."));
|
|
379
295
|
}
|
|
380
296
|
};
|
|
381
|
-
|
|
382
|
-
// Without this, the targeting listener only sees history.pushState/replaceState + popstate +
|
|
383
|
-
// hashchange — so SPA navigations that bypass the history API never re-evaluate TRC and
|
|
384
|
-
// recording never starts on the new URL (enableUrlChangePolling previously only affected the
|
|
385
|
-
// rrweb URL-tracking plugin, which runs only once recording is already active).
|
|
386
|
-
var enablePolling = (_d = (_c = this.config) === null || _c === void 0 ? void 0 : _c.enableUrlChangePolling) !== null && _d !== void 0 ? _d : false;
|
|
387
|
-
this.urlPollFirstTickRecorded = false;
|
|
388
|
-
var unsubscribe = (0, url_tracking_plugin_1.subscribeToUrlChanges)(globalScope, onUrlChange, {
|
|
389
|
-
enablePolling: enablePolling,
|
|
390
|
-
pollingInterval: (_e = this.config) === null || _e === void 0 ? void 0 : _e.urlChangePollingInterval,
|
|
391
|
-
// Mirror each poll tick to the console (Debug level) so we can confirm polling is firing.
|
|
392
|
-
log: this.loggerProvider.debug.bind(this.loggerProvider),
|
|
393
|
-
// Prove in DataDog that polling actually FIRES (not just that it was scheduled). Per-tick is a
|
|
394
|
-
// cheap aggregated counter; the rich event is emitted once (with href) to avoid flooding the
|
|
395
|
-
// diagnostics endpoint with one capture POST per second.
|
|
396
|
-
onPoll: function (href, changed) {
|
|
397
|
-
_this.incrementDiagnostic(diagnostics_1.SrDiagnostic.urlPollTick);
|
|
398
|
-
if (!_this.urlPollFirstTickRecorded) {
|
|
399
|
-
_this.urlPollFirstTickRecorded = true;
|
|
400
|
-
// pollingInterval is already on url_listener.attached, so it's omitted here.
|
|
401
|
-
_this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.urlPollFirstTick, { href: href, changed: changed });
|
|
402
|
-
}
|
|
403
|
-
},
|
|
404
|
-
});
|
|
405
|
-
// Confirm the listener is actually live, and under what settings — if recording never starts on
|
|
406
|
-
// navigation, this tells us whether the listener existed and whether polling (the fallback for
|
|
407
|
-
// SPAs that bypass the History API) was on.
|
|
408
|
-
this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.urlListenerAttached, {
|
|
409
|
-
hasTargeting: hasTargeting,
|
|
410
|
-
enablePolling: enablePolling,
|
|
411
|
-
pollingInterval: (_f = this.config) === null || _f === void 0 ? void 0 : _f.urlChangePollingInterval,
|
|
412
|
-
});
|
|
413
|
-
this.loggerProvider.debug("URL-change listener attached (polling: ".concat(String(enablePolling), ")."));
|
|
297
|
+
var unsubscribe = url_tracking_plugin_1.subscribeToUrlChanges(globalScope, onUrlChange);
|
|
414
298
|
this.urlChangeCleanup = function () {
|
|
415
299
|
unsubscribe();
|
|
416
300
|
_this.urlChangeCleanup = null;
|
|
@@ -439,34 +323,14 @@ var SessionReplay = /** @class */ (function () {
|
|
|
439
323
|
var currentUrl = (_b = (_a = (0, analytics_core_1.getGlobalScope)()) === null || _a === void 0 ? void 0 : _a.location) === null || _b === void 0 ? void 0 : _b.href;
|
|
440
324
|
return currentUrl != null ? { url: currentUrl } : undefined;
|
|
441
325
|
};
|
|
442
|
-
/**
|
|
443
|
-
* Best-effort navigation type from the Navigation Timing API: 'reload' | 'navigate' |
|
|
444
|
-
* 'back_forward' | 'prerender'. Surfaced in the init diagnostic so a page refresh ('reload')
|
|
445
|
-
* is distinguishable from a fresh load ('navigate') — neither changes the session id, so this
|
|
446
|
-
* is the only way to tell them apart. Returns undefined when the API is unavailable.
|
|
447
|
-
*/
|
|
448
|
-
SessionReplay.prototype.getNavigationType = function () {
|
|
449
|
-
try {
|
|
450
|
-
var globalScope = (0, analytics_core_1.getGlobalScope)();
|
|
451
|
-
var performance_1 = globalScope && globalScope.performance;
|
|
452
|
-
if (!performance_1 || typeof performance_1.getEntriesByType !== 'function') {
|
|
453
|
-
return undefined;
|
|
454
|
-
}
|
|
455
|
-
var navEntries = performance_1.getEntriesByType('navigation');
|
|
456
|
-
return navEntries.length > 0 ? navEntries[0].type : undefined;
|
|
457
|
-
}
|
|
458
|
-
catch (_a) {
|
|
459
|
-
return undefined;
|
|
460
|
-
}
|
|
461
|
-
};
|
|
462
326
|
SessionReplay.prototype._init = function (apiKey, options) {
|
|
463
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p
|
|
327
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
464
328
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
465
|
-
var now,
|
|
466
|
-
var e_2,
|
|
329
|
+
var now, _q, _r, joinedConfig, localConfig, remoteConfig, scrollWatcher, managers, storeType, compressionWorkerScript, trackDestinationWorkerScript, globalScope, _s, compressionScript, trackDestinationScript, rrwebEventManager, error_1, typedError, payloadBatcher, interactionEventManager, error_2, typedError, onFullSnapshotProcessed, pending_2, pending_1, pending_1_1, _t, event_1, sessionId, messenger, needsUrlTracking;
|
|
330
|
+
var e_2, _u;
|
|
467
331
|
var _this = this;
|
|
468
|
-
return tslib_1.__generator(this, function (
|
|
469
|
-
switch (
|
|
332
|
+
return tslib_1.__generator(this, function (_v) {
|
|
333
|
+
switch (_v.label) {
|
|
470
334
|
case 0:
|
|
471
335
|
// Re-init should always tear down any previous URL-change subscription, even when the
|
|
472
336
|
// next config has no targeting config and we don't subscribe again.
|
|
@@ -482,13 +346,13 @@ var SessionReplay = /** @class */ (function () {
|
|
|
482
346
|
options.sessionId !== undefined
|
|
483
347
|
? (_b = (0, replay_start_time_store_1.getOrInitReplayStartTime)(apiKey, options.sessionId, now, this.loggerProvider)) !== null && _b !== void 0 ? _b : now
|
|
484
348
|
: now;
|
|
485
|
-
|
|
349
|
+
_q = this;
|
|
486
350
|
return [4 /*yield*/, (0, joined_config_1.createSessionReplayJoinedConfigGenerator)(apiKey, options)];
|
|
487
351
|
case 1:
|
|
488
|
-
|
|
352
|
+
_q.joinedConfigGenerator = _v.sent();
|
|
489
353
|
return [4 /*yield*/, this.joinedConfigGenerator.generateJoinedConfig()];
|
|
490
354
|
case 2:
|
|
491
|
-
|
|
355
|
+
_r = _v.sent(), joinedConfig = _r.joinedConfig, localConfig = _r.localConfig, remoteConfig = _r.remoteConfig;
|
|
492
356
|
this.config = joinedConfig;
|
|
493
357
|
this.setMetadata(options.sessionId, joinedConfig, localConfig, remoteConfig, (_c = options.version) === null || _c === void 0 ? void 0 : _c.version, version_1.VERSION, (_d = options.version) === null || _d === void 0 ? void 0 : _d.type);
|
|
494
358
|
this.pageLeaveFns = [];
|
|
@@ -512,12 +376,12 @@ var SessionReplay = /** @class */ (function () {
|
|
|
512
376
|
if (!(this.config.useWebWorker && globalScope && globalScope.Worker)) return [3 /*break*/, 4];
|
|
513
377
|
return [4 /*yield*/, Promise.resolve().then(function () { return tslib_1.__importStar(require('./worker')); })];
|
|
514
378
|
case 3:
|
|
515
|
-
|
|
379
|
+
_s = _v.sent(), compressionScript = _s.compressionScript, trackDestinationScript = _s.trackDestinationScript;
|
|
516
380
|
compressionWorkerScript = compressionScript;
|
|
517
381
|
trackDestinationWorkerScript = trackDestinationScript;
|
|
518
|
-
|
|
382
|
+
_v.label = 4;
|
|
519
383
|
case 4:
|
|
520
|
-
|
|
384
|
+
_v.trys.push([4, 6, , 7]);
|
|
521
385
|
return [4 /*yield*/, (0, events_manager_1.createEventsManager)({
|
|
522
386
|
config: this.config,
|
|
523
387
|
type: 'replay',
|
|
@@ -529,21 +393,21 @@ var SessionReplay = /** @class */ (function () {
|
|
|
529
393
|
shouldSend: function () { return !_this.isBelowMinSessionDuration(); },
|
|
530
394
|
})];
|
|
531
395
|
case 5:
|
|
532
|
-
rrwebEventManager =
|
|
396
|
+
rrwebEventManager = _v.sent();
|
|
533
397
|
this.rrwebEventManager = rrwebEventManager;
|
|
534
398
|
managers.push({ name: 'replay', manager: rrwebEventManager });
|
|
535
399
|
return [3 /*break*/, 7];
|
|
536
400
|
case 6:
|
|
537
|
-
error_1 =
|
|
401
|
+
error_1 = _v.sent();
|
|
538
402
|
typedError = error_1;
|
|
539
403
|
this.loggerProvider.warn("Error occurred while creating replay events manager: ".concat(typedError.toString()));
|
|
540
404
|
return [3 /*break*/, 7];
|
|
541
405
|
case 7:
|
|
542
406
|
if (!((_j = this.config.interactionConfig) === null || _j === void 0 ? void 0 : _j.enabled)) return [3 /*break*/, 11];
|
|
543
407
|
payloadBatcher = this.config.interactionConfig.batch ? click_1.clickBatcher : click_1.clickNonBatcher;
|
|
544
|
-
|
|
408
|
+
_v.label = 8;
|
|
545
409
|
case 8:
|
|
546
|
-
|
|
410
|
+
_v.trys.push([8, 10, , 11]);
|
|
547
411
|
return [4 /*yield*/, (0, events_manager_1.createEventsManager)({
|
|
548
412
|
config: this.config,
|
|
549
413
|
type: 'interaction',
|
|
@@ -555,11 +419,11 @@ var SessionReplay = /** @class */ (function () {
|
|
|
555
419
|
trackDestinationWorkerScript: trackDestinationWorkerScript,
|
|
556
420
|
})];
|
|
557
421
|
case 9:
|
|
558
|
-
interactionEventManager =
|
|
422
|
+
interactionEventManager = _v.sent();
|
|
559
423
|
managers.push({ name: 'interaction', manager: interactionEventManager });
|
|
560
424
|
return [3 /*break*/, 11];
|
|
561
425
|
case 10:
|
|
562
|
-
error_2 =
|
|
426
|
+
error_2 = _v.sent();
|
|
563
427
|
typedError = error_2;
|
|
564
428
|
this.loggerProvider.warn("Error occurred while creating interaction events manager: ".concat(typedError.toString()));
|
|
565
429
|
return [3 /*break*/, 11];
|
|
@@ -577,14 +441,14 @@ var SessionReplay = /** @class */ (function () {
|
|
|
577
441
|
pending_2 = this.pendingEmitEvents.splice(0);
|
|
578
442
|
try {
|
|
579
443
|
for (pending_1 = tslib_1.__values(pending_2), pending_1_1 = pending_1.next(); !pending_1_1.done; pending_1_1 = pending_1.next()) {
|
|
580
|
-
|
|
444
|
+
_t = pending_1_1.value, event_1 = _t.event, sessionId = _t.sessionId;
|
|
581
445
|
this.eventCompressor.enqueueEvent(event_1, sessionId);
|
|
582
446
|
}
|
|
583
447
|
}
|
|
584
448
|
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
585
449
|
finally {
|
|
586
450
|
try {
|
|
587
|
-
if (pending_1_1 && !pending_1_1.done && (
|
|
451
|
+
if (pending_1_1 && !pending_1_1.done && (_u = pending_1.return)) _u.call(pending_1);
|
|
588
452
|
}
|
|
589
453
|
finally { if (e_2) throw e_2.error; }
|
|
590
454
|
}
|
|
@@ -621,7 +485,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
621
485
|
], false);
|
|
622
486
|
return [4 /*yield*/, this.initializeNetworkObservers()];
|
|
623
487
|
case 12:
|
|
624
|
-
|
|
488
|
+
_v.sent();
|
|
625
489
|
// Enable background capture when this page is opened by the Amplitude app
|
|
626
490
|
// (window.opener exists). Uses the shared messenger singleton so that if
|
|
627
491
|
// autocapture is also loaded, both share a single messenger and script load.
|
|
@@ -632,38 +496,10 @@ var SessionReplay = /** @class */ (function () {
|
|
|
632
496
|
}
|
|
633
497
|
this.loggerProvider.log('Installing @amplitude/session-replay-browser.');
|
|
634
498
|
this.teardownEventListeners(false);
|
|
635
|
-
// Q1 "did init happen?": its presence in DataDog proves init() ran to completion for this
|
|
636
|
-
// session; the props show whether the prerequisites (session/device id, config) were present.
|
|
637
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.init);
|
|
638
|
-
this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.init, {
|
|
639
|
-
// sessionId is always stamped by recordDiagnosticEvent, so no separate hasSessionId here.
|
|
640
|
-
hasDeviceId: !!this.getDeviceId(),
|
|
641
|
-
captureEnabled: this.config.captureEnabled,
|
|
642
|
-
hasTargetingConfig: !!this.config.targetingConfig,
|
|
643
|
-
sampleRate: this.config.sampleRate,
|
|
644
|
-
optOut: this.shouldOptOut(),
|
|
645
|
-
currentUrl: (_m = this.getCurrentPageForTargeting()) === null || _m === void 0 ? void 0 : _m.url,
|
|
646
|
-
// 'reload' tells a page refresh apart from a fresh load ('navigate') or back/forward
|
|
647
|
-
// ('back_forward'). New tabs and refreshes keep the same session id, so this is the only
|
|
648
|
-
// way to distinguish a refresh from a brand-new init within a session.
|
|
649
|
-
navigationType: this.getNavigationType(),
|
|
650
|
-
});
|
|
651
499
|
return [4 /*yield*/, this.evaluateTargetingAndCapture({ userProperties: options.userProperties, page: this.getCurrentPageForTargeting() }, true)];
|
|
652
500
|
case 13:
|
|
653
|
-
|
|
654
|
-
needsUrlTracking = this.config.targetingConfig || ((
|
|
655
|
-
// Record whether we even attempt to wire up the URL-change listener, and the inputs behind that
|
|
656
|
-
// decision. If `needsUrlTracking` is false the listener is never attached, so SPA navigations are
|
|
657
|
-
// invisible to TRC — this is the first thing to check when "TRC is on but never re-evaluates".
|
|
658
|
-
this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.urlListenerSetup, {
|
|
659
|
-
needsUrlTracking: !!needsUrlTracking,
|
|
660
|
-
hasTargetingConfig: !!this.config.targetingConfig,
|
|
661
|
-
urlMaskLevels: (_t = (_s = (_r = this.config.privacyConfig) === null || _r === void 0 ? void 0 : _r.urlMaskLevels) === null || _s === void 0 ? void 0 : _s.length) !== null && _t !== void 0 ? _t : 0,
|
|
662
|
-
// config always defaults this to a boolean (see local-config), so no `?? false` needed here.
|
|
663
|
-
enableUrlChangePolling: this.config.enableUrlChangePolling,
|
|
664
|
-
urlChangePollingInterval: this.config.urlChangePollingInterval,
|
|
665
|
-
});
|
|
666
|
-
this.loggerProvider.debug("URL-change listener needed: ".concat(String(!!needsUrlTracking), "."));
|
|
501
|
+
_v.sent();
|
|
502
|
+
needsUrlTracking = this.config.targetingConfig || ((_p = (_o = (_m = this.config.privacyConfig) === null || _m === void 0 ? void 0 : _m.urlMaskLevels) === null || _o === void 0 ? void 0 : _o.length) !== null && _p !== void 0 ? _p : 0) > 0;
|
|
667
503
|
if (needsUrlTracking) {
|
|
668
504
|
this.setupUrlChangeListener();
|
|
669
505
|
}
|
|
@@ -703,18 +539,6 @@ var SessionReplay = /** @class */ (function () {
|
|
|
703
539
|
this.sendEvents(previousSessionId);
|
|
704
540
|
}
|
|
705
541
|
isSessionChange = previousSessionId !== sessionId;
|
|
706
|
-
// A real session transition (not the first set): recording stops/restarts and targeting is
|
|
707
|
-
// re-evaluated here, so session churn (timeout, multi-tab custom ids, explicit setSessionId)
|
|
708
|
-
// is a prime suspect for "sometimes records, sometimes not". recordDiagnosticEvent ships to
|
|
709
|
-
// DataDog AND mirrors to loggerProvider.debug. New tabs / refreshes keep the same id and won't
|
|
710
|
-
// hit this — use the init diagnostic's navigationType for those.
|
|
711
|
-
if (isSessionChange && previousSessionId !== undefined) {
|
|
712
|
-
this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.sessionChanged, {
|
|
713
|
-
from: previousSessionId,
|
|
714
|
-
to: sessionId,
|
|
715
|
-
deviceIdChanged: deviceId !== undefined && deviceId !== currentDeviceId,
|
|
716
|
-
});
|
|
717
|
-
}
|
|
718
542
|
// Drop any beacon-buffered events from the previous session BEFORE installing the
|
|
719
543
|
// new identifiers / start time. Otherwise the page-leave beacon path could attribute
|
|
720
544
|
// old-session events to the new session id, and the gate (using the new start time)
|
|
@@ -811,9 +635,6 @@ var SessionReplay = /** @class */ (function () {
|
|
|
811
635
|
// Cross-session leak is prevented in asyncSetSessionId, which drops the buffer
|
|
812
636
|
// at the session transition. The page-leave path also gates independently.
|
|
813
637
|
this.suppressedSendCount++;
|
|
814
|
-
// gap #1: recording but events held back by min_session_duration — another "recording yet
|
|
815
|
-
// no replay in Amplitude" cause.
|
|
816
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.sendSuppressedMinDuration);
|
|
817
638
|
return;
|
|
818
639
|
}
|
|
819
640
|
// On the first send-after-pass for the session, emit a custom rrweb event so the
|
|
@@ -870,120 +691,17 @@ var SessionReplay = /** @class */ (function () {
|
|
|
870
691
|
}
|
|
871
692
|
return identityStoreOptOut !== undefined ? identityStoreOptOut : (_b = this.config) === null || _b === void 0 ? void 0 : _b.optOut;
|
|
872
693
|
};
|
|
873
|
-
/**
|
|
874
|
-
* Increment a diagnostics counter so the team can see the distribution of recording decisions
|
|
875
|
-
* across a customer's sessions (e.g. lots of sr.gate.trc_no_match => rule isn't matching).
|
|
876
|
-
* Ships via the analytics SDK's DiagnosticsClient. No-op when there's no client or diagnostics
|
|
877
|
-
* isn't sampled in; never throws — diagnostics must never interfere with recording.
|
|
878
|
-
*/
|
|
879
|
-
SessionReplay.prototype.incrementDiagnostic = function (counter) {
|
|
880
|
-
var _a, _b;
|
|
881
|
-
try {
|
|
882
|
-
// Mirror to the console (Debug level) so the full set of diagnostics is visible in the
|
|
883
|
-
// browser, not only in DataDog — helps debugging when a customer can't share a repro env.
|
|
884
|
-
this.loggerProvider.debug("[SR diagnostics] ".concat(counter));
|
|
885
|
-
(_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.diagnosticsClient) === null || _b === void 0 ? void 0 : _b.increment(counter);
|
|
886
|
-
}
|
|
887
|
-
catch (_c) {
|
|
888
|
-
// swallow — diagnostics is best-effort
|
|
889
|
-
}
|
|
890
|
-
};
|
|
891
|
-
/**
|
|
892
|
-
* Record a diagnostics histogram value (min/max/avg/count in DataDog). Same best-effort, never-
|
|
893
|
-
* throws contract as incrementDiagnostic. Use for latencies/sizes, not per-call counts.
|
|
894
|
-
*/
|
|
895
|
-
SessionReplay.prototype.recordDiagnosticHistogram = function (name, value) {
|
|
896
|
-
var _a, _b;
|
|
897
|
-
try {
|
|
898
|
-
// Mirror to the console (Debug level) — see incrementDiagnostic.
|
|
899
|
-
this.loggerProvider.debug("[SR diagnostics] ".concat(name, "=").concat(value));
|
|
900
|
-
// The only caller runs inside evaluateTargetingAndCapture's `this.config` guard, so the
|
|
901
|
-
// `config == null` arm of this optional chain is unreachable here (kept as defensive parity
|
|
902
|
-
// with recordDiagnosticEvent). The diagnosticsClient-absent arm IS exercised by no-client tests.
|
|
903
|
-
/* istanbul ignore next */
|
|
904
|
-
(_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.diagnosticsClient) === null || _b === void 0 ? void 0 : _b.recordHistogram(name, value);
|
|
905
|
-
}
|
|
906
|
-
catch (_c) {
|
|
907
|
-
// swallow — diagnostics is best-effort
|
|
908
|
-
}
|
|
909
|
-
};
|
|
910
|
-
/**
|
|
911
|
-
* Record a diagnostics EVENT with properties. Events are forwarded to DataDog Logs, so the
|
|
912
|
-
* properties become queryable fields (e.g. @matched, @pageUrl). Use sparingly vs counters: the
|
|
913
|
-
* client caps in-memory events (~10 per save interval), so this is for context-rich signals at
|
|
914
|
-
* meaningful decision points, not per-call tallies. Best-effort, never throws.
|
|
915
|
-
*/
|
|
916
|
-
SessionReplay.prototype.recordDiagnosticEvent = function (name, properties) {
|
|
917
|
-
var _a, _b, _c, _d, _e, _f;
|
|
918
|
-
try {
|
|
919
|
-
var sessionId = (_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId;
|
|
920
|
-
var deviceId = this.getDeviceId();
|
|
921
|
-
// Always stamp sessionId, deviceId and srId so every diagnostics event (→ DataDog Logs) can
|
|
922
|
-
// be correlated to a single session/device — and to the actual replay, since the Session
|
|
923
|
-
// Replay ID is `${deviceId}/${sessionId}`. Caller props override if they pass their own.
|
|
924
|
-
var enriched = tslib_1.__assign({ sessionId: sessionId, deviceId: deviceId, srId: deviceId != null && sessionId != null ? "".concat(deviceId, "/").concat(sessionId) : undefined }, properties);
|
|
925
|
-
// Mirror to the console (Debug level) so the full event + props are visible in the browser,
|
|
926
|
-
// not only in DataDog — see incrementDiagnostic.
|
|
927
|
-
this.loggerProvider.debug("[SR diagnostics] ".concat(name, " ").concat(JSON.stringify(enriched)));
|
|
928
|
-
(_c = (_b = this.config) === null || _b === void 0 ? void 0 : _b.diagnosticsClient) === null || _c === void 0 ? void 0 : _c.recordEvent(name, enriched);
|
|
929
|
-
// Flush immediately so the event ships now rather than on the client's ~5-min timer (and so
|
|
930
|
-
// short sessions that never reach the timer aren't lost). NOTE: this sends one capture POST
|
|
931
|
-
// per event — higher request volume; revisit/gate before production.
|
|
932
|
-
void ((_f = (_e = (_d = this.config) === null || _d === void 0 ? void 0 : _d.diagnosticsClient) === null || _e === void 0 ? void 0 : _e._flush) === null || _f === void 0 ? void 0 : _f.call(_e));
|
|
933
|
-
}
|
|
934
|
-
catch (_g) {
|
|
935
|
-
// swallow — diagnostics is best-effort
|
|
936
|
-
}
|
|
937
|
-
};
|
|
938
|
-
/**
|
|
939
|
-
* Emit a single rich TRC decision snapshot per session to diagnostics — surfaced even when
|
|
940
|
-
* nothing records (the exact case customers can't reproduce locally).
|
|
941
|
-
*/
|
|
942
|
-
SessionReplay.prototype.recordTrcDecisionDiagnostic = function (shouldRecord) {
|
|
943
|
-
var _a, _b;
|
|
944
|
-
var config = this.config;
|
|
945
|
-
// Every caller is past getShouldRecord's `!this.identifiers`/`!this.config` guard, so both are
|
|
946
|
-
// defined here; the `?.` arms below are unreachable defensive narrowing and excluded from
|
|
947
|
-
// coverage. The reachable guards (no diagnosticsClient, undefined/duplicate sessionId) are tested.
|
|
948
|
-
/* istanbul ignore next */
|
|
949
|
-
if (!config) {
|
|
950
|
-
return;
|
|
951
|
-
}
|
|
952
|
-
/* istanbul ignore next */
|
|
953
|
-
var sessionId = (_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId;
|
|
954
|
-
// Once past this guard, config.diagnosticsClient is truthy, so the fields below read config
|
|
955
|
-
// directly rather than re-asserting with `?.` on every access.
|
|
956
|
-
if (!config.diagnosticsClient || sessionId === undefined || sessionId === this.trcDiagnosticSessionId) {
|
|
957
|
-
return;
|
|
958
|
-
}
|
|
959
|
-
this.trcDiagnosticSessionId = sessionId;
|
|
960
|
-
// Goes through recordDiagnosticEvent so it carries sessionId + deviceId like every other event.
|
|
961
|
-
this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.decision, {
|
|
962
|
-
shouldRecord: shouldRecord,
|
|
963
|
-
captureEnabled: config.captureEnabled,
|
|
964
|
-
hasTargetingConfig: !!config.targetingConfig,
|
|
965
|
-
sessionTargetingMatch: this.sessionTargetingMatch,
|
|
966
|
-
sampleRate: config.sampleRate,
|
|
967
|
-
pageUrl: (_b = this.getCurrentPageForTargeting()) === null || _b === void 0 ? void 0 : _b.url,
|
|
968
|
-
sdkVersion: version_1.VERSION,
|
|
969
|
-
});
|
|
970
|
-
};
|
|
971
694
|
SessionReplay.prototype.getShouldRecord = function () {
|
|
972
695
|
if (!this.identifiers || !this.config || !this.identifiers.sessionId) {
|
|
973
696
|
this.loggerProvider.warn("Session is not being recorded due to lack of config, please call sessionReplay.init.");
|
|
974
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.gateNoIdentifiers);
|
|
975
697
|
return false;
|
|
976
698
|
}
|
|
977
699
|
if (!this.config.captureEnabled) {
|
|
978
700
|
this.loggerProvider.log("Session ".concat(this.identifiers.sessionId, " not being captured due to capture being disabled for project or because the remote config could not be fetched."));
|
|
979
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.gateCaptureDisabled);
|
|
980
|
-
this.recordTrcDecisionDiagnostic(false);
|
|
981
701
|
return false;
|
|
982
702
|
}
|
|
983
703
|
if (this.shouldOptOut()) {
|
|
984
704
|
this.loggerProvider.log("Opting session ".concat(this.identifiers.sessionId, " out of recording due to optOut config."));
|
|
985
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.gateOptOut);
|
|
986
|
-
this.recordTrcDecisionDiagnostic(false);
|
|
987
705
|
return false;
|
|
988
706
|
}
|
|
989
707
|
var shouldRecord = false;
|
|
@@ -997,14 +715,12 @@ var SessionReplay = /** @class */ (function () {
|
|
|
997
715
|
this.loggerProvider.log(message);
|
|
998
716
|
shouldRecord = false;
|
|
999
717
|
matched = false;
|
|
1000
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.gateTrcNoMatch);
|
|
1001
718
|
}
|
|
1002
719
|
else {
|
|
1003
720
|
message = "Capturing replays for session ".concat(this.identifiers.sessionId, " due to matching targeting conditions.");
|
|
1004
721
|
this.loggerProvider.log(message);
|
|
1005
722
|
shouldRecord = true;
|
|
1006
723
|
matched = true;
|
|
1007
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.gateTrcMatch);
|
|
1008
724
|
}
|
|
1009
725
|
}
|
|
1010
726
|
else {
|
|
@@ -1014,12 +730,10 @@ var SessionReplay = /** @class */ (function () {
|
|
|
1014
730
|
this.loggerProvider.log(message);
|
|
1015
731
|
shouldRecord = false;
|
|
1016
732
|
matched = false;
|
|
1017
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.gateSampleOut);
|
|
1018
733
|
}
|
|
1019
734
|
else {
|
|
1020
735
|
shouldRecord = true;
|
|
1021
736
|
matched = true;
|
|
1022
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.gateSampleIn);
|
|
1023
737
|
}
|
|
1024
738
|
}
|
|
1025
739
|
// Only send custom rrweb event for targeting decision when the decision changes
|
|
@@ -1032,7 +746,6 @@ var SessionReplay = /** @class */ (function () {
|
|
|
1032
746
|
});
|
|
1033
747
|
this.lastShouldRecordDecision = shouldRecord;
|
|
1034
748
|
}
|
|
1035
|
-
this.recordTrcDecisionDiagnostic(shouldRecord);
|
|
1036
749
|
return shouldRecord;
|
|
1037
750
|
};
|
|
1038
751
|
SessionReplay.prototype.getBlockSelectors = function () {
|
|
@@ -1197,9 +910,6 @@ var SessionReplay = /** @class */ (function () {
|
|
|
1197
910
|
recordFunction = _o.sent();
|
|
1198
911
|
// May be undefined if cannot import rrweb-record
|
|
1199
912
|
if (!recordFunction) {
|
|
1200
|
-
// gap #1: gate said record, but rrweb couldn't load → no replay despite shouldRecord=true.
|
|
1201
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.recordNoRecordFn);
|
|
1202
|
-
this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.recordNoRecordFn, {});
|
|
1203
913
|
return [2 /*return*/];
|
|
1204
914
|
}
|
|
1205
915
|
return [4 /*yield*/, this.initializeNetworkObservers()];
|
|
@@ -1230,11 +940,6 @@ var SessionReplay = /** @class */ (function () {
|
|
|
1230
940
|
: {};
|
|
1231
941
|
ugcFilterRules = (interactionConfig === null || interactionConfig === void 0 ? void 0 : interactionConfig.enabled) && interactionConfig.ugcFilterRules ? interactionConfig.ugcFilterRules : [];
|
|
1232
942
|
this.loggerProvider.log("Session Replay capture beginning for ".concat(sessionId, "."));
|
|
1233
|
-
// gap #1: rrweb is actually starting. Closes the "gate said yes but no replay" blind spot,
|
|
1234
|
-
// and its srId is the id the replay uploads under (compare with analytics events to catch the
|
|
1235
|
-
// device-id mismatch that breaks stitching).
|
|
1236
|
-
this.incrementDiagnostic(diagnostics_1.SrDiagnostic.recordStarted);
|
|
1237
|
-
this.recordDiagnosticEvent(diagnostics_1.SrDiagnostic.recordStarted, {});
|
|
1238
943
|
_o.label = 3;
|
|
1239
944
|
case 3:
|
|
1240
945
|
_o.trys.push([3, 5, , 6]);
|