@newrelic/browser-agent 1.268.0 → 1.269.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +2 -1
  3. package/dist/cjs/common/constants/env.cdn.js +1 -1
  4. package/dist/cjs/common/constants/env.npm.js +1 -1
  5. package/dist/cjs/features/jserrors/aggregate/index.js +21 -1
  6. package/dist/cjs/features/jserrors/aggregate/internal-errors.js +42 -0
  7. package/dist/cjs/features/logging/aggregate/index.js +9 -1
  8. package/dist/cjs/features/session_trace/aggregate/index.js +5 -5
  9. package/dist/cjs/features/spa/instrument/index.js +4 -0
  10. package/dist/cjs/loaders/agent-base.js +1 -0
  11. package/dist/cjs/loaders/micro-agent.js +1 -1
  12. package/dist/esm/common/constants/env.cdn.js +1 -1
  13. package/dist/esm/common/constants/env.npm.js +1 -1
  14. package/dist/esm/features/jserrors/aggregate/index.js +21 -1
  15. package/dist/esm/features/jserrors/aggregate/internal-errors.js +36 -0
  16. package/dist/esm/features/logging/aggregate/index.js +9 -1
  17. package/dist/esm/features/session_trace/aggregate/index.js +5 -5
  18. package/dist/esm/features/spa/instrument/index.js +4 -0
  19. package/dist/esm/loaders/agent-base.js +1 -0
  20. package/dist/esm/loaders/micro-agent.js +1 -1
  21. package/dist/types/features/jserrors/aggregate/index.d.ts +10 -1
  22. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  23. package/dist/types/features/jserrors/aggregate/internal-errors.d.ts +7 -0
  24. package/dist/types/features/jserrors/aggregate/internal-errors.d.ts.map +1 -0
  25. package/dist/types/features/logging/aggregate/index.d.ts +3 -0
  26. package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
  27. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  28. package/dist/types/features/spa/instrument/index.d.ts +3 -0
  29. package/dist/types/features/spa/instrument/index.d.ts.map +1 -1
  30. package/dist/types/loaders/agent-base.d.ts +1 -0
  31. package/dist/types/loaders/agent-base.d.ts.map +1 -1
  32. package/dist/types/loaders/micro-agent.d.ts.map +1 -1
  33. package/package.json +1 -1
  34. package/src/features/jserrors/aggregate/index.js +19 -1
  35. package/src/features/jserrors/aggregate/internal-errors.js +33 -0
  36. package/src/features/logging/aggregate/index.js +8 -1
  37. package/src/features/session_trace/aggregate/index.js +6 -6
  38. package/src/features/spa/instrument/index.js +3 -0
  39. package/src/loaders/agent-base.js +1 -0
  40. package/src/loaders/micro-agent.js +2 -1
package/CHANGELOG.md CHANGED
@@ -3,6 +3,20 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.269.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.268.0...v1.269.0) (2024-10-16)
7
+
8
+
9
+ ### Features
10
+
11
+ * Add instrumentation metadata to logging ([#1208](https://github.com/newrelic/newrelic-browser-agent/issues/1208)) ([6926474](https://github.com/newrelic/newrelic-browser-agent/commit/6926474fe2530475e10daab2bb6bad745bb547e1))
12
+ * Include logging feature in micro agent loader ([#1210](https://github.com/newrelic/newrelic-browser-agent/issues/1210)) ([1b24484](https://github.com/newrelic/newrelic-browser-agent/commit/1b2448498cf285f36530f2107cb0403401958b1f))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * Handle Session Replay Security Policy Errors ([#1215](https://github.com/newrelic/newrelic-browser-agent/issues/1215)) ([f14b0fe](https://github.com/newrelic/newrelic-browser-agent/commit/f14b0fec81d7d21b418b6be6c5d415bdd813eca9))
18
+ * Only ever allow session traces to capture page load timings once ([#1212](https://github.com/newrelic/newrelic-browser-agent/issues/1212)) ([d189686](https://github.com/newrelic/newrelic-browser-agent/commit/d1896869858eca3320144113e168f17f524f3119))
19
+
6
20
  ## [1.268.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.267.0...v1.268.0) (2024-10-08)
7
21
 
8
22
 
package/README.md CHANGED
@@ -238,7 +238,8 @@ A lot of new frameworks support the concept of server-side rendering the pages o
238
238
 
239
239
  ## Disclaimers
240
240
 
241
- The session replay library shipping as part of the browser agent is not turned on by default. For information on the use of this feature, see [Session Replay](#session-replay)
241
+ * The session replay feature is not turned on by default. For information on the use of this feature, see [Session Replay](#session-replay)
242
+ * As part of the improvement efforts around our SPA capabilities, the `createTracer` API has been [deprecated](https://docs.newrelic.com/eol/2024/04/eol-04-24-24-createtracer/). Please engage in removing usage of that library. If tracking task duration, we recommend utilizing the generic browser performance mark and measure APIs, which will gain native detection support from the agent in a future update.
242
243
 
243
244
  ## Support
244
245
 
@@ -12,7 +12,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
12
12
  /**
13
13
  * Exposes the version of the agent
14
14
  */
15
- const VERSION = exports.VERSION = "1.268.0";
15
+ const VERSION = exports.VERSION = "1.269.0";
16
16
 
17
17
  /**
18
18
  * Exposes the build type of the agent
@@ -12,7 +12,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
12
12
  /**
13
13
  * Exposes the version of the agent
14
14
  */
15
- const VERSION = exports.VERSION = "1.268.0";
15
+ const VERSION = exports.VERSION = "1.269.0";
16
16
 
17
17
  /**
18
18
  * Exposes the build type of the agent
@@ -23,6 +23,8 @@ var _nreum = require("../../../common/window/nreum");
23
23
  var _drain = require("../../../common/drain/drain");
24
24
  var _now = require("../../../common/timing/now");
25
25
  var _traverse = require("../../../common/util/traverse");
26
+ var _internalErrors = require("./internal-errors");
27
+ var _constants2 = require("../../metrics/constants");
26
28
  /*
27
29
  * Copyright 2020 New Relic Corporation. All rights reserved.
28
30
  * SPDX-License-Identifier: Apache-2.0
@@ -130,6 +132,16 @@ class Aggregate extends _aggregateBase.AggregateBase {
130
132
  }
131
133
  return canonicalStackString;
132
134
  }
135
+
136
+ /**
137
+ *
138
+ * @param {Error|UncaughtError} err The error instance to be processed
139
+ * @param {number} time the relative ms (to origin) timestamp of occurence
140
+ * @param {boolean=} internal if the error was "caught" and deemed "internal" before reporting to the jserrors feature
141
+ * @param {object=} customAttributes any custom attributes to be included in the error payload
142
+ * @param {boolean=} hasReplay a flag indicating if the error occurred during a replay session
143
+ * @returns
144
+ */
133
145
  storeError(err, time, internal, customAttributes, hasReplay) {
134
146
  if (!err) return;
135
147
  // are we in an interaction
@@ -146,6 +158,14 @@ class Aggregate extends _aggregateBase.AggregateBase {
146
158
  // Again as with previous usage, all falsey values would include the error.
147
159
  }
148
160
  var stackInfo = (0, _computeStackTrace.computeStackTrace)(err);
161
+ const {
162
+ shouldSwallow,
163
+ reason
164
+ } = (0, _internalErrors.evaluateInternalError)(stackInfo, internal);
165
+ if (shouldSwallow) {
166
+ (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Internal/Error/' + reason], undefined, _features.FEATURE_NAMES.metrics, this.ee);
167
+ return;
168
+ }
149
169
  var canonicalStackString = this.buildCanonicalStackString(stackInfo);
150
170
  const params = {
151
171
  stackHash: (0, _stringHashCode.stringHashCode)(canonicalStackString),
@@ -184,7 +204,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
184
204
  }
185
205
  params.firstOccurrenceTimestamp = this.observedAt[bucketHash];
186
206
  params.timestamp = Math.floor(agentRuntime.timeKeeper.correctRelativeTimestamp(time));
187
- var type = internal ? 'ierr' : 'err';
207
+ var type = 'err';
188
208
  var newMetrics = {
189
209
  time
190
210
  };
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.evaluateInternalError = evaluateInternalError;
7
+ const REASON_RRWEB = 'Rrweb';
8
+ const REASON_SECURITY_POLICY = 'Security-Policy';
9
+ /**
10
+ * This function is responsible for determining if an error should be swallowed or not.
11
+ * @param {Object} stackInfo - The error stack information.
12
+ * @returns {boolean} - Whether the error should be swallowed or not.
13
+ */
14
+ function evaluateInternalError(stackInfo, internal) {
15
+ const output = {
16
+ shouldSwallow: internal || false,
17
+ reason: 'Other'
18
+ };
19
+ const leadingFrame = stackInfo.frames?.[0];
20
+ /** If we cant otherwise determine from the frames and message, the default of internal + reason will be the fallback */
21
+ if (!leadingFrame || typeof stackInfo?.message !== 'string') return output;
22
+
23
+ // check if the error happened in expected modules or if messages match known patterns
24
+ const isNrRecorder = leadingFrame?.url?.match(/nr-(.*)-recorder.min.js/);
25
+ const isRrweb = leadingFrame?.url?.match(/rrweb/);
26
+ const isMaybeNrRecorder = leadingFrame?.url?.match(/recorder/);
27
+ const isSecurityPolicyAPIError = stackInfo.message.toLowerCase().match(/an attempt was made to break through the security policy of the user agent/);
28
+
29
+ // check if modules and patterns above fit known swallow cases
30
+ if (!!isNrRecorder || !!isRrweb) {
31
+ /** We know -for sure- that the error came from our recorder module or rrweb directly if these are true, so swallow it */
32
+ output.shouldSwallow = true;
33
+ output.reason = REASON_RRWEB;
34
+ if (isSecurityPolicyAPIError) output.reason += '-' + REASON_SECURITY_POLICY;
35
+ } else if (!!isMaybeNrRecorder && isSecurityPolicyAPIError) {
36
+ /** We -suspect- that the error came from NR, so if it matches the exact case we know about, swallow it */
37
+ output.shouldSwallow = true;
38
+ output.reason = REASON_RRWEB + '-' + REASON_SECURITY_POLICY;
39
+ }
40
+ // other swallow conditions could also be added here
41
+ return output;
42
+ }
@@ -84,6 +84,12 @@ class Aggregate extends _aggregateBase.AggregateBase {
84
84
  }
85
85
  prepareHarvest(options = {}) {
86
86
  if (this.blocked || !this.bufferedLogs.hasData) return;
87
+ /** These attributes are evaluated and dropped at ingest processing time and do not get stored on NRDB */
88
+ const unbilledAttributes = {
89
+ 'instrumentation.provider': 'browser',
90
+ 'instrumentation.version': this.#agentRuntime.version,
91
+ 'instrumentation.name': this.#agentRuntime.loaderType
92
+ };
87
93
  /** see https://source.datanerd.us/agents/rum-specs/blob/main/browser/Log for logging spec */
88
94
  const payload = {
89
95
  qs: {
@@ -107,7 +113,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
107
113
  // Application ID from info object,
108
114
  standalone: Boolean(this.#agentInfo.sa),
109
115
  // copy paste (true) vs APM (false)
110
- agentVersion: this.#agentRuntime.version // browser agent version
116
+ agentVersion: this.#agentRuntime.version,
117
+ // browser agent version,
118
+ ...unbilledAttributes
111
119
  }
112
120
  },
113
121
  /** logs section contains individual unique log entries */
@@ -66,6 +66,11 @@ class Aggregate extends _aggregateBase.AggregateBase {
66
66
  // if another page's session entity has expired, or another page has transitioned to off and this one hasn't... we can just abort straight away here
67
67
  if (this.sessionId !== sessionState.value || eventType === 'cross-tab' && this.scheduler?.started && sessionState.sessionTraceMode === _constants2.MODE.OFF) this.abort(2);
68
68
  });
69
+ if (typeof PerformanceNavigationTiming !== 'undefined') {
70
+ this.traceStorage.storeTiming(_runtime2.globalScope.performance?.getEntriesByType?.('navigation')[0]);
71
+ } else {
72
+ this.traceStorage.storeTiming(_runtime2.globalScope.performance?.timing, true);
73
+ }
69
74
  }
70
75
 
71
76
  /** ST/SR sampling flow in BCS - https://drive.google.com/file/d/19hwt2oft-8Hh4RrjpLqEXfpP_9wYBLcq/view?usp=sharing */
@@ -91,11 +96,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
91
96
  (0, _registerHandler.registerHandler)('bstApi', (...args) => this.traceStorage.storeSTN(...args), this.featureName, this.ee);
92
97
  (0, _registerHandler.registerHandler)('trace-jserror', (...args) => this.traceStorage.storeErrorAgg(...args), this.featureName, this.ee);
93
98
  (0, _registerHandler.registerHandler)('pvtAdded', (...args) => this.traceStorage.processPVT(...args), this.featureName, this.ee);
94
- if (typeof PerformanceNavigationTiming !== 'undefined') {
95
- this.traceStorage.storeTiming(_runtime2.globalScope.performance?.getEntriesByType?.('navigation')[0]);
96
- } else {
97
- this.traceStorage.storeTiming(_runtime2.globalScope.performance?.timing, true);
98
- }
99
99
 
100
100
  /** Only start actually harvesting if running in full mode at init time */
101
101
  if (this.mode === _constants2.MODE.FULL) this.startHarvesting();else {
@@ -36,6 +36,10 @@ const {
36
36
  CB_START,
37
37
  FN_END
38
38
  } = CONSTANTS;
39
+
40
+ /**
41
+ * @deprecated This feature has been deprecated, in favor of `soft_navigations`, which is in limited preview. Consider using/importing `SoftNavigations` instead. To gain access to the limited preview, please see https://docs.newrelic.com/docs/browser/single-page-app-monitoring/get-started/browser-spa-v2/ for more information. This feature will be removed in a future release.
42
+ */
39
43
  class Instrument extends _instrumentBase.InstrumentBase {
40
44
  static featureName = FEATURE_NAME;
41
45
  constructor(agentIdentifier, aggregator, auto = true) {
@@ -176,6 +176,7 @@ class AgentBase {
176
176
  * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/interaction/}
177
177
  * @returns {InteractionInstance} An API object that is bound to a specific BrowserInteraction event. Each time this method is called for the same BrowserInteraction, a new object is created, but it still references the same interaction.
178
178
  * - Note: Does not apply to MicroAgent
179
+ * - Deprecation Notice: interaction.createTracer is deprecated. See https://docs.newrelic.com/eol/2024/04/eol-04-24-24-createtracer/ for more information.
179
180
  */
180
181
  interaction() {
181
182
  return this.#callMethod('interaction');
@@ -20,7 +20,7 @@ var _agentBase = require("./agent-base");
20
20
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
21
21
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } // loader files
22
22
  // core files
23
- const nonAutoFeatures = [_features.FEATURE_NAMES.jserrors, _features.FEATURE_NAMES.genericEvents, _features.FEATURE_NAMES.metrics];
23
+ const nonAutoFeatures = [_features.FEATURE_NAMES.jserrors, _features.FEATURE_NAMES.genericEvents, _features.FEATURE_NAMES.metrics, _features.FEATURE_NAMES.logging];
24
24
 
25
25
  /**
26
26
  * A minimal agent class designed to only respond to manual user input. As such, this class does not
@@ -6,7 +6,7 @@
6
6
  /**
7
7
  * Exposes the version of the agent
8
8
  */
9
- export const VERSION = "1.268.0";
9
+ export const VERSION = "1.269.0";
10
10
 
11
11
  /**
12
12
  * Exposes the build type of the agent
@@ -6,7 +6,7 @@
6
6
  /**
7
7
  * Exposes the version of the agent
8
8
  */
9
- export const VERSION = "1.268.0";
9
+ export const VERSION = "1.269.0";
10
10
 
11
11
  /**
12
12
  * Exposes the build type of the agent
@@ -22,6 +22,8 @@ import { getNREUMInitializedAgent } from '../../../common/window/nreum';
22
22
  import { deregisterDrain } from '../../../common/drain/drain';
23
23
  import { now } from '../../../common/timing/now';
24
24
  import { applyFnToProps } from '../../../common/util/traverse';
25
+ import { evaluateInternalError } from './internal-errors';
26
+ import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants';
25
27
 
26
28
  /**
27
29
  * @typedef {import('./compute-stack-trace.js').StackInfo} StackInfo
@@ -125,6 +127,16 @@ export class Aggregate extends AggregateBase {
125
127
  }
126
128
  return canonicalStackString;
127
129
  }
130
+
131
+ /**
132
+ *
133
+ * @param {Error|UncaughtError} err The error instance to be processed
134
+ * @param {number} time the relative ms (to origin) timestamp of occurence
135
+ * @param {boolean=} internal if the error was "caught" and deemed "internal" before reporting to the jserrors feature
136
+ * @param {object=} customAttributes any custom attributes to be included in the error payload
137
+ * @param {boolean=} hasReplay a flag indicating if the error occurred during a replay session
138
+ * @returns
139
+ */
128
140
  storeError(err, time, internal, customAttributes, hasReplay) {
129
141
  if (!err) return;
130
142
  // are we in an interaction
@@ -141,6 +153,14 @@ export class Aggregate extends AggregateBase {
141
153
  // Again as with previous usage, all falsey values would include the error.
142
154
  }
143
155
  var stackInfo = computeStackTrace(err);
156
+ const {
157
+ shouldSwallow,
158
+ reason
159
+ } = evaluateInternalError(stackInfo, internal);
160
+ if (shouldSwallow) {
161
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['Internal/Error/' + reason], undefined, FEATURE_NAMES.metrics, this.ee);
162
+ return;
163
+ }
144
164
  var canonicalStackString = this.buildCanonicalStackString(stackInfo);
145
165
  const params = {
146
166
  stackHash: stringHashCode(canonicalStackString),
@@ -179,7 +199,7 @@ export class Aggregate extends AggregateBase {
179
199
  }
180
200
  params.firstOccurrenceTimestamp = this.observedAt[bucketHash];
181
201
  params.timestamp = Math.floor(agentRuntime.timeKeeper.correctRelativeTimestamp(time));
182
- var type = internal ? 'ierr' : 'err';
202
+ var type = 'err';
183
203
  var newMetrics = {
184
204
  time
185
205
  };
@@ -0,0 +1,36 @@
1
+ const REASON_RRWEB = 'Rrweb';
2
+ const REASON_SECURITY_POLICY = 'Security-Policy';
3
+ /**
4
+ * This function is responsible for determining if an error should be swallowed or not.
5
+ * @param {Object} stackInfo - The error stack information.
6
+ * @returns {boolean} - Whether the error should be swallowed or not.
7
+ */
8
+ export function evaluateInternalError(stackInfo, internal) {
9
+ const output = {
10
+ shouldSwallow: internal || false,
11
+ reason: 'Other'
12
+ };
13
+ const leadingFrame = stackInfo.frames?.[0];
14
+ /** If we cant otherwise determine from the frames and message, the default of internal + reason will be the fallback */
15
+ if (!leadingFrame || typeof stackInfo?.message !== 'string') return output;
16
+
17
+ // check if the error happened in expected modules or if messages match known patterns
18
+ const isNrRecorder = leadingFrame?.url?.match(/nr-(.*)-recorder.min.js/);
19
+ const isRrweb = leadingFrame?.url?.match(/rrweb/);
20
+ const isMaybeNrRecorder = leadingFrame?.url?.match(/recorder/);
21
+ const isSecurityPolicyAPIError = stackInfo.message.toLowerCase().match(/an attempt was made to break through the security policy of the user agent/);
22
+
23
+ // check if modules and patterns above fit known swallow cases
24
+ if (!!isNrRecorder || !!isRrweb) {
25
+ /** We know -for sure- that the error came from our recorder module or rrweb directly if these are true, so swallow it */
26
+ output.shouldSwallow = true;
27
+ output.reason = REASON_RRWEB;
28
+ if (isSecurityPolicyAPIError) output.reason += '-' + REASON_SECURITY_POLICY;
29
+ } else if (!!isMaybeNrRecorder && isSecurityPolicyAPIError) {
30
+ /** We -suspect- that the error came from NR, so if it matches the exact case we know about, swallow it */
31
+ output.shouldSwallow = true;
32
+ output.reason = REASON_RRWEB + '-' + REASON_SECURITY_POLICY;
33
+ }
34
+ // other swallow conditions could also be added here
35
+ return output;
36
+ }
@@ -78,6 +78,12 @@ export class Aggregate extends AggregateBase {
78
78
  }
79
79
  prepareHarvest(options = {}) {
80
80
  if (this.blocked || !this.bufferedLogs.hasData) return;
81
+ /** These attributes are evaluated and dropped at ingest processing time and do not get stored on NRDB */
82
+ const unbilledAttributes = {
83
+ 'instrumentation.provider': 'browser',
84
+ 'instrumentation.version': this.#agentRuntime.version,
85
+ 'instrumentation.name': this.#agentRuntime.loaderType
86
+ };
81
87
  /** see https://source.datanerd.us/agents/rum-specs/blob/main/browser/Log for logging spec */
82
88
  const payload = {
83
89
  qs: {
@@ -101,7 +107,9 @@ export class Aggregate extends AggregateBase {
101
107
  // Application ID from info object,
102
108
  standalone: Boolean(this.#agentInfo.sa),
103
109
  // copy paste (true) vs APM (false)
104
- agentVersion: this.#agentRuntime.version // browser agent version
110
+ agentVersion: this.#agentRuntime.version,
111
+ // browser agent version,
112
+ ...unbilledAttributes
105
113
  }
106
114
  },
107
115
  /** logs section contains individual unique log entries */
@@ -60,6 +60,11 @@ export class Aggregate extends AggregateBase {
60
60
  // if another page's session entity has expired, or another page has transitioned to off and this one hasn't... we can just abort straight away here
61
61
  if (this.sessionId !== sessionState.value || eventType === 'cross-tab' && this.scheduler?.started && sessionState.sessionTraceMode === MODE.OFF) this.abort(2);
62
62
  });
63
+ if (typeof PerformanceNavigationTiming !== 'undefined') {
64
+ this.traceStorage.storeTiming(globalScope.performance?.getEntriesByType?.('navigation')[0]);
65
+ } else {
66
+ this.traceStorage.storeTiming(globalScope.performance?.timing, true);
67
+ }
63
68
  }
64
69
 
65
70
  /** ST/SR sampling flow in BCS - https://drive.google.com/file/d/19hwt2oft-8Hh4RrjpLqEXfpP_9wYBLcq/view?usp=sharing */
@@ -85,11 +90,6 @@ export class Aggregate extends AggregateBase {
85
90
  registerHandler('bstApi', (...args) => this.traceStorage.storeSTN(...args), this.featureName, this.ee);
86
91
  registerHandler('trace-jserror', (...args) => this.traceStorage.storeErrorAgg(...args), this.featureName, this.ee);
87
92
  registerHandler('pvtAdded', (...args) => this.traceStorage.processPVT(...args), this.featureName, this.ee);
88
- if (typeof PerformanceNavigationTiming !== 'undefined') {
89
- this.traceStorage.storeTiming(globalScope.performance?.getEntriesByType?.('navigation')[0]);
90
- } else {
91
- this.traceStorage.storeTiming(globalScope.performance?.timing, true);
92
- }
93
93
 
94
94
  /** Only start actually harvesting if running in full mode at init time */
95
95
  if (this.mode === MODE.FULL) this.startHarvesting();else {
@@ -27,6 +27,10 @@ const {
27
27
  CB_START,
28
28
  FN_END
29
29
  } = CONSTANTS;
30
+
31
+ /**
32
+ * @deprecated This feature has been deprecated, in favor of `soft_navigations`, which is in limited preview. Consider using/importing `SoftNavigations` instead. To gain access to the limited preview, please see https://docs.newrelic.com/docs/browser/single-page-app-monitoring/get-started/browser-spa-v2/ for more information. This feature will be removed in a future release.
33
+ */
30
34
  export class Instrument extends InstrumentBase {
31
35
  static featureName = FEATURE_NAME;
32
36
  constructor(agentIdentifier, aggregator, auto = true) {
@@ -171,6 +171,7 @@ export class AgentBase {
171
171
  * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/interaction/}
172
172
  * @returns {InteractionInstance} An API object that is bound to a specific BrowserInteraction event. Each time this method is called for the same BrowserInteraction, a new object is created, but it still references the same interaction.
173
173
  * - Note: Does not apply to MicroAgent
174
+ * - Deprecation Notice: interaction.createTracer is deprecated. See https://docs.newrelic.com/eol/2024/04/eol-04-24-24-createtracer/ for more information.
174
175
  */
175
176
  interaction() {
176
177
  return this.#callMethod('interaction');
@@ -13,7 +13,7 @@ import { FEATURE_NAMES } from './features/features';
13
13
  import { warn } from '../common/util/console';
14
14
  import { onWindowLoad } from '../common/window/load';
15
15
  import { AgentBase } from './agent-base';
16
- const nonAutoFeatures = [FEATURE_NAMES.jserrors, FEATURE_NAMES.genericEvents, FEATURE_NAMES.metrics];
16
+ const nonAutoFeatures = [FEATURE_NAMES.jserrors, FEATURE_NAMES.genericEvents, FEATURE_NAMES.metrics, FEATURE_NAMES.logging];
17
17
 
18
18
  /**
19
19
  * A minimal agent class designed to only respond to manual user input. As such, this class does not
@@ -25,7 +25,16 @@ export class Aggregate extends AggregateBase {
25
25
  * @returns {string} A canonical stack string built from the URLs and function names in the given `stackInfo` object.
26
26
  */
27
27
  buildCanonicalStackString(stackInfo: StackInfo): string;
28
- storeError(err: any, time: any, internal: any, customAttributes: any, hasReplay: any): void;
28
+ /**
29
+ *
30
+ * @param {Error|UncaughtError} err The error instance to be processed
31
+ * @param {number} time the relative ms (to origin) timestamp of occurence
32
+ * @param {boolean=} internal if the error was "caught" and deemed "internal" before reporting to the jserrors feature
33
+ * @param {object=} customAttributes any custom attributes to be included in the error payload
34
+ * @param {boolean=} hasReplay a flag indicating if the error occurred during a replay session
35
+ * @returns
36
+ */
37
+ storeError(err: Error | UncaughtError, time: number, internal?: boolean | undefined, customAttributes?: object | undefined, hasReplay?: boolean | undefined): void;
29
38
  onInteractionDone(interaction: any, wasSaved: any): void;
30
39
  onSoftNavNotification(interactionId: any, wasFinished: any, softNavAttrs: any): void;
31
40
  #private;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/jserrors/aggregate/index.js"],"names":[],"mappings":"AA2BA;;GAEG;AAEH;IACE,2BAAiC;IACjC,mDAgCC;IA7BC,kBAAuB;IACvB,eAAoB;IACpB,qBAA0B;IAC1B,2BAAgC;IAChC,uCAA4B;IAC5B,qBAAwB;IA0B1B;;;MA2BC;IAED,qCAWC;IAED,8BAEC;IAED,oEAMC;IAED;;;;;;OAMG;IACH,qCAHW,SAAS,GACP,MAAM,CAgBlB;IAED,4FA4FC;IA4BD,yDA6BC;IAED,qFAOC;;CAwBF;wBA1SY,OAAO,0BAA0B,EAAE,SAAS;8BAP3B,4BAA4B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/jserrors/aggregate/index.js"],"names":[],"mappings":"AA6BA;;GAEG;AAEH;IACE,2BAAiC;IACjC,mDAgCC;IA7BC,kBAAuB;IACvB,eAAoB;IACpB,qBAA0B;IAC1B,2BAAgC;IAChC,uCAA4B;IAC5B,qBAAwB;IA0B1B;;;MA2BC;IAED,qCAWC;IAED,8BAEC;IAED,oEAMC;IAED;;;;;;OAMG;IACH,qCAHW,SAAS,GACP,MAAM,CAgBlB;IAED;;;;;;;;OAQG;IACH,gBAPW,KAAK,GAAC,aAAa,QACnB,MAAM,aACN,OAAO,YAAC,qBACR,MAAM,YAAC,cACP,OAAO,YAAC,QAsGlB;IA4BD,yDA6BC;IAED,qFAOC;;CAwBF;wBA1TY,OAAO,0BAA0B,EAAE,SAAS;8BAT3B,4BAA4B"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * This function is responsible for determining if an error should be swallowed or not.
3
+ * @param {Object} stackInfo - The error stack information.
4
+ * @returns {boolean} - Whether the error should be swallowed or not.
5
+ */
6
+ export function evaluateInternalError(stackInfo: Object, internal: any): boolean;
7
+ //# sourceMappingURL=internal-errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal-errors.d.ts","sourceRoot":"","sources":["../../../../../src/features/jserrors/aggregate/internal-errors.js"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,iDAHW,MAAM,kBACJ,OAAO,CA2BnB"}
@@ -14,6 +14,9 @@ export class Aggregate extends AggregateBase {
14
14
  common: {
15
15
  /** Attributes in the `common` section are added to `all` logs generated in the payload */
16
16
  attributes: {
17
+ 'instrumentation.provider': string;
18
+ 'instrumentation.version': any;
19
+ 'instrumentation.name': any;
17
20
  'entity.guid': any;
18
21
  session: any;
19
22
  hasReplay: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/logging/aggregate/index.js"],"names":[],"mappings":"AAiBA;IACE,2BAAiC;IAGjC,mDAwBC;IArBC,+BAA+B;IAC/B,0BAAqC;IAKrC,wBAAmG;IAGjG,4BAKQ;IASZ,+EA6CC;IAED;;;;;;gBASQ,0FAA0F;;;;;;;;;;;;YAY5F,0DAA0D;;;kBAY/D;IAED,qCAGC;;CACF;8BA5H6B,4BAA4B;4BAM9B,0BAA0B;iCAVrB,2CAA2C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/logging/aggregate/index.js"],"names":[],"mappings":"AAiBA;IACE,2BAAiC;IAGjC,mDAwBC;IArBC,+BAA+B;IAC/B,0BAAqC;IAKrC,wBAAmG;IAGjG,4BAKQ;IASZ,+EA6CC;IAED;;;;;;gBAeQ,0FAA0F;;;;;;;;;;;;;;;YAa5F,0DAA0D;;;kBAY/D;IAED,qCAGC;;CACF;8BAnI6B,4BAA4B;4BAM9B,0BAA0B;iCAVrB,2CAA2C"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_trace/aggregate/index.js"],"names":[],"mappings":"AAkBA;IACE,2BAAiC;IAEjC,mDAmBC;IAjBC,kBAA+C;IAC/C,eAAyC;IAEzC,0FAA0F;IAC1F,wBAAqB;IACrB,wBAA0G;IAC1G,0GAA0G;IAC1G,cAAyB;IACzB,mIAAmI;IACnI,uBAA0B;IAC1B,0CAA0C;IAC1C,oBAAuB;IACvB,wIAAwI;IACxI,2BAA0C;IAM5C,gLAAgL;IAChL,mEAoEC;IA/DG,iCAAuB;IACvB,yJAAyJ;IACzJ,UAAkC;IAClC,eAAuD;IAmBD,UAA4D;IASpH,wCAKQ;IA6BV,kJAAkJ;IAClJ,wBAIC;IAED,iJAAiJ;IACjJ;;;;;;;;;;MA6DC;IAED;;OAEG;IACH,qCAKC;IAED,8DAA8D;IAC9D,qBAUC;IAED,2DAA2D;IAC3D,yBAKC;CACF;8BAhN6B,4BAA4B;6BAC7B,iBAAiB;iCANb,2CAA2C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_trace/aggregate/index.js"],"names":[],"mappings":"AAkBA;IACE,2BAAiC;IAEjC,mDAmBC;IAjBC,kBAA+C;IAC/C,eAAyC;IAEzC,0FAA0F;IAC1F,wBAAqB;IACrB,wBAA0G;IAC1G,0GAA0G;IAC1G,cAAyB;IACzB,mIAAmI;IACnI,uBAA0B;IAC1B,0CAA0C;IAC1C,oBAAuB;IACvB,wIAAwI;IACxI,2BAA0C;IAM5C,gLAAgL;IAChL,mEAoEC;IA/DG,iCAAuB;IACvB,yJAAyJ;IACzJ,UAAkC;IAClC,eAAuD;IAyBD,UAA4D;IASpH,wCAKQ;IAuBV,kJAAkJ;IAClJ,wBAIC;IAED,iJAAiJ;IACjJ;;;;;;;;;;MA6DC;IAED;;OAEG;IACH,qCAKC;IAED,8DAA8D;IAC9D,qBAUC;IAED,2DAA2D;IAC3D,yBAKC;CACF;8BAhN6B,4BAA4B;6BAC7B,iBAAiB;iCANb,2CAA2C"}
@@ -1,3 +1,6 @@
1
+ /**
2
+ * @deprecated This feature has been deprecated, in favor of `soft_navigations`, which is in limited preview. Consider using/importing `SoftNavigations` instead. To gain access to the limited preview, please see https://docs.newrelic.com/docs/browser/single-page-app-monitoring/get-started/browser-spa-v2/ for more information. This feature will be removed in a future release.
3
+ */
1
4
  export class Instrument extends InstrumentBase {
2
5
  static featureName: string;
3
6
  constructor(agentIdentifier: any, aggregator: any, auto?: boolean);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/spa/instrument/index.js"],"names":[],"mappings":"AAsBA;IACE,2BAAiC;IACjC,mEAsFC;IAjFG,2CAA0C;;CAwF/C;AAED,oCAA6B;+BAlHE,6BAA6B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/spa/instrument/index.js"],"names":[],"mappings":"AAsBA;;GAEG;AACH;IACE,2BAAiC;IACjC,mEAsFC;IAjFG,2CAA0C;;CAwF/C;AAED,oCAA6B;+BArHE,6BAA6B"}
@@ -118,6 +118,7 @@ export class AgentBase {
118
118
  * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/interaction/}
119
119
  * @returns {InteractionInstance} An API object that is bound to a specific BrowserInteraction event. Each time this method is called for the same BrowserInteraction, a new object is created, but it still references the same interaction.
120
120
  * - Note: Does not apply to MicroAgent
121
+ * - Deprecation Notice: interaction.createTracer is deprecated. See https://docs.newrelic.com/eol/2024/04/eol-04-24-24-createtracer/ for more information.
121
122
  */
122
123
  interaction(): InteractionInstance;
123
124
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"agent-base.d.ts","sourceRoot":"","sources":["../../../src/loaders/agent-base.js"],"names":[],"mappings":"AAMA;;GAEG;AAEH;IAGE,sCAEC;IAJD,wBAAe;IAgBf;;;;;OAKG;IACH,oBAHW,MAAM,wCAKhB;IAED;;;;;OAKG;IACH,sBAHW,MAAM,kCAKhB;IAED;;;;;;OAMG;IACH,yBAJW,MAAM,SACN,MAAM,GAAC,MAAM,GAAC,OAAO,GAAC,IAAI,sCAKpC;IAED;;;;;OAKG;IACH,mBAHW,KAAK,GAAC,MAAM,8CAKtB;IAED;;;;OAIG;IACH,iBAFW,MAAM,GAAC,IAAI,OAIrB;IAED;;;;;;;OAOG;IACH,6BAJW,MAAM,GAAC,IAAI,OAMrB;IAED;;;;OAIG;IACH,0BAFW,CAAC,KAAK,EAAE,KAAK,GAAC,MAAM,KAAK,OAAO,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,OAI9D;IAED;;;;OAIG;IACH,8CAEC;IAED;;;;;OAKG;IACH,iBAHW,MAAM,MACN,MAAM,OAIhB;IAED;;;;OAIG;IACH,yDAEC;IAED;;;;OAIG;IACH,oBAEC;IAED;;;;;OAKG;IACH,mBAEC;IAED;;;;;;;;;;OAUG;IACH,6BARW;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAC,OAUrF;IAED;;;;;OAKG;IACH,0BAHW,MAAM,OAKhB;IAED;;;;;MAKE;IACF,eAHa,mBAAmB,CAK/B;IAED;;;;;MAKE;IACF,aAHW,MAAM;2BACc,MAAM;gBAAU,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,MAAM,GAAC,MAAM;wBAInF;IAED;;;;;;MAME;IACF,mBAJW,MAAM,gBACN,MAAM;2BACc,MAAM;gBAAU,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,MAAM,GAAC,MAAM;wBAInF;;CACF;kCAjMY,OAAO,yBAAyB,EAAE,mBAAmB"}
1
+ {"version":3,"file":"agent-base.d.ts","sourceRoot":"","sources":["../../../src/loaders/agent-base.js"],"names":[],"mappings":"AAMA;;GAEG;AAEH;IAGE,sCAEC;IAJD,wBAAe;IAgBf;;;;;OAKG;IACH,oBAHW,MAAM,wCAKhB;IAED;;;;;OAKG;IACH,sBAHW,MAAM,kCAKhB;IAED;;;;;;OAMG;IACH,yBAJW,MAAM,SACN,MAAM,GAAC,MAAM,GAAC,OAAO,GAAC,IAAI,sCAKpC;IAED;;;;;OAKG;IACH,mBAHW,KAAK,GAAC,MAAM,8CAKtB;IAED;;;;OAIG;IACH,iBAFW,MAAM,GAAC,IAAI,OAIrB;IAED;;;;;;;OAOG;IACH,6BAJW,MAAM,GAAC,IAAI,OAMrB;IAED;;;;OAIG;IACH,0BAFW,CAAC,KAAK,EAAE,KAAK,GAAC,MAAM,KAAK,OAAO,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,OAI9D;IAED;;;;OAIG;IACH,8CAEC;IAED;;;;;OAKG;IACH,iBAHW,MAAM,MACN,MAAM,OAIhB;IAED;;;;OAIG;IACH,yDAEC;IAED;;;;OAIG;IACH,oBAEC;IAED;;;;;OAKG;IACH,mBAEC;IAED;;;;;;;;;;OAUG;IACH,6BARW;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAC,OAUrF;IAED;;;;;OAKG;IACH,0BAHW,MAAM,OAKhB;IAED;;;;;;MAME;IACF,eAJa,mBAAmB,CAM/B;IAED;;;;;MAKE;IACF,aAHW,MAAM;2BACc,MAAM;gBAAU,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,MAAM,GAAC,MAAM;wBAInF;IAED;;;;;;MAME;IACF,mBAJW,MAAM,gBACN,MAAM;2BACc,MAAM;gBAAU,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,MAAM,GAAC,MAAM;wBAInF;;CACF;kCAlMY,OAAO,yBAAyB,EAAE,mBAAmB"}
@@ -1 +1 @@
1
- {"version":3,"file":"micro-agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/micro-agent.js"],"names":[],"mappings":"AAsBA;;;;GAIG;AACH;IACE;;;OAGG;IACH,qBAHW,MAAM,oBACN,MAAM,YAAC,EAmBjB;IAdC,6BAAiF;IACjF,aAAkB;IAMlB;;;;OAIG;IACH,yCAA2C;IAI7C;;;;;MAOC;IAED,mCAyCC;CACF;0BAxFyB,cAAc;2BATb,gCAAgC"}
1
+ {"version":3,"file":"micro-agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/micro-agent.js"],"names":[],"mappings":"AAuBA;;;;GAIG;AACH;IACE;;;OAGG;IACH,qBAHW,MAAM,oBACN,MAAM,YAAC,EAmBjB;IAdC,6BAAiF;IACjF,aAAkB;IAMlB;;;;OAIG;IACH,yCAA2C;IAI7C;;;;;MAOC;IAED,mCAyCC;CACF;0BAzFyB,cAAc;2BATb,gCAAgC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newrelic/browser-agent",
3
- "version": "1.268.0",
3
+ "version": "1.269.0",
4
4
  "private": false,
5
5
  "author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
6
6
  "description": "New Relic Browser Agent",
@@ -24,6 +24,8 @@ import { getNREUMInitializedAgent } from '../../../common/window/nreum'
24
24
  import { deregisterDrain } from '../../../common/drain/drain'
25
25
  import { now } from '../../../common/timing/now'
26
26
  import { applyFnToProps } from '../../../common/util/traverse'
27
+ import { evaluateInternalError } from './internal-errors'
28
+ import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants'
27
29
 
28
30
  /**
29
31
  * @typedef {import('./compute-stack-trace.js').StackInfo} StackInfo
@@ -142,6 +144,15 @@ export class Aggregate extends AggregateBase {
142
144
  return canonicalStackString
143
145
  }
144
146
 
147
+ /**
148
+ *
149
+ * @param {Error|UncaughtError} err The error instance to be processed
150
+ * @param {number} time the relative ms (to origin) timestamp of occurence
151
+ * @param {boolean=} internal if the error was "caught" and deemed "internal" before reporting to the jserrors feature
152
+ * @param {object=} customAttributes any custom attributes to be included in the error payload
153
+ * @param {boolean=} hasReplay a flag indicating if the error occurred during a replay session
154
+ * @returns
155
+ */
145
156
  storeError (err, time, internal, customAttributes, hasReplay) {
146
157
  if (!err) return
147
158
  // are we in an interaction
@@ -160,6 +171,13 @@ export class Aggregate extends AggregateBase {
160
171
  }
161
172
 
162
173
  var stackInfo = computeStackTrace(err)
174
+
175
+ const { shouldSwallow, reason } = evaluateInternalError(stackInfo, internal)
176
+ if (shouldSwallow) {
177
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['Internal/Error/' + reason], undefined, FEATURE_NAMES.metrics, this.ee)
178
+ return
179
+ }
180
+
163
181
  var canonicalStackString = this.buildCanonicalStackString(stackInfo)
164
182
 
165
183
  const params = {
@@ -203,7 +221,7 @@ export class Aggregate extends AggregateBase {
203
221
  params.firstOccurrenceTimestamp = this.observedAt[bucketHash]
204
222
  params.timestamp = Math.floor(agentRuntime.timeKeeper.correctRelativeTimestamp(time))
205
223
 
206
- var type = internal ? 'ierr' : 'err'
224
+ var type = 'err'
207
225
  var newMetrics = { time }
208
226
 
209
227
  // Trace sends the error in its payload, and both trace & replay simply listens for any error to occur.
@@ -0,0 +1,33 @@
1
+ const REASON_RRWEB = 'Rrweb'
2
+ const REASON_SECURITY_POLICY = 'Security-Policy'
3
+ /**
4
+ * This function is responsible for determining if an error should be swallowed or not.
5
+ * @param {Object} stackInfo - The error stack information.
6
+ * @returns {boolean} - Whether the error should be swallowed or not.
7
+ */
8
+ export function evaluateInternalError (stackInfo, internal) {
9
+ const output = { shouldSwallow: internal || false, reason: 'Other' }
10
+ const leadingFrame = stackInfo.frames?.[0]
11
+ /** If we cant otherwise determine from the frames and message, the default of internal + reason will be the fallback */
12
+ if (!leadingFrame || typeof stackInfo?.message !== 'string') return output
13
+
14
+ // check if the error happened in expected modules or if messages match known patterns
15
+ const isNrRecorder = leadingFrame?.url?.match(/nr-(.*)-recorder.min.js/)
16
+ const isRrweb = leadingFrame?.url?.match(/rrweb/)
17
+ const isMaybeNrRecorder = leadingFrame?.url?.match(/recorder/)
18
+ const isSecurityPolicyAPIError = stackInfo.message.toLowerCase().match(/an attempt was made to break through the security policy of the user agent/)
19
+
20
+ // check if modules and patterns above fit known swallow cases
21
+ if (!!isNrRecorder || !!isRrweb) {
22
+ /** We know -for sure- that the error came from our recorder module or rrweb directly if these are true, so swallow it */
23
+ output.shouldSwallow = true
24
+ output.reason = REASON_RRWEB
25
+ if (isSecurityPolicyAPIError) output.reason += '-' + REASON_SECURITY_POLICY
26
+ } else if (!!isMaybeNrRecorder && isSecurityPolicyAPIError) {
27
+ /** We -suspect- that the error came from NR, so if it matches the exact case we know about, swallow it */
28
+ output.shouldSwallow = true
29
+ output.reason = REASON_RRWEB + '-' + REASON_SECURITY_POLICY
30
+ }
31
+ // other swallow conditions could also be added here
32
+ return output
33
+ }
@@ -94,6 +94,12 @@ export class Aggregate extends AggregateBase {
94
94
 
95
95
  prepareHarvest (options = {}) {
96
96
  if (this.blocked || !this.bufferedLogs.hasData) return
97
+ /** These attributes are evaluated and dropped at ingest processing time and do not get stored on NRDB */
98
+ const unbilledAttributes = {
99
+ 'instrumentation.provider': 'browser',
100
+ 'instrumentation.version': this.#agentRuntime.version,
101
+ 'instrumentation.name': this.#agentRuntime.loaderType
102
+ }
97
103
  /** see https://source.datanerd.us/agents/rum-specs/blob/main/browser/Log for logging spec */
98
104
  const payload = {
99
105
  qs: {
@@ -110,7 +116,8 @@ export class Aggregate extends AggregateBase {
110
116
  ptid: this.#agentRuntime.ptid, // page trace id
111
117
  appId: this.#agentInfo.applicationID, // Application ID from info object,
112
118
  standalone: Boolean(this.#agentInfo.sa), // copy paste (true) vs APM (false)
113
- agentVersion: this.#agentRuntime.version // browser agent version
119
+ agentVersion: this.#agentRuntime.version, // browser agent version,
120
+ ...unbilledAttributes
114
121
  }
115
122
  },
116
123
  /** logs section contains individual unique log entries */
@@ -64,6 +64,12 @@ export class Aggregate extends AggregateBase {
64
64
  // if another page's session entity has expired, or another page has transitioned to off and this one hasn't... we can just abort straight away here
65
65
  if (this.sessionId !== sessionState.value || (eventType === 'cross-tab' && this.scheduler?.started && sessionState.sessionTraceMode === MODE.OFF)) this.abort(2)
66
66
  })
67
+
68
+ if (typeof PerformanceNavigationTiming !== 'undefined') {
69
+ this.traceStorage.storeTiming(globalScope.performance?.getEntriesByType?.('navigation')[0])
70
+ } else {
71
+ this.traceStorage.storeTiming(globalScope.performance?.timing, true)
72
+ }
67
73
  }
68
74
 
69
75
  /** ST/SR sampling flow in BCS - https://drive.google.com/file/d/19hwt2oft-8Hh4RrjpLqEXfpP_9wYBLcq/view?usp=sharing */
@@ -93,12 +99,6 @@ export class Aggregate extends AggregateBase {
93
99
  registerHandler('trace-jserror', (...args) => this.traceStorage.storeErrorAgg(...args), this.featureName, this.ee)
94
100
  registerHandler('pvtAdded', (...args) => this.traceStorage.processPVT(...args), this.featureName, this.ee)
95
101
 
96
- if (typeof PerformanceNavigationTiming !== 'undefined') {
97
- this.traceStorage.storeTiming(globalScope.performance?.getEntriesByType?.('navigation')[0])
98
- } else {
99
- this.traceStorage.storeTiming(globalScope.performance?.timing, true)
100
- }
101
-
102
102
  /** Only start actually harvesting if running in full mode at init time */
103
103
  if (this.mode === MODE.FULL) this.startHarvesting()
104
104
  else {
@@ -20,6 +20,9 @@ const {
20
20
  FEATURE_NAME, START, END, BODY, CB_END, JS_TIME, FETCH, FN_START, CB_START, FN_END
21
21
  } = CONSTANTS
22
22
 
23
+ /**
24
+ * @deprecated This feature has been deprecated, in favor of `soft_navigations`, which is in limited preview. Consider using/importing `SoftNavigations` instead. To gain access to the limited preview, please see https://docs.newrelic.com/docs/browser/single-page-app-monitoring/get-started/browser-spa-v2/ for more information. This feature will be removed in a future release.
25
+ */
23
26
  export class Instrument extends InstrumentBase {
24
27
  static featureName = FEATURE_NAME
25
28
  constructor (agentIdentifier, aggregator, auto = true) {
@@ -173,6 +173,7 @@ export class AgentBase {
173
173
  * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/interaction/}
174
174
  * @returns {InteractionInstance} An API object that is bound to a specific BrowserInteraction event. Each time this method is called for the same BrowserInteraction, a new object is created, but it still references the same interaction.
175
175
  * - Note: Does not apply to MicroAgent
176
+ * - Deprecation Notice: interaction.createTracer is deprecated. See https://docs.newrelic.com/eol/2024/04/eol-04-24-24-createtracer/ for more information.
176
177
  */
177
178
  interaction () {
178
179
  return this.#callMethod('interaction')
@@ -17,7 +17,8 @@ import { AgentBase } from './agent-base'
17
17
  const nonAutoFeatures = [
18
18
  FEATURE_NAMES.jserrors,
19
19
  FEATURE_NAMES.genericEvents,
20
- FEATURE_NAMES.metrics
20
+ FEATURE_NAMES.metrics,
21
+ FEATURE_NAMES.logging
21
22
  ]
22
23
 
23
24
  /**