@newrelic/browser-agent 1.239.1 → 1.240.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 (167) hide show
  1. package/README.md +4 -0
  2. package/dist/cjs/cdn/pro.js +3 -2
  3. package/dist/cjs/cdn/spa.js +4 -3
  4. package/dist/cjs/common/config/state/init.js +6 -0
  5. package/dist/cjs/common/constants/env.cdn.js +1 -1
  6. package/dist/cjs/common/constants/env.npm.js +1 -1
  7. package/dist/cjs/common/constants/runtime.js +9 -5
  8. package/dist/cjs/common/harvest/harvest.js +5 -3
  9. package/dist/cjs/common/vitals/constants.js +17 -0
  10. package/dist/cjs/common/vitals/cumulative-layout-shift.js +27 -0
  11. package/dist/cjs/common/vitals/first-contentful-paint.js +49 -0
  12. package/dist/cjs/common/vitals/first-input-delay.js +32 -0
  13. package/dist/{esm/features/page_view_timing → cjs/common/vitals}/first-paint.js +19 -17
  14. package/dist/cjs/common/vitals/interaction-to-next-paint.js +29 -0
  15. package/dist/cjs/common/vitals/largest-contentful-paint.js +41 -0
  16. package/dist/cjs/common/vitals/long-task.js +64 -0
  17. package/dist/cjs/common/vitals/time-to-first-byte.js +36 -0
  18. package/dist/cjs/common/vitals/vital-metric.js +71 -0
  19. package/dist/cjs/features/ajax/aggregate/index.js +4 -1
  20. package/dist/cjs/features/metrics/aggregate/index.js +7 -0
  21. package/dist/cjs/features/page_view_event/aggregate/index.js +18 -40
  22. package/dist/cjs/features/page_view_event/constants.js +2 -8
  23. package/dist/cjs/features/page_view_event/instrument/index.js +0 -22
  24. package/dist/cjs/features/page_view_timing/aggregate/index.js +27 -138
  25. package/dist/cjs/features/page_view_timing/instrument/index.js +0 -3
  26. package/dist/cjs/features/session_trace/aggregate/index.js +13 -1
  27. package/dist/cjs/features/spa/aggregate/index.js +4 -3
  28. package/dist/cjs/loaders/agent.js +3 -0
  29. package/dist/cjs/loaders/api/api.js +2 -0
  30. package/dist/cjs/loaders/api/apiAsync.js +4 -2
  31. package/dist/cjs/loaders/configure/configure.js +13 -1
  32. package/dist/cjs/loaders/configure/public-path.js +13 -0
  33. package/dist/cjs/loaders/configure/public-path.npm.js +10 -0
  34. package/dist/esm/cdn/pro.js +2 -1
  35. package/dist/esm/cdn/spa.js +2 -1
  36. package/dist/esm/common/config/state/init.js +6 -0
  37. package/dist/esm/common/constants/env.cdn.js +1 -1
  38. package/dist/esm/common/constants/env.npm.js +1 -1
  39. package/dist/esm/common/constants/runtime.js +5 -3
  40. package/dist/esm/common/harvest/harvest.js +6 -4
  41. package/dist/esm/common/vitals/constants.js +10 -0
  42. package/dist/esm/common/vitals/cumulative-layout-shift.js +20 -0
  43. package/dist/esm/common/vitals/first-contentful-paint.js +41 -0
  44. package/dist/esm/common/vitals/first-input-delay.js +25 -0
  45. package/dist/{cjs/features/page_view_timing → esm/common/vitals}/first-paint.js +12 -24
  46. package/dist/esm/common/vitals/interaction-to-next-paint.js +22 -0
  47. package/dist/esm/common/vitals/largest-contentful-paint.js +34 -0
  48. package/dist/esm/common/vitals/long-task.js +57 -0
  49. package/dist/esm/common/vitals/time-to-first-byte.js +29 -0
  50. package/dist/esm/common/vitals/vital-metric.js +64 -0
  51. package/dist/esm/features/ajax/aggregate/index.js +4 -1
  52. package/dist/esm/features/metrics/aggregate/index.js +8 -1
  53. package/dist/esm/features/page_view_event/aggregate/index.js +20 -42
  54. package/dist/esm/features/page_view_event/constants.js +1 -4
  55. package/dist/esm/features/page_view_event/instrument/index.js +0 -22
  56. package/dist/esm/features/page_view_timing/aggregate/index.js +28 -139
  57. package/dist/esm/features/page_view_timing/instrument/index.js +0 -3
  58. package/dist/esm/features/session_trace/aggregate/index.js +13 -1
  59. package/dist/esm/features/spa/aggregate/index.js +4 -3
  60. package/dist/esm/loaders/agent.js +2 -0
  61. package/dist/esm/loaders/api/api.js +2 -0
  62. package/dist/esm/loaders/api/apiAsync.js +5 -3
  63. package/dist/esm/loaders/configure/configure.js +13 -1
  64. package/dist/esm/loaders/configure/public-path.js +6 -0
  65. package/dist/esm/loaders/configure/public-path.npm.js +3 -0
  66. package/dist/types/common/config/state/init.d.ts.map +1 -1
  67. package/dist/types/common/constants/runtime.d.ts +3 -1
  68. package/dist/types/common/constants/runtime.d.ts.map +1 -1
  69. package/dist/types/common/harvest/harvest.d.ts +0 -1
  70. package/dist/types/common/harvest/harvest.d.ts.map +1 -1
  71. package/dist/types/common/vitals/constants.d.ts +11 -0
  72. package/dist/types/common/vitals/constants.d.ts.map +1 -0
  73. package/dist/types/common/vitals/cumulative-layout-shift.d.ts +3 -0
  74. package/dist/types/common/vitals/cumulative-layout-shift.d.ts.map +1 -0
  75. package/dist/types/common/vitals/first-contentful-paint.d.ts +3 -0
  76. package/dist/types/common/vitals/first-contentful-paint.d.ts.map +1 -0
  77. package/dist/types/common/vitals/first-input-delay.d.ts +3 -0
  78. package/dist/types/common/vitals/first-input-delay.d.ts.map +1 -0
  79. package/dist/types/common/vitals/first-paint.d.ts +3 -0
  80. package/dist/types/common/vitals/first-paint.d.ts.map +1 -0
  81. package/dist/types/common/vitals/interaction-to-next-paint.d.ts +3 -0
  82. package/dist/types/common/vitals/interaction-to-next-paint.d.ts.map +1 -0
  83. package/dist/types/common/vitals/largest-contentful-paint.d.ts +3 -0
  84. package/dist/types/common/vitals/largest-contentful-paint.d.ts.map +1 -0
  85. package/dist/types/common/vitals/long-task.d.ts +3 -0
  86. package/dist/types/common/vitals/long-task.d.ts.map +1 -0
  87. package/dist/types/common/vitals/time-to-first-byte.d.ts +3 -0
  88. package/dist/types/common/vitals/time-to-first-byte.d.ts.map +1 -0
  89. package/dist/types/common/vitals/vital-metric.d.ts +18 -0
  90. package/dist/types/common/vitals/vital-metric.d.ts.map +1 -0
  91. package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
  92. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  93. package/dist/types/features/page_view_event/aggregate/index.d.ts +3 -2
  94. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  95. package/dist/types/features/page_view_event/constants.d.ts +0 -3
  96. package/dist/types/features/page_view_event/constants.d.ts.map +1 -1
  97. package/dist/types/features/page_view_event/instrument/index.d.ts.map +1 -1
  98. package/dist/types/features/page_view_timing/aggregate/index.d.ts +1 -3
  99. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  100. package/dist/types/features/page_view_timing/instrument/index.d.ts.map +1 -1
  101. package/dist/types/features/session_trace/aggregate/index.d.ts +9 -1
  102. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  103. package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
  104. package/dist/types/loaders/agent.d.ts.map +1 -1
  105. package/dist/types/loaders/api/api.d.ts.map +1 -1
  106. package/dist/types/loaders/api/apiAsync.d.ts.map +1 -1
  107. package/dist/types/loaders/configure/configure.d.ts.map +1 -1
  108. package/dist/types/loaders/configure/public-path.d.ts +2 -0
  109. package/dist/types/loaders/configure/public-path.d.ts.map +1 -0
  110. package/dist/types/loaders/configure/public-path.npm.d.ts +2 -0
  111. package/dist/types/loaders/configure/public-path.npm.d.ts.map +1 -0
  112. package/package.json +1 -1
  113. package/src/cdn/pro.js +2 -0
  114. package/src/cdn/spa.js +2 -0
  115. package/src/common/config/state/init.js +4 -0
  116. package/src/common/constants/runtime.js +7 -3
  117. package/src/common/constants/runtime.test.js +8 -0
  118. package/src/common/harvest/harvest.js +6 -4
  119. package/src/common/harvest/harvest.test.js +17 -0
  120. package/src/common/vitals/__mocks__/web-vitals.js +19 -0
  121. package/src/common/vitals/constants.js +10 -0
  122. package/src/common/vitals/cumulative-layout-shift.js +13 -0
  123. package/src/common/vitals/cumulative-layout-shift.test.js +71 -0
  124. package/src/common/vitals/first-contentful-paint.js +31 -0
  125. package/src/common/vitals/first-contentful-paint.test.js +124 -0
  126. package/src/common/vitals/first-input-delay.js +20 -0
  127. package/src/common/vitals/first-input-delay.test.js +88 -0
  128. package/src/{features/page_view_timing → common/vitals}/first-paint.js +11 -17
  129. package/src/common/vitals/first-paint.test.js +127 -0
  130. package/src/common/vitals/interaction-to-next-paint.js +13 -0
  131. package/src/common/vitals/interaction-to-next-paint.test.js +74 -0
  132. package/src/common/vitals/largest-contentful-paint.js +29 -0
  133. package/src/common/vitals/largest-contentful-paint.test.js +94 -0
  134. package/src/common/vitals/long-task.js +52 -0
  135. package/src/common/vitals/long-task.test.js +122 -0
  136. package/src/common/vitals/time-to-first-byte.js +21 -0
  137. package/src/common/vitals/time-to-first-byte.test.js +147 -0
  138. package/src/common/vitals/vital-metric.js +60 -0
  139. package/src/common/vitals/vital-metric.test.js +171 -0
  140. package/src/features/ajax/aggregate/index.js +5 -1
  141. package/src/features/metrics/aggregate/index.js +6 -1
  142. package/src/features/page_view_event/aggregate/index.js +20 -43
  143. package/src/features/page_view_event/constants.js +0 -3
  144. package/src/features/page_view_event/instrument/index.js +0 -21
  145. package/src/features/page_view_timing/aggregate/index.component-test.js +86 -0
  146. package/src/features/page_view_timing/aggregate/index.js +24 -102
  147. package/src/features/page_view_timing/instrument/index.js +0 -3
  148. package/src/features/session_trace/aggregate/index.js +15 -1
  149. package/src/features/spa/aggregate/index.js +4 -3
  150. package/src/loaders/agent.js +2 -0
  151. package/src/loaders/api/api.js +2 -0
  152. package/src/loaders/api/apiAsync.js +5 -4
  153. package/src/loaders/configure/configure.js +15 -7
  154. package/src/loaders/configure/public-path.js +6 -0
  155. package/src/loaders/configure/public-path.npm.js +4 -0
  156. package/dist/cjs/common/metrics/paint-metrics.js +0 -13
  157. package/dist/cjs/features/page_view_timing/long-tasks.js +0 -75
  158. package/dist/esm/common/metrics/paint-metrics.js +0 -6
  159. package/dist/esm/features/page_view_timing/long-tasks.js +0 -69
  160. package/dist/types/common/metrics/paint-metrics.d.ts +0 -2
  161. package/dist/types/common/metrics/paint-metrics.d.ts.map +0 -1
  162. package/dist/types/features/page_view_timing/first-paint.d.ts +0 -2
  163. package/dist/types/features/page_view_timing/first-paint.d.ts.map +0 -1
  164. package/dist/types/features/page_view_timing/long-tasks.d.ts +0 -2
  165. package/dist/types/features/page_view_timing/long-tasks.d.ts.map +0 -1
  166. package/src/common/metrics/paint-metrics.js +0 -6
  167. package/src/features/page_view_timing/long-tasks.js +0 -60
package/README.md CHANGED
@@ -210,6 +210,10 @@ import { Agent } from '@newrelic/browser-agent/loaders/agent'
210
210
  import { Metrics } from '@newrelic/browser-agent/src/features/metrics'
211
211
  ```
212
212
 
213
+ ## Disclaimers
214
+
215
+ The session replay library shipping with this version of the browser agent is in *limited preview* and is not turned on by default. To use the feature, users will need to be part of the limited preview customer group and configure their browser application settings in the UI.
216
+
213
217
  ## Support
214
218
 
215
219
  New Relic hosts and moderates an online forum where customers can interact with New Relic employees as well as other customers to get help and share best practices. Like all official New Relic open source projects, there's a related Community topic in the New Relic Explorers Hub. You can find this project's topic/threads here:
@@ -7,13 +7,14 @@ var _instrument3 = require("../features/metrics/instrument");
7
7
  var _instrument4 = require("../features/jserrors/instrument");
8
8
  var _instrument5 = require("../features/ajax/instrument");
9
9
  var _instrument6 = require("../features/session_trace/instrument");
10
- var _instrument7 = require("../features/page_action/instrument");
10
+ var _instrument7 = require("../features/session_replay/instrument");
11
+ var _instrument8 = require("../features/page_action/instrument");
11
12
  /**
12
13
  * @file Creates a "Pro" agent loader bundle composed of the core Agent and all available feature modules except `spa`.
13
14
  * This excludes collection of BrowserInteraction and BrowserTiming events.
14
15
  */
15
16
 
16
17
  new _agent.Agent({
17
- features: [_instrument.Instrument, _instrument2.Instrument, _instrument6.Instrument, _instrument5.Instrument, _instrument3.Instrument, _instrument7.Instrument, _instrument4.Instrument],
18
+ features: [_instrument.Instrument, _instrument2.Instrument, _instrument6.Instrument, _instrument7.Instrument, _instrument5.Instrument, _instrument3.Instrument, _instrument8.Instrument, _instrument4.Instrument],
18
19
  loaderType: 'pro'
19
20
  });
@@ -7,13 +7,14 @@ var _instrument3 = require("../features/metrics/instrument");
7
7
  var _instrument4 = require("../features/jserrors/instrument");
8
8
  var _instrument5 = require("../features/ajax/instrument");
9
9
  var _instrument6 = require("../features/session_trace/instrument");
10
- var _instrument7 = require("../features/spa/instrument");
11
- var _instrument8 = require("../features/page_action/instrument");
10
+ var _instrument7 = require("../features/session_replay/instrument");
11
+ var _instrument8 = require("../features/spa/instrument");
12
+ var _instrument9 = require("../features/page_action/instrument");
12
13
  /**
13
14
  * @file Creates a "SPA" agent loader bundle composed of the core agent and all available feature modules.
14
15
  */
15
16
 
16
17
  new _agent.Agent({
17
- features: [_instrument5.Instrument, _instrument.Instrument, _instrument2.Instrument, _instrument6.Instrument, _instrument3.Instrument, _instrument8.Instrument, _instrument4.Instrument, _instrument7.Instrument],
18
+ features: [_instrument5.Instrument, _instrument.Instrument, _instrument2.Instrument, _instrument6.Instrument, _instrument7.Instrument, _instrument3.Instrument, _instrument9.Instrument, _instrument4.Instrument, _instrument8.Instrument],
18
19
  loaderType: 'spa'
19
20
  });
@@ -17,6 +17,12 @@ const model = () => {
17
17
  }
18
18
  };
19
19
  return {
20
+ proxy: {
21
+ assets: undefined,
22
+ // if this value is set, it will be used to overwrite the webpack asset path used to fetch assets
23
+ beacon: undefined // likewise for the url to which we send analytics
24
+ },
25
+
20
26
  privacy: {
21
27
  cookies_enabled: true
22
28
  },
@@ -12,7 +12,7 @@ exports.VERSION = exports.DIST_METHOD = exports.BUILD_ENV = void 0;
12
12
  /**
13
13
  * Exposes the version of the agent
14
14
  */
15
- const VERSION = "1.239.1";
15
+ const VERSION = "1.240.0";
16
16
 
17
17
  /**
18
18
  * Exposes the build type of the agent
@@ -12,7 +12,7 @@ exports.VERSION = exports.DIST_METHOD = exports.BUILD_ENV = void 0;
12
12
  /**
13
13
  * Exposes the version of the agent
14
14
  */
15
- const VERSION = "1.239.1";
15
+ const VERSION = "1.240.0";
16
16
 
17
17
  /**
18
18
  * Exposes the build type of the agent
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.supportsSendBeacon = exports.isiOS = exports.isWorkerScope = exports.isIE = exports.isBrowserScope = exports.initialLocation = exports.iOSBelow16 = exports.globalScope = exports.ffVersion = void 0;
6
+ exports.supportsSendBeacon = exports.offset = exports.isiOS = exports.isWorkerScope = exports.isIE = exports.isBrowserScope = exports.initiallyHidden = exports.initialLocation = exports.iOSBelow16 = exports.globalScope = exports.ffVersion = void 0;
7
7
  /**
8
8
  * @file Contains constants about the environment the agent is running
9
9
  * within. These values are derived at the time the agent is first loaded.
@@ -24,9 +24,11 @@ const isWorkerScope = typeof WorkerGlobalScope !== 'undefined' && (typeof self !
24
24
  exports.isWorkerScope = isWorkerScope;
25
25
  const globalScope = isBrowserScope ? window : typeof WorkerGlobalScope !== 'undefined' && (typeof self !== 'undefined' && self instanceof WorkerGlobalScope && self || typeof globalThis !== 'undefined' && globalThis instanceof WorkerGlobalScope && globalThis);
26
26
  exports.globalScope = globalScope;
27
+ const initiallyHidden = Boolean(globalScope?.document?.visibilityState === 'hidden');
28
+ exports.initiallyHidden = initiallyHidden;
27
29
  const initialLocation = '' + globalScope?.location;
28
30
  exports.initialLocation = initialLocation;
29
- const isiOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
31
+ const isiOS = /iPad|iPhone|iPod/.test(globalScope.navigator?.userAgent);
30
32
 
31
33
  /**
32
34
  * Shared Web Workers introduced in iOS 16.0+ and n/a in 15.6-
@@ -39,7 +41,7 @@ exports.isiOS = isiOS;
39
41
  const iOSBelow16 = isiOS && typeof SharedWorker === 'undefined';
40
42
  exports.iOSBelow16 = iOSBelow16;
41
43
  const ffVersion = (() => {
42
- const match = navigator.userAgent.match(/Firefox[/\s](\d+\.\d+)/);
44
+ const match = globalScope.navigator?.userAgent?.match(/Firefox[/\s](\d+\.\d+)/);
43
45
  if (Array.isArray(match) && match.length >= 2) {
44
46
  return +match[1];
45
47
  }
@@ -48,5 +50,7 @@ const ffVersion = (() => {
48
50
  exports.ffVersion = ffVersion;
49
51
  const isIE = Boolean(isBrowserScope && window.document.documentMode); // deprecated property that only works in IE
50
52
  exports.isIE = isIE;
51
- const supportsSendBeacon = !!navigator.sendBeacon;
52
- exports.supportsSendBeacon = supportsSendBeacon;
53
+ const supportsSendBeacon = !!globalScope.navigator?.sendBeacon;
54
+ exports.supportsSendBeacon = supportsSendBeacon;
55
+ const offset = Math.floor(globalScope?.performance?.timeOrigin || globalScope?.performance?.timing?.navigationStart || Date.now());
56
+ exports.offset = offset;
@@ -40,7 +40,6 @@ class Harvest extends _sharedContext.SharedContext {
40
40
 
41
41
  this.tooManyRequestsDelay = (0, _config.getConfigurationValue)(this.sharedContext.agentIdentifier, 'harvest.tooManyRequestsDelay') || 60;
42
42
  this.obfuscator = new _obfuscate.Obfuscator(this.sharedContext);
43
- this.getScheme = () => (0, _config.getConfigurationValue)(this.sharedContext.agentIdentifier, 'ssl') === false ? 'http' : 'https';
44
43
  this._events = {};
45
44
  }
46
45
 
@@ -131,10 +130,13 @@ class Harvest extends _sharedContext.SharedContext {
131
130
  }
132
131
  return false;
133
132
  }
133
+ const init = (0, _config.getConfiguration)(this.sharedContext.agentIdentifier);
134
+ const protocol = init.ssl === false ? 'http' : 'https';
135
+ const perceviedBeacon = init.proxy.beacon || info.errorBeacon;
134
136
  const endpointURLPart = endpoint !== 'rum' ? "/".concat(endpoint) : '';
135
- let url = "".concat(this.getScheme(), "://").concat(info.errorBeacon).concat(endpointURLPart, "/1/").concat(info.licenseKey);
137
+ let url = "".concat(protocol, "://").concat(perceviedBeacon).concat(endpointURLPart, "/1/").concat(info.licenseKey);
136
138
  if (customUrl) url = customUrl;
137
- if (raw) url = "".concat(this.getScheme(), "://").concat(info.errorBeacon, "/").concat(endpoint);
139
+ if (raw) url = "".concat(protocol, "://").concat(perceviedBeacon, "/").concat(endpoint);
138
140
  const baseParams = !raw && includeBaseParams ? this.baseQueryString() : '';
139
141
  let payloadParams = (0, _encode.obj)(qs, agentRuntime.maxBytes);
140
142
  if (!submitMethod) {
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.VITAL_NAMES = void 0;
7
+ const VITAL_NAMES = {
8
+ FIRST_PAINT: 'fp',
9
+ FIRST_CONTENTFUL_PAINT: 'fcp',
10
+ FIRST_INPUT_DELAY: 'fi',
11
+ LARGEST_CONTENTFUL_PAINT: 'lcp',
12
+ CUMULATIVE_LAYOUT_SHIFT: 'cls',
13
+ INTERACTION_TO_NEXT_PAINT: 'inp',
14
+ LONG_TASK: 'lt',
15
+ TIME_TO_FIRST_BYTE: 'ttfb'
16
+ };
17
+ exports.VITAL_NAMES = VITAL_NAMES;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.cumulativeLayoutShift = void 0;
7
+ var _webVitals = require("web-vitals");
8
+ var _constants = require("./constants");
9
+ var _vitalMetric = require("./vital-metric");
10
+ var _runtime = require("../constants/runtime");
11
+ const cumulativeLayoutShift = new _vitalMetric.VitalMetric(_constants.VITAL_NAMES.CUMULATIVE_LAYOUT_SHIFT, x => x);
12
+ exports.cumulativeLayoutShift = cumulativeLayoutShift;
13
+ if (_runtime.isBrowserScope) {
14
+ (0, _webVitals.onCLS)(_ref => {
15
+ let {
16
+ value,
17
+ entries
18
+ } = _ref;
19
+ if (cumulativeLayoutShift.roundingMethod(value) === cumulativeLayoutShift.current.value) return;
20
+ cumulativeLayoutShift.update({
21
+ value,
22
+ entries
23
+ });
24
+ }, {
25
+ reportAllChanges: true
26
+ });
27
+ }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.firstContentfulPaint = void 0;
7
+ var _webVitals = require("web-vitals");
8
+ var _runtime = require("../constants/runtime");
9
+ var _constants = require("./constants");
10
+ var _vitalMetric = require("./vital-metric");
11
+ // eslint-disable-next-line camelcase
12
+
13
+ const firstContentfulPaint = new _vitalMetric.VitalMetric(_constants.VITAL_NAMES.FIRST_CONTENTFUL_PAINT);
14
+
15
+ /* First Contentful Paint - As of WV v3, it still imperfectly tries to detect document vis state asap and isn't supposed to report if page starts hidden. */
16
+ exports.firstContentfulPaint = firstContentfulPaint;
17
+ if (_runtime.isBrowserScope) {
18
+ // eslint-disable-next-line camelcase
19
+ if (_runtime.iOSBelow16) {
20
+ try {
21
+ if (!_runtime.initiallyHidden) {
22
+ // see ios-version.js for detail on this following bug case; tldr: buffered flag doesn't work but getEntriesByType does
23
+ const paintEntries = performance.getEntriesByType('paint');
24
+ paintEntries.forEach(entry => {
25
+ if (entry.name === 'first-contentful-paint') {
26
+ firstContentfulPaint.update({
27
+ value: Math.floor(entry.startTime),
28
+ entries: paintEntries
29
+ });
30
+ }
31
+ });
32
+ }
33
+ } catch (e) {
34
+ // ignore
35
+ }
36
+ } else {
37
+ (0, _webVitals.onFCP)(_ref => {
38
+ let {
39
+ value,
40
+ entries
41
+ } = _ref;
42
+ if (_runtime.initiallyHidden || firstContentfulPaint.isValid) return;
43
+ firstContentfulPaint.update({
44
+ value,
45
+ entries
46
+ });
47
+ });
48
+ }
49
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.firstInputDelay = void 0;
7
+ var _webVitals = require("web-vitals");
8
+ var _vitalMetric = require("./vital-metric");
9
+ var _constants = require("./constants");
10
+ var _runtime = require("../constants/runtime");
11
+ const firstInputDelay = new _vitalMetric.VitalMetric(_constants.VITAL_NAMES.FIRST_INPUT_DELAY);
12
+ exports.firstInputDelay = firstInputDelay;
13
+ if (_runtime.isBrowserScope) {
14
+ (0, _webVitals.onFID)(_ref => {
15
+ let {
16
+ value,
17
+ entries
18
+ } = _ref;
19
+ if (_runtime.initiallyHidden || firstInputDelay.isValid || entries.length === 0) return;
20
+
21
+ // CWV will only report one (THE) first-input entry to us; fid isn't reported if there are no user interactions occurs before the *first* page hiding.
22
+ firstInputDelay.update({
23
+ value: entries[0].startTime,
24
+ entries,
25
+ attrs: {
26
+ type: entries[0].name,
27
+ fid: Math.round(value)
28
+ },
29
+ shouldAddConnectionAttributes: true
30
+ });
31
+ });
32
+ }
@@ -1,27 +1,31 @@
1
- /**
2
- * Calls the `onReport` function when the 'first-paint' PerformancePaintTiming entry is observed.
3
- * The argument supplied is an object similar to the Metric type used by web-vitals library.
4
- *
5
- * @param {Function} onReport - callback that accepts a `metric` object as the single parameter
6
- */
7
- export const onFirstPaint = onReport => {
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.firstPaint = void 0;
7
+ var _runtime = require("../constants/runtime");
8
+ var _constants = require("./constants");
9
+ var _vitalMetric = require("./vital-metric");
10
+ const firstPaint = new _vitalMetric.VitalMetric(_constants.VITAL_NAMES.FIRST_PAINT);
11
+ exports.firstPaint = firstPaint;
12
+ if (_runtime.isBrowserScope) {
8
13
  const handleEntries = entries => {
9
14
  entries.forEach(entry => {
10
- if (entry.name === 'first-paint') {
15
+ if (entry.name === 'first-paint' && !firstPaint.isValid) {
11
16
  observer.disconnect();
12
17
 
13
18
  /* Initial hidden state and pre-rendering not yet considered for first paint. See web-vitals onFCP for example. */
14
- const metric = {
15
- name: 'FP',
16
- value: entry.startTime
17
- };
18
- onReport(metric);
19
+ firstPaint.update({
20
+ value: entry.startTime,
21
+ entries
22
+ });
19
23
  }
20
24
  });
21
25
  };
22
26
  let observer;
23
27
  try {
24
- if (PerformanceObserver.supportedEntryTypes.includes('paint')) {
28
+ if (PerformanceObserver.supportedEntryTypes.includes('paint') && !_runtime.initiallyHidden) {
25
29
  observer = new PerformanceObserver(list => {
26
30
  // Delay by a microtask to workaround a bug in Safari where the
27
31
  // callback is invoked immediately, rather than in a separate task.
@@ -38,6 +42,4 @@ export const onFirstPaint = onReport => {
38
42
  } catch (e) {
39
43
  // Do nothing.
40
44
  }
41
-
42
- /* BFCache restore not yet considered for first paint. See web-vitals onFCP for example. */
43
- };
45
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.interactionToNextPaint = void 0;
7
+ var _webVitals = require("web-vitals");
8
+ var _vitalMetric = require("./vital-metric");
9
+ var _constants = require("./constants");
10
+ var _runtime = require("../constants/runtime");
11
+ const interactionToNextPaint = new _vitalMetric.VitalMetric(_constants.VITAL_NAMES.INTERACTION_TO_NEXT_PAINT);
12
+ exports.interactionToNextPaint = interactionToNextPaint;
13
+ if (_runtime.isBrowserScope) {
14
+ /* Interaction-to-Next-Paint */
15
+ (0, _webVitals.onINP)(_ref => {
16
+ let {
17
+ value,
18
+ entries,
19
+ id
20
+ } = _ref;
21
+ interactionToNextPaint.update({
22
+ value,
23
+ entries,
24
+ attrs: {
25
+ metricId: id
26
+ }
27
+ });
28
+ });
29
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.largestContentfulPaint = void 0;
7
+ var _webVitals = require("web-vitals");
8
+ var _vitalMetric = require("./vital-metric");
9
+ var _constants = require("./constants");
10
+ var _runtime = require("../constants/runtime");
11
+ var _cleanUrl = require("../url/clean-url");
12
+ const largestContentfulPaint = new _vitalMetric.VitalMetric(_constants.VITAL_NAMES.LARGEST_CONTENTFUL_PAINT);
13
+ exports.largestContentfulPaint = largestContentfulPaint;
14
+ if (_runtime.isBrowserScope) {
15
+ (0, _webVitals.onLCP)(_ref => {
16
+ let {
17
+ value,
18
+ entries
19
+ } = _ref;
20
+ /* Largest Contentful Paint - As of WV v3, it still imperfectly tries to detect document vis state asap and isn't supposed to report if page starts hidden. */
21
+ if (_runtime.initiallyHidden || largestContentfulPaint.isValid) return;
22
+ const lcpEntry = entries[entries.length - 1]; // this looks weird if we only expect one, but this is how cwv-attribution gets it so to be sure...
23
+ largestContentfulPaint.update({
24
+ value,
25
+ entries,
26
+ ...(entries.length > 0 && {
27
+ attrs: {
28
+ size: lcpEntry.size,
29
+ eid: lcpEntry.id,
30
+ ...(!!lcpEntry.url && {
31
+ elUrl: (0, _cleanUrl.cleanURL)(lcpEntry.url)
32
+ }),
33
+ ...(!!lcpEntry.element?.tagName && {
34
+ elTag: lcpEntry.element.tagName
35
+ })
36
+ }
37
+ }),
38
+ shouldAddConnectionAttributes: true
39
+ });
40
+ });
41
+ }
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.longTask = void 0;
7
+ var _runtime = require("../constants/runtime");
8
+ var _eol = require("../unload/eol");
9
+ var _constants = require("./constants");
10
+ var _vitalMetric = require("./vital-metric");
11
+ const longTask = new _vitalMetric.VitalMetric(_constants.VITAL_NAMES.LONG_TASK);
12
+ exports.longTask = longTask;
13
+ if (_runtime.isBrowserScope) {
14
+ const handleEntries = entries => {
15
+ entries.forEach(entry => {
16
+ longTask.update({
17
+ value: entry.duration,
18
+ entries: [entry],
19
+ attrs: {
20
+ ltFrame: entry.name,
21
+ // MDN: the browsing context or frame that can be attributed to the long task
22
+ ltStart: entry.startTime,
23
+ // MDN: a double representing the time (millisec) when the task started
24
+ ltCtr: entry.attribution[0].containerType,
25
+ // MDN: type of frame container: 'iframe', 'embed', or 'object' ... but this can also be 'window',
26
+ ...(entry.attribution[0].containerType !== 'window' && {
27
+ ltCtrSrc: entry.attribution[0].containerSrc,
28
+ // MDN: container's 'src' attribute
29
+ ltCtrId: entry.attribution[0].containerId,
30
+ // MDN: container's 'id' attribute
31
+ ltCtrName: entry.attribution[0].containerName // MDN: container's 'name' attribute
32
+ })
33
+ }
34
+ });
35
+ });
36
+ };
37
+
38
+ let observer;
39
+ try {
40
+ if (PerformanceObserver.supportedEntryTypes.includes('longtask')) {
41
+ observer = new PerformanceObserver(list => {
42
+ // Delay by a microtask to workaround a bug in Safari where the
43
+ // callback is invoked immediately, rather than in a separate task.
44
+ // See: https://github.com/GoogleChrome/web-vitals/issues/277
45
+ Promise.resolve().then(() => {
46
+ handleEntries(list.getEntries());
47
+ });
48
+ });
49
+ observer.observe({
50
+ type: 'longtask',
51
+ buffered: true
52
+ });
53
+ }
54
+ } catch (e) {
55
+ // Do nothing.
56
+ }
57
+ if (observer) {
58
+ (0, _eol.subscribeToEOL)(() => {
59
+ handleEntries(observer.takeRecords());
60
+ }, true); // this bool is a temp arg under staged BFCache work that runs the func under the new page session logic -- tb removed w/ the feature flag later
61
+
62
+ /* No work needed on BFCache restore for long task. */
63
+ }
64
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.timeToFirstByte = void 0;
7
+ var _runtime = require("../constants/runtime");
8
+ var _constants = require("./constants");
9
+ var _vitalMetric = require("./vital-metric");
10
+ var _webVitals = require("web-vitals");
11
+ const timeToFirstByte = new _vitalMetric.VitalMetric(_constants.VITAL_NAMES.TIME_TO_FIRST_BYTE);
12
+ exports.timeToFirstByte = timeToFirstByte;
13
+ if (_runtime.isBrowserScope && typeof PerformanceNavigationTiming !== 'undefined' && !_runtime.isiOS) {
14
+ (0, _webVitals.onTTFB)(_ref => {
15
+ let {
16
+ value,
17
+ entries
18
+ } = _ref;
19
+ if (!timeToFirstByte.isValid) timeToFirstByte.update({
20
+ value,
21
+ entries
22
+ });
23
+ });
24
+ } else {
25
+ if (!timeToFirstByte.isValid) {
26
+ const entry = {};
27
+ // convert real timestamps to relative timestamps to match web-vitals behavior
28
+ for (let key in _runtime.globalScope?.performance?.timing || {}) entry[key] = Math.max(_runtime.globalScope?.performance?.timing[key] - _runtime.offset, 0);
29
+
30
+ // ttfb is equiv to document's responseStart property in timing API --> https://developer.mozilla.org/en-US/docs/Web/API/PerformanceTiming/responseStart
31
+ timeToFirstByte.update({
32
+ value: entry.responseStart,
33
+ entries: [entry]
34
+ });
35
+ }
36
+ }
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.VitalMetric = void 0;
7
+ class VitalMetric {
8
+ #subscribers = new Set();
9
+ history = [];
10
+ constructor(name, roundingMethod) {
11
+ this.name = name;
12
+ this.attrs = {};
13
+ this.roundingMethod = typeof roundingMethod === 'function' ? roundingMethod : Math.floor;
14
+ }
15
+ update(_ref) {
16
+ let {
17
+ value,
18
+ entries = [],
19
+ attrs = {},
20
+ shouldAddConnectionAttributes = false
21
+ } = _ref;
22
+ if (value < 0) return;
23
+ const state = {
24
+ value: this.roundingMethod(value),
25
+ name: this.name,
26
+ entries,
27
+ attrs
28
+ };
29
+ if (shouldAddConnectionAttributes) addConnectionAttributes(state.attrs);
30
+ this.history.push(state);
31
+ this.#subscribers.forEach(cb => {
32
+ try {
33
+ cb(this.current);
34
+ } catch (e) {
35
+ // ignore errors
36
+ }
37
+ });
38
+ }
39
+ get current() {
40
+ return this.history[this.history.length - 1] || {
41
+ value: undefined,
42
+ name: this.name,
43
+ entries: [],
44
+ attrs: {}
45
+ };
46
+ }
47
+ get isValid() {
48
+ return this.current.value >= 0;
49
+ }
50
+ subscribe(callback) {
51
+ let buffered = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
52
+ if (typeof callback !== 'function') return;
53
+ this.#subscribers.add(callback);
54
+ // emit full history on subscription ("buffered" behavior)
55
+ if (this.isValid && !!buffered) this.history.forEach(state => {
56
+ callback(state);
57
+ });
58
+ return () => {
59
+ this.#subscribers.delete(callback);
60
+ };
61
+ }
62
+ }
63
+ exports.VitalMetric = VitalMetric;
64
+ function addConnectionAttributes(obj) {
65
+ var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection; // to date, both window & worker shares the same support for connection
66
+ if (!connection) return;
67
+ if (connection.type) obj['net-type'] = connection.type;
68
+ if (connection.effectiveType) obj['net-etype'] = connection.effectiveType;
69
+ if (connection.rtt) obj['net-rtt'] = connection.rtt;
70
+ if (connection.downlink) obj['net-dlink'] = connection.downlink;
71
+ }
@@ -71,6 +71,8 @@ class Aggregate extends _aggregateBase.AggregateBase {
71
71
  scheduler.startTimer(harvestTimeSeconds);
72
72
  });
73
73
  this.drain();
74
+ const beacon = (0, _config.getInfo)(agentIdentifier).errorBeacon;
75
+ const proxyBeacon = agentInit.proxy.beacon;
74
76
  function storeXhr(params, metrics, startTime, endTime, type) {
75
77
  metrics.time = startTime;
76
78
 
@@ -87,7 +89,8 @@ class Aggregate extends _aggregateBase.AggregateBase {
87
89
  aggregator.store('xhr', hash, params, metrics);
88
90
  if (!allAjaxIsEnabled) return;
89
91
  if (!(0, _denyList.shouldCollectEvent)(params)) {
90
- if (params.hostname === (0, _config.getInfo)(agentIdentifier).errorBeacon) {
92
+ if (params.hostname === beacon || proxyBeacon && params.hostname === proxyBeacon) {
93
+ // This doesn't make a distinction if the same-domain request is going to a different port or path...
91
94
  (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Ajax/Events/Excluded/Agent'], undefined, _features.FEATURE_NAMES.metrics, ee);
92
95
  } else {
93
96
  (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Ajax/Events/Excluded/App'], undefined, _features.FEATURE_NAMES.metrics, ee);
@@ -93,6 +93,13 @@ class Aggregate extends _aggregateBase.AggregateBase {
93
93
  const rules = (0, _obfuscate.getRules)(this.agentIdentifier);
94
94
  if (rules.length > 0) this.storeSupportabilityMetrics('Generic/Obfuscate/Detected');
95
95
  if (rules.length > 0 && !(0, _obfuscate.validateRules)(rules)) this.storeSupportabilityMetrics('Generic/Obfuscate/Invalid');
96
+
97
+ // Check if proxy for either chunks or beacon is being used
98
+ const {
99
+ proxy
100
+ } = (0, _config.getConfiguration)(this.agentIdentifier);
101
+ if (proxy.assets) this.storeSupportabilityMetrics('Config/AssetsUrl/Changed');
102
+ if (proxy.beacon) this.storeSupportabilityMetrics('Config/BeaconUrl/Changed');
96
103
  }
97
104
  eachSessionChecks() {
98
105
  if (!_runtime.isBrowserScope) return;