@amplitude/session-replay-browser 1.2.1 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/config.d.ts +0 -3
- package/lib/cjs/config.d.ts.map +1 -1
- package/lib/cjs/config.js +0 -9
- package/lib/cjs/config.js.map +1 -1
- package/lib/cjs/events-manager.d.ts +49 -0
- package/lib/cjs/events-manager.d.ts.map +1 -0
- package/lib/cjs/events-manager.js +157 -0
- package/lib/cjs/events-manager.js.map +1 -0
- package/lib/cjs/identifiers.d.ts +9 -0
- package/lib/cjs/identifiers.d.ts.map +1 -0
- package/lib/cjs/identifiers.js +18 -0
- package/lib/cjs/identifiers.js.map +1 -0
- package/lib/cjs/session-idb-store.d.ts +15 -0
- package/lib/cjs/session-idb-store.d.ts.map +1 -0
- package/lib/cjs/session-idb-store.js +107 -0
- package/lib/cjs/session-idb-store.js.map +1 -0
- package/lib/cjs/session-replay.d.ts +5 -41
- package/lib/cjs/session-replay.d.ts.map +1 -1
- package/lib/cjs/session-replay.js +55 -406
- package/lib/cjs/session-replay.js.map +1 -1
- package/lib/cjs/track-destination.d.ts +27 -0
- package/lib/cjs/track-destination.d.ts.map +1 -0
- package/lib/cjs/track-destination.js +201 -0
- package/lib/cjs/track-destination.js.map +1 -0
- package/lib/cjs/typings/session-replay.d.ts +45 -7
- package/lib/cjs/typings/session-replay.d.ts.map +1 -1
- package/lib/cjs/typings/session-replay.js.map +1 -1
- package/lib/esm/config.d.ts +0 -3
- package/lib/esm/config.d.ts.map +1 -1
- package/lib/esm/config.js +0 -9
- package/lib/esm/config.js.map +1 -1
- package/lib/esm/events-manager.d.ts +49 -0
- package/lib/esm/events-manager.d.ts.map +1 -0
- package/lib/esm/events-manager.js +155 -0
- package/lib/esm/events-manager.js.map +1 -0
- package/lib/esm/identifiers.d.ts +9 -0
- package/lib/esm/identifiers.d.ts.map +1 -0
- package/lib/esm/identifiers.js +16 -0
- package/lib/esm/identifiers.js.map +1 -0
- package/lib/esm/session-idb-store.d.ts +15 -0
- package/lib/esm/session-idb-store.d.ts.map +1 -0
- package/lib/esm/session-idb-store.js +105 -0
- package/lib/esm/session-idb-store.js.map +1 -0
- package/lib/esm/session-replay.d.ts +5 -41
- package/lib/esm/session-replay.d.ts.map +1 -1
- package/lib/esm/session-replay.js +59 -410
- package/lib/esm/session-replay.js.map +1 -1
- package/lib/esm/track-destination.d.ts +27 -0
- package/lib/esm/track-destination.d.ts.map +1 -0
- package/lib/esm/track-destination.js +199 -0
- package/lib/esm/track-destination.js.map +1 -0
- package/lib/esm/typings/session-replay.d.ts +45 -7
- package/lib/esm/typings/session-replay.d.ts.map +1 -1
- package/lib/esm/typings/session-replay.js.map +1 -1
- package/lib/scripts/amplitude-min.js +1 -1
- package/lib/scripts/amplitude-min.js.gz +0 -0
- package/lib/scripts/amplitude-min.umd.js +1 -1
- package/lib/scripts/amplitude-min.umd.js.gz +0 -0
- package/lib/scripts/config.d.ts +0 -3
- package/lib/scripts/config.d.ts.map +1 -1
- package/lib/scripts/events-manager.d.ts +49 -0
- package/lib/scripts/events-manager.d.ts.map +1 -0
- package/lib/scripts/identifiers.d.ts +9 -0
- package/lib/scripts/identifiers.d.ts.map +1 -0
- package/lib/scripts/session-idb-store.d.ts +15 -0
- package/lib/scripts/session-idb-store.d.ts.map +1 -0
- package/lib/scripts/session-replay.d.ts +5 -41
- package/lib/scripts/session-replay.d.ts.map +1 -1
- package/lib/scripts/track-destination.d.ts +27 -0
- package/lib/scripts/track-destination.d.ts.map +1 -0
- package/lib/scripts/typings/session-replay.d.ts +45 -7
- package/lib/scripts/typings/session-replay.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -1,54 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __awaiter, __generator } from "tslib";
|
|
2
2
|
import { getAnalyticsConnector, getGlobalScope } from '@amplitude/analytics-client-common';
|
|
3
|
-
import {
|
|
4
|
-
import { ServerZone, Status } from '@amplitude/analytics-types';
|
|
3
|
+
import { Logger, returnWrapper } from '@amplitude/analytics-core';
|
|
5
4
|
import { pack, record } from '@amplitude/rrweb';
|
|
6
|
-
import * as IDBKeyVal from 'idb-keyval';
|
|
7
5
|
import { SessionReplayConfig } from './config';
|
|
8
|
-
import { BLOCK_CLASS,
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { VERSION } from './version';
|
|
6
|
+
import { BLOCK_CLASS, DEFAULT_SESSION_REPLAY_PROPERTY, MASK_TEXT_CLASS, SESSION_REPLAY_DEBUG_PROPERTY, } from './constants';
|
|
7
|
+
import { SessionReplayEventsManager } from './events-manager';
|
|
8
|
+
import { generateHashCode, generateSessionReplayId, isSessionInSample, maskInputFn } from './helpers';
|
|
9
|
+
import { SessionIdentifiers } from './identifiers';
|
|
13
10
|
var SessionReplay = /** @class */ (function () {
|
|
14
11
|
function SessionReplay() {
|
|
15
12
|
var _this = this;
|
|
16
13
|
this.name = '@amplitude/session-replay-browser';
|
|
17
|
-
this.storageKey = '';
|
|
18
|
-
this.retryTimeout = 1000;
|
|
19
|
-
this.events = [];
|
|
20
|
-
this.currentSequenceId = 0;
|
|
21
|
-
this.scheduled = null;
|
|
22
|
-
this.queue = [];
|
|
23
14
|
this.stopRecordingEvents = null;
|
|
24
|
-
this.maxPersistedEventsSize = MAX_EVENT_LIST_SIZE_IN_BYTES;
|
|
25
|
-
this.interval = MIN_INTERVAL;
|
|
26
|
-
this.timeAtLastSend = null;
|
|
27
15
|
this.blurListener = function () {
|
|
28
16
|
_this.stopRecordingAndSendEvents();
|
|
29
17
|
};
|
|
30
18
|
this.focusListener = function () {
|
|
31
19
|
void _this.initialize();
|
|
32
20
|
};
|
|
33
|
-
/**
|
|
34
|
-
* Determines whether to send the events list to the backend and start a new
|
|
35
|
-
* empty events list, based on the size of the list as well as the last time sent
|
|
36
|
-
* @param nextEventString
|
|
37
|
-
* @returns boolean
|
|
38
|
-
*/
|
|
39
|
-
this.shouldSplitEventsList = function (nextEventString) {
|
|
40
|
-
var sizeOfNextEvent = new Blob([nextEventString]).size;
|
|
41
|
-
var sizeOfEventsList = new Blob(_this.events).size;
|
|
42
|
-
if (sizeOfEventsList + sizeOfNextEvent >= _this.maxPersistedEventsSize) {
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
if (_this.timeAtLastSend !== null && Date.now() - _this.timeAtLastSend > _this.interval && _this.events.length) {
|
|
46
|
-
_this.interval = Math.min(MAX_INTERVAL, _this.interval + MIN_INTERVAL);
|
|
47
|
-
_this.timeAtLastSend = Date.now();
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
return false;
|
|
51
|
-
};
|
|
52
21
|
this.loggerProvider = new Logger();
|
|
53
22
|
}
|
|
54
23
|
SessionReplay.prototype.init = function (apiKey, options) {
|
|
@@ -62,8 +31,11 @@ var SessionReplay = /** @class */ (function () {
|
|
|
62
31
|
case 0:
|
|
63
32
|
this.config = new SessionReplayConfig(apiKey, options);
|
|
64
33
|
this.loggerProvider = this.config.loggerProvider;
|
|
34
|
+
this.identifiers = new SessionIdentifiers(options, this.loggerProvider);
|
|
35
|
+
this.eventsManager = new SessionReplayEventsManager({
|
|
36
|
+
config: this.config,
|
|
37
|
+
});
|
|
65
38
|
this.loggerProvider.log('Installing @amplitude/session-replay-browser.');
|
|
66
|
-
this.storageKey = "".concat(STORAGE_PREFIX, "_").concat(this.config.apiKey.substring(0, 10));
|
|
67
39
|
globalScope = getGlobalScope();
|
|
68
40
|
if (globalScope) {
|
|
69
41
|
globalScope.addEventListener('blur', this.blurListener);
|
|
@@ -80,26 +52,25 @@ var SessionReplay = /** @class */ (function () {
|
|
|
80
52
|
});
|
|
81
53
|
};
|
|
82
54
|
SessionReplay.prototype.setSessionId = function (sessionId, deviceId) {
|
|
83
|
-
if (!this.
|
|
55
|
+
if (!this.identifiers) {
|
|
84
56
|
this.loggerProvider.error('Session replay init has not been called, cannot set session id.');
|
|
85
57
|
return;
|
|
86
58
|
}
|
|
87
59
|
if (deviceId) {
|
|
88
|
-
this.
|
|
60
|
+
this.identifiers.deviceId = deviceId;
|
|
89
61
|
}
|
|
90
62
|
// use a consistent device id.
|
|
91
63
|
var deviceIdForReplayId = this.getDeviceId();
|
|
92
64
|
if (sessionId && deviceIdForReplayId) {
|
|
93
|
-
this.
|
|
65
|
+
this.identifiers.sessionReplayId = generateSessionReplayId(sessionId, deviceIdForReplayId);
|
|
94
66
|
}
|
|
95
67
|
else {
|
|
96
68
|
this.loggerProvider.error('Must provide either session replay id or session id when starting a new session.');
|
|
97
69
|
return;
|
|
98
70
|
}
|
|
99
|
-
this.stopRecordingAndSendEvents(this.
|
|
100
|
-
this.
|
|
101
|
-
this.
|
|
102
|
-
this.currentSequenceId = 0;
|
|
71
|
+
this.stopRecordingAndSendEvents(this.identifiers.sessionId);
|
|
72
|
+
this.identifiers.sessionId = sessionId;
|
|
73
|
+
this.eventsManager && this.eventsManager.resetSequence();
|
|
103
74
|
this.recordEvents();
|
|
104
75
|
};
|
|
105
76
|
SessionReplay.prototype.getSessionReplayDebugPropertyValue = function () {
|
|
@@ -113,7 +84,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
113
84
|
};
|
|
114
85
|
SessionReplay.prototype.getSessionReplayProperties = function () {
|
|
115
86
|
var _a;
|
|
116
|
-
if (!this.config) {
|
|
87
|
+
if (!this.config || !this.identifiers) {
|
|
117
88
|
this.loggerProvider.error('Session replay init has not been called, cannot get session recording properties.');
|
|
118
89
|
return {};
|
|
119
90
|
}
|
|
@@ -123,7 +94,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
123
94
|
var shouldRecord = this.getShouldRecord(ignoreFocus);
|
|
124
95
|
if (shouldRecord) {
|
|
125
96
|
var eventProperties = (_a = {},
|
|
126
|
-
_a[DEFAULT_SESSION_REPLAY_PROPERTY] = this.
|
|
97
|
+
_a[DEFAULT_SESSION_REPLAY_PROPERTY] = this.identifiers.sessionReplayId ? this.identifiers.sessionReplayId : null,
|
|
127
98
|
_a);
|
|
128
99
|
if (this.config.debugMode) {
|
|
129
100
|
eventProperties[SESSION_REPLAY_DEBUG_PROPERTY] = this.getSessionReplayDebugPropertyValue();
|
|
@@ -142,54 +113,39 @@ var SessionReplay = /** @class */ (function () {
|
|
|
142
113
|
var typedError = error;
|
|
143
114
|
this.loggerProvider.warn("Error occurred while stopping recording: ".concat(typedError.toString()));
|
|
144
115
|
}
|
|
145
|
-
var sessionIdToSend = sessionId || ((_a = this.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
});
|
|
152
|
-
}
|
|
116
|
+
var sessionIdToSend = sessionId || ((_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId);
|
|
117
|
+
var deviceId = this.getDeviceId();
|
|
118
|
+
this.eventsManager &&
|
|
119
|
+
sessionIdToSend &&
|
|
120
|
+
deviceId &&
|
|
121
|
+
this.eventsManager.sendEvents({ sessionId: sessionIdToSend, deviceId: deviceId });
|
|
153
122
|
};
|
|
154
123
|
SessionReplay.prototype.initialize = function (shouldSendStoredEvents) {
|
|
155
124
|
var _a;
|
|
156
125
|
if (shouldSendStoredEvents === void 0) { shouldSendStoredEvents = false; }
|
|
157
126
|
return __awaiter(this, void 0, void 0, function () {
|
|
158
|
-
var
|
|
159
|
-
return __generator(this, function (
|
|
160
|
-
switch (
|
|
127
|
+
var deviceId, _b;
|
|
128
|
+
return __generator(this, function (_c) {
|
|
129
|
+
switch (_c.label) {
|
|
161
130
|
case 0:
|
|
162
|
-
|
|
163
|
-
if (!((_a = this.config) === null || _a === void 0 ? void 0 : _a.sessionId)) {
|
|
131
|
+
if (!((_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId)) {
|
|
164
132
|
this.loggerProvider.warn("Session is not being recorded due to lack of session id.");
|
|
165
133
|
return [2 /*return*/];
|
|
166
134
|
}
|
|
167
|
-
|
|
135
|
+
deviceId = this.getDeviceId();
|
|
136
|
+
_b = this.eventsManager &&
|
|
137
|
+
deviceId;
|
|
138
|
+
if (!_b) return [3 /*break*/, 2];
|
|
139
|
+
return [4 /*yield*/, this.eventsManager.initialize({
|
|
140
|
+
sessionId: this.identifiers.sessionId,
|
|
141
|
+
shouldSendStoredEvents: shouldSendStoredEvents,
|
|
142
|
+
deviceId: deviceId,
|
|
143
|
+
})];
|
|
168
144
|
case 1:
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (this.stopRecordingEvents) {
|
|
174
|
-
return [2 /*return*/];
|
|
175
|
-
}
|
|
176
|
-
storedSequencesForSession = storedReplaySessions && storedReplaySessions[this.config.sessionId];
|
|
177
|
-
if (storedReplaySessions && storedSequencesForSession && storedSequencesForSession.sessionSequences) {
|
|
178
|
-
storedSeqId = storedSequencesForSession.currentSequenceId;
|
|
179
|
-
lastSequence = storedSequencesForSession.sessionSequences[storedSeqId];
|
|
180
|
-
if (lastSequence && lastSequence.status !== RecordingStatus.RECORDING) {
|
|
181
|
-
this.currentSequenceId = storedSeqId + 1;
|
|
182
|
-
this.events = [];
|
|
183
|
-
}
|
|
184
|
-
else {
|
|
185
|
-
// Pick up recording where it was left off in another tab or window
|
|
186
|
-
this.currentSequenceId = storedSeqId;
|
|
187
|
-
this.events = (lastSequence === null || lastSequence === void 0 ? void 0 : lastSequence.events) || [];
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
if (shouldSendStoredEvents && storedReplaySessions) {
|
|
191
|
-
this.sendStoredEvents(storedReplaySessions);
|
|
192
|
-
}
|
|
145
|
+
_b = (_c.sent());
|
|
146
|
+
_c.label = 2;
|
|
147
|
+
case 2:
|
|
148
|
+
_b;
|
|
193
149
|
this.recordEvents();
|
|
194
150
|
return [2 /*return*/];
|
|
195
151
|
}
|
|
@@ -207,30 +163,30 @@ var SessionReplay = /** @class */ (function () {
|
|
|
207
163
|
};
|
|
208
164
|
SessionReplay.prototype.getShouldRecord = function (ignoreFocus) {
|
|
209
165
|
if (ignoreFocus === void 0) { ignoreFocus = false; }
|
|
210
|
-
if (!this.config) {
|
|
166
|
+
if (!this.identifiers || !this.config) {
|
|
211
167
|
this.loggerProvider.error("Session is not being recorded due to lack of config, please call sessionReplay.init.");
|
|
212
168
|
return false;
|
|
213
169
|
}
|
|
214
170
|
var globalScope = getGlobalScope();
|
|
215
171
|
if (!ignoreFocus && globalScope && globalScope.document && !globalScope.document.hasFocus()) {
|
|
216
|
-
if (this.
|
|
217
|
-
this.loggerProvider.log("Session ".concat(this.
|
|
172
|
+
if (this.identifiers.sessionId) {
|
|
173
|
+
this.loggerProvider.log("Session ".concat(this.identifiers.sessionId, " temporarily not recording due to lack of browser focus."));
|
|
218
174
|
}
|
|
219
175
|
return false;
|
|
220
176
|
}
|
|
221
177
|
else if (this.shouldOptOut()) {
|
|
222
|
-
if (this.
|
|
223
|
-
this.loggerProvider.log("Opting session ".concat(this.
|
|
178
|
+
if (this.identifiers.sessionId) {
|
|
179
|
+
this.loggerProvider.log("Opting session ".concat(this.identifiers.sessionId, " out of recording due to optOut config."));
|
|
224
180
|
}
|
|
225
181
|
return false;
|
|
226
182
|
}
|
|
227
|
-
else if (!this.
|
|
183
|
+
else if (!this.identifiers.sessionId) {
|
|
228
184
|
this.loggerProvider.warn("Session is not being recorded due to lack of session id.");
|
|
229
185
|
return false;
|
|
230
186
|
}
|
|
231
|
-
var isInSample = isSessionInSample(this.
|
|
187
|
+
var isInSample = isSessionInSample(this.identifiers.sessionId, this.config.sampleRate);
|
|
232
188
|
if (!isInSample) {
|
|
233
|
-
this.loggerProvider.log("Opting session ".concat(this.
|
|
189
|
+
this.loggerProvider.log("Opting session ".concat(this.identifiers.sessionId, " out of recording due to sample rate."));
|
|
234
190
|
}
|
|
235
191
|
return isInSample;
|
|
236
192
|
};
|
|
@@ -238,32 +194,11 @@ var SessionReplay = /** @class */ (function () {
|
|
|
238
194
|
var _a, _b;
|
|
239
195
|
return (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.privacyConfig) === null || _b === void 0 ? void 0 : _b.blockSelector;
|
|
240
196
|
};
|
|
241
|
-
SessionReplay.prototype.sendStoredEvents = function (storedReplaySessions) {
|
|
242
|
-
var _a;
|
|
243
|
-
for (var sessionId in storedReplaySessions) {
|
|
244
|
-
var storedSequences = storedReplaySessions[sessionId].sessionSequences;
|
|
245
|
-
for (var storedSeqId in storedSequences) {
|
|
246
|
-
var seq = storedSequences[storedSeqId];
|
|
247
|
-
var numericSeqId = parseInt(storedSeqId, 10);
|
|
248
|
-
var numericSessionId = parseInt(sessionId, 10);
|
|
249
|
-
if (numericSessionId === ((_a = this.config) === null || _a === void 0 ? void 0 : _a.sessionId) && numericSeqId === this.currentSequenceId) {
|
|
250
|
-
continue;
|
|
251
|
-
}
|
|
252
|
-
if (seq.events && seq.events.length && seq.status === RecordingStatus.RECORDING) {
|
|
253
|
-
this.sendEventsList({
|
|
254
|
-
events: seq.events,
|
|
255
|
-
sequenceId: numericSeqId,
|
|
256
|
-
sessionId: numericSessionId,
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
197
|
SessionReplay.prototype.recordEvents = function () {
|
|
263
198
|
var _this = this;
|
|
264
199
|
var _a;
|
|
265
200
|
var shouldRecord = this.getShouldRecord();
|
|
266
|
-
var sessionId = (_a = this.
|
|
201
|
+
var sessionId = (_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId;
|
|
267
202
|
if (!shouldRecord || !sessionId) {
|
|
268
203
|
return;
|
|
269
204
|
}
|
|
@@ -275,18 +210,8 @@ var SessionReplay = /** @class */ (function () {
|
|
|
275
210
|
return;
|
|
276
211
|
}
|
|
277
212
|
var eventString = JSON.stringify(event);
|
|
278
|
-
var
|
|
279
|
-
|
|
280
|
-
_this.sendEventsList({
|
|
281
|
-
events: _this.events,
|
|
282
|
-
sequenceId: _this.currentSequenceId,
|
|
283
|
-
sessionId: sessionId,
|
|
284
|
-
});
|
|
285
|
-
_this.events = [];
|
|
286
|
-
_this.currentSequenceId++;
|
|
287
|
-
}
|
|
288
|
-
_this.events.push(eventString);
|
|
289
|
-
void _this.storeEventsForSession(_this.events, _this.currentSequenceId, sessionId);
|
|
213
|
+
var deviceId = _this.getDeviceId();
|
|
214
|
+
deviceId && _this.eventsManager && _this.eventsManager.addEvent({ event: eventString, sessionId: sessionId, deviceId: deviceId });
|
|
290
215
|
},
|
|
291
216
|
packFn: pack,
|
|
292
217
|
maskAllInputs: true,
|
|
@@ -303,96 +228,6 @@ var SessionReplay = /** @class */ (function () {
|
|
|
303
228
|
},
|
|
304
229
|
});
|
|
305
230
|
};
|
|
306
|
-
SessionReplay.prototype.sendEventsList = function (_a) {
|
|
307
|
-
var events = _a.events, sequenceId = _a.sequenceId, sessionId = _a.sessionId;
|
|
308
|
-
this.addToQueue({
|
|
309
|
-
events: events,
|
|
310
|
-
sequenceId: sequenceId,
|
|
311
|
-
attempts: 0,
|
|
312
|
-
timeout: 0,
|
|
313
|
-
sessionId: sessionId,
|
|
314
|
-
});
|
|
315
|
-
};
|
|
316
|
-
SessionReplay.prototype.addToQueue = function () {
|
|
317
|
-
var _this = this;
|
|
318
|
-
var list = [];
|
|
319
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
320
|
-
list[_i] = arguments[_i];
|
|
321
|
-
}
|
|
322
|
-
var tryable = list.filter(function (context) {
|
|
323
|
-
var _a;
|
|
324
|
-
if (context.attempts < (((_a = _this.config) === null || _a === void 0 ? void 0 : _a.flushMaxRetries) || 0)) {
|
|
325
|
-
context.attempts += 1;
|
|
326
|
-
return true;
|
|
327
|
-
}
|
|
328
|
-
_this.completeRequest({
|
|
329
|
-
context: context,
|
|
330
|
-
err: "".concat(MAX_RETRIES_EXCEEDED_MESSAGE, ", batch sequence id, ").concat(context.sequenceId),
|
|
331
|
-
});
|
|
332
|
-
return false;
|
|
333
|
-
});
|
|
334
|
-
tryable.forEach(function (context) {
|
|
335
|
-
_this.queue = _this.queue.concat(context);
|
|
336
|
-
if (context.timeout === 0) {
|
|
337
|
-
_this.schedule(0);
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
setTimeout(function () {
|
|
341
|
-
context.timeout = 0;
|
|
342
|
-
_this.schedule(0);
|
|
343
|
-
}, context.timeout);
|
|
344
|
-
});
|
|
345
|
-
};
|
|
346
|
-
SessionReplay.prototype.schedule = function (timeout) {
|
|
347
|
-
var _this = this;
|
|
348
|
-
if (this.scheduled)
|
|
349
|
-
return;
|
|
350
|
-
this.scheduled = setTimeout(function () {
|
|
351
|
-
void _this.flush(true).then(function () {
|
|
352
|
-
if (_this.queue.length > 0) {
|
|
353
|
-
_this.schedule(timeout);
|
|
354
|
-
}
|
|
355
|
-
});
|
|
356
|
-
}, timeout);
|
|
357
|
-
};
|
|
358
|
-
SessionReplay.prototype.flush = function (useRetry) {
|
|
359
|
-
if (useRetry === void 0) { useRetry = false; }
|
|
360
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
361
|
-
var list, later;
|
|
362
|
-
var _this = this;
|
|
363
|
-
return __generator(this, function (_a) {
|
|
364
|
-
switch (_a.label) {
|
|
365
|
-
case 0:
|
|
366
|
-
list = [];
|
|
367
|
-
later = [];
|
|
368
|
-
this.queue.forEach(function (context) { return (context.timeout === 0 ? list.push(context) : later.push(context)); });
|
|
369
|
-
this.queue = later;
|
|
370
|
-
if (this.scheduled) {
|
|
371
|
-
clearTimeout(this.scheduled);
|
|
372
|
-
this.scheduled = null;
|
|
373
|
-
}
|
|
374
|
-
return [4 /*yield*/, Promise.all(list.map(function (context) { return _this.send(context, useRetry); }))];
|
|
375
|
-
case 1:
|
|
376
|
-
_a.sent();
|
|
377
|
-
return [2 /*return*/];
|
|
378
|
-
}
|
|
379
|
-
});
|
|
380
|
-
});
|
|
381
|
-
};
|
|
382
|
-
SessionReplay.prototype.getSampleRate = function () {
|
|
383
|
-
var _a;
|
|
384
|
-
return ((_a = this.config) === null || _a === void 0 ? void 0 : _a.sampleRate) || DEFAULT_SAMPLE_RATE;
|
|
385
|
-
};
|
|
386
|
-
SessionReplay.prototype.getServerUrl = function () {
|
|
387
|
-
var _a, _b;
|
|
388
|
-
if (((_a = this.config) === null || _a === void 0 ? void 0 : _a.serverZone) === ServerZone.STAGING) {
|
|
389
|
-
return SESSION_REPLAY_STAGING_SERVER_URL;
|
|
390
|
-
}
|
|
391
|
-
if (((_b = this.config) === null || _b === void 0 ? void 0 : _b.serverZone) === ServerZone.EU) {
|
|
392
|
-
return SESSION_REPLAY_EU_SERVER_URL;
|
|
393
|
-
}
|
|
394
|
-
return SESSION_REPLAY_SERVER_URL;
|
|
395
|
-
};
|
|
396
231
|
SessionReplay.prototype.getDeviceId = function () {
|
|
397
232
|
var _a, _b;
|
|
398
233
|
var identityStoreDeviceId;
|
|
@@ -400,209 +235,23 @@ var SessionReplay = /** @class */ (function () {
|
|
|
400
235
|
var identityStore = getAnalyticsConnector(this.config.instanceName).identityStore;
|
|
401
236
|
identityStoreDeviceId = identityStore.getIdentity().deviceId;
|
|
402
237
|
}
|
|
403
|
-
return identityStoreDeviceId || ((_b = this.
|
|
238
|
+
return identityStoreDeviceId || ((_b = this.identifiers) === null || _b === void 0 ? void 0 : _b.deviceId);
|
|
404
239
|
};
|
|
405
240
|
SessionReplay.prototype.getSessionId = function () {
|
|
406
241
|
var _a;
|
|
407
|
-
return (_a = this.
|
|
242
|
+
return (_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId;
|
|
408
243
|
};
|
|
409
|
-
SessionReplay.prototype.
|
|
410
|
-
|
|
411
|
-
if (useRetry === void 0) { useRetry = true; }
|
|
412
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
413
|
-
var apiKey, deviceId, url, version, sampleRate, urlParams, payload, options, server_url, res, responseBody, e_1;
|
|
414
|
-
return __generator(this, function (_b) {
|
|
415
|
-
switch (_b.label) {
|
|
416
|
-
case 0:
|
|
417
|
-
apiKey = (_a = this.config) === null || _a === void 0 ? void 0 : _a.apiKey;
|
|
418
|
-
if (!apiKey) {
|
|
419
|
-
return [2 /*return*/, this.completeRequest({ context: context, err: MISSING_API_KEY_MESSAGE })];
|
|
420
|
-
}
|
|
421
|
-
deviceId = this.getDeviceId();
|
|
422
|
-
if (!deviceId) {
|
|
423
|
-
return [2 /*return*/, this.completeRequest({ context: context, err: MISSING_DEVICE_ID_MESSAGE })];
|
|
424
|
-
}
|
|
425
|
-
url = getCurrentUrl();
|
|
426
|
-
version = VERSION;
|
|
427
|
-
sampleRate = this.getSampleRate();
|
|
428
|
-
urlParams = new URLSearchParams({
|
|
429
|
-
device_id: deviceId,
|
|
430
|
-
session_id: "".concat(context.sessionId),
|
|
431
|
-
seq_number: "".concat(context.sequenceId),
|
|
432
|
-
});
|
|
433
|
-
payload = {
|
|
434
|
-
version: 1,
|
|
435
|
-
events: context.events,
|
|
436
|
-
};
|
|
437
|
-
_b.label = 1;
|
|
438
|
-
case 1:
|
|
439
|
-
_b.trys.push([1, 3, , 4]);
|
|
440
|
-
options = {
|
|
441
|
-
headers: {
|
|
442
|
-
'Content-Type': 'application/json',
|
|
443
|
-
Accept: '*/*',
|
|
444
|
-
Authorization: "Bearer ".concat(apiKey),
|
|
445
|
-
'X-Client-Version': version,
|
|
446
|
-
'X-Client-Url': url,
|
|
447
|
-
'X-Client-Sample-Rate': "".concat(sampleRate),
|
|
448
|
-
},
|
|
449
|
-
body: JSON.stringify(payload),
|
|
450
|
-
method: 'POST',
|
|
451
|
-
};
|
|
452
|
-
server_url = "".concat(this.getServerUrl(), "?").concat(urlParams.toString());
|
|
453
|
-
return [4 /*yield*/, fetch(server_url, options)];
|
|
454
|
-
case 2:
|
|
455
|
-
res = _b.sent();
|
|
456
|
-
if (res === null) {
|
|
457
|
-
this.completeRequest({ context: context, err: UNEXPECTED_ERROR_MESSAGE });
|
|
458
|
-
return [2 /*return*/];
|
|
459
|
-
}
|
|
460
|
-
if (!useRetry) {
|
|
461
|
-
responseBody = '';
|
|
462
|
-
try {
|
|
463
|
-
responseBody = JSON.stringify(res.body, null, 2);
|
|
464
|
-
}
|
|
465
|
-
catch (_c) {
|
|
466
|
-
// to avoid crash, but don't care about the error, add comment to avoid empty block lint error
|
|
467
|
-
}
|
|
468
|
-
this.completeRequest({ context: context, success: "".concat(res.status, ": ").concat(responseBody) });
|
|
469
|
-
}
|
|
470
|
-
else {
|
|
471
|
-
this.handleReponse(res.status, context);
|
|
472
|
-
}
|
|
473
|
-
return [3 /*break*/, 4];
|
|
474
|
-
case 3:
|
|
475
|
-
e_1 = _b.sent();
|
|
476
|
-
this.completeRequest({ context: context, err: e_1 });
|
|
477
|
-
return [3 /*break*/, 4];
|
|
478
|
-
case 4: return [2 /*return*/];
|
|
479
|
-
}
|
|
480
|
-
});
|
|
481
|
-
});
|
|
482
|
-
};
|
|
483
|
-
SessionReplay.prototype.handleReponse = function (status, context) {
|
|
484
|
-
var parsedStatus = new BaseTransport().buildStatus(status);
|
|
485
|
-
switch (parsedStatus) {
|
|
486
|
-
case Status.Success:
|
|
487
|
-
this.handleSuccessResponse(context);
|
|
488
|
-
break;
|
|
489
|
-
case Status.Failed:
|
|
490
|
-
this.handleOtherResponse(context);
|
|
491
|
-
break;
|
|
492
|
-
default:
|
|
493
|
-
this.completeRequest({ context: context, err: UNEXPECTED_NETWORK_ERROR_MESSAGE });
|
|
494
|
-
}
|
|
495
|
-
};
|
|
496
|
-
SessionReplay.prototype.handleSuccessResponse = function (context) {
|
|
497
|
-
this.completeRequest({ context: context, success: getSuccessMessage(context.sessionId) });
|
|
498
|
-
};
|
|
499
|
-
SessionReplay.prototype.handleOtherResponse = function (context) {
|
|
500
|
-
this.addToQueue(__assign(__assign({}, context), { timeout: context.attempts * this.retryTimeout }));
|
|
501
|
-
};
|
|
502
|
-
SessionReplay.prototype.getAllSessionEventsFromStore = function () {
|
|
503
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
504
|
-
var storedReplaySessionContexts, e_2;
|
|
505
|
-
return __generator(this, function (_a) {
|
|
506
|
-
switch (_a.label) {
|
|
507
|
-
case 0:
|
|
508
|
-
_a.trys.push([0, 2, , 3]);
|
|
509
|
-
return [4 /*yield*/, IDBKeyVal.get(this.storageKey)];
|
|
510
|
-
case 1:
|
|
511
|
-
storedReplaySessionContexts = _a.sent();
|
|
512
|
-
return [2 /*return*/, storedReplaySessionContexts];
|
|
513
|
-
case 2:
|
|
514
|
-
e_2 = _a.sent();
|
|
515
|
-
this.loggerProvider.warn("".concat(STORAGE_FAILURE, ": ").concat(e_2));
|
|
516
|
-
return [3 /*break*/, 3];
|
|
517
|
-
case 3: return [2 /*return*/, undefined];
|
|
518
|
-
}
|
|
519
|
-
});
|
|
520
|
-
});
|
|
521
|
-
};
|
|
522
|
-
SessionReplay.prototype.storeEventsForSession = function (events, sequenceId, sessionId) {
|
|
523
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
524
|
-
var e_3;
|
|
525
|
-
return __generator(this, function (_a) {
|
|
526
|
-
switch (_a.label) {
|
|
527
|
-
case 0:
|
|
528
|
-
_a.trys.push([0, 2, , 3]);
|
|
529
|
-
return [4 /*yield*/, IDBKeyVal.update(this.storageKey, function (sessionMap) {
|
|
530
|
-
var _a, _b;
|
|
531
|
-
if (sessionMap === void 0) { sessionMap = {}; }
|
|
532
|
-
var session = sessionMap[sessionId] || __assign({}, defaultSessionStore);
|
|
533
|
-
session.currentSequenceId = sequenceId;
|
|
534
|
-
var currentSequence = (session.sessionSequences && session.sessionSequences[sequenceId]) || {};
|
|
535
|
-
currentSequence.events = events;
|
|
536
|
-
currentSequence.status = RecordingStatus.RECORDING;
|
|
537
|
-
return __assign(__assign({}, sessionMap), (_a = {}, _a[sessionId] = __assign(__assign({}, session), { sessionSequences: __assign(__assign({}, session.sessionSequences), (_b = {}, _b[sequenceId] = currentSequence, _b)) }), _a));
|
|
538
|
-
})];
|
|
539
|
-
case 1:
|
|
540
|
-
_a.sent();
|
|
541
|
-
return [3 /*break*/, 3];
|
|
542
|
-
case 2:
|
|
543
|
-
e_3 = _a.sent();
|
|
544
|
-
this.loggerProvider.warn("".concat(STORAGE_FAILURE, ": ").concat(e_3));
|
|
545
|
-
return [3 /*break*/, 3];
|
|
546
|
-
case 3: return [2 /*return*/];
|
|
547
|
-
}
|
|
548
|
-
});
|
|
549
|
-
});
|
|
550
|
-
};
|
|
551
|
-
SessionReplay.prototype.cleanUpSessionEventsStore = function (sessionId, sequenceId) {
|
|
244
|
+
SessionReplay.prototype.flush = function (useRetry) {
|
|
245
|
+
if (useRetry === void 0) { useRetry = false; }
|
|
552
246
|
return __awaiter(this, void 0, void 0, function () {
|
|
553
|
-
var e_4;
|
|
554
247
|
return __generator(this, function (_a) {
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
_a.trys.push([0, 2, , 3]);
|
|
558
|
-
return [4 /*yield*/, IDBKeyVal.update(this.storageKey, function (sessionMap) {
|
|
559
|
-
if (sessionMap === void 0) { sessionMap = {}; }
|
|
560
|
-
var session = sessionMap[sessionId];
|
|
561
|
-
var sequenceToUpdate = (session === null || session === void 0 ? void 0 : session.sessionSequences) && session.sessionSequences[sequenceId];
|
|
562
|
-
if (!sequenceToUpdate) {
|
|
563
|
-
return sessionMap;
|
|
564
|
-
}
|
|
565
|
-
sequenceToUpdate.events = [];
|
|
566
|
-
sequenceToUpdate.status = RecordingStatus.SENT;
|
|
567
|
-
// Delete sent sequences for current session
|
|
568
|
-
Object.entries(session.sessionSequences).forEach(function (_a) {
|
|
569
|
-
var _b = __read(_a, 2), storedSeqId = _b[0], sequence = _b[1];
|
|
570
|
-
var numericStoredSeqId = parseInt(storedSeqId, 10);
|
|
571
|
-
if (sequence.status === RecordingStatus.SENT && sequenceId !== numericStoredSeqId) {
|
|
572
|
-
delete session.sessionSequences[numericStoredSeqId];
|
|
573
|
-
}
|
|
574
|
-
});
|
|
575
|
-
// Delete any sessions that are older than 3 days
|
|
576
|
-
Object.keys(sessionMap).forEach(function (sessionId) {
|
|
577
|
-
var numericSessionId = parseInt(sessionId, 10);
|
|
578
|
-
if (Date.now() - numericSessionId >= MAX_IDB_STORAGE_LENGTH) {
|
|
579
|
-
delete sessionMap[numericSessionId];
|
|
580
|
-
}
|
|
581
|
-
});
|
|
582
|
-
return sessionMap;
|
|
583
|
-
})];
|
|
584
|
-
case 1:
|
|
585
|
-
_a.sent();
|
|
586
|
-
return [3 /*break*/, 3];
|
|
587
|
-
case 2:
|
|
588
|
-
e_4 = _a.sent();
|
|
589
|
-
this.loggerProvider.warn("".concat(STORAGE_FAILURE, ": ").concat(e_4));
|
|
590
|
-
return [3 /*break*/, 3];
|
|
591
|
-
case 3: return [2 /*return*/];
|
|
248
|
+
if (this.eventsManager) {
|
|
249
|
+
return [2 /*return*/, this.eventsManager.flush(useRetry)];
|
|
592
250
|
}
|
|
251
|
+
return [2 /*return*/];
|
|
593
252
|
});
|
|
594
253
|
});
|
|
595
254
|
};
|
|
596
|
-
SessionReplay.prototype.completeRequest = function (_a) {
|
|
597
|
-
var context = _a.context, err = _a.err, success = _a.success;
|
|
598
|
-
context.sessionId && this.cleanUpSessionEventsStore(context.sessionId, context.sequenceId);
|
|
599
|
-
if (err) {
|
|
600
|
-
this.loggerProvider.warn(err);
|
|
601
|
-
}
|
|
602
|
-
else if (success) {
|
|
603
|
-
this.loggerProvider.log(success);
|
|
604
|
-
}
|
|
605
|
-
};
|
|
606
255
|
SessionReplay.prototype.shutdown = function () {
|
|
607
256
|
var globalScope = getGlobalScope();
|
|
608
257
|
if (globalScope) {
|