@sentry/replay 7.104.0 → 8.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/cjs/index.js +128 -258
- package/cjs/index.js.map +1 -1
- package/esm/index.js +130 -260
- package/esm/index.js.map +1 -1
- package/package.json +7 -7
- package/types/coreHandlers/handleBreadcrumbs.d.ts +14 -0
- package/types/coreHandlers/handleBreadcrumbs.d.ts.map +1 -0
- package/types/coreHandlers/handleGlobalEvent.d.ts +1 -1
- package/types/coreHandlers/handleGlobalEvent.d.ts.map +1 -1
- package/types/coreHandlers/handleNetworkBreadcrumbs.d.ts +1 -2
- package/types/coreHandlers/handleNetworkBreadcrumbs.d.ts.map +1 -1
- package/types/coreHandlers/util/fetchUtils.d.ts +3 -8
- package/types/coreHandlers/util/fetchUtils.d.ts.map +1 -1
- package/types/coreHandlers/util/networkUtils.d.ts +1 -2
- package/types/coreHandlers/util/networkUtils.d.ts.map +1 -1
- package/types/coreHandlers/util/xhrUtils.d.ts +2 -4
- package/types/coreHandlers/util/xhrUtils.d.ts.map +1 -1
- package/types/util/addGlobalListeners.d.ts.map +1 -1
- package/types/util/getReplay.d.ts.map +1 -1
- package/types/util/prepareReplayEvent.d.ts +2 -2
- package/types/util/prepareReplayEvent.d.ts.map +1 -1
- package/types-ts3.8/coreHandlers/handleBreadcrumbs.d.ts +14 -0
- package/types-ts3.8/coreHandlers/handleGlobalEvent.d.ts +1 -1
- package/types-ts3.8/coreHandlers/handleNetworkBreadcrumbs.d.ts +1 -2
- package/types-ts3.8/coreHandlers/util/fetchUtils.d.ts +3 -8
- package/types-ts3.8/coreHandlers/util/networkUtils.d.ts +1 -2
- package/types-ts3.8/coreHandlers/util/xhrUtils.d.ts +2 -4
- package/types-ts3.8/util/prepareReplayEvent.d.ts +2 -2
- package/types/coreHandlers/handleFetch.d.ts +0 -9
- package/types/coreHandlers/handleFetch.d.ts.map +0 -1
- package/types/coreHandlers/handleScope.d.ts +0 -13
- package/types/coreHandlers/handleScope.d.ts.map +0 -1
- package/types/coreHandlers/handleXhr.d.ts +0 -9
- package/types/coreHandlers/handleXhr.d.ts.map +0 -1
- package/types-ts3.8/coreHandlers/handleFetch.d.ts +0 -9
- package/types-ts3.8/coreHandlers/handleScope.d.ts +0 -13
- package/types-ts3.8/coreHandlers/handleXhr.d.ts +0 -9
package/esm/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { _nullishCoalesce, _optionalChain } from '@sentry/utils';
|
|
2
|
-
import { addBreadcrumb, getClient, isSentryRequestUrl,
|
|
3
|
-
import { GLOBAL_OBJ, normalize, fill, htmlTreeAsString, browserPerformanceTimeOrigin, logger, uuid4,
|
|
2
|
+
import { addBreadcrumb, getClient, isSentryRequestUrl, addEventProcessor, prepareEvent, getIsolationScope, getCurrentScope, setContext, captureException, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core';
|
|
3
|
+
import { GLOBAL_OBJ, normalize, fill, htmlTreeAsString, browserPerformanceTimeOrigin, logger, uuid4, dropUndefinedKeys, stringMatchesSomePattern, SENTRY_XHR_DATA_KEY, addClickKeypressInstrumentationHandler, addHistoryInstrumentationHandler, createEnvelope, createEventEnvelopeHeaders, getSdkMetadataForEnvelopeHeader, updateRateLimits, isRateLimited, consoleSandbox, isBrowser } from '@sentry/utils';
|
|
4
4
|
import { addPerformanceInstrumentationHandler, addLcpInstrumentationHandler } from '@sentry-internal/tracing';
|
|
5
5
|
|
|
6
6
|
// exporting a separate copy of `WINDOW` rather than exporting the one from `@sentry/browser`
|
|
@@ -5829,6 +5829,112 @@ function handleHydrationError(replay, event) {
|
|
|
5829
5829
|
}
|
|
5830
5830
|
}
|
|
5831
5831
|
|
|
5832
|
+
/**
|
|
5833
|
+
* Handle breadcrumbs that Sentry captures, and make sure to capture relevant breadcrumbs to Replay as well.
|
|
5834
|
+
*/
|
|
5835
|
+
function handleBreadcrumbs(replay) {
|
|
5836
|
+
const client = getClient();
|
|
5837
|
+
|
|
5838
|
+
if (!client) {
|
|
5839
|
+
return;
|
|
5840
|
+
}
|
|
5841
|
+
|
|
5842
|
+
client.on('beforeAddBreadcrumb', breadcrumb => beforeAddBreadcrumb(replay, breadcrumb));
|
|
5843
|
+
}
|
|
5844
|
+
|
|
5845
|
+
function beforeAddBreadcrumb(replay, breadcrumb) {
|
|
5846
|
+
if (!replay.isEnabled() || !isBreadcrumbWithCategory(breadcrumb)) {
|
|
5847
|
+
return;
|
|
5848
|
+
}
|
|
5849
|
+
|
|
5850
|
+
const result = normalizeBreadcrumb(breadcrumb);
|
|
5851
|
+
if (result) {
|
|
5852
|
+
addBreadcrumbEvent(replay, result);
|
|
5853
|
+
}
|
|
5854
|
+
}
|
|
5855
|
+
|
|
5856
|
+
/** Exported only for tests. */
|
|
5857
|
+
function normalizeBreadcrumb(breadcrumb) {
|
|
5858
|
+
if (
|
|
5859
|
+
!isBreadcrumbWithCategory(breadcrumb) ||
|
|
5860
|
+
[
|
|
5861
|
+
// fetch & xhr are handled separately,in handleNetworkBreadcrumbs
|
|
5862
|
+
'fetch',
|
|
5863
|
+
'xhr',
|
|
5864
|
+
// These two are breadcrumbs for emitted sentry events, we don't care about them
|
|
5865
|
+
'sentry.event',
|
|
5866
|
+
'sentry.transaction',
|
|
5867
|
+
].includes(breadcrumb.category) ||
|
|
5868
|
+
// We capture UI breadcrumbs separately
|
|
5869
|
+
breadcrumb.category.startsWith('ui.')
|
|
5870
|
+
) {
|
|
5871
|
+
return null;
|
|
5872
|
+
}
|
|
5873
|
+
|
|
5874
|
+
if (breadcrumb.category === 'console') {
|
|
5875
|
+
return normalizeConsoleBreadcrumb(breadcrumb);
|
|
5876
|
+
}
|
|
5877
|
+
|
|
5878
|
+
return createBreadcrumb(breadcrumb);
|
|
5879
|
+
}
|
|
5880
|
+
|
|
5881
|
+
/** exported for tests only */
|
|
5882
|
+
function normalizeConsoleBreadcrumb(
|
|
5883
|
+
breadcrumb,
|
|
5884
|
+
) {
|
|
5885
|
+
const args = breadcrumb.data && breadcrumb.data.arguments;
|
|
5886
|
+
|
|
5887
|
+
if (!Array.isArray(args) || args.length === 0) {
|
|
5888
|
+
return createBreadcrumb(breadcrumb);
|
|
5889
|
+
}
|
|
5890
|
+
|
|
5891
|
+
let isTruncated = false;
|
|
5892
|
+
|
|
5893
|
+
// Avoid giant args captures
|
|
5894
|
+
const normalizedArgs = args.map(arg => {
|
|
5895
|
+
if (!arg) {
|
|
5896
|
+
return arg;
|
|
5897
|
+
}
|
|
5898
|
+
if (typeof arg === 'string') {
|
|
5899
|
+
if (arg.length > CONSOLE_ARG_MAX_SIZE) {
|
|
5900
|
+
isTruncated = true;
|
|
5901
|
+
return `${arg.slice(0, CONSOLE_ARG_MAX_SIZE)}…`;
|
|
5902
|
+
}
|
|
5903
|
+
|
|
5904
|
+
return arg;
|
|
5905
|
+
}
|
|
5906
|
+
if (typeof arg === 'object') {
|
|
5907
|
+
try {
|
|
5908
|
+
const normalizedArg = normalize(arg, 7);
|
|
5909
|
+
const stringified = JSON.stringify(normalizedArg);
|
|
5910
|
+
if (stringified.length > CONSOLE_ARG_MAX_SIZE) {
|
|
5911
|
+
isTruncated = true;
|
|
5912
|
+
// We use the pretty printed JSON string here as a base
|
|
5913
|
+
return `${JSON.stringify(normalizedArg, null, 2).slice(0, CONSOLE_ARG_MAX_SIZE)}…`;
|
|
5914
|
+
}
|
|
5915
|
+
return normalizedArg;
|
|
5916
|
+
} catch (e) {
|
|
5917
|
+
// fall back to default
|
|
5918
|
+
}
|
|
5919
|
+
}
|
|
5920
|
+
|
|
5921
|
+
return arg;
|
|
5922
|
+
});
|
|
5923
|
+
|
|
5924
|
+
return createBreadcrumb({
|
|
5925
|
+
...breadcrumb,
|
|
5926
|
+
data: {
|
|
5927
|
+
...breadcrumb.data,
|
|
5928
|
+
arguments: normalizedArgs,
|
|
5929
|
+
...(isTruncated ? { _meta: { warnings: ['CONSOLE_ARG_TRUNCATED'] } } : {}),
|
|
5930
|
+
},
|
|
5931
|
+
});
|
|
5932
|
+
}
|
|
5933
|
+
|
|
5934
|
+
function isBreadcrumbWithCategory(breadcrumb) {
|
|
5935
|
+
return !!breadcrumb.category;
|
|
5936
|
+
}
|
|
5937
|
+
|
|
5832
5938
|
/**
|
|
5833
5939
|
* Returns true if we think the given event is an error originating inside of rrweb.
|
|
5834
5940
|
*/
|
|
@@ -5906,12 +6012,7 @@ function shouldSampleForBufferEvent(replay, event) {
|
|
|
5906
6012
|
/**
|
|
5907
6013
|
* Returns a listener to be added to `addEventProcessor(listener)`.
|
|
5908
6014
|
*/
|
|
5909
|
-
function handleGlobalEventListener(
|
|
5910
|
-
replay,
|
|
5911
|
-
includeAfterSendEventHandling = false,
|
|
5912
|
-
) {
|
|
5913
|
-
const afterSendHandler = includeAfterSendEventHandling ? handleAfterSendEvent(replay) : undefined;
|
|
5914
|
-
|
|
6015
|
+
function handleGlobalEventListener(replay) {
|
|
5915
6016
|
return Object.assign(
|
|
5916
6017
|
(event, hint) => {
|
|
5917
6018
|
// Do nothing if replay has been disabled
|
|
@@ -5967,13 +6068,6 @@ function handleGlobalEventListener(
|
|
|
5967
6068
|
event.tags = { ...event.tags, replayId: replay.getSessionId() };
|
|
5968
6069
|
}
|
|
5969
6070
|
|
|
5970
|
-
// In cases where a custom client is used that does not support the new hooks (yet),
|
|
5971
|
-
// we manually call this hook method here
|
|
5972
|
-
if (afterSendHandler) {
|
|
5973
|
-
// Pretend the error had a 200 response so we always capture it
|
|
5974
|
-
afterSendHandler(event, { statusCode: 200 });
|
|
5975
|
-
}
|
|
5976
|
-
|
|
5977
6071
|
return event;
|
|
5978
6072
|
},
|
|
5979
6073
|
{ id: 'Replay' },
|
|
@@ -6090,97 +6184,14 @@ function addNetworkBreadcrumb(
|
|
|
6090
6184
|
});
|
|
6091
6185
|
}
|
|
6092
6186
|
|
|
6093
|
-
/** only exported for tests */
|
|
6094
|
-
function handleFetch(handlerData) {
|
|
6095
|
-
const { startTimestamp, endTimestamp, fetchData, response } = handlerData;
|
|
6096
|
-
|
|
6097
|
-
if (!endTimestamp) {
|
|
6098
|
-
return null;
|
|
6099
|
-
}
|
|
6100
|
-
|
|
6101
|
-
// This is only used as a fallback, so we know the body sizes are never set here
|
|
6102
|
-
const { method, url } = fetchData;
|
|
6103
|
-
|
|
6104
|
-
return {
|
|
6105
|
-
type: 'resource.fetch',
|
|
6106
|
-
start: startTimestamp / 1000,
|
|
6107
|
-
end: endTimestamp / 1000,
|
|
6108
|
-
name: url,
|
|
6109
|
-
data: {
|
|
6110
|
-
method,
|
|
6111
|
-
statusCode: response ? (response ).status : undefined,
|
|
6112
|
-
},
|
|
6113
|
-
};
|
|
6114
|
-
}
|
|
6115
|
-
|
|
6116
|
-
/**
|
|
6117
|
-
* Returns a listener to be added to `addFetchInstrumentationHandler(listener)`.
|
|
6118
|
-
*/
|
|
6119
|
-
function handleFetchSpanListener(replay) {
|
|
6120
|
-
return (handlerData) => {
|
|
6121
|
-
if (!replay.isEnabled()) {
|
|
6122
|
-
return;
|
|
6123
|
-
}
|
|
6124
|
-
|
|
6125
|
-
const result = handleFetch(handlerData);
|
|
6126
|
-
|
|
6127
|
-
addNetworkBreadcrumb(replay, result);
|
|
6128
|
-
};
|
|
6129
|
-
}
|
|
6130
|
-
|
|
6131
|
-
/** only exported for tests */
|
|
6132
|
-
function handleXhr(handlerData) {
|
|
6133
|
-
const { startTimestamp, endTimestamp, xhr } = handlerData;
|
|
6134
|
-
|
|
6135
|
-
const sentryXhrData = xhr[SENTRY_XHR_DATA_KEY];
|
|
6136
|
-
|
|
6137
|
-
if (!startTimestamp || !endTimestamp || !sentryXhrData) {
|
|
6138
|
-
return null;
|
|
6139
|
-
}
|
|
6140
|
-
|
|
6141
|
-
// This is only used as a fallback, so we know the body sizes are never set here
|
|
6142
|
-
const { method, url, status_code: statusCode } = sentryXhrData;
|
|
6143
|
-
|
|
6144
|
-
if (url === undefined) {
|
|
6145
|
-
return null;
|
|
6146
|
-
}
|
|
6147
|
-
|
|
6148
|
-
return {
|
|
6149
|
-
type: 'resource.xhr',
|
|
6150
|
-
name: url,
|
|
6151
|
-
start: startTimestamp / 1000,
|
|
6152
|
-
end: endTimestamp / 1000,
|
|
6153
|
-
data: {
|
|
6154
|
-
method,
|
|
6155
|
-
statusCode,
|
|
6156
|
-
},
|
|
6157
|
-
};
|
|
6158
|
-
}
|
|
6159
|
-
|
|
6160
|
-
/**
|
|
6161
|
-
* Returns a listener to be added to `addXhrInstrumentationHandler(listener)`.
|
|
6162
|
-
*/
|
|
6163
|
-
function handleXhrSpanListener(replay) {
|
|
6164
|
-
return (handlerData) => {
|
|
6165
|
-
if (!replay.isEnabled()) {
|
|
6166
|
-
return;
|
|
6167
|
-
}
|
|
6168
|
-
|
|
6169
|
-
const result = handleXhr(handlerData);
|
|
6170
|
-
|
|
6171
|
-
addNetworkBreadcrumb(replay, result);
|
|
6172
|
-
};
|
|
6173
|
-
}
|
|
6174
|
-
|
|
6175
6187
|
/** Get the size of a body. */
|
|
6176
|
-
function getBodySize(
|
|
6177
|
-
body,
|
|
6178
|
-
textEncoder,
|
|
6179
|
-
) {
|
|
6188
|
+
function getBodySize(body) {
|
|
6180
6189
|
if (!body) {
|
|
6181
6190
|
return undefined;
|
|
6182
6191
|
}
|
|
6183
6192
|
|
|
6193
|
+
const textEncoder = new TextEncoder();
|
|
6194
|
+
|
|
6184
6195
|
try {
|
|
6185
6196
|
if (typeof body === 'string') {
|
|
6186
6197
|
return textEncoder.encode(body).length;
|
|
@@ -6480,12 +6491,11 @@ async function captureFetchBreadcrumbToReplay(
|
|
|
6480
6491
|
function enrichFetchBreadcrumb(
|
|
6481
6492
|
breadcrumb,
|
|
6482
6493
|
hint,
|
|
6483
|
-
options,
|
|
6484
6494
|
) {
|
|
6485
6495
|
const { input, response } = hint;
|
|
6486
6496
|
|
|
6487
6497
|
const body = input ? _getFetchRequestArgBody(input) : undefined;
|
|
6488
|
-
const reqSize = getBodySize(body
|
|
6498
|
+
const reqSize = getBodySize(body);
|
|
6489
6499
|
|
|
6490
6500
|
const resSize = response ? parseContentLengthHeader(response.headers.get('content-length')) : undefined;
|
|
6491
6501
|
|
|
@@ -6500,9 +6510,7 @@ function enrichFetchBreadcrumb(
|
|
|
6500
6510
|
async function _prepareFetchData(
|
|
6501
6511
|
breadcrumb,
|
|
6502
6512
|
hint,
|
|
6503
|
-
options
|
|
6504
|
-
|
|
6505
|
-
,
|
|
6513
|
+
options,
|
|
6506
6514
|
) {
|
|
6507
6515
|
const now = Date.now();
|
|
6508
6516
|
const { startTimestamp = now, endTimestamp = now } = hint;
|
|
@@ -6562,11 +6570,8 @@ async function _getResponseInfo(
|
|
|
6562
6570
|
captureDetails,
|
|
6563
6571
|
{
|
|
6564
6572
|
networkCaptureBodies,
|
|
6565
|
-
textEncoder,
|
|
6566
6573
|
networkResponseHeaders,
|
|
6567
|
-
}
|
|
6568
|
-
|
|
6569
|
-
,
|
|
6574
|
+
},
|
|
6570
6575
|
response,
|
|
6571
6576
|
responseBodySize,
|
|
6572
6577
|
) {
|
|
@@ -6583,7 +6588,7 @@ async function _getResponseInfo(
|
|
|
6583
6588
|
const [bodyText, warning] = await _parseFetchResponseBody(response);
|
|
6584
6589
|
const result = getResponseData(bodyText, {
|
|
6585
6590
|
networkCaptureBodies,
|
|
6586
|
-
|
|
6591
|
+
|
|
6587
6592
|
responseBodySize,
|
|
6588
6593
|
captureDetails,
|
|
6589
6594
|
headers,
|
|
@@ -6600,7 +6605,6 @@ function getResponseData(
|
|
|
6600
6605
|
bodyText,
|
|
6601
6606
|
{
|
|
6602
6607
|
networkCaptureBodies,
|
|
6603
|
-
textEncoder,
|
|
6604
6608
|
responseBodySize,
|
|
6605
6609
|
captureDetails,
|
|
6606
6610
|
headers,
|
|
@@ -6610,9 +6614,7 @@ function getResponseData(
|
|
|
6610
6614
|
) {
|
|
6611
6615
|
try {
|
|
6612
6616
|
const size =
|
|
6613
|
-
bodyText && bodyText.length && responseBodySize === undefined
|
|
6614
|
-
? getBodySize(bodyText, textEncoder)
|
|
6615
|
-
: responseBodySize;
|
|
6617
|
+
bodyText && bodyText.length && responseBodySize === undefined ? getBodySize(bodyText) : responseBodySize;
|
|
6616
6618
|
|
|
6617
6619
|
if (!captureDetails) {
|
|
6618
6620
|
return buildSkippedNetworkRequestOrResponse(size);
|
|
@@ -6767,7 +6769,6 @@ async function captureXhrBreadcrumbToReplay(
|
|
|
6767
6769
|
function enrichXhrBreadcrumb(
|
|
6768
6770
|
breadcrumb,
|
|
6769
6771
|
hint,
|
|
6770
|
-
options,
|
|
6771
6772
|
) {
|
|
6772
6773
|
const { xhr, input } = hint;
|
|
6773
6774
|
|
|
@@ -6775,10 +6776,10 @@ function enrichXhrBreadcrumb(
|
|
|
6775
6776
|
return;
|
|
6776
6777
|
}
|
|
6777
6778
|
|
|
6778
|
-
const reqSize = getBodySize(input
|
|
6779
|
+
const reqSize = getBodySize(input);
|
|
6779
6780
|
const resSize = xhr.getResponseHeader('content-length')
|
|
6780
6781
|
? parseContentLengthHeader(xhr.getResponseHeader('content-length'))
|
|
6781
|
-
: _getBodySize(xhr.response, xhr.responseType
|
|
6782
|
+
: _getBodySize(xhr.response, xhr.responseType);
|
|
6782
6783
|
|
|
6783
6784
|
if (reqSize !== undefined) {
|
|
6784
6785
|
breadcrumb.data.request_body_size = reqSize;
|
|
@@ -6925,11 +6926,10 @@ function _parseXhrResponse(
|
|
|
6925
6926
|
function _getBodySize(
|
|
6926
6927
|
body,
|
|
6927
6928
|
responseType,
|
|
6928
|
-
textEncoder,
|
|
6929
6929
|
) {
|
|
6930
6930
|
try {
|
|
6931
6931
|
const bodyStr = responseType === 'json' && body && typeof body === 'object' ? JSON.stringify(body) : body;
|
|
6932
|
-
return getBodySize(bodyStr
|
|
6932
|
+
return getBodySize(bodyStr);
|
|
6933
6933
|
} catch (e3) {
|
|
6934
6934
|
return undefined;
|
|
6935
6935
|
}
|
|
@@ -6945,8 +6945,6 @@ function handleNetworkBreadcrumbs(replay) {
|
|
|
6945
6945
|
const client = getClient();
|
|
6946
6946
|
|
|
6947
6947
|
try {
|
|
6948
|
-
const textEncoder = new TextEncoder();
|
|
6949
|
-
|
|
6950
6948
|
const {
|
|
6951
6949
|
networkDetailAllowUrls,
|
|
6952
6950
|
networkDetailDenyUrls,
|
|
@@ -6957,7 +6955,6 @@ function handleNetworkBreadcrumbs(replay) {
|
|
|
6957
6955
|
|
|
6958
6956
|
const options = {
|
|
6959
6957
|
replay,
|
|
6960
|
-
textEncoder,
|
|
6961
6958
|
networkDetailAllowUrls,
|
|
6962
6959
|
networkDetailDenyUrls,
|
|
6963
6960
|
networkCaptureBodies,
|
|
@@ -6965,12 +6962,8 @@ function handleNetworkBreadcrumbs(replay) {
|
|
|
6965
6962
|
networkResponseHeaders,
|
|
6966
6963
|
};
|
|
6967
6964
|
|
|
6968
|
-
if (client
|
|
6965
|
+
if (client) {
|
|
6969
6966
|
client.on('beforeAddBreadcrumb', (breadcrumb, hint) => beforeAddNetworkBreadcrumb(options, breadcrumb, hint));
|
|
6970
|
-
} else {
|
|
6971
|
-
// Fallback behavior
|
|
6972
|
-
addFetchInstrumentationHandler(handleFetchSpanListener(replay));
|
|
6973
|
-
addXhrInstrumentationHandler(handleXhrSpanListener(replay));
|
|
6974
6967
|
}
|
|
6975
6968
|
} catch (e2) {
|
|
6976
6969
|
// Do nothing
|
|
@@ -6992,7 +6985,7 @@ function beforeAddNetworkBreadcrumb(
|
|
|
6992
6985
|
// This has to be sync, as we need to ensure the breadcrumb is enriched in the same tick
|
|
6993
6986
|
// Because the hook runs synchronously, and the breadcrumb is afterwards passed on
|
|
6994
6987
|
// So any async mutations to it will not be reflected in the final breadcrumb
|
|
6995
|
-
enrichXhrBreadcrumb(breadcrumb, hint
|
|
6988
|
+
enrichXhrBreadcrumb(breadcrumb, hint);
|
|
6996
6989
|
|
|
6997
6990
|
// This call should not reject
|
|
6998
6991
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
@@ -7003,7 +6996,7 @@ function beforeAddNetworkBreadcrumb(
|
|
|
7003
6996
|
// This has to be sync, as we need to ensure the breadcrumb is enriched in the same tick
|
|
7004
6997
|
// Because the hook runs synchronously, and the breadcrumb is afterwards passed on
|
|
7005
6998
|
// So any async mutations to it will not be reflected in the final breadcrumb
|
|
7006
|
-
enrichFetchBreadcrumb(breadcrumb, hint
|
|
6999
|
+
enrichFetchBreadcrumb(breadcrumb, hint);
|
|
7007
7000
|
|
|
7008
7001
|
// This call should not reject
|
|
7009
7002
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
@@ -7030,138 +7023,25 @@ function _isFetchHint(hint) {
|
|
|
7030
7023
|
return hint && hint.response;
|
|
7031
7024
|
}
|
|
7032
7025
|
|
|
7033
|
-
let _LAST_BREADCRUMB = null;
|
|
7034
|
-
|
|
7035
|
-
function isBreadcrumbWithCategory(breadcrumb) {
|
|
7036
|
-
return !!breadcrumb.category;
|
|
7037
|
-
}
|
|
7038
|
-
|
|
7039
|
-
const handleScopeListener =
|
|
7040
|
-
(replay) =>
|
|
7041
|
-
(scope) => {
|
|
7042
|
-
if (!replay.isEnabled()) {
|
|
7043
|
-
return;
|
|
7044
|
-
}
|
|
7045
|
-
|
|
7046
|
-
const result = handleScope(scope);
|
|
7047
|
-
|
|
7048
|
-
if (!result) {
|
|
7049
|
-
return;
|
|
7050
|
-
}
|
|
7051
|
-
|
|
7052
|
-
addBreadcrumbEvent(replay, result);
|
|
7053
|
-
};
|
|
7054
|
-
|
|
7055
|
-
/**
|
|
7056
|
-
* An event handler to handle scope changes.
|
|
7057
|
-
*/
|
|
7058
|
-
function handleScope(scope) {
|
|
7059
|
-
// TODO (v8): Remove this guard. This was put in place because we introduced
|
|
7060
|
-
// Scope.getLastBreadcrumb mid-v7 which caused incompatibilities with older SDKs.
|
|
7061
|
-
// For now, we'll just return null if the method doesn't exist but we should eventually
|
|
7062
|
-
// get rid of this guard.
|
|
7063
|
-
const newBreadcrumb = scope.getLastBreadcrumb && scope.getLastBreadcrumb();
|
|
7064
|
-
|
|
7065
|
-
// Listener can be called when breadcrumbs have not changed, so we store the
|
|
7066
|
-
// reference to the last crumb and only return a crumb if it has changed
|
|
7067
|
-
if (_LAST_BREADCRUMB === newBreadcrumb || !newBreadcrumb) {
|
|
7068
|
-
return null;
|
|
7069
|
-
}
|
|
7070
|
-
|
|
7071
|
-
_LAST_BREADCRUMB = newBreadcrumb;
|
|
7072
|
-
|
|
7073
|
-
if (
|
|
7074
|
-
!isBreadcrumbWithCategory(newBreadcrumb) ||
|
|
7075
|
-
['fetch', 'xhr', 'sentry.event', 'sentry.transaction'].includes(newBreadcrumb.category) ||
|
|
7076
|
-
newBreadcrumb.category.startsWith('ui.')
|
|
7077
|
-
) {
|
|
7078
|
-
return null;
|
|
7079
|
-
}
|
|
7080
|
-
|
|
7081
|
-
if (newBreadcrumb.category === 'console') {
|
|
7082
|
-
return normalizeConsoleBreadcrumb(newBreadcrumb);
|
|
7083
|
-
}
|
|
7084
|
-
|
|
7085
|
-
return createBreadcrumb(newBreadcrumb);
|
|
7086
|
-
}
|
|
7087
|
-
|
|
7088
|
-
/** exported for tests only */
|
|
7089
|
-
function normalizeConsoleBreadcrumb(
|
|
7090
|
-
breadcrumb,
|
|
7091
|
-
) {
|
|
7092
|
-
const args = breadcrumb.data && breadcrumb.data.arguments;
|
|
7093
|
-
|
|
7094
|
-
if (!Array.isArray(args) || args.length === 0) {
|
|
7095
|
-
return createBreadcrumb(breadcrumb);
|
|
7096
|
-
}
|
|
7097
|
-
|
|
7098
|
-
let isTruncated = false;
|
|
7099
|
-
|
|
7100
|
-
// Avoid giant args captures
|
|
7101
|
-
const normalizedArgs = args.map(arg => {
|
|
7102
|
-
if (!arg) {
|
|
7103
|
-
return arg;
|
|
7104
|
-
}
|
|
7105
|
-
if (typeof arg === 'string') {
|
|
7106
|
-
if (arg.length > CONSOLE_ARG_MAX_SIZE) {
|
|
7107
|
-
isTruncated = true;
|
|
7108
|
-
return `${arg.slice(0, CONSOLE_ARG_MAX_SIZE)}…`;
|
|
7109
|
-
}
|
|
7110
|
-
|
|
7111
|
-
return arg;
|
|
7112
|
-
}
|
|
7113
|
-
if (typeof arg === 'object') {
|
|
7114
|
-
try {
|
|
7115
|
-
const normalizedArg = normalize(arg, 7);
|
|
7116
|
-
const stringified = JSON.stringify(normalizedArg);
|
|
7117
|
-
if (stringified.length > CONSOLE_ARG_MAX_SIZE) {
|
|
7118
|
-
isTruncated = true;
|
|
7119
|
-
// We use the pretty printed JSON string here as a base
|
|
7120
|
-
return `${JSON.stringify(normalizedArg, null, 2).slice(0, CONSOLE_ARG_MAX_SIZE)}…`;
|
|
7121
|
-
}
|
|
7122
|
-
return normalizedArg;
|
|
7123
|
-
} catch (e) {
|
|
7124
|
-
// fall back to default
|
|
7125
|
-
}
|
|
7126
|
-
}
|
|
7127
|
-
|
|
7128
|
-
return arg;
|
|
7129
|
-
});
|
|
7130
|
-
|
|
7131
|
-
return createBreadcrumb({
|
|
7132
|
-
...breadcrumb,
|
|
7133
|
-
data: {
|
|
7134
|
-
...breadcrumb.data,
|
|
7135
|
-
arguments: normalizedArgs,
|
|
7136
|
-
...(isTruncated ? { _meta: { warnings: ['CONSOLE_ARG_TRUNCATED'] } } : {}),
|
|
7137
|
-
},
|
|
7138
|
-
});
|
|
7139
|
-
}
|
|
7140
|
-
|
|
7141
7026
|
/**
|
|
7142
7027
|
* Add global listeners that cannot be removed.
|
|
7143
7028
|
*/
|
|
7144
7029
|
function addGlobalListeners(replay) {
|
|
7145
7030
|
// Listeners from core SDK //
|
|
7146
|
-
const scope = getCurrentScope();
|
|
7147
7031
|
const client = getClient();
|
|
7148
7032
|
|
|
7149
|
-
scope.addScopeListener(handleScopeListener(replay));
|
|
7150
7033
|
addClickKeypressInstrumentationHandler(handleDomListener(replay));
|
|
7151
7034
|
addHistoryInstrumentationHandler(handleHistorySpanListener(replay));
|
|
7035
|
+
handleBreadcrumbs(replay);
|
|
7152
7036
|
handleNetworkBreadcrumbs(replay);
|
|
7153
7037
|
|
|
7154
7038
|
// Tag all (non replay) events that get sent to Sentry with the current
|
|
7155
7039
|
// replay ID so that we can reference them later in the UI
|
|
7156
|
-
const eventProcessor = handleGlobalEventListener(replay
|
|
7157
|
-
|
|
7158
|
-
client.addEventProcessor(eventProcessor);
|
|
7159
|
-
} else {
|
|
7160
|
-
addEventProcessor(eventProcessor);
|
|
7161
|
-
}
|
|
7040
|
+
const eventProcessor = handleGlobalEventListener(replay);
|
|
7041
|
+
addEventProcessor(eventProcessor);
|
|
7162
7042
|
|
|
7163
7043
|
// If a custom client has no hooks yet, we continue to use the "old" implementation
|
|
7164
|
-
if (
|
|
7044
|
+
if (client) {
|
|
7165
7045
|
client.on('beforeSendEvent', handleBeforeSendEvent(replay));
|
|
7166
7046
|
client.on('afterSendEvent', handleAfterSendEvent(replay));
|
|
7167
7047
|
client.on('createDsc', (dsc) => {
|
|
@@ -7199,11 +7079,6 @@ function addGlobalListeners(replay) {
|
|
|
7199
7079
|
}
|
|
7200
7080
|
}
|
|
7201
7081
|
|
|
7202
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7203
|
-
function hasHooks(client) {
|
|
7204
|
-
return !!(client && client.on);
|
|
7205
|
-
}
|
|
7206
|
-
|
|
7207
7082
|
/**
|
|
7208
7083
|
* Create a "span" for the total amount of memory being used by JS objects
|
|
7209
7084
|
* (including v8 internal objects).
|
|
@@ -7525,9 +7400,7 @@ async function prepareReplayEvent({
|
|
|
7525
7400
|
|
|
7526
7401
|
const eventHint = { event_id, integrations };
|
|
7527
7402
|
|
|
7528
|
-
|
|
7529
|
-
client.emit('preprocessEvent', event, eventHint);
|
|
7530
|
-
}
|
|
7403
|
+
client.emit('preprocessEvent', event, eventHint);
|
|
7531
7404
|
|
|
7532
7405
|
const preparedEvent = (await prepareEvent(
|
|
7533
7406
|
client.getOptions(),
|
|
@@ -7549,7 +7422,7 @@ async function prepareReplayEvent({
|
|
|
7549
7422
|
preparedEvent.platform = preparedEvent.platform || 'javascript';
|
|
7550
7423
|
|
|
7551
7424
|
// extract the SDK name because `client._prepareEvent` doesn't add it to the event
|
|
7552
|
-
const metadata = client.getSdkMetadata
|
|
7425
|
+
const metadata = client.getSdkMetadata();
|
|
7553
7426
|
const { name, version } = (metadata && metadata.sdk) || {};
|
|
7554
7427
|
|
|
7555
7428
|
preparedEvent.sdk = {
|
|
@@ -9533,12 +9406,9 @@ function _getMergedNetworkHeaders(headers) {
|
|
|
9533
9406
|
/**
|
|
9534
9407
|
* This is a small utility to get a type-safe instance of the Replay integration.
|
|
9535
9408
|
*/
|
|
9536
|
-
// eslint-disable-next-line deprecation/deprecation
|
|
9537
9409
|
function getReplay() {
|
|
9538
9410
|
const client = getClient();
|
|
9539
|
-
return (
|
|
9540
|
-
client && client.getIntegrationByName && client.getIntegrationByName('Replay')
|
|
9541
|
-
);
|
|
9411
|
+
return client && client.getIntegrationByName('Replay');
|
|
9542
9412
|
}
|
|
9543
9413
|
|
|
9544
9414
|
export { Replay, getReplay, replayIntegration };
|