@amplitude/session-replay-browser 1.2.2 → 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/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/session-replay.d.ts +2 -21
- package/lib/cjs/session-replay.d.ts.map +1 -1
- package/lib/cjs/session-replay.js +23 -124
- package/lib/cjs/session-replay.js.map +1 -1
- package/lib/cjs/track-destination.d.ts +0 -1
- package/lib/cjs/track-destination.d.ts.map +1 -1
- package/lib/cjs/track-destination.js +0 -3
- package/lib/cjs/track-destination.js.map +1 -1
- package/lib/cjs/typings/session-replay.d.ts +19 -1
- package/lib/cjs/typings/session-replay.d.ts.map +1 -1
- package/lib/cjs/typings/session-replay.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/session-replay.d.ts +2 -21
- package/lib/esm/session-replay.d.ts.map +1 -1
- package/lib/esm/session-replay.js +24 -125
- package/lib/esm/session-replay.js.map +1 -1
- package/lib/esm/track-destination.d.ts +0 -1
- package/lib/esm/track-destination.d.ts.map +1 -1
- package/lib/esm/track-destination.js +0 -3
- package/lib/esm/track-destination.js.map +1 -1
- package/lib/esm/typings/session-replay.d.ts +19 -1
- 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/events-manager.d.ts +49 -0
- package/lib/scripts/events-manager.d.ts.map +1 -0
- package/lib/scripts/session-replay.d.ts +2 -21
- package/lib/scripts/session-replay.d.ts.map +1 -1
- package/lib/scripts/track-destination.d.ts +0 -1
- package/lib/scripts/track-destination.d.ts.map +1 -1
- package/lib/scripts/typings/session-replay.d.ts +19 -1
- package/lib/scripts/typings/session-replay.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { SessionReplayEventsManager as AmplitudeSessionReplayEventsManager, SessionReplaySessionIDBStore as AmplitudeSessionReplayEventsStorage, SessionReplayTrackDestination as AmplitudeSessionReplayTrackDestination, Events, IDBStore, SessionReplayConfig } from './typings/session-replay';
|
|
2
|
+
export declare class SessionReplayEventsManager implements AmplitudeSessionReplayEventsManager {
|
|
3
|
+
events: Events;
|
|
4
|
+
currentSequenceId: number;
|
|
5
|
+
maxPersistedEventsSize: number;
|
|
6
|
+
interval: number;
|
|
7
|
+
timeAtLastSend: number | null;
|
|
8
|
+
sessionIDBStore: AmplitudeSessionReplayEventsStorage;
|
|
9
|
+
trackDestination: AmplitudeSessionReplayTrackDestination;
|
|
10
|
+
config: SessionReplayConfig;
|
|
11
|
+
constructor({ config }: {
|
|
12
|
+
config: SessionReplayConfig;
|
|
13
|
+
});
|
|
14
|
+
initialize({ sessionId, deviceId, shouldSendStoredEvents, }: {
|
|
15
|
+
sessionId: number;
|
|
16
|
+
deviceId: string;
|
|
17
|
+
shouldSendStoredEvents?: boolean;
|
|
18
|
+
}): Promise<void>;
|
|
19
|
+
sendStoredEvents({ storedReplaySessions, sessionId, deviceId, }: {
|
|
20
|
+
storedReplaySessions: IDBStore;
|
|
21
|
+
sessionId: number;
|
|
22
|
+
deviceId: string;
|
|
23
|
+
}): void;
|
|
24
|
+
resetSequence(): void;
|
|
25
|
+
addEvent({ event, sessionId, deviceId }: {
|
|
26
|
+
event: string;
|
|
27
|
+
sessionId: number;
|
|
28
|
+
deviceId: string;
|
|
29
|
+
}): void;
|
|
30
|
+
/**
|
|
31
|
+
* Determines whether to send the events list to the backend and start a new
|
|
32
|
+
* empty events list, based on the size of the list as well as the last time sent
|
|
33
|
+
* @param nextEventString
|
|
34
|
+
* @returns boolean
|
|
35
|
+
*/
|
|
36
|
+
shouldSplitEventsList: (nextEventString: string) => boolean;
|
|
37
|
+
sendEvents({ sessionId, deviceId }: {
|
|
38
|
+
sessionId: number;
|
|
39
|
+
deviceId: string;
|
|
40
|
+
}): void;
|
|
41
|
+
sendEventsList({ events, sequenceId, sessionId, deviceId, }: {
|
|
42
|
+
events: string[];
|
|
43
|
+
sequenceId: number;
|
|
44
|
+
sessionId: number;
|
|
45
|
+
deviceId: string;
|
|
46
|
+
}): void;
|
|
47
|
+
flush(useRetry?: boolean): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=events-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events-manager.d.ts","sourceRoot":"","sources":["../../src/events-manager.ts"],"names":[],"mappings":"AACA,OAAO,EACL,0BAA0B,IAAI,mCAAmC,EACjE,4BAA4B,IAAI,mCAAmC,EACnE,6BAA6B,IAAI,sCAAsC,EACvE,MAAM,EACN,QAAQ,EAER,mBAAmB,EACpB,MAAM,0BAA0B,CAAC;AAKlC,qBAAa,0BAA2B,YAAW,mCAAmC;IACpF,MAAM,EAAE,MAAM,CAAM;IACpB,iBAAiB,SAAK;IACtB,sBAAsB,SAAgC;IACtD,QAAQ,SAAgB;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAQ;IACrC,eAAe,EAAE,mCAAmC,CAAC;IACrD,gBAAgB,EAAE,sCAAsC,CAAC;IACzD,MAAM,EAAE,mBAAmB,CAAC;gBAEhB,EAAE,MAAM,EAAE,EAAE;QAAE,MAAM,EAAE,mBAAmB,CAAA;KAAE;IASjD,UAAU,CAAC,EACf,SAAS,EACT,QAAQ,EACR,sBAA8B,GAC/B,EAAE;QACD,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,sBAAsB,CAAC,EAAE,OAAO,CAAC;KAClC;IAsBD,gBAAgB,CAAC,EACf,oBAAoB,EACpB,SAAS,EACT,QAAQ,GACT,EAAE;QACD,oBAAoB,EAAE,QAAQ,CAAC;QAC/B,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;KAClB;IAuBD,aAAa;IAKb,QAAQ,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;IAgB/F;;;;;OAKG;IACH,qBAAqB,oBAAqB,MAAM,KAAG,OAAO,CAYxD;IAEF,UAAU,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;IAW3E,cAAc,CAAC,EACb,MAAM,EACN,UAAU,EACV,SAAS,EACT,QAAQ,GACT,EAAE;QACD,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;KAClB;IAcK,KAAK,CAAC,QAAQ,UAAQ;CAK7B"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
|
+
exports.SessionReplayEventsManager = void 0;
|
|
3
|
+
var tslib_1 = require("tslib");
|
|
4
|
+
var constants_1 = require("./constants");
|
|
5
|
+
var session_replay_1 = require("./typings/session-replay");
|
|
6
|
+
var session_idb_store_1 = require("./session-idb-store");
|
|
7
|
+
var track_destination_1 = require("./track-destination");
|
|
8
|
+
var SessionReplayEventsManager = /** @class */ (function () {
|
|
9
|
+
function SessionReplayEventsManager(_a) {
|
|
10
|
+
var config = _a.config;
|
|
11
|
+
var _this = this;
|
|
12
|
+
this.events = [];
|
|
13
|
+
this.currentSequenceId = 0;
|
|
14
|
+
this.maxPersistedEventsSize = constants_1.MAX_EVENT_LIST_SIZE_IN_BYTES;
|
|
15
|
+
this.interval = constants_1.MIN_INTERVAL;
|
|
16
|
+
this.timeAtLastSend = null;
|
|
17
|
+
/**
|
|
18
|
+
* Determines whether to send the events list to the backend and start a new
|
|
19
|
+
* empty events list, based on the size of the list as well as the last time sent
|
|
20
|
+
* @param nextEventString
|
|
21
|
+
* @returns boolean
|
|
22
|
+
*/
|
|
23
|
+
this.shouldSplitEventsList = function (nextEventString) {
|
|
24
|
+
var sizeOfNextEvent = new Blob([nextEventString]).size;
|
|
25
|
+
var sizeOfEventsList = new Blob(_this.events).size;
|
|
26
|
+
if (sizeOfEventsList + sizeOfNextEvent >= _this.maxPersistedEventsSize) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
if (_this.timeAtLastSend !== null && Date.now() - _this.timeAtLastSend > _this.interval && _this.events.length) {
|
|
30
|
+
_this.interval = Math.min(constants_1.MAX_INTERVAL, _this.interval + constants_1.MIN_INTERVAL);
|
|
31
|
+
_this.timeAtLastSend = Date.now();
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
};
|
|
36
|
+
this.config = config;
|
|
37
|
+
this.trackDestination = new track_destination_1.SessionReplayTrackDestination({ loggerProvider: this.config.loggerProvider });
|
|
38
|
+
this.sessionIDBStore = new session_idb_store_1.SessionReplaySessionIDBStore({
|
|
39
|
+
loggerProvider: this.config.loggerProvider,
|
|
40
|
+
apiKey: this.config.apiKey,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
SessionReplayEventsManager.prototype.initialize = function (_a) {
|
|
44
|
+
var sessionId = _a.sessionId, deviceId = _a.deviceId, _b = _a.shouldSendStoredEvents, shouldSendStoredEvents = _b === void 0 ? false : _b;
|
|
45
|
+
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
46
|
+
var storedReplaySessions, storedSequencesForSession, storedSeqId, lastSequence;
|
|
47
|
+
return tslib_1.__generator(this, function (_c) {
|
|
48
|
+
switch (_c.label) {
|
|
49
|
+
case 0:
|
|
50
|
+
this.timeAtLastSend = Date.now(); // Initialize this so we have a point of comparison when events are recorded
|
|
51
|
+
return [4 /*yield*/, this.sessionIDBStore.getAllSessionDataFromStore()];
|
|
52
|
+
case 1:
|
|
53
|
+
storedReplaySessions = _c.sent();
|
|
54
|
+
storedSequencesForSession = storedReplaySessions && storedReplaySessions[sessionId];
|
|
55
|
+
if (storedReplaySessions && storedSequencesForSession && storedSequencesForSession.sessionSequences) {
|
|
56
|
+
storedSeqId = storedSequencesForSession.currentSequenceId;
|
|
57
|
+
lastSequence = storedSequencesForSession.sessionSequences[storedSeqId];
|
|
58
|
+
if (lastSequence && lastSequence.status !== session_replay_1.RecordingStatus.RECORDING) {
|
|
59
|
+
this.currentSequenceId = storedSeqId + 1;
|
|
60
|
+
this.events = [];
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// Pick up recording where it was left off in another tab or window
|
|
64
|
+
this.currentSequenceId = storedSeqId;
|
|
65
|
+
this.events = (lastSequence === null || lastSequence === void 0 ? void 0 : lastSequence.events) || [];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (shouldSendStoredEvents && storedReplaySessions) {
|
|
69
|
+
this.sendStoredEvents({ storedReplaySessions: storedReplaySessions, deviceId: deviceId, sessionId: sessionId });
|
|
70
|
+
}
|
|
71
|
+
return [2 /*return*/];
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
SessionReplayEventsManager.prototype.sendStoredEvents = function (_a) {
|
|
77
|
+
var storedReplaySessions = _a.storedReplaySessions, sessionId = _a.sessionId, deviceId = _a.deviceId;
|
|
78
|
+
for (var storedSessionId in storedReplaySessions) {
|
|
79
|
+
var storedSequences = storedReplaySessions[storedSessionId].sessionSequences;
|
|
80
|
+
for (var storedSeqId in storedSequences) {
|
|
81
|
+
var seq = storedSequences[storedSeqId];
|
|
82
|
+
var numericSeqId = parseInt(storedSeqId, 10);
|
|
83
|
+
var numericSessionId = parseInt(storedSessionId, 10);
|
|
84
|
+
if (numericSessionId === sessionId && numericSeqId === this.currentSequenceId) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (seq.events && seq.events.length && seq.status === session_replay_1.RecordingStatus.RECORDING) {
|
|
88
|
+
this.sendEventsList({
|
|
89
|
+
events: seq.events,
|
|
90
|
+
sequenceId: numericSeqId,
|
|
91
|
+
sessionId: numericSessionId,
|
|
92
|
+
deviceId: deviceId,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
SessionReplayEventsManager.prototype.resetSequence = function () {
|
|
99
|
+
this.events = [];
|
|
100
|
+
this.currentSequenceId = 0;
|
|
101
|
+
};
|
|
102
|
+
SessionReplayEventsManager.prototype.addEvent = function (_a) {
|
|
103
|
+
var event = _a.event, sessionId = _a.sessionId, deviceId = _a.deviceId;
|
|
104
|
+
var shouldSplit = this.shouldSplitEventsList(event);
|
|
105
|
+
if (shouldSplit) {
|
|
106
|
+
this.sendEventsList({
|
|
107
|
+
events: this.events,
|
|
108
|
+
sequenceId: this.currentSequenceId,
|
|
109
|
+
sessionId: sessionId,
|
|
110
|
+
deviceId: deviceId,
|
|
111
|
+
});
|
|
112
|
+
this.events = [];
|
|
113
|
+
this.currentSequenceId++;
|
|
114
|
+
}
|
|
115
|
+
this.events.push(event);
|
|
116
|
+
void this.sessionIDBStore.storeEventsForSession(this.events, this.currentSequenceId, sessionId);
|
|
117
|
+
};
|
|
118
|
+
SessionReplayEventsManager.prototype.sendEvents = function (_a) {
|
|
119
|
+
var sessionId = _a.sessionId, deviceId = _a.deviceId;
|
|
120
|
+
if (this.events.length && sessionId) {
|
|
121
|
+
this.sendEventsList({
|
|
122
|
+
events: this.events,
|
|
123
|
+
sequenceId: this.currentSequenceId,
|
|
124
|
+
sessionId: sessionId,
|
|
125
|
+
deviceId: deviceId,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
SessionReplayEventsManager.prototype.sendEventsList = function (_a) {
|
|
130
|
+
var events = _a.events, sequenceId = _a.sequenceId, sessionId = _a.sessionId, deviceId = _a.deviceId;
|
|
131
|
+
this.trackDestination.sendEventsList({
|
|
132
|
+
events: events,
|
|
133
|
+
sequenceId: sequenceId,
|
|
134
|
+
sessionId: sessionId,
|
|
135
|
+
flushMaxRetries: this.config.flushMaxRetries,
|
|
136
|
+
apiKey: this.config.apiKey,
|
|
137
|
+
deviceId: deviceId,
|
|
138
|
+
sampleRate: this.config.sampleRate,
|
|
139
|
+
serverZone: this.config.serverZone,
|
|
140
|
+
onComplete: this.sessionIDBStore.cleanUpSessionEventsStore.bind(this.sessionIDBStore),
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
SessionReplayEventsManager.prototype.flush = function (useRetry) {
|
|
144
|
+
if (useRetry === void 0) { useRetry = false; }
|
|
145
|
+
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
146
|
+
return tslib_1.__generator(this, function (_a) {
|
|
147
|
+
if (this.trackDestination) {
|
|
148
|
+
return [2 /*return*/, this.trackDestination.flush(useRetry)];
|
|
149
|
+
}
|
|
150
|
+
return [2 /*return*/];
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
};
|
|
154
|
+
return SessionReplayEventsManager;
|
|
155
|
+
}());
|
|
156
|
+
exports.SessionReplayEventsManager = SessionReplayEventsManager;
|
|
157
|
+
//# sourceMappingURL=events-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events-manager.js","sourceRoot":"","sources":["../../src/events-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { MAX_EVENT_LIST_SIZE_IN_BYTES, MAX_INTERVAL, MIN_INTERVAL } from './constants';\nimport {\n SessionReplayEventsManager as AmplitudeSessionReplayEventsManager,\n SessionReplaySessionIDBStore as AmplitudeSessionReplayEventsStorage,\n SessionReplayTrackDestination as AmplitudeSessionReplayTrackDestination,\n Events,\n IDBStore,\n RecordingStatus,\n SessionReplayConfig,\n} from './typings/session-replay';\n\nimport { SessionReplaySessionIDBStore } from './session-idb-store';\nimport { SessionReplayTrackDestination } from './track-destination';\n\nexport class SessionReplayEventsManager implements AmplitudeSessionReplayEventsManager {\n events: Events = [];\n currentSequenceId = 0;\n maxPersistedEventsSize = MAX_EVENT_LIST_SIZE_IN_BYTES;\n interval = MIN_INTERVAL;\n timeAtLastSend: number | null = null;\n sessionIDBStore: AmplitudeSessionReplayEventsStorage;\n trackDestination: AmplitudeSessionReplayTrackDestination;\n config: SessionReplayConfig;\n\n constructor({ config }: { config: SessionReplayConfig }) {\n this.config = config;\n this.trackDestination = new SessionReplayTrackDestination({ loggerProvider: this.config.loggerProvider });\n this.sessionIDBStore = new SessionReplaySessionIDBStore({\n loggerProvider: this.config.loggerProvider,\n apiKey: this.config.apiKey,\n });\n }\n\n async initialize({\n sessionId,\n deviceId,\n shouldSendStoredEvents = false,\n }: {\n sessionId: number;\n deviceId: string;\n shouldSendStoredEvents?: boolean;\n }) {\n this.timeAtLastSend = Date.now(); // Initialize this so we have a point of comparison when events are recorded\n const storedReplaySessions = await this.sessionIDBStore.getAllSessionDataFromStore();\n\n const storedSequencesForSession = storedReplaySessions && storedReplaySessions[sessionId];\n if (storedReplaySessions && storedSequencesForSession && storedSequencesForSession.sessionSequences) {\n const storedSeqId = storedSequencesForSession.currentSequenceId;\n const lastSequence = storedSequencesForSession.sessionSequences[storedSeqId];\n if (lastSequence && lastSequence.status !== RecordingStatus.RECORDING) {\n this.currentSequenceId = storedSeqId + 1;\n this.events = [];\n } else {\n // Pick up recording where it was left off in another tab or window\n this.currentSequenceId = storedSeqId;\n this.events = lastSequence?.events || [];\n }\n }\n if (shouldSendStoredEvents && storedReplaySessions) {\n this.sendStoredEvents({ storedReplaySessions, deviceId, sessionId });\n }\n }\n\n sendStoredEvents({\n storedReplaySessions,\n sessionId,\n deviceId,\n }: {\n storedReplaySessions: IDBStore;\n sessionId: number;\n deviceId: string;\n }) {\n for (const storedSessionId in storedReplaySessions) {\n const storedSequences = storedReplaySessions[storedSessionId].sessionSequences;\n for (const storedSeqId in storedSequences) {\n const seq = storedSequences[storedSeqId];\n const numericSeqId = parseInt(storedSeqId, 10);\n const numericSessionId = parseInt(storedSessionId, 10);\n if (numericSessionId === sessionId && numericSeqId === this.currentSequenceId) {\n continue;\n }\n\n if (seq.events && seq.events.length && seq.status === RecordingStatus.RECORDING) {\n this.sendEventsList({\n events: seq.events,\n sequenceId: numericSeqId,\n sessionId: numericSessionId,\n deviceId,\n });\n }\n }\n }\n }\n\n resetSequence() {\n this.events = [];\n this.currentSequenceId = 0;\n }\n\n addEvent({ event, sessionId, deviceId }: { event: string; sessionId: number; deviceId: string }) {\n const shouldSplit = this.shouldSplitEventsList(event);\n if (shouldSplit) {\n this.sendEventsList({\n events: this.events,\n sequenceId: this.currentSequenceId,\n sessionId,\n deviceId,\n });\n this.events = [];\n this.currentSequenceId++;\n }\n this.events.push(event);\n void this.sessionIDBStore.storeEventsForSession(this.events, this.currentSequenceId, sessionId);\n }\n\n /**\n * Determines whether to send the events list to the backend and start a new\n * empty events list, based on the size of the list as well as the last time sent\n * @param nextEventString\n * @returns boolean\n */\n shouldSplitEventsList = (nextEventString: string): boolean => {\n const sizeOfNextEvent = new Blob([nextEventString]).size;\n const sizeOfEventsList = new Blob(this.events).size;\n if (sizeOfEventsList + sizeOfNextEvent >= this.maxPersistedEventsSize) {\n return true;\n }\n if (this.timeAtLastSend !== null && Date.now() - this.timeAtLastSend > this.interval && this.events.length) {\n this.interval = Math.min(MAX_INTERVAL, this.interval + MIN_INTERVAL);\n this.timeAtLastSend = Date.now();\n return true;\n }\n return false;\n };\n\n sendEvents({ sessionId, deviceId }: { sessionId: number; deviceId: string }) {\n if (this.events.length && sessionId) {\n this.sendEventsList({\n events: this.events,\n sequenceId: this.currentSequenceId,\n sessionId,\n deviceId,\n });\n }\n }\n\n sendEventsList({\n events,\n sequenceId,\n sessionId,\n deviceId,\n }: {\n events: string[];\n sequenceId: number;\n sessionId: number;\n deviceId: string;\n }) {\n this.trackDestination.sendEventsList({\n events: events,\n sequenceId: sequenceId,\n sessionId: sessionId,\n flushMaxRetries: this.config.flushMaxRetries,\n apiKey: this.config.apiKey,\n deviceId: deviceId,\n sampleRate: this.config.sampleRate,\n serverZone: this.config.serverZone,\n onComplete: this.sessionIDBStore.cleanUpSessionEventsStore.bind(this.sessionIDBStore),\n });\n }\n\n async flush(useRetry = false) {\n if (this.trackDestination) {\n return this.trackDestination.flush(useRetry);\n }\n }\n}\n"]}
|
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
import { Logger as ILogger } from '@amplitude/analytics-types';
|
|
2
2
|
import { record } from '@amplitude/rrweb';
|
|
3
|
-
import { AmplitudeSessionReplay,
|
|
3
|
+
import { AmplitudeSessionReplay, SessionReplayEventsManager as AmplitudeSessionReplayEventsManager, SessionIdentifiers as ISessionIdentifiers, SessionReplayConfig as ISessionReplayConfig, SessionReplayOptions } from './typings/session-replay';
|
|
4
4
|
export declare class SessionReplay implements AmplitudeSessionReplay {
|
|
5
5
|
name: string;
|
|
6
6
|
config: ISessionReplayConfig | undefined;
|
|
7
7
|
identifiers: ISessionIdentifiers | undefined;
|
|
8
|
-
|
|
9
|
-
sessionIDBStore: AmplitudeSessionReplaySessionIDBStore | undefined;
|
|
8
|
+
eventsManager: AmplitudeSessionReplayEventsManager | undefined;
|
|
10
9
|
loggerProvider: ILogger;
|
|
11
|
-
events: Events;
|
|
12
|
-
currentSequenceId: number;
|
|
13
10
|
stopRecordingEvents: ReturnType<typeof record> | null;
|
|
14
|
-
maxPersistedEventsSize: number;
|
|
15
|
-
interval: number;
|
|
16
|
-
timeAtLastSend: number | null;
|
|
17
11
|
constructor();
|
|
18
12
|
init(apiKey: string, options: SessionReplayOptions): import("@amplitude/analytics-types").AmplitudeReturn<void>;
|
|
19
13
|
protected _init(apiKey: string, options: SessionReplayOptions): Promise<void>;
|
|
@@ -29,20 +23,7 @@ export declare class SessionReplay implements AmplitudeSessionReplay {
|
|
|
29
23
|
shouldOptOut(): boolean | undefined;
|
|
30
24
|
getShouldRecord(ignoreFocus?: boolean): boolean;
|
|
31
25
|
getBlockSelectors(): string | string[] | undefined;
|
|
32
|
-
sendStoredEvents(storedReplaySessions: IDBStore): void;
|
|
33
26
|
recordEvents(): void;
|
|
34
|
-
/**
|
|
35
|
-
* Determines whether to send the events list to the backend and start a new
|
|
36
|
-
* empty events list, based on the size of the list as well as the last time sent
|
|
37
|
-
* @param nextEventString
|
|
38
|
-
* @returns boolean
|
|
39
|
-
*/
|
|
40
|
-
shouldSplitEventsList: (nextEventString: string) => boolean;
|
|
41
|
-
sendEventsList({ events, sequenceId, sessionId }: {
|
|
42
|
-
events: string[];
|
|
43
|
-
sequenceId: number;
|
|
44
|
-
sessionId: number;
|
|
45
|
-
}): void;
|
|
46
27
|
getDeviceId(): string | undefined;
|
|
47
28
|
getSessionId(): number | undefined;
|
|
48
29
|
flush(useRetry?: boolean): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAQ,MAAM,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAQ,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAWhD,OAAO,EACL,sBAAsB,EACtB,0BAA0B,IAAI,mCAAmC,EACjE,kBAAkB,IAAI,mBAAmB,EACzC,mBAAmB,IAAI,oBAAoB,EAC3C,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAElC,qBAAa,aAAc,YAAW,sBAAsB;IAC1D,IAAI,SAAuC;IAC3C,MAAM,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACzC,WAAW,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAC7C,aAAa,EAAE,mCAAmC,GAAG,SAAS,CAAC;IAC/D,cAAc,EAAE,OAAO,CAAC;IACxB,mBAAmB,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,GAAG,IAAI,CAAQ;;IAM7D,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;cAIlC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB;IAsBnE,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAwBjD,kCAAkC;IAUlC,0BAA0B;;;IAwB1B,YAAY,aAEV;IAEF,aAAa,aAEX;IAEF,0BAA0B,CAAC,SAAS,CAAC,EAAE,MAAM;IAiBvC,UAAU,CAAC,sBAAsB,UAAQ;IAkB/C,YAAY;IAUZ,eAAe,CAAC,WAAW,UAAQ;IA8BnC,iBAAiB,IAAI,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAIlD,YAAY;IAkCZ,WAAW;IAUX,YAAY;IAIN,KAAK,CAAC,QAAQ,UAAQ;IAM5B,QAAQ;CAST"}
|
|
@@ -6,48 +6,21 @@ var analytics_core_1 = require("@amplitude/analytics-core");
|
|
|
6
6
|
var rrweb_1 = require("@amplitude/rrweb");
|
|
7
7
|
var config_1 = require("./config");
|
|
8
8
|
var constants_1 = require("./constants");
|
|
9
|
+
var events_manager_1 = require("./events-manager");
|
|
9
10
|
var helpers_1 = require("./helpers");
|
|
10
11
|
var identifiers_1 = require("./identifiers");
|
|
11
|
-
var session_idb_store_1 = require("./session-idb-store");
|
|
12
|
-
var track_destination_1 = require("./track-destination");
|
|
13
|
-
var session_replay_1 = require("./typings/session-replay");
|
|
14
12
|
var SessionReplay = /** @class */ (function () {
|
|
15
13
|
function SessionReplay() {
|
|
16
14
|
var _this = this;
|
|
17
15
|
this.name = '@amplitude/session-replay-browser';
|
|
18
|
-
this.events = [];
|
|
19
|
-
this.currentSequenceId = 0;
|
|
20
16
|
this.stopRecordingEvents = null;
|
|
21
|
-
this.maxPersistedEventsSize = constants_1.MAX_EVENT_LIST_SIZE_IN_BYTES;
|
|
22
|
-
this.interval = constants_1.MIN_INTERVAL;
|
|
23
|
-
this.timeAtLastSend = null;
|
|
24
17
|
this.blurListener = function () {
|
|
25
18
|
_this.stopRecordingAndSendEvents();
|
|
26
19
|
};
|
|
27
20
|
this.focusListener = function () {
|
|
28
21
|
void _this.initialize();
|
|
29
22
|
};
|
|
30
|
-
/**
|
|
31
|
-
* Determines whether to send the events list to the backend and start a new
|
|
32
|
-
* empty events list, based on the size of the list as well as the last time sent
|
|
33
|
-
* @param nextEventString
|
|
34
|
-
* @returns boolean
|
|
35
|
-
*/
|
|
36
|
-
this.shouldSplitEventsList = function (nextEventString) {
|
|
37
|
-
var sizeOfNextEvent = new Blob([nextEventString]).size;
|
|
38
|
-
var sizeOfEventsList = new Blob(_this.events).size;
|
|
39
|
-
if (sizeOfEventsList + sizeOfNextEvent >= _this.maxPersistedEventsSize) {
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
if (_this.timeAtLastSend !== null && Date.now() - _this.timeAtLastSend > _this.interval && _this.events.length) {
|
|
43
|
-
_this.interval = Math.min(constants_1.MAX_INTERVAL, _this.interval + constants_1.MIN_INTERVAL);
|
|
44
|
-
_this.timeAtLastSend = Date.now();
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
return false;
|
|
48
|
-
};
|
|
49
23
|
this.loggerProvider = new analytics_core_1.Logger();
|
|
50
|
-
this.trackDestination = new track_destination_1.SessionReplayTrackDestination({ loggerProvider: this.loggerProvider });
|
|
51
24
|
}
|
|
52
25
|
SessionReplay.prototype.init = function (apiKey, options) {
|
|
53
26
|
return (0, analytics_core_1.returnWrapper)(this._init(apiKey, options));
|
|
@@ -61,11 +34,8 @@ var SessionReplay = /** @class */ (function () {
|
|
|
61
34
|
this.config = new config_1.SessionReplayConfig(apiKey, options);
|
|
62
35
|
this.loggerProvider = this.config.loggerProvider;
|
|
63
36
|
this.identifiers = new identifiers_1.SessionIdentifiers(options, this.loggerProvider);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this.sessionIDBStore = new session_idb_store_1.SessionReplaySessionIDBStore({
|
|
67
|
-
loggerProvider: this.loggerProvider,
|
|
68
|
-
apiKey: this.config.apiKey,
|
|
37
|
+
this.eventsManager = new events_manager_1.SessionReplayEventsManager({
|
|
38
|
+
config: this.config,
|
|
69
39
|
});
|
|
70
40
|
this.loggerProvider.log('Installing @amplitude/session-replay-browser.');
|
|
71
41
|
globalScope = (0, analytics_client_common_1.getGlobalScope)();
|
|
@@ -102,8 +72,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
102
72
|
}
|
|
103
73
|
this.stopRecordingAndSendEvents(this.identifiers.sessionId);
|
|
104
74
|
this.identifiers.sessionId = sessionId;
|
|
105
|
-
this.
|
|
106
|
-
this.currentSequenceId = 0;
|
|
75
|
+
this.eventsManager && this.eventsManager.resetSequence();
|
|
107
76
|
this.recordEvents();
|
|
108
77
|
};
|
|
109
78
|
SessionReplay.prototype.getSessionReplayDebugPropertyValue = function () {
|
|
@@ -147,58 +116,38 @@ var SessionReplay = /** @class */ (function () {
|
|
|
147
116
|
this.loggerProvider.warn("Error occurred while stopping recording: ".concat(typedError.toString()));
|
|
148
117
|
}
|
|
149
118
|
var sessionIdToSend = sessionId || ((_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId);
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
});
|
|
156
|
-
}
|
|
119
|
+
var deviceId = this.getDeviceId();
|
|
120
|
+
this.eventsManager &&
|
|
121
|
+
sessionIdToSend &&
|
|
122
|
+
deviceId &&
|
|
123
|
+
this.eventsManager.sendEvents({ sessionId: sessionIdToSend, deviceId: deviceId });
|
|
157
124
|
};
|
|
158
125
|
SessionReplay.prototype.initialize = function (shouldSendStoredEvents) {
|
|
159
126
|
var _a;
|
|
160
127
|
if (shouldSendStoredEvents === void 0) { shouldSendStoredEvents = false; }
|
|
161
128
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
162
|
-
var
|
|
129
|
+
var deviceId, _b;
|
|
163
130
|
return tslib_1.__generator(this, function (_c) {
|
|
164
131
|
switch (_c.label) {
|
|
165
132
|
case 0:
|
|
166
|
-
this.timeAtLastSend = Date.now(); // Initialize this so we have a point of comparison when events are recorded
|
|
167
133
|
if (!((_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId)) {
|
|
168
134
|
this.loggerProvider.warn("Session is not being recorded due to lack of session id.");
|
|
169
135
|
return [2 /*return*/];
|
|
170
136
|
}
|
|
171
|
-
|
|
137
|
+
deviceId = this.getDeviceId();
|
|
138
|
+
_b = this.eventsManager &&
|
|
139
|
+
deviceId;
|
|
172
140
|
if (!_b) return [3 /*break*/, 2];
|
|
173
|
-
return [4 /*yield*/, this.
|
|
141
|
+
return [4 /*yield*/, this.eventsManager.initialize({
|
|
142
|
+
sessionId: this.identifiers.sessionId,
|
|
143
|
+
shouldSendStoredEvents: shouldSendStoredEvents,
|
|
144
|
+
deviceId: deviceId,
|
|
145
|
+
})];
|
|
174
146
|
case 1:
|
|
175
147
|
_b = (_c.sent());
|
|
176
148
|
_c.label = 2;
|
|
177
149
|
case 2:
|
|
178
|
-
|
|
179
|
-
// This resolves a timing issue when focus is fired multiple times in short succession,
|
|
180
|
-
// we only want the rest of this function to run once. We can be sure that initialize has
|
|
181
|
-
// already been called if this.stopRecordingEvents is defined
|
|
182
|
-
if (this.stopRecordingEvents) {
|
|
183
|
-
return [2 /*return*/];
|
|
184
|
-
}
|
|
185
|
-
storedSequencesForSession = storedReplaySessions && storedReplaySessions[this.identifiers.sessionId];
|
|
186
|
-
if (storedReplaySessions && storedSequencesForSession && storedSequencesForSession.sessionSequences) {
|
|
187
|
-
storedSeqId = storedSequencesForSession.currentSequenceId;
|
|
188
|
-
lastSequence = storedSequencesForSession.sessionSequences[storedSeqId];
|
|
189
|
-
if (lastSequence && lastSequence.status !== session_replay_1.RecordingStatus.RECORDING) {
|
|
190
|
-
this.currentSequenceId = storedSeqId + 1;
|
|
191
|
-
this.events = [];
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
// Pick up recording where it was left off in another tab or window
|
|
195
|
-
this.currentSequenceId = storedSeqId;
|
|
196
|
-
this.events = (lastSequence === null || lastSequence === void 0 ? void 0 : lastSequence.events) || [];
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
if (shouldSendStoredEvents && storedReplaySessions) {
|
|
200
|
-
this.sendStoredEvents(storedReplaySessions);
|
|
201
|
-
}
|
|
150
|
+
_b;
|
|
202
151
|
this.recordEvents();
|
|
203
152
|
return [2 /*return*/];
|
|
204
153
|
}
|
|
@@ -247,27 +196,6 @@ var SessionReplay = /** @class */ (function () {
|
|
|
247
196
|
var _a, _b;
|
|
248
197
|
return (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.privacyConfig) === null || _b === void 0 ? void 0 : _b.blockSelector;
|
|
249
198
|
};
|
|
250
|
-
SessionReplay.prototype.sendStoredEvents = function (storedReplaySessions) {
|
|
251
|
-
var _a;
|
|
252
|
-
for (var sessionId in storedReplaySessions) {
|
|
253
|
-
var storedSequences = storedReplaySessions[sessionId].sessionSequences;
|
|
254
|
-
for (var storedSeqId in storedSequences) {
|
|
255
|
-
var seq = storedSequences[storedSeqId];
|
|
256
|
-
var numericSeqId = parseInt(storedSeqId, 10);
|
|
257
|
-
var numericSessionId = parseInt(sessionId, 10);
|
|
258
|
-
if (numericSessionId === ((_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId) && numericSeqId === this.currentSequenceId) {
|
|
259
|
-
continue;
|
|
260
|
-
}
|
|
261
|
-
if (seq.events && seq.events.length && seq.status === session_replay_1.RecordingStatus.RECORDING) {
|
|
262
|
-
this.sendEventsList({
|
|
263
|
-
events: seq.events,
|
|
264
|
-
sequenceId: numericSeqId,
|
|
265
|
-
sessionId: numericSessionId,
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
199
|
SessionReplay.prototype.recordEvents = function () {
|
|
272
200
|
var _this = this;
|
|
273
201
|
var _a;
|
|
@@ -284,19 +212,8 @@ var SessionReplay = /** @class */ (function () {
|
|
|
284
212
|
return;
|
|
285
213
|
}
|
|
286
214
|
var eventString = JSON.stringify(event);
|
|
287
|
-
var
|
|
288
|
-
|
|
289
|
-
_this.sendEventsList({
|
|
290
|
-
events: _this.events,
|
|
291
|
-
sequenceId: _this.currentSequenceId,
|
|
292
|
-
sessionId: sessionId,
|
|
293
|
-
});
|
|
294
|
-
_this.events = [];
|
|
295
|
-
_this.currentSequenceId++;
|
|
296
|
-
}
|
|
297
|
-
_this.events.push(eventString);
|
|
298
|
-
_this.sessionIDBStore &&
|
|
299
|
-
void _this.sessionIDBStore.storeEventsForSession(_this.events, _this.currentSequenceId, sessionId);
|
|
215
|
+
var deviceId = _this.getDeviceId();
|
|
216
|
+
deviceId && _this.eventsManager && _this.eventsManager.addEvent({ event: eventString, sessionId: sessionId, deviceId: deviceId });
|
|
300
217
|
},
|
|
301
218
|
packFn: rrweb_1.pack,
|
|
302
219
|
maskAllInputs: true,
|
|
@@ -313,24 +230,6 @@ var SessionReplay = /** @class */ (function () {
|
|
|
313
230
|
},
|
|
314
231
|
});
|
|
315
232
|
};
|
|
316
|
-
SessionReplay.prototype.sendEventsList = function (_a) {
|
|
317
|
-
var events = _a.events, sequenceId = _a.sequenceId, sessionId = _a.sessionId;
|
|
318
|
-
if (!this.config || !this.sessionIDBStore) {
|
|
319
|
-
this.loggerProvider.error("Session is not being recorded due to lack of config, please call sessionReplay.init.");
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
this.trackDestination.sendEventsList({
|
|
323
|
-
events: events,
|
|
324
|
-
sequenceId: sequenceId,
|
|
325
|
-
sessionId: sessionId,
|
|
326
|
-
flushMaxRetries: this.config.flushMaxRetries,
|
|
327
|
-
apiKey: this.config.apiKey,
|
|
328
|
-
deviceId: this.getDeviceId(),
|
|
329
|
-
sampleRate: this.config.sampleRate,
|
|
330
|
-
serverZone: this.config.serverZone,
|
|
331
|
-
onComplete: this.sessionIDBStore.cleanUpSessionEventsStore.bind(this.sessionIDBStore),
|
|
332
|
-
});
|
|
333
|
-
};
|
|
334
233
|
SessionReplay.prototype.getDeviceId = function () {
|
|
335
234
|
var _a, _b;
|
|
336
235
|
var identityStoreDeviceId;
|
|
@@ -348,8 +247,8 @@ var SessionReplay = /** @class */ (function () {
|
|
|
348
247
|
if (useRetry === void 0) { useRetry = false; }
|
|
349
248
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
350
249
|
return tslib_1.__generator(this, function (_a) {
|
|
351
|
-
if (this.
|
|
352
|
-
return [2 /*return*/, this.
|
|
250
|
+
if (this.eventsManager) {
|
|
251
|
+
return [2 /*return*/, this.eventsManager.flush(useRetry)];
|
|
353
252
|
}
|
|
354
253
|
return [2 /*return*/];
|
|
355
254
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-replay.js","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"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","sourcesContent":["import { getAnalyticsConnector, getGlobalScope } from '@amplitude/analytics-client-common';\nimport { Logger, returnWrapper } from '@amplitude/analytics-core';\nimport { Logger as ILogger } from '@amplitude/analytics-types';\nimport { pack, record } from '@amplitude/rrweb';\nimport { SessionReplayConfig } from './config';\nimport {\n BLOCK_CLASS,\n DEFAULT_SESSION_REPLAY_PROPERTY,\n MASK_TEXT_CLASS,\n MAX_EVENT_LIST_SIZE_IN_BYTES,\n MAX_INTERVAL,\n MIN_INTERVAL,\n SESSION_REPLAY_DEBUG_PROPERTY,\n} from './constants';\nimport { generateHashCode, generateSessionReplayId, isSessionInSample, maskInputFn } from './helpers';\nimport { SessionIdentifiers } from './identifiers';\nimport { SessionReplaySessionIDBStore } from './session-idb-store';\nimport { SessionReplayTrackDestination } from './track-destination';\nimport {\n AmplitudeSessionReplay,\n SessionReplaySessionIDBStore as AmplitudeSessionReplaySessionIDBStore,\n SessionReplayTrackDestination as AmplitudeSessionReplayTrackDestination,\n Events,\n IDBStore,\n SessionIdentifiers as ISessionIdentifiers,\n SessionReplayConfig as ISessionReplayConfig,\n RecordingStatus,\n SessionReplayOptions,\n} from './typings/session-replay';\n\nexport class SessionReplay implements AmplitudeSessionReplay {\n name = '@amplitude/session-replay-browser';\n config: ISessionReplayConfig | undefined;\n identifiers: ISessionIdentifiers | undefined;\n trackDestination: AmplitudeSessionReplayTrackDestination;\n sessionIDBStore: AmplitudeSessionReplaySessionIDBStore | undefined;\n loggerProvider: ILogger;\n events: Events = [];\n currentSequenceId = 0;\n stopRecordingEvents: ReturnType<typeof record> | null = null;\n maxPersistedEventsSize = MAX_EVENT_LIST_SIZE_IN_BYTES;\n interval = MIN_INTERVAL;\n timeAtLastSend: number | null = null;\n\n constructor() {\n this.loggerProvider = new Logger();\n this.trackDestination = new SessionReplayTrackDestination({ loggerProvider: this.loggerProvider });\n }\n\n init(apiKey: string, options: SessionReplayOptions) {\n return returnWrapper(this._init(apiKey, options));\n }\n\n protected async _init(apiKey: string, options: SessionReplayOptions) {\n this.config = new SessionReplayConfig(apiKey, options);\n this.loggerProvider = this.config.loggerProvider;\n this.identifiers = new SessionIdentifiers(options, this.loggerProvider);\n // Update logger provider in trackDestination\n this.trackDestination.setLoggerProvider(this.loggerProvider);\n\n this.sessionIDBStore = new SessionReplaySessionIDBStore({\n loggerProvider: this.loggerProvider,\n apiKey: this.config.apiKey,\n });\n\n this.loggerProvider.log('Installing @amplitude/session-replay-browser.');\n\n const globalScope = getGlobalScope();\n if (globalScope) {\n globalScope.addEventListener('blur', this.blurListener);\n globalScope.addEventListener('focus', this.focusListener);\n }\n\n if (globalScope && globalScope.document && globalScope.document.hasFocus()) {\n await this.initialize(true);\n }\n }\n\n setSessionId(sessionId: number, deviceId?: string) {\n if (!this.identifiers) {\n this.loggerProvider.error('Session replay init has not been called, cannot set session id.');\n return;\n }\n\n if (deviceId) {\n this.identifiers.deviceId = deviceId;\n }\n // use a consistent device id.\n const deviceIdForReplayId = this.getDeviceId();\n if (sessionId && deviceIdForReplayId) {\n this.identifiers.sessionReplayId = generateSessionReplayId(sessionId, deviceIdForReplayId);\n } else {\n this.loggerProvider.error('Must provide either session replay id or session id when starting a new session.');\n return;\n }\n\n this.stopRecordingAndSendEvents(this.identifiers.sessionId);\n this.identifiers.sessionId = sessionId;\n this.events = [];\n this.currentSequenceId = 0;\n this.recordEvents();\n }\n\n getSessionReplayDebugPropertyValue() {\n let apiKeyHash = '';\n if (this.config) {\n apiKeyHash = generateHashCode(this.config.apiKey).toString();\n }\n return JSON.stringify({\n appHash: apiKeyHash,\n });\n }\n\n getSessionReplayProperties() {\n if (!this.config || !this.identifiers) {\n this.loggerProvider.error('Session replay init has not been called, cannot get session recording properties.');\n return {};\n }\n\n // If the user is in debug mode, ignore the focus handler when tagging events.\n // this is a common mishap when someone is developing locally and not seeing events getting tagged.\n const ignoreFocus = !!this.config.debugMode;\n const shouldRecord = this.getShouldRecord(ignoreFocus);\n\n if (shouldRecord) {\n const eventProperties: { [key: string]: string | null } = {\n [DEFAULT_SESSION_REPLAY_PROPERTY]: this.identifiers.sessionReplayId ? this.identifiers.sessionReplayId : null,\n };\n if (this.config.debugMode) {\n eventProperties[SESSION_REPLAY_DEBUG_PROPERTY] = this.getSessionReplayDebugPropertyValue();\n }\n return eventProperties;\n }\n\n return {};\n }\n\n blurListener = () => {\n this.stopRecordingAndSendEvents();\n };\n\n focusListener = () => {\n void this.initialize();\n };\n\n stopRecordingAndSendEvents(sessionId?: number) {\n try {\n this.stopRecordingEvents && this.stopRecordingEvents();\n this.stopRecordingEvents = null;\n } catch (error) {\n const typedError = error as Error;\n this.loggerProvider.warn(`Error occurred while stopping recording: ${typedError.toString()}`);\n }\n\n const sessionIdToSend = sessionId || this.identifiers?.sessionId;\n if (this.events.length && sessionIdToSend) {\n this.sendEventsList({\n events: this.events,\n sequenceId: this.currentSequenceId,\n sessionId: sessionIdToSend,\n });\n }\n }\n\n async initialize(shouldSendStoredEvents = false) {\n this.timeAtLastSend = Date.now(); // Initialize this so we have a point of comparison when events are recorded\n if (!this.identifiers?.sessionId) {\n this.loggerProvider.warn(`Session is not being recorded due to lack of session id.`);\n return;\n }\n const storedReplaySessions = this.sessionIDBStore && (await this.sessionIDBStore.getAllSessionDataFromStore());\n // This resolves a timing issue when focus is fired multiple times in short succession,\n // we only want the rest of this function to run once. We can be sure that initialize has\n // already been called if this.stopRecordingEvents is defined\n if (this.stopRecordingEvents) {\n return;\n }\n const storedSequencesForSession = storedReplaySessions && storedReplaySessions[this.identifiers.sessionId];\n if (storedReplaySessions && storedSequencesForSession && storedSequencesForSession.sessionSequences) {\n const storedSeqId = storedSequencesForSession.currentSequenceId;\n const lastSequence = storedSequencesForSession.sessionSequences[storedSeqId];\n if (lastSequence && lastSequence.status !== RecordingStatus.RECORDING) {\n this.currentSequenceId = storedSeqId + 1;\n this.events = [];\n } else {\n // Pick up recording where it was left off in another tab or window\n this.currentSequenceId = storedSeqId;\n this.events = lastSequence?.events || [];\n }\n }\n if (shouldSendStoredEvents && storedReplaySessions) {\n this.sendStoredEvents(storedReplaySessions);\n }\n this.recordEvents();\n }\n\n shouldOptOut() {\n let identityStoreOptOut: boolean | undefined;\n if (this.config?.instanceName) {\n const identityStore = getAnalyticsConnector(this.config.instanceName).identityStore;\n identityStoreOptOut = identityStore.getIdentity().optOut;\n }\n\n return identityStoreOptOut !== undefined ? identityStoreOptOut : this.config?.optOut;\n }\n\n getShouldRecord(ignoreFocus = false) {\n if (!this.identifiers || !this.config) {\n this.loggerProvider.error(`Session is not being recorded due to lack of config, please call sessionReplay.init.`);\n return false;\n }\n const globalScope = getGlobalScope();\n if (!ignoreFocus && globalScope && globalScope.document && !globalScope.document.hasFocus()) {\n if (this.identifiers.sessionId) {\n this.loggerProvider.log(\n `Session ${this.identifiers.sessionId} temporarily not recording due to lack of browser focus.`,\n );\n }\n return false;\n } else if (this.shouldOptOut()) {\n if (this.identifiers.sessionId) {\n this.loggerProvider.log(`Opting session ${this.identifiers.sessionId} out of recording due to optOut config.`);\n }\n return false;\n } else if (!this.identifiers.sessionId) {\n this.loggerProvider.warn(`Session is not being recorded due to lack of session id.`);\n return false;\n }\n\n const isInSample = isSessionInSample(this.identifiers.sessionId, this.config.sampleRate);\n if (!isInSample) {\n this.loggerProvider.log(`Opting session ${this.identifiers.sessionId} out of recording due to sample rate.`);\n }\n return isInSample;\n }\n\n getBlockSelectors(): string | string[] | undefined {\n return this.config?.privacyConfig?.blockSelector;\n }\n\n sendStoredEvents(storedReplaySessions: IDBStore) {\n for (const sessionId in storedReplaySessions) {\n const storedSequences = storedReplaySessions[sessionId].sessionSequences;\n for (const storedSeqId in storedSequences) {\n const seq = storedSequences[storedSeqId];\n const numericSeqId = parseInt(storedSeqId, 10);\n const numericSessionId = parseInt(sessionId, 10);\n if (numericSessionId === this.identifiers?.sessionId && numericSeqId === this.currentSequenceId) {\n continue;\n }\n\n if (seq.events && seq.events.length && seq.status === RecordingStatus.RECORDING) {\n this.sendEventsList({\n events: seq.events,\n sequenceId: numericSeqId,\n sessionId: numericSessionId,\n });\n }\n }\n }\n }\n\n recordEvents() {\n const shouldRecord = this.getShouldRecord();\n const sessionId = this.identifiers?.sessionId;\n if (!shouldRecord || !sessionId) {\n return;\n }\n this.stopRecordingEvents = record({\n emit: (event) => {\n const globalScope = getGlobalScope();\n if ((globalScope && globalScope.document && !globalScope.document.hasFocus()) || !this.getShouldRecord()) {\n this.stopRecordingAndSendEvents();\n return;\n }\n const eventString = JSON.stringify(event);\n\n const shouldSplit = this.shouldSplitEventsList(eventString);\n if (shouldSplit && this.config) {\n this.sendEventsList({\n events: this.events,\n sequenceId: this.currentSequenceId,\n sessionId: sessionId,\n });\n this.events = [];\n this.currentSequenceId++;\n }\n this.events.push(eventString);\n this.sessionIDBStore &&\n void this.sessionIDBStore.storeEventsForSession(this.events, this.currentSequenceId, sessionId);\n },\n packFn: pack,\n maskAllInputs: true,\n maskTextClass: MASK_TEXT_CLASS,\n blockClass: BLOCK_CLASS,\n // rrweb only exposes array type through its types, but arrays are also be supported. #class, ['#class', 'id']\n blockSelector: this.getBlockSelectors() as string,\n maskInputFn,\n recordCanvas: false,\n errorHandler: (error) => {\n const typedError = error as Error;\n this.loggerProvider.warn('Error while recording: ', typedError.toString());\n\n return true;\n },\n });\n }\n\n /**\n * Determines whether to send the events list to the backend and start a new\n * empty events list, based on the size of the list as well as the last time sent\n * @param nextEventString\n * @returns boolean\n */\n shouldSplitEventsList = (nextEventString: string): boolean => {\n const sizeOfNextEvent = new Blob([nextEventString]).size;\n const sizeOfEventsList = new Blob(this.events).size;\n if (sizeOfEventsList + sizeOfNextEvent >= this.maxPersistedEventsSize) {\n return true;\n }\n if (this.timeAtLastSend !== null && Date.now() - this.timeAtLastSend > this.interval && this.events.length) {\n this.interval = Math.min(MAX_INTERVAL, this.interval + MIN_INTERVAL);\n this.timeAtLastSend = Date.now();\n return true;\n }\n return false;\n };\n\n sendEventsList({ events, sequenceId, sessionId }: { events: string[]; sequenceId: number; sessionId: number }) {\n if (!this.config || !this.sessionIDBStore) {\n this.loggerProvider.error(`Session is not being recorded due to lack of config, please call sessionReplay.init.`);\n return;\n }\n this.trackDestination.sendEventsList({\n events: events,\n sequenceId: sequenceId,\n sessionId: sessionId,\n flushMaxRetries: this.config.flushMaxRetries,\n apiKey: this.config.apiKey,\n deviceId: this.getDeviceId(),\n sampleRate: this.config.sampleRate,\n serverZone: this.config.serverZone,\n onComplete: this.sessionIDBStore.cleanUpSessionEventsStore.bind(this.sessionIDBStore),\n });\n }\n\n getDeviceId() {\n let identityStoreDeviceId: string | undefined;\n if (this.config?.instanceName) {\n const identityStore = getAnalyticsConnector(this.config.instanceName).identityStore;\n identityStoreDeviceId = identityStore.getIdentity().deviceId;\n }\n\n return identityStoreDeviceId || this.identifiers?.deviceId;\n }\n\n getSessionId() {\n return this.identifiers?.sessionId;\n }\n\n async flush(useRetry = false) {\n if (this.trackDestination) {\n return this.trackDestination.flush(useRetry);\n }\n }\n\n shutdown() {\n const globalScope = getGlobalScope();\n if (globalScope) {\n globalScope.removeEventListener('blur', this.blurListener);\n globalScope.removeEventListener('focus', this.focusListener);\n }\n\n this.stopRecordingAndSendEvents();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session-replay.js","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"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","sourcesContent":["import { getAnalyticsConnector, getGlobalScope } from '@amplitude/analytics-client-common';\nimport { Logger, returnWrapper } from '@amplitude/analytics-core';\nimport { Logger as ILogger } from '@amplitude/analytics-types';\nimport { pack, record } from '@amplitude/rrweb';\nimport { SessionReplayConfig } from './config';\nimport {\n BLOCK_CLASS,\n DEFAULT_SESSION_REPLAY_PROPERTY,\n MASK_TEXT_CLASS,\n SESSION_REPLAY_DEBUG_PROPERTY,\n} from './constants';\nimport { SessionReplayEventsManager } from './events-manager';\nimport { generateHashCode, generateSessionReplayId, isSessionInSample, maskInputFn } from './helpers';\nimport { SessionIdentifiers } from './identifiers';\nimport {\n AmplitudeSessionReplay,\n SessionReplayEventsManager as AmplitudeSessionReplayEventsManager,\n SessionIdentifiers as ISessionIdentifiers,\n SessionReplayConfig as ISessionReplayConfig,\n SessionReplayOptions,\n} from './typings/session-replay';\n\nexport class SessionReplay implements AmplitudeSessionReplay {\n name = '@amplitude/session-replay-browser';\n config: ISessionReplayConfig | undefined;\n identifiers: ISessionIdentifiers | undefined;\n eventsManager: AmplitudeSessionReplayEventsManager | undefined;\n loggerProvider: ILogger;\n stopRecordingEvents: ReturnType<typeof record> | null = null;\n\n constructor() {\n this.loggerProvider = new Logger();\n }\n\n init(apiKey: string, options: SessionReplayOptions) {\n return returnWrapper(this._init(apiKey, options));\n }\n\n protected async _init(apiKey: string, options: SessionReplayOptions) {\n this.config = new SessionReplayConfig(apiKey, options);\n this.loggerProvider = this.config.loggerProvider;\n this.identifiers = new SessionIdentifiers(options, this.loggerProvider);\n\n this.eventsManager = new SessionReplayEventsManager({\n config: this.config,\n });\n\n this.loggerProvider.log('Installing @amplitude/session-replay-browser.');\n\n const globalScope = getGlobalScope();\n if (globalScope) {\n globalScope.addEventListener('blur', this.blurListener);\n globalScope.addEventListener('focus', this.focusListener);\n }\n\n if (globalScope && globalScope.document && globalScope.document.hasFocus()) {\n await this.initialize(true);\n }\n }\n\n setSessionId(sessionId: number, deviceId?: string) {\n if (!this.identifiers) {\n this.loggerProvider.error('Session replay init has not been called, cannot set session id.');\n return;\n }\n\n if (deviceId) {\n this.identifiers.deviceId = deviceId;\n }\n // use a consistent device id.\n const deviceIdForReplayId = this.getDeviceId();\n if (sessionId && deviceIdForReplayId) {\n this.identifiers.sessionReplayId = generateSessionReplayId(sessionId, deviceIdForReplayId);\n } else {\n this.loggerProvider.error('Must provide either session replay id or session id when starting a new session.');\n return;\n }\n\n this.stopRecordingAndSendEvents(this.identifiers.sessionId);\n this.identifiers.sessionId = sessionId;\n this.eventsManager && this.eventsManager.resetSequence();\n this.recordEvents();\n }\n\n getSessionReplayDebugPropertyValue() {\n let apiKeyHash = '';\n if (this.config) {\n apiKeyHash = generateHashCode(this.config.apiKey).toString();\n }\n return JSON.stringify({\n appHash: apiKeyHash,\n });\n }\n\n getSessionReplayProperties() {\n if (!this.config || !this.identifiers) {\n this.loggerProvider.error('Session replay init has not been called, cannot get session recording properties.');\n return {};\n }\n\n // If the user is in debug mode, ignore the focus handler when tagging events.\n // this is a common mishap when someone is developing locally and not seeing events getting tagged.\n const ignoreFocus = !!this.config.debugMode;\n const shouldRecord = this.getShouldRecord(ignoreFocus);\n\n if (shouldRecord) {\n const eventProperties: { [key: string]: string | null } = {\n [DEFAULT_SESSION_REPLAY_PROPERTY]: this.identifiers.sessionReplayId ? this.identifiers.sessionReplayId : null,\n };\n if (this.config.debugMode) {\n eventProperties[SESSION_REPLAY_DEBUG_PROPERTY] = this.getSessionReplayDebugPropertyValue();\n }\n return eventProperties;\n }\n\n return {};\n }\n\n blurListener = () => {\n this.stopRecordingAndSendEvents();\n };\n\n focusListener = () => {\n void this.initialize();\n };\n\n stopRecordingAndSendEvents(sessionId?: number) {\n try {\n this.stopRecordingEvents && this.stopRecordingEvents();\n this.stopRecordingEvents = null;\n } catch (error) {\n const typedError = error as Error;\n this.loggerProvider.warn(`Error occurred while stopping recording: ${typedError.toString()}`);\n }\n\n const sessionIdToSend = sessionId || this.identifiers?.sessionId;\n const deviceId = this.getDeviceId();\n this.eventsManager &&\n sessionIdToSend &&\n deviceId &&\n this.eventsManager.sendEvents({ sessionId: sessionIdToSend, deviceId });\n }\n\n async initialize(shouldSendStoredEvents = false) {\n if (!this.identifiers?.sessionId) {\n this.loggerProvider.warn(`Session is not being recorded due to lack of session id.`);\n return;\n }\n\n const deviceId = this.getDeviceId();\n this.eventsManager &&\n deviceId &&\n (await this.eventsManager.initialize({\n sessionId: this.identifiers.sessionId,\n shouldSendStoredEvents,\n deviceId,\n }));\n\n this.recordEvents();\n }\n\n shouldOptOut() {\n let identityStoreOptOut: boolean | undefined;\n if (this.config?.instanceName) {\n const identityStore = getAnalyticsConnector(this.config.instanceName).identityStore;\n identityStoreOptOut = identityStore.getIdentity().optOut;\n }\n\n return identityStoreOptOut !== undefined ? identityStoreOptOut : this.config?.optOut;\n }\n\n getShouldRecord(ignoreFocus = false) {\n if (!this.identifiers || !this.config) {\n this.loggerProvider.error(`Session is not being recorded due to lack of config, please call sessionReplay.init.`);\n return false;\n }\n const globalScope = getGlobalScope();\n if (!ignoreFocus && globalScope && globalScope.document && !globalScope.document.hasFocus()) {\n if (this.identifiers.sessionId) {\n this.loggerProvider.log(\n `Session ${this.identifiers.sessionId} temporarily not recording due to lack of browser focus.`,\n );\n }\n return false;\n } else if (this.shouldOptOut()) {\n if (this.identifiers.sessionId) {\n this.loggerProvider.log(`Opting session ${this.identifiers.sessionId} out of recording due to optOut config.`);\n }\n return false;\n } else if (!this.identifiers.sessionId) {\n this.loggerProvider.warn(`Session is not being recorded due to lack of session id.`);\n return false;\n }\n\n const isInSample = isSessionInSample(this.identifiers.sessionId, this.config.sampleRate);\n if (!isInSample) {\n this.loggerProvider.log(`Opting session ${this.identifiers.sessionId} out of recording due to sample rate.`);\n }\n return isInSample;\n }\n\n getBlockSelectors(): string | string[] | undefined {\n return this.config?.privacyConfig?.blockSelector;\n }\n\n recordEvents() {\n const shouldRecord = this.getShouldRecord();\n const sessionId = this.identifiers?.sessionId;\n if (!shouldRecord || !sessionId) {\n return;\n }\n this.stopRecordingEvents = record({\n emit: (event) => {\n const globalScope = getGlobalScope();\n if ((globalScope && globalScope.document && !globalScope.document.hasFocus()) || !this.getShouldRecord()) {\n this.stopRecordingAndSendEvents();\n return;\n }\n const eventString = JSON.stringify(event);\n const deviceId = this.getDeviceId();\n deviceId && this.eventsManager && this.eventsManager.addEvent({ event: eventString, sessionId, deviceId });\n },\n packFn: pack,\n maskAllInputs: true,\n maskTextClass: MASK_TEXT_CLASS,\n blockClass: BLOCK_CLASS,\n // rrweb only exposes array type through its types, but arrays are also be supported. #class, ['#class', 'id']\n blockSelector: this.getBlockSelectors() as string,\n maskInputFn,\n recordCanvas: false,\n errorHandler: (error) => {\n const typedError = error as Error;\n this.loggerProvider.warn('Error while recording: ', typedError.toString());\n\n return true;\n },\n });\n }\n\n getDeviceId() {\n let identityStoreDeviceId: string | undefined;\n if (this.config?.instanceName) {\n const identityStore = getAnalyticsConnector(this.config.instanceName).identityStore;\n identityStoreDeviceId = identityStore.getIdentity().deviceId;\n }\n\n return identityStoreDeviceId || this.identifiers?.deviceId;\n }\n\n getSessionId() {\n return this.identifiers?.sessionId;\n }\n\n async flush(useRetry = false) {\n if (this.eventsManager) {\n return this.eventsManager.flush(useRetry);\n }\n }\n\n shutdown() {\n const globalScope = getGlobalScope();\n if (globalScope) {\n globalScope.removeEventListener('blur', this.blurListener);\n globalScope.removeEventListener('focus', this.focusListener);\n }\n\n this.stopRecordingAndSendEvents();\n }\n}\n"]}
|
|
@@ -9,7 +9,6 @@ export declare class SessionReplayTrackDestination implements AmplitudeSessionRe
|
|
|
9
9
|
constructor({ loggerProvider }: {
|
|
10
10
|
loggerProvider: ILogger;
|
|
11
11
|
});
|
|
12
|
-
setLoggerProvider(loggerProvider: ILogger): void;
|
|
13
12
|
sendEventsList(destinationData: SessionReplayDestination): void;
|
|
14
13
|
getServerUrl(serverZone?: keyof typeof ServerZone): "https://api-sr.amplitude.com/sessions/v2/track" | "https://api-sr.eu.amplitude.com/sessions/v2/track" | "https://api-sr.stag2.amplitude.com//sessions/v2/track";
|
|
15
14
|
addToQueue(...list: SessionReplayDestinationContext[]): void;
|