@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/esm/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getCurrentHub, isSentryRequestUrl, addGlobalEventProcessor, prepareEvent, setContext, captureException } from '@sentry/core';
|
|
2
|
-
import { GLOBAL_OBJ, normalize, fill, htmlTreeAsString, browserPerformanceTimeOrigin, logger, uuid4, SENTRY_XHR_DATA_KEY, dropUndefinedKeys, stringMatchesSomePattern,
|
|
1
|
+
import { getCurrentHub, getClient, isSentryRequestUrl, addGlobalEventProcessor, prepareEvent, setContext, captureException } from '@sentry/core';
|
|
2
|
+
import { GLOBAL_OBJ, normalize, fill, htmlTreeAsString, browserPerformanceTimeOrigin, logger, uuid4, SENTRY_XHR_DATA_KEY, dropUndefinedKeys, stringMatchesSomePattern, addFetchInstrumentationHandler, addXhrInstrumentationHandler, addClickKeypressInstrumentationHandler, addHistoryInstrumentationHandler, createEnvelope, createEventEnvelopeHeaders, getSdkMetadataForEnvelopeHeader, updateRateLimits, isRateLimited, isBrowser } from '@sentry/utils';
|
|
3
3
|
import { addPerformanceInstrumentationHandler, addLcpInstrumentationHandler } from '@sentry-internal/tracing';
|
|
4
4
|
|
|
5
5
|
// exporting a separate copy of `WINDOW` rather than exporting the one from `@sentry/browser`
|
|
@@ -4339,12 +4339,13 @@ const handleDomListener = (
|
|
|
4339
4339
|
}
|
|
4340
4340
|
|
|
4341
4341
|
const isClick = handlerData.name === 'click';
|
|
4342
|
-
const event = isClick
|
|
4342
|
+
const event = isClick ? (handlerData.event ) : undefined;
|
|
4343
4343
|
// Ignore clicks if ctrl/alt/meta/shift keys are held down as they alter behavior of clicks (e.g. open in new tab)
|
|
4344
4344
|
if (
|
|
4345
4345
|
isClick &&
|
|
4346
4346
|
replay.clickDetector &&
|
|
4347
4347
|
event &&
|
|
4348
|
+
event.target &&
|
|
4348
4349
|
!event.altKey &&
|
|
4349
4350
|
!event.metaKey &&
|
|
4350
4351
|
!event.ctrlKey &&
|
|
@@ -5470,7 +5471,7 @@ async function _addEvent(
|
|
|
5470
5471
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.error(error);
|
|
5471
5472
|
await replay.stop({ reason });
|
|
5472
5473
|
|
|
5473
|
-
const client =
|
|
5474
|
+
const client = getClient();
|
|
5474
5475
|
|
|
5475
5476
|
if (client) {
|
|
5476
5477
|
client.recordDroppedEvent('internal_sdk_error', 'replay');
|
|
@@ -5616,7 +5617,7 @@ function handleErrorEvent(replay, event) {
|
|
|
5616
5617
|
}
|
|
5617
5618
|
|
|
5618
5619
|
function isBaseTransportSend() {
|
|
5619
|
-
const client =
|
|
5620
|
+
const client = getClient();
|
|
5620
5621
|
if (!client) {
|
|
5621
5622
|
return false;
|
|
5622
5623
|
}
|
|
@@ -5822,7 +5823,7 @@ function handleHistory(handlerData) {
|
|
|
5822
5823
|
}
|
|
5823
5824
|
|
|
5824
5825
|
/**
|
|
5825
|
-
* Returns a listener to be added to `
|
|
5826
|
+
* Returns a listener to be added to `addHistoryInstrumentationHandler(listener)`.
|
|
5826
5827
|
*/
|
|
5827
5828
|
function handleHistorySpanListener(replay) {
|
|
5828
5829
|
return (handlerData) => {
|
|
@@ -5911,7 +5912,7 @@ function handleFetch(handlerData) {
|
|
|
5911
5912
|
}
|
|
5912
5913
|
|
|
5913
5914
|
/**
|
|
5914
|
-
* Returns a listener to be added to `
|
|
5915
|
+
* Returns a listener to be added to `addFetchInstrumentationHandler(listener)`.
|
|
5915
5916
|
*/
|
|
5916
5917
|
function handleFetchSpanListener(replay) {
|
|
5917
5918
|
return (handlerData) => {
|
|
@@ -5955,7 +5956,7 @@ function handleXhr(handlerData) {
|
|
|
5955
5956
|
}
|
|
5956
5957
|
|
|
5957
5958
|
/**
|
|
5958
|
-
* Returns a listener to be added to `
|
|
5959
|
+
* Returns a listener to be added to `addXhrInstrumentationHandler(listener)`.
|
|
5959
5960
|
*/
|
|
5960
5961
|
function handleXhrSpanListener(replay) {
|
|
5961
5962
|
return (handlerData) => {
|
|
@@ -6022,23 +6023,47 @@ function parseContentLengthHeader(header) {
|
|
|
6022
6023
|
function getBodyString(body) {
|
|
6023
6024
|
try {
|
|
6024
6025
|
if (typeof body === 'string') {
|
|
6025
|
-
return body;
|
|
6026
|
+
return [body];
|
|
6026
6027
|
}
|
|
6027
6028
|
|
|
6028
6029
|
if (body instanceof URLSearchParams) {
|
|
6029
|
-
return body.toString();
|
|
6030
|
+
return [body.toString()];
|
|
6030
6031
|
}
|
|
6031
6032
|
|
|
6032
6033
|
if (body instanceof FormData) {
|
|
6033
|
-
return _serializeFormData(body);
|
|
6034
|
+
return [_serializeFormData(body)];
|
|
6034
6035
|
}
|
|
6035
6036
|
} catch (e2) {
|
|
6036
6037
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('[Replay] Failed to serialize body', body);
|
|
6038
|
+
return [undefined, 'BODY_PARSE_ERROR'];
|
|
6037
6039
|
}
|
|
6038
6040
|
|
|
6039
6041
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.info('[Replay] Skipping network body because of body type', body);
|
|
6040
6042
|
|
|
6041
|
-
return undefined;
|
|
6043
|
+
return [undefined];
|
|
6044
|
+
}
|
|
6045
|
+
|
|
6046
|
+
/** Merge a warning into an existing network request/response. */
|
|
6047
|
+
function mergeWarning(
|
|
6048
|
+
info,
|
|
6049
|
+
warning,
|
|
6050
|
+
) {
|
|
6051
|
+
if (!info) {
|
|
6052
|
+
return {
|
|
6053
|
+
headers: {},
|
|
6054
|
+
size: undefined,
|
|
6055
|
+
_meta: {
|
|
6056
|
+
warnings: [warning],
|
|
6057
|
+
},
|
|
6058
|
+
};
|
|
6059
|
+
}
|
|
6060
|
+
|
|
6061
|
+
const newMeta = { ...info._meta };
|
|
6062
|
+
const existingWarnings = newMeta.warnings || [];
|
|
6063
|
+
newMeta.warnings = [...existingWarnings, warning];
|
|
6064
|
+
|
|
6065
|
+
info._meta = newMeta;
|
|
6066
|
+
return info;
|
|
6042
6067
|
}
|
|
6043
6068
|
|
|
6044
6069
|
/** Convert ReplayNetworkRequestData to a PerformanceEntry. */
|
|
@@ -6171,7 +6196,7 @@ function normalizeNetworkBody(body)
|
|
|
6171
6196
|
return {
|
|
6172
6197
|
body: jsonBody,
|
|
6173
6198
|
};
|
|
6174
|
-
} catch (
|
|
6199
|
+
} catch (e3) {
|
|
6175
6200
|
// fall back to just send the body as string
|
|
6176
6201
|
}
|
|
6177
6202
|
}
|
|
@@ -6316,10 +6341,17 @@ function _getRequestInfo(
|
|
|
6316
6341
|
|
|
6317
6342
|
// We only want to transmit string or string-like bodies
|
|
6318
6343
|
const requestBody = _getFetchRequestArgBody(input);
|
|
6319
|
-
const bodyStr = getBodyString(requestBody);
|
|
6320
|
-
|
|
6344
|
+
const [bodyStr, warning] = getBodyString(requestBody);
|
|
6345
|
+
const data = buildNetworkRequestOrResponse(headers, requestBodySize, bodyStr);
|
|
6346
|
+
|
|
6347
|
+
if (warning) {
|
|
6348
|
+
return mergeWarning(data, warning);
|
|
6349
|
+
}
|
|
6350
|
+
|
|
6351
|
+
return data;
|
|
6321
6352
|
}
|
|
6322
6353
|
|
|
6354
|
+
/** Exported only for tests. */
|
|
6323
6355
|
async function _getResponseInfo(
|
|
6324
6356
|
captureDetails,
|
|
6325
6357
|
{
|
|
@@ -6342,12 +6374,35 @@ async function _getResponseInfo(
|
|
|
6342
6374
|
return buildNetworkRequestOrResponse(headers, responseBodySize, undefined);
|
|
6343
6375
|
}
|
|
6344
6376
|
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6377
|
+
const [bodyText, warning] = await _parseFetchResponseBody(response);
|
|
6378
|
+
const result = getResponseData(bodyText, {
|
|
6379
|
+
networkCaptureBodies,
|
|
6380
|
+
textEncoder,
|
|
6381
|
+
responseBodySize,
|
|
6382
|
+
captureDetails,
|
|
6383
|
+
headers,
|
|
6384
|
+
});
|
|
6385
|
+
|
|
6386
|
+
if (warning) {
|
|
6387
|
+
return mergeWarning(result, warning);
|
|
6388
|
+
}
|
|
6389
|
+
|
|
6390
|
+
return result;
|
|
6391
|
+
}
|
|
6392
|
+
|
|
6393
|
+
function getResponseData(
|
|
6394
|
+
bodyText,
|
|
6395
|
+
{
|
|
6396
|
+
networkCaptureBodies,
|
|
6397
|
+
textEncoder,
|
|
6398
|
+
responseBodySize,
|
|
6399
|
+
captureDetails,
|
|
6400
|
+
headers,
|
|
6401
|
+
}
|
|
6350
6402
|
|
|
6403
|
+
,
|
|
6404
|
+
) {
|
|
6405
|
+
try {
|
|
6351
6406
|
const size =
|
|
6352
6407
|
bodyText && bodyText.length && responseBodySize === undefined
|
|
6353
6408
|
? getBodySize(bodyText, textEncoder)
|
|
@@ -6369,11 +6424,19 @@ async function _getResponseInfo(
|
|
|
6369
6424
|
}
|
|
6370
6425
|
}
|
|
6371
6426
|
|
|
6372
|
-
async function
|
|
6427
|
+
async function _parseFetchResponseBody(response) {
|
|
6428
|
+
const res = _tryCloneResponse(response);
|
|
6429
|
+
|
|
6430
|
+
if (!res) {
|
|
6431
|
+
return [undefined, 'BODY_PARSE_ERROR'];
|
|
6432
|
+
}
|
|
6433
|
+
|
|
6373
6434
|
try {
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6435
|
+
const text = await _tryGetResponseText(res);
|
|
6436
|
+
return [text];
|
|
6437
|
+
} catch (error) {
|
|
6438
|
+
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('[Replay] Failed to get text body from response', error);
|
|
6439
|
+
return [undefined, 'BODY_PARSE_ERROR'];
|
|
6377
6440
|
}
|
|
6378
6441
|
}
|
|
6379
6442
|
|
|
@@ -6436,6 +6499,40 @@ function getHeadersFromOptions(
|
|
|
6436
6499
|
return getAllowedHeaders(headers, allowedHeaders);
|
|
6437
6500
|
}
|
|
6438
6501
|
|
|
6502
|
+
function _tryCloneResponse(response) {
|
|
6503
|
+
try {
|
|
6504
|
+
// We have to clone this, as the body can only be read once
|
|
6505
|
+
return response.clone();
|
|
6506
|
+
} catch (error) {
|
|
6507
|
+
// this can throw if the response was already consumed before
|
|
6508
|
+
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('[Replay] Failed to clone response body', error);
|
|
6509
|
+
}
|
|
6510
|
+
}
|
|
6511
|
+
|
|
6512
|
+
/**
|
|
6513
|
+
* Get the response body of a fetch request, or timeout after 500ms.
|
|
6514
|
+
* Fetch can return a streaming body, that may not resolve (or not for a long time).
|
|
6515
|
+
* If that happens, we rather abort after a short time than keep waiting for this.
|
|
6516
|
+
*/
|
|
6517
|
+
function _tryGetResponseText(response) {
|
|
6518
|
+
return new Promise((resolve, reject) => {
|
|
6519
|
+
const timeout = setTimeout(() => reject(new Error('Timeout while trying to read response body')), 500);
|
|
6520
|
+
|
|
6521
|
+
_getResponseText(response)
|
|
6522
|
+
.then(
|
|
6523
|
+
txt => resolve(txt),
|
|
6524
|
+
reason => reject(reason),
|
|
6525
|
+
)
|
|
6526
|
+
.finally(() => clearTimeout(timeout));
|
|
6527
|
+
});
|
|
6528
|
+
}
|
|
6529
|
+
|
|
6530
|
+
async function _getResponseText(response) {
|
|
6531
|
+
// Force this to be a promise, just to be safe
|
|
6532
|
+
// eslint-disable-next-line no-return-await
|
|
6533
|
+
return await response.text();
|
|
6534
|
+
}
|
|
6535
|
+
|
|
6439
6536
|
/**
|
|
6440
6537
|
* Capture an XHR breadcrumb to a replay.
|
|
6441
6538
|
* This adds additional data (where approriate).
|
|
@@ -6525,8 +6622,8 @@ function _prepareXhrData(
|
|
|
6525
6622
|
: {};
|
|
6526
6623
|
const networkResponseHeaders = getAllowedHeaders(getResponseHeaders(xhr), options.networkResponseHeaders);
|
|
6527
6624
|
|
|
6528
|
-
const requestBody = options.networkCaptureBodies ? getBodyString(input) : undefined;
|
|
6529
|
-
const responseBody = options.networkCaptureBodies ? _getXhrResponseBody(xhr) : undefined;
|
|
6625
|
+
const [requestBody, requestWarning] = options.networkCaptureBodies ? getBodyString(input) : [undefined];
|
|
6626
|
+
const [responseBody, responseWarning] = options.networkCaptureBodies ? _getXhrResponseBody(xhr) : [undefined];
|
|
6530
6627
|
|
|
6531
6628
|
const request = buildNetworkRequestOrResponse(networkRequestHeaders, requestBodySize, requestBody);
|
|
6532
6629
|
const response = buildNetworkRequestOrResponse(networkResponseHeaders, responseBodySize, responseBody);
|
|
@@ -6537,8 +6634,8 @@ function _prepareXhrData(
|
|
|
6537
6634
|
url,
|
|
6538
6635
|
method,
|
|
6539
6636
|
statusCode,
|
|
6540
|
-
request,
|
|
6541
|
-
response,
|
|
6637
|
+
request: requestWarning ? mergeWarning(request, requestWarning) : request,
|
|
6638
|
+
response: responseWarning ? mergeWarning(response, responseWarning) : response,
|
|
6542
6639
|
};
|
|
6543
6640
|
}
|
|
6544
6641
|
|
|
@@ -6561,7 +6658,7 @@ function _getXhrResponseBody(xhr) {
|
|
|
6561
6658
|
const errors = [];
|
|
6562
6659
|
|
|
6563
6660
|
try {
|
|
6564
|
-
return xhr.responseText;
|
|
6661
|
+
return [xhr.responseText];
|
|
6565
6662
|
} catch (e) {
|
|
6566
6663
|
errors.push(e);
|
|
6567
6664
|
}
|
|
@@ -6576,7 +6673,7 @@ function _getXhrResponseBody(xhr) {
|
|
|
6576
6673
|
|
|
6577
6674
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('[Replay] Failed to get xhr response body', ...errors);
|
|
6578
6675
|
|
|
6579
|
-
return undefined;
|
|
6676
|
+
return [undefined];
|
|
6580
6677
|
}
|
|
6581
6678
|
|
|
6582
6679
|
/**
|
|
@@ -6586,7 +6683,7 @@ function _getXhrResponseBody(xhr) {
|
|
|
6586
6683
|
* (enriching it with further data that is _not_ added to the regular breadcrumbs)
|
|
6587
6684
|
*/
|
|
6588
6685
|
function handleNetworkBreadcrumbs(replay) {
|
|
6589
|
-
const client =
|
|
6686
|
+
const client = getClient();
|
|
6590
6687
|
|
|
6591
6688
|
try {
|
|
6592
6689
|
const textEncoder = new TextEncoder();
|
|
@@ -6613,8 +6710,8 @@ function handleNetworkBreadcrumbs(replay) {
|
|
|
6613
6710
|
client.on('beforeAddBreadcrumb', (breadcrumb, hint) => beforeAddNetworkBreadcrumb(options, breadcrumb, hint));
|
|
6614
6711
|
} else {
|
|
6615
6712
|
// Fallback behavior
|
|
6616
|
-
|
|
6617
|
-
|
|
6713
|
+
addFetchInstrumentationHandler(handleFetchSpanListener(replay));
|
|
6714
|
+
addXhrInstrumentationHandler(handleXhrSpanListener(replay));
|
|
6618
6715
|
}
|
|
6619
6716
|
} catch (e2) {
|
|
6620
6717
|
// Do nothing
|
|
@@ -6784,11 +6881,11 @@ function normalizeConsoleBreadcrumb(
|
|
|
6784
6881
|
function addGlobalListeners(replay) {
|
|
6785
6882
|
// Listeners from core SDK //
|
|
6786
6883
|
const scope = getCurrentHub().getScope();
|
|
6787
|
-
const client =
|
|
6884
|
+
const client = getClient();
|
|
6788
6885
|
|
|
6789
6886
|
scope.addScopeListener(handleScopeListener(replay));
|
|
6790
|
-
|
|
6791
|
-
|
|
6887
|
+
addClickKeypressInstrumentationHandler(handleDomListener(replay));
|
|
6888
|
+
addHistoryInstrumentationHandler(handleHistorySpanListener(replay));
|
|
6792
6889
|
handleNetworkBreadcrumbs(replay);
|
|
6793
6890
|
|
|
6794
6891
|
// Tag all (non replay) events that get sent to Sentry with the current
|
|
@@ -8486,7 +8583,7 @@ class ReplayContainer {
|
|
|
8486
8583
|
// In this case, we want to completely stop the replay - otherwise, we may get inconsistent segments
|
|
8487
8584
|
void this.stop({ reason: 'sendReplay' });
|
|
8488
8585
|
|
|
8489
|
-
const client =
|
|
8586
|
+
const client = getClient();
|
|
8490
8587
|
|
|
8491
8588
|
if (client) {
|
|
8492
8589
|
client.recordDroppedEvent('send_error', 'replay');
|
|
@@ -9051,7 +9148,7 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`,
|
|
|
9051
9148
|
|
|
9052
9149
|
/** Parse Replay-related options from SDK options */
|
|
9053
9150
|
function loadReplayOptionsFromClient(initialOptions) {
|
|
9054
|
-
const client =
|
|
9151
|
+
const client = getClient();
|
|
9055
9152
|
const opt = client && (client.getOptions() );
|
|
9056
9153
|
|
|
9057
9154
|
const finalOptions = { sessionSampleRate: 0, errorSampleRate: 0, ...dropUndefinedKeys(initialOptions) };
|