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