@amplitude/session-replay-browser 1.47.0-sr-trc-debug-log.4 → 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 -339
- 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 -339
- 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,42 +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
|
-
// sdkVersion is the session-replay-browser version; `version` carries the integration
|
|
648
|
-
// (`{ type: 'plugin'|'standalone', version }`) so DataDog shows the actual plugin version too.
|
|
649
|
-
sdkVersion: VERSION,
|
|
650
|
-
version: this.config.version,
|
|
651
|
-
});
|
|
652
496
|
return [4 /*yield*/, this.evaluateTargetingAndCapture({ userProperties: options.userProperties, page: this.getCurrentPageForTargeting() }, true)];
|
|
653
497
|
case 13:
|
|
654
|
-
|
|
655
|
-
needsUrlTracking = this.config.targetingConfig || ((
|
|
656
|
-
// Record whether we even attempt to wire up the URL-change listener, and the inputs behind that
|
|
657
|
-
// decision. If `needsUrlTracking` is false the listener is never attached, so SPA navigations are
|
|
658
|
-
// invisible to TRC — this is the first thing to check when "TRC is on but never re-evaluates".
|
|
659
|
-
this.recordDiagnosticEvent(SrDiagnostic.urlListenerSetup, {
|
|
660
|
-
needsUrlTracking: !!needsUrlTracking,
|
|
661
|
-
hasTargetingConfig: !!this.config.targetingConfig,
|
|
662
|
-
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,
|
|
663
|
-
// config always defaults this to a boolean (see local-config), so no `?? false` needed here.
|
|
664
|
-
enableUrlChangePolling: this.config.enableUrlChangePolling,
|
|
665
|
-
urlChangePollingInterval: this.config.urlChangePollingInterval,
|
|
666
|
-
});
|
|
667
|
-
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;
|
|
668
500
|
if (needsUrlTracking) {
|
|
669
501
|
this.setupUrlChangeListener();
|
|
670
502
|
}
|
|
@@ -704,18 +536,6 @@ var SessionReplay = /** @class */ (function () {
|
|
|
704
536
|
this.sendEvents(previousSessionId);
|
|
705
537
|
}
|
|
706
538
|
isSessionChange = previousSessionId !== sessionId;
|
|
707
|
-
// A real session transition (not the first set): recording stops/restarts and targeting is
|
|
708
|
-
// re-evaluated here, so session churn (timeout, multi-tab custom ids, explicit setSessionId)
|
|
709
|
-
// is a prime suspect for "sometimes records, sometimes not". recordDiagnosticEvent ships to
|
|
710
|
-
// DataDog AND mirrors to loggerProvider.debug. New tabs / refreshes keep the same id and won't
|
|
711
|
-
// hit this — use the init diagnostic's navigationType for those.
|
|
712
|
-
if (isSessionChange && previousSessionId !== undefined) {
|
|
713
|
-
this.recordDiagnosticEvent(SrDiagnostic.sessionChanged, {
|
|
714
|
-
from: previousSessionId,
|
|
715
|
-
to: sessionId,
|
|
716
|
-
deviceIdChanged: deviceId !== undefined && deviceId !== currentDeviceId,
|
|
717
|
-
});
|
|
718
|
-
}
|
|
719
539
|
// Drop any beacon-buffered events from the previous session BEFORE installing the
|
|
720
540
|
// new identifiers / start time. Otherwise the page-leave beacon path could attribute
|
|
721
541
|
// old-session events to the new session id, and the gate (using the new start time)
|
|
@@ -812,9 +632,6 @@ var SessionReplay = /** @class */ (function () {
|
|
|
812
632
|
// Cross-session leak is prevented in asyncSetSessionId, which drops the buffer
|
|
813
633
|
// at the session transition. The page-leave path also gates independently.
|
|
814
634
|
this.suppressedSendCount++;
|
|
815
|
-
// gap #1: recording but events held back by min_session_duration — another "recording yet
|
|
816
|
-
// no replay in Amplitude" cause.
|
|
817
|
-
this.incrementDiagnostic(SrDiagnostic.sendSuppressedMinDuration);
|
|
818
635
|
return;
|
|
819
636
|
}
|
|
820
637
|
// On the first send-after-pass for the session, emit a custom rrweb event so the
|
|
@@ -871,120 +688,17 @@ var SessionReplay = /** @class */ (function () {
|
|
|
871
688
|
}
|
|
872
689
|
return identityStoreOptOut !== undefined ? identityStoreOptOut : (_b = this.config) === null || _b === void 0 ? void 0 : _b.optOut;
|
|
873
690
|
};
|
|
874
|
-
/**
|
|
875
|
-
* Increment a diagnostics counter so the team can see the distribution of recording decisions
|
|
876
|
-
* across a customer's sessions (e.g. lots of sr.gate.trc_no_match => rule isn't matching).
|
|
877
|
-
* Ships via the analytics SDK's DiagnosticsClient. No-op when there's no client or diagnostics
|
|
878
|
-
* isn't sampled in; never throws — diagnostics must never interfere with recording.
|
|
879
|
-
*/
|
|
880
|
-
SessionReplay.prototype.incrementDiagnostic = function (counter) {
|
|
881
|
-
var _a, _b;
|
|
882
|
-
try {
|
|
883
|
-
// Mirror to the console (Debug level) so the full set of diagnostics is visible in the
|
|
884
|
-
// browser, not only in DataDog — helps debugging when a customer can't share a repro env.
|
|
885
|
-
this.loggerProvider.debug("[SR diagnostics] ".concat(counter));
|
|
886
|
-
(_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.diagnosticsClient) === null || _b === void 0 ? void 0 : _b.increment(counter);
|
|
887
|
-
}
|
|
888
|
-
catch (_c) {
|
|
889
|
-
// swallow — diagnostics is best-effort
|
|
890
|
-
}
|
|
891
|
-
};
|
|
892
|
-
/**
|
|
893
|
-
* Record a diagnostics histogram value (min/max/avg/count in DataDog). Same best-effort, never-
|
|
894
|
-
* throws contract as incrementDiagnostic. Use for latencies/sizes, not per-call counts.
|
|
895
|
-
*/
|
|
896
|
-
SessionReplay.prototype.recordDiagnosticHistogram = function (name, value) {
|
|
897
|
-
var _a, _b;
|
|
898
|
-
try {
|
|
899
|
-
// Mirror to the console (Debug level) — see incrementDiagnostic.
|
|
900
|
-
this.loggerProvider.debug("[SR diagnostics] ".concat(name, "=").concat(value));
|
|
901
|
-
// The only caller runs inside evaluateTargetingAndCapture's `this.config` guard, so the
|
|
902
|
-
// `config == null` arm of this optional chain is unreachable here (kept as defensive parity
|
|
903
|
-
// with recordDiagnosticEvent). The diagnosticsClient-absent arm IS exercised by no-client tests.
|
|
904
|
-
/* istanbul ignore next */
|
|
905
|
-
(_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.diagnosticsClient) === null || _b === void 0 ? void 0 : _b.recordHistogram(name, value);
|
|
906
|
-
}
|
|
907
|
-
catch (_c) {
|
|
908
|
-
// swallow — diagnostics is best-effort
|
|
909
|
-
}
|
|
910
|
-
};
|
|
911
|
-
/**
|
|
912
|
-
* Record a diagnostics EVENT with properties. Events are forwarded to DataDog Logs, so the
|
|
913
|
-
* properties become queryable fields (e.g. @matched, @pageUrl). Use sparingly vs counters: the
|
|
914
|
-
* client caps in-memory events (~10 per save interval), so this is for context-rich signals at
|
|
915
|
-
* meaningful decision points, not per-call tallies. Best-effort, never throws.
|
|
916
|
-
*/
|
|
917
|
-
SessionReplay.prototype.recordDiagnosticEvent = function (name, properties) {
|
|
918
|
-
var _a, _b, _c, _d, _e, _f;
|
|
919
|
-
try {
|
|
920
|
-
var sessionId = (_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId;
|
|
921
|
-
var deviceId = this.getDeviceId();
|
|
922
|
-
// Always stamp sessionId, deviceId and srId so every diagnostics event (→ DataDog Logs) can
|
|
923
|
-
// be correlated to a single session/device — and to the actual replay, since the Session
|
|
924
|
-
// Replay ID is `${deviceId}/${sessionId}`. Caller props override if they pass their own.
|
|
925
|
-
var enriched = __assign({ sessionId: sessionId, deviceId: deviceId, srId: deviceId != null && sessionId != null ? "".concat(deviceId, "/").concat(sessionId) : undefined }, properties);
|
|
926
|
-
// Mirror to the console (Debug level) so the full event + props are visible in the browser,
|
|
927
|
-
// not only in DataDog — see incrementDiagnostic.
|
|
928
|
-
this.loggerProvider.debug("[SR diagnostics] ".concat(name, " ").concat(JSON.stringify(enriched)));
|
|
929
|
-
(_c = (_b = this.config) === null || _b === void 0 ? void 0 : _b.diagnosticsClient) === null || _c === void 0 ? void 0 : _c.recordEvent(name, enriched);
|
|
930
|
-
// Flush immediately so the event ships now rather than on the client's ~5-min timer (and so
|
|
931
|
-
// short sessions that never reach the timer aren't lost). NOTE: this sends one capture POST
|
|
932
|
-
// per event — higher request volume; revisit/gate before production.
|
|
933
|
-
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));
|
|
934
|
-
}
|
|
935
|
-
catch (_g) {
|
|
936
|
-
// swallow — diagnostics is best-effort
|
|
937
|
-
}
|
|
938
|
-
};
|
|
939
|
-
/**
|
|
940
|
-
* Emit a single rich TRC decision snapshot per session to diagnostics — surfaced even when
|
|
941
|
-
* nothing records (the exact case customers can't reproduce locally).
|
|
942
|
-
*/
|
|
943
|
-
SessionReplay.prototype.recordTrcDecisionDiagnostic = function (shouldRecord) {
|
|
944
|
-
var _a, _b;
|
|
945
|
-
var config = this.config;
|
|
946
|
-
// Every caller is past getShouldRecord's `!this.identifiers`/`!this.config` guard, so both are
|
|
947
|
-
// defined here; the `?.` arms below are unreachable defensive narrowing and excluded from
|
|
948
|
-
// coverage. The reachable guards (no diagnosticsClient, undefined/duplicate sessionId) are tested.
|
|
949
|
-
/* istanbul ignore next */
|
|
950
|
-
if (!config) {
|
|
951
|
-
return;
|
|
952
|
-
}
|
|
953
|
-
/* istanbul ignore next */
|
|
954
|
-
var sessionId = (_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId;
|
|
955
|
-
// Once past this guard, config.diagnosticsClient is truthy, so the fields below read config
|
|
956
|
-
// directly rather than re-asserting with `?.` on every access.
|
|
957
|
-
if (!config.diagnosticsClient || sessionId === undefined || sessionId === this.trcDiagnosticSessionId) {
|
|
958
|
-
return;
|
|
959
|
-
}
|
|
960
|
-
this.trcDiagnosticSessionId = sessionId;
|
|
961
|
-
// Goes through recordDiagnosticEvent so it carries sessionId + deviceId like every other event.
|
|
962
|
-
this.recordDiagnosticEvent(SrDiagnostic.decision, {
|
|
963
|
-
shouldRecord: shouldRecord,
|
|
964
|
-
captureEnabled: config.captureEnabled,
|
|
965
|
-
hasTargetingConfig: !!config.targetingConfig,
|
|
966
|
-
sessionTargetingMatch: this.sessionTargetingMatch,
|
|
967
|
-
sampleRate: config.sampleRate,
|
|
968
|
-
pageUrl: (_b = this.getCurrentPageForTargeting()) === null || _b === void 0 ? void 0 : _b.url,
|
|
969
|
-
sdkVersion: VERSION,
|
|
970
|
-
});
|
|
971
|
-
};
|
|
972
691
|
SessionReplay.prototype.getShouldRecord = function () {
|
|
973
692
|
if (!this.identifiers || !this.config || !this.identifiers.sessionId) {
|
|
974
693
|
this.loggerProvider.warn("Session is not being recorded due to lack of config, please call sessionReplay.init.");
|
|
975
|
-
this.incrementDiagnostic(SrDiagnostic.gateNoIdentifiers);
|
|
976
694
|
return false;
|
|
977
695
|
}
|
|
978
696
|
if (!this.config.captureEnabled) {
|
|
979
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."));
|
|
980
|
-
this.incrementDiagnostic(SrDiagnostic.gateCaptureDisabled);
|
|
981
|
-
this.recordTrcDecisionDiagnostic(false);
|
|
982
698
|
return false;
|
|
983
699
|
}
|
|
984
700
|
if (this.shouldOptOut()) {
|
|
985
701
|
this.loggerProvider.log("Opting session ".concat(this.identifiers.sessionId, " out of recording due to optOut config."));
|
|
986
|
-
this.incrementDiagnostic(SrDiagnostic.gateOptOut);
|
|
987
|
-
this.recordTrcDecisionDiagnostic(false);
|
|
988
702
|
return false;
|
|
989
703
|
}
|
|
990
704
|
var shouldRecord = false;
|
|
@@ -998,14 +712,12 @@ var SessionReplay = /** @class */ (function () {
|
|
|
998
712
|
this.loggerProvider.log(message);
|
|
999
713
|
shouldRecord = false;
|
|
1000
714
|
matched = false;
|
|
1001
|
-
this.incrementDiagnostic(SrDiagnostic.gateTrcNoMatch);
|
|
1002
715
|
}
|
|
1003
716
|
else {
|
|
1004
717
|
message = "Capturing replays for session ".concat(this.identifiers.sessionId, " due to matching targeting conditions.");
|
|
1005
718
|
this.loggerProvider.log(message);
|
|
1006
719
|
shouldRecord = true;
|
|
1007
720
|
matched = true;
|
|
1008
|
-
this.incrementDiagnostic(SrDiagnostic.gateTrcMatch);
|
|
1009
721
|
}
|
|
1010
722
|
}
|
|
1011
723
|
else {
|
|
@@ -1015,12 +727,10 @@ var SessionReplay = /** @class */ (function () {
|
|
|
1015
727
|
this.loggerProvider.log(message);
|
|
1016
728
|
shouldRecord = false;
|
|
1017
729
|
matched = false;
|
|
1018
|
-
this.incrementDiagnostic(SrDiagnostic.gateSampleOut);
|
|
1019
730
|
}
|
|
1020
731
|
else {
|
|
1021
732
|
shouldRecord = true;
|
|
1022
733
|
matched = true;
|
|
1023
|
-
this.incrementDiagnostic(SrDiagnostic.gateSampleIn);
|
|
1024
734
|
}
|
|
1025
735
|
}
|
|
1026
736
|
// Only send custom rrweb event for targeting decision when the decision changes
|
|
@@ -1033,7 +743,6 @@ var SessionReplay = /** @class */ (function () {
|
|
|
1033
743
|
});
|
|
1034
744
|
this.lastShouldRecordDecision = shouldRecord;
|
|
1035
745
|
}
|
|
1036
|
-
this.recordTrcDecisionDiagnostic(shouldRecord);
|
|
1037
746
|
return shouldRecord;
|
|
1038
747
|
};
|
|
1039
748
|
SessionReplay.prototype.getBlockSelectors = function () {
|
|
@@ -1198,9 +907,6 @@ var SessionReplay = /** @class */ (function () {
|
|
|
1198
907
|
recordFunction = _o.sent();
|
|
1199
908
|
// May be undefined if cannot import rrweb-record
|
|
1200
909
|
if (!recordFunction) {
|
|
1201
|
-
// gap #1: gate said record, but rrweb couldn't load → no replay despite shouldRecord=true.
|
|
1202
|
-
this.incrementDiagnostic(SrDiagnostic.recordNoRecordFn);
|
|
1203
|
-
this.recordDiagnosticEvent(SrDiagnostic.recordNoRecordFn, {});
|
|
1204
910
|
return [2 /*return*/];
|
|
1205
911
|
}
|
|
1206
912
|
return [4 /*yield*/, this.initializeNetworkObservers()];
|
|
@@ -1231,11 +937,6 @@ var SessionReplay = /** @class */ (function () {
|
|
|
1231
937
|
: {};
|
|
1232
938
|
ugcFilterRules = (interactionConfig === null || interactionConfig === void 0 ? void 0 : interactionConfig.enabled) && interactionConfig.ugcFilterRules ? interactionConfig.ugcFilterRules : [];
|
|
1233
939
|
this.loggerProvider.log("Session Replay capture beginning for ".concat(sessionId, "."));
|
|
1234
|
-
// gap #1: rrweb is actually starting. Closes the "gate said yes but no replay" blind spot,
|
|
1235
|
-
// and its srId is the id the replay uploads under (compare with analytics events to catch the
|
|
1236
|
-
// device-id mismatch that breaks stitching).
|
|
1237
|
-
this.incrementDiagnostic(SrDiagnostic.recordStarted);
|
|
1238
|
-
this.recordDiagnosticEvent(SrDiagnostic.recordStarted, {});
|
|
1239
940
|
_o.label = 3;
|
|
1240
941
|
case 3:
|
|
1241
942
|
_o.trys.push([3, 5, , 6]);
|