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