@newrelic/browser-agent 1.294.0-rc.1 → 1.294.0-rc.3

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.
@@ -17,7 +17,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
17
17
  /**
18
18
  * Exposes the version of the agent
19
19
  */
20
- const VERSION = exports.VERSION = "1.294.0-rc.1";
20
+ const VERSION = exports.VERSION = "1.294.0-rc.3";
21
21
 
22
22
  /**
23
23
  * Exposes the build type of the agent
@@ -17,7 +17,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
17
17
  /**
18
18
  * Exposes the version of the agent
19
19
  */
20
- const VERSION = exports.VERSION = "1.294.0-rc.1";
20
+ const VERSION = exports.VERSION = "1.294.0-rc.3";
21
21
 
22
22
  /**
23
23
  * Exposes the build type of the agent
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.buildCauseString = buildCauseString;
7
+ var _stringify = require("../../../common/util/stringify");
8
+ var _computeStackTrace = require("./compute-stack-trace");
9
+ /**
10
+ * Copyright 2020-2025 New Relic, Inc. All rights reserved.
11
+ * SPDX-License-Identifier: Apache-2.0
12
+ * @fileoverview; Extracts the cause string from an error object.
13
+ */
14
+
15
+ /**
16
+ * Extracts and normalizes a string from an error instance with a cause attribute.
17
+ * @param {Error} err - The error object to extract the cause from.
18
+ * @returns {string} The cause string extracted from the error object. Will be an empty string if no cause is present.
19
+ */
20
+ function buildCauseString(err) {
21
+ let causeStackString = '';
22
+ if (!err?.cause) return causeStackString;
23
+ if (err.cause instanceof Error) {
24
+ const stackInfo = (0, _computeStackTrace.computeStackTrace)(err.cause);
25
+ causeStackString = stackInfo.stackString || err.cause.stack;
26
+ if (stackInfo.message && !causeStackString.includes(stackInfo.message)) causeStackString = stackInfo.message + '\n' + causeStackString;
27
+ if (stackInfo.name && !causeStackString.includes(stackInfo.name)) causeStackString = stackInfo.name + ': ' + causeStackString;
28
+ } else causeStackString = typeof err.cause === 'string' ? err.cause : (0, _stringify.stringify)(err.cause);
29
+ causeStackString ||= err.cause.toString(); // fallback to try the string representation if all else fails
30
+ return causeStackString;
31
+ }
@@ -20,6 +20,7 @@ var _traverse = require("../../../common/util/traverse");
20
20
  var _internalErrors = require("./internal-errors");
21
21
  var _target = require("../../../common/util/target");
22
22
  var _console = require("../../../common/util/console");
23
+ var _causeString = require("./cause-string");
23
24
  /**
24
25
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
25
26
  * SPDX-License-Identifier: Apache-2.0
@@ -132,10 +133,14 @@ class Aggregate extends _aggregateBase.AggregateBase {
132
133
  return;
133
134
  }
134
135
  var canonicalStackString = this.buildCanonicalStackString(stackInfo);
136
+ const causeStackString = (0, _causeString.buildCauseString)(err);
135
137
  const params = {
136
138
  stackHash: (0, _stringHashCode.stringHashCode)(canonicalStackString),
137
139
  exceptionClass: stackInfo.name,
138
- request_uri: _runtime.globalScope?.location.pathname
140
+ request_uri: _runtime.globalScope?.location.pathname,
141
+ ...(causeStackString && {
142
+ cause: causeStackString
143
+ })
139
144
  };
140
145
  if (stackInfo.message) params.message = '' + stackInfo.message;
141
146
  // Notice if filterOutput isn't false|undefined OR our specified object, this func would've returned already (so it's unnecessary to req-check group).
@@ -28,7 +28,7 @@ function castError(error) {
28
28
  * The thrown value may contain a message property. If it does, try to treat the thrown
29
29
  * value as an Error-like object.
30
30
  */
31
- return new _uncaughtError.UncaughtError(error?.message !== undefined ? error.message : error, error?.filename || error?.sourceURL, error?.lineno || error?.line, error?.colno || error?.col, error?.__newrelic);
31
+ return new _uncaughtError.UncaughtError(error?.message !== undefined ? error.message : error, error?.filename || error?.sourceURL, error?.lineno || error?.line, error?.colno || error?.col, error?.__newrelic, error?.cause);
32
32
  }
33
33
 
34
34
  /**
@@ -65,7 +65,7 @@ function castPromiseRejectionEvent(promiseRejectionEvent) {
65
65
  */
66
66
  function castErrorEvent(errorEvent) {
67
67
  if (errorEvent.error instanceof SyntaxError && !/:\d+$/.test(errorEvent.error.stack?.trim())) {
68
- const error = new _uncaughtError.UncaughtError(errorEvent.message, errorEvent.filename, errorEvent.lineno, errorEvent.colno, errorEvent.error.__newrelic);
68
+ const error = new _uncaughtError.UncaughtError(errorEvent.message, errorEvent.filename, errorEvent.lineno, errorEvent.colno, errorEvent.error.__newrelic, errorEvent.cause);
69
69
  error.name = SyntaxError.name;
70
70
  return error;
71
71
  }
@@ -291,6 +291,24 @@ class Aggregate extends _aggregateBase.AggregateBase {
291
291
  if (node.__newrelic) return node.timestamp;
292
292
  return this.timeKeeper.correctAbsoluteTimestamp(node.timestamp);
293
293
  }
294
+
295
+ /**
296
+ * returns the timestamps for the earliest and latest nodes in the provided array, even if out of order
297
+ * @param {Object[]} [nodes] - the nodes to evaluate
298
+ * @returns {{ firstEvent: Object|undefined, lastEvent: Object|undefined }} - the earliest and latest nodes. Defaults to undefined if no nodes are provided or if no timestamps are found in the nodes.
299
+ */
300
+ getFirstAndLastNodes(nodes = []) {
301
+ const output = {
302
+ firstEvent: nodes[0],
303
+ lastEvent: nodes[nodes.length - 1]
304
+ };
305
+ nodes.forEach(node => {
306
+ const timestamp = node?.timestamp;
307
+ if (!output.firstEvent?.timestamp || (timestamp || Infinity) < output.firstEvent.timestamp) output.firstEvent = node;
308
+ if (!output.lastEvent?.timestamp || (timestamp || -Infinity) > output.lastEvent.timestamp) output.lastEvent = node;
309
+ });
310
+ return output;
311
+ }
294
312
  getHarvestContents(recorderEvents) {
295
313
  recorderEvents ??= this.recorder.getEvents();
296
314
  let events = recorderEvents.events;
@@ -315,11 +333,13 @@ class Aggregate extends _aggregateBase.AggregateBase {
315
333
  recorderEvents.hasMeta = !!events.find(x => x.type === _constants.RRWEB_EVENT_TYPES.Meta);
316
334
  }
317
335
  const relativeNow = (0, _now.now)();
318
- const firstEventTimestamp = this.getCorrectedTimestamp(events[0]); // from rrweb node
319
- const lastEventTimestamp = this.getCorrectedTimestamp(events[events.length - 1]); // from rrweb node
336
+ const {
337
+ firstEvent,
338
+ lastEvent
339
+ } = this.getFirstAndLastNodes(events);
320
340
  // from rrweb node || from when the harvest cycle started
321
- const firstTimestamp = firstEventTimestamp || Math.floor(this.timeKeeper.correctAbsoluteTimestamp(recorderEvents.cycleTimestamp));
322
- const lastTimestamp = lastEventTimestamp || Math.floor(this.timeKeeper.correctRelativeTimestamp(relativeNow));
341
+ const firstTimestamp = this.getCorrectedTimestamp(firstEvent) || Math.floor(this.timeKeeper.correctAbsoluteTimestamp(recorderEvents.cycleTimestamp));
342
+ const lastTimestamp = this.getCorrectedTimestamp(lastEvent) || Math.floor(this.timeKeeper.correctRelativeTimestamp(relativeNow));
323
343
  const agentMetadata = agentRuntime.appMetadata?.agents?.[0] || {};
324
344
  return {
325
345
  qs: {
@@ -11,7 +11,7 @@
11
11
  /**
12
12
  * Exposes the version of the agent
13
13
  */
14
- export const VERSION = "1.294.0-rc.1";
14
+ export const VERSION = "1.294.0-rc.3";
15
15
 
16
16
  /**
17
17
  * Exposes the build type of the agent
@@ -11,7 +11,7 @@
11
11
  /**
12
12
  * Exposes the version of the agent
13
13
  */
14
- export const VERSION = "1.294.0-rc.1";
14
+ export const VERSION = "1.294.0-rc.3";
15
15
 
16
16
  /**
17
17
  * Exposes the build type of the agent
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Copyright 2020-2025 New Relic, Inc. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ * @fileoverview; Extracts the cause string from an error object.
5
+ */
6
+
7
+ import { stringify } from '../../../common/util/stringify';
8
+ import { computeStackTrace } from './compute-stack-trace';
9
+
10
+ /**
11
+ * Extracts and normalizes a string from an error instance with a cause attribute.
12
+ * @param {Error} err - The error object to extract the cause from.
13
+ * @returns {string} The cause string extracted from the error object. Will be an empty string if no cause is present.
14
+ */
15
+ export function buildCauseString(err) {
16
+ let causeStackString = '';
17
+ if (!err?.cause) return causeStackString;
18
+ if (err.cause instanceof Error) {
19
+ const stackInfo = computeStackTrace(err.cause);
20
+ causeStackString = stackInfo.stackString || err.cause.stack;
21
+ if (stackInfo.message && !causeStackString.includes(stackInfo.message)) causeStackString = stackInfo.message + '\n' + causeStackString;
22
+ if (stackInfo.name && !causeStackString.includes(stackInfo.name)) causeStackString = stackInfo.name + ': ' + causeStackString;
23
+ } else causeStackString = typeof err.cause === 'string' ? err.cause : stringify(err.cause);
24
+ causeStackString ||= err.cause.toString(); // fallback to try the string representation if all else fails
25
+ return causeStackString;
26
+ }
@@ -19,6 +19,7 @@ import { applyFnToProps } from '../../../common/util/traverse';
19
19
  import { evaluateInternalError } from './internal-errors';
20
20
  import { isContainerAgentTarget } from '../../../common/util/target';
21
21
  import { warn } from '../../../common/util/console';
22
+ import { buildCauseString } from './cause-string';
22
23
 
23
24
  /**
24
25
  * @typedef {import('./compute-stack-trace.js').StackInfo} StackInfo
@@ -127,10 +128,14 @@ export class Aggregate extends AggregateBase {
127
128
  return;
128
129
  }
129
130
  var canonicalStackString = this.buildCanonicalStackString(stackInfo);
131
+ const causeStackString = buildCauseString(err);
130
132
  const params = {
131
133
  stackHash: stringHashCode(canonicalStackString),
132
134
  exceptionClass: stackInfo.name,
133
- request_uri: globalScope?.location.pathname
135
+ request_uri: globalScope?.location.pathname,
136
+ ...(causeStackString && {
137
+ cause: causeStackString
138
+ })
134
139
  };
135
140
  if (stackInfo.message) params.message = '' + stackInfo.message;
136
141
  // Notice if filterOutput isn't false|undefined OR our specified object, this func would've returned already (so it's unnecessary to req-check group).
@@ -20,7 +20,7 @@ export function castError(error) {
20
20
  * The thrown value may contain a message property. If it does, try to treat the thrown
21
21
  * value as an Error-like object.
22
22
  */
23
- return new UncaughtError(error?.message !== undefined ? error.message : error, error?.filename || error?.sourceURL, error?.lineno || error?.line, error?.colno || error?.col, error?.__newrelic);
23
+ return new UncaughtError(error?.message !== undefined ? error.message : error, error?.filename || error?.sourceURL, error?.lineno || error?.line, error?.colno || error?.col, error?.__newrelic, error?.cause);
24
24
  }
25
25
 
26
26
  /**
@@ -57,7 +57,7 @@ export function castPromiseRejectionEvent(promiseRejectionEvent) {
57
57
  */
58
58
  export function castErrorEvent(errorEvent) {
59
59
  if (errorEvent.error instanceof SyntaxError && !/:\d+$/.test(errorEvent.error.stack?.trim())) {
60
- const error = new UncaughtError(errorEvent.message, errorEvent.filename, errorEvent.lineno, errorEvent.colno, errorEvent.error.__newrelic);
60
+ const error = new UncaughtError(errorEvent.message, errorEvent.filename, errorEvent.lineno, errorEvent.colno, errorEvent.error.__newrelic, errorEvent.cause);
61
61
  error.name = SyntaxError.name;
62
62
  return error;
63
63
  }
@@ -286,6 +286,24 @@ export class Aggregate extends AggregateBase {
286
286
  if (node.__newrelic) return node.timestamp;
287
287
  return this.timeKeeper.correctAbsoluteTimestamp(node.timestamp);
288
288
  }
289
+
290
+ /**
291
+ * returns the timestamps for the earliest and latest nodes in the provided array, even if out of order
292
+ * @param {Object[]} [nodes] - the nodes to evaluate
293
+ * @returns {{ firstEvent: Object|undefined, lastEvent: Object|undefined }} - the earliest and latest nodes. Defaults to undefined if no nodes are provided or if no timestamps are found in the nodes.
294
+ */
295
+ getFirstAndLastNodes(nodes = []) {
296
+ const output = {
297
+ firstEvent: nodes[0],
298
+ lastEvent: nodes[nodes.length - 1]
299
+ };
300
+ nodes.forEach(node => {
301
+ const timestamp = node?.timestamp;
302
+ if (!output.firstEvent?.timestamp || (timestamp || Infinity) < output.firstEvent.timestamp) output.firstEvent = node;
303
+ if (!output.lastEvent?.timestamp || (timestamp || -Infinity) > output.lastEvent.timestamp) output.lastEvent = node;
304
+ });
305
+ return output;
306
+ }
289
307
  getHarvestContents(recorderEvents) {
290
308
  recorderEvents ??= this.recorder.getEvents();
291
309
  let events = recorderEvents.events;
@@ -310,11 +328,13 @@ export class Aggregate extends AggregateBase {
310
328
  recorderEvents.hasMeta = !!events.find(x => x.type === RRWEB_EVENT_TYPES.Meta);
311
329
  }
312
330
  const relativeNow = now();
313
- const firstEventTimestamp = this.getCorrectedTimestamp(events[0]); // from rrweb node
314
- const lastEventTimestamp = this.getCorrectedTimestamp(events[events.length - 1]); // from rrweb node
331
+ const {
332
+ firstEvent,
333
+ lastEvent
334
+ } = this.getFirstAndLastNodes(events);
315
335
  // from rrweb node || from when the harvest cycle started
316
- const firstTimestamp = firstEventTimestamp || Math.floor(this.timeKeeper.correctAbsoluteTimestamp(recorderEvents.cycleTimestamp));
317
- const lastTimestamp = lastEventTimestamp || Math.floor(this.timeKeeper.correctRelativeTimestamp(relativeNow));
336
+ const firstTimestamp = this.getCorrectedTimestamp(firstEvent) || Math.floor(this.timeKeeper.correctAbsoluteTimestamp(recorderEvents.cycleTimestamp));
337
+ const lastTimestamp = this.getCorrectedTimestamp(lastEvent) || Math.floor(this.timeKeeper.correctRelativeTimestamp(relativeNow));
318
338
  const agentMetadata = agentRuntime.appMetadata?.agents?.[0] || {};
319
339
  return {
320
340
  qs: {
@@ -1 +1 @@
1
- {"root":["../src/index.js","../src/cdn/experimental.js","../src/cdn/lite.js","../src/cdn/pro.js","../src/cdn/spa.js","../src/common/aggregate/aggregator.js","../src/common/aggregate/event-aggregator.js","../src/common/config/configurable.js","../src/common/config/info.js","../src/common/config/init-types.js","../src/common/config/init.js","../src/common/config/loader-config.js","../src/common/config/runtime.js","../src/common/constants/agent-constants.js","../src/common/constants/env.cdn.js","../src/common/constants/env.js","../src/common/constants/env.npm.js","../src/common/constants/runtime.js","../src/common/constants/shared-channel.js","../src/common/deny-list/deny-list.js","../src/common/dispatch/global-event.js","../src/common/dom/iframe.js","../src/common/dom/query-selector.js","../src/common/dom/selector-path.js","../src/common/drain/drain.js","../src/common/event-emitter/contextual-ee.js","../src/common/event-emitter/event-context.js","../src/common/event-emitter/handle.js","../src/common/event-emitter/register-handler.js","../src/common/event-listener/event-listener-opts.js","../src/common/harvest/harvester.js","../src/common/harvest/types.js","../src/common/ids/bundle-id.js","../src/common/ids/id.js","../src/common/ids/unique-id.js","../src/common/serialize/bel-serializer.js","../src/common/session/constants.js","../src/common/session/session-entity.js","../src/common/storage/local-storage.js","../src/common/timer/interaction-timer.js","../src/common/timer/timer.js","../src/common/timing/nav-timing.js","../src/common/timing/now.js","../src/common/timing/time-keeper.js","../src/common/unload/eol.js","../src/common/url/canonicalize-url.js","../src/common/url/clean-url.js","../src/common/url/encode.js","../src/common/url/location.js","../src/common/url/parse-url.js","../src/common/url/protocol.js","../src/common/util/attribute-size.js","../src/common/util/console.js","../src/common/util/data-size.js","../src/common/util/event-origin.js","../src/common/util/feature-flags.js","../src/common/util/get-or-set.js","../src/common/util/invoke.js","../src/common/util/obfuscate.js","../src/common/util/stringify.js","../src/common/util/submit-data.js","../src/common/util/target.js","../src/common/util/text.js","../src/common/util/traverse.js","../src/common/util/type-check.js","../src/common/vitals/constants.js","../src/common/vitals/cumulative-layout-shift.js","../src/common/vitals/first-contentful-paint.js","../src/common/vitals/first-paint.js","../src/common/vitals/interaction-to-next-paint.js","../src/common/vitals/largest-contentful-paint.js","../src/common/vitals/time-to-first-byte.js","../src/common/vitals/vital-metric.js","../src/common/window/load.js","../src/common/window/nreum.js","../src/common/window/page-visibility.js","../src/common/wrap/wrap-events.js","../src/common/wrap/wrap-fetch.js","../src/common/wrap/wrap-function.js","../src/common/wrap/wrap-history.js","../src/common/wrap/wrap-jsonp.js","../src/common/wrap/wrap-logger.js","../src/common/wrap/wrap-mutation.js","../src/common/wrap/wrap-promise.js","../src/common/wrap/wrap-timer.js","../src/common/wrap/wrap-websocket.js","../src/common/wrap/wrap-xhr.js","../src/features/ajax/constants.js","../src/features/ajax/index.js","../src/features/ajax/aggregate/gql.js","../src/features/ajax/aggregate/index.js","../src/features/ajax/instrument/distributed-tracing.js","../src/features/ajax/instrument/index.js","../src/features/ajax/instrument/response-size.js","../src/features/generic_events/constants.js","../src/features/generic_events/index.js","../src/features/generic_events/aggregate/index.js","../src/features/generic_events/aggregate/user-actions/aggregated-user-action.js","../src/features/generic_events/aggregate/user-actions/user-actions-aggregator.js","../src/features/generic_events/instrument/index.js","../src/features/jserrors/constants.js","../src/features/jserrors/index.js","../src/features/jserrors/aggregate/canonical-function-name.js","../src/features/jserrors/aggregate/compute-stack-trace.js","../src/features/jserrors/aggregate/format-stack-trace.js","../src/features/jserrors/aggregate/index.js","../src/features/jserrors/aggregate/internal-errors.js","../src/features/jserrors/aggregate/string-hash-code.js","../src/features/jserrors/instrument/index.js","../src/features/jserrors/shared/cast-error.js","../src/features/jserrors/shared/uncaught-error.js","../src/features/logging/constants.js","../src/features/logging/index.js","../src/features/logging/aggregate/index.js","../src/features/logging/instrument/index.js","../src/features/logging/shared/log.js","../src/features/logging/shared/utils.js","../src/features/metrics/constants.js","../src/features/metrics/index.js","../src/features/metrics/aggregate/framework-detection.js","../src/features/metrics/aggregate/index.js","../src/features/metrics/aggregate/websocket-detection.js","../src/features/metrics/instrument/index.js","../src/features/page_action/constants.js","../src/features/page_action/index.js","../src/features/page_action/instrument/index.js","../src/features/page_view_event/constants.js","../src/features/page_view_event/index.js","../src/features/page_view_event/aggregate/index.js","../src/features/page_view_event/aggregate/initialized-features.js","../src/features/page_view_event/instrument/index.js","../src/features/page_view_timing/constants.js","../src/features/page_view_timing/index.js","../src/features/page_view_timing/aggregate/index.js","../src/features/page_view_timing/instrument/index.js","../src/features/session_replay/constants.js","../src/features/session_replay/index.js","../src/features/session_replay/aggregate/index.js","../src/features/session_replay/instrument/index.js","../src/features/session_replay/shared/recorder-events.js","../src/features/session_replay/shared/recorder.js","../src/features/session_replay/shared/stylesheet-evaluator.js","../src/features/session_replay/shared/utils.js","../src/features/session_trace/constants.js","../src/features/session_trace/index.js","../src/features/session_trace/aggregate/index.js","../src/features/session_trace/aggregate/trace/node.js","../src/features/session_trace/aggregate/trace/storage.js","../src/features/session_trace/instrument/index.js","../src/features/soft_navigations/constants.js","../src/features/soft_navigations/index.js","../src/features/soft_navigations/aggregate/ajax-node.js","../src/features/soft_navigations/aggregate/bel-node.js","../src/features/soft_navigations/aggregate/index.js","../src/features/soft_navigations/aggregate/initial-page-load-interaction.js","../src/features/soft_navigations/aggregate/interaction.js","../src/features/soft_navigations/instrument/index.js","../src/features/spa/constants.js","../src/features/spa/index.js","../src/features/spa/aggregate/index.js","../src/features/spa/aggregate/interaction-node.js","../src/features/spa/aggregate/interaction.js","../src/features/spa/aggregate/serializer.js","../src/features/spa/instrument/index.js","../src/features/utils/agent-session.js","../src/features/utils/aggregate-base.js","../src/features/utils/entity-manager.js","../src/features/utils/event-buffer.js","../src/features/utils/event-store-manager.js","../src/features/utils/feature-base.js","../src/features/utils/feature-gates.js","../src/features/utils/instrument-base.js","../src/features/utils/nr1-debugger.js","../src/interfaces/registered-entity.js","../src/loaders/agent-base.js","../src/loaders/agent.js","../src/loaders/api-base.js","../src/loaders/browser-agent.js","../src/loaders/micro-agent-base.js","../src/loaders/micro-agent.js","../src/loaders/api/addPageAction.js","../src/loaders/api/addRelease.js","../src/loaders/api/addToTrace.js","../src/loaders/api/constants.js","../src/loaders/api/finished.js","../src/loaders/api/interaction-types.js","../src/loaders/api/interaction.js","../src/loaders/api/log.js","../src/loaders/api/measure.js","../src/loaders/api/noticeError.js","../src/loaders/api/pauseReplay.js","../src/loaders/api/recordCustomEvent.js","../src/loaders/api/recordReplay.js","../src/loaders/api/register-api-types.js","../src/loaders/api/register-api.js","../src/loaders/api/register.js","../src/loaders/api/setApplicationVersion.js","../src/loaders/api/setCustomAttribute.js","../src/loaders/api/setErrorHandler.js","../src/loaders/api/setPageViewName.js","../src/loaders/api/setUserId.js","../src/loaders/api/sharedHandlers.js","../src/loaders/api/start.js","../src/loaders/api/topLevelCallers.js","../src/loaders/api/wrapLogger.js","../src/loaders/configure/configure.js","../src/loaders/configure/nonce.js","../src/loaders/configure/public-path.js","../src/loaders/features/enabled-features.js","../src/loaders/features/featureDependencies.js","../src/loaders/features/features.js"],"version":"5.7.3"}
1
+ {"root":["../src/index.js","../src/cdn/experimental.js","../src/cdn/lite.js","../src/cdn/pro.js","../src/cdn/spa.js","../src/common/aggregate/aggregator.js","../src/common/aggregate/event-aggregator.js","../src/common/config/configurable.js","../src/common/config/info.js","../src/common/config/init-types.js","../src/common/config/init.js","../src/common/config/loader-config.js","../src/common/config/runtime.js","../src/common/constants/agent-constants.js","../src/common/constants/env.cdn.js","../src/common/constants/env.js","../src/common/constants/env.npm.js","../src/common/constants/runtime.js","../src/common/constants/shared-channel.js","../src/common/deny-list/deny-list.js","../src/common/dispatch/global-event.js","../src/common/dom/iframe.js","../src/common/dom/query-selector.js","../src/common/dom/selector-path.js","../src/common/drain/drain.js","../src/common/event-emitter/contextual-ee.js","../src/common/event-emitter/event-context.js","../src/common/event-emitter/handle.js","../src/common/event-emitter/register-handler.js","../src/common/event-listener/event-listener-opts.js","../src/common/harvest/harvester.js","../src/common/harvest/types.js","../src/common/ids/bundle-id.js","../src/common/ids/id.js","../src/common/ids/unique-id.js","../src/common/serialize/bel-serializer.js","../src/common/session/constants.js","../src/common/session/session-entity.js","../src/common/storage/local-storage.js","../src/common/timer/interaction-timer.js","../src/common/timer/timer.js","../src/common/timing/nav-timing.js","../src/common/timing/now.js","../src/common/timing/time-keeper.js","../src/common/unload/eol.js","../src/common/url/canonicalize-url.js","../src/common/url/clean-url.js","../src/common/url/encode.js","../src/common/url/location.js","../src/common/url/parse-url.js","../src/common/url/protocol.js","../src/common/util/attribute-size.js","../src/common/util/console.js","../src/common/util/data-size.js","../src/common/util/event-origin.js","../src/common/util/feature-flags.js","../src/common/util/get-or-set.js","../src/common/util/invoke.js","../src/common/util/obfuscate.js","../src/common/util/stringify.js","../src/common/util/submit-data.js","../src/common/util/target.js","../src/common/util/text.js","../src/common/util/traverse.js","../src/common/util/type-check.js","../src/common/vitals/constants.js","../src/common/vitals/cumulative-layout-shift.js","../src/common/vitals/first-contentful-paint.js","../src/common/vitals/first-paint.js","../src/common/vitals/interaction-to-next-paint.js","../src/common/vitals/largest-contentful-paint.js","../src/common/vitals/time-to-first-byte.js","../src/common/vitals/vital-metric.js","../src/common/window/load.js","../src/common/window/nreum.js","../src/common/window/page-visibility.js","../src/common/wrap/wrap-events.js","../src/common/wrap/wrap-fetch.js","../src/common/wrap/wrap-function.js","../src/common/wrap/wrap-history.js","../src/common/wrap/wrap-jsonp.js","../src/common/wrap/wrap-logger.js","../src/common/wrap/wrap-mutation.js","../src/common/wrap/wrap-promise.js","../src/common/wrap/wrap-timer.js","../src/common/wrap/wrap-websocket.js","../src/common/wrap/wrap-xhr.js","../src/features/ajax/constants.js","../src/features/ajax/index.js","../src/features/ajax/aggregate/gql.js","../src/features/ajax/aggregate/index.js","../src/features/ajax/instrument/distributed-tracing.js","../src/features/ajax/instrument/index.js","../src/features/ajax/instrument/response-size.js","../src/features/generic_events/constants.js","../src/features/generic_events/index.js","../src/features/generic_events/aggregate/index.js","../src/features/generic_events/aggregate/user-actions/aggregated-user-action.js","../src/features/generic_events/aggregate/user-actions/user-actions-aggregator.js","../src/features/generic_events/instrument/index.js","../src/features/jserrors/constants.js","../src/features/jserrors/index.js","../src/features/jserrors/aggregate/canonical-function-name.js","../src/features/jserrors/aggregate/cause-string.js","../src/features/jserrors/aggregate/compute-stack-trace.js","../src/features/jserrors/aggregate/format-stack-trace.js","../src/features/jserrors/aggregate/index.js","../src/features/jserrors/aggregate/internal-errors.js","../src/features/jserrors/aggregate/string-hash-code.js","../src/features/jserrors/instrument/index.js","../src/features/jserrors/shared/cast-error.js","../src/features/jserrors/shared/uncaught-error.js","../src/features/logging/constants.js","../src/features/logging/index.js","../src/features/logging/aggregate/index.js","../src/features/logging/instrument/index.js","../src/features/logging/shared/log.js","../src/features/logging/shared/utils.js","../src/features/metrics/constants.js","../src/features/metrics/index.js","../src/features/metrics/aggregate/framework-detection.js","../src/features/metrics/aggregate/index.js","../src/features/metrics/aggregate/websocket-detection.js","../src/features/metrics/instrument/index.js","../src/features/page_action/constants.js","../src/features/page_action/index.js","../src/features/page_action/instrument/index.js","../src/features/page_view_event/constants.js","../src/features/page_view_event/index.js","../src/features/page_view_event/aggregate/index.js","../src/features/page_view_event/aggregate/initialized-features.js","../src/features/page_view_event/instrument/index.js","../src/features/page_view_timing/constants.js","../src/features/page_view_timing/index.js","../src/features/page_view_timing/aggregate/index.js","../src/features/page_view_timing/instrument/index.js","../src/features/session_replay/constants.js","../src/features/session_replay/index.js","../src/features/session_replay/aggregate/index.js","../src/features/session_replay/instrument/index.js","../src/features/session_replay/shared/recorder-events.js","../src/features/session_replay/shared/recorder.js","../src/features/session_replay/shared/stylesheet-evaluator.js","../src/features/session_replay/shared/utils.js","../src/features/session_trace/constants.js","../src/features/session_trace/index.js","../src/features/session_trace/aggregate/index.js","../src/features/session_trace/aggregate/trace/node.js","../src/features/session_trace/aggregate/trace/storage.js","../src/features/session_trace/instrument/index.js","../src/features/soft_navigations/constants.js","../src/features/soft_navigations/index.js","../src/features/soft_navigations/aggregate/ajax-node.js","../src/features/soft_navigations/aggregate/bel-node.js","../src/features/soft_navigations/aggregate/index.js","../src/features/soft_navigations/aggregate/initial-page-load-interaction.js","../src/features/soft_navigations/aggregate/interaction.js","../src/features/soft_navigations/instrument/index.js","../src/features/spa/constants.js","../src/features/spa/index.js","../src/features/spa/aggregate/index.js","../src/features/spa/aggregate/interaction-node.js","../src/features/spa/aggregate/interaction.js","../src/features/spa/aggregate/serializer.js","../src/features/spa/instrument/index.js","../src/features/utils/agent-session.js","../src/features/utils/aggregate-base.js","../src/features/utils/entity-manager.js","../src/features/utils/event-buffer.js","../src/features/utils/event-store-manager.js","../src/features/utils/feature-base.js","../src/features/utils/feature-gates.js","../src/features/utils/instrument-base.js","../src/features/utils/nr1-debugger.js","../src/interfaces/registered-entity.js","../src/loaders/agent-base.js","../src/loaders/agent.js","../src/loaders/api-base.js","../src/loaders/browser-agent.js","../src/loaders/micro-agent-base.js","../src/loaders/micro-agent.js","../src/loaders/api/addPageAction.js","../src/loaders/api/addRelease.js","../src/loaders/api/addToTrace.js","../src/loaders/api/constants.js","../src/loaders/api/finished.js","../src/loaders/api/interaction-types.js","../src/loaders/api/interaction.js","../src/loaders/api/log.js","../src/loaders/api/measure.js","../src/loaders/api/noticeError.js","../src/loaders/api/pauseReplay.js","../src/loaders/api/recordCustomEvent.js","../src/loaders/api/recordReplay.js","../src/loaders/api/register-api-types.js","../src/loaders/api/register-api.js","../src/loaders/api/register.js","../src/loaders/api/setApplicationVersion.js","../src/loaders/api/setCustomAttribute.js","../src/loaders/api/setErrorHandler.js","../src/loaders/api/setPageViewName.js","../src/loaders/api/setUserId.js","../src/loaders/api/sharedHandlers.js","../src/loaders/api/start.js","../src/loaders/api/topLevelCallers.js","../src/loaders/api/wrapLogger.js","../src/loaders/configure/configure.js","../src/loaders/configure/nonce.js","../src/loaders/configure/public-path.js","../src/loaders/features/enabled-features.js","../src/loaders/features/featureDependencies.js","../src/loaders/features/features.js"],"version":"5.7.3"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Extracts and normalizes a string from an error instance with a cause attribute.
3
+ * @param {Error} err - The error object to extract the cause from.
4
+ * @returns {string} The cause string extracted from the error object. Will be an empty string if no cause is present.
5
+ */
6
+ export function buildCauseString(err: Error): string;
7
+ //# sourceMappingURL=cause-string.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cause-string.d.ts","sourceRoot":"","sources":["../../../../../src/features/jserrors/aggregate/cause-string.js"],"names":[],"mappings":"AASA;;;;GAIG;AACH,sCAHW,KAAK,GACH,MAAM,CAalB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/jserrors/aggregate/index.js"],"names":[],"mappings":"AAwBA;;GAEG;AAEH;IACE,2BAAiC;IACjC,2BA4BC;IAzBC,kBAAuB;IACvB,eAAoB;IACpB,qBAA0B;IAC1B,2BAAgC;IAChC,qBAAwB;IAuB1B,oDAEC;IAED;;;MAcC;IAED;;;;;;OAMG;IACH,qCAHW,SAAS,GACP,MAAM,CAgBlB;IAED;;;;;;;;;;OAUG;IACH,gBATW,KAAK,GAAC,aAAa,QACnB,MAAM,aACN,OAAO,YAAC,qBACR,MAAM,YAAC,cACP,OAAO,YAAC,kBACR,MAAM,YAAC,+BA8GjB;IA4BD;;;;;MAKE;IACF,0CAHU,MAAM,GACJ,OAAO,CAIlB;IAGD,yDA6BC;IAED,qFAOC;;CACF;wBAjRY,OAAO,0BAA0B,EAAE,SAAS;8BAR3B,4BAA4B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/jserrors/aggregate/index.js"],"names":[],"mappings":"AAyBA;;GAEG;AAEH;IACE,2BAAiC;IACjC,2BA4BC;IAzBC,kBAAuB;IACvB,eAAoB;IACpB,qBAA0B;IAC1B,2BAAgC;IAChC,qBAAwB;IAuB1B,oDAEC;IAED;;;MAcC;IAED;;;;;;OAMG;IACH,qCAHW,SAAS,GACP,MAAM,CAgBlB;IAED;;;;;;;;;;OAUG;IACH,gBATW,KAAK,GAAC,aAAa,QACnB,MAAM,aACN,OAAO,YAAC,qBACR,MAAM,YAAC,cACP,OAAO,YAAC,kBACR,MAAM,YAAC,+BAiHjB;IA4BD;;;;;MAKE;IACF,0CAHU,MAAM,GACJ,OAAO,CAIlB;IAGD,yDA6BC;IAED,qFAOC;;CACF;wBApRY,OAAO,0BAA0B,EAAE,SAAS;8BAT3B,4BAA4B"}
@@ -1 +1 @@
1
- {"version":3,"file":"cast-error.d.ts","sourceRoot":"","sources":["../../../../../src/features/jserrors/shared/cast-error.js"],"names":[],"mappings":"AAMA;;;;;KAKK;AACL,iCAHa,GAAG,GACD,KAAK,GAAC,aAAa,CAmBjC;AAED;;;;KAIK;AACL,uEAFe,KAAK,CAwBnB;AAED;;;;KAIK;AACL,2CAHa,UAAU,GACR,KAAK,GAAC,aAAa,CAUjC;8BArE6B,kBAAkB"}
1
+ {"version":3,"file":"cast-error.d.ts","sourceRoot":"","sources":["../../../../../src/features/jserrors/shared/cast-error.js"],"names":[],"mappings":"AAMA;;;;;KAKK;AACL,iCAHa,GAAG,GACD,KAAK,GAAC,aAAa,CAoBjC;AAED;;;;KAIK;AACL,uEAFe,KAAK,CAwBnB;AAED;;;;KAIK;AACL,2CAHa,UAAU,GACR,KAAK,GAAC,aAAa,CAUjC;8BAtE6B,kBAAkB"}
@@ -31,6 +31,15 @@ export class Aggregate extends AggregateBase {
31
31
  payload: undefined;
32
32
  }[] | undefined;
33
33
  getCorrectedTimestamp(node: any): any;
34
+ /**
35
+ * returns the timestamps for the earliest and latest nodes in the provided array, even if out of order
36
+ * @param {Object[]} [nodes] - the nodes to evaluate
37
+ * @returns {{ firstEvent: Object|undefined, lastEvent: Object|undefined }} - the earliest and latest nodes. Defaults to undefined if no nodes are provided or if no timestamps are found in the nodes.
38
+ */
39
+ getFirstAndLastNodes(nodes?: Object[]): {
40
+ firstEvent: Object | undefined;
41
+ lastEvent: Object | undefined;
42
+ };
34
43
  getHarvestContents(recorderEvents: any): {
35
44
  qs: {
36
45
  browser_monitoring_key: any;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/aggregate/index.js"],"names":[],"mappings":"AAyBA;IACE,2BAAiC;IAIjC,sCAsFC;IAzFD,aAAe;IAKb,iFAAiF;IACjF,qBAAwB;IAGxB,2CAA2C;IAC3C,sDAAwB;IACxB,6CAA6C;IAC7C,gDAAmB;IAEnB,0BAA0B;IAC1B,kBAAqB;IACrB,6CAA6C;IAC7C,gBAA2B;IAE3B,cAA8B;IAC9B,kBAA+C;IAG/C,kCAAqG;IAoEvG,0BAEC;IAED,0BAMC;IAED,qBAUC;IAED;;;;;OAKG;IACH,4BAJW,OAAO,iBACP,OAAO,GACL,IAAI,CAuDhB;IAED,2BASC;IAED;;;oBAuDC;IAED,sCAIC;IAED;;;;;;;;;;MAuEC;IAED,sCAKC;IAED;;;;OAIG;IACH,mCAKC;IAED,yDAAyD;IACzD,+CASC;IAED,yCAIC;CACF;8BAxX6B,4BAA4B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/aggregate/index.js"],"names":[],"mappings":"AAyBA;IACE,2BAAiC;IAIjC,sCAsFC;IAzFD,aAAe;IAKb,iFAAiF;IACjF,qBAAwB;IAGxB,2CAA2C;IAC3C,sDAAwB;IACxB,6CAA6C;IAC7C,gDAAmB;IAEnB,0BAA0B;IAC1B,kBAAqB;IACrB,6CAA6C;IAC7C,gBAA2B;IAE3B,cAA8B;IAC9B,kBAA+C;IAG/C,kCAAqG;IAoEvG,0BAEC;IAED,0BAMC;IAED,qBAUC;IAED;;;;;OAKG;IACH,4BAJW,OAAO,iBACP,OAAO,GACL,IAAI,CAuDhB;IAED,2BASC;IAED;;;oBAuDC;IAED,sCAIC;IAED;;;;OAIG;IACH,6BAHW,MAAM,EAAE,GACN;QAAE,UAAU,EAAE,MAAM,GAAC,SAAS,CAAC;QAAC,SAAS,EAAE,MAAM,GAAC,SAAS,CAAA;KAAE,CAUzE;IAED;;;;;;;;;;MAsEC;IAED,sCAKC;IAED;;;;OAIG;IACH,mCAKC;IAED,yDAAyD;IACzD,+CASC;IAED,yCAIC;CACF;8BAtY6B,4BAA4B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newrelic/browser-agent",
3
- "version": "1.294.0-rc.1",
3
+ "version": "1.294.0-rc.3",
4
4
  "private": false,
5
5
  "author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
6
6
  "description": "New Relic Browser Agent",
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Copyright 2020-2025 New Relic, Inc. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ * @fileoverview; Extracts the cause string from an error object.
5
+ */
6
+
7
+ import { stringify } from '../../../common/util/stringify'
8
+ import { computeStackTrace } from './compute-stack-trace'
9
+
10
+ /**
11
+ * Extracts and normalizes a string from an error instance with a cause attribute.
12
+ * @param {Error} err - The error object to extract the cause from.
13
+ * @returns {string} The cause string extracted from the error object. Will be an empty string if no cause is present.
14
+ */
15
+ export function buildCauseString (err) {
16
+ let causeStackString = ''
17
+ if (!err?.cause) return causeStackString
18
+ if (err.cause instanceof Error) {
19
+ const stackInfo = computeStackTrace(err.cause)
20
+ causeStackString = stackInfo.stackString || err.cause.stack
21
+ if (stackInfo.message && !causeStackString.includes(stackInfo.message)) causeStackString = stackInfo.message + '\n' + causeStackString
22
+ if (stackInfo.name && !causeStackString.includes(stackInfo.name)) causeStackString = stackInfo.name + ': ' + causeStackString
23
+ } else causeStackString = typeof err.cause === 'string' ? err.cause : stringify(err.cause)
24
+ causeStackString ||= err.cause.toString() // fallback to try the string representation if all else fails
25
+ return causeStackString
26
+ }
@@ -21,6 +21,7 @@ import { applyFnToProps } from '../../../common/util/traverse'
21
21
  import { evaluateInternalError } from './internal-errors'
22
22
  import { isContainerAgentTarget } from '../../../common/util/target'
23
23
  import { warn } from '../../../common/util/console'
24
+ import { buildCauseString } from './cause-string'
24
25
 
25
26
  /**
26
27
  * @typedef {import('./compute-stack-trace.js').StackInfo} StackInfo
@@ -140,10 +141,13 @@ export class Aggregate extends AggregateBase {
140
141
 
141
142
  var canonicalStackString = this.buildCanonicalStackString(stackInfo)
142
143
 
144
+ const causeStackString = buildCauseString(err)
145
+
143
146
  const params = {
144
147
  stackHash: stringHashCode(canonicalStackString),
145
148
  exceptionClass: stackInfo.name,
146
- request_uri: globalScope?.location.pathname
149
+ request_uri: globalScope?.location.pathname,
150
+ ...(causeStackString && { cause: causeStackString })
147
151
  }
148
152
  if (stackInfo.message) params.message = '' + stackInfo.message
149
153
  // Notice if filterOutput isn't false|undefined OR our specified object, this func would've returned already (so it's unnecessary to req-check group).
@@ -25,7 +25,8 @@ export function castError (error) {
25
25
  error?.filename || error?.sourceURL,
26
26
  error?.lineno || error?.line,
27
27
  error?.colno || error?.col,
28
- error?.__newrelic
28
+ error?.__newrelic,
29
+ error?.cause
29
30
  )
30
31
  }
31
32
 
@@ -65,7 +66,7 @@ export function castPromiseRejectionEvent (promiseRejectionEvent) {
65
66
  */
66
67
  export function castErrorEvent (errorEvent) {
67
68
  if (errorEvent.error instanceof SyntaxError && !/:\d+$/.test(errorEvent.error.stack?.trim())) {
68
- const error = new UncaughtError(errorEvent.message, errorEvent.filename, errorEvent.lineno, errorEvent.colno, errorEvent.error.__newrelic)
69
+ const error = new UncaughtError(errorEvent.message, errorEvent.filename, errorEvent.lineno, errorEvent.colno, errorEvent.error.__newrelic, errorEvent.cause)
69
70
  error.name = SyntaxError.name
70
71
  return error
71
72
  }
@@ -275,6 +275,21 @@ export class Aggregate extends AggregateBase {
275
275
  return this.timeKeeper.correctAbsoluteTimestamp(node.timestamp)
276
276
  }
277
277
 
278
+ /**
279
+ * returns the timestamps for the earliest and latest nodes in the provided array, even if out of order
280
+ * @param {Object[]} [nodes] - the nodes to evaluate
281
+ * @returns {{ firstEvent: Object|undefined, lastEvent: Object|undefined }} - the earliest and latest nodes. Defaults to undefined if no nodes are provided or if no timestamps are found in the nodes.
282
+ */
283
+ getFirstAndLastNodes (nodes = []) {
284
+ const output = { firstEvent: nodes[0], lastEvent: nodes[nodes.length - 1] }
285
+ nodes.forEach(node => {
286
+ const timestamp = node?.timestamp
287
+ if (!output.firstEvent?.timestamp || (timestamp || Infinity) < output.firstEvent.timestamp) output.firstEvent = node
288
+ if (!output.lastEvent?.timestamp || (timestamp || -Infinity) > output.lastEvent.timestamp) output.lastEvent = node
289
+ })
290
+ return output
291
+ }
292
+
278
293
  getHarvestContents (recorderEvents) {
279
294
  recorderEvents ??= this.recorder.getEvents()
280
295
  let events = recorderEvents.events
@@ -301,11 +316,10 @@ export class Aggregate extends AggregateBase {
301
316
 
302
317
  const relativeNow = now()
303
318
 
304
- const firstEventTimestamp = this.getCorrectedTimestamp(events[0]) // from rrweb node
305
- const lastEventTimestamp = this.getCorrectedTimestamp(events[events.length - 1]) // from rrweb node
319
+ const { firstEvent, lastEvent } = this.getFirstAndLastNodes(events)
306
320
  // from rrweb node || from when the harvest cycle started
307
- const firstTimestamp = firstEventTimestamp || Math.floor(this.timeKeeper.correctAbsoluteTimestamp(recorderEvents.cycleTimestamp))
308
- const lastTimestamp = lastEventTimestamp || Math.floor(this.timeKeeper.correctRelativeTimestamp(relativeNow))
321
+ const firstTimestamp = this.getCorrectedTimestamp(firstEvent) || Math.floor(this.timeKeeper.correctAbsoluteTimestamp(recorderEvents.cycleTimestamp))
322
+ const lastTimestamp = this.getCorrectedTimestamp(lastEvent) || Math.floor(this.timeKeeper.correctRelativeTimestamp(relativeNow))
309
323
 
310
324
  const agentMetadata = agentRuntime.appMetadata?.agents?.[0] || {}
311
325