posthog-js 1.92.0 → 1.92.1
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/dist/array.full.js +1 -1
- package/dist/array.full.js.map +1 -1
- package/dist/array.js +1 -1
- package/dist/array.js.map +1 -1
- package/dist/es.js +1 -1
- package/dist/es.js.map +1 -1
- package/dist/exception-autocapture.js +1 -1
- package/dist/exception-autocapture.js.map +1 -1
- package/dist/module.d.ts +21 -23
- package/dist/module.js +1 -1
- package/dist/module.js.map +1 -1
- package/dist/recorder-v2.js +2 -2
- package/dist/recorder-v2.js.map +1 -1
- package/dist/surveys.js.map +1 -1
- package/lib/package.json +1 -1
- package/lib/src/decide.js +4 -5
- package/lib/src/decide.js.map +1 -1
- package/lib/src/extensions/replay/config.d.ts +2 -2
- package/lib/src/extensions/replay/config.js +73 -6
- package/lib/src/extensions/replay/config.js.map +1 -1
- package/lib/src/extensions/replay/sessionrecording.d.ts +1 -0
- package/lib/src/extensions/replay/sessionrecording.js +14 -2
- package/lib/src/extensions/replay/sessionrecording.js.map +1 -1
- package/lib/src/loader-recorder-v2.d.ts +2 -2
- package/lib/src/loader-recorder-v2.js +101 -49
- package/lib/src/loader-recorder-v2.js.map +1 -1
- package/lib/src/posthog-core.d.ts +7 -2
- package/lib/src/posthog-core.js +18 -3
- package/lib/src/posthog-core.js.map +1 -1
- package/lib/src/types.d.ts +13 -2
- package/lib/src/types.js.map +1 -1
- package/lib/src/utils/event-utils.js +3 -4
- package/lib/src/utils/event-utils.js.map +1 -1
- package/lib/src/utils/request-utils.d.ts +7 -0
- package/lib/src/utils/request-utils.js +15 -0
- package/lib/src/utils/request-utils.js.map +1 -1
- package/lib/src/utils/type-utils.js +2 -7
- package/lib/src/utils/type-utils.js.map +1 -1
- package/package.json +1 -1
- package/lib/src/extensions/replay/web-performance.d.ts +0 -20
- package/lib/src/extensions/replay/web-performance.js +0 -248
- package/lib/src/extensions/replay/web-performance.js.map +0 -1
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
var __values = (this && this.__values) || function(o) {
|
|
2
|
-
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
3
|
-
if (m) return m.call(o);
|
|
4
|
-
if (o && typeof o.length === "number") return {
|
|
5
|
-
next: function () {
|
|
6
|
-
if (o && i >= o.length) o = void 0;
|
|
7
|
-
return { value: o && o[i++], done: !o };
|
|
8
|
-
}
|
|
9
|
-
};
|
|
10
|
-
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
11
|
-
};
|
|
12
|
-
import { isLocalhost } from '../../utils/request-utils';
|
|
13
|
-
import { _isUndefined } from '../../utils/type-utils';
|
|
14
|
-
import { logger } from '../../utils/logger';
|
|
15
|
-
import { window } from '../../utils/globals';
|
|
16
|
-
var PERFORMANCE_EVENTS_MAPPING = {
|
|
17
|
-
// BASE_PERFORMANCE_EVENT_COLUMNS
|
|
18
|
-
entryType: 0,
|
|
19
|
-
timeOrigin: 1,
|
|
20
|
-
name: 2,
|
|
21
|
-
// RESOURCE_EVENT_COLUMNS
|
|
22
|
-
startTime: 3,
|
|
23
|
-
redirectStart: 4,
|
|
24
|
-
redirectEnd: 5,
|
|
25
|
-
workerStart: 6,
|
|
26
|
-
fetchStart: 7,
|
|
27
|
-
domainLookupStart: 8,
|
|
28
|
-
domainLookupEnd: 9,
|
|
29
|
-
connectStart: 10,
|
|
30
|
-
secureConnectionStart: 11,
|
|
31
|
-
connectEnd: 12,
|
|
32
|
-
requestStart: 13,
|
|
33
|
-
responseStart: 14,
|
|
34
|
-
responseEnd: 15,
|
|
35
|
-
decodedBodySize: 16,
|
|
36
|
-
encodedBodySize: 17,
|
|
37
|
-
initiatorType: 18,
|
|
38
|
-
nextHopProtocol: 19,
|
|
39
|
-
renderBlockingStatus: 20,
|
|
40
|
-
responseStatus: 21,
|
|
41
|
-
transferSize: 22,
|
|
42
|
-
// LARGEST_CONTENTFUL_PAINT_EVENT_COLUMNS
|
|
43
|
-
element: 23,
|
|
44
|
-
renderTime: 24,
|
|
45
|
-
loadTime: 25,
|
|
46
|
-
size: 26,
|
|
47
|
-
id: 27,
|
|
48
|
-
url: 28,
|
|
49
|
-
// NAVIGATION_EVENT_COLUMNS
|
|
50
|
-
domComplete: 29,
|
|
51
|
-
domContentLoadedEvent: 30,
|
|
52
|
-
domInteractive: 31,
|
|
53
|
-
loadEventEnd: 32,
|
|
54
|
-
loadEventStart: 33,
|
|
55
|
-
redirectCount: 34,
|
|
56
|
-
navigationType: 35,
|
|
57
|
-
unloadEventEnd: 36,
|
|
58
|
-
unloadEventStart: 37,
|
|
59
|
-
// Added after v1
|
|
60
|
-
duration: 39,
|
|
61
|
-
timestamp: 40,
|
|
62
|
-
// NOTE: CURRENTLY UNSUPPORTED
|
|
63
|
-
// EVENT_TIMING_EVENT_COLUMNS
|
|
64
|
-
// processingStart: null,
|
|
65
|
-
// processingEnd: null,
|
|
66
|
-
// MARK_AND_MEASURE_EVENT_COLUMNS
|
|
67
|
-
// detail: null,
|
|
68
|
-
};
|
|
69
|
-
var ENTRY_TYPES_TO_OBSERVE = [
|
|
70
|
-
// 'event', // This is too noisy as it covers all browser events
|
|
71
|
-
'first-input',
|
|
72
|
-
// 'mark', // Mark is used too liberally. We would need to filter for specific marks
|
|
73
|
-
// 'measure', // Measure is used too liberally. We would need to filter for specific measures
|
|
74
|
-
'navigation',
|
|
75
|
-
'paint',
|
|
76
|
-
'resource',
|
|
77
|
-
];
|
|
78
|
-
var PERFORMANCE_INGESTION_ENDPOINT = '/e/';
|
|
79
|
-
// Don't monitor posthog paths because then events cause performance events which are events and the snake eats its tail 😱
|
|
80
|
-
var POSTHOG_PATHS_TO_IGNORE = ['/s/', PERFORMANCE_INGESTION_ENDPOINT];
|
|
81
|
-
var WebPerformanceObserver = /** @class */ (function () {
|
|
82
|
-
function WebPerformanceObserver(instance) {
|
|
83
|
-
// Util to help developers working on this feature manually override
|
|
84
|
-
this._forceAllowLocalhost = false;
|
|
85
|
-
this.instance = instance;
|
|
86
|
-
}
|
|
87
|
-
WebPerformanceObserver.prototype.startObservingIfEnabled = function () {
|
|
88
|
-
if (this.isEnabled()) {
|
|
89
|
-
this.startObserving();
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
this.stopObserving();
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
WebPerformanceObserver.prototype.startObserving = function () {
|
|
96
|
-
var _this = this;
|
|
97
|
-
var _a;
|
|
98
|
-
if (this.observer) {
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
if (_isUndefined((_a = window === null || window === void 0 ? void 0 : window.PerformanceObserver) === null || _a === void 0 ? void 0 : _a.supportedEntryTypes)) {
|
|
102
|
-
logger.info('[PerformanceObserver] not started because PerformanceObserver is not supported by this browser.');
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
if (isLocalhost() && !this._forceAllowLocalhost) {
|
|
106
|
-
logger.info('[PerformanceObserver] not started because we are on localhost.');
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
try {
|
|
110
|
-
// compat checked above with early return
|
|
111
|
-
// eslint-disable-next-line compat/compat
|
|
112
|
-
this.observer = new PerformanceObserver(function (list) {
|
|
113
|
-
list.getEntries().forEach(function (entry) {
|
|
114
|
-
_this._capturePerformanceEvent(entry);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
// compat checked above with early return
|
|
118
|
-
// eslint-disable-next-line compat/compat
|
|
119
|
-
var entryTypes = PerformanceObserver.supportedEntryTypes.filter(function (x) { return ENTRY_TYPES_TO_OBSERVE.includes(x); });
|
|
120
|
-
entryTypes.forEach(function (entryType) {
|
|
121
|
-
var _a;
|
|
122
|
-
(_a = _this.observer) === null || _a === void 0 ? void 0 : _a.observe({ type: entryType, buffered: true });
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
catch (e) {
|
|
126
|
-
logger.error('PostHog failed to start performance observer', e);
|
|
127
|
-
this.stopObserving();
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
WebPerformanceObserver.prototype.stopObserving = function () {
|
|
131
|
-
if (this.observer) {
|
|
132
|
-
this.observer.disconnect();
|
|
133
|
-
this.observer = undefined;
|
|
134
|
-
}
|
|
135
|
-
};
|
|
136
|
-
WebPerformanceObserver.prototype.isObserving = function () {
|
|
137
|
-
return !!this.observer;
|
|
138
|
-
};
|
|
139
|
-
WebPerformanceObserver.prototype.isEnabled = function () {
|
|
140
|
-
var _a, _b;
|
|
141
|
-
return (_b = (_a = this.instance.config.capture_performance) !== null && _a !== void 0 ? _a : this.remoteEnabled) !== null && _b !== void 0 ? _b : false;
|
|
142
|
-
};
|
|
143
|
-
WebPerformanceObserver.prototype.afterDecideResponse = function (response) {
|
|
144
|
-
this.remoteEnabled = response.capturePerformance || false;
|
|
145
|
-
if (this.isEnabled()) {
|
|
146
|
-
this.startObserving();
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
WebPerformanceObserver.prototype._capturePerformanceEvent = function (event) {
|
|
150
|
-
// NOTE: We don't want to capture our own request events.
|
|
151
|
-
var e_1, _a, _b;
|
|
152
|
-
if (event.name.indexOf(this.instance.config.api_host) === 0) {
|
|
153
|
-
var path_1 = event.name.replace(this.instance.config.api_host, '');
|
|
154
|
-
if (POSTHOG_PATHS_TO_IGNORE.find(function (x) { return path_1.indexOf(x) === 0; })) {
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
// NOTE: This is minimal atm but will include more options when we move to the
|
|
159
|
-
// built-in rrweb network recorder
|
|
160
|
-
var networkRequest = {
|
|
161
|
-
url: event.name,
|
|
162
|
-
};
|
|
163
|
-
var userSessionRecordingOptions = this.instance.config.session_recording;
|
|
164
|
-
if (userSessionRecordingOptions.maskNetworkRequestFn) {
|
|
165
|
-
networkRequest = userSessionRecordingOptions.maskNetworkRequestFn(networkRequest);
|
|
166
|
-
}
|
|
167
|
-
if (!networkRequest) {
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
var eventJson = event.toJSON();
|
|
171
|
-
eventJson.name = networkRequest.url;
|
|
172
|
-
var properties = {};
|
|
173
|
-
// kudos to sentry javascript sdk for excellent background on why to use Date.now() here
|
|
174
|
-
// https://github.com/getsentry/sentry-javascript/blob/e856e40b6e71a73252e788cd42b5260f81c9c88e/packages/utils/src/time.ts#L70
|
|
175
|
-
// can't start observer if performance.now() is not available
|
|
176
|
-
// eslint-disable-next-line compat/compat
|
|
177
|
-
var timeOrigin = Math.floor(Date.now() - performance.now());
|
|
178
|
-
properties[PERFORMANCE_EVENTS_MAPPING['timeOrigin']] = timeOrigin;
|
|
179
|
-
// clickhouse can't ingest timestamps that are floats
|
|
180
|
-
// (in this case representing fractions of a millisecond we don't care about anyway)
|
|
181
|
-
properties[PERFORMANCE_EVENTS_MAPPING['timestamp']] = Math.floor(timeOrigin + event.startTime);
|
|
182
|
-
for (var key in PERFORMANCE_EVENTS_MAPPING) {
|
|
183
|
-
if (!_isUndefined(eventJson[key])) {
|
|
184
|
-
properties[PERFORMANCE_EVENTS_MAPPING[key]] = eventJson[key];
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
this.capturePerformanceEvent(properties);
|
|
188
|
-
if (exposesServerTiming(event)) {
|
|
189
|
-
try {
|
|
190
|
-
for (var _c = __values(event.serverTiming || []), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
191
|
-
var timing = _d.value;
|
|
192
|
-
this.capturePerformanceEvent((_b = {},
|
|
193
|
-
_b[PERFORMANCE_EVENTS_MAPPING['timeOrigin']] = timeOrigin,
|
|
194
|
-
_b[PERFORMANCE_EVENTS_MAPPING['timestamp']] = Math.floor(timeOrigin + event.startTime),
|
|
195
|
-
_b[PERFORMANCE_EVENTS_MAPPING['name']] = timing.name,
|
|
196
|
-
_b[PERFORMANCE_EVENTS_MAPPING['duration']] = timing.duration,
|
|
197
|
-
// the spec has a closed list of possible types
|
|
198
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry/entryType
|
|
199
|
-
// but, we need to know this was a server timing so that we know to
|
|
200
|
-
// match it to the appropriate navigation or resource timing
|
|
201
|
-
// that matching will have to be on timestamp and $current_url
|
|
202
|
-
_b[PERFORMANCE_EVENTS_MAPPING['entryType']] = 'serverTiming',
|
|
203
|
-
_b));
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
207
|
-
finally {
|
|
208
|
-
try {
|
|
209
|
-
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
|
|
210
|
-
}
|
|
211
|
-
finally { if (e_1) throw e_1.error; }
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
};
|
|
215
|
-
/**
|
|
216
|
-
* :TRICKY: Make sure we batch these requests, and don't truncate the strings.
|
|
217
|
-
*/
|
|
218
|
-
WebPerformanceObserver.prototype.capturePerformanceEvent = function (properties) {
|
|
219
|
-
var _a;
|
|
220
|
-
var timestamp = properties[PERFORMANCE_EVENTS_MAPPING['timestamp']];
|
|
221
|
-
(_a = this.instance.sessionRecording) === null || _a === void 0 ? void 0 : _a.onRRwebEmit({
|
|
222
|
-
type: 6,
|
|
223
|
-
data: {
|
|
224
|
-
plugin: 'posthog/network@1',
|
|
225
|
-
payload: properties,
|
|
226
|
-
},
|
|
227
|
-
timestamp: timestamp,
|
|
228
|
-
});
|
|
229
|
-
// this.instance.capture('$performance_event', properties, {
|
|
230
|
-
// transport: 'XHR',
|
|
231
|
-
// method: 'POST',
|
|
232
|
-
// endpoint: PERFORMANCE_INGESTION_ENDPOINT,
|
|
233
|
-
// _noTruncate: true,
|
|
234
|
-
// _batchKey: 'performanceEvent',
|
|
235
|
-
// })
|
|
236
|
-
};
|
|
237
|
-
return WebPerformanceObserver;
|
|
238
|
-
}());
|
|
239
|
-
export { WebPerformanceObserver };
|
|
240
|
-
/**
|
|
241
|
-
* Check if this PerformanceEntry is either a PerformanceResourceTiming or a PerformanceNavigationTiming
|
|
242
|
-
* NB PerformanceNavigationTiming extends PerformanceResourceTiming
|
|
243
|
-
* Here we don't care which interface it implements as both expose `serverTimings`
|
|
244
|
-
*/
|
|
245
|
-
var exposesServerTiming = function (event) {
|
|
246
|
-
return event.entryType === 'navigation' || event.entryType === 'resource';
|
|
247
|
-
};
|
|
248
|
-
//# sourceMappingURL=web-performance.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"web-performance.js","sourceRoot":"","sources":["../../../../src/extensions/replay/web-performance.ts"],"names":[],"mappings":"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","sourcesContent":["import { PostHog } from '../../posthog-core'\nimport { DecideResponse, NetworkRequest } from '../../types'\nimport { isLocalhost } from '../../utils/request-utils'\n\nimport { _isUndefined } from '../../utils/type-utils'\nimport { logger } from '../../utils/logger'\nimport { window } from '../../utils/globals'\n\nconst PERFORMANCE_EVENTS_MAPPING: { [key: string]: number } = {\n // BASE_PERFORMANCE_EVENT_COLUMNS\n entryType: 0,\n timeOrigin: 1,\n name: 2,\n\n // RESOURCE_EVENT_COLUMNS\n startTime: 3,\n redirectStart: 4,\n redirectEnd: 5,\n workerStart: 6,\n fetchStart: 7,\n domainLookupStart: 8,\n domainLookupEnd: 9,\n connectStart: 10,\n secureConnectionStart: 11,\n connectEnd: 12,\n requestStart: 13,\n responseStart: 14,\n responseEnd: 15,\n decodedBodySize: 16,\n encodedBodySize: 17,\n initiatorType: 18,\n nextHopProtocol: 19,\n renderBlockingStatus: 20,\n responseStatus: 21,\n transferSize: 22,\n\n // LARGEST_CONTENTFUL_PAINT_EVENT_COLUMNS\n element: 23,\n renderTime: 24,\n loadTime: 25,\n size: 26,\n id: 27,\n url: 28,\n\n // NAVIGATION_EVENT_COLUMNS\n domComplete: 29,\n domContentLoadedEvent: 30,\n domInteractive: 31,\n loadEventEnd: 32,\n loadEventStart: 33,\n redirectCount: 34,\n navigationType: 35,\n unloadEventEnd: 36,\n unloadEventStart: 37,\n\n // Added after v1\n duration: 39,\n timestamp: 40,\n\n // NOTE: CURRENTLY UNSUPPORTED\n // EVENT_TIMING_EVENT_COLUMNS\n // processingStart: null,\n // processingEnd: null,\n\n // MARK_AND_MEASURE_EVENT_COLUMNS\n // detail: null,\n}\n\nconst ENTRY_TYPES_TO_OBSERVE = [\n // 'event', // This is too noisy as it covers all browser events\n 'first-input',\n // 'mark', // Mark is used too liberally. We would need to filter for specific marks\n // 'measure', // Measure is used too liberally. We would need to filter for specific measures\n 'navigation',\n 'paint',\n 'resource',\n]\n\nconst PERFORMANCE_INGESTION_ENDPOINT = '/e/'\n// Don't monitor posthog paths because then events cause performance events which are events and the snake eats its tail 😱\nconst POSTHOG_PATHS_TO_IGNORE = ['/s/', PERFORMANCE_INGESTION_ENDPOINT]\n\nexport class WebPerformanceObserver {\n instance: PostHog\n remoteEnabled: boolean | undefined\n observer: PerformanceObserver | undefined\n\n // Util to help developers working on this feature manually override\n _forceAllowLocalhost = false\n\n constructor(instance: PostHog) {\n this.instance = instance\n }\n\n startObservingIfEnabled() {\n if (this.isEnabled()) {\n this.startObserving()\n } else {\n this.stopObserving()\n }\n }\n\n startObserving() {\n if (this.observer) {\n return\n }\n\n if (_isUndefined(window?.PerformanceObserver?.supportedEntryTypes)) {\n logger.info(\n '[PerformanceObserver] not started because PerformanceObserver is not supported by this browser.'\n )\n return\n }\n\n if (isLocalhost() && !this._forceAllowLocalhost) {\n logger.info('[PerformanceObserver] not started because we are on localhost.')\n return\n }\n\n try {\n // compat checked above with early return\n // eslint-disable-next-line compat/compat\n this.observer = new PerformanceObserver((list) => {\n list.getEntries().forEach((entry) => {\n this._capturePerformanceEvent(entry)\n })\n })\n\n // compat checked above with early return\n // eslint-disable-next-line compat/compat\n const entryTypes = PerformanceObserver.supportedEntryTypes.filter((x) => ENTRY_TYPES_TO_OBSERVE.includes(x))\n\n entryTypes.forEach((entryType) => {\n this.observer?.observe({ type: entryType, buffered: true })\n })\n } catch (e) {\n logger.error('PostHog failed to start performance observer', e)\n this.stopObserving()\n }\n }\n\n stopObserving() {\n if (this.observer) {\n this.observer.disconnect()\n this.observer = undefined\n }\n }\n\n isObserving() {\n return !!this.observer\n }\n\n isEnabled() {\n return this.instance.config.capture_performance ?? this.remoteEnabled ?? false\n }\n\n afterDecideResponse(response: DecideResponse) {\n this.remoteEnabled = response.capturePerformance || false\n if (this.isEnabled()) {\n this.startObserving()\n }\n }\n\n _capturePerformanceEvent(event: PerformanceEntry) {\n // NOTE: We don't want to capture our own request events.\n\n if (event.name.indexOf(this.instance.config.api_host) === 0) {\n const path = event.name.replace(this.instance.config.api_host, '')\n\n if (POSTHOG_PATHS_TO_IGNORE.find((x) => path.indexOf(x) === 0)) {\n return\n }\n }\n\n // NOTE: This is minimal atm but will include more options when we move to the\n // built-in rrweb network recorder\n let networkRequest: NetworkRequest | null | undefined = {\n url: event.name,\n }\n\n const userSessionRecordingOptions = this.instance.config.session_recording\n\n if (userSessionRecordingOptions.maskNetworkRequestFn) {\n networkRequest = userSessionRecordingOptions.maskNetworkRequestFn(networkRequest)\n }\n\n if (!networkRequest) {\n return\n }\n\n const eventJson = event.toJSON()\n eventJson.name = networkRequest.url\n const properties: { [key: number]: any } = {}\n // kudos to sentry javascript sdk for excellent background on why to use Date.now() here\n // https://github.com/getsentry/sentry-javascript/blob/e856e40b6e71a73252e788cd42b5260f81c9c88e/packages/utils/src/time.ts#L70\n // can't start observer if performance.now() is not available\n // eslint-disable-next-line compat/compat\n const timeOrigin = Math.floor(Date.now() - performance.now())\n properties[PERFORMANCE_EVENTS_MAPPING['timeOrigin']] = timeOrigin\n // clickhouse can't ingest timestamps that are floats\n // (in this case representing fractions of a millisecond we don't care about anyway)\n properties[PERFORMANCE_EVENTS_MAPPING['timestamp']] = Math.floor(timeOrigin + event.startTime)\n for (const key in PERFORMANCE_EVENTS_MAPPING) {\n if (!_isUndefined(eventJson[key])) {\n properties[PERFORMANCE_EVENTS_MAPPING[key]] = eventJson[key]\n }\n }\n\n this.capturePerformanceEvent(properties)\n\n if (exposesServerTiming(event)) {\n for (const timing of event.serverTiming || []) {\n this.capturePerformanceEvent({\n [PERFORMANCE_EVENTS_MAPPING['timeOrigin']]: timeOrigin,\n [PERFORMANCE_EVENTS_MAPPING['timestamp']]: Math.floor(timeOrigin + event.startTime),\n [PERFORMANCE_EVENTS_MAPPING['name']]: timing.name,\n [PERFORMANCE_EVENTS_MAPPING['duration']]: timing.duration,\n // the spec has a closed list of possible types\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry/entryType\n // but, we need to know this was a server timing so that we know to\n // match it to the appropriate navigation or resource timing\n // that matching will have to be on timestamp and $current_url\n [PERFORMANCE_EVENTS_MAPPING['entryType']]: 'serverTiming',\n })\n }\n }\n }\n\n /**\n * :TRICKY: Make sure we batch these requests, and don't truncate the strings.\n */\n private capturePerformanceEvent(properties: { [key: number]: any }) {\n const timestamp = properties[PERFORMANCE_EVENTS_MAPPING['timestamp']]\n\n this.instance.sessionRecording?.onRRwebEmit({\n type: 6, // EventType.Plugin,\n data: {\n plugin: 'posthog/network@1',\n payload: properties,\n },\n timestamp,\n })\n\n // this.instance.capture('$performance_event', properties, {\n // transport: 'XHR',\n // method: 'POST',\n // endpoint: PERFORMANCE_INGESTION_ENDPOINT,\n // _noTruncate: true,\n // _batchKey: 'performanceEvent',\n // })\n }\n}\n\n/**\n * Check if this PerformanceEntry is either a PerformanceResourceTiming or a PerformanceNavigationTiming\n * NB PerformanceNavigationTiming extends PerformanceResourceTiming\n * Here we don't care which interface it implements as both expose `serverTimings`\n */\nconst exposesServerTiming = (event: PerformanceEntry): event is PerformanceResourceTiming =>\n event.entryType === 'navigation' || event.entryType === 'resource'\n"]}
|