@amplitude/plugin-session-replay-browser 0.1.0 → 0.1.2
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/session-replay.d.ts.map +1 -1
- package/lib/cjs/session-replay.js +41 -6
- package/lib/cjs/session-replay.js.map +1 -1
- package/lib/cjs/typings/session-replay.d.ts +3 -0
- package/lib/cjs/typings/session-replay.d.ts.map +1 -1
- package/lib/cjs/typings/session-replay.js.map +1 -1
- package/lib/esm/session-replay.d.ts.map +1 -1
- package/lib/esm/session-replay.js +42 -7
- package/lib/esm/session-replay.js.map +1 -1
- package/lib/esm/typings/session-replay.d.ts +3 -0
- 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/session-replay.d.ts.map +1 -1
- package/lib/scripts/typings/session-replay.d.ts +3 -0
- package/lib/scripts/typings/session-replay.d.ts.map +1 -1
- package/package.json +3 -4
- package/lib/cjs/helpers.d.ts +0 -2
- package/lib/cjs/helpers.d.ts.map +0 -1
- package/lib/cjs/helpers.js +0 -12
- package/lib/cjs/helpers.js.map +0 -1
- package/lib/esm/helpers.d.ts +0 -2
- package/lib/esm/helpers.d.ts.map +0 -1
- package/lib/esm/helpers.js +0 -9
- package/lib/esm/helpers.js.map +0 -1
- package/lib/scripts/helpers.d.ts +0 -2
- package/lib/scripts/helpers.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"AAMA,OAAO,EAKL,mBAAmB,EACpB,MAAM,0BAA0B,CAAC;AA6TlC,eAAO,MAAM,mBAAmB,EAAE,mBAEjC,CAAC"}
|
|
@@ -6,16 +6,18 @@ var analytics_types_1 = require("@amplitude/analytics-types");
|
|
|
6
6
|
var IDBKeyVal = tslib_1.__importStar(require("idb-keyval"));
|
|
7
7
|
var rrweb_1 = require("rrweb");
|
|
8
8
|
var constants_1 = require("./constants");
|
|
9
|
-
var helpers_1 = require("./helpers");
|
|
10
9
|
var messages_1 = require("./messages");
|
|
11
10
|
var SESSION_REPLAY_SERVER_URL = 'https://api-secure.amplitude.com/sessions/track';
|
|
12
11
|
var STORAGE_PREFIX = "".concat(analytics_core_1.AMPLITUDE_PREFIX, "_replay_unsent");
|
|
13
12
|
var PAYLOAD_ESTIMATED_SIZE_IN_BYTES_WITHOUT_EVENTS = 200; // derived by JSON stringifying an example payload without events
|
|
14
13
|
var MAX_EVENT_LIST_SIZE_IN_BYTES = 20 * 1000000 - PAYLOAD_ESTIMATED_SIZE_IN_BYTES_WITHOUT_EVENTS;
|
|
14
|
+
var MIN_INTERVAL = 1 * 1000; // 1 second
|
|
15
|
+
var MAX_INTERVAL = 10 * 1000; // 10 seconds
|
|
15
16
|
var SessionReplay = /** @class */ (function () {
|
|
16
17
|
function SessionReplay() {
|
|
18
|
+
var _this = this;
|
|
17
19
|
this.name = '@amplitude/plugin-session-replay-browser';
|
|
18
|
-
this.type =
|
|
20
|
+
this.type = 'enrichment';
|
|
19
21
|
this.storageKey = '';
|
|
20
22
|
this.retryTimeout = 1000;
|
|
21
23
|
this.events = [];
|
|
@@ -24,6 +26,26 @@ var SessionReplay = /** @class */ (function () {
|
|
|
24
26
|
this.queue = [];
|
|
25
27
|
this.stopRecordingEvents = null;
|
|
26
28
|
this.maxPersistedEventsSize = MAX_EVENT_LIST_SIZE_IN_BYTES;
|
|
29
|
+
this.interval = MIN_INTERVAL;
|
|
30
|
+
this.timeAtLastSend = null;
|
|
31
|
+
/**
|
|
32
|
+
* Determines whether to send the events list to the backend and start a new
|
|
33
|
+
* empty events list, based on the size of the list as well as the last time sent
|
|
34
|
+
* @param nextEventString
|
|
35
|
+
* @returns boolean
|
|
36
|
+
*/
|
|
37
|
+
this.shouldSplitEventsList = function (nextEventString) {
|
|
38
|
+
var sizeOfNextEvent = new Blob([nextEventString]).size;
|
|
39
|
+
var sizeOfEventsList = new Blob(_this.events).size;
|
|
40
|
+
if (sizeOfEventsList + sizeOfNextEvent >= _this.maxPersistedEventsSize) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
if (_this.timeAtLastSend !== null && Date.now() - _this.timeAtLastSend > _this.interval) {
|
|
44
|
+
_this.interval = Math.min(MAX_INTERVAL, _this.interval + MIN_INTERVAL);
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
};
|
|
27
49
|
}
|
|
28
50
|
SessionReplay.prototype.setup = function (config) {
|
|
29
51
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
@@ -41,8 +63,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
41
63
|
var _a;
|
|
42
64
|
return tslib_1.__generator(this, function (_b) {
|
|
43
65
|
event.event_properties = tslib_1.__assign(tslib_1.__assign({}, event.event_properties), (_a = {}, _a[constants_1.DEFAULT_SESSION_REPLAY_PROPERTY] = true, _a));
|
|
44
|
-
if (event.event_type === constants_1.DEFAULT_SESSION_START_EVENT
|
|
45
|
-
this.stopRecordingEvents();
|
|
66
|
+
if (event.event_type === constants_1.DEFAULT_SESSION_START_EVENT) {
|
|
46
67
|
this.recordEvents();
|
|
47
68
|
}
|
|
48
69
|
else if (event.event_type === constants_1.DEFAULT_SESSION_END_EVENT) {
|
|
@@ -53,6 +74,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
53
74
|
sessionId: event.session_id,
|
|
54
75
|
});
|
|
55
76
|
}
|
|
77
|
+
this.stopRecordingEvents && this.stopRecordingEvents();
|
|
56
78
|
this.events = [];
|
|
57
79
|
this.currentSequenceId = 0;
|
|
58
80
|
}
|
|
@@ -95,7 +117,18 @@ var SessionReplay = /** @class */ (function () {
|
|
|
95
117
|
this.stopRecordingEvents = (0, rrweb_1.record)({
|
|
96
118
|
emit: function (event) {
|
|
97
119
|
var eventString = JSON.stringify(event);
|
|
98
|
-
|
|
120
|
+
// Send the first two recorded events immediately
|
|
121
|
+
if (_this.events.length === 1 && _this.currentSequenceId === 0) {
|
|
122
|
+
_this.sendEventsList({
|
|
123
|
+
events: _this.events.concat(eventString),
|
|
124
|
+
sequenceId: _this.currentSequenceId,
|
|
125
|
+
sessionId: _this.config.sessionId,
|
|
126
|
+
});
|
|
127
|
+
_this.events = [];
|
|
128
|
+
_this.currentSequenceId++;
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
var shouldSplit = _this.shouldSplitEventsList(eventString);
|
|
99
132
|
if (shouldSplit) {
|
|
100
133
|
_this.sendEventsList({
|
|
101
134
|
events: _this.events,
|
|
@@ -109,6 +142,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
109
142
|
void _this.storeEventsForSession(_this.events, _this.currentSequenceId);
|
|
110
143
|
},
|
|
111
144
|
packFn: rrweb_1.pack,
|
|
145
|
+
maskAllInputs: true,
|
|
112
146
|
});
|
|
113
147
|
};
|
|
114
148
|
SessionReplay.prototype.sendEventsList = function (_a) {
|
|
@@ -141,7 +175,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
141
175
|
tryable.forEach(function (context) {
|
|
142
176
|
_this.queue = _this.queue.concat(context);
|
|
143
177
|
if (context.timeout === 0) {
|
|
144
|
-
_this.schedule(
|
|
178
|
+
_this.schedule(0);
|
|
145
179
|
return;
|
|
146
180
|
}
|
|
147
181
|
setTimeout(function () {
|
|
@@ -341,6 +375,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
341
375
|
this.config.loggerProvider.error(err);
|
|
342
376
|
}
|
|
343
377
|
else if (success) {
|
|
378
|
+
this.timeAtLastSend = Date.now();
|
|
344
379
|
this.config.loggerProvider.log(success);
|
|
345
380
|
}
|
|
346
381
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-replay.js","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"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","sourcesContent":["import { AMPLITUDE_PREFIX, BaseTransport } from '@amplitude/analytics-core';\nimport { BrowserConfig, Event, PluginType, Status } from '@amplitude/analytics-types';\nimport * as IDBKeyVal from 'idb-keyval';\nimport { pack, record } from 'rrweb';\nimport { DEFAULT_SESSION_END_EVENT, DEFAULT_SESSION_REPLAY_PROPERTY, DEFAULT_SESSION_START_EVENT } from './constants';\nimport { shouldSplitEventsList } from './helpers';\nimport { MAX_RETRIES_EXCEEDED_MESSAGE, STORAGE_FAILURE, SUCCESS_MESSAGE, UNEXPECTED_ERROR_MESSAGE } from './messages';\nimport {\n Events,\n IDBStore,\n SessionReplayContext,\n SessionReplayEnrichmentPlugin,\n SessionReplayPlugin,\n} from './typings/session-replay';\n\nconst SESSION_REPLAY_SERVER_URL = 'https://api-secure.amplitude.com/sessions/track';\nconst STORAGE_PREFIX = `${AMPLITUDE_PREFIX}_replay_unsent`;\nconst PAYLOAD_ESTIMATED_SIZE_IN_BYTES_WITHOUT_EVENTS = 200; // derived by JSON stringifying an example payload without events\nconst MAX_EVENT_LIST_SIZE_IN_BYTES = 20 * 1000000 - PAYLOAD_ESTIMATED_SIZE_IN_BYTES_WITHOUT_EVENTS;\n\nclass SessionReplay implements SessionReplayEnrichmentPlugin {\n name = '@amplitude/plugin-session-replay-browser';\n type = PluginType.ENRICHMENT as const;\n // this.config is defined in setup() which will always be called first\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n config: BrowserConfig;\n storageKey = '';\n retryTimeout = 1000;\n events: Events = [];\n currentSequenceId = 0;\n private scheduled: ReturnType<typeof setTimeout> | null = null;\n queue: SessionReplayContext[] = [];\n stopRecordingEvents: ReturnType<typeof record> | null = null;\n maxPersistedEventsSize = MAX_EVENT_LIST_SIZE_IN_BYTES;\n\n async setup(config: BrowserConfig) {\n config.loggerProvider.log('Installing @amplitude/plugin-session-replay.');\n\n this.config = config;\n this.storageKey = `${STORAGE_PREFIX}_${this.config.apiKey.substring(0, 10)}`;\n void this.emptyStoreAndReset();\n }\n\n async execute(event: Event) {\n event.event_properties = {\n ...event.event_properties,\n [DEFAULT_SESSION_REPLAY_PROPERTY]: true,\n };\n if (event.event_type === DEFAULT_SESSION_START_EVENT && this.stopRecordingEvents) {\n this.stopRecordingEvents();\n this.recordEvents();\n } else if (event.event_type === DEFAULT_SESSION_END_EVENT) {\n if (event.session_id) {\n this.sendEventsList({\n events: this.events,\n sequenceId: this.currentSequenceId,\n sessionId: event.session_id,\n });\n }\n this.events = [];\n this.currentSequenceId = 0;\n }\n return Promise.resolve(event);\n }\n\n async emptyStoreAndReset() {\n const storedReplaySessions = await this.getAllSessionEventsFromStore();\n if (storedReplaySessions) {\n for (const sessionId in storedReplaySessions) {\n const storedReplayEvents = storedReplaySessions[sessionId];\n if (storedReplayEvents.events.length) {\n this.sendEventsList({\n events: storedReplayEvents.events,\n sequenceId: storedReplayEvents.sequenceId,\n sessionId: parseInt(sessionId, 10),\n });\n }\n }\n this.events = [];\n const currentSessionStoredEvents = this.config.sessionId && storedReplaySessions[this.config.sessionId];\n this.currentSequenceId = currentSessionStoredEvents ? currentSessionStoredEvents.sequenceId + 1 : 0;\n void this.storeEventsForSession([], this.currentSequenceId);\n this.recordEvents();\n }\n }\n\n recordEvents() {\n this.stopRecordingEvents = record({\n emit: (event) => {\n const eventString = JSON.stringify(event);\n const shouldSplit = shouldSplitEventsList(this.events, eventString, this.maxPersistedEventsSize);\n if (shouldSplit) {\n this.sendEventsList({\n events: this.events,\n sequenceId: this.currentSequenceId,\n sessionId: this.config.sessionId as number,\n });\n this.events = [];\n this.currentSequenceId++;\n }\n this.events.push(eventString);\n void this.storeEventsForSession(this.events, this.currentSequenceId);\n },\n packFn: pack,\n });\n }\n\n sendEventsList({ events, sequenceId, sessionId }: { events: string[]; sequenceId: number; sessionId: number }) {\n this.addToQueue({\n events,\n sequenceId,\n attempts: 0,\n timeout: 0,\n sessionId,\n });\n }\n\n addToQueue(...list: SessionReplayContext[]) {\n const tryable = list.filter((context) => {\n if (context.attempts < this.config.flushMaxRetries) {\n context.attempts += 1;\n return true;\n }\n this.completeRequest({\n context,\n err: `${MAX_RETRIES_EXCEEDED_MESSAGE}, batch sequence id, ${context.sequenceId}`,\n });\n return false;\n });\n tryable.forEach((context) => {\n this.queue = this.queue.concat(context);\n if (context.timeout === 0) {\n this.schedule(this.config.flushIntervalMillis);\n return;\n }\n\n setTimeout(() => {\n context.timeout = 0;\n this.schedule(0);\n }, context.timeout);\n });\n }\n\n schedule(timeout: number) {\n if (this.scheduled) return;\n this.scheduled = setTimeout(() => {\n void this.flush(true).then(() => {\n if (this.queue.length > 0) {\n this.schedule(timeout);\n }\n });\n }, timeout);\n }\n\n async flush(useRetry = false) {\n const list: SessionReplayContext[] = [];\n const later: SessionReplayContext[] = [];\n this.queue.forEach((context) => (context.timeout === 0 ? list.push(context) : later.push(context)));\n this.queue = later;\n\n if (this.scheduled) {\n clearTimeout(this.scheduled);\n this.scheduled = null;\n }\n\n await Promise.all(list.map((context) => this.send(context, useRetry)));\n }\n\n async send(context: SessionReplayContext, useRetry = true) {\n const payload = {\n api_key: this.config.apiKey,\n device_id: this.config.deviceId,\n session_id: context.sessionId,\n start_timestamp: context.sessionId,\n events_batch: {\n version: 1,\n events: context.events,\n seq_number: context.sequenceId,\n },\n };\n try {\n const options: RequestInit = {\n headers: {\n 'Content-Type': 'application/json',\n Accept: '*/*',\n },\n body: JSON.stringify(payload),\n method: 'POST',\n };\n const res = await fetch(SESSION_REPLAY_SERVER_URL, options);\n if (res === null) {\n this.completeRequest({ context, err: UNEXPECTED_ERROR_MESSAGE, removeEvents: false });\n return;\n }\n if (!useRetry) {\n let responseBody = '';\n try {\n responseBody = JSON.stringify(res.body, null, 2);\n } catch {\n // to avoid crash, but don't care about the error, add comment to avoid empty block lint error\n }\n this.completeRequest({ context, success: `${res.status}: ${responseBody}` });\n } else {\n this.handleReponse(res.status, context);\n }\n } catch (e) {\n this.completeRequest({ context, err: e as string, removeEvents: false });\n }\n }\n\n handleReponse(status: number, context: SessionReplayContext) {\n const parsedStatus = new BaseTransport().buildStatus(status);\n switch (parsedStatus) {\n case Status.Success:\n this.handleSuccessResponse(context);\n break;\n default:\n this.handleOtherResponse(context);\n }\n }\n\n handleSuccessResponse(context: SessionReplayContext) {\n this.completeRequest({ context, success: SUCCESS_MESSAGE });\n }\n\n handleOtherResponse(context: SessionReplayContext) {\n this.addToQueue({\n ...context,\n timeout: context.attempts * this.retryTimeout,\n });\n }\n\n async getAllSessionEventsFromStore() {\n try {\n const storedReplaySessionContexts: IDBStore | undefined = await IDBKeyVal.get(this.storageKey);\n\n return storedReplaySessionContexts;\n } catch (e) {\n this.config.loggerProvider.error(`${STORAGE_FAILURE}: ${e as string}`);\n }\n return undefined;\n }\n\n async storeEventsForSession(events: Events, sequenceId: number) {\n try {\n await IDBKeyVal.update(this.storageKey, (sessionMap: IDBStore | undefined): IDBStore => {\n return {\n ...sessionMap,\n ...(this.config.sessionId && {\n [this.config.sessionId]: {\n events: events,\n sequenceId,\n },\n }),\n };\n });\n } catch (e) {\n this.config.loggerProvider.error(`${STORAGE_FAILURE}: ${e as string}`);\n }\n }\n\n async removeSessionEventsStore(sessionId: number) {\n try {\n await IDBKeyVal.update(this.storageKey, (sessionMap: IDBStore = {}): IDBStore => {\n delete sessionMap[sessionId];\n return sessionMap;\n });\n } catch (e) {\n this.config.loggerProvider.error(`${STORAGE_FAILURE}: ${e as string}`);\n }\n }\n\n completeRequest({\n context,\n err,\n success,\n removeEvents = true,\n }: {\n context: SessionReplayContext;\n err?: string;\n success?: string;\n removeEvents?: boolean;\n }) {\n removeEvents && context.sessionId && this.removeSessionEventsStore(context.sessionId);\n if (err) {\n this.config.loggerProvider.error(err);\n } else if (success) {\n this.config.loggerProvider.log(success);\n }\n }\n}\n\nexport const sessionReplayPlugin: SessionReplayPlugin = () => {\n return new SessionReplay();\n};\n"]}
|
|
1
|
+
{"version":3,"file":"session-replay.js","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"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","sourcesContent":["import { AMPLITUDE_PREFIX, BaseTransport } from '@amplitude/analytics-core';\nimport { BrowserConfig, Event, Status } from '@amplitude/analytics-types';\nimport * as IDBKeyVal from 'idb-keyval';\nimport { pack, record } from 'rrweb';\nimport { DEFAULT_SESSION_END_EVENT, DEFAULT_SESSION_REPLAY_PROPERTY, DEFAULT_SESSION_START_EVENT } from './constants';\nimport { MAX_RETRIES_EXCEEDED_MESSAGE, STORAGE_FAILURE, SUCCESS_MESSAGE, UNEXPECTED_ERROR_MESSAGE } from './messages';\nimport {\n Events,\n IDBStore,\n SessionReplayContext,\n SessionReplayEnrichmentPlugin,\n SessionReplayPlugin,\n} from './typings/session-replay';\n\nconst SESSION_REPLAY_SERVER_URL = 'https://api-secure.amplitude.com/sessions/track';\nconst STORAGE_PREFIX = `${AMPLITUDE_PREFIX}_replay_unsent`;\nconst PAYLOAD_ESTIMATED_SIZE_IN_BYTES_WITHOUT_EVENTS = 200; // derived by JSON stringifying an example payload without events\nconst MAX_EVENT_LIST_SIZE_IN_BYTES = 20 * 1000000 - PAYLOAD_ESTIMATED_SIZE_IN_BYTES_WITHOUT_EVENTS;\nconst MIN_INTERVAL = 1 * 1000; // 1 second\nconst MAX_INTERVAL = 10 * 1000; // 10 seconds\n\nclass SessionReplay implements SessionReplayEnrichmentPlugin {\n name = '@amplitude/plugin-session-replay-browser';\n type = 'enrichment' as const;\n // this.config is defined in setup() which will always be called first\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n config: BrowserConfig;\n storageKey = '';\n retryTimeout = 1000;\n events: Events = [];\n currentSequenceId = 0;\n private scheduled: ReturnType<typeof setTimeout> | null = null;\n queue: SessionReplayContext[] = [];\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 async setup(config: BrowserConfig) {\n config.loggerProvider.log('Installing @amplitude/plugin-session-replay.');\n\n this.config = config;\n this.storageKey = `${STORAGE_PREFIX}_${this.config.apiKey.substring(0, 10)}`;\n void this.emptyStoreAndReset();\n }\n\n async execute(event: Event) {\n event.event_properties = {\n ...event.event_properties,\n [DEFAULT_SESSION_REPLAY_PROPERTY]: true,\n };\n if (event.event_type === DEFAULT_SESSION_START_EVENT) {\n this.recordEvents();\n } else if (event.event_type === DEFAULT_SESSION_END_EVENT) {\n if (event.session_id) {\n this.sendEventsList({\n events: this.events,\n sequenceId: this.currentSequenceId,\n sessionId: event.session_id,\n });\n }\n this.stopRecordingEvents && this.stopRecordingEvents();\n this.events = [];\n this.currentSequenceId = 0;\n }\n return Promise.resolve(event);\n }\n\n async emptyStoreAndReset() {\n const storedReplaySessions = await this.getAllSessionEventsFromStore();\n if (storedReplaySessions) {\n for (const sessionId in storedReplaySessions) {\n const storedReplayEvents = storedReplaySessions[sessionId];\n if (storedReplayEvents.events.length) {\n this.sendEventsList({\n events: storedReplayEvents.events,\n sequenceId: storedReplayEvents.sequenceId,\n sessionId: parseInt(sessionId, 10),\n });\n }\n }\n this.events = [];\n const currentSessionStoredEvents = this.config.sessionId && storedReplaySessions[this.config.sessionId];\n this.currentSequenceId = currentSessionStoredEvents ? currentSessionStoredEvents.sequenceId + 1 : 0;\n void this.storeEventsForSession([], this.currentSequenceId);\n this.recordEvents();\n }\n }\n\n recordEvents() {\n this.stopRecordingEvents = record({\n emit: (event) => {\n const eventString = JSON.stringify(event);\n // Send the first two recorded events immediately\n if (this.events.length === 1 && this.currentSequenceId === 0) {\n this.sendEventsList({\n events: this.events.concat(eventString),\n sequenceId: this.currentSequenceId,\n sessionId: this.config.sessionId as number,\n });\n this.events = [];\n this.currentSequenceId++;\n return;\n }\n\n const shouldSplit = this.shouldSplitEventsList(eventString);\n if (shouldSplit) {\n this.sendEventsList({\n events: this.events,\n sequenceId: this.currentSequenceId,\n sessionId: this.config.sessionId as number,\n });\n this.events = [];\n this.currentSequenceId++;\n }\n this.events.push(eventString);\n void this.storeEventsForSession(this.events, this.currentSequenceId);\n },\n packFn: pack,\n maskAllInputs: true,\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) {\n this.interval = Math.min(MAX_INTERVAL, this.interval + MIN_INTERVAL);\n return true;\n }\n return false;\n };\n\n sendEventsList({ events, sequenceId, sessionId }: { events: string[]; sequenceId: number; sessionId: number }) {\n this.addToQueue({\n events,\n sequenceId,\n attempts: 0,\n timeout: 0,\n sessionId,\n });\n }\n\n addToQueue(...list: SessionReplayContext[]) {\n const tryable = list.filter((context) => {\n if (context.attempts < this.config.flushMaxRetries) {\n context.attempts += 1;\n return true;\n }\n this.completeRequest({\n context,\n err: `${MAX_RETRIES_EXCEEDED_MESSAGE}, batch sequence id, ${context.sequenceId}`,\n });\n return false;\n });\n tryable.forEach((context) => {\n this.queue = this.queue.concat(context);\n if (context.timeout === 0) {\n this.schedule(0);\n return;\n }\n\n setTimeout(() => {\n context.timeout = 0;\n this.schedule(0);\n }, context.timeout);\n });\n }\n\n schedule(timeout: number) {\n if (this.scheduled) return;\n this.scheduled = setTimeout(() => {\n void this.flush(true).then(() => {\n if (this.queue.length > 0) {\n this.schedule(timeout);\n }\n });\n }, timeout);\n }\n\n async flush(useRetry = false) {\n const list: SessionReplayContext[] = [];\n const later: SessionReplayContext[] = [];\n this.queue.forEach((context) => (context.timeout === 0 ? list.push(context) : later.push(context)));\n this.queue = later;\n\n if (this.scheduled) {\n clearTimeout(this.scheduled);\n this.scheduled = null;\n }\n\n await Promise.all(list.map((context) => this.send(context, useRetry)));\n }\n\n async send(context: SessionReplayContext, useRetry = true) {\n const payload = {\n api_key: this.config.apiKey,\n device_id: this.config.deviceId,\n session_id: context.sessionId,\n start_timestamp: context.sessionId,\n events_batch: {\n version: 1,\n events: context.events,\n seq_number: context.sequenceId,\n },\n };\n try {\n const options: RequestInit = {\n headers: {\n 'Content-Type': 'application/json',\n Accept: '*/*',\n },\n body: JSON.stringify(payload),\n method: 'POST',\n };\n const res = await fetch(SESSION_REPLAY_SERVER_URL, options);\n if (res === null) {\n this.completeRequest({ context, err: UNEXPECTED_ERROR_MESSAGE, removeEvents: false });\n return;\n }\n if (!useRetry) {\n let responseBody = '';\n try {\n responseBody = JSON.stringify(res.body, null, 2);\n } catch {\n // to avoid crash, but don't care about the error, add comment to avoid empty block lint error\n }\n this.completeRequest({ context, success: `${res.status}: ${responseBody}` });\n } else {\n this.handleReponse(res.status, context);\n }\n } catch (e) {\n this.completeRequest({ context, err: e as string, removeEvents: false });\n }\n }\n\n handleReponse(status: number, context: SessionReplayContext) {\n const parsedStatus = new BaseTransport().buildStatus(status);\n switch (parsedStatus) {\n case Status.Success:\n this.handleSuccessResponse(context);\n break;\n default:\n this.handleOtherResponse(context);\n }\n }\n\n handleSuccessResponse(context: SessionReplayContext) {\n this.completeRequest({ context, success: SUCCESS_MESSAGE });\n }\n\n handleOtherResponse(context: SessionReplayContext) {\n this.addToQueue({\n ...context,\n timeout: context.attempts * this.retryTimeout,\n });\n }\n\n async getAllSessionEventsFromStore() {\n try {\n const storedReplaySessionContexts: IDBStore | undefined = await IDBKeyVal.get(this.storageKey);\n\n return storedReplaySessionContexts;\n } catch (e) {\n this.config.loggerProvider.error(`${STORAGE_FAILURE}: ${e as string}`);\n }\n return undefined;\n }\n\n async storeEventsForSession(events: Events, sequenceId: number) {\n try {\n await IDBKeyVal.update(this.storageKey, (sessionMap: IDBStore | undefined): IDBStore => {\n return {\n ...sessionMap,\n ...(this.config.sessionId && {\n [this.config.sessionId]: {\n events: events,\n sequenceId,\n },\n }),\n };\n });\n } catch (e) {\n this.config.loggerProvider.error(`${STORAGE_FAILURE}: ${e as string}`);\n }\n }\n\n async removeSessionEventsStore(sessionId: number) {\n try {\n await IDBKeyVal.update(this.storageKey, (sessionMap: IDBStore = {}): IDBStore => {\n delete sessionMap[sessionId];\n return sessionMap;\n });\n } catch (e) {\n this.config.loggerProvider.error(`${STORAGE_FAILURE}: ${e as string}`);\n }\n }\n\n completeRequest({\n context,\n err,\n success,\n removeEvents = true,\n }: {\n context: SessionReplayContext;\n err?: string;\n success?: string;\n removeEvents?: boolean;\n }) {\n removeEvents && context.sessionId && this.removeSessionEventsStore(context.sessionId);\n if (err) {\n this.config.loggerProvider.error(err);\n } else if (success) {\n this.timeAtLastSend = Date.now();\n this.config.loggerProvider.log(success);\n }\n }\n}\n\nexport const sessionReplayPlugin: SessionReplayPlugin = () => {\n return new SessionReplay();\n};\n"]}
|
|
@@ -22,11 +22,14 @@ export interface SessionReplayEnrichmentPlugin extends EnrichmentPlugin {
|
|
|
22
22
|
retryTimeout: number;
|
|
23
23
|
events: Events;
|
|
24
24
|
currentSequenceId: number;
|
|
25
|
+
interval: number;
|
|
25
26
|
queue: SessionReplayContext[];
|
|
27
|
+
timeAtLastSend: number | null;
|
|
26
28
|
stopRecordingEvents: ReturnType<typeof record> | null;
|
|
27
29
|
maxPersistedEventsSize: number;
|
|
28
30
|
emptyStoreAndReset: () => Promise<void>;
|
|
29
31
|
recordEvents: () => void;
|
|
32
|
+
shouldSplitEventsList: (nextEventString: string) => boolean;
|
|
30
33
|
sendEventsList: ({ events, sequenceId, sessionId, }: {
|
|
31
34
|
events: string[];
|
|
32
35
|
sequenceId: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../../src/typings/session-replay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC5F,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAG/B,MAAM,WAAW,OAAO;CAAG;AAE3B,MAAM,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;AAE9B,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,CAAC,SAAS,EAAE,MAAM,GAAG;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AACD,MAAM,WAAW,6BAA8B,SAAQ,gBAAgB;IACrE,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC9B,mBAAmB,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,GAAG,IAAI,CAAC;IACtD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,kBAAkB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,cAAc,EAAE,CAAC,EACf,MAAM,EACN,UAAU,EACV,SAAS,GACV,EAAE;QACD,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KACnB,KAAK,IAAI,CAAC;IACX,UAAU,EAAE,CAAC,GAAG,IAAI,EAAE,oBAAoB,EAAE,KAAK,IAAI,CAAC;IACtD,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,KAAK,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,IAAI,EAAE,CAAC,OAAO,EAAE,oBAAoB,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,eAAe,CAAC,EACd,OAAO,EACP,GAAG,EACH,OAAO,EACP,YAAY,GACb,EAAE;QACD,OAAO,EAAE,oBAAoB,CAAC;QAC9B,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACzB,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC7B,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;KACpC,GAAG,IAAI,CAAC;IACT,4BAA4B,EAAE,MAAM,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IAClE,qBAAqB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,wBAAwB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,mBAAmB;IAClC,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,6BAA6B,CAAC;IAC1E,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,6BAA6B,CAAC;CACpD;AAED,MAAM,MAAM,6BAA6B,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../../src/typings/session-replay.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-replay.js","sourceRoot":"","sources":["../../../src/typings/session-replay.ts"],"names":[],"mappings":"","sourcesContent":["import { BrowserClient, BrowserConfig, EnrichmentPlugin } from '@amplitude/analytics-types';\nimport { record } from 'rrweb';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface Options {}\n\nexport type Events = string[];\n\nexport interface SessionReplayContext {\n events: Events;\n sequenceId: number;\n attempts: number;\n timeout: number;\n sessionId: number;\n}\n\nexport interface IDBStore {\n [sessionId: number]: {\n events: Events;\n sequenceId: number;\n };\n}\nexport interface SessionReplayEnrichmentPlugin extends EnrichmentPlugin {\n config: BrowserConfig;\n storageKey: string;\n retryTimeout: number;\n events: Events;\n currentSequenceId: number;\n queue: SessionReplayContext[];\n stopRecordingEvents: ReturnType<typeof record> | null;\n maxPersistedEventsSize: number;\n emptyStoreAndReset: () => Promise<void>;\n recordEvents: () => void;\n sendEventsList: ({\n events,\n sequenceId,\n sessionId,\n }: {\n events: string[];\n sequenceId: number;\n sessionId: number;\n }) => void;\n addToQueue: (...list: SessionReplayContext[]) => void;\n schedule: (timeout: number) => void;\n flush: (useRetry?: boolean) => Promise<void>;\n send: (context: SessionReplayContext, useRetry?: boolean) => Promise<void>;\n completeRequest({\n context,\n err,\n success,\n removeEvents,\n }: {\n context: SessionReplayContext;\n err?: string | undefined;\n success?: string | undefined;\n removeEvents?: boolean | undefined;\n }): void;\n getAllSessionEventsFromStore: () => Promise<IDBStore | undefined>;\n storeEventsForSession: (events: Events, sequenceId: number) => Promise<void>;\n removeSessionEventsStore: (sessionId: number) => Promise<void>;\n}\n\nexport interface SessionReplayPlugin {\n (client: BrowserClient, options?: Options): SessionReplayEnrichmentPlugin;\n (options?: Options): SessionReplayEnrichmentPlugin;\n}\n\nexport type SessionReplayPluginParameters = [BrowserClient, Options?] | [Options?];\n"]}
|
|
1
|
+
{"version":3,"file":"session-replay.js","sourceRoot":"","sources":["../../../src/typings/session-replay.ts"],"names":[],"mappings":"","sourcesContent":["import { BrowserClient, BrowserConfig, EnrichmentPlugin } from '@amplitude/analytics-types';\nimport { record } from 'rrweb';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface Options {}\n\nexport type Events = string[];\n\nexport interface SessionReplayContext {\n events: Events;\n sequenceId: number;\n attempts: number;\n timeout: number;\n sessionId: number;\n}\n\nexport interface IDBStore {\n [sessionId: number]: {\n events: Events;\n sequenceId: number;\n };\n}\nexport interface SessionReplayEnrichmentPlugin extends EnrichmentPlugin {\n config: BrowserConfig;\n storageKey: string;\n retryTimeout: number;\n events: Events;\n currentSequenceId: number;\n interval: number;\n queue: SessionReplayContext[];\n timeAtLastSend: number | null;\n stopRecordingEvents: ReturnType<typeof record> | null;\n maxPersistedEventsSize: number;\n emptyStoreAndReset: () => Promise<void>;\n recordEvents: () => void;\n shouldSplitEventsList: (nextEventString: string) => boolean;\n sendEventsList: ({\n events,\n sequenceId,\n sessionId,\n }: {\n events: string[];\n sequenceId: number;\n sessionId: number;\n }) => void;\n addToQueue: (...list: SessionReplayContext[]) => void;\n schedule: (timeout: number) => void;\n flush: (useRetry?: boolean) => Promise<void>;\n send: (context: SessionReplayContext, useRetry?: boolean) => Promise<void>;\n completeRequest({\n context,\n err,\n success,\n removeEvents,\n }: {\n context: SessionReplayContext;\n err?: string | undefined;\n success?: string | undefined;\n removeEvents?: boolean | undefined;\n }): void;\n getAllSessionEventsFromStore: () => Promise<IDBStore | undefined>;\n storeEventsForSession: (events: Events, sequenceId: number) => Promise<void>;\n removeSessionEventsStore: (sessionId: number) => Promise<void>;\n}\n\nexport interface SessionReplayPlugin {\n (client: BrowserClient, options?: Options): SessionReplayEnrichmentPlugin;\n (options?: Options): SessionReplayEnrichmentPlugin;\n}\n\nexport type SessionReplayPluginParameters = [BrowserClient, Options?] | [Options?];\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"AAMA,OAAO,EAKL,mBAAmB,EACpB,MAAM,0BAA0B,CAAC;AA6TlC,eAAO,MAAM,mBAAmB,EAAE,mBAEjC,CAAC"}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { __assign, __awaiter, __generator } from "tslib";
|
|
2
2
|
import { AMPLITUDE_PREFIX, BaseTransport } from '@amplitude/analytics-core';
|
|
3
|
-
import {
|
|
3
|
+
import { Status } from '@amplitude/analytics-types';
|
|
4
4
|
import * as IDBKeyVal from 'idb-keyval';
|
|
5
5
|
import { pack, record } from 'rrweb';
|
|
6
6
|
import { DEFAULT_SESSION_END_EVENT, DEFAULT_SESSION_REPLAY_PROPERTY, DEFAULT_SESSION_START_EVENT } from './constants';
|
|
7
|
-
import { shouldSplitEventsList } from './helpers';
|
|
8
7
|
import { MAX_RETRIES_EXCEEDED_MESSAGE, STORAGE_FAILURE, SUCCESS_MESSAGE, UNEXPECTED_ERROR_MESSAGE } from './messages';
|
|
9
8
|
var SESSION_REPLAY_SERVER_URL = 'https://api-secure.amplitude.com/sessions/track';
|
|
10
9
|
var STORAGE_PREFIX = "".concat(AMPLITUDE_PREFIX, "_replay_unsent");
|
|
11
10
|
var PAYLOAD_ESTIMATED_SIZE_IN_BYTES_WITHOUT_EVENTS = 200; // derived by JSON stringifying an example payload without events
|
|
12
11
|
var MAX_EVENT_LIST_SIZE_IN_BYTES = 20 * 1000000 - PAYLOAD_ESTIMATED_SIZE_IN_BYTES_WITHOUT_EVENTS;
|
|
12
|
+
var MIN_INTERVAL = 1 * 1000; // 1 second
|
|
13
|
+
var MAX_INTERVAL = 10 * 1000; // 10 seconds
|
|
13
14
|
var SessionReplay = /** @class */ (function () {
|
|
14
15
|
function SessionReplay() {
|
|
16
|
+
var _this = this;
|
|
15
17
|
this.name = '@amplitude/plugin-session-replay-browser';
|
|
16
|
-
this.type =
|
|
18
|
+
this.type = 'enrichment';
|
|
17
19
|
this.storageKey = '';
|
|
18
20
|
this.retryTimeout = 1000;
|
|
19
21
|
this.events = [];
|
|
@@ -22,6 +24,26 @@ var SessionReplay = /** @class */ (function () {
|
|
|
22
24
|
this.queue = [];
|
|
23
25
|
this.stopRecordingEvents = null;
|
|
24
26
|
this.maxPersistedEventsSize = MAX_EVENT_LIST_SIZE_IN_BYTES;
|
|
27
|
+
this.interval = MIN_INTERVAL;
|
|
28
|
+
this.timeAtLastSend = null;
|
|
29
|
+
/**
|
|
30
|
+
* Determines whether to send the events list to the backend and start a new
|
|
31
|
+
* empty events list, based on the size of the list as well as the last time sent
|
|
32
|
+
* @param nextEventString
|
|
33
|
+
* @returns boolean
|
|
34
|
+
*/
|
|
35
|
+
this.shouldSplitEventsList = function (nextEventString) {
|
|
36
|
+
var sizeOfNextEvent = new Blob([nextEventString]).size;
|
|
37
|
+
var sizeOfEventsList = new Blob(_this.events).size;
|
|
38
|
+
if (sizeOfEventsList + sizeOfNextEvent >= _this.maxPersistedEventsSize) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
if (_this.timeAtLastSend !== null && Date.now() - _this.timeAtLastSend > _this.interval) {
|
|
42
|
+
_this.interval = Math.min(MAX_INTERVAL, _this.interval + MIN_INTERVAL);
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
};
|
|
25
47
|
}
|
|
26
48
|
SessionReplay.prototype.setup = function (config) {
|
|
27
49
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -39,8 +61,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
39
61
|
var _a;
|
|
40
62
|
return __generator(this, function (_b) {
|
|
41
63
|
event.event_properties = __assign(__assign({}, event.event_properties), (_a = {}, _a[DEFAULT_SESSION_REPLAY_PROPERTY] = true, _a));
|
|
42
|
-
if (event.event_type === DEFAULT_SESSION_START_EVENT
|
|
43
|
-
this.stopRecordingEvents();
|
|
64
|
+
if (event.event_type === DEFAULT_SESSION_START_EVENT) {
|
|
44
65
|
this.recordEvents();
|
|
45
66
|
}
|
|
46
67
|
else if (event.event_type === DEFAULT_SESSION_END_EVENT) {
|
|
@@ -51,6 +72,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
51
72
|
sessionId: event.session_id,
|
|
52
73
|
});
|
|
53
74
|
}
|
|
75
|
+
this.stopRecordingEvents && this.stopRecordingEvents();
|
|
54
76
|
this.events = [];
|
|
55
77
|
this.currentSequenceId = 0;
|
|
56
78
|
}
|
|
@@ -93,7 +115,18 @@ var SessionReplay = /** @class */ (function () {
|
|
|
93
115
|
this.stopRecordingEvents = record({
|
|
94
116
|
emit: function (event) {
|
|
95
117
|
var eventString = JSON.stringify(event);
|
|
96
|
-
|
|
118
|
+
// Send the first two recorded events immediately
|
|
119
|
+
if (_this.events.length === 1 && _this.currentSequenceId === 0) {
|
|
120
|
+
_this.sendEventsList({
|
|
121
|
+
events: _this.events.concat(eventString),
|
|
122
|
+
sequenceId: _this.currentSequenceId,
|
|
123
|
+
sessionId: _this.config.sessionId,
|
|
124
|
+
});
|
|
125
|
+
_this.events = [];
|
|
126
|
+
_this.currentSequenceId++;
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
var shouldSplit = _this.shouldSplitEventsList(eventString);
|
|
97
130
|
if (shouldSplit) {
|
|
98
131
|
_this.sendEventsList({
|
|
99
132
|
events: _this.events,
|
|
@@ -107,6 +140,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
107
140
|
void _this.storeEventsForSession(_this.events, _this.currentSequenceId);
|
|
108
141
|
},
|
|
109
142
|
packFn: pack,
|
|
143
|
+
maskAllInputs: true,
|
|
110
144
|
});
|
|
111
145
|
};
|
|
112
146
|
SessionReplay.prototype.sendEventsList = function (_a) {
|
|
@@ -139,7 +173,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
139
173
|
tryable.forEach(function (context) {
|
|
140
174
|
_this.queue = _this.queue.concat(context);
|
|
141
175
|
if (context.timeout === 0) {
|
|
142
|
-
_this.schedule(
|
|
176
|
+
_this.schedule(0);
|
|
143
177
|
return;
|
|
144
178
|
}
|
|
145
179
|
setTimeout(function () {
|
|
@@ -339,6 +373,7 @@ var SessionReplay = /** @class */ (function () {
|
|
|
339
373
|
this.config.loggerProvider.error(err);
|
|
340
374
|
}
|
|
341
375
|
else if (success) {
|
|
376
|
+
this.timeAtLastSend = Date.now();
|
|
342
377
|
this.config.loggerProvider.log(success);
|
|
343
378
|
}
|
|
344
379
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-replay.js","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"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","sourcesContent":["import { AMPLITUDE_PREFIX, BaseTransport } from '@amplitude/analytics-core';\nimport { BrowserConfig, Event, PluginType, Status } from '@amplitude/analytics-types';\nimport * as IDBKeyVal from 'idb-keyval';\nimport { pack, record } from 'rrweb';\nimport { DEFAULT_SESSION_END_EVENT, DEFAULT_SESSION_REPLAY_PROPERTY, DEFAULT_SESSION_START_EVENT } from './constants';\nimport { shouldSplitEventsList } from './helpers';\nimport { MAX_RETRIES_EXCEEDED_MESSAGE, STORAGE_FAILURE, SUCCESS_MESSAGE, UNEXPECTED_ERROR_MESSAGE } from './messages';\nimport {\n Events,\n IDBStore,\n SessionReplayContext,\n SessionReplayEnrichmentPlugin,\n SessionReplayPlugin,\n} from './typings/session-replay';\n\nconst SESSION_REPLAY_SERVER_URL = 'https://api-secure.amplitude.com/sessions/track';\nconst STORAGE_PREFIX = `${AMPLITUDE_PREFIX}_replay_unsent`;\nconst PAYLOAD_ESTIMATED_SIZE_IN_BYTES_WITHOUT_EVENTS = 200; // derived by JSON stringifying an example payload without events\nconst MAX_EVENT_LIST_SIZE_IN_BYTES = 20 * 1000000 - PAYLOAD_ESTIMATED_SIZE_IN_BYTES_WITHOUT_EVENTS;\n\nclass SessionReplay implements SessionReplayEnrichmentPlugin {\n name = '@amplitude/plugin-session-replay-browser';\n type = PluginType.ENRICHMENT as const;\n // this.config is defined in setup() which will always be called first\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n config: BrowserConfig;\n storageKey = '';\n retryTimeout = 1000;\n events: Events = [];\n currentSequenceId = 0;\n private scheduled: ReturnType<typeof setTimeout> | null = null;\n queue: SessionReplayContext[] = [];\n stopRecordingEvents: ReturnType<typeof record> | null = null;\n maxPersistedEventsSize = MAX_EVENT_LIST_SIZE_IN_BYTES;\n\n async setup(config: BrowserConfig) {\n config.loggerProvider.log('Installing @amplitude/plugin-session-replay.');\n\n this.config = config;\n this.storageKey = `${STORAGE_PREFIX}_${this.config.apiKey.substring(0, 10)}`;\n void this.emptyStoreAndReset();\n }\n\n async execute(event: Event) {\n event.event_properties = {\n ...event.event_properties,\n [DEFAULT_SESSION_REPLAY_PROPERTY]: true,\n };\n if (event.event_type === DEFAULT_SESSION_START_EVENT && this.stopRecordingEvents) {\n this.stopRecordingEvents();\n this.recordEvents();\n } else if (event.event_type === DEFAULT_SESSION_END_EVENT) {\n if (event.session_id) {\n this.sendEventsList({\n events: this.events,\n sequenceId: this.currentSequenceId,\n sessionId: event.session_id,\n });\n }\n this.events = [];\n this.currentSequenceId = 0;\n }\n return Promise.resolve(event);\n }\n\n async emptyStoreAndReset() {\n const storedReplaySessions = await this.getAllSessionEventsFromStore();\n if (storedReplaySessions) {\n for (const sessionId in storedReplaySessions) {\n const storedReplayEvents = storedReplaySessions[sessionId];\n if (storedReplayEvents.events.length) {\n this.sendEventsList({\n events: storedReplayEvents.events,\n sequenceId: storedReplayEvents.sequenceId,\n sessionId: parseInt(sessionId, 10),\n });\n }\n }\n this.events = [];\n const currentSessionStoredEvents = this.config.sessionId && storedReplaySessions[this.config.sessionId];\n this.currentSequenceId = currentSessionStoredEvents ? currentSessionStoredEvents.sequenceId + 1 : 0;\n void this.storeEventsForSession([], this.currentSequenceId);\n this.recordEvents();\n }\n }\n\n recordEvents() {\n this.stopRecordingEvents = record({\n emit: (event) => {\n const eventString = JSON.stringify(event);\n const shouldSplit = shouldSplitEventsList(this.events, eventString, this.maxPersistedEventsSize);\n if (shouldSplit) {\n this.sendEventsList({\n events: this.events,\n sequenceId: this.currentSequenceId,\n sessionId: this.config.sessionId as number,\n });\n this.events = [];\n this.currentSequenceId++;\n }\n this.events.push(eventString);\n void this.storeEventsForSession(this.events, this.currentSequenceId);\n },\n packFn: pack,\n });\n }\n\n sendEventsList({ events, sequenceId, sessionId }: { events: string[]; sequenceId: number; sessionId: number }) {\n this.addToQueue({\n events,\n sequenceId,\n attempts: 0,\n timeout: 0,\n sessionId,\n });\n }\n\n addToQueue(...list: SessionReplayContext[]) {\n const tryable = list.filter((context) => {\n if (context.attempts < this.config.flushMaxRetries) {\n context.attempts += 1;\n return true;\n }\n this.completeRequest({\n context,\n err: `${MAX_RETRIES_EXCEEDED_MESSAGE}, batch sequence id, ${context.sequenceId}`,\n });\n return false;\n });\n tryable.forEach((context) => {\n this.queue = this.queue.concat(context);\n if (context.timeout === 0) {\n this.schedule(this.config.flushIntervalMillis);\n return;\n }\n\n setTimeout(() => {\n context.timeout = 0;\n this.schedule(0);\n }, context.timeout);\n });\n }\n\n schedule(timeout: number) {\n if (this.scheduled) return;\n this.scheduled = setTimeout(() => {\n void this.flush(true).then(() => {\n if (this.queue.length > 0) {\n this.schedule(timeout);\n }\n });\n }, timeout);\n }\n\n async flush(useRetry = false) {\n const list: SessionReplayContext[] = [];\n const later: SessionReplayContext[] = [];\n this.queue.forEach((context) => (context.timeout === 0 ? list.push(context) : later.push(context)));\n this.queue = later;\n\n if (this.scheduled) {\n clearTimeout(this.scheduled);\n this.scheduled = null;\n }\n\n await Promise.all(list.map((context) => this.send(context, useRetry)));\n }\n\n async send(context: SessionReplayContext, useRetry = true) {\n const payload = {\n api_key: this.config.apiKey,\n device_id: this.config.deviceId,\n session_id: context.sessionId,\n start_timestamp: context.sessionId,\n events_batch: {\n version: 1,\n events: context.events,\n seq_number: context.sequenceId,\n },\n };\n try {\n const options: RequestInit = {\n headers: {\n 'Content-Type': 'application/json',\n Accept: '*/*',\n },\n body: JSON.stringify(payload),\n method: 'POST',\n };\n const res = await fetch(SESSION_REPLAY_SERVER_URL, options);\n if (res === null) {\n this.completeRequest({ context, err: UNEXPECTED_ERROR_MESSAGE, removeEvents: false });\n return;\n }\n if (!useRetry) {\n let responseBody = '';\n try {\n responseBody = JSON.stringify(res.body, null, 2);\n } catch {\n // to avoid crash, but don't care about the error, add comment to avoid empty block lint error\n }\n this.completeRequest({ context, success: `${res.status}: ${responseBody}` });\n } else {\n this.handleReponse(res.status, context);\n }\n } catch (e) {\n this.completeRequest({ context, err: e as string, removeEvents: false });\n }\n }\n\n handleReponse(status: number, context: SessionReplayContext) {\n const parsedStatus = new BaseTransport().buildStatus(status);\n switch (parsedStatus) {\n case Status.Success:\n this.handleSuccessResponse(context);\n break;\n default:\n this.handleOtherResponse(context);\n }\n }\n\n handleSuccessResponse(context: SessionReplayContext) {\n this.completeRequest({ context, success: SUCCESS_MESSAGE });\n }\n\n handleOtherResponse(context: SessionReplayContext) {\n this.addToQueue({\n ...context,\n timeout: context.attempts * this.retryTimeout,\n });\n }\n\n async getAllSessionEventsFromStore() {\n try {\n const storedReplaySessionContexts: IDBStore | undefined = await IDBKeyVal.get(this.storageKey);\n\n return storedReplaySessionContexts;\n } catch (e) {\n this.config.loggerProvider.error(`${STORAGE_FAILURE}: ${e as string}`);\n }\n return undefined;\n }\n\n async storeEventsForSession(events: Events, sequenceId: number) {\n try {\n await IDBKeyVal.update(this.storageKey, (sessionMap: IDBStore | undefined): IDBStore => {\n return {\n ...sessionMap,\n ...(this.config.sessionId && {\n [this.config.sessionId]: {\n events: events,\n sequenceId,\n },\n }),\n };\n });\n } catch (e) {\n this.config.loggerProvider.error(`${STORAGE_FAILURE}: ${e as string}`);\n }\n }\n\n async removeSessionEventsStore(sessionId: number) {\n try {\n await IDBKeyVal.update(this.storageKey, (sessionMap: IDBStore = {}): IDBStore => {\n delete sessionMap[sessionId];\n return sessionMap;\n });\n } catch (e) {\n this.config.loggerProvider.error(`${STORAGE_FAILURE}: ${e as string}`);\n }\n }\n\n completeRequest({\n context,\n err,\n success,\n removeEvents = true,\n }: {\n context: SessionReplayContext;\n err?: string;\n success?: string;\n removeEvents?: boolean;\n }) {\n removeEvents && context.sessionId && this.removeSessionEventsStore(context.sessionId);\n if (err) {\n this.config.loggerProvider.error(err);\n } else if (success) {\n this.config.loggerProvider.log(success);\n }\n }\n}\n\nexport const sessionReplayPlugin: SessionReplayPlugin = () => {\n return new SessionReplay();\n};\n"]}
|
|
1
|
+
{"version":3,"file":"session-replay.js","sourceRoot":"","sources":["../../src/session-replay.ts"],"names":[],"mappings":"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","sourcesContent":["import { AMPLITUDE_PREFIX, BaseTransport } from '@amplitude/analytics-core';\nimport { BrowserConfig, Event, Status } from '@amplitude/analytics-types';\nimport * as IDBKeyVal from 'idb-keyval';\nimport { pack, record } from 'rrweb';\nimport { DEFAULT_SESSION_END_EVENT, DEFAULT_SESSION_REPLAY_PROPERTY, DEFAULT_SESSION_START_EVENT } from './constants';\nimport { MAX_RETRIES_EXCEEDED_MESSAGE, STORAGE_FAILURE, SUCCESS_MESSAGE, UNEXPECTED_ERROR_MESSAGE } from './messages';\nimport {\n Events,\n IDBStore,\n SessionReplayContext,\n SessionReplayEnrichmentPlugin,\n SessionReplayPlugin,\n} from './typings/session-replay';\n\nconst SESSION_REPLAY_SERVER_URL = 'https://api-secure.amplitude.com/sessions/track';\nconst STORAGE_PREFIX = `${AMPLITUDE_PREFIX}_replay_unsent`;\nconst PAYLOAD_ESTIMATED_SIZE_IN_BYTES_WITHOUT_EVENTS = 200; // derived by JSON stringifying an example payload without events\nconst MAX_EVENT_LIST_SIZE_IN_BYTES = 20 * 1000000 - PAYLOAD_ESTIMATED_SIZE_IN_BYTES_WITHOUT_EVENTS;\nconst MIN_INTERVAL = 1 * 1000; // 1 second\nconst MAX_INTERVAL = 10 * 1000; // 10 seconds\n\nclass SessionReplay implements SessionReplayEnrichmentPlugin {\n name = '@amplitude/plugin-session-replay-browser';\n type = 'enrichment' as const;\n // this.config is defined in setup() which will always be called first\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n config: BrowserConfig;\n storageKey = '';\n retryTimeout = 1000;\n events: Events = [];\n currentSequenceId = 0;\n private scheduled: ReturnType<typeof setTimeout> | null = null;\n queue: SessionReplayContext[] = [];\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 async setup(config: BrowserConfig) {\n config.loggerProvider.log('Installing @amplitude/plugin-session-replay.');\n\n this.config = config;\n this.storageKey = `${STORAGE_PREFIX}_${this.config.apiKey.substring(0, 10)}`;\n void this.emptyStoreAndReset();\n }\n\n async execute(event: Event) {\n event.event_properties = {\n ...event.event_properties,\n [DEFAULT_SESSION_REPLAY_PROPERTY]: true,\n };\n if (event.event_type === DEFAULT_SESSION_START_EVENT) {\n this.recordEvents();\n } else if (event.event_type === DEFAULT_SESSION_END_EVENT) {\n if (event.session_id) {\n this.sendEventsList({\n events: this.events,\n sequenceId: this.currentSequenceId,\n sessionId: event.session_id,\n });\n }\n this.stopRecordingEvents && this.stopRecordingEvents();\n this.events = [];\n this.currentSequenceId = 0;\n }\n return Promise.resolve(event);\n }\n\n async emptyStoreAndReset() {\n const storedReplaySessions = await this.getAllSessionEventsFromStore();\n if (storedReplaySessions) {\n for (const sessionId in storedReplaySessions) {\n const storedReplayEvents = storedReplaySessions[sessionId];\n if (storedReplayEvents.events.length) {\n this.sendEventsList({\n events: storedReplayEvents.events,\n sequenceId: storedReplayEvents.sequenceId,\n sessionId: parseInt(sessionId, 10),\n });\n }\n }\n this.events = [];\n const currentSessionStoredEvents = this.config.sessionId && storedReplaySessions[this.config.sessionId];\n this.currentSequenceId = currentSessionStoredEvents ? currentSessionStoredEvents.sequenceId + 1 : 0;\n void this.storeEventsForSession([], this.currentSequenceId);\n this.recordEvents();\n }\n }\n\n recordEvents() {\n this.stopRecordingEvents = record({\n emit: (event) => {\n const eventString = JSON.stringify(event);\n // Send the first two recorded events immediately\n if (this.events.length === 1 && this.currentSequenceId === 0) {\n this.sendEventsList({\n events: this.events.concat(eventString),\n sequenceId: this.currentSequenceId,\n sessionId: this.config.sessionId as number,\n });\n this.events = [];\n this.currentSequenceId++;\n return;\n }\n\n const shouldSplit = this.shouldSplitEventsList(eventString);\n if (shouldSplit) {\n this.sendEventsList({\n events: this.events,\n sequenceId: this.currentSequenceId,\n sessionId: this.config.sessionId as number,\n });\n this.events = [];\n this.currentSequenceId++;\n }\n this.events.push(eventString);\n void this.storeEventsForSession(this.events, this.currentSequenceId);\n },\n packFn: pack,\n maskAllInputs: true,\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) {\n this.interval = Math.min(MAX_INTERVAL, this.interval + MIN_INTERVAL);\n return true;\n }\n return false;\n };\n\n sendEventsList({ events, sequenceId, sessionId }: { events: string[]; sequenceId: number; sessionId: number }) {\n this.addToQueue({\n events,\n sequenceId,\n attempts: 0,\n timeout: 0,\n sessionId,\n });\n }\n\n addToQueue(...list: SessionReplayContext[]) {\n const tryable = list.filter((context) => {\n if (context.attempts < this.config.flushMaxRetries) {\n context.attempts += 1;\n return true;\n }\n this.completeRequest({\n context,\n err: `${MAX_RETRIES_EXCEEDED_MESSAGE}, batch sequence id, ${context.sequenceId}`,\n });\n return false;\n });\n tryable.forEach((context) => {\n this.queue = this.queue.concat(context);\n if (context.timeout === 0) {\n this.schedule(0);\n return;\n }\n\n setTimeout(() => {\n context.timeout = 0;\n this.schedule(0);\n }, context.timeout);\n });\n }\n\n schedule(timeout: number) {\n if (this.scheduled) return;\n this.scheduled = setTimeout(() => {\n void this.flush(true).then(() => {\n if (this.queue.length > 0) {\n this.schedule(timeout);\n }\n });\n }, timeout);\n }\n\n async flush(useRetry = false) {\n const list: SessionReplayContext[] = [];\n const later: SessionReplayContext[] = [];\n this.queue.forEach((context) => (context.timeout === 0 ? list.push(context) : later.push(context)));\n this.queue = later;\n\n if (this.scheduled) {\n clearTimeout(this.scheduled);\n this.scheduled = null;\n }\n\n await Promise.all(list.map((context) => this.send(context, useRetry)));\n }\n\n async send(context: SessionReplayContext, useRetry = true) {\n const payload = {\n api_key: this.config.apiKey,\n device_id: this.config.deviceId,\n session_id: context.sessionId,\n start_timestamp: context.sessionId,\n events_batch: {\n version: 1,\n events: context.events,\n seq_number: context.sequenceId,\n },\n };\n try {\n const options: RequestInit = {\n headers: {\n 'Content-Type': 'application/json',\n Accept: '*/*',\n },\n body: JSON.stringify(payload),\n method: 'POST',\n };\n const res = await fetch(SESSION_REPLAY_SERVER_URL, options);\n if (res === null) {\n this.completeRequest({ context, err: UNEXPECTED_ERROR_MESSAGE, removeEvents: false });\n return;\n }\n if (!useRetry) {\n let responseBody = '';\n try {\n responseBody = JSON.stringify(res.body, null, 2);\n } catch {\n // to avoid crash, but don't care about the error, add comment to avoid empty block lint error\n }\n this.completeRequest({ context, success: `${res.status}: ${responseBody}` });\n } else {\n this.handleReponse(res.status, context);\n }\n } catch (e) {\n this.completeRequest({ context, err: e as string, removeEvents: false });\n }\n }\n\n handleReponse(status: number, context: SessionReplayContext) {\n const parsedStatus = new BaseTransport().buildStatus(status);\n switch (parsedStatus) {\n case Status.Success:\n this.handleSuccessResponse(context);\n break;\n default:\n this.handleOtherResponse(context);\n }\n }\n\n handleSuccessResponse(context: SessionReplayContext) {\n this.completeRequest({ context, success: SUCCESS_MESSAGE });\n }\n\n handleOtherResponse(context: SessionReplayContext) {\n this.addToQueue({\n ...context,\n timeout: context.attempts * this.retryTimeout,\n });\n }\n\n async getAllSessionEventsFromStore() {\n try {\n const storedReplaySessionContexts: IDBStore | undefined = await IDBKeyVal.get(this.storageKey);\n\n return storedReplaySessionContexts;\n } catch (e) {\n this.config.loggerProvider.error(`${STORAGE_FAILURE}: ${e as string}`);\n }\n return undefined;\n }\n\n async storeEventsForSession(events: Events, sequenceId: number) {\n try {\n await IDBKeyVal.update(this.storageKey, (sessionMap: IDBStore | undefined): IDBStore => {\n return {\n ...sessionMap,\n ...(this.config.sessionId && {\n [this.config.sessionId]: {\n events: events,\n sequenceId,\n },\n }),\n };\n });\n } catch (e) {\n this.config.loggerProvider.error(`${STORAGE_FAILURE}: ${e as string}`);\n }\n }\n\n async removeSessionEventsStore(sessionId: number) {\n try {\n await IDBKeyVal.update(this.storageKey, (sessionMap: IDBStore = {}): IDBStore => {\n delete sessionMap[sessionId];\n return sessionMap;\n });\n } catch (e) {\n this.config.loggerProvider.error(`${STORAGE_FAILURE}: ${e as string}`);\n }\n }\n\n completeRequest({\n context,\n err,\n success,\n removeEvents = true,\n }: {\n context: SessionReplayContext;\n err?: string;\n success?: string;\n removeEvents?: boolean;\n }) {\n removeEvents && context.sessionId && this.removeSessionEventsStore(context.sessionId);\n if (err) {\n this.config.loggerProvider.error(err);\n } else if (success) {\n this.timeAtLastSend = Date.now();\n this.config.loggerProvider.log(success);\n }\n }\n}\n\nexport const sessionReplayPlugin: SessionReplayPlugin = () => {\n return new SessionReplay();\n};\n"]}
|
|
@@ -22,11 +22,14 @@ export interface SessionReplayEnrichmentPlugin extends EnrichmentPlugin {
|
|
|
22
22
|
retryTimeout: number;
|
|
23
23
|
events: Events;
|
|
24
24
|
currentSequenceId: number;
|
|
25
|
+
interval: number;
|
|
25
26
|
queue: SessionReplayContext[];
|
|
27
|
+
timeAtLastSend: number | null;
|
|
26
28
|
stopRecordingEvents: ReturnType<typeof record> | null;
|
|
27
29
|
maxPersistedEventsSize: number;
|
|
28
30
|
emptyStoreAndReset: () => Promise<void>;
|
|
29
31
|
recordEvents: () => void;
|
|
32
|
+
shouldSplitEventsList: (nextEventString: string) => boolean;
|
|
30
33
|
sendEventsList: ({ events, sequenceId, sessionId, }: {
|
|
31
34
|
events: string[];
|
|
32
35
|
sequenceId: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../../src/typings/session-replay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC5F,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAG/B,MAAM,WAAW,OAAO;CAAG;AAE3B,MAAM,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;AAE9B,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,CAAC,SAAS,EAAE,MAAM,GAAG;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AACD,MAAM,WAAW,6BAA8B,SAAQ,gBAAgB;IACrE,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC9B,mBAAmB,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,GAAG,IAAI,CAAC;IACtD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,kBAAkB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,cAAc,EAAE,CAAC,EACf,MAAM,EACN,UAAU,EACV,SAAS,GACV,EAAE;QACD,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KACnB,KAAK,IAAI,CAAC;IACX,UAAU,EAAE,CAAC,GAAG,IAAI,EAAE,oBAAoB,EAAE,KAAK,IAAI,CAAC;IACtD,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,KAAK,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,IAAI,EAAE,CAAC,OAAO,EAAE,oBAAoB,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,eAAe,CAAC,EACd,OAAO,EACP,GAAG,EACH,OAAO,EACP,YAAY,GACb,EAAE;QACD,OAAO,EAAE,oBAAoB,CAAC;QAC9B,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACzB,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC7B,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;KACpC,GAAG,IAAI,CAAC;IACT,4BAA4B,EAAE,MAAM,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IAClE,qBAAqB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,wBAAwB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,mBAAmB;IAClC,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,6BAA6B,CAAC;IAC1E,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,6BAA6B,CAAC;CACpD;AAED,MAAM,MAAM,6BAA6B,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"session-replay.d.ts","sourceRoot":"","sources":["../../../src/typings/session-replay.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-replay.js","sourceRoot":"","sources":["../../../src/typings/session-replay.ts"],"names":[],"mappings":"","sourcesContent":["import { BrowserClient, BrowserConfig, EnrichmentPlugin } from '@amplitude/analytics-types';\nimport { record } from 'rrweb';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface Options {}\n\nexport type Events = string[];\n\nexport interface SessionReplayContext {\n events: Events;\n sequenceId: number;\n attempts: number;\n timeout: number;\n sessionId: number;\n}\n\nexport interface IDBStore {\n [sessionId: number]: {\n events: Events;\n sequenceId: number;\n };\n}\nexport interface SessionReplayEnrichmentPlugin extends EnrichmentPlugin {\n config: BrowserConfig;\n storageKey: string;\n retryTimeout: number;\n events: Events;\n currentSequenceId: number;\n queue: SessionReplayContext[];\n stopRecordingEvents: ReturnType<typeof record> | null;\n maxPersistedEventsSize: number;\n emptyStoreAndReset: () => Promise<void>;\n recordEvents: () => void;\n sendEventsList: ({\n events,\n sequenceId,\n sessionId,\n }: {\n events: string[];\n sequenceId: number;\n sessionId: number;\n }) => void;\n addToQueue: (...list: SessionReplayContext[]) => void;\n schedule: (timeout: number) => void;\n flush: (useRetry?: boolean) => Promise<void>;\n send: (context: SessionReplayContext, useRetry?: boolean) => Promise<void>;\n completeRequest({\n context,\n err,\n success,\n removeEvents,\n }: {\n context: SessionReplayContext;\n err?: string | undefined;\n success?: string | undefined;\n removeEvents?: boolean | undefined;\n }): void;\n getAllSessionEventsFromStore: () => Promise<IDBStore | undefined>;\n storeEventsForSession: (events: Events, sequenceId: number) => Promise<void>;\n removeSessionEventsStore: (sessionId: number) => Promise<void>;\n}\n\nexport interface SessionReplayPlugin {\n (client: BrowserClient, options?: Options): SessionReplayEnrichmentPlugin;\n (options?: Options): SessionReplayEnrichmentPlugin;\n}\n\nexport type SessionReplayPluginParameters = [BrowserClient, Options?] | [Options?];\n"]}
|
|
1
|
+
{"version":3,"file":"session-replay.js","sourceRoot":"","sources":["../../../src/typings/session-replay.ts"],"names":[],"mappings":"","sourcesContent":["import { BrowserClient, BrowserConfig, EnrichmentPlugin } from '@amplitude/analytics-types';\nimport { record } from 'rrweb';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface Options {}\n\nexport type Events = string[];\n\nexport interface SessionReplayContext {\n events: Events;\n sequenceId: number;\n attempts: number;\n timeout: number;\n sessionId: number;\n}\n\nexport interface IDBStore {\n [sessionId: number]: {\n events: Events;\n sequenceId: number;\n };\n}\nexport interface SessionReplayEnrichmentPlugin extends EnrichmentPlugin {\n config: BrowserConfig;\n storageKey: string;\n retryTimeout: number;\n events: Events;\n currentSequenceId: number;\n interval: number;\n queue: SessionReplayContext[];\n timeAtLastSend: number | null;\n stopRecordingEvents: ReturnType<typeof record> | null;\n maxPersistedEventsSize: number;\n emptyStoreAndReset: () => Promise<void>;\n recordEvents: () => void;\n shouldSplitEventsList: (nextEventString: string) => boolean;\n sendEventsList: ({\n events,\n sequenceId,\n sessionId,\n }: {\n events: string[];\n sequenceId: number;\n sessionId: number;\n }) => void;\n addToQueue: (...list: SessionReplayContext[]) => void;\n schedule: (timeout: number) => void;\n flush: (useRetry?: boolean) => Promise<void>;\n send: (context: SessionReplayContext, useRetry?: boolean) => Promise<void>;\n completeRequest({\n context,\n err,\n success,\n removeEvents,\n }: {\n context: SessionReplayContext;\n err?: string | undefined;\n success?: string | undefined;\n removeEvents?: boolean | undefined;\n }): void;\n getAllSessionEventsFromStore: () => Promise<IDBStore | undefined>;\n storeEventsForSession: (events: Events, sequenceId: number) => Promise<void>;\n removeSessionEventsStore: (sessionId: number) => Promise<void>;\n}\n\nexport interface SessionReplayPlugin {\n (client: BrowserClient, options?: Options): SessionReplayEnrichmentPlugin;\n (options?: Options): SessionReplayEnrichmentPlugin;\n}\n\nexport type SessionReplayPluginParameters = [BrowserClient, Options?] | [Options?];\n"]}
|