noibu-react-native 0.0.1 → 0.0.2

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.
@@ -1,295 +1,142 @@
1
1
  import { replace } from '../utils/object.js';
2
- import 'stacktrace-parser';
3
- import 'react-native-device-info';
4
- import { ERROR_EVENT_ERROR_TYPE, EVENT_TARGETS, CONSOLE_FUNCTION_OVERRIDES, WRAPPED_EXCEPTION_ERROR_TYPE, ERROR_LOG_EVENT_ERROR_TYPE } from '../constants.js';
2
+ import { isStackTrace } from '../utils/function.js';
3
+ import { ERROR_EVENT_ERROR_TYPE, CONSOLE_FUNCTION_OVERRIDES, ERROR_LOG_EVENT_ERROR_TYPE } from '../constants.js';
5
4
  import { saveErrorToPagevisit } from '../pageVisit/pageVisitEventError/pageVisitEventError.js';
6
- import 'react-native-uuid';
7
5
 
6
+ /* eslint-disable @typescript-eslint/ban-types,prefer-arrow-callback */
8
7
  /** @module ErrorMonitor */
9
-
10
- /**
11
- * will make sure that we ignore the next error caught by the error event listener
12
- * ignoreError is used to not store errors that were generated by noibu wrapped
13
- * code twice (once by wrapped code, once by error event listener).
14
- */
15
- function ignoreNextError() {
16
-
17
- // this works because setTimeout without a delay fires
18
- // as the immidiate next event in the event loop. Which should
19
- // be right after the error that we throw before callign this error
20
- setTimeout(() => {
21
- });
22
- }
23
-
24
8
  /**
25
- * wraps a provided function into a function that try and catches
26
- * the original function, doing so allows us to catch errors
27
- * functionToWrap: function to be wrapped
28
- * @param {} functionToWrap
9
+ * transform a log into an error since React hides component errors
10
+ * tps://reactjs.org/docs/error-boundaries.html
11
+ * @param {Error|any} errorLog
12
+ * @returns {boolean} true on success
29
13
  */
30
- function wrap(functionToWrap) {
31
- if (typeof functionToWrap !== 'function') {
32
- return functionToWrap;
33
- }
34
-
35
- try {
36
- // the function was wrapped already
37
- if (functionToWrap.__noibu__) {
38
- return functionToWrap;
39
- }
40
-
41
- // trying to wrap a function that was already wrapped in the past,
42
- // return the wrapped value
43
- if (functionToWrap.__noibu_wrapped__) {
44
- return functionToWrap.__noibu_wrapped__;
45
- }
46
- } catch (err) {
47
- // silently failling
48
- return functionToWrap;
49
- }
50
- /**
51
- * wrapper for most prototypes we know can generate errors
52
- * @param {} ...args
53
- */
54
- const nbuWrapper = function (...args) {
55
- // Trying to call the function in a wrapped try and catch
56
- // this will generate an error in the console if there is one.
57
- try {
58
- // Recursively wrap arguments in case that some are
59
- // functions
60
- const wrappedArguments = Array.prototype.slice
61
- .call(args)
62
- .map(arg => wrap(arg));
63
-
64
- // checking if the function is served through the handleEvent property
65
- // for compatibility reasons
66
- if (functionToWrap.handleEvent) {
67
- return functionToWrap.handleEvent.apply(this, wrappedArguments);
68
- }
69
- return functionToWrap.apply(this, wrappedArguments);
70
- // user land
71
- } catch (exception) {
72
- // we need to ignore this error during the onerror otherwise
73
- // we catch it 2x
74
- saveErrorToPagevisit(WRAPPED_EXCEPTION_ERROR_TYPE, {
75
- error: exception,
76
- });
77
- ignoreNextError();
78
- throw exception;
14
+ function processErrorLog(errorLog) {
15
+ // handle empty arguments
16
+ if (!errorLog) {
17
+ return false;
79
18
  }
80
- };
81
-
82
- try {
83
- // eslint-disable-next-line no-restricted-syntax
84
- for (const property in functionToWrap) {
85
- if (Object.prototype.hasOwnProperty.call(functionToWrap, property)) {
86
- nbuWrapper[property] = functionToWrap[property];
87
- }
19
+ const { message, stack } = errorLog;
20
+ // for now, we only process error logs if they are a way to describe an error
21
+ if (!stack || !message) {
22
+ return false;
88
23
  }
89
- } catch (err) {
90
- // silently failling
91
- }
92
-
93
- nbuWrapper.prototype = functionToWrap.prototype || {};
94
-
95
- Object.defineProperty(functionToWrap, '__noibu_wrapped__', {
96
- enumerable: false,
97
- value: nbuWrapper,
98
- });
99
-
100
- // Signal that this function has been wrapped/filled already
101
- // for both debugging and to prevent it to being wrapped/filled twice
102
- Object.defineProperties(nbuWrapper, {
103
- __noibu__: {
104
- enumerable: false,
105
- value: true,
106
- },
107
- __noibu_original__: {
108
- enumerable: false,
109
- value: functionToWrap,
110
- },
111
- });
112
-
113
- // Restore original function name (not all browsers allow that)
114
- try {
115
- const descriptor = Object.getOwnPropertyDescriptor(nbuWrapper, 'name');
116
- if (descriptor.configurable) {
117
- Object.defineProperty(nbuWrapper, 'name', {
118
- // eslint-disable-next-line require-jsdoc
119
- get() {
120
- return functionToWrap.name;
121
- },
122
- });
123
- }
124
- } catch (err) {
125
- return functionToWrap;
126
- }
127
-
128
- return nbuWrapper;
24
+ saveErrorToPagevisit(ERROR_LOG_EVENT_ERROR_TYPE, { message, stack });
25
+ return true;
129
26
  }
130
-
131
27
  /**
132
- * transform a log into an error since React hides component errors
133
- * tps://reactjs.org/docs/error-boundaries.html
134
- * @param {} errorLog
28
+ * Constructs error objects based on console args.
29
+ * Relies on isStackTrace() to determine if arg is a stack trace, otherwise the arg must be a message.
30
+ *
31
+ * If there are multiple stack traces or the number of error messages is not equal to one,
32
+ * it maps the stack traces to objects with their respective first lines as messages.
33
+ * Otherwise, if there is exactly one stack trace and one error message,
34
+ * it constructs an array with a single object containing the first stack trace and the first error message.
35
+ * @param {Array<string>} args
135
36
  */
136
- function processErrorLog(errorLog) {
137
- // handle empty arguments
138
- if (!errorLog) {
139
- return;
140
- }
141
- const { message, stack } = errorLog;
142
- // for now we only process error logs if they are a way to describe an error
143
- if (!stack || !message) {
144
- return;
145
- }
146
-
147
- saveErrorToPagevisit(ERROR_LOG_EVENT_ERROR_TYPE, { message, stack });
37
+ function constructErrors(args) {
38
+ if (args.length === 0) {
39
+ return [];
40
+ }
41
+ if (args.length === 2) {
42
+ if (isStackTrace(args[0])) {
43
+ return [{ stack: args[0], message: args[1] }];
44
+ }
45
+ if (isStackTrace(args[1])) {
46
+ return [{ stack: args[1], message: args[0] }];
47
+ }
48
+ return [];
49
+ }
50
+ const stacks = [];
51
+ const messages = [];
52
+ args.forEach(sm => {
53
+ if (isStackTrace(sm)) {
54
+ stacks.push(sm);
55
+ const lines = sm.split('\n');
56
+ if (isStackTrace(lines[0])) {
57
+ messages.push('_');
58
+ }
59
+ else {
60
+ // we can use 1st line of stack trace as a message
61
+ messages.push(lines[0]);
62
+ }
63
+ }
64
+ });
65
+ return stacks.map((stack, i) => ({ stack, message: messages[i] }));
148
66
  }
149
-
150
67
  /** iterates arguments to try to extract errors from them
151
- * @param {} argsFromErrorLog
68
+ * @param {Array<string | Error>} argsFromErrorLog
152
69
  */
153
70
  function processErrorLogArguments(argsFromErrorLog) {
154
- // we may receive multiple arguments
155
- argsFromErrorLog.forEach(arg => {
156
- // ensure arg exists before attempting processing
157
- if (!arg) {
158
- return;
159
- }
160
- // if we pass an array of elements in the console, we want to go through that
161
- // away and make sure we are extracting the error object. We dont do nested arrays.
162
- if (Array.isArray(arg)) {
163
- arg.forEach(nestedArg => {
164
- processErrorLog(nestedArg);
165
- });
166
- return;
167
- }
168
- processErrorLog(arg);
169
- });
71
+ // tracks if arguments were processed at least once successfully, and if not, tries to reconstruct an Error
72
+ const collectedArgs = [];
73
+ // we may receive multiple arguments
74
+ argsFromErrorLog.forEach(arg => {
75
+ // ensure arg exists before attempting processing
76
+ if (!arg) {
77
+ return;
78
+ }
79
+ // if we pass an array of elements in the console, we want to go through that
80
+ // away and make sure we are extracting the error object. We don't do nested arrays.
81
+ if (Array.isArray(arg)) {
82
+ collectedArgs.push(...arg);
83
+ return;
84
+ }
85
+ collectedArgs.push(arg);
86
+ });
87
+ const argsToBeReconstructedIntoErrors = collectedArgs.filter(arg => !processErrorLog(arg));
88
+ // if previous process calls return nothing,
89
+ // try to reconstruct error from the args
90
+ constructErrors(argsToBeReconstructedIntoErrors).forEach(processErrorLog);
170
91
  }
171
-
172
92
  /**
173
93
  * wraps and replaces the addEventListener property
174
94
  * of event targets to try and catch errors
175
95
  * eventTargetString: event target name
176
96
  */
177
97
  function configureEventListeners() {
178
- EVENT_TARGETS.forEach(eventTargetString => {
179
- const eventTarget = window[eventTargetString];
180
- // The event target needs to have a prototype and have the
181
- // addEventListener function
182
- const proto = eventTarget && eventTarget.prototype;
183
- if (
184
- !proto ||
185
- !proto.hasOwnProperty ||
186
- // eslint-disable-next-line no-prototype-builtins
187
- !proto.hasOwnProperty('addEventListener')
188
- ) {
189
- return;
190
- }
191
- replace(
192
- proto,
193
- 'addEventListener',
194
- originalFunction =>
195
- // We set nbuWrapper to the handler function so if this returns an error
196
- // the trace message will start with nbuWrapper which would allow us to
197
- // detect that this is a wrapped function and not a NoibuJS error
198
- function nbuWrapper(eventName, handler, capture) {
199
- // testPassive is done by passing a null handler, so we code
200
- // against that
201
- if (!handler) {
202
- return originalFunction.call(this, eventName, handler, capture);
203
- }
204
- let wrappedHandler;
205
- // Checking if handleEvent is explicitely
206
- // passed for compatibility reason
207
- if (handler.handleEvent) {
208
- const wrappedHandleEvent = wrap(handler.handleEvent.bind(handler));
209
- // in some case the handler is an object that contains much more than just the
210
- // the single handle event property, in such cases we need to make sure we are not
211
- // overwritting any other critical functionality by wrapping the event handler
212
- wrappedHandler = handler;
213
- wrappedHandler.handleEvent = wrappedHandleEvent;
214
- } else {
215
- wrappedHandler = wrap(handler);
216
- }
217
-
218
- return originalFunction.call(
219
- this,
220
- eventName,
221
- wrappedHandler,
222
- capture,
223
- );
224
- },
225
- );
226
-
227
- // replacing the removeEventListener function as well to wrap the listener
228
- replace(
229
- proto,
230
- 'removeEventListener',
231
- originalFunction =>
232
- // We set nbuWrapper to the handler function so if this returns an error
233
- // the trace message will start with nbuWrapper which would allow us to
234
- // detect that this is a wrapped function and not a NoibuJS error
235
- function nbuWrapper(eventName, handler, options) {
236
- let callback = handler;
237
- try {
238
- callback = callback && (callback.__noibu_wrapped__ || callback);
239
- } catch (e) {
240
- // fail silently
241
- }
242
- return originalFunction.call(this, eventName, callback, options);
243
- },
244
- );
245
- });
246
-
247
- // we wrap all logging to catch any potential errors passed in logs
248
- CONSOLE_FUNCTION_OVERRIDES.forEach(consoleFunction => {
249
- if (!window.console || !window.console[consoleFunction]) {
250
- return;
251
- }
252
- replace(
253
- window.console,
254
- consoleFunction,
255
- originalFunction =>
256
- // We set nbuWrapper to the handler function so if this returns an error
257
- // the trace message will start with nbuWrapper which would allow us to
258
- // detect that this is a wrapped function and not a NoibuJS error
259
- function nbuWrapper() {
260
- // ignoring this linting error since we don't want
261
- // potentially overide the actual functioning of console.error
262
- // eslint-disable-next-line prefer-rest-params
263
- originalFunction.call(window.console, ...arguments);
264
- // converting the arguments to an array so that we do not nest argument objects
265
- // eslint-disable-next-line prefer-rest-params
266
- processErrorLogArguments(Array.from(arguments));
267
- },
268
- );
269
- });
98
+ // we wrap all logging to catch any potential errors passed in logs
99
+ CONSOLE_FUNCTION_OVERRIDES.forEach(consoleFunction => {
100
+ if (!window.console || !window.console[consoleFunction]) {
101
+ return;
102
+ }
103
+ replace(window.console, consoleFunction, function (originalFunction) {
104
+ // We set nbuWrapper to the handler function so if this returns an error
105
+ // the trace message will start with nbuWrapper which would allow us to
106
+ // detect that this is a wrapped function and not a NoibuJS error
107
+ return function nbuWrapper() {
108
+ // ignoring this linting error since we don't want
109
+ // potentially overide the actual functioning of console.error
110
+ // eslint-disable-next-line prefer-rest-params
111
+ originalFunction.call(window.console, ...arguments);
112
+ // converting the arguments to an array so that we do not nest argument objects
113
+ // eslint-disable-next-line prefer-rest-params
114
+ processErrorLogArguments(Array.from(arguments));
115
+ };
116
+ });
117
+ });
270
118
  }
271
-
272
119
  /**
273
120
  * Monitors the errors happening on the window
274
121
  */
275
122
  function monitorErrors() {
276
- // wrapping all listeners as soon as possible after we set the above listener
277
- configureEventListeners();
278
- global.ErrorUtils.setGlobalHandler((error, isFatal) => {
279
- saveErrorToPagevisit(ERROR_EVENT_ERROR_TYPE, {
280
- error,
281
- });
282
- }, true);
283
- if (global.HermesInternal) {
284
- global.HermesInternal.enablePromiseRejectionTracker({
285
- allRejections: true,
286
- onUnhandled: (id, rejection = {}) => {
123
+ // wrapping all listeners as soon as possible after we set the above listener
124
+ configureEventListeners();
125
+ global.ErrorUtils.setGlobalHandler((error) => {
287
126
  saveErrorToPagevisit(ERROR_EVENT_ERROR_TYPE, {
288
- error: rejection,
127
+ error,
289
128
  });
290
- },
291
- });
292
- }
129
+ }, true);
130
+ if (global.HermesInternal) {
131
+ global.HermesInternal.enablePromiseRejectionTracker({
132
+ allRejections: true,
133
+ onUnhandled: (id, rejection = {}) => {
134
+ saveErrorToPagevisit(ERROR_EVENT_ERROR_TYPE, {
135
+ error: rejection,
136
+ });
137
+ },
138
+ });
139
+ }
293
140
  }
294
141
 
295
142
  export { monitorErrors, processErrorLogArguments };
@@ -85,7 +85,10 @@ class HTTPDataBundler {
85
85
  ];
86
86
  }
87
87
 
88
- /** gets the singleton instance */
88
+ /**
89
+ * gets the singleton instance
90
+ * @returns {HTTPDataBundler}
91
+ */
89
92
  static getInstance() {
90
93
  if (!this.instance) {
91
94
  this.instance = new HTTPDataBundler();
@@ -208,7 +211,7 @@ class HTTPDataBundler {
208
211
  return false;
209
212
  }
210
213
 
211
- let requestHostname; // has to be declared outside of `try`
214
+ let requestHostname; // has to be declared outside `try`
212
215
 
213
216
  // Use URL constructor to extract hostname
214
217
  try {
@@ -251,11 +254,10 @@ class HTTPDataBundler {
251
254
  * Builds an HTTP Data bundle
252
255
  * @param {} url
253
256
  * @param {} requestHeaders is a map of request headers
254
- * @param {} requestPayload
257
+ * @param {} rawRequestPayload
255
258
  * @param {} responseHeaders is a map of response headers
256
259
  * @param {} responsePayload
257
260
  * @param {} method
258
- * @param {} isError Response code is an error
259
261
  */
260
262
  bundleHTTPData(
261
263
  url,
@@ -264,9 +266,8 @@ class HTTPDataBundler {
264
266
  responseHeaders,
265
267
  responsePayload,
266
268
  method,
267
- isError,
268
269
  ) {
269
- if (!this.isValidRequest(url, method, isError)) return null;
270
+ if (!this.isValidRequest(url, method)) return null;
270
271
 
271
272
  // stringify payload if correct type and not too large
272
273
  let requestPayload = '';
@@ -320,15 +321,13 @@ class HTTPDataBundler {
320
321
  * de-duping the requests
321
322
  * @param {string} url
322
323
  * @param {string} method
323
- * @param {} isError Response code is an error
324
324
  * @returns boolean indicating whether the validation passed
325
325
  */
326
- isValidRequest(url, method, isError) {
326
+ isValidRequest(url, method) {
327
327
  if (!this.httpDataCollectionEnabled) return false;
328
328
  if (!method || typeof method !== 'string') {
329
329
  return false;
330
330
  }
331
- if (!isError) return false;
332
331
  // TODO: Check below disabled for beta. NOI-4253
333
332
  // only bundle and send once per request/method/response code combination
334
333
  // const urlWithoutParams = url.split('?')[0];
@@ -408,7 +407,7 @@ class HTTPDataBundler {
408
407
  * @returns the restricted payload
409
408
  */
410
409
  restrictPayload(payload, url) {
411
- // if no payload, too large, payload already dropped,
410
+ // if no payload, or too large, payload already dropped,
412
411
  // or payloads not allowed for this URL: nothing to do
413
412
  if (!payload || !this.shouldCollectPayloadForURL(url)) {
414
413
  return HTTP_BODY_NULL_STRING;
@@ -611,7 +610,7 @@ ${HTTPDataBundler.getInstance().contentLength(headers)}`;
611
610
  if (typeof dirtyBody !== 'string') return null;
612
611
  if (dirtyBody.length < 1) return dirtyBody;
613
612
 
614
- let cleanString = this.tryPaseObjectAndRemovePII(dirtyBody);
613
+ let cleanString = this.tryParseObjectAndRemovePII(dirtyBody);
615
614
  // Go through each of the PII matching patterns
616
615
  HTTP_PII_BLOCKING_PATTERNS.forEach(pattern => {
617
616
  // Replace all matches with the appropriate number of asterisks
@@ -630,7 +629,7 @@ ${HTTPDataBundler.getInstance().contentLength(headers)}`;
630
629
  * Returns original content if nothing was changes or error is thrown.
631
630
  * @param {String} content
632
631
  */
633
- tryPaseObjectAndRemovePII(content) {
632
+ tryParseObjectAndRemovePII(content) {
634
633
  const first = content[0];
635
634
  const isParsable = first === '{' || first === '[';
636
635
  if (!isParsable) {
@@ -42,7 +42,10 @@ class InputMonitor {
42
42
  this._setupUnloadHandler();
43
43
  }
44
44
 
45
- /** gets the instance of InputMonitor */
45
+ /**
46
+ * gets the instance of InputMonitor
47
+ * @returns {InputMonitor}
48
+ */
46
49
  static getInstance() {
47
50
  if (!this.instance) {
48
51
  this.instance = new InputMonitor();
@@ -1,11 +1,9 @@
1
- import { getProperGlobalUrl } from '../utils/function.js';
2
- import { InputMonitor } from './inputMonitor.js';
3
- import { URL_ATT_NAME, LOCATION_EVENT_TYPE } from '../constants.js';
1
+ import 'react-native-device-info';
2
+ import 'react-native-localize';
3
+ import 'react-native-uuid';
4
4
 
5
5
  /** @module LocationMonitor */
6
6
 
7
- let currentLocation = (window.location && window.location.href) || '';
8
-
9
7
  /**
10
8
  * will poll the url on a 1 second basis to see if it has changed
11
9
  * there is currently no alternative to getting an accurate url
@@ -13,17 +11,6 @@ let currentLocation = (window.location && window.location.href) || '';
13
11
  */
14
12
  function monitorLocation() {
15
13
  setInterval(() => {
16
- if (currentLocation !== ((window.location && window.location.href) || '')) {
17
- // updating the current url to be the new one
18
- currentLocation = (window.location && window.location.href) || '';
19
-
20
- const payload = {
21
- [URL_ATT_NAME]: getProperGlobalUrl(),
22
- };
23
-
24
- // storing the location change in the page visit queue
25
- InputMonitor.getInstance().addEvent(payload, LOCATION_EVENT_TYPE);
26
- }
27
14
  }, 1000);
28
15
  }
29
16
 
@@ -6,7 +6,10 @@ import { addSafeEventListener } from '../utils/eventlistener.js';
6
6
 
7
7
  /** Monitors the page events which we capture and later process */
8
8
  class PageMonitor {
9
- /** gets the singleton instance */
9
+ /**
10
+ * gets the singleton instance
11
+ * @returns {PageMonitor}
12
+ */
10
13
  static getInstance() {
11
14
  if (!this.instance) {
12
15
  this.instance = new PageMonitor();
@@ -2,12 +2,12 @@ import 'react-native/Libraries/Network/fetch';
2
2
  import { saveErrorToPagevisit } from '../pageVisit/pageVisitEventError/pageVisitEventError.js';
3
3
  import { PageVisitEventHTTP, isHttpCodeFailure } from '../pageVisit/pageVisitEventHTTP/pageVisitEventHTTP.js';
4
4
  import { propWriteableOrMadeWriteable, replace } from '../utils/object.js';
5
- import 'stacktrace-parser';
6
5
  import 'react-native-device-info';
6
+ import 'react-native-localize';
7
7
  import { PV_SEQ_ATT_NAME, XML_HTTP_REQUEST_ERROR_TYPE, GQL_ERROR_TYPE, SEVERITY_ERROR, SEVERITY_WARN, RESPONSE_ERROR_TYPE, HTTP_METHOD_ATT_NAME, HTTP_RESP_CODE_ATT_NAME, URL_ATT_NAME, HTTP_RESP_TIME_ATT_NAME, HTTP_RESP_LENGTH_ATT_NAME, FETCH_EXCEPTION_ERROR_TYPE } from '../constants.js';
8
+ import ClientConfig from '../api/clientConfig.js';
8
9
  import { addSafeEventListener } from '../utils/eventlistener.js';
9
10
  import { HTTPDataBundler } from './httpDataBundler.js';
10
- import ClientConfig from '../api/clientConfig.js';
11
11
  import GqlErrorValidator from './gqlErrorValidator.js';
12
12
 
13
13
  /** @module RequestMonitor */
@@ -20,7 +20,6 @@ import GqlErrorValidator from './gqlErrorValidator.js';
20
20
  * @param {string} method
21
21
  * @param {string} url
22
22
  * @param {number} respTime
23
- * @param {object} gqlError
24
23
  * @param {*} rawPayload
25
24
  * @returns HTTP event and data
26
25
  */
@@ -29,7 +28,6 @@ function _buildHttpEventDataObjectsForXHR(
29
28
  method,
30
29
  url,
31
30
  respTime,
32
- gqlError,
33
31
  rawPayload = null,
34
32
  ) {
35
33
  const httpEvent = {
@@ -39,9 +37,8 @@ function _buildHttpEventDataObjectsForXHR(
39
37
  [HTTP_RESP_TIME_ATT_NAME]: respTime,
40
38
  };
41
39
  let httpData = null;
42
- const isGqlError = gqlError != null;
43
- const isError = isHttpCodeFailure(xhrObj.status) || isGqlError;
44
- if (isError && HTTPDataBundler.getInstance().shouldContinueForURL(url)) {
40
+
41
+ if (HTTPDataBundler.getInstance().shouldContinueForURL(url)) {
45
42
  const responseHeaders = HTTPDataBundler.headersMapFromString(
46
43
  xhrObj.getAllResponseHeaders(),
47
44
  );
@@ -72,7 +69,6 @@ function _buildHttpEventDataObjectsForXHR(
72
69
  responseHeaders,
73
70
  responseBody,
74
71
  method,
75
- isError,
76
72
  );
77
73
  }
78
74
  return [httpEvent, httpData];
@@ -88,7 +84,6 @@ function _buildHttpEventDataObjectsForXHR(
88
84
  * [0] is the response body, [1] is an optional response body.
89
85
  * @param {string} url the URL of the request
90
86
  * @param {string} method the method used in the fetch call
91
- * @param {boolean} isError is an error
92
87
  * @returns the return from the bundleHTTPData() call
93
88
  */
94
89
  function _handleFetchOnPromiseCompletion(
@@ -98,7 +93,6 @@ function _handleFetchOnPromiseCompletion(
98
93
  bodyStrings,
99
94
  url,
100
95
  method,
101
- isError,
102
96
  ) {
103
97
  let reqBody; //
104
98
  let reqHeaders = new Map();
@@ -154,7 +148,6 @@ function _handleFetchOnPromiseCompletion(
154
148
  respHeaders,
155
149
  bodyStrings[0],
156
150
  method,
157
- isError,
158
151
  );
159
152
  }
160
153
 
@@ -167,7 +160,6 @@ function _handleFetchOnPromiseCompletion(
167
160
  * @param {object} options the options parameter from the original fetch() call
168
161
  * @param {number} respTime the time between the fetch() call and the the resolution of the
169
162
  * original implementation's return
170
- * @param {object} gqlError a GraphQL error object
171
163
  * @param {Promise<string>} requestTextPromise
172
164
  * @returns an array in the form [httpEvent, httpData]
173
165
  */
@@ -179,7 +171,6 @@ async function _buildHttpEventDataObjectsForFetch(
179
171
  options,
180
172
  respTime,
181
173
  requestTextPromise,
182
- gqlError,
183
174
  ) {
184
175
  const httpEvent = {
185
176
  [HTTP_METHOD_ATT_NAME]: method,
@@ -189,10 +180,8 @@ async function _buildHttpEventDataObjectsForFetch(
189
180
  };
190
181
 
191
182
  let httpData = null;
192
- const isGqlError = gqlError != null;
193
- const isError = isHttpCodeFailure(response.status) || isGqlError;
194
183
  // Only get the bodies of the request and response on error and if the URL is one we care about.
195
- if (isError && HTTPDataBundler.getInstance().shouldContinueForURL(url)) {
184
+ if (HTTPDataBundler.getInstance().shouldContinueForURL(url)) {
196
185
  // add response payload length, if any
197
186
  if (response && response.headers) {
198
187
  const contentLength = HTTPDataBundler.getInstance().contentLength(
@@ -206,7 +195,6 @@ async function _buildHttpEventDataObjectsForFetch(
206
195
  let responseText = '';
207
196
  if (
208
197
  HTTPDataBundler.getInstance().shouldCollectPayloadForURL(url) &&
209
- !!response &&
210
198
  response instanceof Response
211
199
  ) {
212
200
  const droppedResponseText =
@@ -235,7 +223,6 @@ async function _buildHttpEventDataObjectsForFetch(
235
223
  data,
236
224
  url,
237
225
  method,
238
- isError,
239
226
  ),
240
227
  )
241
228
  .then(httpDataReturn => {
@@ -591,7 +578,6 @@ function setupGlobalFetchWrapper() {
591
578
  options,
592
579
  respTime,
593
580
  requestTextPromise,
594
- gqlError,
595
581
  );
596
582
 
597
583
  let pageVisitEventHTTP = new PageVisitEventHTTP(