@sentry/replay 7.81.1 → 7.82.0
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/cjs/index.js +133 -36
- package/cjs/index.js.map +1 -1
- package/esm/index.js +135 -38
- package/esm/index.js.map +1 -1
- package/package.json +6 -6
- package/types/coreHandlers/handleDom.d.ts +3 -4
- package/types/coreHandlers/handleDom.d.ts.map +1 -1
- package/types/coreHandlers/handleFetch.d.ts +1 -1
- package/types/coreHandlers/handleHistory.d.ts +3 -7
- package/types/coreHandlers/handleHistory.d.ts.map +1 -1
- package/types/coreHandlers/handleXhr.d.ts +1 -1
- package/types/coreHandlers/util/domUtils.d.ts +2 -7
- package/types/coreHandlers/util/domUtils.d.ts.map +1 -1
- package/types/coreHandlers/util/fetchUtils.d.ts +5 -1
- package/types/coreHandlers/util/fetchUtils.d.ts.map +1 -1
- package/types/coreHandlers/util/networkUtils.d.ts +4 -4
- package/types/coreHandlers/util/networkUtils.d.ts.map +1 -1
- package/types/coreHandlers/util/xhrUtils.d.ts.map +1 -1
- package/types/types/performance.d.ts +1 -1
- package/types/types/performance.d.ts.map +1 -1
- package/types/types/request.d.ts +1 -1
- package/types/types/request.d.ts.map +1 -1
- package/types-ts3.8/coreHandlers/handleDom.d.ts +3 -4
- package/types-ts3.8/coreHandlers/handleFetch.d.ts +1 -1
- package/types-ts3.8/coreHandlers/handleHistory.d.ts +3 -7
- package/types-ts3.8/coreHandlers/handleXhr.d.ts +1 -1
- package/types-ts3.8/coreHandlers/util/domUtils.d.ts +2 -7
- package/types-ts3.8/coreHandlers/util/fetchUtils.d.ts +5 -1
- package/types-ts3.8/coreHandlers/util/networkUtils.d.ts +7 -4
- package/types-ts3.8/types/performance.d.ts +1 -1
- package/types-ts3.8/types/request.d.ts +1 -1
package/cjs/index.js
CHANGED
|
@@ -4341,12 +4341,13 @@ const handleDomListener = (
|
|
|
4341
4341
|
}
|
|
4342
4342
|
|
|
4343
4343
|
const isClick = handlerData.name === 'click';
|
|
4344
|
-
const event = isClick
|
|
4344
|
+
const event = isClick ? (handlerData.event ) : undefined;
|
|
4345
4345
|
// Ignore clicks if ctrl/alt/meta/shift keys are held down as they alter behavior of clicks (e.g. open in new tab)
|
|
4346
4346
|
if (
|
|
4347
4347
|
isClick &&
|
|
4348
4348
|
replay.clickDetector &&
|
|
4349
4349
|
event &&
|
|
4350
|
+
event.target &&
|
|
4350
4351
|
!event.altKey &&
|
|
4351
4352
|
!event.metaKey &&
|
|
4352
4353
|
!event.ctrlKey &&
|
|
@@ -5472,7 +5473,7 @@ async function _addEvent(
|
|
|
5472
5473
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && utils.logger.error(error);
|
|
5473
5474
|
await replay.stop({ reason });
|
|
5474
5475
|
|
|
5475
|
-
const client = core.
|
|
5476
|
+
const client = core.getClient();
|
|
5476
5477
|
|
|
5477
5478
|
if (client) {
|
|
5478
5479
|
client.recordDroppedEvent('internal_sdk_error', 'replay');
|
|
@@ -5618,7 +5619,7 @@ function handleErrorEvent(replay, event) {
|
|
|
5618
5619
|
}
|
|
5619
5620
|
|
|
5620
5621
|
function isBaseTransportSend() {
|
|
5621
|
-
const client = core.
|
|
5622
|
+
const client = core.getClient();
|
|
5622
5623
|
if (!client) {
|
|
5623
5624
|
return false;
|
|
5624
5625
|
}
|
|
@@ -5824,7 +5825,7 @@ function handleHistory(handlerData) {
|
|
|
5824
5825
|
}
|
|
5825
5826
|
|
|
5826
5827
|
/**
|
|
5827
|
-
* Returns a listener to be added to `
|
|
5828
|
+
* Returns a listener to be added to `addHistoryInstrumentationHandler(listener)`.
|
|
5828
5829
|
*/
|
|
5829
5830
|
function handleHistorySpanListener(replay) {
|
|
5830
5831
|
return (handlerData) => {
|
|
@@ -5913,7 +5914,7 @@ function handleFetch(handlerData) {
|
|
|
5913
5914
|
}
|
|
5914
5915
|
|
|
5915
5916
|
/**
|
|
5916
|
-
* Returns a listener to be added to `
|
|
5917
|
+
* Returns a listener to be added to `addFetchInstrumentationHandler(listener)`.
|
|
5917
5918
|
*/
|
|
5918
5919
|
function handleFetchSpanListener(replay) {
|
|
5919
5920
|
return (handlerData) => {
|
|
@@ -5957,7 +5958,7 @@ function handleXhr(handlerData) {
|
|
|
5957
5958
|
}
|
|
5958
5959
|
|
|
5959
5960
|
/**
|
|
5960
|
-
* Returns a listener to be added to `
|
|
5961
|
+
* Returns a listener to be added to `addXhrInstrumentationHandler(listener)`.
|
|
5961
5962
|
*/
|
|
5962
5963
|
function handleXhrSpanListener(replay) {
|
|
5963
5964
|
return (handlerData) => {
|
|
@@ -6024,23 +6025,47 @@ function parseContentLengthHeader(header) {
|
|
|
6024
6025
|
function getBodyString(body) {
|
|
6025
6026
|
try {
|
|
6026
6027
|
if (typeof body === 'string') {
|
|
6027
|
-
return body;
|
|
6028
|
+
return [body];
|
|
6028
6029
|
}
|
|
6029
6030
|
|
|
6030
6031
|
if (body instanceof URLSearchParams) {
|
|
6031
|
-
return body.toString();
|
|
6032
|
+
return [body.toString()];
|
|
6032
6033
|
}
|
|
6033
6034
|
|
|
6034
6035
|
if (body instanceof FormData) {
|
|
6035
|
-
return _serializeFormData(body);
|
|
6036
|
+
return [_serializeFormData(body)];
|
|
6036
6037
|
}
|
|
6037
6038
|
} catch (e2) {
|
|
6038
6039
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && utils.logger.warn('[Replay] Failed to serialize body', body);
|
|
6040
|
+
return [undefined, 'BODY_PARSE_ERROR'];
|
|
6039
6041
|
}
|
|
6040
6042
|
|
|
6041
6043
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && utils.logger.info('[Replay] Skipping network body because of body type', body);
|
|
6042
6044
|
|
|
6043
|
-
return undefined;
|
|
6045
|
+
return [undefined];
|
|
6046
|
+
}
|
|
6047
|
+
|
|
6048
|
+
/** Merge a warning into an existing network request/response. */
|
|
6049
|
+
function mergeWarning(
|
|
6050
|
+
info,
|
|
6051
|
+
warning,
|
|
6052
|
+
) {
|
|
6053
|
+
if (!info) {
|
|
6054
|
+
return {
|
|
6055
|
+
headers: {},
|
|
6056
|
+
size: undefined,
|
|
6057
|
+
_meta: {
|
|
6058
|
+
warnings: [warning],
|
|
6059
|
+
},
|
|
6060
|
+
};
|
|
6061
|
+
}
|
|
6062
|
+
|
|
6063
|
+
const newMeta = { ...info._meta };
|
|
6064
|
+
const existingWarnings = newMeta.warnings || [];
|
|
6065
|
+
newMeta.warnings = [...existingWarnings, warning];
|
|
6066
|
+
|
|
6067
|
+
info._meta = newMeta;
|
|
6068
|
+
return info;
|
|
6044
6069
|
}
|
|
6045
6070
|
|
|
6046
6071
|
/** Convert ReplayNetworkRequestData to a PerformanceEntry. */
|
|
@@ -6173,7 +6198,7 @@ function normalizeNetworkBody(body)
|
|
|
6173
6198
|
return {
|
|
6174
6199
|
body: jsonBody,
|
|
6175
6200
|
};
|
|
6176
|
-
} catch (
|
|
6201
|
+
} catch (e3) {
|
|
6177
6202
|
// fall back to just send the body as string
|
|
6178
6203
|
}
|
|
6179
6204
|
}
|
|
@@ -6318,10 +6343,17 @@ function _getRequestInfo(
|
|
|
6318
6343
|
|
|
6319
6344
|
// We only want to transmit string or string-like bodies
|
|
6320
6345
|
const requestBody = _getFetchRequestArgBody(input);
|
|
6321
|
-
const bodyStr = getBodyString(requestBody);
|
|
6322
|
-
|
|
6346
|
+
const [bodyStr, warning] = getBodyString(requestBody);
|
|
6347
|
+
const data = buildNetworkRequestOrResponse(headers, requestBodySize, bodyStr);
|
|
6348
|
+
|
|
6349
|
+
if (warning) {
|
|
6350
|
+
return mergeWarning(data, warning);
|
|
6351
|
+
}
|
|
6352
|
+
|
|
6353
|
+
return data;
|
|
6323
6354
|
}
|
|
6324
6355
|
|
|
6356
|
+
/** Exported only for tests. */
|
|
6325
6357
|
async function _getResponseInfo(
|
|
6326
6358
|
captureDetails,
|
|
6327
6359
|
{
|
|
@@ -6344,12 +6376,35 @@ async function _getResponseInfo(
|
|
|
6344
6376
|
return buildNetworkRequestOrResponse(headers, responseBodySize, undefined);
|
|
6345
6377
|
}
|
|
6346
6378
|
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6379
|
+
const [bodyText, warning] = await _parseFetchResponseBody(response);
|
|
6380
|
+
const result = getResponseData(bodyText, {
|
|
6381
|
+
networkCaptureBodies,
|
|
6382
|
+
textEncoder,
|
|
6383
|
+
responseBodySize,
|
|
6384
|
+
captureDetails,
|
|
6385
|
+
headers,
|
|
6386
|
+
});
|
|
6387
|
+
|
|
6388
|
+
if (warning) {
|
|
6389
|
+
return mergeWarning(result, warning);
|
|
6390
|
+
}
|
|
6391
|
+
|
|
6392
|
+
return result;
|
|
6393
|
+
}
|
|
6394
|
+
|
|
6395
|
+
function getResponseData(
|
|
6396
|
+
bodyText,
|
|
6397
|
+
{
|
|
6398
|
+
networkCaptureBodies,
|
|
6399
|
+
textEncoder,
|
|
6400
|
+
responseBodySize,
|
|
6401
|
+
captureDetails,
|
|
6402
|
+
headers,
|
|
6403
|
+
}
|
|
6352
6404
|
|
|
6405
|
+
,
|
|
6406
|
+
) {
|
|
6407
|
+
try {
|
|
6353
6408
|
const size =
|
|
6354
6409
|
bodyText && bodyText.length && responseBodySize === undefined
|
|
6355
6410
|
? getBodySize(bodyText, textEncoder)
|
|
@@ -6371,11 +6426,19 @@ async function _getResponseInfo(
|
|
|
6371
6426
|
}
|
|
6372
6427
|
}
|
|
6373
6428
|
|
|
6374
|
-
async function
|
|
6429
|
+
async function _parseFetchResponseBody(response) {
|
|
6430
|
+
const res = _tryCloneResponse(response);
|
|
6431
|
+
|
|
6432
|
+
if (!res) {
|
|
6433
|
+
return [undefined, 'BODY_PARSE_ERROR'];
|
|
6434
|
+
}
|
|
6435
|
+
|
|
6375
6436
|
try {
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6437
|
+
const text = await _tryGetResponseText(res);
|
|
6438
|
+
return [text];
|
|
6439
|
+
} catch (error) {
|
|
6440
|
+
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && utils.logger.warn('[Replay] Failed to get text body from response', error);
|
|
6441
|
+
return [undefined, 'BODY_PARSE_ERROR'];
|
|
6379
6442
|
}
|
|
6380
6443
|
}
|
|
6381
6444
|
|
|
@@ -6438,6 +6501,40 @@ function getHeadersFromOptions(
|
|
|
6438
6501
|
return getAllowedHeaders(headers, allowedHeaders);
|
|
6439
6502
|
}
|
|
6440
6503
|
|
|
6504
|
+
function _tryCloneResponse(response) {
|
|
6505
|
+
try {
|
|
6506
|
+
// We have to clone this, as the body can only be read once
|
|
6507
|
+
return response.clone();
|
|
6508
|
+
} catch (error) {
|
|
6509
|
+
// this can throw if the response was already consumed before
|
|
6510
|
+
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && utils.logger.warn('[Replay] Failed to clone response body', error);
|
|
6511
|
+
}
|
|
6512
|
+
}
|
|
6513
|
+
|
|
6514
|
+
/**
|
|
6515
|
+
* Get the response body of a fetch request, or timeout after 500ms.
|
|
6516
|
+
* Fetch can return a streaming body, that may not resolve (or not for a long time).
|
|
6517
|
+
* If that happens, we rather abort after a short time than keep waiting for this.
|
|
6518
|
+
*/
|
|
6519
|
+
function _tryGetResponseText(response) {
|
|
6520
|
+
return new Promise((resolve, reject) => {
|
|
6521
|
+
const timeout = setTimeout(() => reject(new Error('Timeout while trying to read response body')), 500);
|
|
6522
|
+
|
|
6523
|
+
_getResponseText(response)
|
|
6524
|
+
.then(
|
|
6525
|
+
txt => resolve(txt),
|
|
6526
|
+
reason => reject(reason),
|
|
6527
|
+
)
|
|
6528
|
+
.finally(() => clearTimeout(timeout));
|
|
6529
|
+
});
|
|
6530
|
+
}
|
|
6531
|
+
|
|
6532
|
+
async function _getResponseText(response) {
|
|
6533
|
+
// Force this to be a promise, just to be safe
|
|
6534
|
+
// eslint-disable-next-line no-return-await
|
|
6535
|
+
return await response.text();
|
|
6536
|
+
}
|
|
6537
|
+
|
|
6441
6538
|
/**
|
|
6442
6539
|
* Capture an XHR breadcrumb to a replay.
|
|
6443
6540
|
* This adds additional data (where approriate).
|
|
@@ -6527,8 +6624,8 @@ function _prepareXhrData(
|
|
|
6527
6624
|
: {};
|
|
6528
6625
|
const networkResponseHeaders = getAllowedHeaders(getResponseHeaders(xhr), options.networkResponseHeaders);
|
|
6529
6626
|
|
|
6530
|
-
const requestBody = options.networkCaptureBodies ? getBodyString(input) : undefined;
|
|
6531
|
-
const responseBody = options.networkCaptureBodies ? _getXhrResponseBody(xhr) : undefined;
|
|
6627
|
+
const [requestBody, requestWarning] = options.networkCaptureBodies ? getBodyString(input) : [undefined];
|
|
6628
|
+
const [responseBody, responseWarning] = options.networkCaptureBodies ? _getXhrResponseBody(xhr) : [undefined];
|
|
6532
6629
|
|
|
6533
6630
|
const request = buildNetworkRequestOrResponse(networkRequestHeaders, requestBodySize, requestBody);
|
|
6534
6631
|
const response = buildNetworkRequestOrResponse(networkResponseHeaders, responseBodySize, responseBody);
|
|
@@ -6539,8 +6636,8 @@ function _prepareXhrData(
|
|
|
6539
6636
|
url,
|
|
6540
6637
|
method,
|
|
6541
6638
|
statusCode,
|
|
6542
|
-
request,
|
|
6543
|
-
response,
|
|
6639
|
+
request: requestWarning ? mergeWarning(request, requestWarning) : request,
|
|
6640
|
+
response: responseWarning ? mergeWarning(response, responseWarning) : response,
|
|
6544
6641
|
};
|
|
6545
6642
|
}
|
|
6546
6643
|
|
|
@@ -6563,7 +6660,7 @@ function _getXhrResponseBody(xhr) {
|
|
|
6563
6660
|
const errors = [];
|
|
6564
6661
|
|
|
6565
6662
|
try {
|
|
6566
|
-
return xhr.responseText;
|
|
6663
|
+
return [xhr.responseText];
|
|
6567
6664
|
} catch (e) {
|
|
6568
6665
|
errors.push(e);
|
|
6569
6666
|
}
|
|
@@ -6578,7 +6675,7 @@ function _getXhrResponseBody(xhr) {
|
|
|
6578
6675
|
|
|
6579
6676
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && utils.logger.warn('[Replay] Failed to get xhr response body', ...errors);
|
|
6580
6677
|
|
|
6581
|
-
return undefined;
|
|
6678
|
+
return [undefined];
|
|
6582
6679
|
}
|
|
6583
6680
|
|
|
6584
6681
|
/**
|
|
@@ -6588,7 +6685,7 @@ function _getXhrResponseBody(xhr) {
|
|
|
6588
6685
|
* (enriching it with further data that is _not_ added to the regular breadcrumbs)
|
|
6589
6686
|
*/
|
|
6590
6687
|
function handleNetworkBreadcrumbs(replay) {
|
|
6591
|
-
const client = core.
|
|
6688
|
+
const client = core.getClient();
|
|
6592
6689
|
|
|
6593
6690
|
try {
|
|
6594
6691
|
const textEncoder = new TextEncoder();
|
|
@@ -6615,8 +6712,8 @@ function handleNetworkBreadcrumbs(replay) {
|
|
|
6615
6712
|
client.on('beforeAddBreadcrumb', (breadcrumb, hint) => beforeAddNetworkBreadcrumb(options, breadcrumb, hint));
|
|
6616
6713
|
} else {
|
|
6617
6714
|
// Fallback behavior
|
|
6618
|
-
utils.
|
|
6619
|
-
utils.
|
|
6715
|
+
utils.addFetchInstrumentationHandler(handleFetchSpanListener(replay));
|
|
6716
|
+
utils.addXhrInstrumentationHandler(handleXhrSpanListener(replay));
|
|
6620
6717
|
}
|
|
6621
6718
|
} catch (e2) {
|
|
6622
6719
|
// Do nothing
|
|
@@ -6786,11 +6883,11 @@ function normalizeConsoleBreadcrumb(
|
|
|
6786
6883
|
function addGlobalListeners(replay) {
|
|
6787
6884
|
// Listeners from core SDK //
|
|
6788
6885
|
const scope = core.getCurrentHub().getScope();
|
|
6789
|
-
const client = core.
|
|
6886
|
+
const client = core.getClient();
|
|
6790
6887
|
|
|
6791
6888
|
scope.addScopeListener(handleScopeListener(replay));
|
|
6792
|
-
utils.
|
|
6793
|
-
utils.
|
|
6889
|
+
utils.addClickKeypressInstrumentationHandler(handleDomListener(replay));
|
|
6890
|
+
utils.addHistoryInstrumentationHandler(handleHistorySpanListener(replay));
|
|
6794
6891
|
handleNetworkBreadcrumbs(replay);
|
|
6795
6892
|
|
|
6796
6893
|
// Tag all (non replay) events that get sent to Sentry with the current
|
|
@@ -8488,7 +8585,7 @@ class ReplayContainer {
|
|
|
8488
8585
|
// In this case, we want to completely stop the replay - otherwise, we may get inconsistent segments
|
|
8489
8586
|
void this.stop({ reason: 'sendReplay' });
|
|
8490
8587
|
|
|
8491
|
-
const client = core.
|
|
8588
|
+
const client = core.getClient();
|
|
8492
8589
|
|
|
8493
8590
|
if (client) {
|
|
8494
8591
|
client.recordDroppedEvent('send_error', 'replay');
|
|
@@ -9053,7 +9150,7 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
|
|
|
9053
9150
|
|
|
9054
9151
|
/** Parse Replay-related options from SDK options */
|
|
9055
9152
|
function loadReplayOptionsFromClient(initialOptions) {
|
|
9056
|
-
const client = core.
|
|
9153
|
+
const client = core.getClient();
|
|
9057
9154
|
const opt = client && (client.getOptions() );
|
|
9058
9155
|
|
|
9059
9156
|
const finalOptions = { sessionSampleRate: 0, errorSampleRate: 0, ...utils.dropUndefinedKeys(initialOptions) };
|