@myinterview/widget-react 1.1.23-beta-78ffddc → 1.1.23-binary-001
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/cjs/components/CountDown.d.ts +2 -2
- package/dist/cjs/components/Counter.d.ts +2 -2
- package/dist/cjs/components/DeviceSelector.d.ts +1 -1
- package/dist/cjs/index.js +776 -2187
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/interfaces/widgetInterface.d.ts +7 -2
- package/dist/cjs/services/event.service.d.ts +6 -1
- package/dist/cjs/utils/constants.utils.d.ts +1 -0
- package/dist/esm/components/CountDown.d.ts +2 -2
- package/dist/esm/components/Counter.d.ts +2 -2
- package/dist/esm/components/DeviceSelector.d.ts +1 -1
- package/dist/esm/index.js +762 -2173
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/interfaces/widgetInterface.d.ts +7 -2
- package/dist/esm/services/event.service.d.ts +6 -1
- package/dist/esm/utils/constants.utils.d.ts +1 -0
- package/package.json +43 -43
package/dist/esm/index.js
CHANGED
|
@@ -2,6 +2,31 @@ import * as React from 'react';
|
|
|
2
2
|
import React__default, { createContext, forwardRef, useRef, useEffect, useState, useLayoutEffect, useImperativeHandle, useDebugValue, useContext, createElement, useCallback, useMemo } from 'react';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
4
|
|
|
5
|
+
/*! *****************************************************************************
|
|
6
|
+
Copyright (c) Microsoft Corporation.
|
|
7
|
+
|
|
8
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
9
|
+
purpose with or without fee is hereby granted.
|
|
10
|
+
|
|
11
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
12
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
13
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
14
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
15
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
16
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
17
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
18
|
+
***************************************************************************** */
|
|
19
|
+
|
|
20
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
21
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
22
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
23
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
24
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
25
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
26
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
5
30
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
6
31
|
const objectToString = Object.prototype.toString;
|
|
7
32
|
|
|
@@ -922,12 +947,6 @@ function createStackParser(...parsers) {
|
|
|
922
947
|
// Remove webpack (error: *) wrappers
|
|
923
948
|
const cleanedLine = WEBPACK_ERROR_REGEXP.test(line) ? line.replace(WEBPACK_ERROR_REGEXP, '$1') : line;
|
|
924
949
|
|
|
925
|
-
// https://github.com/getsentry/sentry-javascript/issues/7813
|
|
926
|
-
// Skip Error: lines
|
|
927
|
-
if (cleanedLine.match(/\S*Error: /)) {
|
|
928
|
-
continue;
|
|
929
|
-
}
|
|
930
|
-
|
|
931
950
|
for (const parser of sortedParsers) {
|
|
932
951
|
const frame = parser(cleanedLine);
|
|
933
952
|
|
|
@@ -1112,8 +1131,6 @@ function supportsHistory() {
|
|
|
1112
1131
|
// eslint-disable-next-line deprecation/deprecation
|
|
1113
1132
|
const WINDOW$3 = getGlobalObject();
|
|
1114
1133
|
|
|
1115
|
-
const SENTRY_XHR_DATA_KEY = '__sentry_xhr_v2__';
|
|
1116
|
-
|
|
1117
1134
|
/**
|
|
1118
1135
|
* Instrument native APIs to call handlers that can be used to create breadcrumbs, APM spans etc.
|
|
1119
1136
|
* - Console API
|
|
@@ -1226,13 +1243,11 @@ function instrumentFetch() {
|
|
|
1226
1243
|
|
|
1227
1244
|
fill(WINDOW$3, 'fetch', function (originalFetch) {
|
|
1228
1245
|
return function (...args) {
|
|
1229
|
-
const { method, url } = parseFetchArgs(args);
|
|
1230
|
-
|
|
1231
1246
|
const handlerData = {
|
|
1232
1247
|
args,
|
|
1233
1248
|
fetchData: {
|
|
1234
|
-
method,
|
|
1235
|
-
url,
|
|
1249
|
+
method: getFetchMethod(args),
|
|
1250
|
+
url: getFetchUrl(args),
|
|
1236
1251
|
},
|
|
1237
1252
|
startTimestamp: Date.now(),
|
|
1238
1253
|
};
|
|
@@ -1267,53 +1282,29 @@ function instrumentFetch() {
|
|
|
1267
1282
|
});
|
|
1268
1283
|
}
|
|
1269
1284
|
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
if (typeof resource === 'string') {
|
|
1276
|
-
return resource;
|
|
1277
|
-
}
|
|
1278
|
-
|
|
1279
|
-
if (!resource) {
|
|
1280
|
-
return '';
|
|
1281
|
-
}
|
|
1282
|
-
|
|
1283
|
-
if (hasProp(resource, 'url')) {
|
|
1284
|
-
return resource.url;
|
|
1285
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
1286
|
+
/** Extract `method` from fetch call arguments */
|
|
1287
|
+
function getFetchMethod(fetchArgs = []) {
|
|
1288
|
+
if ('Request' in WINDOW$3 && isInstanceOf(fetchArgs[0], Request) && fetchArgs[0].method) {
|
|
1289
|
+
return String(fetchArgs[0].method).toUpperCase();
|
|
1285
1290
|
}
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
return resource.toString();
|
|
1291
|
+
if (fetchArgs[1] && fetchArgs[1].method) {
|
|
1292
|
+
return String(fetchArgs[1].method).toUpperCase();
|
|
1289
1293
|
}
|
|
1290
|
-
|
|
1291
|
-
return '';
|
|
1294
|
+
return 'GET';
|
|
1292
1295
|
}
|
|
1293
1296
|
|
|
1294
|
-
/**
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
if (fetchArgs.length === 0) {
|
|
1299
|
-
return { method: 'GET', url: '' };
|
|
1297
|
+
/** Extract `url` from fetch call arguments */
|
|
1298
|
+
function getFetchUrl(fetchArgs = []) {
|
|
1299
|
+
if (typeof fetchArgs[0] === 'string') {
|
|
1300
|
+
return fetchArgs[0];
|
|
1300
1301
|
}
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
const [url, options] = fetchArgs ;
|
|
1304
|
-
|
|
1305
|
-
return {
|
|
1306
|
-
url: getUrlFromResource(url),
|
|
1307
|
-
method: hasProp(options, 'method') ? String(options.method).toUpperCase() : 'GET',
|
|
1308
|
-
};
|
|
1302
|
+
if ('Request' in WINDOW$3 && isInstanceOf(fetchArgs[0], Request)) {
|
|
1303
|
+
return fetchArgs[0].url;
|
|
1309
1304
|
}
|
|
1310
|
-
|
|
1311
|
-
const arg = fetchArgs[0];
|
|
1312
|
-
return {
|
|
1313
|
-
url: getUrlFromResource(arg ),
|
|
1314
|
-
method: hasProp(arg, 'method') ? String(arg.method).toUpperCase() : 'GET',
|
|
1315
|
-
};
|
|
1305
|
+
return String(fetchArgs[0]);
|
|
1316
1306
|
}
|
|
1307
|
+
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
|
|
1317
1308
|
|
|
1318
1309
|
/** JSDoc */
|
|
1319
1310
|
function instrumentXHR() {
|
|
@@ -1326,11 +1317,10 @@ function instrumentXHR() {
|
|
|
1326
1317
|
fill(xhrproto, 'open', function (originalOpen) {
|
|
1327
1318
|
return function ( ...args) {
|
|
1328
1319
|
const url = args[1];
|
|
1329
|
-
const xhrInfo = (this
|
|
1320
|
+
const xhrInfo = (this.__sentry_xhr__ = {
|
|
1330
1321
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
1331
1322
|
method: isString$2(args[0]) ? args[0].toUpperCase() : args[0],
|
|
1332
1323
|
url: args[1],
|
|
1333
|
-
request_headers: {},
|
|
1334
1324
|
});
|
|
1335
1325
|
|
|
1336
1326
|
// if Sentry key appears in URL, don't capture it as a request
|
|
@@ -1341,7 +1331,7 @@ function instrumentXHR() {
|
|
|
1341
1331
|
|
|
1342
1332
|
const onreadystatechangeHandler = () => {
|
|
1343
1333
|
// For whatever reason, this is not the same instance here as from the outer method
|
|
1344
|
-
const xhrInfo = this
|
|
1334
|
+
const xhrInfo = this.__sentry_xhr__;
|
|
1345
1335
|
|
|
1346
1336
|
if (!xhrInfo) {
|
|
1347
1337
|
return;
|
|
@@ -1376,32 +1366,14 @@ function instrumentXHR() {
|
|
|
1376
1366
|
this.addEventListener('readystatechange', onreadystatechangeHandler);
|
|
1377
1367
|
}
|
|
1378
1368
|
|
|
1379
|
-
// Intercepting `setRequestHeader` to access the request headers of XHR instance.
|
|
1380
|
-
// This will only work for user/library defined headers, not for the default/browser-assigned headers.
|
|
1381
|
-
// Request cookies are also unavailable for XHR, as `Cookie` header can't be defined by `setRequestHeader`.
|
|
1382
|
-
fill(this, 'setRequestHeader', function (original) {
|
|
1383
|
-
return function ( ...setRequestHeaderArgs) {
|
|
1384
|
-
const [header, value] = setRequestHeaderArgs ;
|
|
1385
|
-
|
|
1386
|
-
const xhrInfo = this[SENTRY_XHR_DATA_KEY];
|
|
1387
|
-
|
|
1388
|
-
if (xhrInfo) {
|
|
1389
|
-
xhrInfo.request_headers[header.toLowerCase()] = value;
|
|
1390
|
-
}
|
|
1391
|
-
|
|
1392
|
-
return original.apply(this, setRequestHeaderArgs);
|
|
1393
|
-
};
|
|
1394
|
-
});
|
|
1395
|
-
|
|
1396
1369
|
return originalOpen.apply(this, args);
|
|
1397
1370
|
};
|
|
1398
1371
|
});
|
|
1399
1372
|
|
|
1400
1373
|
fill(xhrproto, 'send', function (originalSend) {
|
|
1401
1374
|
return function ( ...args) {
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
sentryXhrData.body = args[0];
|
|
1375
|
+
if (this.__sentry_xhr__ && args[0] !== undefined) {
|
|
1376
|
+
this.__sentry_xhr__.body = args[0];
|
|
1405
1377
|
}
|
|
1406
1378
|
|
|
1407
1379
|
triggerHandlers('xhr', {
|
|
@@ -1700,15 +1672,13 @@ function instrumentError() {
|
|
|
1700
1672
|
url,
|
|
1701
1673
|
});
|
|
1702
1674
|
|
|
1703
|
-
if (_oldOnErrorHandler
|
|
1675
|
+
if (_oldOnErrorHandler) {
|
|
1704
1676
|
// eslint-disable-next-line prefer-rest-params
|
|
1705
1677
|
return _oldOnErrorHandler.apply(this, arguments);
|
|
1706
1678
|
}
|
|
1707
1679
|
|
|
1708
1680
|
return false;
|
|
1709
1681
|
};
|
|
1710
|
-
|
|
1711
|
-
WINDOW$3.onerror.__SENTRY_INSTRUMENTED__ = true;
|
|
1712
1682
|
}
|
|
1713
1683
|
|
|
1714
1684
|
let _oldOnUnhandledRejectionHandler = null;
|
|
@@ -1719,15 +1689,13 @@ function instrumentUnhandledRejection() {
|
|
|
1719
1689
|
WINDOW$3.onunhandledrejection = function (e) {
|
|
1720
1690
|
triggerHandlers('unhandledrejection', e);
|
|
1721
1691
|
|
|
1722
|
-
if (_oldOnUnhandledRejectionHandler
|
|
1692
|
+
if (_oldOnUnhandledRejectionHandler) {
|
|
1723
1693
|
// eslint-disable-next-line prefer-rest-params
|
|
1724
1694
|
return _oldOnUnhandledRejectionHandler.apply(this, arguments);
|
|
1725
1695
|
}
|
|
1726
1696
|
|
|
1727
1697
|
return true;
|
|
1728
1698
|
};
|
|
1729
|
-
|
|
1730
|
-
WINDOW$3.onunhandledrejection.__SENTRY_INSTRUMENTED__ = true;
|
|
1731
1699
|
}
|
|
1732
1700
|
|
|
1733
1701
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
@@ -2025,7 +1993,7 @@ function loadModule(moduleName) {
|
|
|
2025
1993
|
* @returns A normalized version of the object, or `"**non-serializable**"` if any errors are thrown during normalization.
|
|
2026
1994
|
*/
|
|
2027
1995
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2028
|
-
function normalize(input, depth =
|
|
1996
|
+
function normalize(input, depth = +Infinity, maxProperties = +Infinity) {
|
|
2029
1997
|
try {
|
|
2030
1998
|
// since we're at the outermost level, we don't provide a key
|
|
2031
1999
|
return visit('', input, depth, maxProperties);
|
|
@@ -2071,10 +2039,7 @@ function visit(
|
|
|
2071
2039
|
const [memoize, unmemoize] = memo;
|
|
2072
2040
|
|
|
2073
2041
|
// Get the simple cases out of the way first
|
|
2074
|
-
if (
|
|
2075
|
-
value == null || // this matches null and undefined -> eqeq not eqeqeq
|
|
2076
|
-
(['number', 'boolean', 'string'].includes(typeof value) && !isNaN$1(value))
|
|
2077
|
-
) {
|
|
2042
|
+
if (value === null || (['number', 'boolean', 'string'].includes(typeof value) && !isNaN$1(value))) {
|
|
2078
2043
|
return value ;
|
|
2079
2044
|
}
|
|
2080
2045
|
|
|
@@ -2095,16 +2060,17 @@ function visit(
|
|
|
2095
2060
|
return value ;
|
|
2096
2061
|
}
|
|
2097
2062
|
|
|
2098
|
-
//
|
|
2099
|
-
//
|
|
2100
|
-
//
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2063
|
+
// Do not normalize objects that we know have already been normalized. As a general rule, the
|
|
2064
|
+
// "__sentry_skip_normalization__" property should only be used sparingly and only should only be set on objects that
|
|
2065
|
+
// have already been normalized.
|
|
2066
|
+
let overriddenDepth = depth;
|
|
2067
|
+
|
|
2068
|
+
if (typeof (value )['__sentry_override_normalization_depth__'] === 'number') {
|
|
2069
|
+
overriddenDepth = (value )['__sentry_override_normalization_depth__'] ;
|
|
2070
|
+
}
|
|
2105
2071
|
|
|
2106
2072
|
// We're also done if we've reached the max depth
|
|
2107
|
-
if (
|
|
2073
|
+
if (overriddenDepth === 0) {
|
|
2108
2074
|
// At this point we know `serialized` is a string of the form `"[object XXXX]"`. Clean it up so it's just `"[XXXX]"`.
|
|
2109
2075
|
return stringified.replace('object ', '');
|
|
2110
2076
|
}
|
|
@@ -2120,7 +2086,7 @@ function visit(
|
|
|
2120
2086
|
try {
|
|
2121
2087
|
const jsonValue = valueWithToJSON.toJSON();
|
|
2122
2088
|
// We need to normalize the return value of `.toJSON()` in case it has circular references
|
|
2123
|
-
return visit('', jsonValue,
|
|
2089
|
+
return visit('', jsonValue, overriddenDepth - 1, maxProperties, memo);
|
|
2124
2090
|
} catch (err) {
|
|
2125
2091
|
// pass (The built-in `toJSON` failed, but we can still try to do it ourselves)
|
|
2126
2092
|
}
|
|
@@ -2149,7 +2115,7 @@ function visit(
|
|
|
2149
2115
|
|
|
2150
2116
|
// Recursively visit all the child nodes
|
|
2151
2117
|
const visitValue = visitable[visitKey];
|
|
2152
|
-
normalized[visitKey] = visit(visitKey, visitValue,
|
|
2118
|
+
normalized[visitKey] = visit(visitKey, visitValue, overriddenDepth - 1, maxProperties, memo);
|
|
2153
2119
|
|
|
2154
2120
|
numAdded++;
|
|
2155
2121
|
}
|
|
@@ -2161,7 +2127,6 @@ function visit(
|
|
|
2161
2127
|
return normalized;
|
|
2162
2128
|
}
|
|
2163
2129
|
|
|
2164
|
-
/* eslint-disable complexity */
|
|
2165
2130
|
/**
|
|
2166
2131
|
* Stringify the given value. Handles various known special values and types.
|
|
2167
2132
|
*
|
|
@@ -2212,6 +2177,11 @@ function stringifyValue(
|
|
|
2212
2177
|
return '[NaN]';
|
|
2213
2178
|
}
|
|
2214
2179
|
|
|
2180
|
+
// this catches `undefined` (but not `null`, which is a primitive and can be serialized on its own)
|
|
2181
|
+
if (value === void 0) {
|
|
2182
|
+
return '[undefined]';
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2215
2185
|
if (typeof value === 'function') {
|
|
2216
2186
|
return `[Function: ${getFunctionName(value)}]`;
|
|
2217
2187
|
}
|
|
@@ -2229,19 +2199,11 @@ function stringifyValue(
|
|
|
2229
2199
|
// them to strings means that instances of classes which haven't defined their `toStringTag` will just come out as
|
|
2230
2200
|
// `"[object Object]"`. If we instead look at the constructor's name (which is the same as the name of the class),
|
|
2231
2201
|
// we can make sure that only plain objects come out that way.
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
// Handle HTML Elements
|
|
2235
|
-
if (/^HTML(\w*)Element$/.test(objName)) {
|
|
2236
|
-
return `[HTMLElement: ${objName}]`;
|
|
2237
|
-
}
|
|
2238
|
-
|
|
2239
|
-
return `[object ${objName}]`;
|
|
2202
|
+
return `[object ${getConstructorName(value)}]`;
|
|
2240
2203
|
} catch (err) {
|
|
2241
2204
|
return `**non-serializable** (${err})`;
|
|
2242
2205
|
}
|
|
2243
2206
|
}
|
|
2244
|
-
/* eslint-enable complexity */
|
|
2245
2207
|
|
|
2246
2208
|
function getConstructorName(value) {
|
|
2247
2209
|
const prototype = Object.getPrototypeOf(value);
|
|
@@ -2552,7 +2514,9 @@ function makePromiseBuffer(limit) {
|
|
|
2552
2514
|
* // environments where DOM might not be available
|
|
2553
2515
|
* @returns parsed URL object
|
|
2554
2516
|
*/
|
|
2555
|
-
function parseUrl(url)
|
|
2517
|
+
function parseUrl(url)
|
|
2518
|
+
|
|
2519
|
+
{
|
|
2556
2520
|
if (!url) {
|
|
2557
2521
|
return {};
|
|
2558
2522
|
}
|
|
@@ -2570,8 +2534,6 @@ function parseUrl(url) {
|
|
|
2570
2534
|
host: match[4],
|
|
2571
2535
|
path: match[5],
|
|
2572
2536
|
protocol: match[2],
|
|
2573
|
-
search: query,
|
|
2574
|
-
hash: fragment,
|
|
2575
2537
|
relative: match[5] + query + fragment, // everything minus origin
|
|
2576
2538
|
};
|
|
2577
2539
|
}
|
|
@@ -2956,7 +2918,6 @@ const ITEM_TYPE_TO_DATA_CATEGORY_MAP = {
|
|
|
2956
2918
|
profile: 'profile',
|
|
2957
2919
|
replay_event: 'replay',
|
|
2958
2920
|
replay_recording: 'replay',
|
|
2959
|
-
check_in: 'monitor',
|
|
2960
2921
|
};
|
|
2961
2922
|
|
|
2962
2923
|
/**
|
|
@@ -2986,14 +2947,16 @@ function createEventEnvelopeHeaders(
|
|
|
2986
2947
|
dsn,
|
|
2987
2948
|
) {
|
|
2988
2949
|
const dynamicSamplingContext = event.sdkProcessingMetadata && event.sdkProcessingMetadata.dynamicSamplingContext;
|
|
2950
|
+
|
|
2989
2951
|
return {
|
|
2990
2952
|
event_id: event.event_id ,
|
|
2991
2953
|
sent_at: new Date().toISOString(),
|
|
2992
2954
|
...(sdkInfo && { sdk: sdkInfo }),
|
|
2993
2955
|
...(!!tunnel && { dsn: dsnToString(dsn) }),
|
|
2994
|
-
...(
|
|
2995
|
-
|
|
2996
|
-
|
|
2956
|
+
...(event.type === 'transaction' &&
|
|
2957
|
+
dynamicSamplingContext && {
|
|
2958
|
+
trace: dropUndefinedKeys({ ...dynamicSamplingContext }),
|
|
2959
|
+
}),
|
|
2997
2960
|
};
|
|
2998
2961
|
}
|
|
2999
2962
|
|
|
@@ -3698,16 +3661,9 @@ class Scope {
|
|
|
3698
3661
|
// errors with transaction and it relies on that.
|
|
3699
3662
|
if (this._span) {
|
|
3700
3663
|
event.contexts = { trace: this._span.getTraceContext(), ...event.contexts };
|
|
3701
|
-
const
|
|
3702
|
-
if (
|
|
3703
|
-
event.
|
|
3704
|
-
dynamicSamplingContext: transaction.getDynamicSamplingContext(),
|
|
3705
|
-
...event.sdkProcessingMetadata,
|
|
3706
|
-
};
|
|
3707
|
-
const transactionName = transaction.name;
|
|
3708
|
-
if (transactionName) {
|
|
3709
|
-
event.tags = { transaction: transactionName, ...event.tags };
|
|
3710
|
-
}
|
|
3664
|
+
const transactionName = this._span.transaction && this._span.transaction.name;
|
|
3665
|
+
if (transactionName) {
|
|
3666
|
+
event.tags = { transaction: transactionName, ...event.tags };
|
|
3711
3667
|
}
|
|
3712
3668
|
}
|
|
3713
3669
|
|
|
@@ -3831,6 +3787,11 @@ const API_VERSION = 4;
|
|
|
3831
3787
|
*/
|
|
3832
3788
|
const DEFAULT_BREADCRUMBS = 100;
|
|
3833
3789
|
|
|
3790
|
+
/**
|
|
3791
|
+
* A layer in the process stack.
|
|
3792
|
+
* @hidden
|
|
3793
|
+
*/
|
|
3794
|
+
|
|
3834
3795
|
/**
|
|
3835
3796
|
* @inheritDoc
|
|
3836
3797
|
*/
|
|
@@ -4108,17 +4069,7 @@ class Hub {
|
|
|
4108
4069
|
* @inheritDoc
|
|
4109
4070
|
*/
|
|
4110
4071
|
startTransaction(context, customSamplingContext) {
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && !result) {
|
|
4114
|
-
// eslint-disable-next-line no-console
|
|
4115
|
-
console.warn(`Tracing extension 'startTransaction' has not been added. Call 'addTracingExtensions' before calling 'init':
|
|
4116
|
-
Sentry.addTracingExtensions();
|
|
4117
|
-
Sentry.init({...});
|
|
4118
|
-
`);
|
|
4119
|
-
}
|
|
4120
|
-
|
|
4121
|
-
return result;
|
|
4072
|
+
return this._callExtensionMethod('startTransaction', context, customSamplingContext);
|
|
4122
4073
|
}
|
|
4123
4074
|
|
|
4124
4075
|
/**
|
|
@@ -4203,10 +4154,13 @@ Sentry.init({...});
|
|
|
4203
4154
|
*/
|
|
4204
4155
|
_sendSessionUpdate() {
|
|
4205
4156
|
const { scope, client } = this.getStackTop();
|
|
4157
|
+
if (!scope) return;
|
|
4206
4158
|
|
|
4207
4159
|
const session = scope.getSession();
|
|
4208
|
-
if (session
|
|
4209
|
-
client.captureSession
|
|
4160
|
+
if (session) {
|
|
4161
|
+
if (client && client.captureSession) {
|
|
4162
|
+
client.captureSession(session);
|
|
4163
|
+
}
|
|
4210
4164
|
}
|
|
4211
4165
|
}
|
|
4212
4166
|
|
|
@@ -4276,28 +4230,47 @@ function getCurrentHub() {
|
|
|
4276
4230
|
// Get main carrier (global for every environment)
|
|
4277
4231
|
const registry = getMainCarrier();
|
|
4278
4232
|
|
|
4279
|
-
if (registry.__SENTRY__ && registry.__SENTRY__.acs) {
|
|
4280
|
-
const hub = registry.__SENTRY__.acs.getCurrentHub();
|
|
4281
|
-
|
|
4282
|
-
if (hub) {
|
|
4283
|
-
return hub;
|
|
4284
|
-
}
|
|
4285
|
-
}
|
|
4286
|
-
|
|
4287
|
-
// Return hub that lives on a global object
|
|
4288
|
-
return getGlobalHub(registry);
|
|
4289
|
-
}
|
|
4290
|
-
|
|
4291
|
-
function getGlobalHub(registry = getMainCarrier()) {
|
|
4292
4233
|
// If there's no hub, or its an old API, assign a new one
|
|
4293
4234
|
if (!hasHubOnCarrier(registry) || getHubFromCarrier(registry).isOlderThan(API_VERSION)) {
|
|
4294
4235
|
setHubOnCarrier(registry, new Hub());
|
|
4295
4236
|
}
|
|
4296
4237
|
|
|
4238
|
+
// Prefer domains over global if they are there (applicable only to Node environment)
|
|
4239
|
+
if (isNodeEnv()) {
|
|
4240
|
+
return getHubFromActiveDomain(registry);
|
|
4241
|
+
}
|
|
4297
4242
|
// Return hub that lives on a global object
|
|
4298
4243
|
return getHubFromCarrier(registry);
|
|
4299
4244
|
}
|
|
4300
4245
|
|
|
4246
|
+
/**
|
|
4247
|
+
* Try to read the hub from an active domain, and fallback to the registry if one doesn't exist
|
|
4248
|
+
* @returns discovered hub
|
|
4249
|
+
*/
|
|
4250
|
+
function getHubFromActiveDomain(registry) {
|
|
4251
|
+
try {
|
|
4252
|
+
const sentry = getMainCarrier().__SENTRY__;
|
|
4253
|
+
const activeDomain = sentry && sentry.extensions && sentry.extensions.domain && sentry.extensions.domain.active;
|
|
4254
|
+
|
|
4255
|
+
// If there's no active domain, just return global hub
|
|
4256
|
+
if (!activeDomain) {
|
|
4257
|
+
return getHubFromCarrier(registry);
|
|
4258
|
+
}
|
|
4259
|
+
|
|
4260
|
+
// If there's no hub on current domain, or it's an old API, assign a new one
|
|
4261
|
+
if (!hasHubOnCarrier(activeDomain) || getHubFromCarrier(activeDomain).isOlderThan(API_VERSION)) {
|
|
4262
|
+
const registryHubTopStack = getHubFromCarrier(registry).getStackTop();
|
|
4263
|
+
setHubOnCarrier(activeDomain, new Hub(registryHubTopStack.client, Scope.clone(registryHubTopStack.scope)));
|
|
4264
|
+
}
|
|
4265
|
+
|
|
4266
|
+
// Return hub that lives on a domain
|
|
4267
|
+
return getHubFromCarrier(activeDomain);
|
|
4268
|
+
} catch (_Oo) {
|
|
4269
|
+
// Return hub that lives on a global object
|
|
4270
|
+
return getHubFromCarrier(registry);
|
|
4271
|
+
}
|
|
4272
|
+
}
|
|
4273
|
+
|
|
4301
4274
|
/**
|
|
4302
4275
|
* This will tell whether a carrier has a hub on it or not
|
|
4303
4276
|
* @param carrier object
|
|
@@ -4371,69 +4344,6 @@ var SpanStatus; (function (SpanStatus) {
|
|
|
4371
4344
|
const DataLoss = 'data_loss'; SpanStatus["DataLoss"] = DataLoss;
|
|
4372
4345
|
})(SpanStatus || (SpanStatus = {}));
|
|
4373
4346
|
|
|
4374
|
-
/**
|
|
4375
|
-
* Wraps a function with a transaction/span and finishes the span after the function is done.
|
|
4376
|
-
*
|
|
4377
|
-
* Note that if you have not enabled tracing extensions via `addTracingExtensions`, this function
|
|
4378
|
-
* will not generate spans, and the `span` returned from the callback may be undefined.
|
|
4379
|
-
*
|
|
4380
|
-
* This function is meant to be used internally and may break at any time. Use at your own risk.
|
|
4381
|
-
*
|
|
4382
|
-
* @internal
|
|
4383
|
-
* @private
|
|
4384
|
-
*/
|
|
4385
|
-
function trace(
|
|
4386
|
-
context,
|
|
4387
|
-
callback,
|
|
4388
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
4389
|
-
onError = () => {},
|
|
4390
|
-
) {
|
|
4391
|
-
const ctx = { ...context };
|
|
4392
|
-
// If a name is set and a description is not, set the description to the name.
|
|
4393
|
-
if (ctx.name !== undefined && ctx.description === undefined) {
|
|
4394
|
-
ctx.description = ctx.name;
|
|
4395
|
-
}
|
|
4396
|
-
|
|
4397
|
-
const hub = getCurrentHub();
|
|
4398
|
-
const scope = hub.getScope();
|
|
4399
|
-
|
|
4400
|
-
const parentSpan = scope.getSpan();
|
|
4401
|
-
const activeSpan = parentSpan ? parentSpan.startChild(ctx) : hub.startTransaction(ctx);
|
|
4402
|
-
scope.setSpan(activeSpan);
|
|
4403
|
-
|
|
4404
|
-
function finishAndSetSpan() {
|
|
4405
|
-
activeSpan && activeSpan.finish();
|
|
4406
|
-
hub.getScope().setSpan(parentSpan);
|
|
4407
|
-
}
|
|
4408
|
-
|
|
4409
|
-
let maybePromiseResult;
|
|
4410
|
-
try {
|
|
4411
|
-
maybePromiseResult = callback(activeSpan);
|
|
4412
|
-
} catch (e) {
|
|
4413
|
-
activeSpan && activeSpan.setStatus('internal_error');
|
|
4414
|
-
onError(e);
|
|
4415
|
-
finishAndSetSpan();
|
|
4416
|
-
throw e;
|
|
4417
|
-
}
|
|
4418
|
-
|
|
4419
|
-
if (isThenable(maybePromiseResult)) {
|
|
4420
|
-
Promise.resolve(maybePromiseResult).then(
|
|
4421
|
-
() => {
|
|
4422
|
-
finishAndSetSpan();
|
|
4423
|
-
},
|
|
4424
|
-
e => {
|
|
4425
|
-
activeSpan && activeSpan.setStatus('internal_error');
|
|
4426
|
-
onError(e);
|
|
4427
|
-
finishAndSetSpan();
|
|
4428
|
-
},
|
|
4429
|
-
);
|
|
4430
|
-
} else {
|
|
4431
|
-
finishAndSetSpan();
|
|
4432
|
-
}
|
|
4433
|
-
|
|
4434
|
-
return maybePromiseResult;
|
|
4435
|
-
}
|
|
4436
|
-
|
|
4437
4347
|
// Note: All functions in this file are typed with a return value of `ReturnType<Hub[HUB_FUNCTION]>`,
|
|
4438
4348
|
// where HUB_FUNCTION is some method on the Hub class.
|
|
4439
4349
|
//
|
|
@@ -4775,11 +4685,7 @@ function prepareEvent(
|
|
|
4775
4685
|
|
|
4776
4686
|
applyClientOptions(prepared, options);
|
|
4777
4687
|
applyIntegrationsMetadata(prepared, integrations);
|
|
4778
|
-
|
|
4779
|
-
// Only apply debug metadata to error events.
|
|
4780
|
-
if (event.type === undefined) {
|
|
4781
|
-
applyDebugMetadata(prepared, options.stackParser);
|
|
4782
|
-
}
|
|
4688
|
+
applyDebugMetadata(prepared, options.stackParser);
|
|
4783
4689
|
|
|
4784
4690
|
// If we have scope given to us, use it as the base for further modifications.
|
|
4785
4691
|
// This allows us to prevent unnecessary copying of data if `captureContext` is not provided.
|
|
@@ -4856,8 +4762,6 @@ function applyClientOptions(event, options) {
|
|
|
4856
4762
|
}
|
|
4857
4763
|
}
|
|
4858
4764
|
|
|
4859
|
-
const debugIdStackParserCache = new WeakMap();
|
|
4860
|
-
|
|
4861
4765
|
/**
|
|
4862
4766
|
* Applies debug metadata images to the event in order to apply source maps by looking up their debug ID.
|
|
4863
4767
|
*/
|
|
@@ -4868,28 +4772,10 @@ function applyDebugMetadata(event, stackParser) {
|
|
|
4868
4772
|
return;
|
|
4869
4773
|
}
|
|
4870
4774
|
|
|
4871
|
-
let debugIdStackFramesCache;
|
|
4872
|
-
const cachedDebugIdStackFrameCache = debugIdStackParserCache.get(stackParser);
|
|
4873
|
-
if (cachedDebugIdStackFrameCache) {
|
|
4874
|
-
debugIdStackFramesCache = cachedDebugIdStackFrameCache;
|
|
4875
|
-
} else {
|
|
4876
|
-
debugIdStackFramesCache = new Map();
|
|
4877
|
-
debugIdStackParserCache.set(stackParser, debugIdStackFramesCache);
|
|
4878
|
-
}
|
|
4879
|
-
|
|
4880
4775
|
// Build a map of filename -> debug_id
|
|
4881
4776
|
const filenameDebugIdMap = Object.keys(debugIdMap).reduce((acc, debugIdStackTrace) => {
|
|
4882
|
-
|
|
4883
|
-
const
|
|
4884
|
-
if (cachedParsedStack) {
|
|
4885
|
-
parsedStack = cachedParsedStack;
|
|
4886
|
-
} else {
|
|
4887
|
-
parsedStack = stackParser(debugIdStackTrace);
|
|
4888
|
-
debugIdStackFramesCache.set(debugIdStackTrace, parsedStack);
|
|
4889
|
-
}
|
|
4890
|
-
|
|
4891
|
-
for (let i = parsedStack.length - 1; i >= 0; i--) {
|
|
4892
|
-
const stackFrame = parsedStack[i];
|
|
4777
|
+
const parsedStack = stackParser(debugIdStackTrace);
|
|
4778
|
+
for (const stackFrame of parsedStack) {
|
|
4893
4779
|
if (stackFrame.filename) {
|
|
4894
4780
|
acc[stackFrame.filename] = debugIdMap[debugIdStackTrace];
|
|
4895
4781
|
break;
|
|
@@ -5794,7 +5680,7 @@ function getEventForEnvelopeItem(item, type) {
|
|
|
5794
5680
|
return Array.isArray(item) ? (item )[1] : undefined;
|
|
5795
5681
|
}
|
|
5796
5682
|
|
|
5797
|
-
const SDK_VERSION = '7.
|
|
5683
|
+
const SDK_VERSION = '7.46.0';
|
|
5798
5684
|
|
|
5799
5685
|
let originalFunctionToString;
|
|
5800
5686
|
|
|
@@ -5817,17 +5703,11 @@ class FunctionToString {constructor() { FunctionToString.prototype.__init.call(
|
|
|
5817
5703
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
5818
5704
|
originalFunctionToString = Function.prototype.toString;
|
|
5819
5705
|
|
|
5820
|
-
//
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
const context = getOriginalFunction(this) || this;
|
|
5826
|
-
return originalFunctionToString.apply(context, args);
|
|
5827
|
-
};
|
|
5828
|
-
} catch (e) {
|
|
5829
|
-
// ignore errors here, just don't patch this
|
|
5830
|
-
}
|
|
5706
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5707
|
+
Function.prototype.toString = function ( ...args) {
|
|
5708
|
+
const context = getOriginalFunction(this) || this;
|
|
5709
|
+
return originalFunctionToString.apply(context, args);
|
|
5710
|
+
};
|
|
5831
5711
|
}
|
|
5832
5712
|
} FunctionToString.__initStatic();
|
|
5833
5713
|
|
|
@@ -5975,9 +5855,8 @@ function _getPossibleEventMessages(event) {
|
|
|
5975
5855
|
return [event.message];
|
|
5976
5856
|
}
|
|
5977
5857
|
if (event.exception) {
|
|
5978
|
-
const { values } = event.exception;
|
|
5979
5858
|
try {
|
|
5980
|
-
const { type = '', value = '' } = (values && values[
|
|
5859
|
+
const { type = '', value = '' } = (event.exception.values && event.exception.values[0]) || {};
|
|
5981
5860
|
return [`${value}`, `${type}: ${value}`];
|
|
5982
5861
|
} catch (oO) {
|
|
5983
5862
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error(`Cannot extract message for event ${getEventDescription(event)}`);
|
|
@@ -6027,9 +5906,9 @@ function _getEventFilterUrl(event) {
|
|
|
6027
5906
|
}
|
|
6028
5907
|
|
|
6029
5908
|
var Integrations = /*#__PURE__*/Object.freeze({
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
5909
|
+
__proto__: null,
|
|
5910
|
+
FunctionToString: FunctionToString,
|
|
5911
|
+
InboundFilters: InboundFilters
|
|
6033
5912
|
});
|
|
6034
5913
|
|
|
6035
5914
|
const WINDOW$1 = GLOBAL_OBJ ;
|
|
@@ -6636,14 +6515,12 @@ function _consoleBreadcrumb(handlerData) {
|
|
|
6636
6515
|
function _xhrBreadcrumb(handlerData) {
|
|
6637
6516
|
const { startTimestamp, endTimestamp } = handlerData;
|
|
6638
6517
|
|
|
6639
|
-
const sentryXhrData = handlerData.xhr[SENTRY_XHR_DATA_KEY];
|
|
6640
|
-
|
|
6641
6518
|
// We only capture complete, non-sentry requests
|
|
6642
|
-
if (!startTimestamp || !endTimestamp || !
|
|
6519
|
+
if (!startTimestamp || !endTimestamp || !handlerData.xhr.__sentry_xhr__) {
|
|
6643
6520
|
return;
|
|
6644
6521
|
}
|
|
6645
6522
|
|
|
6646
|
-
const { method, url, status_code, body } =
|
|
6523
|
+
const { method, url, status_code, body } = handlerData.xhr.__sentry_xhr__;
|
|
6647
6524
|
|
|
6648
6525
|
const data = {
|
|
6649
6526
|
method,
|
|
@@ -6761,43 +6638,6 @@ function _isEvent(event) {
|
|
|
6761
6638
|
return event && !!(event ).target;
|
|
6762
6639
|
}
|
|
6763
6640
|
|
|
6764
|
-
/**
|
|
6765
|
-
* Creates an envelope from a user feedback.
|
|
6766
|
-
*/
|
|
6767
|
-
function createUserFeedbackEnvelope(
|
|
6768
|
-
feedback,
|
|
6769
|
-
{
|
|
6770
|
-
metadata,
|
|
6771
|
-
tunnel,
|
|
6772
|
-
dsn,
|
|
6773
|
-
}
|
|
6774
|
-
|
|
6775
|
-
,
|
|
6776
|
-
) {
|
|
6777
|
-
const headers = {
|
|
6778
|
-
event_id: feedback.event_id,
|
|
6779
|
-
sent_at: new Date().toISOString(),
|
|
6780
|
-
...(metadata &&
|
|
6781
|
-
metadata.sdk && {
|
|
6782
|
-
sdk: {
|
|
6783
|
-
name: metadata.sdk.name,
|
|
6784
|
-
version: metadata.sdk.version,
|
|
6785
|
-
},
|
|
6786
|
-
}),
|
|
6787
|
-
...(!!tunnel && !!dsn && { dsn: dsnToString(dsn) }),
|
|
6788
|
-
};
|
|
6789
|
-
const item = createUserFeedbackEnvelopeItem(feedback);
|
|
6790
|
-
|
|
6791
|
-
return createEnvelope(headers, [item]);
|
|
6792
|
-
}
|
|
6793
|
-
|
|
6794
|
-
function createUserFeedbackEnvelopeItem(feedback) {
|
|
6795
|
-
const feedbackHeaders = {
|
|
6796
|
-
type: 'user_report',
|
|
6797
|
-
};
|
|
6798
|
-
return [feedbackHeaders, feedback];
|
|
6799
|
-
}
|
|
6800
|
-
|
|
6801
6641
|
/**
|
|
6802
6642
|
* Configuration options for the Sentry Browser SDK.
|
|
6803
6643
|
* @see @sentry/types Options for more information.
|
|
@@ -6880,23 +6720,6 @@ class BrowserClient extends BaseClient {
|
|
|
6880
6720
|
super.sendEvent(event, hint);
|
|
6881
6721
|
}
|
|
6882
6722
|
|
|
6883
|
-
/**
|
|
6884
|
-
* Sends user feedback to Sentry.
|
|
6885
|
-
*/
|
|
6886
|
-
captureUserFeedback(feedback) {
|
|
6887
|
-
if (!this._isEnabled()) {
|
|
6888
|
-
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('SDK not enabled, will not capture user feedback.');
|
|
6889
|
-
return;
|
|
6890
|
-
}
|
|
6891
|
-
|
|
6892
|
-
const envelope = createUserFeedbackEnvelope(feedback, {
|
|
6893
|
-
metadata: this.getSdkMetadata(),
|
|
6894
|
-
dsn: this.getDsn(),
|
|
6895
|
-
tunnel: this.getOptions().tunnel,
|
|
6896
|
-
});
|
|
6897
|
-
void this._sendEnvelope(envelope);
|
|
6898
|
-
}
|
|
6899
|
-
|
|
6900
6723
|
/**
|
|
6901
6724
|
* @inheritDoc
|
|
6902
6725
|
*/
|
|
@@ -7139,7 +6962,7 @@ function createFrame(filename, func, lineno, colno) {
|
|
|
7139
6962
|
|
|
7140
6963
|
// Chromium based browsers: Chrome, Brave, new Opera, new Edge
|
|
7141
6964
|
const chromeRegex =
|
|
7142
|
-
/^\s*at (?:(
|
|
6965
|
+
/^\s*at (?:(.*\).*?|.*?) ?\((?:address at )?)?(?:async )?((?:file|https?|blob|chrome-extension|address|native|eval|webpack|<anonymous>|[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
|
|
7143
6966
|
const chromeEvalRegex = /\((\S*)(?::(\d+))(?::(\d+))\)/;
|
|
7144
6967
|
|
|
7145
6968
|
const chrome = line => {
|
|
@@ -7175,7 +6998,7 @@ const chromeStackLineParser = [CHROME_PRIORITY, chrome];
|
|
|
7175
6998
|
// generates filenames without a prefix like `file://` the filenames in the stacktrace are just 42.js
|
|
7176
6999
|
// We need this specific case for now because we want no other regex to match.
|
|
7177
7000
|
const geckoREgex =
|
|
7178
|
-
/^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:
|
|
7001
|
+
/^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:file|https?|blob|chrome|webpack|resource|moz-extension|safari-extension|safari-web-extension|capacitor)?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js)|\/[\w\-. /=]+)(?::(\d+))?(?::(\d+))?\s*$/i;
|
|
7179
7002
|
const geckoEvalRegex = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
|
|
7180
7003
|
|
|
7181
7004
|
const gecko = line => {
|
|
@@ -7207,7 +7030,8 @@ const gecko = line => {
|
|
|
7207
7030
|
|
|
7208
7031
|
const geckoStackLineParser = [GECKO_PRIORITY, gecko];
|
|
7209
7032
|
|
|
7210
|
-
const winjsRegex =
|
|
7033
|
+
const winjsRegex =
|
|
7034
|
+
/^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
|
|
7211
7035
|
|
|
7212
7036
|
const winjs = line => {
|
|
7213
7037
|
const parts = winjsRegex.exec(line);
|
|
@@ -8253,13 +8077,13 @@ function startSessionTracking() {
|
|
|
8253
8077
|
}
|
|
8254
8078
|
|
|
8255
8079
|
var index$1 = /*#__PURE__*/Object.freeze({
|
|
8256
|
-
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8080
|
+
__proto__: null,
|
|
8081
|
+
GlobalHandlers: GlobalHandlers,
|
|
8082
|
+
TryCatch: TryCatch,
|
|
8083
|
+
Breadcrumbs: Breadcrumbs,
|
|
8084
|
+
LinkedErrors: LinkedErrors,
|
|
8085
|
+
HttpContext: HttpContext,
|
|
8086
|
+
Dedupe: Dedupe
|
|
8263
8087
|
});
|
|
8264
8088
|
|
|
8265
8089
|
// exporting a separate copy of `WINDOW` rather than exporting the one from `@sentry/browser`
|
|
@@ -8272,14 +8096,11 @@ const REPLAY_SESSION_KEY = 'sentryReplaySession';
|
|
|
8272
8096
|
const REPLAY_EVENT_NAME = 'replay_event';
|
|
8273
8097
|
const UNABLE_TO_SEND_REPLAY = 'Unable to send Replay';
|
|
8274
8098
|
|
|
8275
|
-
// The idle limit for a session
|
|
8276
|
-
const
|
|
8277
|
-
|
|
8278
|
-
// The idle limit for a session after which the session expires.
|
|
8279
|
-
const SESSION_IDLE_EXPIRE_DURATION = 900000; // 15 minutes in ms
|
|
8099
|
+
// The idle limit for a session
|
|
8100
|
+
const SESSION_IDLE_DURATION = 300000; // 5 minutes in ms
|
|
8280
8101
|
|
|
8281
8102
|
// The maximum length of a session
|
|
8282
|
-
const MAX_SESSION_LIFE = 3600000; // 60 minutes
|
|
8103
|
+
const MAX_SESSION_LIFE = 3600000; // 60 minutes
|
|
8283
8104
|
|
|
8284
8105
|
/** Default flush delays */
|
|
8285
8106
|
const DEFAULT_FLUSH_MIN_DELAY = 5000;
|
|
@@ -8288,16 +8109,13 @@ const DEFAULT_FLUSH_MIN_DELAY = 5000;
|
|
|
8288
8109
|
const DEFAULT_FLUSH_MAX_DELAY = 5500;
|
|
8289
8110
|
|
|
8290
8111
|
/* How long to wait for error checkouts */
|
|
8291
|
-
const
|
|
8112
|
+
const ERROR_CHECKOUT_TIME = 60000;
|
|
8292
8113
|
|
|
8293
8114
|
const RETRY_BASE_INTERVAL = 5000;
|
|
8294
8115
|
const RETRY_MAX_COUNT = 3;
|
|
8295
8116
|
|
|
8296
|
-
/* The max (uncompressed) size in bytes of a network body. Any body larger than this will be
|
|
8297
|
-
const NETWORK_BODY_MAX_SIZE =
|
|
8298
|
-
|
|
8299
|
-
/* The max size of a single console arg that is captured. Any arg larger than this will be truncated. */
|
|
8300
|
-
const CONSOLE_ARG_MAX_SIZE = 5000;
|
|
8117
|
+
/* The max (uncompressed) size in bytes of a network body. Any body larger than this will be dropped. */
|
|
8118
|
+
const NETWORK_BODY_MAX_SIZE = 300000;
|
|
8301
8119
|
|
|
8302
8120
|
var NodeType$1;
|
|
8303
8121
|
(function (NodeType) {
|
|
@@ -8334,7 +8152,7 @@ function maskInputValue({ input, maskInputSelector, unmaskInputSelector, maskInp
|
|
|
8334
8152
|
if (unmaskInputSelector && input.matches(unmaskInputSelector)) {
|
|
8335
8153
|
return text;
|
|
8336
8154
|
}
|
|
8337
|
-
if (input.hasAttribute('
|
|
8155
|
+
if (input.hasAttribute('rr_is_password')) {
|
|
8338
8156
|
type = 'password';
|
|
8339
8157
|
}
|
|
8340
8158
|
if (isInputTypeMasked({ maskInputOptions, tagName, type }) ||
|
|
@@ -8367,21 +8185,6 @@ function is2DCanvasBlank(canvas) {
|
|
|
8367
8185
|
}
|
|
8368
8186
|
return true;
|
|
8369
8187
|
}
|
|
8370
|
-
function getInputType(element) {
|
|
8371
|
-
const type = element.type;
|
|
8372
|
-
return element.hasAttribute('data-rr-is-password')
|
|
8373
|
-
? 'password'
|
|
8374
|
-
: type
|
|
8375
|
-
? type.toLowerCase()
|
|
8376
|
-
: null;
|
|
8377
|
-
}
|
|
8378
|
-
function getInputValue(el, tagName, type) {
|
|
8379
|
-
typeof type === 'string' ? type.toLowerCase() : '';
|
|
8380
|
-
if (tagName === 'INPUT' && (type === 'radio' || type === 'checkbox')) {
|
|
8381
|
-
return el.getAttribute('value') || '';
|
|
8382
|
-
}
|
|
8383
|
-
return el.value;
|
|
8384
|
-
}
|
|
8385
8188
|
|
|
8386
8189
|
let _id = 1;
|
|
8387
8190
|
const tagNameRegex = new RegExp('[^a-z0-9-_:]');
|
|
@@ -8420,13 +8223,6 @@ function getCssRuleString(rule) {
|
|
|
8420
8223
|
catch (_a) {
|
|
8421
8224
|
}
|
|
8422
8225
|
}
|
|
8423
|
-
return validateStringifiedCssRule(cssStringified);
|
|
8424
|
-
}
|
|
8425
|
-
function validateStringifiedCssRule(cssStringified) {
|
|
8426
|
-
if (cssStringified.indexOf(':') > -1) {
|
|
8427
|
-
const regex = /(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;
|
|
8428
|
-
return cssStringified.replace(regex, '$1\\$2');
|
|
8429
|
-
}
|
|
8430
8226
|
return cssStringified;
|
|
8431
8227
|
}
|
|
8432
8228
|
function isCSSImportRule(rule) {
|
|
@@ -8435,7 +8231,7 @@ function isCSSImportRule(rule) {
|
|
|
8435
8231
|
function stringifyStyleSheet(sheet) {
|
|
8436
8232
|
return sheet.cssRules
|
|
8437
8233
|
? Array.from(sheet.cssRules)
|
|
8438
|
-
.map((rule) => rule.cssText
|
|
8234
|
+
.map((rule) => rule.cssText || '')
|
|
8439
8235
|
.join('')
|
|
8440
8236
|
: '';
|
|
8441
8237
|
}
|
|
@@ -8770,15 +8566,14 @@ function serializeNode(n, options) {
|
|
|
8770
8566
|
tagName === 'select' ||
|
|
8771
8567
|
tagName === 'option') {
|
|
8772
8568
|
const el = n;
|
|
8773
|
-
const
|
|
8774
|
-
const value = getInputValue(el, tagName.toUpperCase(), type);
|
|
8569
|
+
const value = getInputValue(tagName, el, attributes);
|
|
8775
8570
|
const checked = n.checked;
|
|
8776
|
-
if (type !== 'submit' &&
|
|
8777
|
-
type !== 'button' &&
|
|
8571
|
+
if (attributes.type !== 'submit' &&
|
|
8572
|
+
attributes.type !== 'button' &&
|
|
8778
8573
|
value) {
|
|
8779
8574
|
attributes.value = maskInputValue({
|
|
8780
8575
|
input: el,
|
|
8781
|
-
type,
|
|
8576
|
+
type: attributes.type,
|
|
8782
8577
|
tagName,
|
|
8783
8578
|
value,
|
|
8784
8579
|
maskInputSelector,
|
|
@@ -9251,8 +9046,15 @@ function snapshot(n, options) {
|
|
|
9251
9046
|
function skipAttribute(tagName, attributeName, value) {
|
|
9252
9047
|
return ((tagName === 'video' || tagName === 'audio') && attributeName === 'autoplay');
|
|
9253
9048
|
}
|
|
9049
|
+
function getInputValue(tagName, el, attributes) {
|
|
9050
|
+
if (tagName === 'input' &&
|
|
9051
|
+
(attributes.type === 'radio' || attributes.type === 'checkbox')) {
|
|
9052
|
+
return el.getAttribute('value') || '';
|
|
9053
|
+
}
|
|
9054
|
+
return el.value;
|
|
9055
|
+
}
|
|
9254
9056
|
|
|
9255
|
-
var EventType
|
|
9057
|
+
var EventType;
|
|
9256
9058
|
(function (EventType) {
|
|
9257
9059
|
EventType[EventType["DomContentLoaded"] = 0] = "DomContentLoaded";
|
|
9258
9060
|
EventType[EventType["Load"] = 1] = "Load";
|
|
@@ -9261,7 +9063,7 @@ var EventType$1;
|
|
|
9261
9063
|
EventType[EventType["Meta"] = 4] = "Meta";
|
|
9262
9064
|
EventType[EventType["Custom"] = 5] = "Custom";
|
|
9263
9065
|
EventType[EventType["Plugin"] = 6] = "Plugin";
|
|
9264
|
-
})(EventType
|
|
9066
|
+
})(EventType || (EventType = {}));
|
|
9265
9067
|
var IncrementalSource;
|
|
9266
9068
|
(function (IncrementalSource) {
|
|
9267
9069
|
IncrementalSource[IncrementalSource["Mutation"] = 0] = "Mutation";
|
|
@@ -9876,9 +9678,9 @@ class MutationBuffer {
|
|
|
9876
9678
|
this.attributes.push(item);
|
|
9877
9679
|
}
|
|
9878
9680
|
if (m.attributeName === 'type' &&
|
|
9879
|
-
target.tagName === 'INPUT' &&
|
|
9681
|
+
m.target.tagName === 'INPUT' &&
|
|
9880
9682
|
(m.oldValue || '').toLowerCase() === 'password') {
|
|
9881
|
-
target.setAttribute('
|
|
9683
|
+
m.target.setAttribute('rr_is_password', 'true');
|
|
9882
9684
|
}
|
|
9883
9685
|
if (m.attributeName === 'style') {
|
|
9884
9686
|
const old = this.doc.createElement('span');
|
|
@@ -10275,25 +10077,27 @@ function initInputObserver({ inputCb, doc, mirror, blockClass, blockSelector, un
|
|
|
10275
10077
|
isBlocked(target, blockClass, blockSelector, unblockSelector)) {
|
|
10276
10078
|
return;
|
|
10277
10079
|
}
|
|
10278
|
-
|
|
10279
|
-
|
|
10280
|
-
|
|
10281
|
-
(ignoreSelector && el.matches(ignoreSelector))) {
|
|
10080
|
+
let type = target.type;
|
|
10081
|
+
if (target.classList.contains(ignoreClass) ||
|
|
10082
|
+
(ignoreSelector && target.matches(ignoreSelector))) {
|
|
10282
10083
|
return;
|
|
10283
10084
|
}
|
|
10284
|
-
let text =
|
|
10085
|
+
let text = target.value;
|
|
10285
10086
|
let isChecked = false;
|
|
10087
|
+
if (target.hasAttribute('rr_is_password')) {
|
|
10088
|
+
type = 'password';
|
|
10089
|
+
}
|
|
10286
10090
|
if (type === 'radio' || type === 'checkbox') {
|
|
10287
10091
|
isChecked = target.checked;
|
|
10288
10092
|
}
|
|
10289
|
-
if (hasInputMaskOptions({
|
|
10093
|
+
else if (hasInputMaskOptions({
|
|
10290
10094
|
maskInputOptions,
|
|
10291
10095
|
maskInputSelector,
|
|
10292
10096
|
tagName,
|
|
10293
10097
|
type,
|
|
10294
10098
|
})) {
|
|
10295
10099
|
text = maskInputValue({
|
|
10296
|
-
input:
|
|
10100
|
+
input: target,
|
|
10297
10101
|
maskInputOptions,
|
|
10298
10102
|
maskInputSelector,
|
|
10299
10103
|
unmaskInputSelector,
|
|
@@ -10310,18 +10114,8 @@ function initInputObserver({ inputCb, doc, mirror, blockClass, blockSelector, un
|
|
|
10310
10114
|
.querySelectorAll(`input[type="radio"][name="${name}"]`)
|
|
10311
10115
|
.forEach((el) => {
|
|
10312
10116
|
if (el !== target) {
|
|
10313
|
-
const text = maskInputValue({
|
|
10314
|
-
input: el,
|
|
10315
|
-
maskInputOptions,
|
|
10316
|
-
maskInputSelector,
|
|
10317
|
-
unmaskInputSelector,
|
|
10318
|
-
tagName,
|
|
10319
|
-
type,
|
|
10320
|
-
value: getInputValue(el, tagName, type),
|
|
10321
|
-
maskInputFn,
|
|
10322
|
-
});
|
|
10323
10117
|
cbWithDedup(el, callbackWrapper(wrapEventWithUserTriggeredFlag)({
|
|
10324
|
-
text,
|
|
10118
|
+
text: el.value,
|
|
10325
10119
|
isChecked: !isChecked,
|
|
10326
10120
|
userTriggered: false,
|
|
10327
10121
|
}, userTriggeredOnInput));
|
|
@@ -11234,17 +11028,17 @@ function record(options = {}) {
|
|
|
11234
11028
|
wrappedEmit = (e, isCheckout) => {
|
|
11235
11029
|
var _a;
|
|
11236
11030
|
if (((_a = mutationBuffers[0]) === null || _a === void 0 ? void 0 : _a.isFrozen()) &&
|
|
11237
|
-
e.type !== EventType
|
|
11238
|
-
!(e.type === EventType
|
|
11031
|
+
e.type !== EventType.FullSnapshot &&
|
|
11032
|
+
!(e.type === EventType.IncrementalSnapshot &&
|
|
11239
11033
|
e.data.source === IncrementalSource.Mutation)) {
|
|
11240
11034
|
mutationBuffers.forEach((buf) => buf.unfreeze());
|
|
11241
11035
|
}
|
|
11242
11036
|
emit(eventProcessor(e), isCheckout);
|
|
11243
|
-
if (e.type === EventType
|
|
11037
|
+
if (e.type === EventType.FullSnapshot) {
|
|
11244
11038
|
lastFullSnapshotEvent = e;
|
|
11245
11039
|
incrementalSnapshotCount = 0;
|
|
11246
11040
|
}
|
|
11247
|
-
else if (e.type === EventType
|
|
11041
|
+
else if (e.type === EventType.IncrementalSnapshot) {
|
|
11248
11042
|
if (e.data.source === IncrementalSource.Mutation &&
|
|
11249
11043
|
e.data.isAttachIframe) {
|
|
11250
11044
|
return;
|
|
@@ -11260,16 +11054,16 @@ function record(options = {}) {
|
|
|
11260
11054
|
};
|
|
11261
11055
|
const wrappedMutationEmit = (m) => {
|
|
11262
11056
|
wrappedEmit(wrapEvent({
|
|
11263
|
-
type: EventType
|
|
11057
|
+
type: EventType.IncrementalSnapshot,
|
|
11264
11058
|
data: Object.assign({ source: IncrementalSource.Mutation }, m),
|
|
11265
11059
|
}));
|
|
11266
11060
|
};
|
|
11267
11061
|
const wrappedScrollEmit = (p) => wrappedEmit(wrapEvent({
|
|
11268
|
-
type: EventType
|
|
11062
|
+
type: EventType.IncrementalSnapshot,
|
|
11269
11063
|
data: Object.assign({ source: IncrementalSource.Scroll }, p),
|
|
11270
11064
|
}));
|
|
11271
11065
|
const wrappedCanvasMutationEmit = (p) => wrappedEmit(wrapEvent({
|
|
11272
|
-
type: EventType
|
|
11066
|
+
type: EventType.IncrementalSnapshot,
|
|
11273
11067
|
data: Object.assign({ source: IncrementalSource.CanvasMutation }, p),
|
|
11274
11068
|
}));
|
|
11275
11069
|
const iframeManager = new IframeManager({
|
|
@@ -11314,7 +11108,7 @@ function record(options = {}) {
|
|
|
11314
11108
|
takeFullSnapshot = (isCheckout = false) => {
|
|
11315
11109
|
var _a, _b, _c, _d;
|
|
11316
11110
|
wrappedEmit(wrapEvent({
|
|
11317
|
-
type: EventType
|
|
11111
|
+
type: EventType.Meta,
|
|
11318
11112
|
data: {
|
|
11319
11113
|
href: window.location.href,
|
|
11320
11114
|
width: getWindowWidth(),
|
|
@@ -11357,7 +11151,7 @@ function record(options = {}) {
|
|
|
11357
11151
|
}
|
|
11358
11152
|
mirror.map = idNodeMap;
|
|
11359
11153
|
wrappedEmit(wrapEvent({
|
|
11360
|
-
type: EventType
|
|
11154
|
+
type: EventType.FullSnapshot,
|
|
11361
11155
|
data: {
|
|
11362
11156
|
node,
|
|
11363
11157
|
initialOffset: {
|
|
@@ -11382,7 +11176,7 @@ function record(options = {}) {
|
|
|
11382
11176
|
const handlers = [];
|
|
11383
11177
|
handlers.push(on$1('DOMContentLoaded', () => {
|
|
11384
11178
|
wrappedEmit(wrapEvent({
|
|
11385
|
-
type: EventType
|
|
11179
|
+
type: EventType.DomContentLoaded,
|
|
11386
11180
|
data: {},
|
|
11387
11181
|
}));
|
|
11388
11182
|
}));
|
|
@@ -11392,40 +11186,40 @@ function record(options = {}) {
|
|
|
11392
11186
|
onMutation,
|
|
11393
11187
|
mutationCb: wrappedMutationEmit,
|
|
11394
11188
|
mousemoveCb: (positions, source) => wrappedEmit(wrapEvent({
|
|
11395
|
-
type: EventType
|
|
11189
|
+
type: EventType.IncrementalSnapshot,
|
|
11396
11190
|
data: {
|
|
11397
11191
|
source,
|
|
11398
11192
|
positions,
|
|
11399
11193
|
},
|
|
11400
11194
|
})),
|
|
11401
11195
|
mouseInteractionCb: (d) => wrappedEmit(wrapEvent({
|
|
11402
|
-
type: EventType
|
|
11196
|
+
type: EventType.IncrementalSnapshot,
|
|
11403
11197
|
data: Object.assign({ source: IncrementalSource.MouseInteraction }, d),
|
|
11404
11198
|
})),
|
|
11405
11199
|
scrollCb: wrappedScrollEmit,
|
|
11406
11200
|
viewportResizeCb: (d) => wrappedEmit(wrapEvent({
|
|
11407
|
-
type: EventType
|
|
11201
|
+
type: EventType.IncrementalSnapshot,
|
|
11408
11202
|
data: Object.assign({ source: IncrementalSource.ViewportResize }, d),
|
|
11409
11203
|
})),
|
|
11410
11204
|
inputCb: (v) => wrappedEmit(wrapEvent({
|
|
11411
|
-
type: EventType
|
|
11205
|
+
type: EventType.IncrementalSnapshot,
|
|
11412
11206
|
data: Object.assign({ source: IncrementalSource.Input }, v),
|
|
11413
11207
|
})),
|
|
11414
11208
|
mediaInteractionCb: (p) => wrappedEmit(wrapEvent({
|
|
11415
|
-
type: EventType
|
|
11209
|
+
type: EventType.IncrementalSnapshot,
|
|
11416
11210
|
data: Object.assign({ source: IncrementalSource.MediaInteraction }, p),
|
|
11417
11211
|
})),
|
|
11418
11212
|
styleSheetRuleCb: (r) => wrappedEmit(wrapEvent({
|
|
11419
|
-
type: EventType
|
|
11213
|
+
type: EventType.IncrementalSnapshot,
|
|
11420
11214
|
data: Object.assign({ source: IncrementalSource.StyleSheetRule }, r),
|
|
11421
11215
|
})),
|
|
11422
11216
|
styleDeclarationCb: (r) => wrappedEmit(wrapEvent({
|
|
11423
|
-
type: EventType
|
|
11217
|
+
type: EventType.IncrementalSnapshot,
|
|
11424
11218
|
data: Object.assign({ source: IncrementalSource.StyleDeclaration }, r),
|
|
11425
11219
|
})),
|
|
11426
11220
|
canvasMutationCb: wrappedCanvasMutationEmit,
|
|
11427
11221
|
fontCb: (p) => wrappedEmit(wrapEvent({
|
|
11428
|
-
type: EventType
|
|
11222
|
+
type: EventType.IncrementalSnapshot,
|
|
11429
11223
|
data: Object.assign({ source: IncrementalSource.Font }, p),
|
|
11430
11224
|
})),
|
|
11431
11225
|
blockClass,
|
|
@@ -11458,7 +11252,7 @@ function record(options = {}) {
|
|
|
11458
11252
|
observer: p.observer,
|
|
11459
11253
|
options: p.options,
|
|
11460
11254
|
callback: (payload) => wrappedEmit(wrapEvent({
|
|
11461
|
-
type: EventType
|
|
11255
|
+
type: EventType.Plugin,
|
|
11462
11256
|
data: {
|
|
11463
11257
|
plugin: p.name,
|
|
11464
11258
|
payload,
|
|
@@ -11486,7 +11280,7 @@ function record(options = {}) {
|
|
|
11486
11280
|
else {
|
|
11487
11281
|
handlers.push(on$1('load', () => {
|
|
11488
11282
|
wrappedEmit(wrapEvent({
|
|
11489
|
-
type: EventType
|
|
11283
|
+
type: EventType.Load,
|
|
11490
11284
|
data: {},
|
|
11491
11285
|
}));
|
|
11492
11286
|
init();
|
|
@@ -11505,7 +11299,7 @@ record.addCustomEvent = (tag, payload) => {
|
|
|
11505
11299
|
throw new Error('please add custom event after start recording');
|
|
11506
11300
|
}
|
|
11507
11301
|
wrappedEmit(wrapEvent({
|
|
11508
|
-
type: EventType
|
|
11302
|
+
type: EventType.Custom,
|
|
11509
11303
|
data: {
|
|
11510
11304
|
tag,
|
|
11511
11305
|
payload,
|
|
@@ -11523,475 +11317,6 @@ record.takeFullSnapshot = (isCheckout) => {
|
|
|
11523
11317
|
};
|
|
11524
11318
|
record.mirror = mirror;
|
|
11525
11319
|
|
|
11526
|
-
/**
|
|
11527
|
-
* Create a breadcrumb for a replay.
|
|
11528
|
-
*/
|
|
11529
|
-
function createBreadcrumb(
|
|
11530
|
-
breadcrumb,
|
|
11531
|
-
) {
|
|
11532
|
-
return {
|
|
11533
|
-
timestamp: Date.now() / 1000,
|
|
11534
|
-
type: 'default',
|
|
11535
|
-
...breadcrumb,
|
|
11536
|
-
};
|
|
11537
|
-
}
|
|
11538
|
-
|
|
11539
|
-
var NodeType;
|
|
11540
|
-
(function (NodeType) {
|
|
11541
|
-
NodeType[NodeType["Document"] = 0] = "Document";
|
|
11542
|
-
NodeType[NodeType["DocumentType"] = 1] = "DocumentType";
|
|
11543
|
-
NodeType[NodeType["Element"] = 2] = "Element";
|
|
11544
|
-
NodeType[NodeType["Text"] = 3] = "Text";
|
|
11545
|
-
NodeType[NodeType["CDATA"] = 4] = "CDATA";
|
|
11546
|
-
NodeType[NodeType["Comment"] = 5] = "Comment";
|
|
11547
|
-
})(NodeType || (NodeType = {}));
|
|
11548
|
-
|
|
11549
|
-
/**
|
|
11550
|
-
* Converts a timestamp to ms, if it was in s, or keeps it as ms.
|
|
11551
|
-
*/
|
|
11552
|
-
function timestampToMs(timestamp) {
|
|
11553
|
-
const isMs = timestamp > 9999999999;
|
|
11554
|
-
return isMs ? timestamp : timestamp * 1000;
|
|
11555
|
-
}
|
|
11556
|
-
|
|
11557
|
-
/**
|
|
11558
|
-
* Add an event to the event buffer.
|
|
11559
|
-
* `isCheckout` is true if this is either the very first event, or an event triggered by `checkoutEveryNms`.
|
|
11560
|
-
*/
|
|
11561
|
-
async function addEvent(
|
|
11562
|
-
replay,
|
|
11563
|
-
event,
|
|
11564
|
-
isCheckout,
|
|
11565
|
-
) {
|
|
11566
|
-
if (!replay.eventBuffer) {
|
|
11567
|
-
// This implies that `_isEnabled` is false
|
|
11568
|
-
return null;
|
|
11569
|
-
}
|
|
11570
|
-
|
|
11571
|
-
if (replay.isPaused()) {
|
|
11572
|
-
// Do not add to event buffer when recording is paused
|
|
11573
|
-
return null;
|
|
11574
|
-
}
|
|
11575
|
-
|
|
11576
|
-
const timestampInMs = timestampToMs(event.timestamp);
|
|
11577
|
-
|
|
11578
|
-
// Throw out events that happen more than 5 minutes ago. This can happen if
|
|
11579
|
-
// page has been left open and idle for a long period of time and user
|
|
11580
|
-
// comes back to trigger a new session. The performance entries rely on
|
|
11581
|
-
// `performance.timeOrigin`, which is when the page first opened.
|
|
11582
|
-
if (timestampInMs + replay.timeouts.sessionIdlePause < Date.now()) {
|
|
11583
|
-
return null;
|
|
11584
|
-
}
|
|
11585
|
-
|
|
11586
|
-
try {
|
|
11587
|
-
if (isCheckout) {
|
|
11588
|
-
replay.eventBuffer.clear();
|
|
11589
|
-
}
|
|
11590
|
-
|
|
11591
|
-
return await replay.eventBuffer.addEvent(event);
|
|
11592
|
-
} catch (error) {
|
|
11593
|
-
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error(error);
|
|
11594
|
-
await replay.stop('addEvent');
|
|
11595
|
-
|
|
11596
|
-
const client = getCurrentHub().getClient();
|
|
11597
|
-
|
|
11598
|
-
if (client) {
|
|
11599
|
-
client.recordDroppedEvent('internal_sdk_error', 'replay');
|
|
11600
|
-
}
|
|
11601
|
-
}
|
|
11602
|
-
}
|
|
11603
|
-
|
|
11604
|
-
/**
|
|
11605
|
-
* Add a breadcrumb event to replay.
|
|
11606
|
-
*/
|
|
11607
|
-
function addBreadcrumbEvent(replay, breadcrumb) {
|
|
11608
|
-
if (breadcrumb.category === 'sentry.transaction') {
|
|
11609
|
-
return;
|
|
11610
|
-
}
|
|
11611
|
-
|
|
11612
|
-
if (['ui.click', 'ui.input'].includes(breadcrumb.category )) {
|
|
11613
|
-
replay.triggerUserActivity();
|
|
11614
|
-
} else {
|
|
11615
|
-
replay.checkAndHandleExpiredSession();
|
|
11616
|
-
}
|
|
11617
|
-
|
|
11618
|
-
replay.addUpdate(() => {
|
|
11619
|
-
void addEvent(replay, {
|
|
11620
|
-
type: EventType$1.Custom,
|
|
11621
|
-
// TODO: We were converting from ms to seconds for breadcrumbs, spans,
|
|
11622
|
-
// but maybe we should just keep them as milliseconds
|
|
11623
|
-
timestamp: (breadcrumb.timestamp || 0) * 1000,
|
|
11624
|
-
data: {
|
|
11625
|
-
tag: 'breadcrumb',
|
|
11626
|
-
// normalize to max. 10 depth and 1_000 properties per object
|
|
11627
|
-
payload: normalize(breadcrumb, 10, 1000),
|
|
11628
|
-
},
|
|
11629
|
-
});
|
|
11630
|
-
|
|
11631
|
-
// Do not flush after console log messages
|
|
11632
|
-
return breadcrumb.category === 'console';
|
|
11633
|
-
});
|
|
11634
|
-
}
|
|
11635
|
-
|
|
11636
|
-
/**
|
|
11637
|
-
* Detect a slow click on a button/a tag,
|
|
11638
|
-
* and potentially create a corresponding breadcrumb.
|
|
11639
|
-
*/
|
|
11640
|
-
function detectSlowClick(
|
|
11641
|
-
replay,
|
|
11642
|
-
config,
|
|
11643
|
-
clickBreadcrumb,
|
|
11644
|
-
node,
|
|
11645
|
-
) {
|
|
11646
|
-
if (ignoreElement(node, config)) {
|
|
11647
|
-
return;
|
|
11648
|
-
}
|
|
11649
|
-
|
|
11650
|
-
/*
|
|
11651
|
-
We consider a slow click a click on a button/a, which does not trigger one of:
|
|
11652
|
-
- DOM mutation
|
|
11653
|
-
- Scroll (within 100ms)
|
|
11654
|
-
Within the given threshold time.
|
|
11655
|
-
After time timeout time, we stop listening and mark it as a slow click anyhow.
|
|
11656
|
-
*/
|
|
11657
|
-
|
|
11658
|
-
let cleanup = () => {
|
|
11659
|
-
// replaced further down
|
|
11660
|
-
};
|
|
11661
|
-
|
|
11662
|
-
// After timeout time, def. consider this a slow click, and stop watching for mutations
|
|
11663
|
-
const timeout = setTimeout(() => {
|
|
11664
|
-
handleSlowClick(replay, clickBreadcrumb, config.timeout, 'timeout');
|
|
11665
|
-
cleanup();
|
|
11666
|
-
}, config.timeout);
|
|
11667
|
-
|
|
11668
|
-
const mutationHandler = () => {
|
|
11669
|
-
maybeHandleSlowClick(replay, clickBreadcrumb, config.threshold, config.timeout, 'mutation');
|
|
11670
|
-
cleanup();
|
|
11671
|
-
};
|
|
11672
|
-
|
|
11673
|
-
const scrollHandler = () => {
|
|
11674
|
-
maybeHandleSlowClick(replay, clickBreadcrumb, config.scrollTimeout, config.timeout, 'scroll');
|
|
11675
|
-
cleanup();
|
|
11676
|
-
};
|
|
11677
|
-
|
|
11678
|
-
const obs = new MutationObserver(mutationHandler);
|
|
11679
|
-
|
|
11680
|
-
obs.observe(WINDOW.document.documentElement, {
|
|
11681
|
-
attributes: true,
|
|
11682
|
-
characterData: true,
|
|
11683
|
-
childList: true,
|
|
11684
|
-
subtree: true,
|
|
11685
|
-
});
|
|
11686
|
-
|
|
11687
|
-
WINDOW.addEventListener('scroll', scrollHandler);
|
|
11688
|
-
|
|
11689
|
-
// Stop listening to scroll timeouts early
|
|
11690
|
-
const scrollTimeout = setTimeout(() => {
|
|
11691
|
-
WINDOW.removeEventListener('scroll', scrollHandler);
|
|
11692
|
-
}, config.scrollTimeout);
|
|
11693
|
-
|
|
11694
|
-
cleanup = () => {
|
|
11695
|
-
clearTimeout(timeout);
|
|
11696
|
-
clearTimeout(scrollTimeout);
|
|
11697
|
-
obs.disconnect();
|
|
11698
|
-
WINDOW.removeEventListener('scroll', scrollHandler);
|
|
11699
|
-
};
|
|
11700
|
-
}
|
|
11701
|
-
|
|
11702
|
-
function maybeHandleSlowClick(
|
|
11703
|
-
replay,
|
|
11704
|
-
clickBreadcrumb,
|
|
11705
|
-
threshold,
|
|
11706
|
-
timeout,
|
|
11707
|
-
endReason,
|
|
11708
|
-
) {
|
|
11709
|
-
const now = Date.now();
|
|
11710
|
-
const timeAfterClickMs = now - clickBreadcrumb.timestamp * 1000;
|
|
11711
|
-
|
|
11712
|
-
if (timeAfterClickMs > threshold) {
|
|
11713
|
-
handleSlowClick(replay, clickBreadcrumb, Math.min(timeAfterClickMs, timeout), endReason);
|
|
11714
|
-
return true;
|
|
11715
|
-
}
|
|
11716
|
-
|
|
11717
|
-
return false;
|
|
11718
|
-
}
|
|
11719
|
-
|
|
11720
|
-
function handleSlowClick(
|
|
11721
|
-
replay,
|
|
11722
|
-
clickBreadcrumb,
|
|
11723
|
-
timeAfterClickMs,
|
|
11724
|
-
endReason,
|
|
11725
|
-
) {
|
|
11726
|
-
const breadcrumb = {
|
|
11727
|
-
message: clickBreadcrumb.message,
|
|
11728
|
-
timestamp: clickBreadcrumb.timestamp,
|
|
11729
|
-
category: 'ui.slowClickDetected',
|
|
11730
|
-
data: {
|
|
11731
|
-
...clickBreadcrumb.data,
|
|
11732
|
-
url: WINDOW.location.href,
|
|
11733
|
-
// TODO FN: add parametrized route, when possible
|
|
11734
|
-
timeAfterClickMs,
|
|
11735
|
-
endReason,
|
|
11736
|
-
},
|
|
11737
|
-
};
|
|
11738
|
-
|
|
11739
|
-
addBreadcrumbEvent(replay, breadcrumb);
|
|
11740
|
-
}
|
|
11741
|
-
|
|
11742
|
-
const SLOW_CLICK_IGNORE_TAGS = ['SELECT', 'OPTION'];
|
|
11743
|
-
|
|
11744
|
-
function ignoreElement(node, config) {
|
|
11745
|
-
// If <input> tag, we only want to consider input[type='submit'] & input[type='button']
|
|
11746
|
-
if (node.tagName === 'INPUT' && !['submit', 'button'].includes(node.getAttribute('type') || '')) {
|
|
11747
|
-
return true;
|
|
11748
|
-
}
|
|
11749
|
-
|
|
11750
|
-
if (SLOW_CLICK_IGNORE_TAGS.includes(node.tagName)) {
|
|
11751
|
-
return true;
|
|
11752
|
-
}
|
|
11753
|
-
|
|
11754
|
-
// If <a> tag, detect special variants that may not lead to an action
|
|
11755
|
-
// If target !== _self, we may open the link somewhere else, which would lead to no action
|
|
11756
|
-
// Also, when downloading a file, we may not leave the page, but still not trigger an action
|
|
11757
|
-
if (
|
|
11758
|
-
node.tagName === 'A' &&
|
|
11759
|
-
(node.hasAttribute('download') || (node.hasAttribute('target') && node.getAttribute('target') !== '_self'))
|
|
11760
|
-
) {
|
|
11761
|
-
return true;
|
|
11762
|
-
}
|
|
11763
|
-
|
|
11764
|
-
if (config.ignoreSelector && node.matches(config.ignoreSelector)) {
|
|
11765
|
-
return true;
|
|
11766
|
-
}
|
|
11767
|
-
|
|
11768
|
-
return false;
|
|
11769
|
-
}
|
|
11770
|
-
|
|
11771
|
-
// Note that these are the serialized attributes and not attributes directly on
|
|
11772
|
-
// the DOM Node. Attributes we are interested in:
|
|
11773
|
-
const ATTRIBUTES_TO_RECORD = new Set([
|
|
11774
|
-
'id',
|
|
11775
|
-
'class',
|
|
11776
|
-
'aria-label',
|
|
11777
|
-
'role',
|
|
11778
|
-
'name',
|
|
11779
|
-
'alt',
|
|
11780
|
-
'title',
|
|
11781
|
-
'data-test-id',
|
|
11782
|
-
'data-testid',
|
|
11783
|
-
]);
|
|
11784
|
-
|
|
11785
|
-
/**
|
|
11786
|
-
* Inclusion list of attributes that we want to record from the DOM element
|
|
11787
|
-
*/
|
|
11788
|
-
function getAttributesToRecord(attributes) {
|
|
11789
|
-
const obj = {};
|
|
11790
|
-
for (const key in attributes) {
|
|
11791
|
-
if (ATTRIBUTES_TO_RECORD.has(key)) {
|
|
11792
|
-
let normalizedKey = key;
|
|
11793
|
-
|
|
11794
|
-
if (key === 'data-testid' || key === 'data-test-id') {
|
|
11795
|
-
normalizedKey = 'testId';
|
|
11796
|
-
}
|
|
11797
|
-
|
|
11798
|
-
obj[normalizedKey] = attributes[key];
|
|
11799
|
-
}
|
|
11800
|
-
}
|
|
11801
|
-
|
|
11802
|
-
return obj;
|
|
11803
|
-
}
|
|
11804
|
-
|
|
11805
|
-
const handleDomListener = (
|
|
11806
|
-
replay,
|
|
11807
|
-
) => {
|
|
11808
|
-
const slowClickExperiment = replay.getOptions()._experiments.slowClicks;
|
|
11809
|
-
|
|
11810
|
-
const slowClickConfig = slowClickExperiment
|
|
11811
|
-
? {
|
|
11812
|
-
threshold: slowClickExperiment.threshold,
|
|
11813
|
-
timeout: slowClickExperiment.timeout,
|
|
11814
|
-
scrollTimeout: slowClickExperiment.scrollTimeout,
|
|
11815
|
-
ignoreSelector: slowClickExperiment.ignoreSelectors ? slowClickExperiment.ignoreSelectors.join(',') : '',
|
|
11816
|
-
}
|
|
11817
|
-
: undefined;
|
|
11818
|
-
|
|
11819
|
-
return (handlerData) => {
|
|
11820
|
-
if (!replay.isEnabled()) {
|
|
11821
|
-
return;
|
|
11822
|
-
}
|
|
11823
|
-
|
|
11824
|
-
const result = handleDom(handlerData);
|
|
11825
|
-
|
|
11826
|
-
if (!result) {
|
|
11827
|
-
return;
|
|
11828
|
-
}
|
|
11829
|
-
|
|
11830
|
-
const isClick = handlerData.name === 'click';
|
|
11831
|
-
const event = isClick && (handlerData.event );
|
|
11832
|
-
// Ignore clicks if ctrl/alt/meta keys are held down as they alter behavior of clicks (e.g. open in new tab)
|
|
11833
|
-
if (isClick && slowClickConfig && event && !event.altKey && !event.metaKey && !event.ctrlKey) {
|
|
11834
|
-
detectSlowClick(
|
|
11835
|
-
replay,
|
|
11836
|
-
slowClickConfig,
|
|
11837
|
-
result ,
|
|
11838
|
-
getClickTargetNode(handlerData.event) ,
|
|
11839
|
-
);
|
|
11840
|
-
}
|
|
11841
|
-
|
|
11842
|
-
addBreadcrumbEvent(replay, result);
|
|
11843
|
-
};
|
|
11844
|
-
};
|
|
11845
|
-
|
|
11846
|
-
/** Get the base DOM breadcrumb. */
|
|
11847
|
-
function getBaseDomBreadcrumb(target, message) {
|
|
11848
|
-
// `__sn` property is the serialized node created by rrweb
|
|
11849
|
-
const serializedNode = target && isRrwebNode(target) && target.__sn.type === NodeType.Element ? target.__sn : null;
|
|
11850
|
-
|
|
11851
|
-
return {
|
|
11852
|
-
message,
|
|
11853
|
-
data: serializedNode
|
|
11854
|
-
? {
|
|
11855
|
-
nodeId: serializedNode.id,
|
|
11856
|
-
node: {
|
|
11857
|
-
id: serializedNode.id,
|
|
11858
|
-
tagName: serializedNode.tagName,
|
|
11859
|
-
textContent: target
|
|
11860
|
-
? Array.from(target.childNodes)
|
|
11861
|
-
.map(
|
|
11862
|
-
(node) => '__sn' in node && node.__sn.type === NodeType.Text && node.__sn.textContent,
|
|
11863
|
-
)
|
|
11864
|
-
.filter(Boolean) // filter out empty values
|
|
11865
|
-
.map(text => (text ).trim())
|
|
11866
|
-
.join('')
|
|
11867
|
-
: '',
|
|
11868
|
-
attributes: getAttributesToRecord(serializedNode.attributes),
|
|
11869
|
-
},
|
|
11870
|
-
}
|
|
11871
|
-
: {},
|
|
11872
|
-
};
|
|
11873
|
-
}
|
|
11874
|
-
|
|
11875
|
-
/**
|
|
11876
|
-
* An event handler to react to DOM events.
|
|
11877
|
-
* Exported for tests.
|
|
11878
|
-
*/
|
|
11879
|
-
function handleDom(handlerData) {
|
|
11880
|
-
const { target, message } = getDomTarget(handlerData);
|
|
11881
|
-
|
|
11882
|
-
return createBreadcrumb({
|
|
11883
|
-
category: `ui.${handlerData.name}`,
|
|
11884
|
-
...getBaseDomBreadcrumb(target, message),
|
|
11885
|
-
});
|
|
11886
|
-
}
|
|
11887
|
-
|
|
11888
|
-
function getDomTarget(handlerData) {
|
|
11889
|
-
const isClick = handlerData.name === 'click';
|
|
11890
|
-
|
|
11891
|
-
let message;
|
|
11892
|
-
let target = null;
|
|
11893
|
-
|
|
11894
|
-
// Accessing event.target can throw (see getsentry/raven-js#838, #768)
|
|
11895
|
-
try {
|
|
11896
|
-
target = isClick ? getClickTargetNode(handlerData.event) : getTargetNode(handlerData.event);
|
|
11897
|
-
message = htmlTreeAsString(target, { maxStringLength: 200 }) || '<unknown>';
|
|
11898
|
-
} catch (e) {
|
|
11899
|
-
message = '<unknown>';
|
|
11900
|
-
}
|
|
11901
|
-
|
|
11902
|
-
return { target, message };
|
|
11903
|
-
}
|
|
11904
|
-
|
|
11905
|
-
function isRrwebNode(node) {
|
|
11906
|
-
return '__sn' in node;
|
|
11907
|
-
}
|
|
11908
|
-
|
|
11909
|
-
function getTargetNode(event) {
|
|
11910
|
-
if (isEventWithTarget(event)) {
|
|
11911
|
-
return event.target ;
|
|
11912
|
-
}
|
|
11913
|
-
|
|
11914
|
-
return event;
|
|
11915
|
-
}
|
|
11916
|
-
|
|
11917
|
-
const INTERACTIVE_SELECTOR = 'button,a';
|
|
11918
|
-
|
|
11919
|
-
// For clicks, we check if the target is inside of a button or link
|
|
11920
|
-
// If so, we use this as the target instead
|
|
11921
|
-
// This is useful because if you click on the image in <button><img></button>,
|
|
11922
|
-
// The target will be the image, not the button, which we don't want here
|
|
11923
|
-
function getClickTargetNode(event) {
|
|
11924
|
-
const target = getTargetNode(event);
|
|
11925
|
-
|
|
11926
|
-
if (!target || !(target instanceof Element)) {
|
|
11927
|
-
return target;
|
|
11928
|
-
}
|
|
11929
|
-
|
|
11930
|
-
const closestInteractive = target.closest(INTERACTIVE_SELECTOR);
|
|
11931
|
-
return closestInteractive || target;
|
|
11932
|
-
}
|
|
11933
|
-
|
|
11934
|
-
function isEventWithTarget(event) {
|
|
11935
|
-
return typeof event === 'object' && !!event && 'target' in event;
|
|
11936
|
-
}
|
|
11937
|
-
|
|
11938
|
-
/** Handle keyboard events & create breadcrumbs. */
|
|
11939
|
-
function handleKeyboardEvent(replay, event) {
|
|
11940
|
-
if (!replay.isEnabled()) {
|
|
11941
|
-
return;
|
|
11942
|
-
}
|
|
11943
|
-
|
|
11944
|
-
replay.triggerUserActivity();
|
|
11945
|
-
|
|
11946
|
-
const breadcrumb = getKeyboardBreadcrumb(event);
|
|
11947
|
-
|
|
11948
|
-
if (!breadcrumb) {
|
|
11949
|
-
return;
|
|
11950
|
-
}
|
|
11951
|
-
|
|
11952
|
-
addBreadcrumbEvent(replay, breadcrumb);
|
|
11953
|
-
}
|
|
11954
|
-
|
|
11955
|
-
/** exported only for tests */
|
|
11956
|
-
function getKeyboardBreadcrumb(event) {
|
|
11957
|
-
const { metaKey, shiftKey, ctrlKey, altKey, key, target } = event;
|
|
11958
|
-
|
|
11959
|
-
// never capture for input fields
|
|
11960
|
-
if (!target || isInputElement(target )) {
|
|
11961
|
-
return null;
|
|
11962
|
-
}
|
|
11963
|
-
|
|
11964
|
-
// Note: We do not consider shift here, as that means "uppercase"
|
|
11965
|
-
const hasModifierKey = metaKey || ctrlKey || altKey;
|
|
11966
|
-
const isCharacterKey = key.length === 1; // other keys like Escape, Tab, etc have a longer length
|
|
11967
|
-
|
|
11968
|
-
// Do not capture breadcrumb if only a word key is pressed
|
|
11969
|
-
// This could leak e.g. user input
|
|
11970
|
-
if (!hasModifierKey && isCharacterKey) {
|
|
11971
|
-
return null;
|
|
11972
|
-
}
|
|
11973
|
-
|
|
11974
|
-
const message = htmlTreeAsString(target, { maxStringLength: 200 }) || '<unknown>';
|
|
11975
|
-
const baseBreadcrumb = getBaseDomBreadcrumb(target , message);
|
|
11976
|
-
|
|
11977
|
-
return createBreadcrumb({
|
|
11978
|
-
category: 'ui.keyDown',
|
|
11979
|
-
message,
|
|
11980
|
-
data: {
|
|
11981
|
-
...baseBreadcrumb.data,
|
|
11982
|
-
metaKey,
|
|
11983
|
-
shiftKey,
|
|
11984
|
-
ctrlKey,
|
|
11985
|
-
altKey,
|
|
11986
|
-
key,
|
|
11987
|
-
},
|
|
11988
|
-
});
|
|
11989
|
-
}
|
|
11990
|
-
|
|
11991
|
-
function isInputElement(target) {
|
|
11992
|
-
return target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable;
|
|
11993
|
-
}
|
|
11994
|
-
|
|
11995
11320
|
const NAVIGATION_ENTRY_KEYS = [
|
|
11996
11321
|
'name',
|
|
11997
11322
|
'type',
|
|
@@ -12145,19 +11470,20 @@ class EventBufferArray {
|
|
|
12145
11470
|
return this.events.length > 0;
|
|
12146
11471
|
}
|
|
12147
11472
|
|
|
12148
|
-
/** @inheritdoc */
|
|
12149
|
-
get type() {
|
|
12150
|
-
return 'sync';
|
|
12151
|
-
}
|
|
12152
|
-
|
|
12153
11473
|
/** @inheritdoc */
|
|
12154
11474
|
destroy() {
|
|
12155
11475
|
this.events = [];
|
|
12156
11476
|
}
|
|
12157
11477
|
|
|
12158
11478
|
/** @inheritdoc */
|
|
12159
|
-
async addEvent(event) {
|
|
11479
|
+
async addEvent(event, isCheckout) {
|
|
11480
|
+
if (isCheckout) {
|
|
11481
|
+
this.events = [event];
|
|
11482
|
+
return;
|
|
11483
|
+
}
|
|
11484
|
+
|
|
12160
11485
|
this.events.push(event);
|
|
11486
|
+
return;
|
|
12161
11487
|
}
|
|
12162
11488
|
|
|
12163
11489
|
/** @inheritdoc */
|
|
@@ -12171,22 +11497,6 @@ class EventBufferArray {
|
|
|
12171
11497
|
resolve(JSON.stringify(eventsRet));
|
|
12172
11498
|
});
|
|
12173
11499
|
}
|
|
12174
|
-
|
|
12175
|
-
/** @inheritdoc */
|
|
12176
|
-
clear() {
|
|
12177
|
-
this.events = [];
|
|
12178
|
-
}
|
|
12179
|
-
|
|
12180
|
-
/** @inheritdoc */
|
|
12181
|
-
getEarliestTimestamp() {
|
|
12182
|
-
const timestamp = this.events.map(event => event.timestamp).sort()[0];
|
|
12183
|
-
|
|
12184
|
-
if (!timestamp) {
|
|
12185
|
-
return null;
|
|
12186
|
-
}
|
|
12187
|
-
|
|
12188
|
-
return timestampToMs(timestamp);
|
|
12189
|
-
}
|
|
12190
11500
|
}
|
|
12191
11501
|
|
|
12192
11502
|
/**
|
|
@@ -12294,20 +11604,11 @@ class WorkerHandler {
|
|
|
12294
11604
|
* Exported only for testing.
|
|
12295
11605
|
*/
|
|
12296
11606
|
class EventBufferCompressionWorker {
|
|
11607
|
+
/** @inheritdoc */
|
|
12297
11608
|
|
|
12298
11609
|
constructor(worker) {
|
|
12299
11610
|
this._worker = new WorkerHandler(worker);
|
|
12300
|
-
this.
|
|
12301
|
-
}
|
|
12302
|
-
|
|
12303
|
-
/** @inheritdoc */
|
|
12304
|
-
get hasEvents() {
|
|
12305
|
-
return !!this._earliestTimestamp;
|
|
12306
|
-
}
|
|
12307
|
-
|
|
12308
|
-
/** @inheritdoc */
|
|
12309
|
-
get type() {
|
|
12310
|
-
return 'worker';
|
|
11611
|
+
this.hasEvents = false;
|
|
12311
11612
|
}
|
|
12312
11613
|
|
|
12313
11614
|
/**
|
|
@@ -12330,10 +11631,13 @@ class EventBufferCompressionWorker {
|
|
|
12330
11631
|
*
|
|
12331
11632
|
* Returns true if event was successfuly received and processed by worker.
|
|
12332
11633
|
*/
|
|
12333
|
-
addEvent(event) {
|
|
12334
|
-
|
|
12335
|
-
|
|
12336
|
-
|
|
11634
|
+
async addEvent(event, isCheckout) {
|
|
11635
|
+
this.hasEvents = true;
|
|
11636
|
+
|
|
11637
|
+
if (isCheckout) {
|
|
11638
|
+
// This event is a checkout, make sure worker buffer is cleared before
|
|
11639
|
+
// proceeding.
|
|
11640
|
+
await this._clear();
|
|
12337
11641
|
}
|
|
12338
11642
|
|
|
12339
11643
|
return this._sendEventToWorker(event);
|
|
@@ -12346,18 +11650,6 @@ class EventBufferCompressionWorker {
|
|
|
12346
11650
|
return this._finishRequest();
|
|
12347
11651
|
}
|
|
12348
11652
|
|
|
12349
|
-
/** @inheritdoc */
|
|
12350
|
-
clear() {
|
|
12351
|
-
this._earliestTimestamp = null;
|
|
12352
|
-
// We do not wait on this, as we assume the order of messages is consistent for the worker
|
|
12353
|
-
void this._worker.postMessage('clear');
|
|
12354
|
-
}
|
|
12355
|
-
|
|
12356
|
-
/** @inheritdoc */
|
|
12357
|
-
getEarliestTimestamp() {
|
|
12358
|
-
return this._earliestTimestamp;
|
|
12359
|
-
}
|
|
12360
|
-
|
|
12361
11653
|
/**
|
|
12362
11654
|
* Send the event to the worker.
|
|
12363
11655
|
*/
|
|
@@ -12371,10 +11663,15 @@ class EventBufferCompressionWorker {
|
|
|
12371
11663
|
async _finishRequest() {
|
|
12372
11664
|
const response = await this._worker.postMessage('finish');
|
|
12373
11665
|
|
|
12374
|
-
this.
|
|
11666
|
+
this.hasEvents = false;
|
|
12375
11667
|
|
|
12376
11668
|
return response;
|
|
12377
11669
|
}
|
|
11670
|
+
|
|
11671
|
+
/** Clear any pending events from the worker. */
|
|
11672
|
+
_clear() {
|
|
11673
|
+
return this._worker.postMessage('clear');
|
|
11674
|
+
}
|
|
12378
11675
|
}
|
|
12379
11676
|
|
|
12380
11677
|
/**
|
|
@@ -12392,11 +11689,6 @@ class EventBufferProxy {
|
|
|
12392
11689
|
this._ensureWorkerIsLoadedPromise = this._ensureWorkerIsLoaded();
|
|
12393
11690
|
}
|
|
12394
11691
|
|
|
12395
|
-
/** @inheritdoc */
|
|
12396
|
-
get type() {
|
|
12397
|
-
return this._used.type;
|
|
12398
|
-
}
|
|
12399
|
-
|
|
12400
11692
|
/** @inheritDoc */
|
|
12401
11693
|
get hasEvents() {
|
|
12402
11694
|
return this._used.hasEvents;
|
|
@@ -12408,23 +11700,13 @@ class EventBufferProxy {
|
|
|
12408
11700
|
this._compression.destroy();
|
|
12409
11701
|
}
|
|
12410
11702
|
|
|
12411
|
-
/** @inheritdoc */
|
|
12412
|
-
clear() {
|
|
12413
|
-
return this._used.clear();
|
|
12414
|
-
}
|
|
12415
|
-
|
|
12416
|
-
/** @inheritdoc */
|
|
12417
|
-
getEarliestTimestamp() {
|
|
12418
|
-
return this._used.getEarliestTimestamp();
|
|
12419
|
-
}
|
|
12420
|
-
|
|
12421
11703
|
/**
|
|
12422
11704
|
* Add an event to the event buffer.
|
|
12423
11705
|
*
|
|
12424
11706
|
* Returns true if event was successfully added.
|
|
12425
11707
|
*/
|
|
12426
|
-
addEvent(event) {
|
|
12427
|
-
return this._used.addEvent(event);
|
|
11708
|
+
addEvent(event, isCheckout) {
|
|
11709
|
+
return this._used.addEvent(event, isCheckout);
|
|
12428
11710
|
}
|
|
12429
11711
|
|
|
12430
11712
|
/** @inheritDoc */
|
|
@@ -12499,31 +11781,6 @@ function createEventBuffer({ useCompression }) {
|
|
|
12499
11781
|
return new EventBufferArray();
|
|
12500
11782
|
}
|
|
12501
11783
|
|
|
12502
|
-
/**
|
|
12503
|
-
* Removes the session from Session Storage and unsets session in replay instance
|
|
12504
|
-
*/
|
|
12505
|
-
function clearSession(replay) {
|
|
12506
|
-
deleteSession();
|
|
12507
|
-
replay.session = undefined;
|
|
12508
|
-
}
|
|
12509
|
-
|
|
12510
|
-
/**
|
|
12511
|
-
* Deletes a session from storage
|
|
12512
|
-
*/
|
|
12513
|
-
function deleteSession() {
|
|
12514
|
-
const hasSessionStorage = 'sessionStorage' in WINDOW;
|
|
12515
|
-
|
|
12516
|
-
if (!hasSessionStorage) {
|
|
12517
|
-
return;
|
|
12518
|
-
}
|
|
12519
|
-
|
|
12520
|
-
try {
|
|
12521
|
-
WINDOW.sessionStorage.removeItem(REPLAY_SESSION_KEY);
|
|
12522
|
-
} catch (e) {
|
|
12523
|
-
// Ignore potential SecurityError exceptions
|
|
12524
|
-
}
|
|
12525
|
-
}
|
|
12526
|
-
|
|
12527
11784
|
/**
|
|
12528
11785
|
* Given an initial timestamp and an expiry duration, checks to see if current
|
|
12529
11786
|
* time should be considered as expired.
|
|
@@ -12554,26 +11811,11 @@ function isSessionExpired(session, timeouts, targetTime = +new Date()) {
|
|
|
12554
11811
|
// First, check that maximum session length has not been exceeded
|
|
12555
11812
|
isExpired(session.started, timeouts.maxSessionLife, targetTime) ||
|
|
12556
11813
|
// check that the idle timeout has not been exceeded (i.e. user has
|
|
12557
|
-
// performed an action within the last `
|
|
12558
|
-
isExpired(session.lastActivity, timeouts.
|
|
11814
|
+
// performed an action within the last `idleTimeout` ms)
|
|
11815
|
+
isExpired(session.lastActivity, timeouts.sessionIdle, targetTime)
|
|
12559
11816
|
);
|
|
12560
11817
|
}
|
|
12561
11818
|
|
|
12562
|
-
/**
|
|
12563
|
-
* Given a sample rate, returns true if replay should be sampled.
|
|
12564
|
-
*
|
|
12565
|
-
* 1.0 = 100% sampling
|
|
12566
|
-
* 0.0 = 0% sampling
|
|
12567
|
-
*/
|
|
12568
|
-
function isSampled(sampleRate) {
|
|
12569
|
-
if (sampleRate === undefined) {
|
|
12570
|
-
return false;
|
|
12571
|
-
}
|
|
12572
|
-
|
|
12573
|
-
// Math.random() returns a number in range of 0 to 1 (inclusive of 0, but not 1)
|
|
12574
|
-
return Math.random() < sampleRate;
|
|
12575
|
-
}
|
|
12576
|
-
|
|
12577
11819
|
/**
|
|
12578
11820
|
* Save a session to session storage.
|
|
12579
11821
|
*/
|
|
@@ -12590,6 +11832,21 @@ function saveSession(session) {
|
|
|
12590
11832
|
}
|
|
12591
11833
|
}
|
|
12592
11834
|
|
|
11835
|
+
/**
|
|
11836
|
+
* Given a sample rate, returns true if replay should be sampled.
|
|
11837
|
+
*
|
|
11838
|
+
* 1.0 = 100% sampling
|
|
11839
|
+
* 0.0 = 0% sampling
|
|
11840
|
+
*/
|
|
11841
|
+
function isSampled(sampleRate) {
|
|
11842
|
+
if (sampleRate === undefined) {
|
|
11843
|
+
return false;
|
|
11844
|
+
}
|
|
11845
|
+
|
|
11846
|
+
// Math.random() returns a number in range of 0 to 1 (inclusive of 0, but not 1)
|
|
11847
|
+
return Math.random() < sampleRate;
|
|
11848
|
+
}
|
|
11849
|
+
|
|
12593
11850
|
/**
|
|
12594
11851
|
* Get a session with defaults & applied sampling.
|
|
12595
11852
|
*/
|
|
@@ -12608,15 +11865,14 @@ function makeSession(session) {
|
|
|
12608
11865
|
lastActivity,
|
|
12609
11866
|
segmentId,
|
|
12610
11867
|
sampled,
|
|
12611
|
-
shouldRefresh: true,
|
|
12612
11868
|
};
|
|
12613
11869
|
}
|
|
12614
11870
|
|
|
12615
11871
|
/**
|
|
12616
11872
|
* Get the sampled status for a session based on sample rates & current sampled status.
|
|
12617
11873
|
*/
|
|
12618
|
-
function getSessionSampleType(sessionSampleRate,
|
|
12619
|
-
return isSampled(sessionSampleRate) ? 'session' :
|
|
11874
|
+
function getSessionSampleType(sessionSampleRate, errorSampleRate) {
|
|
11875
|
+
return isSampled(sessionSampleRate) ? 'session' : isSampled(errorSampleRate) ? 'error' : false;
|
|
12620
11876
|
}
|
|
12621
11877
|
|
|
12622
11878
|
/**
|
|
@@ -12624,8 +11880,8 @@ function getSessionSampleType(sessionSampleRate, allowBuffering) {
|
|
|
12624
11880
|
* that all replays will be saved to as attachments. Currently, we only expect
|
|
12625
11881
|
* one of these Sentry events per "replay session".
|
|
12626
11882
|
*/
|
|
12627
|
-
function createSession({ sessionSampleRate,
|
|
12628
|
-
const sampled = getSessionSampleType(sessionSampleRate,
|
|
11883
|
+
function createSession({ sessionSampleRate, errorSampleRate, stickySession = false }) {
|
|
11884
|
+
const sampled = getSessionSampleType(sessionSampleRate, errorSampleRate);
|
|
12629
11885
|
const session = makeSession({
|
|
12630
11886
|
sampled,
|
|
12631
11887
|
});
|
|
@@ -12673,7 +11929,7 @@ function getSession({
|
|
|
12673
11929
|
currentSession,
|
|
12674
11930
|
stickySession,
|
|
12675
11931
|
sessionSampleRate,
|
|
12676
|
-
|
|
11932
|
+
errorSampleRate,
|
|
12677
11933
|
}) {
|
|
12678
11934
|
// If session exists and is passed, use it instead of always hitting session storage
|
|
12679
11935
|
const session = currentSession || (stickySession && fetchSession());
|
|
@@ -12686,9 +11942,8 @@ function getSession({
|
|
|
12686
11942
|
|
|
12687
11943
|
if (!isExpired) {
|
|
12688
11944
|
return { type: 'saved', session };
|
|
12689
|
-
} else if (
|
|
12690
|
-
//
|
|
12691
|
-
// This is the case if we have an error session that is completed (=triggered an error)
|
|
11945
|
+
} else if (session.sampled === 'error') {
|
|
11946
|
+
// Error samples should not be re-created when expired, but instead we stop when the replay is done
|
|
12692
11947
|
const discardedSession = makeSession({ sampled: false });
|
|
12693
11948
|
return { type: 'new', session: discardedSession };
|
|
12694
11949
|
} else {
|
|
@@ -12700,12 +11955,65 @@ function getSession({
|
|
|
12700
11955
|
const newSession = createSession({
|
|
12701
11956
|
stickySession,
|
|
12702
11957
|
sessionSampleRate,
|
|
12703
|
-
|
|
11958
|
+
errorSampleRate,
|
|
12704
11959
|
});
|
|
12705
11960
|
|
|
12706
11961
|
return { type: 'new', session: newSession };
|
|
12707
11962
|
}
|
|
12708
11963
|
|
|
11964
|
+
/**
|
|
11965
|
+
* Add an event to the event buffer.
|
|
11966
|
+
* `isCheckout` is true if this is either the very first event, or an event triggered by `checkoutEveryNms`.
|
|
11967
|
+
*/
|
|
11968
|
+
async function addEvent(
|
|
11969
|
+
replay,
|
|
11970
|
+
event,
|
|
11971
|
+
isCheckout,
|
|
11972
|
+
) {
|
|
11973
|
+
if (!replay.eventBuffer) {
|
|
11974
|
+
// This implies that `_isEnabled` is false
|
|
11975
|
+
return null;
|
|
11976
|
+
}
|
|
11977
|
+
|
|
11978
|
+
if (replay.isPaused()) {
|
|
11979
|
+
// Do not add to event buffer when recording is paused
|
|
11980
|
+
return null;
|
|
11981
|
+
}
|
|
11982
|
+
|
|
11983
|
+
// TODO: sadness -- we will want to normalize timestamps to be in ms -
|
|
11984
|
+
// requires coordination with frontend
|
|
11985
|
+
const isMs = event.timestamp > 9999999999;
|
|
11986
|
+
const timestampInMs = isMs ? event.timestamp : event.timestamp * 1000;
|
|
11987
|
+
|
|
11988
|
+
// Throw out events that happen more than 5 minutes ago. This can happen if
|
|
11989
|
+
// page has been left open and idle for a long period of time and user
|
|
11990
|
+
// comes back to trigger a new session. The performance entries rely on
|
|
11991
|
+
// `performance.timeOrigin`, which is when the page first opened.
|
|
11992
|
+
if (timestampInMs + replay.timeouts.sessionIdle < Date.now()) {
|
|
11993
|
+
return null;
|
|
11994
|
+
}
|
|
11995
|
+
|
|
11996
|
+
// Only record earliest event if a new session was created, otherwise it
|
|
11997
|
+
// shouldn't be relevant
|
|
11998
|
+
const earliestEvent = replay.getContext().earliestEvent;
|
|
11999
|
+
if (replay.session && replay.session.segmentId === 0 && (!earliestEvent || timestampInMs < earliestEvent)) {
|
|
12000
|
+
replay.getContext().earliestEvent = timestampInMs;
|
|
12001
|
+
}
|
|
12002
|
+
|
|
12003
|
+
try {
|
|
12004
|
+
return await replay.eventBuffer.addEvent(event, isCheckout);
|
|
12005
|
+
} catch (error) {
|
|
12006
|
+
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error(error);
|
|
12007
|
+
replay.stop('addEvent');
|
|
12008
|
+
|
|
12009
|
+
const client = getCurrentHub().getClient();
|
|
12010
|
+
|
|
12011
|
+
if (client) {
|
|
12012
|
+
client.recordDroppedEvent('internal_sdk_error', 'replay');
|
|
12013
|
+
}
|
|
12014
|
+
}
|
|
12015
|
+
}
|
|
12016
|
+
|
|
12709
12017
|
/** If the event is an error event */
|
|
12710
12018
|
function isErrorEvent(event) {
|
|
12711
12019
|
return !event.type;
|
|
@@ -12755,21 +12063,31 @@ function handleAfterSendEvent(replay) {
|
|
|
12755
12063
|
return;
|
|
12756
12064
|
}
|
|
12757
12065
|
|
|
12758
|
-
// Add error to list of errorIds of replay
|
|
12759
|
-
// sampled because context will get reset at next checkout.
|
|
12760
|
-
// XXX: There is also a race condition where it's possible to capture an
|
|
12761
|
-
// error to Sentry before Replay SDK has loaded, but response returns after
|
|
12762
|
-
// it was loaded, and this gets called.
|
|
12066
|
+
// Add error to list of errorIds of replay
|
|
12763
12067
|
if (event.event_id) {
|
|
12764
12068
|
replay.getContext().errorIds.add(event.event_id);
|
|
12765
12069
|
}
|
|
12766
12070
|
|
|
12767
|
-
//
|
|
12071
|
+
// Trigger error recording
|
|
12768
12072
|
// Need to be very careful that this does not cause an infinite loop
|
|
12769
|
-
if (
|
|
12770
|
-
|
|
12771
|
-
|
|
12772
|
-
|
|
12073
|
+
if (
|
|
12074
|
+
replay.recordingMode === 'error' &&
|
|
12075
|
+
event.exception &&
|
|
12076
|
+
event.message !== UNABLE_TO_SEND_REPLAY // ignore this error because otherwise we could loop indefinitely with trying to capture replay and failing
|
|
12077
|
+
) {
|
|
12078
|
+
setTimeout(async () => {
|
|
12079
|
+
// Allow flush to complete before resuming as a session recording, otherwise
|
|
12080
|
+
// the checkout from `startRecording` may be included in the payload.
|
|
12081
|
+
// Prefer to keep the error replay as a separate (and smaller) segment
|
|
12082
|
+
// than the session replay.
|
|
12083
|
+
await replay.flushImmediate();
|
|
12084
|
+
|
|
12085
|
+
if (replay.stopRecording()) {
|
|
12086
|
+
// Reset all "capture on error" configuration before
|
|
12087
|
+
// starting a new recording
|
|
12088
|
+
replay.recordingMode = 'session';
|
|
12089
|
+
replay.startRecording();
|
|
12090
|
+
}
|
|
12773
12091
|
});
|
|
12774
12092
|
}
|
|
12775
12093
|
};
|
|
@@ -12791,6 +12109,166 @@ function isBaseTransportSend() {
|
|
|
12791
12109
|
);
|
|
12792
12110
|
}
|
|
12793
12111
|
|
|
12112
|
+
var NodeType;
|
|
12113
|
+
(function (NodeType) {
|
|
12114
|
+
NodeType[NodeType["Document"] = 0] = "Document";
|
|
12115
|
+
NodeType[NodeType["DocumentType"] = 1] = "DocumentType";
|
|
12116
|
+
NodeType[NodeType["Element"] = 2] = "Element";
|
|
12117
|
+
NodeType[NodeType["Text"] = 3] = "Text";
|
|
12118
|
+
NodeType[NodeType["CDATA"] = 4] = "CDATA";
|
|
12119
|
+
NodeType[NodeType["Comment"] = 5] = "Comment";
|
|
12120
|
+
})(NodeType || (NodeType = {}));
|
|
12121
|
+
|
|
12122
|
+
/**
|
|
12123
|
+
* Create a breadcrumb for a replay.
|
|
12124
|
+
*/
|
|
12125
|
+
function createBreadcrumb(
|
|
12126
|
+
breadcrumb,
|
|
12127
|
+
) {
|
|
12128
|
+
return {
|
|
12129
|
+
timestamp: Date.now() / 1000,
|
|
12130
|
+
type: 'default',
|
|
12131
|
+
...breadcrumb,
|
|
12132
|
+
};
|
|
12133
|
+
}
|
|
12134
|
+
|
|
12135
|
+
/**
|
|
12136
|
+
* Add a breadcrumb event to replay.
|
|
12137
|
+
*/
|
|
12138
|
+
function addBreadcrumbEvent(replay, breadcrumb) {
|
|
12139
|
+
if (breadcrumb.category === 'sentry.transaction') {
|
|
12140
|
+
return;
|
|
12141
|
+
}
|
|
12142
|
+
|
|
12143
|
+
if (['ui.click', 'ui.input'].includes(breadcrumb.category )) {
|
|
12144
|
+
replay.triggerUserActivity();
|
|
12145
|
+
} else {
|
|
12146
|
+
replay.checkAndHandleExpiredSession();
|
|
12147
|
+
}
|
|
12148
|
+
|
|
12149
|
+
replay.addUpdate(() => {
|
|
12150
|
+
void addEvent(replay, {
|
|
12151
|
+
type: EventType.Custom,
|
|
12152
|
+
// TODO: We were converting from ms to seconds for breadcrumbs, spans,
|
|
12153
|
+
// but maybe we should just keep them as milliseconds
|
|
12154
|
+
timestamp: (breadcrumb.timestamp || 0) * 1000,
|
|
12155
|
+
data: {
|
|
12156
|
+
tag: 'breadcrumb',
|
|
12157
|
+
payload: breadcrumb,
|
|
12158
|
+
},
|
|
12159
|
+
});
|
|
12160
|
+
|
|
12161
|
+
// Do not flush after console log messages
|
|
12162
|
+
return breadcrumb.category === 'console';
|
|
12163
|
+
});
|
|
12164
|
+
}
|
|
12165
|
+
|
|
12166
|
+
// Note that these are the serialized attributes and not attributes directly on
|
|
12167
|
+
// the DOM Node. Attributes we are interested in:
|
|
12168
|
+
const ATTRIBUTES_TO_RECORD = new Set([
|
|
12169
|
+
'id',
|
|
12170
|
+
'class',
|
|
12171
|
+
'aria-label',
|
|
12172
|
+
'role',
|
|
12173
|
+
'name',
|
|
12174
|
+
'alt',
|
|
12175
|
+
'title',
|
|
12176
|
+
'data-test-id',
|
|
12177
|
+
'data-testid',
|
|
12178
|
+
]);
|
|
12179
|
+
|
|
12180
|
+
/**
|
|
12181
|
+
* Inclusion list of attributes that we want to record from the DOM element
|
|
12182
|
+
*/
|
|
12183
|
+
function getAttributesToRecord(attributes) {
|
|
12184
|
+
const obj = {};
|
|
12185
|
+
for (const key in attributes) {
|
|
12186
|
+
if (ATTRIBUTES_TO_RECORD.has(key)) {
|
|
12187
|
+
let normalizedKey = key;
|
|
12188
|
+
|
|
12189
|
+
if (key === 'data-testid' || key === 'data-test-id') {
|
|
12190
|
+
normalizedKey = 'testId';
|
|
12191
|
+
}
|
|
12192
|
+
|
|
12193
|
+
obj[normalizedKey] = attributes[key];
|
|
12194
|
+
}
|
|
12195
|
+
}
|
|
12196
|
+
|
|
12197
|
+
return obj;
|
|
12198
|
+
}
|
|
12199
|
+
|
|
12200
|
+
const handleDomListener =
|
|
12201
|
+
(replay) =>
|
|
12202
|
+
(handlerData) => {
|
|
12203
|
+
if (!replay.isEnabled()) {
|
|
12204
|
+
return;
|
|
12205
|
+
}
|
|
12206
|
+
|
|
12207
|
+
const result = handleDom(handlerData);
|
|
12208
|
+
|
|
12209
|
+
if (!result) {
|
|
12210
|
+
return;
|
|
12211
|
+
}
|
|
12212
|
+
|
|
12213
|
+
addBreadcrumbEvent(replay, result);
|
|
12214
|
+
};
|
|
12215
|
+
|
|
12216
|
+
/**
|
|
12217
|
+
* An event handler to react to DOM events.
|
|
12218
|
+
*/
|
|
12219
|
+
function handleDom(handlerData) {
|
|
12220
|
+
let target;
|
|
12221
|
+
let targetNode;
|
|
12222
|
+
|
|
12223
|
+
// Accessing event.target can throw (see getsentry/raven-js#838, #768)
|
|
12224
|
+
try {
|
|
12225
|
+
targetNode = getTargetNode(handlerData);
|
|
12226
|
+
target = htmlTreeAsString(targetNode);
|
|
12227
|
+
} catch (e) {
|
|
12228
|
+
target = '<unknown>';
|
|
12229
|
+
}
|
|
12230
|
+
|
|
12231
|
+
// `__sn` property is the serialized node created by rrweb
|
|
12232
|
+
const serializedNode =
|
|
12233
|
+
targetNode && '__sn' in targetNode && targetNode.__sn.type === NodeType.Element ? targetNode.__sn : null;
|
|
12234
|
+
|
|
12235
|
+
return createBreadcrumb({
|
|
12236
|
+
category: `ui.${handlerData.name}`,
|
|
12237
|
+
message: target,
|
|
12238
|
+
data: serializedNode
|
|
12239
|
+
? {
|
|
12240
|
+
nodeId: serializedNode.id,
|
|
12241
|
+
node: {
|
|
12242
|
+
id: serializedNode.id,
|
|
12243
|
+
tagName: serializedNode.tagName,
|
|
12244
|
+
textContent: targetNode
|
|
12245
|
+
? Array.from(targetNode.childNodes)
|
|
12246
|
+
.map(
|
|
12247
|
+
(node) => '__sn' in node && node.__sn.type === NodeType.Text && node.__sn.textContent,
|
|
12248
|
+
)
|
|
12249
|
+
.filter(Boolean) // filter out empty values
|
|
12250
|
+
.map(text => (text ).trim())
|
|
12251
|
+
.join('')
|
|
12252
|
+
: '',
|
|
12253
|
+
attributes: getAttributesToRecord(serializedNode.attributes),
|
|
12254
|
+
},
|
|
12255
|
+
}
|
|
12256
|
+
: {},
|
|
12257
|
+
});
|
|
12258
|
+
}
|
|
12259
|
+
|
|
12260
|
+
function getTargetNode(handlerData) {
|
|
12261
|
+
if (isEventWithTarget(handlerData.event)) {
|
|
12262
|
+
return handlerData.event.target;
|
|
12263
|
+
}
|
|
12264
|
+
|
|
12265
|
+
return handlerData.event;
|
|
12266
|
+
}
|
|
12267
|
+
|
|
12268
|
+
function isEventWithTarget(event) {
|
|
12269
|
+
return !!(event ).target;
|
|
12270
|
+
}
|
|
12271
|
+
|
|
12794
12272
|
/**
|
|
12795
12273
|
* Returns true if we think the given event is an error originating inside of rrweb.
|
|
12796
12274
|
*/
|
|
@@ -12814,30 +12292,6 @@ function isRrwebError(event, hint) {
|
|
|
12814
12292
|
});
|
|
12815
12293
|
}
|
|
12816
12294
|
|
|
12817
|
-
/**
|
|
12818
|
-
* Determine if event should be sampled (only applies in buffer mode).
|
|
12819
|
-
* When an event is captured by `hanldleGlobalEvent`, when in buffer mode
|
|
12820
|
-
* we determine if we want to sample the error or not.
|
|
12821
|
-
*/
|
|
12822
|
-
function shouldSampleForBufferEvent(replay, event) {
|
|
12823
|
-
if (replay.recordingMode !== 'buffer') {
|
|
12824
|
-
return false;
|
|
12825
|
-
}
|
|
12826
|
-
|
|
12827
|
-
// ignore this error because otherwise we could loop indefinitely with
|
|
12828
|
-
// trying to capture replay and failing
|
|
12829
|
-
if (event.message === UNABLE_TO_SEND_REPLAY) {
|
|
12830
|
-
return false;
|
|
12831
|
-
}
|
|
12832
|
-
|
|
12833
|
-
// Require the event to be an error event & to have an exception
|
|
12834
|
-
if (!event.exception || event.type) {
|
|
12835
|
-
return false;
|
|
12836
|
-
}
|
|
12837
|
-
|
|
12838
|
-
return isSampled(replay.getOptions().errorSampleRate);
|
|
12839
|
-
}
|
|
12840
|
-
|
|
12841
12295
|
/**
|
|
12842
12296
|
* Returns a listener to be added to `addGlobalEventProcessor(listener)`.
|
|
12843
12297
|
*/
|
|
@@ -12867,16 +12321,8 @@ function handleGlobalEventListener(
|
|
|
12867
12321
|
return null;
|
|
12868
12322
|
}
|
|
12869
12323
|
|
|
12870
|
-
//
|
|
12871
|
-
|
|
12872
|
-
// And convert the buffer session to a full session
|
|
12873
|
-
const isErrorEventSampled = shouldSampleForBufferEvent(replay, event);
|
|
12874
|
-
|
|
12875
|
-
// Tag errors if it has been sampled in buffer mode, or if it is session mode
|
|
12876
|
-
// Only tag transactions if in session mode
|
|
12877
|
-
const shouldTagReplayId = isErrorEventSampled || replay.recordingMode === 'session';
|
|
12878
|
-
|
|
12879
|
-
if (shouldTagReplayId) {
|
|
12324
|
+
// Only tag transactions with replayId if not waiting for an error
|
|
12325
|
+
if (isErrorEvent(event) || (isTransactionEvent(event) && replay.recordingMode === 'session')) {
|
|
12880
12326
|
event.tags = { ...event.tags, replayId: replay.getSessionId() };
|
|
12881
12327
|
}
|
|
12882
12328
|
|
|
@@ -12926,7 +12372,7 @@ function createPerformanceSpans(
|
|
|
12926
12372
|
) {
|
|
12927
12373
|
return entries.map(({ type, start, end, name, data }) =>
|
|
12928
12374
|
addEvent(replay, {
|
|
12929
|
-
type: EventType
|
|
12375
|
+
type: EventType.Custom,
|
|
12930
12376
|
timestamp: start,
|
|
12931
12377
|
data: {
|
|
12932
12378
|
tag: 'performanceSpan',
|
|
@@ -13075,14 +12521,12 @@ function handleFetchSpanListener(replay) {
|
|
|
13075
12521
|
function handleXhr(handlerData) {
|
|
13076
12522
|
const { startTimestamp, endTimestamp, xhr } = handlerData;
|
|
13077
12523
|
|
|
13078
|
-
|
|
13079
|
-
|
|
13080
|
-
if (!startTimestamp || !endTimestamp || !sentryXhrData) {
|
|
12524
|
+
if (!startTimestamp || !endTimestamp || !xhr.__sentry_xhr__) {
|
|
13081
12525
|
return null;
|
|
13082
12526
|
}
|
|
13083
12527
|
|
|
13084
12528
|
// This is only used as a fallback, so we know the body sizes are never set here
|
|
13085
|
-
const { method, url, status_code: statusCode } =
|
|
12529
|
+
const { method, url, status_code: statusCode } = xhr.__sentry_xhr__;
|
|
13086
12530
|
|
|
13087
12531
|
if (url === undefined) {
|
|
13088
12532
|
return null;
|
|
@@ -13115,393 +12559,6 @@ function handleXhrSpanListener(replay) {
|
|
|
13115
12559
|
};
|
|
13116
12560
|
}
|
|
13117
12561
|
|
|
13118
|
-
const OBJ = 10;
|
|
13119
|
-
const OBJ_KEY = 11;
|
|
13120
|
-
const OBJ_KEY_STR = 12;
|
|
13121
|
-
const OBJ_VAL = 13;
|
|
13122
|
-
const OBJ_VAL_STR = 14;
|
|
13123
|
-
const OBJ_VAL_COMPLETED = 15;
|
|
13124
|
-
|
|
13125
|
-
const ARR = 20;
|
|
13126
|
-
const ARR_VAL = 21;
|
|
13127
|
-
const ARR_VAL_STR = 22;
|
|
13128
|
-
const ARR_VAL_COMPLETED = 23;
|
|
13129
|
-
|
|
13130
|
-
const ALLOWED_PRIMITIVES = ['true', 'false', 'null'];
|
|
13131
|
-
|
|
13132
|
-
/**
|
|
13133
|
-
* Complete an incomplete JSON string.
|
|
13134
|
-
* This will ensure that the last element always has a `"~~"` to indicate it was truncated.
|
|
13135
|
-
* For example, `[1,2,` will be completed to `[1,2,"~~"]`
|
|
13136
|
-
* and `{"aa":"b` will be completed to `{"aa":"b~~"}`
|
|
13137
|
-
*/
|
|
13138
|
-
function completeJson(incompleteJson, stack) {
|
|
13139
|
-
if (!stack.length) {
|
|
13140
|
-
return incompleteJson;
|
|
13141
|
-
}
|
|
13142
|
-
|
|
13143
|
-
let json = incompleteJson;
|
|
13144
|
-
|
|
13145
|
-
// Most checks are only needed for the last step in the stack
|
|
13146
|
-
const lastPos = stack.length - 1;
|
|
13147
|
-
const lastStep = stack[lastPos];
|
|
13148
|
-
|
|
13149
|
-
json = _fixLastStep(json, lastStep);
|
|
13150
|
-
|
|
13151
|
-
// Complete remaining steps - just add closing brackets
|
|
13152
|
-
for (let i = lastPos; i >= 0; i--) {
|
|
13153
|
-
const step = stack[i];
|
|
13154
|
-
|
|
13155
|
-
switch (step) {
|
|
13156
|
-
case OBJ:
|
|
13157
|
-
json = `${json}}`;
|
|
13158
|
-
break;
|
|
13159
|
-
case ARR:
|
|
13160
|
-
json = `${json}]`;
|
|
13161
|
-
break;
|
|
13162
|
-
}
|
|
13163
|
-
}
|
|
13164
|
-
|
|
13165
|
-
return json;
|
|
13166
|
-
}
|
|
13167
|
-
|
|
13168
|
-
function _fixLastStep(json, lastStep) {
|
|
13169
|
-
switch (lastStep) {
|
|
13170
|
-
// Object cases
|
|
13171
|
-
case OBJ:
|
|
13172
|
-
return `${json}"~~":"~~"`;
|
|
13173
|
-
case OBJ_KEY:
|
|
13174
|
-
return `${json}:"~~"`;
|
|
13175
|
-
case OBJ_KEY_STR:
|
|
13176
|
-
return `${json}~~":"~~"`;
|
|
13177
|
-
case OBJ_VAL:
|
|
13178
|
-
return _maybeFixIncompleteObjValue(json);
|
|
13179
|
-
case OBJ_VAL_STR:
|
|
13180
|
-
return `${json}~~"`;
|
|
13181
|
-
case OBJ_VAL_COMPLETED:
|
|
13182
|
-
return `${json},"~~":"~~"`;
|
|
13183
|
-
|
|
13184
|
-
// Array cases
|
|
13185
|
-
case ARR:
|
|
13186
|
-
return `${json}"~~"`;
|
|
13187
|
-
case ARR_VAL:
|
|
13188
|
-
return _maybeFixIncompleteArrValue(json);
|
|
13189
|
-
case ARR_VAL_STR:
|
|
13190
|
-
return `${json}~~"`;
|
|
13191
|
-
case ARR_VAL_COMPLETED:
|
|
13192
|
-
return `${json},"~~"`;
|
|
13193
|
-
}
|
|
13194
|
-
|
|
13195
|
-
return json;
|
|
13196
|
-
}
|
|
13197
|
-
|
|
13198
|
-
function _maybeFixIncompleteArrValue(json) {
|
|
13199
|
-
const pos = _findLastArrayDelimiter(json);
|
|
13200
|
-
|
|
13201
|
-
if (pos > -1) {
|
|
13202
|
-
const part = json.slice(pos + 1);
|
|
13203
|
-
|
|
13204
|
-
if (ALLOWED_PRIMITIVES.includes(part.trim())) {
|
|
13205
|
-
return `${json},"~~"`;
|
|
13206
|
-
}
|
|
13207
|
-
|
|
13208
|
-
// Everything else is replaced with `"~~"`
|
|
13209
|
-
return `${json.slice(0, pos + 1)}"~~"`;
|
|
13210
|
-
}
|
|
13211
|
-
|
|
13212
|
-
// fallback, this shouldn't happen, to be save
|
|
13213
|
-
return json;
|
|
13214
|
-
}
|
|
13215
|
-
|
|
13216
|
-
function _findLastArrayDelimiter(json) {
|
|
13217
|
-
for (let i = json.length - 1; i >= 0; i--) {
|
|
13218
|
-
const char = json[i];
|
|
13219
|
-
|
|
13220
|
-
if (char === ',' || char === '[') {
|
|
13221
|
-
return i;
|
|
13222
|
-
}
|
|
13223
|
-
}
|
|
13224
|
-
|
|
13225
|
-
return -1;
|
|
13226
|
-
}
|
|
13227
|
-
|
|
13228
|
-
function _maybeFixIncompleteObjValue(json) {
|
|
13229
|
-
const startPos = json.lastIndexOf(':');
|
|
13230
|
-
|
|
13231
|
-
const part = json.slice(startPos + 1);
|
|
13232
|
-
|
|
13233
|
-
if (ALLOWED_PRIMITIVES.includes(part.trim())) {
|
|
13234
|
-
return `${json},"~~":"~~"`;
|
|
13235
|
-
}
|
|
13236
|
-
|
|
13237
|
-
// Everything else is replaced with `"~~"`
|
|
13238
|
-
// This also means we do not have incomplete numbers, e.g `[1` is replaced with `["~~"]`
|
|
13239
|
-
return `${json.slice(0, startPos + 1)}"~~"`;
|
|
13240
|
-
}
|
|
13241
|
-
|
|
13242
|
-
/**
|
|
13243
|
-
* Evaluate an (incomplete) JSON string.
|
|
13244
|
-
*/
|
|
13245
|
-
function evaluateJson(json) {
|
|
13246
|
-
const stack = [];
|
|
13247
|
-
|
|
13248
|
-
for (let pos = 0; pos < json.length; pos++) {
|
|
13249
|
-
_evaluateJsonPos(stack, json, pos);
|
|
13250
|
-
}
|
|
13251
|
-
|
|
13252
|
-
return stack;
|
|
13253
|
-
}
|
|
13254
|
-
|
|
13255
|
-
function _evaluateJsonPos(stack, json, pos) {
|
|
13256
|
-
const curStep = stack[stack.length - 1];
|
|
13257
|
-
|
|
13258
|
-
const char = json[pos];
|
|
13259
|
-
|
|
13260
|
-
const whitespaceRegex = /\s/;
|
|
13261
|
-
|
|
13262
|
-
if (whitespaceRegex.test(char)) {
|
|
13263
|
-
return;
|
|
13264
|
-
}
|
|
13265
|
-
|
|
13266
|
-
if (char === '"' && !_isEscaped(json, pos)) {
|
|
13267
|
-
_handleQuote(stack, curStep);
|
|
13268
|
-
return;
|
|
13269
|
-
}
|
|
13270
|
-
|
|
13271
|
-
switch (char) {
|
|
13272
|
-
case '{':
|
|
13273
|
-
_handleObj(stack, curStep);
|
|
13274
|
-
break;
|
|
13275
|
-
case '[':
|
|
13276
|
-
_handleArr(stack, curStep);
|
|
13277
|
-
break;
|
|
13278
|
-
case ':':
|
|
13279
|
-
_handleColon(stack, curStep);
|
|
13280
|
-
break;
|
|
13281
|
-
case ',':
|
|
13282
|
-
_handleComma(stack, curStep);
|
|
13283
|
-
break;
|
|
13284
|
-
case '}':
|
|
13285
|
-
_handleObjClose(stack, curStep);
|
|
13286
|
-
break;
|
|
13287
|
-
case ']':
|
|
13288
|
-
_handleArrClose(stack, curStep);
|
|
13289
|
-
break;
|
|
13290
|
-
}
|
|
13291
|
-
}
|
|
13292
|
-
|
|
13293
|
-
function _handleQuote(stack, curStep) {
|
|
13294
|
-
// End of obj value
|
|
13295
|
-
if (curStep === OBJ_VAL_STR) {
|
|
13296
|
-
stack.pop();
|
|
13297
|
-
stack.push(OBJ_VAL_COMPLETED);
|
|
13298
|
-
return;
|
|
13299
|
-
}
|
|
13300
|
-
|
|
13301
|
-
// End of arr value
|
|
13302
|
-
if (curStep === ARR_VAL_STR) {
|
|
13303
|
-
stack.pop();
|
|
13304
|
-
stack.push(ARR_VAL_COMPLETED);
|
|
13305
|
-
return;
|
|
13306
|
-
}
|
|
13307
|
-
|
|
13308
|
-
// Start of obj value
|
|
13309
|
-
if (curStep === OBJ_VAL) {
|
|
13310
|
-
stack.push(OBJ_VAL_STR);
|
|
13311
|
-
return;
|
|
13312
|
-
}
|
|
13313
|
-
|
|
13314
|
-
// Start of arr value
|
|
13315
|
-
if (curStep === ARR_VAL) {
|
|
13316
|
-
stack.push(ARR_VAL_STR);
|
|
13317
|
-
return;
|
|
13318
|
-
}
|
|
13319
|
-
|
|
13320
|
-
// Start of obj key
|
|
13321
|
-
if (curStep === OBJ) {
|
|
13322
|
-
stack.push(OBJ_KEY_STR);
|
|
13323
|
-
return;
|
|
13324
|
-
}
|
|
13325
|
-
|
|
13326
|
-
// End of obj key
|
|
13327
|
-
if (curStep === OBJ_KEY_STR) {
|
|
13328
|
-
stack.pop();
|
|
13329
|
-
stack.push(OBJ_KEY);
|
|
13330
|
-
return;
|
|
13331
|
-
}
|
|
13332
|
-
}
|
|
13333
|
-
|
|
13334
|
-
function _handleObj(stack, curStep) {
|
|
13335
|
-
// Initial object
|
|
13336
|
-
if (!curStep) {
|
|
13337
|
-
stack.push(OBJ);
|
|
13338
|
-
return;
|
|
13339
|
-
}
|
|
13340
|
-
|
|
13341
|
-
// New object as obj value
|
|
13342
|
-
if (curStep === OBJ_VAL) {
|
|
13343
|
-
stack.push(OBJ);
|
|
13344
|
-
return;
|
|
13345
|
-
}
|
|
13346
|
-
|
|
13347
|
-
// New object as array element
|
|
13348
|
-
if (curStep === ARR_VAL) {
|
|
13349
|
-
stack.push(OBJ);
|
|
13350
|
-
}
|
|
13351
|
-
|
|
13352
|
-
// New object as first array element
|
|
13353
|
-
if (curStep === ARR) {
|
|
13354
|
-
stack.push(OBJ);
|
|
13355
|
-
return;
|
|
13356
|
-
}
|
|
13357
|
-
}
|
|
13358
|
-
|
|
13359
|
-
function _handleArr(stack, curStep) {
|
|
13360
|
-
// Initial array
|
|
13361
|
-
if (!curStep) {
|
|
13362
|
-
stack.push(ARR);
|
|
13363
|
-
stack.push(ARR_VAL);
|
|
13364
|
-
return;
|
|
13365
|
-
}
|
|
13366
|
-
|
|
13367
|
-
// New array as obj value
|
|
13368
|
-
if (curStep === OBJ_VAL) {
|
|
13369
|
-
stack.push(ARR);
|
|
13370
|
-
stack.push(ARR_VAL);
|
|
13371
|
-
return;
|
|
13372
|
-
}
|
|
13373
|
-
|
|
13374
|
-
// New array as array element
|
|
13375
|
-
if (curStep === ARR_VAL) {
|
|
13376
|
-
stack.push(ARR);
|
|
13377
|
-
stack.push(ARR_VAL);
|
|
13378
|
-
}
|
|
13379
|
-
|
|
13380
|
-
// New array as first array element
|
|
13381
|
-
if (curStep === ARR) {
|
|
13382
|
-
stack.push(ARR);
|
|
13383
|
-
stack.push(ARR_VAL);
|
|
13384
|
-
return;
|
|
13385
|
-
}
|
|
13386
|
-
}
|
|
13387
|
-
|
|
13388
|
-
function _handleColon(stack, curStep) {
|
|
13389
|
-
if (curStep === OBJ_KEY) {
|
|
13390
|
-
stack.pop();
|
|
13391
|
-
stack.push(OBJ_VAL);
|
|
13392
|
-
}
|
|
13393
|
-
}
|
|
13394
|
-
|
|
13395
|
-
function _handleComma(stack, curStep) {
|
|
13396
|
-
// Comma after obj value
|
|
13397
|
-
if (curStep === OBJ_VAL) {
|
|
13398
|
-
stack.pop();
|
|
13399
|
-
return;
|
|
13400
|
-
}
|
|
13401
|
-
if (curStep === OBJ_VAL_COMPLETED) {
|
|
13402
|
-
// Pop OBJ_VAL_COMPLETED & OBJ_VAL
|
|
13403
|
-
stack.pop();
|
|
13404
|
-
stack.pop();
|
|
13405
|
-
return;
|
|
13406
|
-
}
|
|
13407
|
-
|
|
13408
|
-
// Comma after arr value
|
|
13409
|
-
if (curStep === ARR_VAL) {
|
|
13410
|
-
// do nothing - basically we'd pop ARR_VAL but add it right back
|
|
13411
|
-
return;
|
|
13412
|
-
}
|
|
13413
|
-
|
|
13414
|
-
if (curStep === ARR_VAL_COMPLETED) {
|
|
13415
|
-
// Pop ARR_VAL_COMPLETED
|
|
13416
|
-
stack.pop();
|
|
13417
|
-
|
|
13418
|
-
// basically we'd pop ARR_VAL but add it right back
|
|
13419
|
-
return;
|
|
13420
|
-
}
|
|
13421
|
-
}
|
|
13422
|
-
|
|
13423
|
-
function _handleObjClose(stack, curStep) {
|
|
13424
|
-
// Empty object {}
|
|
13425
|
-
if (curStep === OBJ) {
|
|
13426
|
-
stack.pop();
|
|
13427
|
-
}
|
|
13428
|
-
|
|
13429
|
-
// Object with element
|
|
13430
|
-
if (curStep === OBJ_VAL) {
|
|
13431
|
-
// Pop OBJ_VAL, OBJ
|
|
13432
|
-
stack.pop();
|
|
13433
|
-
stack.pop();
|
|
13434
|
-
}
|
|
13435
|
-
|
|
13436
|
-
// Obj with element
|
|
13437
|
-
if (curStep === OBJ_VAL_COMPLETED) {
|
|
13438
|
-
// Pop OBJ_VAL_COMPLETED, OBJ_VAL, OBJ
|
|
13439
|
-
stack.pop();
|
|
13440
|
-
stack.pop();
|
|
13441
|
-
stack.pop();
|
|
13442
|
-
}
|
|
13443
|
-
|
|
13444
|
-
// if was obj value, complete it
|
|
13445
|
-
if (stack[stack.length - 1] === OBJ_VAL) {
|
|
13446
|
-
stack.push(OBJ_VAL_COMPLETED);
|
|
13447
|
-
}
|
|
13448
|
-
|
|
13449
|
-
// if was arr value, complete it
|
|
13450
|
-
if (stack[stack.length - 1] === ARR_VAL) {
|
|
13451
|
-
stack.push(ARR_VAL_COMPLETED);
|
|
13452
|
-
}
|
|
13453
|
-
}
|
|
13454
|
-
|
|
13455
|
-
function _handleArrClose(stack, curStep) {
|
|
13456
|
-
// Empty array []
|
|
13457
|
-
if (curStep === ARR) {
|
|
13458
|
-
stack.pop();
|
|
13459
|
-
}
|
|
13460
|
-
|
|
13461
|
-
// Array with element
|
|
13462
|
-
if (curStep === ARR_VAL) {
|
|
13463
|
-
// Pop ARR_VAL, ARR
|
|
13464
|
-
stack.pop();
|
|
13465
|
-
stack.pop();
|
|
13466
|
-
}
|
|
13467
|
-
|
|
13468
|
-
// Array with element
|
|
13469
|
-
if (curStep === ARR_VAL_COMPLETED) {
|
|
13470
|
-
// Pop ARR_VAL_COMPLETED, ARR_VAL, ARR
|
|
13471
|
-
stack.pop();
|
|
13472
|
-
stack.pop();
|
|
13473
|
-
stack.pop();
|
|
13474
|
-
}
|
|
13475
|
-
|
|
13476
|
-
// if was obj value, complete it
|
|
13477
|
-
if (stack[stack.length - 1] === OBJ_VAL) {
|
|
13478
|
-
stack.push(OBJ_VAL_COMPLETED);
|
|
13479
|
-
}
|
|
13480
|
-
|
|
13481
|
-
// if was arr value, complete it
|
|
13482
|
-
if (stack[stack.length - 1] === ARR_VAL) {
|
|
13483
|
-
stack.push(ARR_VAL_COMPLETED);
|
|
13484
|
-
}
|
|
13485
|
-
}
|
|
13486
|
-
|
|
13487
|
-
function _isEscaped(str, pos) {
|
|
13488
|
-
const previousChar = str[pos - 1];
|
|
13489
|
-
|
|
13490
|
-
return previousChar === '\\' && !_isEscaped(str, pos - 1);
|
|
13491
|
-
}
|
|
13492
|
-
|
|
13493
|
-
/* eslint-disable max-lines */
|
|
13494
|
-
|
|
13495
|
-
/**
|
|
13496
|
-
* Takes an incomplete JSON string, and returns a hopefully valid JSON string.
|
|
13497
|
-
* Note that this _can_ fail, so you should check the return value is valid JSON.
|
|
13498
|
-
*/
|
|
13499
|
-
function fixJson(incompleteJson) {
|
|
13500
|
-
const stack = evaluateJson(incompleteJson);
|
|
13501
|
-
|
|
13502
|
-
return completeJson(incompleteJson, stack);
|
|
13503
|
-
}
|
|
13504
|
-
|
|
13505
12562
|
/** Get the size of a body. */
|
|
13506
12563
|
function getBodySize(
|
|
13507
12564
|
body,
|
|
@@ -13595,68 +12652,51 @@ function makeNetworkReplayBreadcrumb(
|
|
|
13595
12652
|
return result;
|
|
13596
12653
|
}
|
|
13597
12654
|
|
|
13598
|
-
/**
|
|
13599
|
-
function
|
|
13600
|
-
|
|
13601
|
-
|
|
13602
|
-
|
|
13603
|
-
|
|
13604
|
-
|
|
13605
|
-
|
|
13606
|
-
}
|
|
12655
|
+
/** Get either a JSON network body, or a text representation. */
|
|
12656
|
+
function getNetworkBody(bodyText) {
|
|
12657
|
+
if (!bodyText) {
|
|
12658
|
+
return;
|
|
12659
|
+
}
|
|
12660
|
+
|
|
12661
|
+
try {
|
|
12662
|
+
return JSON.parse(bodyText);
|
|
12663
|
+
} catch (e2) {
|
|
12664
|
+
// return text
|
|
12665
|
+
}
|
|
12666
|
+
|
|
12667
|
+
return bodyText;
|
|
13607
12668
|
}
|
|
13608
12669
|
|
|
13609
12670
|
/** Build the request or response part of a replay network breadcrumb. */
|
|
13610
12671
|
function buildNetworkRequestOrResponse(
|
|
13611
|
-
headers,
|
|
13612
12672
|
bodySize,
|
|
13613
12673
|
body,
|
|
13614
12674
|
) {
|
|
13615
|
-
if (!bodySize && Object.keys(headers).length === 0) {
|
|
13616
|
-
return undefined;
|
|
13617
|
-
}
|
|
13618
|
-
|
|
13619
12675
|
if (!bodySize) {
|
|
13620
|
-
return
|
|
13621
|
-
headers,
|
|
13622
|
-
};
|
|
12676
|
+
return undefined;
|
|
13623
12677
|
}
|
|
13624
12678
|
|
|
13625
12679
|
if (!body) {
|
|
13626
12680
|
return {
|
|
13627
|
-
headers,
|
|
13628
12681
|
size: bodySize,
|
|
13629
12682
|
};
|
|
13630
12683
|
}
|
|
13631
12684
|
|
|
13632
12685
|
const info = {
|
|
13633
|
-
headers,
|
|
13634
12686
|
size: bodySize,
|
|
13635
12687
|
};
|
|
13636
12688
|
|
|
13637
|
-
|
|
13638
|
-
|
|
13639
|
-
|
|
12689
|
+
if (bodySize < NETWORK_BODY_MAX_SIZE) {
|
|
12690
|
+
info.body = body;
|
|
12691
|
+
} else {
|
|
13640
12692
|
info._meta = {
|
|
13641
|
-
|
|
12693
|
+
errors: ['MAX_BODY_SIZE_EXCEEDED'],
|
|
13642
12694
|
};
|
|
13643
12695
|
}
|
|
13644
12696
|
|
|
13645
12697
|
return info;
|
|
13646
12698
|
}
|
|
13647
12699
|
|
|
13648
|
-
/** Filter a set of headers */
|
|
13649
|
-
function getAllowedHeaders(headers, allowedHeaders) {
|
|
13650
|
-
return Object.keys(headers).reduce((filteredHeaders, key) => {
|
|
13651
|
-
const normalizedKey = key.toLowerCase();
|
|
13652
|
-
// Avoid putting empty strings into the headers
|
|
13653
|
-
if (allowedHeaders.includes(normalizedKey) && headers[key]) {
|
|
13654
|
-
filteredHeaders[normalizedKey] = headers[key];
|
|
13655
|
-
}
|
|
13656
|
-
return filteredHeaders;
|
|
13657
|
-
}, {});
|
|
13658
|
-
}
|
|
13659
|
-
|
|
13660
12700
|
function _serializeFormData(formData) {
|
|
13661
12701
|
// This is a bit simplified, but gives us a decent estimate
|
|
13662
12702
|
// This converts e.g. { name: 'Anne Smith', age: 13 } to 'name=Anne+Smith&age=13'
|
|
@@ -13664,78 +12704,6 @@ function _serializeFormData(formData) {
|
|
|
13664
12704
|
return new URLSearchParams(formData).toString();
|
|
13665
12705
|
}
|
|
13666
12706
|
|
|
13667
|
-
function normalizeNetworkBody(body)
|
|
13668
|
-
|
|
13669
|
-
{
|
|
13670
|
-
if (!body || typeof body !== 'string') {
|
|
13671
|
-
return {
|
|
13672
|
-
body,
|
|
13673
|
-
warnings: [],
|
|
13674
|
-
};
|
|
13675
|
-
}
|
|
13676
|
-
|
|
13677
|
-
const exceedsSizeLimit = body.length > NETWORK_BODY_MAX_SIZE;
|
|
13678
|
-
|
|
13679
|
-
if (_strIsProbablyJson(body)) {
|
|
13680
|
-
try {
|
|
13681
|
-
const json = exceedsSizeLimit ? fixJson(body.slice(0, NETWORK_BODY_MAX_SIZE)) : body;
|
|
13682
|
-
const normalizedBody = JSON.parse(json);
|
|
13683
|
-
return {
|
|
13684
|
-
body: normalizedBody,
|
|
13685
|
-
warnings: exceedsSizeLimit ? ['JSON_TRUNCATED'] : [],
|
|
13686
|
-
};
|
|
13687
|
-
} catch (e3) {
|
|
13688
|
-
return {
|
|
13689
|
-
body: exceedsSizeLimit ? `${body.slice(0, NETWORK_BODY_MAX_SIZE)}…` : body,
|
|
13690
|
-
warnings: exceedsSizeLimit ? ['INVALID_JSON', 'TEXT_TRUNCATED'] : ['INVALID_JSON'],
|
|
13691
|
-
};
|
|
13692
|
-
}
|
|
13693
|
-
}
|
|
13694
|
-
|
|
13695
|
-
return {
|
|
13696
|
-
body: exceedsSizeLimit ? `${body.slice(0, NETWORK_BODY_MAX_SIZE)}…` : body,
|
|
13697
|
-
warnings: exceedsSizeLimit ? ['TEXT_TRUNCATED'] : [],
|
|
13698
|
-
};
|
|
13699
|
-
}
|
|
13700
|
-
|
|
13701
|
-
function _strIsProbablyJson(str) {
|
|
13702
|
-
const first = str[0];
|
|
13703
|
-
const last = str[str.length - 1];
|
|
13704
|
-
|
|
13705
|
-
// Simple check: If this does not start & end with {} or [], it's not JSON
|
|
13706
|
-
return (first === '[' && last === ']') || (first === '{' && last === '}');
|
|
13707
|
-
}
|
|
13708
|
-
|
|
13709
|
-
/** Match an URL against a list of strings/Regex. */
|
|
13710
|
-
function urlMatches(url, urls) {
|
|
13711
|
-
const fullUrl = getFullUrl(url);
|
|
13712
|
-
|
|
13713
|
-
return stringMatchesSomePattern(fullUrl, urls);
|
|
13714
|
-
}
|
|
13715
|
-
|
|
13716
|
-
/** exported for tests */
|
|
13717
|
-
function getFullUrl(url, baseURI = WINDOW.document.baseURI) {
|
|
13718
|
-
// Short circuit for common cases:
|
|
13719
|
-
if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith(WINDOW.location.origin)) {
|
|
13720
|
-
return url;
|
|
13721
|
-
}
|
|
13722
|
-
const fixedUrl = new URL(url, baseURI);
|
|
13723
|
-
|
|
13724
|
-
// If these do not match, we are not dealing with a relative URL, so just return it
|
|
13725
|
-
if (fixedUrl.origin !== new URL(baseURI).origin) {
|
|
13726
|
-
return url;
|
|
13727
|
-
}
|
|
13728
|
-
|
|
13729
|
-
const fullUrl = fixedUrl.href;
|
|
13730
|
-
|
|
13731
|
-
// Remove trailing slashes, if they don't match the original URL
|
|
13732
|
-
if (!url.endsWith('/') && fullUrl.endsWith('/')) {
|
|
13733
|
-
return fullUrl.slice(0, -1);
|
|
13734
|
-
}
|
|
13735
|
-
|
|
13736
|
-
return fullUrl;
|
|
13737
|
-
}
|
|
13738
|
-
|
|
13739
12707
|
/**
|
|
13740
12708
|
* Capture a fetch breadcrumb to a replay.
|
|
13741
12709
|
* This adds additional data (where approriate).
|
|
@@ -13743,9 +12711,7 @@ function getFullUrl(url, baseURI = WINDOW.document.baseURI) {
|
|
|
13743
12711
|
async function captureFetchBreadcrumbToReplay(
|
|
13744
12712
|
breadcrumb,
|
|
13745
12713
|
hint,
|
|
13746
|
-
options
|
|
13747
|
-
|
|
13748
|
-
,
|
|
12714
|
+
options,
|
|
13749
12715
|
) {
|
|
13750
12716
|
try {
|
|
13751
12717
|
const data = await _prepareFetchData(breadcrumb, hint, options);
|
|
@@ -13772,7 +12738,6 @@ function enrichFetchBreadcrumb(
|
|
|
13772
12738
|
|
|
13773
12739
|
const body = _getFetchRequestArgBody(input);
|
|
13774
12740
|
const reqSize = getBodySize(body, options.textEncoder);
|
|
13775
|
-
|
|
13776
12741
|
const resSize = response ? parseContentLengthHeader(response.headers.get('content-length')) : undefined;
|
|
13777
12742
|
|
|
13778
12743
|
if (reqSize !== undefined) {
|
|
@@ -13786,109 +12751,97 @@ function enrichFetchBreadcrumb(
|
|
|
13786
12751
|
async function _prepareFetchData(
|
|
13787
12752
|
breadcrumb,
|
|
13788
12753
|
hint,
|
|
13789
|
-
options
|
|
13790
|
-
|
|
13791
|
-
,
|
|
12754
|
+
options,
|
|
13792
12755
|
) {
|
|
13793
12756
|
const { startTimestamp, endTimestamp } = hint;
|
|
13794
12757
|
|
|
13795
12758
|
const {
|
|
13796
12759
|
url,
|
|
13797
12760
|
method,
|
|
13798
|
-
status_code: statusCode
|
|
12761
|
+
status_code: statusCode,
|
|
13799
12762
|
request_body_size: requestBodySize,
|
|
13800
12763
|
response_body_size: responseBodySize,
|
|
13801
12764
|
} = breadcrumb.data;
|
|
13802
12765
|
|
|
13803
|
-
const
|
|
13804
|
-
|
|
13805
|
-
const request = captureDetails
|
|
13806
|
-
? _getRequestInfo(options, hint.input, requestBodySize)
|
|
13807
|
-
: buildSkippedNetworkRequestOrResponse(requestBodySize);
|
|
13808
|
-
const response = await _getResponseInfo(captureDetails, options, hint.response, responseBodySize);
|
|
12766
|
+
const request = _getRequestInfo(options, hint.input, requestBodySize);
|
|
12767
|
+
const response = await _getResponseInfo(options, hint.response, responseBodySize);
|
|
13809
12768
|
|
|
13810
12769
|
return {
|
|
13811
12770
|
startTimestamp,
|
|
13812
12771
|
endTimestamp,
|
|
13813
12772
|
url,
|
|
13814
12773
|
method,
|
|
13815
|
-
statusCode,
|
|
12774
|
+
statusCode: statusCode || 0,
|
|
13816
12775
|
request,
|
|
13817
12776
|
response,
|
|
13818
12777
|
};
|
|
13819
12778
|
}
|
|
13820
12779
|
|
|
13821
12780
|
function _getRequestInfo(
|
|
13822
|
-
{
|
|
12781
|
+
{ captureBodies },
|
|
13823
12782
|
input,
|
|
13824
12783
|
requestBodySize,
|
|
13825
12784
|
) {
|
|
13826
|
-
|
|
13827
|
-
|
|
13828
|
-
if (!networkCaptureBodies) {
|
|
13829
|
-
return buildNetworkRequestOrResponse(headers, requestBodySize, undefined);
|
|
12785
|
+
if (!captureBodies) {
|
|
12786
|
+
return buildNetworkRequestOrResponse(requestBodySize, undefined);
|
|
13830
12787
|
}
|
|
13831
12788
|
|
|
13832
12789
|
// We only want to transmit string or string-like bodies
|
|
13833
12790
|
const requestBody = _getFetchRequestArgBody(input);
|
|
13834
|
-
const
|
|
13835
|
-
return buildNetworkRequestOrResponse(
|
|
12791
|
+
const body = getNetworkBody(getBodyString(requestBody));
|
|
12792
|
+
return buildNetworkRequestOrResponse(requestBodySize, body);
|
|
13836
12793
|
}
|
|
13837
12794
|
|
|
13838
12795
|
async function _getResponseInfo(
|
|
13839
|
-
|
|
13840
|
-
{
|
|
13841
|
-
networkCaptureBodies,
|
|
13842
|
-
textEncoder,
|
|
13843
|
-
networkResponseHeaders,
|
|
13844
|
-
}
|
|
13845
|
-
|
|
13846
|
-
,
|
|
12796
|
+
{ captureBodies, textEncoder },
|
|
13847
12797
|
response,
|
|
13848
12798
|
responseBodySize,
|
|
13849
12799
|
) {
|
|
13850
|
-
if (!
|
|
13851
|
-
return
|
|
13852
|
-
}
|
|
13853
|
-
|
|
13854
|
-
const headers = getAllHeaders(response.headers, networkResponseHeaders);
|
|
13855
|
-
|
|
13856
|
-
if (!networkCaptureBodies && responseBodySize !== undefined) {
|
|
13857
|
-
return buildNetworkRequestOrResponse(headers, responseBodySize, undefined);
|
|
12800
|
+
if (!captureBodies && responseBodySize !== undefined) {
|
|
12801
|
+
return buildNetworkRequestOrResponse(responseBodySize, undefined);
|
|
13858
12802
|
}
|
|
13859
12803
|
|
|
13860
12804
|
// Only clone the response if we need to
|
|
13861
12805
|
try {
|
|
13862
12806
|
// We have to clone this, as the body can only be read once
|
|
13863
12807
|
const res = response.clone();
|
|
13864
|
-
const bodyText = await _parseFetchBody(res);
|
|
12808
|
+
const { body, bodyText } = await _parseFetchBody(res);
|
|
13865
12809
|
|
|
13866
12810
|
const size =
|
|
13867
12811
|
bodyText && bodyText.length && responseBodySize === undefined
|
|
13868
12812
|
? getBodySize(bodyText, textEncoder)
|
|
13869
12813
|
: responseBodySize;
|
|
13870
12814
|
|
|
13871
|
-
if (
|
|
13872
|
-
return
|
|
12815
|
+
if (captureBodies) {
|
|
12816
|
+
return buildNetworkRequestOrResponse(size, body);
|
|
13873
12817
|
}
|
|
13874
12818
|
|
|
13875
|
-
|
|
13876
|
-
return buildNetworkRequestOrResponse(headers, size, bodyText);
|
|
13877
|
-
}
|
|
13878
|
-
|
|
13879
|
-
return buildNetworkRequestOrResponse(headers, size, undefined);
|
|
12819
|
+
return buildNetworkRequestOrResponse(size, undefined);
|
|
13880
12820
|
} catch (e) {
|
|
13881
12821
|
// fallback
|
|
13882
|
-
return buildNetworkRequestOrResponse(
|
|
12822
|
+
return buildNetworkRequestOrResponse(responseBodySize, undefined);
|
|
13883
12823
|
}
|
|
13884
12824
|
}
|
|
13885
12825
|
|
|
13886
|
-
async function _parseFetchBody(
|
|
12826
|
+
async function _parseFetchBody(
|
|
12827
|
+
response,
|
|
12828
|
+
) {
|
|
12829
|
+
let bodyText;
|
|
12830
|
+
|
|
13887
12831
|
try {
|
|
13888
|
-
|
|
12832
|
+
bodyText = await response.text();
|
|
13889
12833
|
} catch (e2) {
|
|
13890
|
-
return
|
|
12834
|
+
return {};
|
|
12835
|
+
}
|
|
12836
|
+
|
|
12837
|
+
try {
|
|
12838
|
+
const body = JSON.parse(bodyText);
|
|
12839
|
+
return { body, bodyText };
|
|
12840
|
+
} catch (e3) {
|
|
12841
|
+
// just send bodyText
|
|
13891
12842
|
}
|
|
12843
|
+
|
|
12844
|
+
return { bodyText, body: bodyText };
|
|
13892
12845
|
}
|
|
13893
12846
|
|
|
13894
12847
|
function _getFetchRequestArgBody(fetchArgs = []) {
|
|
@@ -13900,56 +12853,6 @@ function _getFetchRequestArgBody(fetchArgs = []) {
|
|
|
13900
12853
|
return (fetchArgs[1] ).body;
|
|
13901
12854
|
}
|
|
13902
12855
|
|
|
13903
|
-
function getAllHeaders(headers, allowedHeaders) {
|
|
13904
|
-
const allHeaders = {};
|
|
13905
|
-
|
|
13906
|
-
allowedHeaders.forEach(header => {
|
|
13907
|
-
if (headers.get(header)) {
|
|
13908
|
-
allHeaders[header] = headers.get(header) ;
|
|
13909
|
-
}
|
|
13910
|
-
});
|
|
13911
|
-
|
|
13912
|
-
return allHeaders;
|
|
13913
|
-
}
|
|
13914
|
-
|
|
13915
|
-
function getRequestHeaders(fetchArgs, allowedHeaders) {
|
|
13916
|
-
if (fetchArgs.length === 1 && typeof fetchArgs[0] !== 'string') {
|
|
13917
|
-
return getHeadersFromOptions(fetchArgs[0] , allowedHeaders);
|
|
13918
|
-
}
|
|
13919
|
-
|
|
13920
|
-
if (fetchArgs.length === 2) {
|
|
13921
|
-
return getHeadersFromOptions(fetchArgs[1] , allowedHeaders);
|
|
13922
|
-
}
|
|
13923
|
-
|
|
13924
|
-
return {};
|
|
13925
|
-
}
|
|
13926
|
-
|
|
13927
|
-
function getHeadersFromOptions(
|
|
13928
|
-
input,
|
|
13929
|
-
allowedHeaders,
|
|
13930
|
-
) {
|
|
13931
|
-
if (!input) {
|
|
13932
|
-
return {};
|
|
13933
|
-
}
|
|
13934
|
-
|
|
13935
|
-
const headers = input.headers;
|
|
13936
|
-
|
|
13937
|
-
if (!headers) {
|
|
13938
|
-
return {};
|
|
13939
|
-
}
|
|
13940
|
-
|
|
13941
|
-
if (headers instanceof Headers) {
|
|
13942
|
-
return getAllHeaders(headers, allowedHeaders);
|
|
13943
|
-
}
|
|
13944
|
-
|
|
13945
|
-
// We do not support this, as it is not really documented (anymore?)
|
|
13946
|
-
if (Array.isArray(headers)) {
|
|
13947
|
-
return {};
|
|
13948
|
-
}
|
|
13949
|
-
|
|
13950
|
-
return getAllowedHeaders(headers, allowedHeaders);
|
|
13951
|
-
}
|
|
13952
|
-
|
|
13953
12856
|
/**
|
|
13954
12857
|
* Capture an XHR breadcrumb to a replay.
|
|
13955
12858
|
* This adds additional data (where approriate).
|
|
@@ -14000,12 +12903,12 @@ function _prepareXhrData(
|
|
|
14000
12903
|
hint,
|
|
14001
12904
|
options,
|
|
14002
12905
|
) {
|
|
14003
|
-
const { startTimestamp, endTimestamp, input
|
|
12906
|
+
const { startTimestamp, endTimestamp, input } = hint;
|
|
14004
12907
|
|
|
14005
12908
|
const {
|
|
14006
12909
|
url,
|
|
14007
12910
|
method,
|
|
14008
|
-
status_code: statusCode
|
|
12911
|
+
status_code: statusCode,
|
|
14009
12912
|
request_body_size: requestBodySize,
|
|
14010
12913
|
response_body_size: responseBodySize,
|
|
14011
12914
|
} = breadcrumb.data;
|
|
@@ -14014,35 +12917,13 @@ function _prepareXhrData(
|
|
|
14014
12917
|
return null;
|
|
14015
12918
|
}
|
|
14016
12919
|
|
|
14017
|
-
if (!urlMatches(url, options.networkDetailAllowUrls)) {
|
|
14018
|
-
const request = buildSkippedNetworkRequestOrResponse(requestBodySize);
|
|
14019
|
-
const response = buildSkippedNetworkRequestOrResponse(responseBodySize);
|
|
14020
|
-
return {
|
|
14021
|
-
startTimestamp,
|
|
14022
|
-
endTimestamp,
|
|
14023
|
-
url,
|
|
14024
|
-
method,
|
|
14025
|
-
statusCode,
|
|
14026
|
-
request,
|
|
14027
|
-
response,
|
|
14028
|
-
};
|
|
14029
|
-
}
|
|
14030
|
-
|
|
14031
|
-
const xhrInfo = xhr[SENTRY_XHR_DATA_KEY];
|
|
14032
|
-
const networkRequestHeaders = xhrInfo
|
|
14033
|
-
? getAllowedHeaders(xhrInfo.request_headers, options.networkRequestHeaders)
|
|
14034
|
-
: {};
|
|
14035
|
-
const networkResponseHeaders = getAllowedHeaders(getResponseHeaders(xhr), options.networkResponseHeaders);
|
|
14036
|
-
|
|
14037
12920
|
const request = buildNetworkRequestOrResponse(
|
|
14038
|
-
networkRequestHeaders,
|
|
14039
12921
|
requestBodySize,
|
|
14040
|
-
options.
|
|
12922
|
+
options.captureBodies ? getNetworkBody(getBodyString(input)) : undefined,
|
|
14041
12923
|
);
|
|
14042
12924
|
const response = buildNetworkRequestOrResponse(
|
|
14043
|
-
networkResponseHeaders,
|
|
14044
12925
|
responseBodySize,
|
|
14045
|
-
options.
|
|
12926
|
+
options.captureBodies ? getNetworkBody(hint.xhr.responseText) : undefined,
|
|
14046
12927
|
);
|
|
14047
12928
|
|
|
14048
12929
|
return {
|
|
@@ -14050,26 +12931,12 @@ function _prepareXhrData(
|
|
|
14050
12931
|
endTimestamp,
|
|
14051
12932
|
url,
|
|
14052
12933
|
method,
|
|
14053
|
-
statusCode,
|
|
12934
|
+
statusCode: statusCode || 0,
|
|
14054
12935
|
request,
|
|
14055
12936
|
response,
|
|
14056
12937
|
};
|
|
14057
12938
|
}
|
|
14058
12939
|
|
|
14059
|
-
function getResponseHeaders(xhr) {
|
|
14060
|
-
const headers = xhr.getAllResponseHeaders();
|
|
14061
|
-
|
|
14062
|
-
if (!headers) {
|
|
14063
|
-
return {};
|
|
14064
|
-
}
|
|
14065
|
-
|
|
14066
|
-
return headers.split('\r\n').reduce((acc, line) => {
|
|
14067
|
-
const [key, value] = line.split(': ');
|
|
14068
|
-
acc[key.toLowerCase()] = value;
|
|
14069
|
-
return acc;
|
|
14070
|
-
}, {});
|
|
14071
|
-
}
|
|
14072
|
-
|
|
14073
12940
|
/**
|
|
14074
12941
|
* This method does two things:
|
|
14075
12942
|
* - It enriches the regular XHR/fetch breadcrumbs with request/response size data
|
|
@@ -14082,16 +12949,10 @@ function handleNetworkBreadcrumbs(replay) {
|
|
|
14082
12949
|
try {
|
|
14083
12950
|
const textEncoder = new TextEncoder();
|
|
14084
12951
|
|
|
14085
|
-
const { networkDetailAllowUrls, networkCaptureBodies, networkRequestHeaders, networkResponseHeaders } =
|
|
14086
|
-
replay.getOptions();
|
|
14087
|
-
|
|
14088
12952
|
const options = {
|
|
14089
12953
|
replay,
|
|
14090
12954
|
textEncoder,
|
|
14091
|
-
|
|
14092
|
-
networkCaptureBodies,
|
|
14093
|
-
networkRequestHeaders,
|
|
14094
|
-
networkResponseHeaders,
|
|
12955
|
+
captureBodies: replay.getOptions()._experiments.captureNetworkBodies || false,
|
|
14095
12956
|
};
|
|
14096
12957
|
|
|
14097
12958
|
if (client && client.on) {
|
|
@@ -14199,66 +13060,9 @@ function handleScope(scope) {
|
|
|
14199
13060
|
return null;
|
|
14200
13061
|
}
|
|
14201
13062
|
|
|
14202
|
-
if (newBreadcrumb.category === 'console') {
|
|
14203
|
-
return normalizeConsoleBreadcrumb(newBreadcrumb);
|
|
14204
|
-
}
|
|
14205
|
-
|
|
14206
13063
|
return createBreadcrumb(newBreadcrumb);
|
|
14207
13064
|
}
|
|
14208
13065
|
|
|
14209
|
-
/** exported for tests only */
|
|
14210
|
-
function normalizeConsoleBreadcrumb(breadcrumb) {
|
|
14211
|
-
const args = breadcrumb.data && breadcrumb.data.arguments;
|
|
14212
|
-
|
|
14213
|
-
if (!Array.isArray(args) || args.length === 0) {
|
|
14214
|
-
return createBreadcrumb(breadcrumb);
|
|
14215
|
-
}
|
|
14216
|
-
|
|
14217
|
-
let isTruncated = false;
|
|
14218
|
-
|
|
14219
|
-
// Avoid giant args captures
|
|
14220
|
-
const normalizedArgs = args.map(arg => {
|
|
14221
|
-
if (!arg) {
|
|
14222
|
-
return arg;
|
|
14223
|
-
}
|
|
14224
|
-
if (typeof arg === 'string') {
|
|
14225
|
-
if (arg.length > CONSOLE_ARG_MAX_SIZE) {
|
|
14226
|
-
isTruncated = true;
|
|
14227
|
-
return `${arg.slice(0, CONSOLE_ARG_MAX_SIZE)}…`;
|
|
14228
|
-
}
|
|
14229
|
-
|
|
14230
|
-
return arg;
|
|
14231
|
-
}
|
|
14232
|
-
if (typeof arg === 'object') {
|
|
14233
|
-
try {
|
|
14234
|
-
const normalizedArg = normalize(arg, 7);
|
|
14235
|
-
const stringified = JSON.stringify(normalizedArg);
|
|
14236
|
-
if (stringified.length > CONSOLE_ARG_MAX_SIZE) {
|
|
14237
|
-
const fixedJson = fixJson(stringified.slice(0, CONSOLE_ARG_MAX_SIZE));
|
|
14238
|
-
const json = JSON.parse(fixedJson);
|
|
14239
|
-
// We only set this after JSON.parse() was successfull, so we know we didn't run into `catch`
|
|
14240
|
-
isTruncated = true;
|
|
14241
|
-
return json;
|
|
14242
|
-
}
|
|
14243
|
-
return normalizedArg;
|
|
14244
|
-
} catch (e) {
|
|
14245
|
-
// fall back to default
|
|
14246
|
-
}
|
|
14247
|
-
}
|
|
14248
|
-
|
|
14249
|
-
return arg;
|
|
14250
|
-
});
|
|
14251
|
-
|
|
14252
|
-
return createBreadcrumb({
|
|
14253
|
-
...breadcrumb,
|
|
14254
|
-
data: {
|
|
14255
|
-
...breadcrumb.data,
|
|
14256
|
-
arguments: normalizedArgs,
|
|
14257
|
-
...(isTruncated ? { _meta: { warnings: ['CONSOLE_ARG_TRUNCATED'] } } : {}),
|
|
14258
|
-
},
|
|
14259
|
-
});
|
|
14260
|
-
}
|
|
14261
|
-
|
|
14262
13066
|
/**
|
|
14263
13067
|
* Add global listeners that cannot be removed.
|
|
14264
13068
|
*/
|
|
@@ -14283,8 +13087,7 @@ function addGlobalListeners(replay) {
|
|
|
14283
13087
|
client.on('afterSendEvent', handleAfterSendEvent(replay));
|
|
14284
13088
|
client.on('createDsc', (dsc) => {
|
|
14285
13089
|
const replayId = replay.getSessionId();
|
|
14286
|
-
|
|
14287
|
-
if (replayId && replay.isEnabled() && replay.recordingMode === 'session') {
|
|
13090
|
+
if (replayId) {
|
|
14288
13091
|
dsc.replay_id = replayId;
|
|
14289
13092
|
}
|
|
14290
13093
|
});
|
|
@@ -14564,23 +13367,6 @@ function debounce(func, wait, options) {
|
|
|
14564
13367
|
return debounced;
|
|
14565
13368
|
}
|
|
14566
13369
|
|
|
14567
|
-
/* eslint-disable @typescript-eslint/naming-convention */
|
|
14568
|
-
|
|
14569
|
-
var EventType; (function (EventType) {
|
|
14570
|
-
const DomContentLoaded = 0; EventType[EventType["DomContentLoaded"] = DomContentLoaded] = "DomContentLoaded";
|
|
14571
|
-
const Load = 1; EventType[EventType["Load"] = Load] = "Load";
|
|
14572
|
-
const FullSnapshot = 2; EventType[EventType["FullSnapshot"] = FullSnapshot] = "FullSnapshot";
|
|
14573
|
-
const IncrementalSnapshot = 3; EventType[EventType["IncrementalSnapshot"] = IncrementalSnapshot] = "IncrementalSnapshot";
|
|
14574
|
-
const Meta = 4; EventType[EventType["Meta"] = Meta] = "Meta";
|
|
14575
|
-
const Custom = 5; EventType[EventType["Custom"] = Custom] = "Custom";
|
|
14576
|
-
const Plugin = 6; EventType[EventType["Plugin"] = Plugin] = "Plugin";
|
|
14577
|
-
})(EventType || (EventType = {}));
|
|
14578
|
-
|
|
14579
|
-
/**
|
|
14580
|
-
* This is a partial copy of rrweb's eventWithTime type which only contains the properties
|
|
14581
|
-
* we specifcally need in the SDK.
|
|
14582
|
-
*/
|
|
14583
|
-
|
|
14584
13370
|
/**
|
|
14585
13371
|
* Handler for recording events.
|
|
14586
13372
|
*
|
|
@@ -14609,7 +13395,7 @@ function getHandleRecordingEmit(replay) {
|
|
|
14609
13395
|
// when an error occurs. Clear any state that happens before this current
|
|
14610
13396
|
// checkout. This needs to happen before `addEvent()` which updates state
|
|
14611
13397
|
// dependent on this reset.
|
|
14612
|
-
if (replay.recordingMode === '
|
|
13398
|
+
if (replay.recordingMode === 'error' && isCheckout) {
|
|
14613
13399
|
replay.setInitialState();
|
|
14614
13400
|
}
|
|
14615
13401
|
|
|
@@ -14623,14 +13409,6 @@ function getHandleRecordingEmit(replay) {
|
|
|
14623
13409
|
return false;
|
|
14624
13410
|
}
|
|
14625
13411
|
|
|
14626
|
-
// Additionally, create a meta event that will capture certain SDK settings.
|
|
14627
|
-
// In order to handle buffer mode, this needs to either be done when we
|
|
14628
|
-
// receive checkout events or at flush time.
|
|
14629
|
-
//
|
|
14630
|
-
// `isCheckout` is always true, but want to be explicit that it should
|
|
14631
|
-
// only be added for checkouts
|
|
14632
|
-
void addSettingsEvent(replay, isCheckout);
|
|
14633
|
-
|
|
14634
13412
|
// If there is a previousSessionId after a full snapshot occurs, then
|
|
14635
13413
|
// the replay session was started due to session expiration. The new session
|
|
14636
13414
|
// is started before triggering a new checkout and contains the id
|
|
@@ -14641,10 +13419,10 @@ function getHandleRecordingEmit(replay) {
|
|
|
14641
13419
|
return true;
|
|
14642
13420
|
}
|
|
14643
13421
|
|
|
14644
|
-
//
|
|
14645
|
-
//
|
|
14646
|
-
if (replay.recordingMode === '
|
|
14647
|
-
const earliestEvent = replay.
|
|
13422
|
+
// See note above re: session start needs to reflect the most recent
|
|
13423
|
+
// checkout.
|
|
13424
|
+
if (replay.recordingMode === 'error' && replay.session) {
|
|
13425
|
+
const { earliestEvent } = replay.getContext();
|
|
14648
13426
|
if (earliestEvent) {
|
|
14649
13427
|
replay.session.started = earliestEvent;
|
|
14650
13428
|
|
|
@@ -14668,46 +13446,6 @@ function getHandleRecordingEmit(replay) {
|
|
|
14668
13446
|
};
|
|
14669
13447
|
}
|
|
14670
13448
|
|
|
14671
|
-
/**
|
|
14672
|
-
* Exported for tests
|
|
14673
|
-
*/
|
|
14674
|
-
function createOptionsEvent(replay) {
|
|
14675
|
-
const options = replay.getOptions();
|
|
14676
|
-
return {
|
|
14677
|
-
type: EventType.Custom,
|
|
14678
|
-
timestamp: Date.now(),
|
|
14679
|
-
data: {
|
|
14680
|
-
tag: 'options',
|
|
14681
|
-
payload: {
|
|
14682
|
-
sessionSampleRate: options.sessionSampleRate,
|
|
14683
|
-
errorSampleRate: options.errorSampleRate,
|
|
14684
|
-
useCompressionOption: options.useCompression,
|
|
14685
|
-
blockAllMedia: options.blockAllMedia,
|
|
14686
|
-
maskAllText: options.maskAllText,
|
|
14687
|
-
maskAllInputs: options.maskAllInputs,
|
|
14688
|
-
useCompression: replay.eventBuffer ? replay.eventBuffer.type === 'worker' : false,
|
|
14689
|
-
networkDetailHasUrls: options.networkDetailAllowUrls.length > 0,
|
|
14690
|
-
networkCaptureBodies: options.networkCaptureBodies,
|
|
14691
|
-
networkRequestHasHeaders: options.networkRequestHeaders.length > 0,
|
|
14692
|
-
networkResponseHasHeaders: options.networkResponseHeaders.length > 0,
|
|
14693
|
-
},
|
|
14694
|
-
},
|
|
14695
|
-
};
|
|
14696
|
-
}
|
|
14697
|
-
|
|
14698
|
-
/**
|
|
14699
|
-
* Add a "meta" event that contains a simplified view on current configuration
|
|
14700
|
-
* options. This should only be included on the first segment of a recording.
|
|
14701
|
-
*/
|
|
14702
|
-
function addSettingsEvent(replay, isCheckout) {
|
|
14703
|
-
// Only need to add this event when sending the first segment
|
|
14704
|
-
if (!isCheckout || !replay.session || replay.session.segmentId !== 0) {
|
|
14705
|
-
return Promise.resolve(null);
|
|
14706
|
-
}
|
|
14707
|
-
|
|
14708
|
-
return addEvent(replay, createOptionsEvent(replay), false);
|
|
14709
|
-
}
|
|
14710
|
-
|
|
14711
13449
|
/**
|
|
14712
13450
|
* Create a replay envelope ready to be sent.
|
|
14713
13451
|
* This includes both the replay event, as well as the recording data.
|
|
@@ -14819,9 +13557,11 @@ async function sendReplayRequest({
|
|
|
14819
13557
|
recordingData,
|
|
14820
13558
|
replayId,
|
|
14821
13559
|
segmentId: segment_id,
|
|
13560
|
+
includeReplayStartTimestamp,
|
|
14822
13561
|
eventContext,
|
|
14823
13562
|
timestamp,
|
|
14824
13563
|
session,
|
|
13564
|
+
options,
|
|
14825
13565
|
}) {
|
|
14826
13566
|
const preparedRecordingData = prepareRecordingData({
|
|
14827
13567
|
recordingData,
|
|
@@ -14843,8 +13583,9 @@ async function sendReplayRequest({
|
|
|
14843
13583
|
}
|
|
14844
13584
|
|
|
14845
13585
|
const baseEvent = {
|
|
13586
|
+
// @ts-ignore private api
|
|
14846
13587
|
type: REPLAY_EVENT_NAME,
|
|
14847
|
-
replay_start_timestamp: initialTimestamp / 1000,
|
|
13588
|
+
...(includeReplayStartTimestamp ? { replay_start_timestamp: initialTimestamp / 1000 } : {}),
|
|
14848
13589
|
timestamp: timestamp / 1000,
|
|
14849
13590
|
error_ids: errorIds,
|
|
14850
13591
|
trace_ids: traceIds,
|
|
@@ -14863,6 +13604,15 @@ async function sendReplayRequest({
|
|
|
14863
13604
|
return;
|
|
14864
13605
|
}
|
|
14865
13606
|
|
|
13607
|
+
replayEvent.contexts = {
|
|
13608
|
+
...replayEvent.contexts,
|
|
13609
|
+
replay: {
|
|
13610
|
+
...(replayEvent.contexts && replayEvent.contexts.replay),
|
|
13611
|
+
session_sample_rate: options.sessionSampleRate,
|
|
13612
|
+
error_sample_rate: options.errorSampleRate,
|
|
13613
|
+
},
|
|
13614
|
+
};
|
|
13615
|
+
|
|
14866
13616
|
/*
|
|
14867
13617
|
For reference, the fully built event looks something like this:
|
|
14868
13618
|
{
|
|
@@ -14893,6 +13643,10 @@ async function sendReplayRequest({
|
|
|
14893
13643
|
},
|
|
14894
13644
|
"sdkProcessingMetadata": {},
|
|
14895
13645
|
"contexts": {
|
|
13646
|
+
"replay": {
|
|
13647
|
+
"session_sample_rate": 1,
|
|
13648
|
+
"error_sample_rate": 0,
|
|
13649
|
+
},
|
|
14896
13650
|
},
|
|
14897
13651
|
}
|
|
14898
13652
|
*/
|
|
@@ -15018,11 +13772,9 @@ class ReplayContainer {
|
|
|
15018
13772
|
__init2() {this.performanceEvents = [];}
|
|
15019
13773
|
|
|
15020
13774
|
/**
|
|
15021
|
-
* Recording can happen in one of
|
|
15022
|
-
*
|
|
15023
|
-
*
|
|
15024
|
-
* - having replaysOnErrorSampleRate > 0 to capture replay when an error occurs
|
|
15025
|
-
* - or calling `flush()` to send the replay
|
|
13775
|
+
* Recording can happen in one of two modes:
|
|
13776
|
+
* * session: Record the whole session, sending it continuously
|
|
13777
|
+
* * error: Always keep the last 60s of recording, and when an error occurs, send it immediately
|
|
15026
13778
|
*/
|
|
15027
13779
|
__init3() {this.recordingMode = 'session';}
|
|
15028
13780
|
|
|
@@ -15031,8 +13783,7 @@ class ReplayContainer {
|
|
|
15031
13783
|
* @hidden
|
|
15032
13784
|
*/
|
|
15033
13785
|
__init4() {this.timeouts = {
|
|
15034
|
-
|
|
15035
|
-
sessionIdleExpire: SESSION_IDLE_EXPIRE_DURATION,
|
|
13786
|
+
sessionIdle: SESSION_IDLE_DURATION,
|
|
15036
13787
|
maxSessionLife: MAX_SESSION_LIFE,
|
|
15037
13788
|
}; }
|
|
15038
13789
|
|
|
@@ -15076,6 +13827,7 @@ class ReplayContainer {
|
|
|
15076
13827
|
errorIds: new Set(),
|
|
15077
13828
|
traceIds: new Set(),
|
|
15078
13829
|
urls: [],
|
|
13830
|
+
earliestEvent: null,
|
|
15079
13831
|
initialTimestamp: Date.now(),
|
|
15080
13832
|
initialUrl: '',
|
|
15081
13833
|
};}
|
|
@@ -15085,7 +13837,7 @@ class ReplayContainer {
|
|
|
15085
13837
|
recordingOptions,
|
|
15086
13838
|
}
|
|
15087
13839
|
|
|
15088
|
-
) {ReplayContainer.prototype.__init.call(this);ReplayContainer.prototype.__init2.call(this);ReplayContainer.prototype.__init3.call(this);ReplayContainer.prototype.__init4.call(this);ReplayContainer.prototype.__init5.call(this);ReplayContainer.prototype.__init6.call(this);ReplayContainer.prototype.__init7.call(this);ReplayContainer.prototype.__init8.call(this);ReplayContainer.prototype.__init9.call(this);ReplayContainer.prototype.__init10.call(this);ReplayContainer.prototype.__init11.call(this);ReplayContainer.prototype.__init12.call(this);ReplayContainer.prototype.__init13.call(this);ReplayContainer.prototype.__init14.call(this);ReplayContainer.prototype.__init15.call(this);ReplayContainer.prototype.__init16.call(this);ReplayContainer.prototype.__init17.call(this);
|
|
13840
|
+
) {ReplayContainer.prototype.__init.call(this);ReplayContainer.prototype.__init2.call(this);ReplayContainer.prototype.__init3.call(this);ReplayContainer.prototype.__init4.call(this);ReplayContainer.prototype.__init5.call(this);ReplayContainer.prototype.__init6.call(this);ReplayContainer.prototype.__init7.call(this);ReplayContainer.prototype.__init8.call(this);ReplayContainer.prototype.__init9.call(this);ReplayContainer.prototype.__init10.call(this);ReplayContainer.prototype.__init11.call(this);ReplayContainer.prototype.__init12.call(this);ReplayContainer.prototype.__init13.call(this);ReplayContainer.prototype.__init14.call(this);ReplayContainer.prototype.__init15.call(this);ReplayContainer.prototype.__init16.call(this);ReplayContainer.prototype.__init17.call(this);
|
|
15089
13841
|
this._recordingOptions = recordingOptions;
|
|
15090
13842
|
this._options = options;
|
|
15091
13843
|
|
|
@@ -15115,102 +13867,49 @@ class ReplayContainer {
|
|
|
15115
13867
|
}
|
|
15116
13868
|
|
|
15117
13869
|
/**
|
|
15118
|
-
* Initializes the plugin
|
|
15119
|
-
*
|
|
13870
|
+
* Initializes the plugin.
|
|
13871
|
+
*
|
|
13872
|
+
* Creates or loads a session, attaches listeners to varying events (DOM,
|
|
13873
|
+
* _performanceObserver, Recording, Sentry SDK, etc)
|
|
15120
13874
|
*/
|
|
15121
|
-
|
|
15122
|
-
|
|
15123
|
-
|
|
15124
|
-
// If neither sample rate is > 0, then do nothing - user will need to call one of
|
|
15125
|
-
// `start()` or `startBuffering` themselves.
|
|
15126
|
-
if (errorSampleRate <= 0 && sessionSampleRate <= 0) {
|
|
15127
|
-
return;
|
|
15128
|
-
}
|
|
15129
|
-
|
|
15130
|
-
// Otherwise if there is _any_ sample rate set, try to load an existing
|
|
15131
|
-
// session, or create a new one.
|
|
15132
|
-
const isSessionSampled = this._loadAndCheckSession();
|
|
13875
|
+
start() {
|
|
13876
|
+
this.setInitialState();
|
|
15133
13877
|
|
|
15134
|
-
if (!
|
|
15135
|
-
// This should only occur if `errorSampleRate` is 0 and was unsampled for
|
|
15136
|
-
// session-based replay. In this case there is nothing to do.
|
|
13878
|
+
if (!this._loadAndCheckSession()) {
|
|
15137
13879
|
return;
|
|
15138
13880
|
}
|
|
15139
13881
|
|
|
13882
|
+
// If there is no session, then something bad has happened - can't continue
|
|
15140
13883
|
if (!this.session) {
|
|
15141
|
-
|
|
15142
|
-
this._handleException(new Error('Unable to initialize and create session'));
|
|
13884
|
+
this._handleException(new Error('No session found'));
|
|
15143
13885
|
return;
|
|
15144
13886
|
}
|
|
15145
13887
|
|
|
15146
|
-
if (this.session.sampled
|
|
15147
|
-
// If not sampled
|
|
15148
|
-
|
|
15149
|
-
// could have sessions from Session storage that are still `error` from
|
|
15150
|
-
// prior SDK version.
|
|
15151
|
-
this.recordingMode = 'buffer';
|
|
15152
|
-
}
|
|
15153
|
-
|
|
15154
|
-
this._initializeRecording();
|
|
15155
|
-
}
|
|
15156
|
-
|
|
15157
|
-
/**
|
|
15158
|
-
* Start a replay regardless of sampling rate. Calling this will always
|
|
15159
|
-
* create a new session. Will throw an error if replay is already in progress.
|
|
15160
|
-
*
|
|
15161
|
-
* Creates or loads a session, attaches listeners to varying events (DOM,
|
|
15162
|
-
* _performanceObserver, Recording, Sentry SDK, etc)
|
|
15163
|
-
*/
|
|
15164
|
-
start() {
|
|
15165
|
-
if (this._isEnabled && this.recordingMode === 'session') {
|
|
15166
|
-
throw new Error('Replay recording is already in progress');
|
|
13888
|
+
if (!this.session.sampled) {
|
|
13889
|
+
// If session was not sampled, then we do not initialize the integration at all.
|
|
13890
|
+
return;
|
|
15167
13891
|
}
|
|
15168
13892
|
|
|
15169
|
-
|
|
15170
|
-
|
|
13893
|
+
// If session is sampled for errors, then we need to set the recordingMode
|
|
13894
|
+
// to 'error', which will configure recording with different options.
|
|
13895
|
+
if (this.session.sampled === 'error') {
|
|
13896
|
+
this.recordingMode = 'error';
|
|
15171
13897
|
}
|
|
15172
13898
|
|
|
15173
|
-
|
|
13899
|
+
// setup() is generally called on page load or manually - in both cases we
|
|
13900
|
+
// should treat it as an activity
|
|
13901
|
+
this._updateSessionActivity();
|
|
15174
13902
|
|
|
15175
|
-
|
|
15176
|
-
|
|
15177
|
-
stickySession: Boolean(this._options.stickySession),
|
|
15178
|
-
currentSession: this.session,
|
|
15179
|
-
// This is intentional: create a new session-based replay when calling `start()`
|
|
15180
|
-
sessionSampleRate: 1,
|
|
15181
|
-
allowBuffering: false,
|
|
13903
|
+
this.eventBuffer = createEventBuffer({
|
|
13904
|
+
useCompression: this._options.useCompression,
|
|
15182
13905
|
});
|
|
15183
13906
|
|
|
15184
|
-
|
|
15185
|
-
this.session = session;
|
|
15186
|
-
|
|
15187
|
-
this._initializeRecording();
|
|
15188
|
-
}
|
|
15189
|
-
|
|
15190
|
-
/**
|
|
15191
|
-
* Start replay buffering. Buffers until `flush()` is called or, if
|
|
15192
|
-
* `replaysOnErrorSampleRate` > 0, an error occurs.
|
|
15193
|
-
*/
|
|
15194
|
-
startBuffering() {
|
|
15195
|
-
if (this._isEnabled) {
|
|
15196
|
-
throw new Error('Replay recording is already in progress');
|
|
15197
|
-
}
|
|
15198
|
-
|
|
15199
|
-
const previousSessionId = this.session && this.session.id;
|
|
15200
|
-
|
|
15201
|
-
const { session } = getSession({
|
|
15202
|
-
timeouts: this.timeouts,
|
|
15203
|
-
stickySession: Boolean(this._options.stickySession),
|
|
15204
|
-
currentSession: this.session,
|
|
15205
|
-
sessionSampleRate: 0,
|
|
15206
|
-
allowBuffering: true,
|
|
15207
|
-
});
|
|
13907
|
+
this._addListeners();
|
|
15208
13908
|
|
|
15209
|
-
|
|
15210
|
-
this.
|
|
13909
|
+
// Need to set as enabled before we start recording, as `record()` can trigger a flush with a new checkout
|
|
13910
|
+
this._isEnabled = true;
|
|
15211
13911
|
|
|
15212
|
-
this.
|
|
15213
|
-
this._initializeRecording();
|
|
13912
|
+
this.startRecording();
|
|
15214
13913
|
}
|
|
15215
13914
|
|
|
15216
13915
|
/**
|
|
@@ -15225,7 +13924,7 @@ class ReplayContainer {
|
|
|
15225
13924
|
// When running in error sampling mode, we need to overwrite `checkoutEveryNms`
|
|
15226
13925
|
// Without this, it would record forever, until an error happens, which we don't want
|
|
15227
13926
|
// instead, we'll always keep the last 60 seconds of replay before an error happened
|
|
15228
|
-
...(this.recordingMode === '
|
|
13927
|
+
...(this.recordingMode === 'error' && { checkoutEveryNms: ERROR_CHECKOUT_TIME }),
|
|
15229
13928
|
emit: getHandleRecordingEmit(this),
|
|
15230
13929
|
onMutation: this._onMutationHandler,
|
|
15231
13930
|
});
|
|
@@ -15236,18 +13935,17 @@ class ReplayContainer {
|
|
|
15236
13935
|
|
|
15237
13936
|
/**
|
|
15238
13937
|
* Stops the recording, if it was running.
|
|
15239
|
-
*
|
|
15240
|
-
* Returns true if it was previously stopped, or is now stopped,
|
|
15241
|
-
* otherwise false.
|
|
13938
|
+
* Returns true if it was stopped, else false.
|
|
15242
13939
|
*/
|
|
15243
13940
|
stopRecording() {
|
|
15244
13941
|
try {
|
|
15245
13942
|
if (this._stopRecording) {
|
|
15246
13943
|
this._stopRecording();
|
|
15247
13944
|
this._stopRecording = undefined;
|
|
13945
|
+
return true;
|
|
15248
13946
|
}
|
|
15249
13947
|
|
|
15250
|
-
return
|
|
13948
|
+
return false;
|
|
15251
13949
|
} catch (err) {
|
|
15252
13950
|
this._handleException(err);
|
|
15253
13951
|
return false;
|
|
@@ -15258,7 +13956,7 @@ class ReplayContainer {
|
|
|
15258
13956
|
* Currently, this needs to be manually called (e.g. for tests). Sentry SDK
|
|
15259
13957
|
* does not support a teardown
|
|
15260
13958
|
*/
|
|
15261
|
-
|
|
13959
|
+
stop(reason) {
|
|
15262
13960
|
if (!this._isEnabled) {
|
|
15263
13961
|
return;
|
|
15264
13962
|
}
|
|
@@ -15274,24 +13972,12 @@ class ReplayContainer {
|
|
|
15274
13972
|
log(msg);
|
|
15275
13973
|
}
|
|
15276
13974
|
|
|
15277
|
-
// We can't move `_isEnabled` after awaiting a flush, otherwise we can
|
|
15278
|
-
// enter into an infinite loop when `stop()` is called while flushing.
|
|
15279
13975
|
this._isEnabled = false;
|
|
15280
13976
|
this._removeListeners();
|
|
15281
13977
|
this.stopRecording();
|
|
15282
|
-
|
|
15283
|
-
this._debouncedFlush.cancel();
|
|
15284
|
-
// See comment above re: `_isEnabled`, we "force" a flush, ignoring the
|
|
15285
|
-
// `_isEnabled` state of the plugin since it was disabled above.
|
|
15286
|
-
await this._flush({ force: true });
|
|
15287
|
-
|
|
15288
|
-
// After flush, destroy event buffer
|
|
15289
13978
|
this.eventBuffer && this.eventBuffer.destroy();
|
|
15290
13979
|
this.eventBuffer = null;
|
|
15291
|
-
|
|
15292
|
-
// Clear session from session storage, note this means if a new session
|
|
15293
|
-
// is started after, it will not have `previousSessionId`
|
|
15294
|
-
clearSession(this);
|
|
13980
|
+
this._debouncedFlush.cancel();
|
|
15295
13981
|
} catch (err) {
|
|
15296
13982
|
this._handleException(err);
|
|
15297
13983
|
}
|
|
@@ -15322,45 +14008,6 @@ class ReplayContainer {
|
|
|
15322
14008
|
this.startRecording();
|
|
15323
14009
|
}
|
|
15324
14010
|
|
|
15325
|
-
/**
|
|
15326
|
-
* If not in "session" recording mode, flush event buffer which will create a new replay.
|
|
15327
|
-
* Unless `continueRecording` is false, the replay will continue to record and
|
|
15328
|
-
* behave as a "session"-based replay.
|
|
15329
|
-
*
|
|
15330
|
-
* Otherwise, queue up a flush.
|
|
15331
|
-
*/
|
|
15332
|
-
async sendBufferedReplayOrFlush({ continueRecording = true } = {}) {
|
|
15333
|
-
if (this.recordingMode === 'session') {
|
|
15334
|
-
return this.flushImmediate();
|
|
15335
|
-
}
|
|
15336
|
-
|
|
15337
|
-
// Allow flush to complete before resuming as a session recording, otherwise
|
|
15338
|
-
// the checkout from `startRecording` may be included in the payload.
|
|
15339
|
-
// Prefer to keep the error replay as a separate (and smaller) segment
|
|
15340
|
-
// than the session replay.
|
|
15341
|
-
await this.flushImmediate();
|
|
15342
|
-
|
|
15343
|
-
const hasStoppedRecording = this.stopRecording();
|
|
15344
|
-
|
|
15345
|
-
if (!continueRecording || !hasStoppedRecording) {
|
|
15346
|
-
return;
|
|
15347
|
-
}
|
|
15348
|
-
|
|
15349
|
-
// Re-start recording, but in "session" recording mode
|
|
15350
|
-
|
|
15351
|
-
// Reset all "capture on error" configuration before
|
|
15352
|
-
// starting a new recording
|
|
15353
|
-
this.recordingMode = 'session';
|
|
15354
|
-
|
|
15355
|
-
// Once this session ends, we do not want to refresh it
|
|
15356
|
-
if (this.session) {
|
|
15357
|
-
this.session.shouldRefresh = false;
|
|
15358
|
-
this._maybeSaveSession();
|
|
15359
|
-
}
|
|
15360
|
-
|
|
15361
|
-
this.startRecording();
|
|
15362
|
-
}
|
|
15363
|
-
|
|
15364
14011
|
/**
|
|
15365
14012
|
* We want to batch uploads of replay events. Save events only if
|
|
15366
14013
|
* `<flushMinDelay>` milliseconds have elapsed since the last event
|
|
@@ -15370,12 +14017,12 @@ class ReplayContainer {
|
|
|
15370
14017
|
* processing and hand back control to caller.
|
|
15371
14018
|
*/
|
|
15372
14019
|
addUpdate(cb) {
|
|
15373
|
-
// We need to always run `cb` (e.g. in the case of `this.recordingMode == '
|
|
14020
|
+
// We need to always run `cb` (e.g. in the case of `this.recordingMode == 'error'`)
|
|
15374
14021
|
const cbResult = cb();
|
|
15375
14022
|
|
|
15376
14023
|
// If this option is turned on then we will only want to call `flush`
|
|
15377
14024
|
// explicitly
|
|
15378
|
-
if (this.recordingMode === '
|
|
14025
|
+
if (this.recordingMode === 'error') {
|
|
15379
14026
|
return;
|
|
15380
14027
|
}
|
|
15381
14028
|
|
|
@@ -15447,12 +14094,12 @@ class ReplayContainer {
|
|
|
15447
14094
|
const oldSessionId = this.getSessionId();
|
|
15448
14095
|
|
|
15449
14096
|
// Prevent starting a new session if the last user activity is older than
|
|
15450
|
-
//
|
|
14097
|
+
// SESSION_IDLE_DURATION. Otherwise non-user activity can trigger a new
|
|
15451
14098
|
// session+recording. This creates noisy replays that do not have much
|
|
15452
14099
|
// content in them.
|
|
15453
14100
|
if (
|
|
15454
14101
|
this._lastActivity &&
|
|
15455
|
-
isExpired(this._lastActivity, this.timeouts.
|
|
14102
|
+
isExpired(this._lastActivity, this.timeouts.sessionIdle) &&
|
|
15456
14103
|
this.session &&
|
|
15457
14104
|
this.session.sampled === 'session'
|
|
15458
14105
|
) {
|
|
@@ -15502,30 +14149,6 @@ class ReplayContainer {
|
|
|
15502
14149
|
this._context.urls.push(url);
|
|
15503
14150
|
}
|
|
15504
14151
|
|
|
15505
|
-
/**
|
|
15506
|
-
* Initialize and start all listeners to varying events (DOM,
|
|
15507
|
-
* Performance Observer, Recording, Sentry SDK, etc)
|
|
15508
|
-
*/
|
|
15509
|
-
_initializeRecording() {
|
|
15510
|
-
this.setInitialState();
|
|
15511
|
-
|
|
15512
|
-
// this method is generally called on page load or manually - in both cases
|
|
15513
|
-
// we should treat it as an activity
|
|
15514
|
-
this._updateSessionActivity();
|
|
15515
|
-
|
|
15516
|
-
this.eventBuffer = createEventBuffer({
|
|
15517
|
-
useCompression: this._options.useCompression,
|
|
15518
|
-
});
|
|
15519
|
-
|
|
15520
|
-
this._removeListeners();
|
|
15521
|
-
this._addListeners();
|
|
15522
|
-
|
|
15523
|
-
// Need to set as enabled before we start recording, as `record()` can trigger a flush with a new checkout
|
|
15524
|
-
this._isEnabled = true;
|
|
15525
|
-
|
|
15526
|
-
this.startRecording();
|
|
15527
|
-
}
|
|
15528
|
-
|
|
15529
14152
|
/** A wrapper to conditionally capture exceptions. */
|
|
15530
14153
|
_handleException(error) {
|
|
15531
14154
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error('[Replay]', error);
|
|
@@ -15545,7 +14168,7 @@ class ReplayContainer {
|
|
|
15545
14168
|
stickySession: Boolean(this._options.stickySession),
|
|
15546
14169
|
currentSession: this.session,
|
|
15547
14170
|
sessionSampleRate: this._options.sessionSampleRate,
|
|
15548
|
-
|
|
14171
|
+
errorSampleRate: this._options.errorSampleRate,
|
|
15549
14172
|
});
|
|
15550
14173
|
|
|
15551
14174
|
// If session was newly created (i.e. was not loaded from storage), then
|
|
@@ -15562,7 +14185,7 @@ class ReplayContainer {
|
|
|
15562
14185
|
this.session = session;
|
|
15563
14186
|
|
|
15564
14187
|
if (!this.session.sampled) {
|
|
15565
|
-
|
|
14188
|
+
this.stop('session unsampled');
|
|
15566
14189
|
return false;
|
|
15567
14190
|
}
|
|
15568
14191
|
|
|
@@ -15577,7 +14200,6 @@ class ReplayContainer {
|
|
|
15577
14200
|
WINDOW.document.addEventListener('visibilitychange', this._handleVisibilityChange);
|
|
15578
14201
|
WINDOW.addEventListener('blur', this._handleWindowBlur);
|
|
15579
14202
|
WINDOW.addEventListener('focus', this._handleWindowFocus);
|
|
15580
|
-
WINDOW.addEventListener('keydown', this._handleKeyboardEvent);
|
|
15581
14203
|
|
|
15582
14204
|
// There is no way to remove these listeners, so ensure they are only added once
|
|
15583
14205
|
if (!this._hasInitializedCoreListeners) {
|
|
@@ -15606,7 +14228,6 @@ class ReplayContainer {
|
|
|
15606
14228
|
|
|
15607
14229
|
WINDOW.removeEventListener('blur', this._handleWindowBlur);
|
|
15608
14230
|
WINDOW.removeEventListener('focus', this._handleWindowFocus);
|
|
15609
|
-
WINDOW.removeEventListener('keydown', this._handleKeyboardEvent);
|
|
15610
14231
|
|
|
15611
14232
|
if (this._performanceObserver) {
|
|
15612
14233
|
this._performanceObserver.disconnect();
|
|
@@ -15657,11 +14278,6 @@ class ReplayContainer {
|
|
|
15657
14278
|
this._doChangeToForegroundTasks(breadcrumb);
|
|
15658
14279
|
};}
|
|
15659
14280
|
|
|
15660
|
-
/** Ensure page remains active when a key is pressed. */
|
|
15661
|
-
__init16() {this._handleKeyboardEvent = (event) => {
|
|
15662
|
-
handleKeyboardEvent(this, event);
|
|
15663
|
-
};}
|
|
15664
|
-
|
|
15665
14281
|
/**
|
|
15666
14282
|
* Tasks to run when we consider a page to be hidden (via blurring and/or visibility)
|
|
15667
14283
|
*/
|
|
@@ -15693,7 +14309,7 @@ class ReplayContainer {
|
|
|
15693
14309
|
const isSessionActive = this.checkAndHandleExpiredSession();
|
|
15694
14310
|
|
|
15695
14311
|
if (!isSessionActive) {
|
|
15696
|
-
// If the user has come back to the page within
|
|
14312
|
+
// If the user has come back to the page within SESSION_IDLE_DURATION
|
|
15697
14313
|
// ms, we will re-use the existing session, otherwise create a new
|
|
15698
14314
|
// session
|
|
15699
14315
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log('[Replay] Document has become active, but session has expired');
|
|
@@ -15741,7 +14357,7 @@ class ReplayContainer {
|
|
|
15741
14357
|
_createCustomBreadcrumb(breadcrumb) {
|
|
15742
14358
|
this.addUpdate(() => {
|
|
15743
14359
|
void addEvent(this, {
|
|
15744
|
-
type: EventType
|
|
14360
|
+
type: EventType.Custom,
|
|
15745
14361
|
timestamp: breadcrumb.timestamp || 0,
|
|
15746
14362
|
data: {
|
|
15747
14363
|
tag: 'breadcrumb',
|
|
@@ -15767,7 +14383,7 @@ class ReplayContainer {
|
|
|
15767
14383
|
* Only flush if `this.recordingMode === 'session'`
|
|
15768
14384
|
*/
|
|
15769
14385
|
_conditionalFlush() {
|
|
15770
|
-
if (this.recordingMode === '
|
|
14386
|
+
if (this.recordingMode === 'error') {
|
|
15771
14387
|
return;
|
|
15772
14388
|
}
|
|
15773
14389
|
|
|
@@ -15782,35 +14398,22 @@ class ReplayContainer {
|
|
|
15782
14398
|
this._context.errorIds.clear();
|
|
15783
14399
|
this._context.traceIds.clear();
|
|
15784
14400
|
this._context.urls = [];
|
|
15785
|
-
|
|
15786
|
-
|
|
15787
|
-
/** Update the initial timestamp based on the buffer content. */
|
|
15788
|
-
_updateInitialTimestampFromEventBuffer() {
|
|
15789
|
-
const { session, eventBuffer } = this;
|
|
15790
|
-
if (!session || !eventBuffer) {
|
|
15791
|
-
return;
|
|
15792
|
-
}
|
|
15793
|
-
|
|
15794
|
-
// we only ever update this on the initial segment
|
|
15795
|
-
if (session.segmentId) {
|
|
15796
|
-
return;
|
|
15797
|
-
}
|
|
15798
|
-
|
|
15799
|
-
const earliestEvent = eventBuffer.getEarliestTimestamp();
|
|
15800
|
-
if (earliestEvent && earliestEvent < this._context.initialTimestamp) {
|
|
15801
|
-
this._context.initialTimestamp = earliestEvent;
|
|
15802
|
-
}
|
|
14401
|
+
this._context.earliestEvent = null;
|
|
15803
14402
|
}
|
|
15804
14403
|
|
|
15805
14404
|
/**
|
|
15806
14405
|
* Return and clear _context
|
|
15807
14406
|
*/
|
|
15808
14407
|
_popEventContext() {
|
|
14408
|
+
if (this._context.earliestEvent && this._context.earliestEvent < this._context.initialTimestamp) {
|
|
14409
|
+
this._context.initialTimestamp = this._context.earliestEvent;
|
|
14410
|
+
}
|
|
14411
|
+
|
|
15809
14412
|
const _context = {
|
|
15810
14413
|
initialTimestamp: this._context.initialTimestamp,
|
|
15811
14414
|
initialUrl: this._context.initialUrl,
|
|
15812
|
-
errorIds: Array.from(this._context.errorIds),
|
|
15813
|
-
traceIds: Array.from(this._context.traceIds),
|
|
14415
|
+
errorIds: Array.from(this._context.errorIds).filter(Boolean),
|
|
14416
|
+
traceIds: Array.from(this._context.traceIds).filter(Boolean),
|
|
15814
14417
|
urls: this._context.urls,
|
|
15815
14418
|
};
|
|
15816
14419
|
|
|
@@ -15849,9 +14452,6 @@ class ReplayContainer {
|
|
|
15849
14452
|
}
|
|
15850
14453
|
|
|
15851
14454
|
try {
|
|
15852
|
-
// This uses the data from the eventBuffer, so we need to call this before `finish()
|
|
15853
|
-
this._updateInitialTimestampFromEventBuffer();
|
|
15854
|
-
|
|
15855
14455
|
// Note this empties the event buffer regardless of outcome of sending replay
|
|
15856
14456
|
const recordingData = await this.eventBuffer.finish();
|
|
15857
14457
|
|
|
@@ -15867,6 +14467,7 @@ class ReplayContainer {
|
|
|
15867
14467
|
replayId,
|
|
15868
14468
|
recordingData,
|
|
15869
14469
|
segmentId,
|
|
14470
|
+
includeReplayStartTimestamp: segmentId === 0,
|
|
15870
14471
|
eventContext,
|
|
15871
14472
|
session: this.session,
|
|
15872
14473
|
options: this.getOptions(),
|
|
@@ -15878,7 +14479,7 @@ class ReplayContainer {
|
|
|
15878
14479
|
// This means we retried 3 times and all of them failed,
|
|
15879
14480
|
// or we ran into a problem we don't want to retry, like rate limiting.
|
|
15880
14481
|
// In this case, we want to completely stop the replay - otherwise, we may get inconsistent segments
|
|
15881
|
-
|
|
14482
|
+
this.stop('sendReplay');
|
|
15882
14483
|
|
|
15883
14484
|
const client = getCurrentHub().getClient();
|
|
15884
14485
|
|
|
@@ -15892,12 +14493,8 @@ class ReplayContainer {
|
|
|
15892
14493
|
* Flush recording data to Sentry. Creates a lock so that only a single flush
|
|
15893
14494
|
* can be active at a time. Do not call this directly.
|
|
15894
14495
|
*/
|
|
15895
|
-
|
|
15896
|
-
|
|
15897
|
-
}
|
|
15898
|
-
|
|
15899
|
-
= {}) => {
|
|
15900
|
-
if (!this._isEnabled && !force) {
|
|
14496
|
+
__init16() {this._flush = async () => {
|
|
14497
|
+
if (!this._isEnabled) {
|
|
15901
14498
|
// This can happen if e.g. the replay was stopped because of exceeding the retry limit
|
|
15902
14499
|
return;
|
|
15903
14500
|
}
|
|
@@ -15947,7 +14544,7 @@ class ReplayContainer {
|
|
|
15947
14544
|
}
|
|
15948
14545
|
|
|
15949
14546
|
/** Handler for rrweb.record.onMutation */
|
|
15950
|
-
|
|
14547
|
+
__init17() {this._onMutationHandler = (mutations) => {
|
|
15951
14548
|
const count = mutations.length;
|
|
15952
14549
|
|
|
15953
14550
|
const mutationLimit = this._options._experiments.mutationLimit || 0;
|
|
@@ -16081,8 +14678,6 @@ function isElectronNodeRenderer() {
|
|
|
16081
14678
|
const MEDIA_SELECTORS =
|
|
16082
14679
|
'img,image,svg,video,object,picture,embed,map,audio,link[rel="icon"],link[rel="apple-touch-icon"]';
|
|
16083
14680
|
|
|
16084
|
-
const DEFAULT_NETWORK_HEADERS = ['content-length', 'content-type', 'accept'];
|
|
16085
|
-
|
|
16086
14681
|
let _initialized = false;
|
|
16087
14682
|
|
|
16088
14683
|
/**
|
|
@@ -16123,11 +14718,6 @@ class Replay {
|
|
|
16123
14718
|
maskAllInputs = true,
|
|
16124
14719
|
blockAllMedia = true,
|
|
16125
14720
|
|
|
16126
|
-
networkDetailAllowUrls = [],
|
|
16127
|
-
networkCaptureBodies = true,
|
|
16128
|
-
networkRequestHeaders = [],
|
|
16129
|
-
networkResponseHeaders = [],
|
|
16130
|
-
|
|
16131
14721
|
mask = [],
|
|
16132
14722
|
unmask = [],
|
|
16133
14723
|
block = [],
|
|
@@ -16186,13 +14776,6 @@ class Replay {
|
|
|
16186
14776
|
errorSampleRate,
|
|
16187
14777
|
useCompression,
|
|
16188
14778
|
blockAllMedia,
|
|
16189
|
-
maskAllInputs,
|
|
16190
|
-
maskAllText,
|
|
16191
|
-
networkDetailAllowUrls,
|
|
16192
|
-
networkCaptureBodies,
|
|
16193
|
-
networkRequestHeaders: _getMergedNetworkHeaders(networkRequestHeaders),
|
|
16194
|
-
networkResponseHeaders: _getMergedNetworkHeaders(networkResponseHeaders),
|
|
16195
|
-
|
|
16196
14779
|
_experiments,
|
|
16197
14780
|
};
|
|
16198
14781
|
|
|
@@ -16246,7 +14829,14 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
|
|
|
16246
14829
|
}
|
|
16247
14830
|
|
|
16248
14831
|
/**
|
|
16249
|
-
*
|
|
14832
|
+
* We previously used to create a transaction in `setupOnce` and it would
|
|
14833
|
+
* potentially create a transaction before some native SDK integrations have run
|
|
14834
|
+
* and applied their own global event processor. An example is:
|
|
14835
|
+
* https://github.com/getsentry/sentry-javascript/blob/b47ceafbdac7f8b99093ce6023726ad4687edc48/packages/browser/src/integrations/useragent.ts
|
|
14836
|
+
*
|
|
14837
|
+
* So we call `replay.setup` in next event loop as a workaround to wait for other
|
|
14838
|
+
* global event processors to finish. This is no longer needed, but keeping it
|
|
14839
|
+
* here to avoid any future issues.
|
|
16250
14840
|
*/
|
|
16251
14841
|
setupOnce() {
|
|
16252
14842
|
if (!isBrowser()) {
|
|
@@ -16255,20 +14845,12 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
|
|
|
16255
14845
|
|
|
16256
14846
|
this._setup();
|
|
16257
14847
|
|
|
16258
|
-
//
|
|
16259
|
-
|
|
16260
|
-
// and applied their own global event processor. An example is:
|
|
16261
|
-
// https://github.com/getsentry/sentry-javascript/blob/b47ceafbdac7f8b99093ce6023726ad4687edc48/packages/browser/src/integrations/useragent.ts
|
|
16262
|
-
//
|
|
16263
|
-
// So we call `this._initialize()` in next event loop as a workaround to wait for other
|
|
16264
|
-
// global event processors to finish. This is no longer needed, but keeping it
|
|
16265
|
-
// here to avoid any future issues.
|
|
16266
|
-
setTimeout(() => this._initialize());
|
|
14848
|
+
// XXX: See method comments above
|
|
14849
|
+
setTimeout(() => this.start());
|
|
16267
14850
|
}
|
|
16268
14851
|
|
|
16269
14852
|
/**
|
|
16270
|
-
*
|
|
16271
|
-
* create a new session. Will throw an error if replay is already in progress.
|
|
14853
|
+
* Initializes the plugin.
|
|
16272
14854
|
*
|
|
16273
14855
|
* Creates or loads a session, attaches listeners to varying events (DOM,
|
|
16274
14856
|
* PerformanceObserver, Recording, Sentry SDK, etc)
|
|
@@ -16281,64 +14863,27 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
|
|
|
16281
14863
|
this._replay.start();
|
|
16282
14864
|
}
|
|
16283
14865
|
|
|
16284
|
-
/**
|
|
16285
|
-
* Start replay buffering. Buffers until `flush()` is called or, if
|
|
16286
|
-
* `replaysOnErrorSampleRate` > 0, until an error occurs.
|
|
16287
|
-
*/
|
|
16288
|
-
startBuffering() {
|
|
16289
|
-
if (!this._replay) {
|
|
16290
|
-
return;
|
|
16291
|
-
}
|
|
16292
|
-
|
|
16293
|
-
this._replay.startBuffering();
|
|
16294
|
-
}
|
|
16295
|
-
|
|
16296
14866
|
/**
|
|
16297
14867
|
* Currently, this needs to be manually called (e.g. for tests). Sentry SDK
|
|
16298
14868
|
* does not support a teardown
|
|
16299
14869
|
*/
|
|
16300
14870
|
stop() {
|
|
16301
14871
|
if (!this._replay) {
|
|
16302
|
-
return
|
|
16303
|
-
}
|
|
16304
|
-
|
|
16305
|
-
return this._replay.stop();
|
|
16306
|
-
}
|
|
16307
|
-
|
|
16308
|
-
/**
|
|
16309
|
-
* If not in "session" recording mode, flush event buffer which will create a new replay.
|
|
16310
|
-
* Unless `continueRecording` is false, the replay will continue to record and
|
|
16311
|
-
* behave as a "session"-based replay.
|
|
16312
|
-
*
|
|
16313
|
-
* Otherwise, queue up a flush.
|
|
16314
|
-
*/
|
|
16315
|
-
flush(options) {
|
|
16316
|
-
if (!this._replay || !this._replay.isEnabled()) {
|
|
16317
|
-
return Promise.resolve();
|
|
14872
|
+
return;
|
|
16318
14873
|
}
|
|
16319
14874
|
|
|
16320
|
-
|
|
14875
|
+
this._replay.stop();
|
|
16321
14876
|
}
|
|
16322
14877
|
|
|
16323
14878
|
/**
|
|
16324
|
-
*
|
|
14879
|
+
* Immediately send all pending events.
|
|
16325
14880
|
*/
|
|
16326
|
-
|
|
14881
|
+
flush() {
|
|
16327
14882
|
if (!this._replay || !this._replay.isEnabled()) {
|
|
16328
14883
|
return;
|
|
16329
14884
|
}
|
|
16330
14885
|
|
|
16331
|
-
return this._replay.
|
|
16332
|
-
}
|
|
16333
|
-
/**
|
|
16334
|
-
* Initializes replay.
|
|
16335
|
-
*/
|
|
16336
|
-
_initialize() {
|
|
16337
|
-
if (!this._replay) {
|
|
16338
|
-
return;
|
|
16339
|
-
}
|
|
16340
|
-
|
|
16341
|
-
this._replay.initializeSampling();
|
|
14886
|
+
return this._replay.flushImmediate();
|
|
16342
14887
|
}
|
|
16343
14888
|
|
|
16344
14889
|
/** Setup the integration. */
|
|
@@ -16389,10 +14934,6 @@ function loadReplayOptionsFromClient(initialOptions) {
|
|
|
16389
14934
|
return finalOptions;
|
|
16390
14935
|
}
|
|
16391
14936
|
|
|
16392
|
-
function _getMergedNetworkHeaders(headers) {
|
|
16393
|
-
return [...DEFAULT_NETWORK_HEADERS, ...headers.map(header => header.toLowerCase())];
|
|
16394
|
-
}
|
|
16395
|
-
|
|
16396
14937
|
/**
|
|
16397
14938
|
* Polyfill for the optional chain operator, `?.`, given previous conversion of the expression into an array of values,
|
|
16398
14939
|
* descriptors, and functions.
|
|
@@ -16830,9 +15371,6 @@ class Postgres {
|
|
|
16830
15371
|
const span = _optionalChain([parentSpan, 'optionalAccess', _6 => _6.startChild, 'call', _7 => _7({
|
|
16831
15372
|
description: typeof config === 'string' ? config : (config ).text,
|
|
16832
15373
|
op: 'db',
|
|
16833
|
-
data: {
|
|
16834
|
-
'db.system': 'postgresql',
|
|
16835
|
-
},
|
|
16836
15374
|
})]);
|
|
16837
15375
|
|
|
16838
15376
|
if (typeof callback === 'function') {
|
|
@@ -16909,9 +15447,6 @@ class Mysql {constructor() { Mysql.prototype.__init.call(this); }
|
|
|
16909
15447
|
const span = _optionalChain([parentSpan, 'optionalAccess', _4 => _4.startChild, 'call', _5 => _5({
|
|
16910
15448
|
description: typeof options === 'string' ? options : (options ).sql,
|
|
16911
15449
|
op: 'db',
|
|
16912
|
-
data: {
|
|
16913
|
-
'db.system': 'mysql',
|
|
16914
|
-
},
|
|
16915
15450
|
})]);
|
|
16916
15451
|
|
|
16917
15452
|
if (typeof callback === 'function') {
|
|
@@ -17133,7 +15668,6 @@ class Mongo {
|
|
|
17133
15668
|
collectionName: collection.collectionName,
|
|
17134
15669
|
dbName: collection.dbName,
|
|
17135
15670
|
namespace: collection.namespace,
|
|
17136
|
-
'db.system': 'mongodb',
|
|
17137
15671
|
};
|
|
17138
15672
|
const spanContext = {
|
|
17139
15673
|
op: 'db',
|
|
@@ -17220,15 +15754,31 @@ class Prisma {
|
|
|
17220
15754
|
}
|
|
17221
15755
|
|
|
17222
15756
|
this._client.$use((params, next) => {
|
|
15757
|
+
const scope = getCurrentHub().getScope();
|
|
15758
|
+
const parentSpan = _optionalChain([scope, 'optionalAccess', _2 => _2.getSpan, 'call', _3 => _3()]);
|
|
15759
|
+
|
|
17223
15760
|
const action = params.action;
|
|
17224
15761
|
const model = params.model;
|
|
17225
|
-
|
|
17226
|
-
|
|
17227
|
-
|
|
17228
|
-
|
|
15762
|
+
|
|
15763
|
+
const span = _optionalChain([parentSpan, 'optionalAccess', _4 => _4.startChild, 'call', _5 => _5({
|
|
15764
|
+
description: model ? `${model} ${action}` : action,
|
|
15765
|
+
op: 'db.sql.prisma',
|
|
15766
|
+
})]);
|
|
15767
|
+
|
|
15768
|
+
const rv = next(params);
|
|
15769
|
+
|
|
15770
|
+
if (isThenable(rv)) {
|
|
15771
|
+
return rv.then((res) => {
|
|
15772
|
+
_optionalChain([span, 'optionalAccess', _6 => _6.finish, 'call', _7 => _7()]);
|
|
15773
|
+
return res;
|
|
15774
|
+
});
|
|
15775
|
+
}
|
|
15776
|
+
|
|
15777
|
+
_optionalChain([span, 'optionalAccess', _8 => _8.finish, 'call', _9 => _9()]);
|
|
15778
|
+
return rv;
|
|
17229
15779
|
});
|
|
17230
15780
|
}
|
|
17231
|
-
}
|
|
15781
|
+
}Prisma.__initStatic();
|
|
17232
15782
|
|
|
17233
15783
|
/** Tracing integration for graphql package */
|
|
17234
15784
|
class GraphQL {constructor() { GraphQL.prototype.__init.call(this); }
|
|
@@ -25560,6 +24110,7 @@ var STATES$5;
|
|
|
25560
24110
|
STATES["RE_INIT_RECORDER__NEXT_QUESTION"] = "reInitRecorderNextQuestion";
|
|
25561
24111
|
STATES["UPLOADING"] = "uploading";
|
|
25562
24112
|
STATES["CONFIRM"] = "confirm";
|
|
24113
|
+
STATES["CONFIRM_WATING"] = "confirmWaiting";
|
|
25563
24114
|
STATES["FINISHED"] = "finished";
|
|
25564
24115
|
STATES["ERROR"] = "error";
|
|
25565
24116
|
})(STATES$5 || (STATES$5 = {}));
|
|
@@ -25613,6 +24164,7 @@ var ACTIONS$6;
|
|
|
25613
24164
|
ACTIONS["RESET_FAILED_RECORDING_ATTEMPTS"] = "resetFailedRecordingAttempts";
|
|
25614
24165
|
ACTIONS["CLEAR_VIDEO_ERROR"] = "clearVideoError";
|
|
25615
24166
|
ACTIONS["UPDATE_VIDEO_DIMENSIONS"] = "updateVideoDimensions";
|
|
24167
|
+
ACTIONS["UPDATE_UPLOADED_FALSE_COUNT"] = "updateUploadedFalseCount";
|
|
25616
24168
|
})(ACTIONS$6 || (ACTIONS$6 = {}));
|
|
25617
24169
|
var EVENTS$5;
|
|
25618
24170
|
(function (EVENTS) {
|
|
@@ -25668,6 +24220,7 @@ var GUARDS$3;
|
|
|
25668
24220
|
GUARDS["IS_RECORDER_READY"] = "isRecorderReady";
|
|
25669
24221
|
GUARDS["IS_ASSESSMENT_QUESTION"] = "isAssessmentQuestion";
|
|
25670
24222
|
GUARDS["IS_TIMES_UP"] = "isTimesUp";
|
|
24223
|
+
GUARDS["SHOULD_TRY_TO_CONFIRM"] = "shouldTryToConfirm";
|
|
25671
24224
|
})(GUARDS$3 || (GUARDS$3 = {}));
|
|
25672
24225
|
var TAGS;
|
|
25673
24226
|
(function (TAGS) {
|
|
@@ -25677,6 +24230,7 @@ var TAGS;
|
|
|
25677
24230
|
TAGS["DISPLAY_OUTER_VIEW"] = "displayOuterView";
|
|
25678
24231
|
TAGS["DISPLAY_QUESTION"] = "displayQuestion";
|
|
25679
24232
|
TAGS["DISPLAY_QUESTIONS_LIST"] = "displayQuestionsList";
|
|
24233
|
+
TAGS["DISPLAY_UPLOAD"] = "displayUpload";
|
|
25680
24234
|
TAGS["LOADING"] = "loading";
|
|
25681
24235
|
})(TAGS || (TAGS = {}));
|
|
25682
24236
|
|
|
@@ -30398,7 +28952,7 @@ const configGenerator = () => {
|
|
|
30398
28952
|
let release;
|
|
30399
28953
|
try {
|
|
30400
28954
|
environment !== null && environment !== void 0 ? environment : (environment = "staging");
|
|
30401
|
-
release !== null && release !== void 0 ? release : (release = "1.1.23");
|
|
28955
|
+
release !== null && release !== void 0 ? release : (release = "1.1.23-binary-001");
|
|
30402
28956
|
}
|
|
30403
28957
|
catch (_a) {
|
|
30404
28958
|
console.error('sentry configGenerator error');
|
|
@@ -30871,6 +29425,7 @@ const SECONDS_LEFT_HIGHLIGHT = 10;
|
|
|
30871
29425
|
const DEFAULT_ASSESSMENT_MAX_CHARS = 300;
|
|
30872
29426
|
const DEFAULT_ASSESSMENT_DURATION = 0;
|
|
30873
29427
|
const DEFAULT_VIDEO_DIMENSIONS = { width: 1280, height: 720 }; // Transcoder default dimensions (720p)
|
|
29428
|
+
const MAX_CONFIRM_ATTEMPTS = 5;
|
|
30874
29429
|
// Font
|
|
30875
29430
|
const FONT_URL = 'https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@400;600;700&display=swap';
|
|
30876
29431
|
var RETAKE_SPEED;
|
|
@@ -35031,8 +33586,8 @@ function memoizeOne(resultFn, isEqual) {
|
|
|
35031
33586
|
}
|
|
35032
33587
|
|
|
35033
33588
|
var memoizeOne_esm = /*#__PURE__*/Object.freeze({
|
|
35034
|
-
|
|
35035
|
-
|
|
33589
|
+
__proto__: null,
|
|
33590
|
+
'default': memoizeOne
|
|
35036
33591
|
});
|
|
35037
33592
|
|
|
35038
33593
|
var require$$2 = /*@__PURE__*/getAugmentedNamespace(memoizeOne_esm);
|
|
@@ -38992,6 +37547,11 @@ var EVENT_TYPES;
|
|
|
38992
37547
|
EVENT_TYPES["SOUND_RESTORED"] = "soundRestored";
|
|
38993
37548
|
EVENT_TYPES["TIMES_UP"] = "timesUp";
|
|
38994
37549
|
EVENT_TYPES["COMPLETED_INTERVIEW"] = "completedInterview";
|
|
37550
|
+
EVENT_TYPES["RECONNECTED"] = "reconnected";
|
|
37551
|
+
EVENT_TYPES["CONFIRM_UPLOADED_FAILED"] = "confirmUploadedFailed";
|
|
37552
|
+
EVENT_TYPES["FINISHED"] = "finished";
|
|
37553
|
+
EVENT_TYPES["ON_FINISH_SUCCEED"] = "onFinishSucceed";
|
|
37554
|
+
EVENT_TYPES["ON_FINISH_FAILED"] = "onFinishFailed";
|
|
38995
37555
|
})(EVENT_TYPES || (EVENT_TYPES = {}));
|
|
38996
37556
|
let event_id;
|
|
38997
37557
|
const updateEventId = (eventId) => { event_id = eventId; };
|
|
@@ -39541,31 +38101,6 @@ const Setup = ({ widgetMachine, sendToWidget, isPracticeDisabled, recordWithoutV
|
|
|
39541
38101
|
React__default.createElement(C, { className: startButtonClassNames, color: "special", backgroundColor: "white", onClick: () => sendToWidget(EVENTS$5.QUESTION_MODE), disabled: !canStartInterview }, t(isResumed ? 'welcome.resumeInterview' : 'buttons.btn_start').toUpperCase()))));
|
|
39542
38102
|
};
|
|
39543
38103
|
|
|
39544
|
-
/*! *****************************************************************************
|
|
39545
|
-
Copyright (c) Microsoft Corporation.
|
|
39546
|
-
|
|
39547
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
39548
|
-
purpose with or without fee is hereby granted.
|
|
39549
|
-
|
|
39550
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
39551
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
39552
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
39553
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
39554
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
39555
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
39556
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
39557
|
-
***************************************************************************** */
|
|
39558
|
-
|
|
39559
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
39560
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
39561
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
39562
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39563
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
39564
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
39565
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
39566
|
-
});
|
|
39567
|
-
}
|
|
39568
|
-
|
|
39569
38104
|
const uploadToS3 = (url, data, onProgress, timeout = 0) => s3AxiosInstance.put(url, data, {
|
|
39570
38105
|
headers: { 'Content-Type': 'video/webm' }, onUploadProgress: onProgress, timeout,
|
|
39571
38106
|
});
|
|
@@ -39636,8 +38171,8 @@ const OuterView = ({ widgetMachine, sendToWidget, recorderRef }) => {
|
|
|
39636
38171
|
const isQuestionDisplayed = widgetMachine.hasTag(TAGS.DISPLAY_QUESTION) || (isVideoQuestionState && !currentQuestionObj.thinkingTime);
|
|
39637
38172
|
const isPreviewState = widgetMachine.matches(STATES$5.PREVIEW);
|
|
39638
38173
|
const isUploadingState = widgetMachine.matches(STATES$5.UPLOADING);
|
|
39639
|
-
const isConfirmState = widgetMachine.matches(STATES$5.CONFIRM);
|
|
39640
38174
|
const isQuestionsListDisplayed = widgetMachine.hasTag(TAGS.DISPLAY_QUESTIONS_LIST);
|
|
38175
|
+
const isUploadDisplayed = widgetMachine.hasTag(TAGS.DISPLAY_UPLOAD);
|
|
39641
38176
|
const isRecording = recorderMachine.matches({ [STATES$6.RECORDING]: STATES$6.COLLECTING_BLOBS });
|
|
39642
38177
|
const isCountDown = recorderMachine.matches({ [STATES$6.RECORDING]: STATES$6.COUNT_DOWN });
|
|
39643
38178
|
const isPracticeMode = recordingType === TAKE_TYPES.PRACTICE;
|
|
@@ -39655,7 +38190,7 @@ const OuterView = ({ widgetMachine, sendToWidget, recorderRef }) => {
|
|
|
39655
38190
|
isSetupState && React__default.createElement(Setup, { recordWithoutVideo: recordWithoutVideo, widgetMachine: widgetMachine, sendToWidget: sendToWidget, isPracticeDisabled: !!config.disablePractice }),
|
|
39656
38191
|
isQuestionsListDisplayed && React__default.createElement(QuestionsList, { questions: questions, currentQuestion: currentQuestion, isPracticeMode: isPracticeMode, questionsStatus: questionsStatus }),
|
|
39657
38192
|
isQuestionDisplayed && React__default.createElement(Question, { questionObj: currentQuestionObj }),
|
|
39658
|
-
|
|
38193
|
+
isUploadDisplayed && (React__default.createElement(Upload, { isConnected: isConnected, totalFileSize: totalFileSize, totalUploadedFilesSize: totalUploadedFilesSize, totalUploadSpeed: totalUploadSpeed }))));
|
|
39659
38194
|
};
|
|
39660
38195
|
|
|
39661
38196
|
var actions = {};
|
|
@@ -43484,9 +42019,7 @@ var AsapAction = (function (_super) {
|
|
|
43484
42019
|
var actions = scheduler.actions;
|
|
43485
42020
|
if (id != null && ((_a = actions[actions.length - 1]) === null || _a === void 0 ? void 0 : _a.id) !== id) {
|
|
43486
42021
|
immediateProvider.clearImmediate(id);
|
|
43487
|
-
|
|
43488
|
-
scheduler._scheduled = undefined;
|
|
43489
|
-
}
|
|
42022
|
+
scheduler._scheduled = undefined;
|
|
43490
42023
|
}
|
|
43491
42024
|
return undefined;
|
|
43492
42025
|
};
|
|
@@ -44752,7 +43285,7 @@ const accUploaderMachine = createMachine({
|
|
|
44752
43285
|
actions: [ACTIONS$2.SENTRY],
|
|
44753
43286
|
},
|
|
44754
43287
|
{
|
|
44755
|
-
actions: [ACTIONS$2.
|
|
43288
|
+
actions: [ACTIONS$2.SENTRY],
|
|
44756
43289
|
target: `#uploader.${STATES$2.UPLOADED}`, // In case the video already uploaded
|
|
44757
43290
|
},
|
|
44758
43291
|
],
|
|
@@ -44769,7 +43302,6 @@ const accUploaderMachine = createMachine({
|
|
|
44769
43302
|
id: 'uploadToS3',
|
|
44770
43303
|
src: ({ signedUrl, file }) => (callback) => uploadToS3(signedUrl, file, callback),
|
|
44771
43304
|
onDone: {
|
|
44772
|
-
// actions: [ACTIONS.SET_UPLOADED],
|
|
44773
43305
|
target: `#uploader.${STATES$2.UPLOADED}`,
|
|
44774
43306
|
},
|
|
44775
43307
|
onError: {
|
|
@@ -45125,10 +43657,14 @@ const accWidgetMachine = createMachine({
|
|
|
45125
43657
|
failedRecordingMessage: VIDEO_CORRUPTED_STATES.NO_ERROR,
|
|
45126
43658
|
isResumed: false,
|
|
45127
43659
|
videoDimensions: DEFAULT_VIDEO_DIMENSIONS,
|
|
43660
|
+
confirmUploadedFalseCount: 0,
|
|
45128
43661
|
},
|
|
45129
43662
|
on: {
|
|
45130
43663
|
[EVENTS$1.CONNECTION_CHANGED]: {
|
|
45131
|
-
actions: [
|
|
43664
|
+
actions: [
|
|
43665
|
+
ACTIONS$6.SET_CONNECTION,
|
|
43666
|
+
{ type: ACTIONS$6.EMIT_TRACKING_EVENT, data: { eventType: EVENT_TYPES.RECONNECTED } },
|
|
43667
|
+
],
|
|
45132
43668
|
},
|
|
45133
43669
|
[EVENTS$5.UPLOADER_PROGRESS]: {
|
|
45134
43670
|
actions: [ACTIONS$6.UPDATE_TOTAL_UPLOADED_FILES_SIZE],
|
|
@@ -45655,7 +44191,7 @@ const accWidgetMachine = createMachine({
|
|
|
45655
44191
|
},
|
|
45656
44192
|
},
|
|
45657
44193
|
[STATES$5.UPLOADING]: {
|
|
45658
|
-
tags: [TAGS.DISPLAY_OUTER_VIEW],
|
|
44194
|
+
tags: [TAGS.DISPLAY_OUTER_VIEW, TAGS.DISPLAY_UPLOAD],
|
|
45659
44195
|
entry: [
|
|
45660
44196
|
{ type: ACTIONS$6.SESSION_EVENT, data: { event: 'widget_completed', type: 'date' } },
|
|
45661
44197
|
{ type: ACTIONS$6.CONSOLE_DEBUG, data: { message: DEBUG.UPLOADING_STATE } },
|
|
@@ -45669,30 +44205,57 @@ const accWidgetMachine = createMachine({
|
|
|
45669
44205
|
},
|
|
45670
44206
|
},
|
|
45671
44207
|
},
|
|
44208
|
+
[STATES$5.CONFIRM_WATING]: {
|
|
44209
|
+
tags: [TAGS.DISPLAY_OUTER_VIEW, TAGS.DISPLAY_UPLOAD],
|
|
44210
|
+
always: {
|
|
44211
|
+
target: STATES$5.CONFIRM,
|
|
44212
|
+
cond: GUARDS$3.IS_CONNECTED,
|
|
44213
|
+
},
|
|
44214
|
+
},
|
|
45672
44215
|
[STATES$5.CONFIRM]: {
|
|
45673
|
-
tags: [TAGS.DISPLAY_OUTER_VIEW],
|
|
44216
|
+
tags: [TAGS.DISPLAY_OUTER_VIEW, TAGS.DISPLAY_UPLOAD],
|
|
45674
44217
|
invoke: {
|
|
45675
44218
|
id: 'getVideo',
|
|
45676
44219
|
src: (context) => { var _a; return getVideo(((_a = context.widgetConfig.video) === null || _a === void 0 ? void 0 : _a.video_id) || ''); },
|
|
45677
|
-
onDone:
|
|
45678
|
-
|
|
45679
|
-
|
|
45680
|
-
|
|
44220
|
+
onDone: [
|
|
44221
|
+
{
|
|
44222
|
+
target: STATES$5.FINISHED,
|
|
44223
|
+
cond: (_, event) => !!event.data.data.data.video.uploaded,
|
|
44224
|
+
},
|
|
44225
|
+
{
|
|
44226
|
+
actions: [
|
|
44227
|
+
ACTIONS$6.UPDATE_UPLOADED_FALSE_COUNT,
|
|
44228
|
+
{ type: ACTIONS$6.SENTRY, data: { eventName: 'CONFIRM::UPLOADED_FALSE' } },
|
|
44229
|
+
],
|
|
44230
|
+
target: STATES$5.CONFIRM_WATING,
|
|
44231
|
+
cond: GUARDS$3.SHOULD_TRY_TO_CONFIRM,
|
|
44232
|
+
},
|
|
44233
|
+
{
|
|
44234
|
+
actions: [
|
|
44235
|
+
{ type: ACTIONS$6.SET_VIDEO_ERROR, data: { errorMessage: 'Error, Please contact support' } },
|
|
44236
|
+
{ type: ACTIONS$6.EMIT_TRACKING_EVENT, data: { eventType: EVENT_TYPES.CONFIRM_UPLOADED_FAILED } },
|
|
44237
|
+
],
|
|
44238
|
+
target: STATES$5.ERROR,
|
|
44239
|
+
},
|
|
44240
|
+
],
|
|
45681
44241
|
onError: [
|
|
45682
44242
|
{
|
|
45683
|
-
actions: [() => console.error('UPDATE_VIDEO_UPLADED_ERROR:'), console.error, ACTIONS$6.SENTRY],
|
|
44243
|
+
actions: [() => console.error('UPDATE_VIDEO_UPLADED_ERROR:'), console.error, { type: ACTIONS$6.SENTRY, data: { eventName: 'CONFIRM::ERROR__NOT_FOUND' } }],
|
|
45684
44244
|
target: STATES$5.FINISHED,
|
|
45685
44245
|
cond: (_, event) => event.data.response.status === STATUS_CODES.NOT_FOUND,
|
|
45686
44246
|
},
|
|
45687
44247
|
{
|
|
45688
|
-
actions: [ACTIONS$6.SENTRY],
|
|
45689
|
-
target: STATES$5.
|
|
44248
|
+
actions: [() => console.error('UPDATE_VIDEO_UPLADED_ERROR:'), console.error, { type: ACTIONS$6.SENTRY, data: { eventName: 'CONFIRM::ERROR' } }],
|
|
44249
|
+
target: STATES$5.CONFIRM_WATING,
|
|
45690
44250
|
},
|
|
45691
44251
|
],
|
|
45692
44252
|
},
|
|
45693
44253
|
},
|
|
45694
44254
|
[STATES$5.FINISHED]: {
|
|
45695
|
-
entry: [
|
|
44255
|
+
entry: [
|
|
44256
|
+
{ type: ACTIONS$6.CONSOLE_DEBUG, data: { message: DEBUG.INTERVIEW_SUBMITTED } },
|
|
44257
|
+
{ type: ACTIONS$6.EMIT_TRACKING_EVENT, data: { eventType: EVENT_TYPES.FINISHED } },
|
|
44258
|
+
],
|
|
45696
44259
|
type: 'final',
|
|
45697
44260
|
},
|
|
45698
44261
|
[STATES$5.ERROR]: {
|
|
@@ -45888,9 +44451,12 @@ const accWidgetMachine = createMachine({
|
|
|
45888
44451
|
widgetConfig: Object.assign(Object.assign({}, widgetConfig), { video: Object.assign(Object.assign({}, widgetConfig.video), { videos: (_b = (_a = widgetConfig.video) === null || _a === void 0 ? void 0 : _a.videos) === null || _b === void 0 ? void 0 : _b.map((video, idx) => ((idx !== questionNumber - 1) ? video : videoFile)) }) }),
|
|
45889
44452
|
});
|
|
45890
44453
|
}),
|
|
45891
|
-
[ACTIONS$6.SET_VIDEO_ERROR]: assign$2((_, event) =>
|
|
45892
|
-
|
|
45893
|
-
|
|
44454
|
+
[ACTIONS$6.SET_VIDEO_ERROR]: assign$2((_, event, meta) => {
|
|
44455
|
+
var _a, _b, _c, _d;
|
|
44456
|
+
return ({
|
|
44457
|
+
error: ((_b = (_a = event.data) === null || _a === void 0 ? void 0 : _a.response) === null || _b === void 0 ? void 0 : _b.data) || { errorMessage: ((_c = event.data) === null || _c === void 0 ? void 0 : _c.message) || ((_d = meta.action.data) === null || _d === void 0 ? void 0 : _d.errorMessage) },
|
|
44458
|
+
});
|
|
44459
|
+
}),
|
|
45894
44460
|
[ACTIONS$6.REVOKE_MEMORY]: send$2((_, event) => ({ type: EVENTS$4.REMOVE_TAKES, data: { questionToRemove: event.data.questionNumber } }), { to: ({ storageRef }) => storageRef }),
|
|
45895
44461
|
[ACTIONS$6.UPDATE_VIDEO_OBJECT]: assign$2(({ widgetConfig, recordingType }) => {
|
|
45896
44462
|
var _a, _b;
|
|
@@ -45924,6 +44490,9 @@ const accWidgetMachine = createMachine({
|
|
|
45924
44490
|
height: event.data.height,
|
|
45925
44491
|
},
|
|
45926
44492
|
})),
|
|
44493
|
+
[ACTIONS$6.UPDATE_UPLOADED_FALSE_COUNT]: assign$2(({ confirmUploadedFalseCount }) => ({
|
|
44494
|
+
confirmUploadedFalseCount: confirmUploadedFalseCount + 1,
|
|
44495
|
+
})),
|
|
45927
44496
|
},
|
|
45928
44497
|
services: {
|
|
45929
44498
|
[SERVICES$1.UPDATE_VIDEO_OBJECT_CALL]: ({ widgetConfig: { video }, recordingType, speedTestResult }, event, meta) => (callback, onReceive) => {
|
|
@@ -45967,6 +44536,7 @@ const accWidgetMachine = createMachine({
|
|
|
45967
44536
|
[GUARDS$3.IS_RECORDER_READY]: ({ recorderRef }) => (recorderRef === null || recorderRef === void 0 ? void 0 : recorderRef.getSnapshot().value) === STATES$6.IDLE,
|
|
45968
44537
|
[GUARDS$3.IS_ASSESSMENT_QUESTION]: ({ questions, currentQuestion }) => !!questions[currentQuestion - 1].answerType && questions[currentQuestion - 1].answerType !== ANSWER_TYPES.VIDEO,
|
|
45969
44538
|
[GUARDS$3.IS_TIMES_UP]: (_, event) => !!event.data.isTimesUp,
|
|
44539
|
+
[GUARDS$3.SHOULD_TRY_TO_CONFIRM]: ({ confirmUploadedFalseCount }) => confirmUploadedFalseCount <= MAX_CONFIRM_ATTEMPTS,
|
|
45970
44540
|
},
|
|
45971
44541
|
});
|
|
45972
44542
|
|
|
@@ -48489,10 +47059,25 @@ const Main = ({ widgetConfig, setShouldShowWaterMark, myinterviewRef, isWidgetMi
|
|
|
48489
47059
|
useEffect(() => {
|
|
48490
47060
|
setShouldShowWaterMark(!!(company === null || company === void 0 ? void 0 : company.shouldShowWaterMark));
|
|
48491
47061
|
}, [company === null || company === void 0 ? void 0 : company.shouldShowWaterMark]);
|
|
47062
|
+
const _onFinish = () => __awaiter(void 0, void 0, void 0, function* () { var _a, _b; return (_b = (_a = widgetConfig.config).onFinish) === null || _b === void 0 ? void 0 : _b.call(_a, { redirectUrl: candidate.redirectUrl, video_id: (video === null || video === void 0 ? void 0 : video.video_id) || '' }); });
|
|
48492
47063
|
useEffect(() => {
|
|
48493
|
-
var _a, _b;
|
|
48494
47064
|
if (machine.done) {
|
|
48495
|
-
|
|
47065
|
+
if (widgetConfig.config.onFinish) {
|
|
47066
|
+
_onFinish().then(() => {
|
|
47067
|
+
emitTrackEvent({ eventType: EVENT_TYPES.ON_FINISH_SUCCEED });
|
|
47068
|
+
}).catch((err) => {
|
|
47069
|
+
var _a;
|
|
47070
|
+
let errorMessage = '';
|
|
47071
|
+
try {
|
|
47072
|
+
errorMessage = (err === null || err === void 0 ? void 0 : err.message) || (err === null || err === void 0 ? void 0 : err.msg) || ((_a = err === null || err === void 0 ? void 0 : err.data) === null || _a === void 0 ? void 0 : _a.message);
|
|
47073
|
+
}
|
|
47074
|
+
catch (_b) {
|
|
47075
|
+
//
|
|
47076
|
+
}
|
|
47077
|
+
emitTrackEvent({ eventType: EVENT_TYPES.ON_FINISH_FAILED, extraData: { errorMessage } });
|
|
47078
|
+
throw err;
|
|
47079
|
+
});
|
|
47080
|
+
}
|
|
48496
47081
|
}
|
|
48497
47082
|
}, [machine.done]);
|
|
48498
47083
|
useEffect(() => {
|
|
@@ -48508,11 +47093,16 @@ const Main = ({ widgetConfig, setShouldShowWaterMark, myinterviewRef, isWidgetMi
|
|
|
48508
47093
|
});
|
|
48509
47094
|
}
|
|
48510
47095
|
}, [candidate, job === null || job === void 0 ? void 0 : job.language]);
|
|
47096
|
+
const setBackgroundOpacity = () => {
|
|
47097
|
+
var _a;
|
|
47098
|
+
(_a = myinterviewRef === null || myinterviewRef === void 0 ? void 0 : myinterviewRef.current) === null || _a === void 0 ? void 0 : _a.style.setProperty('--myinterview-background-opacity', isLoading || isErrorState ? '0' : '1');
|
|
47099
|
+
};
|
|
48511
47100
|
useEffect(() => {
|
|
48512
47101
|
var _a, _b;
|
|
48513
47102
|
if (isErrorState && (error === null || error === void 0 ? void 0 : error.statusCode) === 400) {
|
|
48514
47103
|
(_b = (_a = widgetConfig.config).onError) === null || _b === void 0 ? void 0 : _b.call(_a, { messageType: 'applied' });
|
|
48515
47104
|
}
|
|
47105
|
+
setBackgroundOpacity();
|
|
48516
47106
|
}, [isErrorState]);
|
|
48517
47107
|
const isResumed = useMemo(() => { var _a, _b; return !!((_b = (_a = widgetConfig.video) === null || _a === void 0 ? void 0 : _a.videos) === null || _b === void 0 ? void 0 : _b.some((v) => v.uploaded)); }, [widgetConfig.video]);
|
|
48518
47108
|
const handleScroll = (e) => {
|
|
@@ -48522,8 +47112,7 @@ const Main = ({ widgetConfig, setShouldShowWaterMark, myinterviewRef, isWidgetMi
|
|
|
48522
47112
|
(_b = viewsRef === null || viewsRef === void 0 ? void 0 : viewsRef.current) === null || _b === void 0 ? void 0 : _b.style.setProperty('--myinterview-widget-practice-opacity', scrollTop > 10 ? '0' : '1');
|
|
48523
47113
|
};
|
|
48524
47114
|
useEffect(() => {
|
|
48525
|
-
|
|
48526
|
-
(_a = myinterviewRef === null || myinterviewRef === void 0 ? void 0 : myinterviewRef.current) === null || _a === void 0 ? void 0 : _a.style.setProperty('--myinterview-background-opacity', isLoading || isErrorState ? '0' : '1');
|
|
47115
|
+
setBackgroundOpacity();
|
|
48527
47116
|
}, [isLoading]);
|
|
48528
47117
|
const onRetry = () => {
|
|
48529
47118
|
send(EVENTS$5.RETRY);
|
|
@@ -48721,15 +47310,15 @@ const Widget = ({ candidate, job, video, config, disabled = false, buttonText =
|
|
|
48721
47310
|
revertBodyStyling();
|
|
48722
47311
|
setIsWidgetOpen(false);
|
|
48723
47312
|
};
|
|
48724
|
-
const onInterviewCompleted = (data) => {
|
|
47313
|
+
const onInterviewCompleted = (data) => __awaiter(void 0, void 0, void 0, function* () {
|
|
48725
47314
|
var _a;
|
|
48726
|
-
(_a = config.onFinish) === null || _a === void 0 ? void 0 : _a.call(config, data);
|
|
48727
47315
|
onCloseWidget();
|
|
48728
|
-
|
|
47316
|
+
yield ((_a = config.onFinish) === null || _a === void 0 ? void 0 : _a.call(config, data));
|
|
47317
|
+
});
|
|
48729
47318
|
const onError = (data) => {
|
|
48730
47319
|
var _a;
|
|
48731
|
-
(_a = config.onError) === null || _a === void 0 ? void 0 : _a.call(config, data);
|
|
48732
47320
|
onCloseWidget();
|
|
47321
|
+
(_a = config.onError) === null || _a === void 0 ? void 0 : _a.call(config, data);
|
|
48733
47322
|
};
|
|
48734
47323
|
const openWidget = () => {
|
|
48735
47324
|
var _a;
|