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