@newrelic/browser-agent 1.262.0 → 1.263.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 (92) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cjs/common/config/state/configurable.js +4 -4
  3. package/dist/cjs/common/config/state/init.js +5 -3
  4. package/dist/cjs/common/constants/env.cdn.js +1 -1
  5. package/dist/cjs/common/constants/env.npm.js +1 -1
  6. package/dist/cjs/common/context/shared-context.js +2 -2
  7. package/dist/cjs/common/drain/drain.js +1 -1
  8. package/dist/cjs/common/harvest/harvest.js +1 -1
  9. package/dist/cjs/common/session/session-entity.js +2 -2
  10. package/dist/cjs/common/timing/time-keeper.js +13 -2
  11. package/dist/cjs/common/util/console.js +3 -4
  12. package/dist/cjs/common/util/obfuscate.js +3 -3
  13. package/dist/cjs/common/wrap/wrap-logger.js +1 -2
  14. package/dist/cjs/common/wrap/wrap-xhr.js +1 -1
  15. package/dist/cjs/features/logging/aggregate/index.js +5 -5
  16. package/dist/cjs/features/logging/constants.js +2 -5
  17. package/dist/cjs/features/metrics/aggregate/index.js +16 -0
  18. package/dist/cjs/features/page_view_event/aggregate/index.js +20 -4
  19. package/dist/cjs/features/session_replay/aggregate/index.js +1 -1
  20. package/dist/cjs/features/session_replay/shared/recorder.js +1 -1
  21. package/dist/cjs/features/spa/aggregate/index.js +1 -1
  22. package/dist/cjs/features/utils/aggregate-base.js +4 -3
  23. package/dist/cjs/features/utils/instrument-base.js +2 -2
  24. package/dist/cjs/loaders/agent-base.js +1 -1
  25. package/dist/cjs/loaders/agent.js +3 -4
  26. package/dist/cjs/loaders/api/api.js +9 -7
  27. package/dist/cjs/loaders/micro-agent.js +5 -5
  28. package/dist/esm/common/config/state/configurable.js +4 -4
  29. package/dist/esm/common/config/state/init.js +5 -3
  30. package/dist/esm/common/constants/env.cdn.js +1 -1
  31. package/dist/esm/common/constants/env.npm.js +1 -1
  32. package/dist/esm/common/context/shared-context.js +2 -2
  33. package/dist/esm/common/drain/drain.js +1 -1
  34. package/dist/esm/common/harvest/harvest.js +1 -1
  35. package/dist/esm/common/session/session-entity.js +2 -2
  36. package/dist/esm/common/timing/time-keeper.js +12 -2
  37. package/dist/esm/common/util/console.js +3 -4
  38. package/dist/esm/common/util/obfuscate.js +3 -3
  39. package/dist/esm/common/wrap/wrap-logger.js +1 -2
  40. package/dist/esm/common/wrap/wrap-xhr.js +1 -1
  41. package/dist/esm/features/logging/aggregate/index.js +6 -6
  42. package/dist/esm/features/logging/constants.js +1 -4
  43. package/dist/esm/features/metrics/aggregate/index.js +16 -0
  44. package/dist/esm/features/page_view_event/aggregate/index.js +21 -5
  45. package/dist/esm/features/session_replay/aggregate/index.js +1 -1
  46. package/dist/esm/features/session_replay/shared/recorder.js +1 -1
  47. package/dist/esm/features/spa/aggregate/index.js +1 -1
  48. package/dist/esm/features/utils/aggregate-base.js +4 -3
  49. package/dist/esm/features/utils/instrument-base.js +2 -2
  50. package/dist/esm/loaders/agent-base.js +1 -1
  51. package/dist/esm/loaders/agent.js +3 -4
  52. package/dist/esm/loaders/api/api.js +9 -7
  53. package/dist/esm/loaders/micro-agent.js +5 -5
  54. package/dist/types/common/config/state/init.d.ts.map +1 -1
  55. package/dist/types/common/timing/time-keeper.d.ts +2 -1
  56. package/dist/types/common/timing/time-keeper.d.ts.map +1 -1
  57. package/dist/types/common/util/console.d.ts +1 -1
  58. package/dist/types/common/util/console.d.ts.map +1 -1
  59. package/dist/types/common/wrap/wrap-logger.d.ts.map +1 -1
  60. package/dist/types/features/logging/constants.d.ts +0 -3
  61. package/dist/types/features/logging/constants.d.ts.map +1 -1
  62. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  63. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  64. package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
  65. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
  66. package/dist/types/loaders/agent.d.ts.map +1 -1
  67. package/dist/types/loaders/api/api.d.ts.map +1 -1
  68. package/package.json +1 -1
  69. package/src/common/config/state/configurable.js +4 -4
  70. package/src/common/config/state/init.js +4 -3
  71. package/src/common/context/shared-context.js +2 -2
  72. package/src/common/drain/drain.js +1 -1
  73. package/src/common/harvest/harvest.js +1 -1
  74. package/src/common/session/session-entity.js +2 -2
  75. package/src/common/timing/time-keeper.js +14 -2
  76. package/src/common/util/console.js +3 -4
  77. package/src/common/util/obfuscate.js +3 -3
  78. package/src/common/wrap/wrap-logger.js +1 -2
  79. package/src/common/wrap/wrap-xhr.js +1 -1
  80. package/src/features/logging/aggregate/index.js +6 -6
  81. package/src/features/logging/constants.js +0 -4
  82. package/src/features/metrics/aggregate/index.js +12 -0
  83. package/src/features/page_view_event/aggregate/index.js +22 -5
  84. package/src/features/session_replay/aggregate/index.js +1 -1
  85. package/src/features/session_replay/shared/recorder.js +1 -1
  86. package/src/features/spa/aggregate/index.js +1 -1
  87. package/src/features/utils/aggregate-base.js +4 -3
  88. package/src/features/utils/instrument-base.js +2 -2
  89. package/src/loaders/agent-base.js +1 -1
  90. package/src/loaders/agent.js +3 -4
  91. package/src/loaders/api/api.js +9 -7
  92. package/src/loaders/micro-agent.js +5 -5
package/CHANGELOG.md CHANGED
@@ -3,6 +3,19 @@
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.263.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.262.0...v1.263.0) (2024-07-25)
7
+
8
+
9
+ ### Features
10
+
11
+ * Optimize bundle size with warning codes ([#1111](https://github.com/newrelic/newrelic-browser-agent/issues/1111)) ([6ab7d2b](https://github.com/newrelic/newrelic-browser-agent/commit/6ab7d2bee5053fc75c0d20c6257afea5cf16d76d))
12
+ * Shut down agent if improperly configured ([#1116](https://github.com/newrelic/newrelic-browser-agent/issues/1116)) ([edc20d4](https://github.com/newrelic/newrelic-browser-agent/commit/edc20d4f81d1c0662f3f244240cc968b1f3870c9))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * Prevent agent using invalid date header ([#1122](https://github.com/newrelic/newrelic-browser-agent/issues/1122)) ([6851c1b](https://github.com/newrelic/newrelic-browser-agent/commit/6851c1b1733c513ab4de119e875593a418e51b93))
18
+
6
19
  ## [1.262.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.261.2...v1.262.0) (2024-07-09)
7
20
 
8
21
 
@@ -7,8 +7,8 @@ exports.getModeledObject = getModeledObject;
7
7
  var _console = require("../../util/console");
8
8
  function getModeledObject(obj, model) {
9
9
  try {
10
- if (!obj || typeof obj !== 'object') return (0, _console.warn)('Setting a Configurable requires an object as input');
11
- if (!model || typeof model !== 'object') return (0, _console.warn)('Setting a Configurable requires a model to set its initial properties');
10
+ if (!obj || typeof obj !== 'object') return (0, _console.warn)(3);
11
+ if (!model || typeof model !== 'object') return (0, _console.warn)(4);
12
12
  // allow getters and setters to pass from model to target
13
13
  const output = Object.create(Object.getPrototypeOf(model), Object.getOwnPropertyDescriptors(model));
14
14
  const target = Object.keys(output).length === 0 ? obj : output;
@@ -21,11 +21,11 @@ function getModeledObject(obj, model) {
21
21
  }
22
22
  if (Array.isArray(obj[key]) && Array.isArray(model[key])) output[key] = Array.from(new Set([...obj[key], ...model[key]]));else if (typeof obj[key] === 'object' && typeof model[key] === 'object') output[key] = getModeledObject(obj[key], model[key]);else output[key] = obj[key];
23
23
  } catch (e) {
24
- (0, _console.warn)('An error occurred while setting a property of a Configurable', e);
24
+ (0, _console.warn)(1, e);
25
25
  }
26
26
  }
27
27
  return output;
28
28
  } catch (err) {
29
- (0, _console.warn)('An error occured while setting a Configurable', err);
29
+ (0, _console.warn)(2, err);
30
30
  }
31
31
  }
@@ -117,6 +117,8 @@ const model = () => {
117
117
  // serialize images for collection without public asset url -- right now this is only useful for testing as it easily generates payloads too large to be harvested
118
118
  inline_stylesheet: true,
119
119
  // serialize css for collection without public asset url
120
+ fix_stylesheets: true,
121
+ // fetch missing stylesheet resources for inlining, only works if 'inline_stylesheet' is also true
120
122
  // recording config settings
121
123
  mask_all_inputs: true,
122
124
  // this has a getter/setter to facilitate validation of the selectors
@@ -124,7 +126,7 @@ const model = () => {
124
126
  return hiddenState.mask_selector;
125
127
  },
126
128
  set mask_text_selector(val) {
127
- if ((0, _querySelector.isValidSelector)(val)) hiddenState.mask_selector = "".concat(val, ",").concat(nrMask);else if (val === '' || val === null) hiddenState.mask_selector = nrMask;else (0, _console.warn)('An invalid session_replay.mask_selector was provided. \'*\' will be used.', val);
129
+ if ((0, _querySelector.isValidSelector)(val)) hiddenState.mask_selector = "".concat(val, ",").concat(nrMask);else if (val === '' || val === null) hiddenState.mask_selector = nrMask;else (0, _console.warn)(5, val);
128
130
  },
129
131
  // these properties only have getters because they are enforcable constants and should error if someone tries to override them
130
132
  get block_class() {
@@ -142,7 +144,7 @@ const model = () => {
142
144
  return hiddenState.block_selector;
143
145
  },
144
146
  set block_selector(val) {
145
- if ((0, _querySelector.isValidSelector)(val)) hiddenState.block_selector += ",".concat(val);else if (val !== '') (0, _console.warn)('An invalid session_replay.block_selector was provided and will not be used', val);
147
+ if ((0, _querySelector.isValidSelector)(val)) hiddenState.block_selector += ",".concat(val);else if (val !== '') (0, _console.warn)(6, val);
146
148
  },
147
149
  // password: must always be present and true no matter what customer sets
148
150
  get mask_input_options() {
@@ -152,7 +154,7 @@ const model = () => {
152
154
  if (val && typeof val === 'object') hiddenState.mask_input_options = {
153
155
  ...val,
154
156
  password: true
155
- };else (0, _console.warn)('An invalid session_replay.mask_input_option was provided and will not be used', val);
157
+ };else (0, _console.warn)(7, val);
156
158
  }
157
159
  },
158
160
  session_trace: {
@@ -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.262.0";
15
+ const VERSION = exports.VERSION = "1.263.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.262.0";
15
+ const VERSION = exports.VERSION = "1.263.0";
16
16
 
17
17
  /**
18
18
  * Exposes the build type of the agent
@@ -12,7 +12,7 @@ const model = {
12
12
  class SharedContext {
13
13
  constructor(context) {
14
14
  try {
15
- if (typeof context !== 'object') return (0, _console.warn)('shared context requires an object as input');
15
+ if (typeof context !== 'object') return (0, _console.warn)(8);
16
16
  this.sharedContext = {};
17
17
  Object.assign(this.sharedContext, model);
18
18
  Object.entries(context).forEach(_ref => {
@@ -20,7 +20,7 @@ class SharedContext {
20
20
  if (Object.keys(model).includes(key)) this.sharedContext[key] = value;
21
21
  });
22
22
  } catch (err) {
23
- (0, _console.warn)('An error occurred while setting SharedContext', err);
23
+ (0, _console.warn)(9, err);
24
24
  }
25
25
  }
26
26
  }
@@ -107,7 +107,7 @@ function drainGroup(agentIdentifier, group) {
107
107
  let activateGroup = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
108
108
  const baseEE = agentIdentifier ? _contextualEe.ee.get(agentIdentifier) : _contextualEe.ee;
109
109
  const handlers = _registerHandler.registerHandler.handlers; // other storage in registerHandler
110
- if (!baseEE.backlog || !handlers) return;
110
+ if (baseEE.aborted || !baseEE.backlog || !handlers) return;
111
111
 
112
112
  // Only activated features being drained should run queued listeners on buffered events. Deactivated features only need to release memory.
113
113
  if (activateGroup) {
@@ -156,7 +156,7 @@ class Harvest extends _sharedContext.SharedContext {
156
156
  body = (0, _stringify.stringify)(body);
157
157
  }
158
158
  /** Warn --once per endpoint-- if the agent tries to send large payloads */
159
- if (body.length > 750000 && (warnings[endpoint] = (warnings?.[endpoint] || 0) + 1) === 1) (0, _console.warn)("The Browser Agent is attempting to send a very large payload to /".concat(endpoint, ". This is usually tied to large amounts of custom attributes. Please check your configurations."));
159
+ if (body.length > 750000 && (warnings[endpoint] = (warnings?.[endpoint] || 0) + 1) === 1) (0, _console.warn)(28, endpoint);
160
160
  }
161
161
  if (!body || body.length === 0 || body === '{}' || body === '[]') {
162
162
  // If body is null, undefined, or an empty object or array, send an empty string instead
@@ -195,7 +195,7 @@ class SessionEntity {
195
195
  }
196
196
  return obj;
197
197
  } catch (e) {
198
- (0, _console.warn)('Failed to read from storage API', e);
198
+ (0, _console.warn)(10, e);
199
199
  // storage is inaccessible
200
200
  return {};
201
201
  }
@@ -221,7 +221,7 @@ class SessionEntity {
221
221
  return data;
222
222
  } catch (e) {
223
223
  // storage is inaccessible
224
- (0, _console.warn)('Failed to write to the storage API', e);
224
+ (0, _console.warn)(11, e);
225
225
  return null;
226
226
  }
227
227
  }
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.TimeKeeper = void 0;
7
7
  var _runtime = require("../constants/runtime");
8
8
  var _config = require("../config/config");
9
+ const rfc2616Regex = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), ([0-3][0-9]) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([0-9]{4}) ([01][0-9]|2[0-3])(:[0-5][0-9]){2} GMT$/;
10
+
9
11
  /**
10
12
  * Class used to adjust the timestamp of harvested data to New Relic server time. This
11
13
  * is done by tracking the performance timings of the RUM call and applying a calculation
@@ -34,7 +36,7 @@ class TimeKeeper {
34
36
  /**
35
37
  * Represents whether the timekeeper is in a state that it can accurately convert
36
38
  * timestamps.
37
- * @type {number}
39
+ * @type {boolean}
38
40
  */
39
41
  #ready = false;
40
42
  constructor(agentIdentifier) {
@@ -47,6 +49,9 @@ class TimeKeeper {
47
49
  get correctedOriginTime() {
48
50
  return this.#correctedOriginTime;
49
51
  }
52
+ get localTimeDiff() {
53
+ return this.#localTimeDiff;
54
+ }
50
55
 
51
56
  /**
52
57
  * Process a rum request to calculate NR server time.
@@ -55,12 +60,16 @@ class TimeKeeper {
55
60
  * @param endTime {number} The end time of the RUM request
56
61
  */
57
62
  processRumRequest(rumRequest, startTime, endTime) {
58
- this.processStoredDiff();
63
+ this.processStoredDiff(); // Check session entity for stored time diff
59
64
  if (this.#ready) return; // Server time calculated from session entity
65
+
60
66
  const responseDateHeader = rumRequest.getResponseHeader('Date');
61
67
  if (!responseDateHeader) {
62
68
  throw new Error('Missing date header on rum response.');
63
69
  }
70
+ if (!rfc2616Regex.test(responseDateHeader)) {
71
+ throw new Error('Date header invalid format.');
72
+ }
64
73
  const medianRumOffset = (endTime - startTime) / 2;
65
74
  const serverOffset = startTime + medianRumOffset;
66
75
 
@@ -97,6 +106,8 @@ class TimeKeeper {
97
106
 
98
107
  /** Process the session entity and use the info to set the main time calculations if present */
99
108
  processStoredDiff() {
109
+ if (this.#ready) return; // Time diff has already been calculated
110
+
100
111
  const storedServerTimeDiff = this.#session?.read()?.serverTimeDiff;
101
112
  if (typeof storedServerTimeDiff === 'number' && !isNaN(storedServerTimeDiff)) {
102
113
  this.#localTimeDiff = storedServerTimeDiff;
@@ -10,8 +10,7 @@ exports.warn = warn;
10
10
  * @param {*} [secondary] Secondary data to include, usually an error or object
11
11
  * @returns
12
12
  */
13
- function warn(message, secondary) {
14
- if (typeof console.warn !== 'function') return;
15
- console.warn("New Relic: ".concat(message));
16
- if (secondary) console.warn(secondary);
13
+ function warn(code, secondary) {
14
+ if (typeof console.debug !== 'function') return;
15
+ console.debug("New Relic Warning: https://github.com/newrelic/newrelic-browser-agent/blob/main/docs/warning-codes.md#".concat(code), secondary);
17
16
  }
@@ -54,15 +54,15 @@ function validateRules(rules) {
54
54
  var invalidRegexDetected = false;
55
55
  for (var i = 0; i < rules.length; i++) {
56
56
  if (!('regex' in rules[i])) {
57
- (0, _console.warn)('An obfuscation replacement rule was detected missing a "regex" value.');
57
+ (0, _console.warn)(12);
58
58
  invalidRegexDetected = true;
59
59
  } else if (typeof rules[i].regex !== 'string' && !(rules[i].regex instanceof RegExp)) {
60
- (0, _console.warn)('An obfuscation replacement rule contains a "regex" value with an invalid type (must be a string or RegExp)');
60
+ (0, _console.warn)(13);
61
61
  invalidRegexDetected = true;
62
62
  }
63
63
  var replacement = rules[i].replacement;
64
64
  if (replacement && typeof replacement !== 'string') {
65
- (0, _console.warn)('An obfuscation replacement rule contains a "replacement" value with an invalid type (must be a string)');
65
+ (0, _console.warn)(14);
66
66
  invalidReplacementDetected = true;
67
67
  }
68
68
  }
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.scopedEE = scopedEE;
7
7
  exports.wrapLogger = wrapLogger;
8
- var _constants = require("../../features/logging/constants");
9
8
  var _contextualEe = require("../event-emitter/contextual-ee");
10
9
  var _eventContext = require("../event-emitter/event-context");
11
10
  var _console = require("../util/console");
@@ -28,7 +27,7 @@ var _wrapFunction = require("./wrap-function");
28
27
  */
29
28
  // eslint-disable-next-line
30
29
  function wrapLogger(sharedEE, parent, loggerFn, context) {
31
- if (!(typeof parent === 'object' && !!parent && typeof loggerFn === 'string' && !!loggerFn && typeof parent[loggerFn] === 'function')) return (0, _console.warn)(_constants.LOGGING_FAILURE_MESSAGE + 'invalid argument(s)');
30
+ if (!(typeof parent === 'object' && !!parent && typeof loggerFn === 'string' && !!loggerFn && typeof parent[loggerFn] === 'function')) return (0, _console.warn)(29);
32
31
  const ee = scopedEE(sharedEE);
33
32
  const wrapFn = (0, _wrapFunction.createWrapperWithEmitter)(ee);
34
33
 
@@ -56,7 +56,7 @@ function wrapXhr(sharedEE) {
56
56
  ee.emit('new-xhr', [xhr], context);
57
57
  xhr.addEventListener(READY_STATE_CHANGE, wrapXHR(context), (0, _eventListenerOpts.eventListenerOpts)(false));
58
58
  } catch (e) {
59
- (0, _console.warn)('An error occurred while intercepting XHR', e);
59
+ (0, _console.warn)(15, e);
60
60
  try {
61
61
  ee.emit('internal-error', [e]);
62
62
  } catch (err) {
@@ -51,7 +51,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
51
51
  if (this.blocked) return;
52
52
  if (!attributes || typeof attributes !== 'object') attributes = {};
53
53
  if (typeof level === 'string') level = level.toUpperCase();
54
- if (!(0, _utils.isValidLogLevel)(level)) return (0, _console.warn)(_constants2.LOGGING_LEVEL_FAILURE_MESSAGE + level, Object.values(_constants2.LOG_LEVELS));
54
+ if (!(0, _utils.isValidLogLevel)(level)) return (0, _console.warn)(30, level);
55
55
  try {
56
56
  if (typeof message !== 'string') {
57
57
  const stringified = (0, _stringify.stringify)(message);
@@ -63,19 +63,19 @@ class Aggregate extends _aggregateBase.AggregateBase {
63
63
  if (!!stringified && stringified !== '{}') message = stringified;else message = String(message);
64
64
  }
65
65
  } catch (err) {
66
- (0, _console.warn)('could not cast log message to string', message);
66
+ (0, _console.warn)(16, message);
67
67
  return;
68
68
  }
69
- if (typeof message !== 'string' || !message) return (0, _console.warn)(_constants2.LOGGING_IGNORED + 'invalid message');
69
+ if (typeof message !== 'string' || !message) return (0, _console.warn)(32);
70
70
  if (message.length > _constants2.MAX_PAYLOAD_SIZE) {
71
71
  (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Failed/Seen', message.length]);
72
- return (0, _console.warn)(_constants2.LOGGING_IGNORED + '> ' + _constants2.MAX_PAYLOAD_SIZE + ' bytes: ', message.slice(0, 25) + '...');
72
+ return (0, _console.warn)(31, message.slice(0, 25) + '...');
73
73
  }
74
74
  const log = new _log.Log(this.#agentRuntime.timeKeeper.convertRelativeTimestamp(timestamp), message, attributes, level);
75
75
  const logBytes = log.message.length + (0, _stringify.stringify)(log.attributes).length + log.level.length + 10; // timestamp == 10 chars
76
76
  if (logBytes > _constants2.MAX_PAYLOAD_SIZE) {
77
77
  (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Failed/Seen', logBytes]);
78
- return (0, _console.warn)(_constants2.LOGGING_IGNORED + '> ' + _constants2.MAX_PAYLOAD_SIZE + ' bytes: ', log.message.slice(0, 25) + '...');
78
+ return (0, _console.warn)(31, log.message.slice(0, 25) + '...');
79
79
  }
80
80
  if (this.estimatedBytes + logBytes >= _constants2.MAX_PAYLOAD_SIZE) {
81
81
  (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Early/Seen', this.estimatedBytes + logBytes]);
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.MAX_PAYLOAD_SIZE = exports.LOG_LEVELS = exports.LOGGING_LEVEL_FAILURE_MESSAGE = exports.LOGGING_IGNORED = exports.LOGGING_FAILURE_MESSAGE = exports.LOGGING_EVENT_EMITTER_CHANNEL = exports.FEATURE_NAME = void 0;
6
+ exports.MAX_PAYLOAD_SIZE = exports.LOG_LEVELS = exports.LOGGING_EVENT_EMITTER_CHANNEL = exports.FEATURE_NAME = void 0;
7
7
  var _features = require("../../loaders/features/features");
8
8
  const LOG_LEVELS = exports.LOG_LEVELS = {
9
9
  ERROR: 'ERROR',
@@ -14,7 +14,4 @@ const LOG_LEVELS = exports.LOG_LEVELS = {
14
14
  };
15
15
  const LOGGING_EVENT_EMITTER_CHANNEL = exports.LOGGING_EVENT_EMITTER_CHANNEL = 'log';
16
16
  const FEATURE_NAME = exports.FEATURE_NAME = _features.FEATURE_NAMES.logging;
17
- const MAX_PAYLOAD_SIZE = exports.MAX_PAYLOAD_SIZE = 1000000;
18
- const LOGGING_FAILURE_MESSAGE = exports.LOGGING_FAILURE_MESSAGE = 'failed to wrap logger: ';
19
- const LOGGING_LEVEL_FAILURE_MESSAGE = exports.LOGGING_LEVEL_FAILURE_MESSAGE = 'invalid log level: ';
20
- const LOGGING_IGNORED = exports.LOGGING_IGNORED = 'ignored log: ';
17
+ const MAX_PAYLOAD_SIZE = exports.MAX_PAYLOAD_SIZE = 1000000;
@@ -108,6 +108,22 @@ class Aggregate extends _aggregateBase.AggregateBase {
108
108
  // Check if proxy for either chunks or beacon is being used
109
109
  if (proxy.assets) this.storeSupportabilityMetrics('Config/AssetsUrl/Changed');
110
110
  if (proxy.beacon) this.storeSupportabilityMetrics('Config/BeaconUrl/Changed');
111
+ if (_runtime.isBrowserScope && window.MutationObserver) {
112
+ this.storeSupportabilityMetrics('Generic/VideoElement/Added', window.document.querySelectorAll('video').length);
113
+ const mo = new MutationObserver(records => {
114
+ records.forEach(record => {
115
+ record.addedNodes.forEach(addedNode => {
116
+ if (addedNode instanceof HTMLVideoElement) {
117
+ this.storeSupportabilityMetrics('Generic/VideoElement/Added', 1);
118
+ }
119
+ });
120
+ });
121
+ });
122
+ mo.observe(window.document.body, {
123
+ childList: true,
124
+ subtree: true
125
+ });
126
+ }
111
127
  }
112
128
  eachSessionChecks() {
113
129
  if (!_runtime.isBrowserScope) return;
@@ -33,6 +33,10 @@ class Aggregate extends _aggregateBase.AggregateBase {
33
33
  this.firstByteToWindowLoad = 0; // our "frontend" duration
34
34
  this.firstByteToDomContent = 0; // our "dom processing" duration
35
35
  this.timeKeeper = new _timeKeeper.TimeKeeper(this.agentIdentifier);
36
+ if (!(0, _config.isConfigured)(agentIdentifier)) {
37
+ this.ee.abort();
38
+ return (0, _console.warn)(43);
39
+ }
36
40
  if (_runtime.isBrowserScope) {
37
41
  _timeToFirstByte.timeToFirstByte.subscribe(_ref => {
38
42
  let {
@@ -55,7 +59,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
55
59
  const info = (0, _config.getInfo)(this.agentIdentifier);
56
60
  const agentRuntime = (0, _config.getRuntime)(this.agentIdentifier);
57
61
  const harvester = new _harvest.Harvest(this);
58
- if (!info.beacon) return;
59
62
  if (info.queueTime) this.aggregator.store('measures', 'qt', {
60
63
  value: info.queueTime
61
64
  });
@@ -148,11 +151,24 @@ class Aggregate extends _aggregateBase.AggregateBase {
148
151
  this.timeKeeper.processRumRequest(xhr, rumStartTime, rumEndTime);
149
152
  if (!this.timeKeeper.ready) throw new Error('TimeKeeper not ready');
150
153
  agentRuntime.timeKeeper = this.timeKeeper;
154
+
155
+ // Check if the time diff is such that we need to capture a supportability metric
156
+ if (this.timeKeeper.localTimeDiff >= 12 * 60 * 60 * 1000) {
157
+ (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/DiffExceed12Hrs'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
158
+ } else if (this.timeKeeper.localTimeDiff >= 6 * 60 * 60 * 1000) {
159
+ (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/DiffExceed6Hrs'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
160
+ } else if (this.timeKeeper.localTimeDiff >= 60 * 60 * 1000) {
161
+ (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/DiffExceed1Hrs'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
162
+ }
151
163
  } catch (error) {
152
- (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/Failed'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
164
+ if (error?.message?.indexOf('invalid format') > 0) {
165
+ (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/InvalidFormat'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
166
+ } else {
167
+ (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/Failed'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
168
+ }
153
169
  (0, _drain.drain)(this.agentIdentifier, _features.FEATURE_NAMES.metrics, true);
154
170
  this.ee.abort();
155
- (0, _console.warn)('Could not calculate New Relic server time. Agent shutting down.', error);
171
+ (0, _console.warn)(17, error);
156
172
  return;
157
173
  }
158
174
  try {
@@ -165,7 +181,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
165
181
  this.drain();
166
182
  } catch (err) {
167
183
  this.ee.abort();
168
- (0, _console.warn)('RUM call failed. Agent shutting down.', err);
184
+ (0, _console.warn)(18, err);
169
185
  }
170
186
  }
171
187
  });
@@ -421,7 +421,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
421
421
  abort() {
422
422
  let reason = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
423
423
  let data = arguments.length > 1 ? arguments[1] : undefined;
424
- (0, _console.warn)("SR aborted -- ".concat(reason.message));
424
+ (0, _console.warn)(33, reason.message);
425
425
  (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ["SessionReplay/Abort/".concat(reason.sm), data], undefined, _features.FEATURE_NAMES.metrics, this.ee);
426
426
  this.blocked = true;
427
427
  this.mode = _constants3.MODE.OFF;
@@ -39,7 +39,7 @@ class Recorder {
39
39
  /** Config to inform to inline stylesheet contents (true default) */
40
40
  this.shouldInlineStylesheets = (0, _config.getConfigurationValue)(this.parent.agentIdentifier, 'session_replay.inline_stylesheet');
41
41
  /** A flag that can be set to false by failing conversions to stop the fetching process */
42
- this.shouldFix = this.shouldInlineStylesheets;
42
+ this.shouldFix = this.shouldInlineStylesheets && (0, _config.getConfigurationValue)(this.parent.agentIdentifier, 'session_replay.fix_stylesheets');
43
43
  /** The method to stop recording. This defaults to a noop, but is overwritten once the recording library is imported and initialized */
44
44
  this.stopRecording = () => {/* no-op until set by rrweb initializer */};
45
45
  }
@@ -702,7 +702,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
702
702
  if (interaction.root?.attrs?.trigger === 'initialPageLoad') smCategory = 'InitialPageLoad';else if (interaction.routeChange) smCategory = 'RouteChange';else smCategory = 'Custom';
703
703
  (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ["Spa/Interaction/".concat(smCategory, "/Duration/Ms"), Math.max((interaction.root?.end || 0) - (interaction.root?.start || 0), 0)], undefined, _features.FEATURE_NAMES.metrics, baseEE);
704
704
  scheduler?.scheduleHarvest(0);
705
- if (!scheduler) (0, _console.warn)('SPA scheduler is not initialized. Saved interaction is not sent!');
705
+ if (!scheduler) (0, _console.warn)(19);
706
706
  }
707
707
  function isEnabled() {
708
708
  var enabled = (0, _config.getConfigurationValue)(agentIdentifier, 'spa.enabled');
@@ -55,8 +55,9 @@ class AggregateBase extends _featureBase.FeatureBase {
55
55
  checkConfiguration() {
56
56
  // NOTE: This check has to happen at aggregator load time
57
57
  if (!(0, _config.isConfigured)(this.agentIdentifier)) {
58
+ const cdn = (0, _nreum.gosCDN)();
58
59
  let jsAttributes = {
59
- ...(0, _nreum.gosCDN)().info?.jsAttributes
60
+ ...cdn.info?.jsAttributes
60
61
  };
61
62
  try {
62
63
  jsAttributes = {
@@ -69,9 +70,9 @@ class AggregateBase extends _featureBase.FeatureBase {
69
70
  (0, _configure.configure)({
70
71
  agentIdentifier: this.agentIdentifier
71
72
  }, {
72
- ...(0, _nreum.gosCDN)(),
73
+ ...cdn,
73
74
  info: {
74
- ...(0, _nreum.gosCDN)().info,
75
+ ...cdn.info,
75
76
  jsAttributes
76
77
  },
77
78
  runtime: (0, _config.getRuntime)(this.agentIdentifier)
@@ -92,7 +92,7 @@ class InstrumentBase extends _featureBase.FeatureBase {
92
92
  session = setupAgentSession(this.agentIdentifier);
93
93
  }
94
94
  } catch (e) {
95
- (0, _console.warn)('A problem occurred when starting up session manager. This page will not start or extend any session.', e);
95
+ (0, _console.warn)(20, e);
96
96
  this.ee.emit('internal-error', [e]);
97
97
  if (this.featureName === _features.FEATURE_NAMES.sessionReplay) this.abortHandler?.(); // SR should stop recording if session DNE
98
98
  }
@@ -116,7 +116,7 @@ class InstrumentBase extends _featureBase.FeatureBase {
116
116
  this.featAggregate = new Aggregate(this.agentIdentifier, this.aggregator, argsObjFromInstrument);
117
117
  loadedSuccessfully(true);
118
118
  } catch (e) {
119
- (0, _console.warn)("Downloading and initializing ".concat(this.featureName, " failed..."), e);
119
+ (0, _console.warn)(34, e);
120
120
  this.abortHandler?.(); // undo any important alterations made to the page
121
121
  // not supported yet but nice to do: "abort" this agent's EE for this feature specifically
122
122
  (0, _drain.drain)(this.agentIdentifier, this.featureName, true);
@@ -33,7 +33,7 @@ class AgentBase {
33
33
  for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
34
34
  args[_key - 1] = arguments[_key];
35
35
  }
36
- if (typeof this.api?.[methodName] !== 'function') (0, _console.warn)("Call to agent api ".concat(methodName, " failed. The API is not currently initialized."));else return this.api[methodName](...args);
36
+ if (typeof this.api?.[methodName] !== 'function') (0, _console.warn)(35, methodName);else return this.api[methodName](...args);
37
37
  }
38
38
 
39
39
  /**
@@ -15,7 +15,6 @@ var _instrument = require("../features/page_view_event/instrument");
15
15
  var _aggregator = require("../common/aggregate/aggregator");
16
16
  var _nreum = require("../common/window/nreum");
17
17
  var _console = require("../common/util/console");
18
- var _stringify = require("../common/util/stringify");
19
18
  var _runtime = require("../common/constants/runtime");
20
19
  // important side effects
21
20
 
@@ -39,7 +38,7 @@ class Agent extends _agentBase.AgentBase {
39
38
  if (!_runtime.globalScope) {
40
39
  // We could not determine the runtime environment. Short-circuite the agent here
41
40
  // to avoid possible exceptions later that may cause issues with customer's application.
42
- (0, _console.warn)('Failed to initialize the agent. Could not determine the runtime environment.');
41
+ (0, _console.warn)(21);
43
42
  return;
44
43
  }
45
44
  this.sharedAggregator = new _aggregator.Aggregator({
@@ -78,11 +77,11 @@ class Agent extends _agentBase.AgentBase {
78
77
  if (!this.runSoftNavOverSpa && InstrumentCtor.featureName === _features.FEATURE_NAMES.softNav) return;
79
78
  const dependencies = (0, _featureDependencies.getFeatureDependencyNames)(InstrumentCtor.featureName);
80
79
  const hasAllDeps = dependencies.every(featName => featName in this.features); // any other feature(s) this depends on should've been initialized on prior iterations by priority order
81
- if (!hasAllDeps) (0, _console.warn)("".concat(InstrumentCtor.featureName, " is enabled but one or more dependent features has not been initialized (").concat((0, _stringify.stringify)(dependencies), "). This may cause unintended consequences or missing data..."));
80
+ if (!hasAllDeps) (0, _console.warn)(36, InstrumentCtor.featureName);
82
81
  this.features[InstrumentCtor.featureName] = new InstrumentCtor(this.agentIdentifier, this.sharedAggregator);
83
82
  });
84
83
  } catch (err) {
85
- (0, _console.warn)('Failed to initialize all enabled instrument classes (agent aborted) -', err);
84
+ (0, _console.warn)(22, err);
86
85
  for (const featName in this.features) {
87
86
  // this.features hold only features that have been instantiated
88
87
  this.features[featName].abortHandler?.();
@@ -44,7 +44,7 @@ function setTopLevelCallers() {
44
44
  let returnVals = [];
45
45
  Object.values(nr.initializedAgents).forEach(val => {
46
46
  if (!val || !val.api) {
47
- (0, _console.warn)("Call to api '".concat(fnName, "' made before agent fully initialized."));
47
+ (0, _console.warn)(38, fnName);
48
48
  } else if (val.exposed && val.api[fnName]) {
49
49
  returnVals.push(val.api[fnName](...args));
50
50
  }
@@ -70,6 +70,7 @@ function setAPI(agentIdentifier, forceDrain) {
70
70
  customAttributes = {},
71
71
  level = _constants4.LOG_LEVELS.INFO
72
72
  } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
73
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/log/called'], undefined, _features.FEATURE_NAMES.metrics, instanceEE);
73
74
  (0, _utils.bufferLog)(instanceEE, message, customAttributes, level);
74
75
  };
75
76
  apiInterface.wrapLogger = function (parent, functionName) {
@@ -77,6 +78,7 @@ function setAPI(agentIdentifier, forceDrain) {
77
78
  customAttributes = {},
78
79
  level = _constants4.LOG_LEVELS.INFO
79
80
  } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
81
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/wrapLogger/called'], undefined, _features.FEATURE_NAMES.metrics, instanceEE);
80
82
  (0, _wrapLogger.wrapLogger)(instanceEE, parent, functionName, {
81
83
  customAttributes,
82
84
  level
@@ -121,11 +123,11 @@ function setAPI(agentIdentifier, forceDrain) {
121
123
  apiInterface.setCustomAttribute = function (name, value) {
122
124
  let persistAttribute = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
123
125
  if (typeof name !== 'string') {
124
- (0, _console.warn)("Failed to execute setCustomAttribute.\nName must be a string type, but a type of <".concat(typeof name, "> was provided."));
126
+ (0, _console.warn)(39, typeof name);
125
127
  return;
126
128
  }
127
129
  if (!(['string', 'number', 'boolean'].includes(typeof value) || value === null)) {
128
- (0, _console.warn)("Failed to execute setCustomAttribute.\nNon-null value must be a string, number or boolean type, but a type of <".concat(typeof value, "> was provided."));
130
+ (0, _console.warn)(40, typeof value);
129
131
  return;
130
132
  }
131
133
  return appendJsAttribute(name, value, 'setCustomAttribute', persistAttribute);
@@ -137,7 +139,7 @@ function setAPI(agentIdentifier, forceDrain) {
137
139
  */
138
140
  apiInterface.setUserId = function (value) {
139
141
  if (!(typeof value === 'string' || value === null)) {
140
- (0, _console.warn)("Failed to execute setUserId.\nNon-null value must be a string type, but a type of <".concat(typeof value, "> was provided."));
142
+ (0, _console.warn)(41, typeof value);
141
143
  return;
142
144
  }
143
145
  return appendJsAttribute('enduser.id', value, 'setUserId', true);
@@ -150,7 +152,7 @@ function setAPI(agentIdentifier, forceDrain) {
150
152
  */
151
153
  apiInterface.setApplicationVersion = function (value) {
152
154
  if (!(typeof value === 'string' || value === null)) {
153
- (0, _console.warn)("Failed to execute setApplicationVersion. Expected <String | null>, but got <".concat(typeof value, ">."));
155
+ (0, _console.warn)(42, typeof value);
154
156
  return;
155
157
  }
156
158
  return appendJsAttribute('application.version', value, 'setApplicationVersion', false);
@@ -160,7 +162,7 @@ function setAPI(agentIdentifier, forceDrain) {
160
162
  (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/start/called'], undefined, _features.FEATURE_NAMES.metrics, instanceEE);
161
163
  instanceEE.emit('manual-start-all');
162
164
  } catch (err) {
163
- (0, _console.warn)('An unexpected issue occurred', err);
165
+ (0, _console.warn)(23, err);
164
166
  }
165
167
  };
166
168
  apiInterface[_constants2.SR_EVENT_EMITTER_TYPES.RECORD] = function () {
@@ -229,7 +231,7 @@ function setAPI(agentIdentifier, forceDrain) {
229
231
  setAPI(agentIdentifier);
230
232
  (0, _drain.drain)(agentIdentifier, 'api');
231
233
  }).catch(err => {
232
- (0, _console.warn)('Downloading runtime APIs failed...', err);
234
+ (0, _console.warn)(27, err);
233
235
  instanceEE.abort();
234
236
  });
235
237
  }