@newrelic/browser-agent 1.253.0 → 1.254.1

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 (159) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +1 -1
  3. package/dist/cjs/cdn/polyfills.js +2 -1
  4. package/dist/cjs/common/config/state/runtime.js +4 -1
  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/drain/drain.js +41 -27
  8. package/dist/cjs/common/event-emitter/contextual-ee.js +24 -22
  9. package/dist/cjs/common/harvest/harvest.js +5 -1
  10. package/dist/cjs/common/timing/time-keeper.js +89 -0
  11. package/dist/cjs/common/util/feature-flags.js +14 -31
  12. package/dist/cjs/common/wrap/wrap-events.js +2 -2
  13. package/dist/cjs/common/wrap/wrap-fetch.js +1 -2
  14. package/dist/cjs/common/wrap/wrap-function.js +7 -5
  15. package/dist/cjs/common/wrap/wrap-promise.js +1 -2
  16. package/dist/cjs/features/ajax/aggregate/index.js +7 -13
  17. package/dist/cjs/features/jserrors/aggregate/index.js +25 -24
  18. package/dist/cjs/features/metrics/aggregate/index.js +25 -24
  19. package/dist/cjs/features/page_action/aggregate/index.js +6 -4
  20. package/dist/cjs/features/page_view_event/aggregate/index.js +23 -2
  21. package/dist/cjs/features/page_view_timing/aggregate/index.js +15 -16
  22. package/dist/cjs/features/session_replay/aggregate/index.js +12 -4
  23. package/dist/cjs/features/session_trace/aggregate/index.js +11 -8
  24. package/dist/cjs/features/soft_navigations/aggregate/index.js +17 -12
  25. package/dist/cjs/features/spa/aggregate/index.js +19 -14
  26. package/dist/cjs/features/utils/aggregate-base.js +18 -5
  27. package/dist/cjs/features/utils/feature-base.js +2 -0
  28. package/dist/cjs/features/utils/instrument-base.js +1 -0
  29. package/dist/cjs/loaders/agent-base.js +2 -7
  30. package/dist/cjs/loaders/agent.js +4 -4
  31. package/dist/cjs/loaders/api/api.js +1 -1
  32. package/dist/cjs/loaders/configure/configure.js +1 -1
  33. package/dist/cjs/loaders/configure/nonce.cdn.js +13 -0
  34. package/dist/cjs/loaders/configure/nonce.js +2 -13
  35. package/dist/cjs/loaders/configure/public-path.cdn.js +16 -0
  36. package/dist/cjs/loaders/configure/public-path.js +2 -8
  37. package/dist/esm/cdn/polyfills.js +2 -1
  38. package/dist/esm/common/config/state/runtime.js +4 -1
  39. package/dist/esm/common/constants/env.cdn.js +1 -1
  40. package/dist/esm/common/constants/env.npm.js +1 -1
  41. package/dist/esm/common/drain/drain.js +40 -27
  42. package/dist/esm/common/event-emitter/contextual-ee.js +24 -22
  43. package/dist/esm/common/harvest/harvest.js +5 -1
  44. package/dist/esm/common/timing/time-keeper.js +83 -0
  45. package/dist/esm/common/util/feature-flags.js +14 -31
  46. package/dist/esm/common/wrap/wrap-events.js +3 -3
  47. package/dist/esm/common/wrap/wrap-fetch.js +2 -3
  48. package/dist/esm/common/wrap/wrap-function.js +5 -4
  49. package/dist/esm/common/wrap/wrap-promise.js +2 -3
  50. package/dist/esm/features/ajax/aggregate/index.js +7 -13
  51. package/dist/esm/features/jserrors/aggregate/index.js +25 -24
  52. package/dist/esm/features/metrics/aggregate/index.js +25 -24
  53. package/dist/esm/features/page_action/aggregate/index.js +6 -4
  54. package/dist/esm/features/page_view_event/aggregate/index.js +23 -2
  55. package/dist/esm/features/page_view_timing/aggregate/index.js +15 -16
  56. package/dist/esm/features/session_replay/aggregate/index.js +12 -4
  57. package/dist/esm/features/session_trace/aggregate/index.js +11 -8
  58. package/dist/esm/features/soft_navigations/aggregate/index.js +17 -12
  59. package/dist/esm/features/spa/aggregate/index.js +19 -14
  60. package/dist/esm/features/utils/aggregate-base.js +18 -5
  61. package/dist/esm/features/utils/feature-base.js +2 -0
  62. package/dist/esm/features/utils/instrument-base.js +1 -0
  63. package/dist/esm/loaders/agent-base.js +2 -7
  64. package/dist/esm/loaders/agent.js +4 -4
  65. package/dist/esm/loaders/api/api.js +1 -1
  66. package/dist/esm/loaders/configure/configure.js +1 -1
  67. package/dist/esm/loaders/configure/nonce.cdn.js +11 -0
  68. package/dist/esm/loaders/configure/nonce.js +1 -11
  69. package/dist/esm/loaders/configure/public-path.cdn.js +9 -0
  70. package/dist/esm/loaders/configure/public-path.js +2 -8
  71. package/dist/types/common/config/state/runtime.d.ts.map +1 -1
  72. package/dist/types/common/drain/drain.d.ts +6 -0
  73. package/dist/types/common/drain/drain.d.ts.map +1 -1
  74. package/dist/types/common/event-emitter/contextual-ee.d.ts +4 -3
  75. package/dist/types/common/event-emitter/contextual-ee.d.ts.map +1 -1
  76. package/dist/types/common/event-emitter/event-context.d.ts.map +1 -0
  77. package/dist/types/common/harvest/harvest.d.ts.map +1 -1
  78. package/dist/types/common/timing/time-keeper.d.ts +37 -0
  79. package/dist/types/common/timing/time-keeper.d.ts.map +1 -0
  80. package/dist/types/common/util/feature-flags.d.ts +11 -2
  81. package/dist/types/common/util/feature-flags.d.ts.map +1 -1
  82. package/dist/types/common/wrap/wrap-fetch.d.ts.map +1 -1
  83. package/dist/types/common/wrap/wrap-function.d.ts +1 -0
  84. package/dist/types/common/wrap/wrap-function.d.ts.map +1 -1
  85. package/dist/types/common/wrap/wrap-promise.d.ts.map +1 -1
  86. package/dist/types/features/ajax/aggregate/index.d.ts +5 -5
  87. package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
  88. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  89. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  90. package/dist/types/features/page_action/aggregate/index.d.ts.map +1 -1
  91. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  92. package/dist/types/features/page_view_timing/aggregate/index.d.ts +0 -2
  93. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  94. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  95. package/dist/types/features/soft_navigations/aggregate/index.d.ts +0 -2
  96. package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
  97. package/dist/types/features/spa/aggregate/index.d.ts +2 -0
  98. package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
  99. package/dist/types/features/utils/aggregate-base.d.ts +2 -2
  100. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
  101. package/dist/types/features/utils/feature-base.d.ts +1 -0
  102. package/dist/types/features/utils/feature-base.d.ts.map +1 -1
  103. package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
  104. package/dist/types/loaders/agent-base.d.ts +2 -2
  105. package/dist/types/loaders/agent-base.d.ts.map +1 -1
  106. package/dist/types/loaders/configure/public-path.d.ts +1 -1
  107. package/dist/types/loaders/configure/public-path.d.ts.map +1 -1
  108. package/package.json +1 -1
  109. package/src/cdn/polyfills.js +1 -0
  110. package/src/common/config/state/runtime.js +4 -1
  111. package/src/common/drain/drain.js +41 -28
  112. package/src/common/event-emitter/contextual-ee.js +29 -31
  113. package/src/common/harvest/harvest.js +4 -1
  114. package/src/common/timing/time-keeper.js +90 -0
  115. package/src/common/util/feature-flags.js +13 -31
  116. package/src/common/wrap/wrap-events.js +3 -3
  117. package/src/common/wrap/wrap-fetch.js +2 -3
  118. package/src/common/wrap/wrap-function.js +6 -4
  119. package/src/common/wrap/wrap-promise.js +2 -3
  120. package/src/features/ajax/aggregate/index.js +8 -16
  121. package/src/features/jserrors/aggregate/index.js +12 -14
  122. package/src/features/metrics/aggregate/index.js +18 -17
  123. package/src/features/page_action/aggregate/index.js +6 -5
  124. package/src/features/page_view_event/aggregate/index.js +21 -2
  125. package/src/features/page_view_timing/aggregate/index.js +15 -15
  126. package/src/features/session_replay/aggregate/index.js +10 -4
  127. package/src/features/session_trace/aggregate/index.js +2 -2
  128. package/src/features/soft_navigations/aggregate/index.js +14 -12
  129. package/src/features/spa/aggregate/index.js +15 -13
  130. package/src/features/utils/aggregate-base.js +16 -8
  131. package/src/features/utils/feature-base.js +3 -0
  132. package/src/features/utils/instrument-base.js +1 -0
  133. package/src/loaders/agent-base.js +2 -7
  134. package/src/loaders/agent.js +2 -2
  135. package/src/loaders/api/api.js +1 -1
  136. package/src/loaders/configure/nonce.cdn.js +12 -0
  137. package/src/loaders/configure/nonce.js +1 -12
  138. package/src/loaders/configure/public-path.cdn.js +9 -0
  139. package/src/loaders/configure/public-path.js +2 -8
  140. package/dist/cjs/common/context/observation-context-manager.js +0 -56
  141. package/dist/cjs/loaders/configure/nonce.npm.js +0 -2
  142. package/dist/cjs/loaders/configure/public-path.npm.js +0 -10
  143. package/dist/esm/common/context/observation-context-manager.js +0 -49
  144. package/dist/esm/loaders/configure/nonce.npm.js +0 -1
  145. package/dist/esm/loaders/configure/public-path.npm.js +0 -3
  146. package/dist/types/common/context/event-context.d.ts.map +0 -1
  147. package/dist/types/common/context/observation-context-manager.d.ts +0 -28
  148. package/dist/types/common/context/observation-context-manager.d.ts.map +0 -1
  149. package/dist/types/loaders/configure/nonce.npm.d.ts +0 -1
  150. package/dist/types/loaders/configure/nonce.npm.d.ts.map +0 -1
  151. package/dist/types/loaders/configure/public-path.npm.d.ts +0 -2
  152. package/dist/types/loaders/configure/public-path.npm.d.ts.map +0 -1
  153. package/src/common/context/observation-context-manager.js +0 -55
  154. package/src/loaders/configure/nonce.npm.js +0 -1
  155. package/src/loaders/configure/public-path.npm.js +0 -3
  156. /package/dist/cjs/common/{context → event-emitter}/event-context.js +0 -0
  157. /package/dist/esm/common/{context → event-emitter}/event-context.js +0 -0
  158. /package/dist/types/common/{context → event-emitter}/event-context.d.ts +0 -0
  159. /package/src/common/{context → event-emitter}/event-context.js +0 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,28 @@
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.254.1](https://github.com/newrelic/newrelic-browser-agent/compare/v1.254.0...v1.254.1) (2024-03-26)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * Server Timing - Remove reliance on performance API ([#930](https://github.com/newrelic/newrelic-browser-agent/issues/930)) ([250efcd](https://github.com/newrelic/newrelic-browser-agent/commit/250efcd3bf0a730adbb9d5c45be0bf2f71189664))
12
+
13
+ ## [1.254.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.253.0...v1.254.0) (2024-03-25)
14
+
15
+
16
+ ### Features
17
+
18
+ * Add rum-response metadata handler ([#913](https://github.com/newrelic/newrelic-browser-agent/issues/913)) ([2c99a5b](https://github.com/newrelic/newrelic-browser-agent/commit/2c99a5b11300ea9ef9ee7b5158b9d42c00693d03))
19
+ * Calculate New Relic time in the agent ([#911](https://github.com/newrelic/newrelic-browser-agent/issues/911)) ([91b1f96](https://github.com/newrelic/newrelic-browser-agent/commit/91b1f96efafe19f7b1b3fd4f39b9af1136b0a3a8))
20
+ * maintain a harvestCount for use later with harvestId ([#922](https://github.com/newrelic/newrelic-browser-agent/issues/922)) ([d0b5b7d](https://github.com/newrelic/newrelic-browser-agent/commit/d0b5b7d644b8ffc3667bf3b2521733cc7940f982))
21
+ * Standardize all feature behavior to wait for RUM response ([#927](https://github.com/newrelic/newrelic-browser-agent/issues/927)) ([ac266fa](https://github.com/newrelic/newrelic-browser-agent/commit/ac266faea203a7edc01ddecabbfdcc13bf602081))
22
+
23
+
24
+ ### Bug Fixes
25
+
26
+ * Remove webpack imports in npm package ([#925](https://github.com/newrelic/newrelic-browser-agent/issues/925)) ([7b35238](https://github.com/newrelic/newrelic-browser-agent/commit/7b35238d53df97ca0183f06642601eb381aad063))
27
+
6
28
  ## [1.253.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.252.1...v1.253.0) (2024-03-13)
7
29
 
8
30
 
package/README.md CHANGED
@@ -259,7 +259,7 @@ For more details on how best to contribute, see [CONTRIBUTING.md](CONTRIBUTING.m
259
259
 
260
260
  As noted in our [security policy](https://github.com/newrelic/newrelic-browser-agent/security/policy), New Relic is committed to the privacy and security of our customers and their data. We believe that providing coordinated disclosure by security researchers and engaging with the security community are important means to achieve our security goals.
261
261
 
262
- If you believe you have found a security vulnerability in this project or any of New Relic's products or websites, we welcome and greatly appreciate you reporting it to New Relic through [HackerOne](https://hackerone.com/newrelic).
262
+ If you believe you have found a security vulnerability in this project or any of New Relic's products or websites, we welcome and greatly appreciate you reporting it to New Relic through [our bug bounty program](https://docs.newrelic.com/docs/security/security-privacy/information-security/report-security-vulnerabilities/).
263
263
 
264
264
  If you would like to contribute to this project, review [these guidelines](./CONTRIBUTING.md).
265
265
 
@@ -18,4 +18,5 @@ require("core-js/stable/weak-set");
18
18
  require("core-js/stable/object/get-own-property-descriptors");
19
19
  require("core-js/stable/url");
20
20
  require("core-js/stable/url-search-params");
21
- require("core-js/stable/string/starts-with");
21
+ require("core-js/stable/string/starts-with");
22
+ require("core-js/stable/number/is-nan");
@@ -24,10 +24,13 @@ const model = {
24
24
  origin: '' + _runtime.globalScope.location,
25
25
  ptid: undefined,
26
26
  releaseIds: {},
27
+ /** Agent-specific metadata found in the RUM call response. ex. entityGuid */
28
+ appMetadata: {},
27
29
  session: undefined,
28
30
  xhrWrappable: typeof _runtime.globalScope.XMLHttpRequest?.prototype?.addEventListener === 'function',
29
31
  version: _env.VERSION,
30
- denyList: undefined
32
+ denyList: undefined,
33
+ harvestCount: 0
31
34
  };
32
35
  const _cache = {};
33
36
  function getRuntime(id) {
@@ -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.253.0";
15
+ const VERSION = exports.VERSION = "1.254.1";
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.253.0";
15
+ const VERSION = exports.VERSION = "1.254.1";
16
16
 
17
17
  /**
18
18
  * Exposes the build type of the agent
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.deregisterDrain = deregisterDrain;
6
7
  exports.drain = drain;
7
8
  exports.registerDrain = registerDrain;
8
9
  var _contextualEe = require("../event-emitter/contextual-ee");
@@ -35,13 +36,24 @@ function registerDrain(agentIdentifier, group) {
35
36
  if (!registry[agentIdentifier].get(group)) registry[agentIdentifier].set(group, item);
36
37
  }
37
38
 
39
+ /**
40
+ * Removes an item from the registry and immediately re-checks if the registry is ready to "drain all"
41
+ * @param {*} agentIdentifier - A 16 character string uniquely identifying the agent.
42
+ * @param {*} group - The named "bucket" to be removed from the registry
43
+ */
44
+ function deregisterDrain(agentIdentifier, group) {
45
+ curateRegistry(agentIdentifier);
46
+ if (registry[agentIdentifier].get(group)) registry[agentIdentifier].delete(group);
47
+ if (registry[agentIdentifier].size) checkCanDrainAll(agentIdentifier);
48
+ }
49
+
38
50
  /**
39
51
  * Registers the specified agent with the centralized event buffer registry if it is not already registered.
40
52
  * Agents without an identifier (as in the case of some tests) will be excluded from the registry.
41
53
  * @param {string} agentIdentifier - A 16 character string uniquely identifying an agent.
42
54
  */
43
55
  function curateRegistry(agentIdentifier) {
44
- if (!agentIdentifier) return;
56
+ if (!agentIdentifier) throw new Error('agentIdentifier required');
45
57
  if (!registry[agentIdentifier]) registry[agentIdentifier] = new Map();
46
58
  }
47
59
 
@@ -60,11 +72,15 @@ function drain() {
60
72
  // If the feature for the specified agent is not in the registry, that means the instrument file was bypassed.
61
73
  // This could happen in tests, or loaders that directly import the aggregator. In these cases it is safe to
62
74
  // drain the feature group immediately rather than waiting to drain all at once.
63
- if (!agentIdentifier || !registry[agentIdentifier].get(featureName) || force) return drainGroup(featureName);
75
+ if (!agentIdentifier || !registry[agentIdentifier].get(featureName) || force) return drainGroup(agentIdentifier, featureName);
64
76
 
65
77
  // When `drain` is called, this feature is ready to drain (staged).
66
78
  registry[agentIdentifier].get(featureName).staged = true;
79
+ checkCanDrainAll(agentIdentifier);
80
+ }
67
81
 
82
+ /** Checks all items in the registry to see if they have been "staged". If ALL items are staged, it will drain all registry items (drainGroup). It not, nothing will happen */
83
+ function checkCanDrainAll(agentIdentifier) {
68
84
  // Only when the event-groups for all features are ready to drain (staged) do we execute the drain. This has the effect
69
85
  // that the last feature to call drain triggers drain for all features.
70
86
  const items = [...registry[agentIdentifier]];
@@ -76,40 +92,38 @@ function drain() {
76
92
  items.forEach(_ref2 => {
77
93
  let [group] = _ref2;
78
94
  registry[agentIdentifier].delete(group);
79
- drainGroup(group);
95
+ drainGroup(agentIdentifier, group);
80
96
  });
81
97
  }
98
+ }
82
99
 
83
- /**
100
+ /**
84
101
  * Drains all the buffered (backlog) events for a particular feature's event-group by emitting each event to each of
85
102
  * the subscribed handlers for the group.
86
103
  * @param {*} group - The name of a particular feature's event "bucket".
87
104
  */
88
- function drainGroup(group) {
89
- const baseEE = agentIdentifier ? _contextualEe.ee.get(agentIdentifier) : _contextualEe.ee;
90
- const handlers = _registerHandler.registerHandler.handlers;
91
- if (!baseEE.backlog || !handlers) return;
92
- var bufferedEventsInGroup = baseEE.backlog[group];
93
- var groupHandlers = handlers[group];
94
- if (groupHandlers) {
95
- // We don't cache the length of the buffer while looping because events might still be added while processing.
96
- for (var i = 0; bufferedEventsInGroup && i < bufferedEventsInGroup.length; ++i) {
97
- // eslint-disable-line no-unmodified-loop-condition
98
- emitEvent(bufferedEventsInGroup[i], groupHandlers);
99
- }
100
- (0, _mapOwn.mapOwn)(groupHandlers, function (eventType, handlerRegistrationList) {
101
- (0, _mapOwn.mapOwn)(handlerRegistrationList, function (i, registration) {
102
- // registration is an array of: [targetEE, eventHandler]
103
- registration[0].on(eventType, registration[1]);
104
- });
105
- });
105
+ function drainGroup(agentIdentifier, group) {
106
+ const baseEE = agentIdentifier ? _contextualEe.ee.get(agentIdentifier) : _contextualEe.ee;
107
+ const handlers = _registerHandler.registerHandler.handlers; // other storage in registerHandler
108
+ if (!baseEE.backlog || !handlers) return;
109
+ var bufferedEventsInGroup = baseEE.backlog[group];
110
+ var groupHandlers = handlers[group]; // each group in the registerHandler storage
111
+ if (groupHandlers) {
112
+ // We don't cache the length of the buffer while looping because events might still be added while processing.
113
+ for (var i = 0; bufferedEventsInGroup && i < bufferedEventsInGroup.length; ++i) {
114
+ // eslint-disable-line no-unmodified-loop-condition
115
+ emitEvent(bufferedEventsInGroup[i], groupHandlers);
106
116
  }
107
- delete handlers[group];
108
-
109
- // Keep the feature's event-group as a property of the event emitter so we know it was already created and drained.
110
- baseEE.backlog[group] = null;
111
- baseEE.emit('drain-' + group, []);
117
+ (0, _mapOwn.mapOwn)(groupHandlers, function (eventType, handlerRegistrationList) {
118
+ (0, _mapOwn.mapOwn)(handlerRegistrationList, function (i, registration) {
119
+ // registration is an array of: [targetEE, eventHandler]
120
+ registration[0].on(eventType, registration[1]);
121
+ });
122
+ });
112
123
  }
124
+ if (!baseEE.isolatedBacklog) delete handlers[group];
125
+ baseEE.backlog[group] = null;
126
+ baseEE.emit('drain-' + group, []);
113
127
  }
114
128
 
115
129
  /**
@@ -3,17 +3,19 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.ee = void 0;
6
+ exports.ee = exports.contextId = void 0;
7
7
  var _nreum = require("../window/nreum");
8
8
  var _getOrSet = require("../util/get-or-set");
9
9
  var _config = require("../config/config");
10
- var _eventContext = require("../context/event-context");
11
- var _observationContextManager = require("../context/observation-context-manager");
10
+ var _eventContext = require("./event-context");
11
+ var _bundleId = require("../ids/bundle-id");
12
12
  /*
13
13
  * Copyright 2020 New Relic Corporation. All rights reserved.
14
14
  * SPDX-License-Identifier: Apache-2.0
15
15
  */
16
16
 
17
+ // create a unique id to store event context data for the current agent bundle
18
+ const contextId = exports.contextId = "nr@context:".concat(_bundleId.bundleId);
17
19
  // create global emitter instance that can be shared among bundles
18
20
  const globalInstance = exports.ee = ee(undefined, 'globalEE');
19
21
 
@@ -48,20 +50,34 @@ function ee(old, debugId) {
48
50
  context,
49
51
  buffer: bufferEventsByGroup,
50
52
  abort,
51
- aborted: false,
52
53
  isBuffering,
53
54
  debugId,
54
55
  backlog: isolatedBacklog ? {} : old && typeof old.backlog === 'object' ? old.backlog : {},
55
- observationContextManager: null
56
+ isolatedBacklog
56
57
  };
58
+ function abort() {
59
+ emitter._aborted = true;
60
+ Object.keys(emitter.backlog).forEach(key => {
61
+ delete emitter.backlog[key];
62
+ });
63
+ }
64
+ Object.defineProperty(emitter, 'aborted', {
65
+ get: () => {
66
+ let aborted = emitter._aborted || false;
67
+ if (aborted) return aborted;else if (old) {
68
+ aborted = old.aborted;
69
+ }
70
+ return aborted;
71
+ }
72
+ });
57
73
  return emitter;
58
74
  function context(contextOrStore) {
59
75
  if (contextOrStore && contextOrStore instanceof _eventContext.EventContext) {
60
76
  return contextOrStore;
61
77
  } else if (contextOrStore) {
62
- return (0, _getOrSet.getOrSet)(contextOrStore, _observationContextManager.ObservationContextManager.contextId, () => emitter.observationContextManager ? emitter.observationContextManager.getCreateContext(contextOrStore) : new _eventContext.EventContext(_observationContextManager.ObservationContextManager.contextId));
78
+ return (0, _getOrSet.getOrSet)(contextOrStore, contextId, () => new _eventContext.EventContext(contextId));
63
79
  } else {
64
- return emitter.observationContextManager ? emitter.observationContextManager.getCreateContext({}) : new _eventContext.EventContext(_observationContextManager.ObservationContextManager.contextId);
80
+ return new _eventContext.EventContext(contextId);
65
81
  }
66
82
  }
67
83
  function emit(type, args, contextOrStore, force, bubble) {
@@ -105,11 +121,7 @@ function ee(old, debugId) {
105
121
  return handlers[type] || [];
106
122
  }
107
123
  function getOrCreate(name) {
108
- const newEventEmitter = emitters[name] = emitters[name] || ee(emitter, name);
109
- if (!newEventEmitter.observationContextManager && emitter.observationContextManager) {
110
- newEventEmitter.observationContextManager = emitter.observationContextManager;
111
- }
112
- return newEventEmitter;
124
+ return emitters[name] = emitters[name] || ee(emitter, name);
113
125
  }
114
126
  function bufferEventsByGroup(types, group) {
115
127
  const eventBuffer = getBuffer();
@@ -135,14 +147,4 @@ function ee(old, debugId) {
135
147
  function getBuffer() {
136
148
  return emitter.backlog;
137
149
  }
138
- }
139
- function abort() {
140
- globalInstance.aborted = true;
141
- // The global backlog can be referenced directly by other emitters,
142
- // so we need to delete its contents as opposed to replacing it.
143
- // Otherwise, these references to the old backlog would still exist
144
- // and the keys will not be garbage collected.
145
- Object.keys(globalInstance.backlog).forEach(key => {
146
- delete globalInstance.backlog[key];
147
- });
148
150
  }
@@ -185,7 +185,9 @@ class Harvest extends _sharedContext.SharedContext {
185
185
  // status 0 refers to a local error, such as CORS or network failure, or a blocked request by the browser (e.g. adblocker)
186
186
  const cbResult = {
187
187
  sent: this.status !== 0,
188
- status: this.status
188
+ status: this.status,
189
+ xhr: this,
190
+ fullUrl
189
191
  };
190
192
  if (this.status === 429) {
191
193
  cbResult.retry = true;
@@ -199,6 +201,8 @@ class Harvest extends _sharedContext.SharedContext {
199
201
  cbFinished(cbResult);
200
202
  }, (0, _eventListenerOpts.eventListenerOpts)(false));
201
203
  }
204
+ const runtime = (0, _config.getRuntime)(this.sharedContext.agentIdentifier);
205
+ runtime.harvestCount++;
202
206
  return result;
203
207
  }
204
208
 
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.TimeKeeper = void 0;
7
+ var _nreum = require("../window/nreum");
8
+ var _config = require("../config/config");
9
+ /**
10
+ * Class used to adjust the timestamp of harvested data to New Relic server time. This
11
+ * is done by tracking the performance timings of the RUM call and applying a calculation
12
+ * to the harvested data event offset time.
13
+ */
14
+ class TimeKeeper {
15
+ #agent;
16
+
17
+ /**
18
+ * Represents the browser origin time corrected to NR server time.
19
+ * @type {number}
20
+ */
21
+ #correctedOriginTime;
22
+
23
+ /**
24
+ * Represents the difference in milliseconds between the calculated NR server time and
25
+ * the local time.
26
+ * @type {number}
27
+ */
28
+ #localTimeDiff;
29
+ constructor(agent) {
30
+ this.#agent = agent;
31
+ }
32
+ static getTimeKeeperByAgentIdentifier(agentIdentifier) {
33
+ const nr = (0, _nreum.gosNREUM)();
34
+ return Object.keys(nr?.initializedAgents || {}).indexOf(agentIdentifier) > -1 ? nr.initializedAgents[agentIdentifier].timeKeeper : undefined;
35
+ }
36
+ get correctedPageOriginTime() {
37
+ return this.#correctedOriginTime;
38
+ }
39
+
40
+ /**
41
+ * Process a rum request to calculate NR server time.
42
+ * @param rumRequest {XMLHttpRequest} The xhr for the rum request
43
+ * @param startTime {number} The start time of the RUM request
44
+ * @param endTime {number} The end time of the RUM request
45
+ */
46
+ processRumRequest(rumRequest, startTime, endTime) {
47
+ const responseDateHeader = rumRequest.getResponseHeader('Date');
48
+ if (!responseDateHeader) {
49
+ throw new Error('Missing date header on rum response.');
50
+ }
51
+ const medianRumOffset = (endTime - startTime) / 2;
52
+ const serverOffset = Math.floor(startTime + medianRumOffset);
53
+
54
+ // Corrected page origin time
55
+ this.#correctedOriginTime = Math.floor(Date.parse(responseDateHeader) - serverOffset);
56
+ this.#localTimeDiff = (0, _config.getRuntime)(this.#agent.agentIdentifier).offset - this.#correctedOriginTime;
57
+ if (Number.isNaN(this.#correctedOriginTime)) {
58
+ throw new Error('Date header invalid format.');
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Converts a page origin relative time to an absolute timestamp
64
+ * corrected to NR server time.
65
+ * @param relativeTime {number} The relative time of the event in milliseconds
66
+ * @returns {number} The correct timestamp as a unix/epoch timestamp value
67
+ */
68
+ convertRelativeTimestamp(relativeTime) {
69
+ return this.#correctedOriginTime + relativeTime;
70
+ }
71
+
72
+ /**
73
+ * Corrects an event timestamp to NR server time.
74
+ * @param timestamp {number} The unix/epoch timestamp of the event with milliseconds
75
+ * @return {number} Corrected unix/epoch timestamp
76
+ */
77
+ correctAbsoluteTimestamp(timestamp) {
78
+ return Math.floor(timestamp - this.#localTimeDiff);
79
+ }
80
+
81
+ /**
82
+ * Returns the current time offset from page origin.
83
+ * @return {number}
84
+ */
85
+ now() {
86
+ return Math.floor(performance.now());
87
+ }
88
+ }
89
+ exports.TimeKeeper = TimeKeeper;
@@ -6,52 +6,35 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.activateFeatures = activateFeatures;
7
7
  exports.activatedFeatures = void 0;
8
8
  var _contextualEe = require("../event-emitter/contextual-ee");
9
- var _handle = require("../event-emitter/handle");
10
- var _features = require("../../loaders/features/features");
11
9
  var _globalEvent = require("../dispatch/global-event");
12
10
  /*
13
11
  * Copyright 2020 New Relic Corporation. All rights reserved.
14
12
  * SPDX-License-Identifier: Apache-2.0
15
13
  */
16
14
 
17
- const bucketMap = {
18
- stn: [_features.FEATURE_NAMES.sessionTrace],
19
- err: [_features.FEATURE_NAMES.jserrors, _features.FEATURE_NAMES.metrics],
20
- ins: [_features.FEATURE_NAMES.pageAction],
21
- spa: [_features.FEATURE_NAMES.spa, _features.FEATURE_NAMES.softNav],
22
- sr: [_features.FEATURE_NAMES.sessionReplay, _features.FEATURE_NAMES.sessionTrace]
23
- };
24
15
  const sentIds = new Set();
25
16
 
26
- /** Note that this function only processes each unique flag ONCE, with the first occurrence of each flag and numeric value determining its switch on/off setting. */
17
+ /** A map of feature flags and their values as provided by the rum call -- scoped by agent ID */
18
+ const activatedFeatures = exports.activatedFeatures = {};
19
+
20
+ /**
21
+ * Sets the activatedFeatures object, dispatches the global loaded event,
22
+ * and emits the rumresp flag to features
23
+ * @param {{[key:string]:number}} flags key-val pair of flag names and numeric
24
+ * @param {string} agentIdentifier agent instance identifier
25
+ * @returns {void}
26
+ */
27
27
  function activateFeatures(flags, agentIdentifier) {
28
28
  const sharedEE = _contextualEe.ee.get(agentIdentifier);
29
+ activatedFeatures[agentIdentifier] ??= {};
29
30
  if (!(flags && typeof flags === 'object')) return;
30
31
  if (sentIds.has(agentIdentifier)) return;
31
- Object.entries(flags).forEach(_ref => {
32
- let [flag, num] = _ref;
33
- if (bucketMap[flag]) {
34
- bucketMap[flag].forEach(feat => {
35
- if (!num) (0, _handle.handle)('block-' + flag, [], undefined, feat, sharedEE);else (0, _handle.handle)('feat-' + flag, [], undefined, feat, sharedEE);
36
- (0, _handle.handle)('rumresp-' + flag, [Boolean(num)], undefined, feat, sharedEE); // this is a duplicate of feat-/block- but makes awaiting for 1 event easier than 2
37
- });
38
- } else if (num) (0, _handle.handle)('feat-' + flag, [], undefined, undefined, sharedEE); // not sure what other flags are overlooked, but there's a test for ones not in the map --
39
- activatedFeatures[flag] = Boolean(num);
40
- });
41
-
42
- // Let the features waiting on their respective flags know that RUM response was received and that any missing flags are interpreted as bad entitlement / "off".
43
- // Hence, those features will not be hanging forever if their flags aren't included in the response.
44
- Object.keys(bucketMap).forEach(flag => {
45
- if (activatedFeatures[flag] === undefined) {
46
- bucketMap[flag]?.forEach(feat => (0, _handle.handle)('rumresp-' + flag, [false], undefined, feat, sharedEE));
47
- activatedFeatures[flag] = false;
48
- }
49
- });
32
+ sharedEE.emit('rumresp', [flags]);
33
+ activatedFeatures[agentIdentifier] = flags;
50
34
  sentIds.add(agentIdentifier);
51
35
 
52
36
  // let any window level subscribers know that the agent is running
53
37
  (0, _globalEvent.dispatchGlobalEvent)({
54
38
  loaded: true
55
39
  });
56
- }
57
- const activatedFeatures = exports.activatedFeatures = {};
40
+ }
@@ -9,7 +9,6 @@ var _contextualEe = require("../event-emitter/contextual-ee");
9
9
  var _wrapFunction = require("./wrap-function");
10
10
  var _getOrSet = require("../util/get-or-set");
11
11
  var _runtime = require("../constants/runtime");
12
- var _observationContextManager = require("../context/observation-context-manager");
13
12
  /*
14
13
  * Copyright 2020 New Relic Corporation. All rights reserved.
15
14
  * SPDX-License-Identifier: Apache-2.0
@@ -24,6 +23,7 @@ const wrapped = {};
24
23
  const XHR = _runtime.globalScope.XMLHttpRequest;
25
24
  const ADD_EVENT_LISTENER = 'addEventListener';
26
25
  const REMOVE_EVENT_LISTENER = 'removeEventListener';
26
+ const flag = "nr@wrapped:".concat(_contextualEe.contextId);
27
27
 
28
28
  /**
29
29
  * Wraps `addEventListener` and `removeEventListener` on: global scope; the prototype of `XMLHttpRequest`, and
@@ -52,7 +52,7 @@ function wrapEvents(sharedEE) {
52
52
  if (originalListener === null || typeof originalListener !== 'function' && typeof originalListener !== 'object') {
53
53
  return;
54
54
  }
55
- var wrapped = (0, _getOrSet.getOrSet)(originalListener, _observationContextManager.ObservationContextManager.contextWrappedId, function () {
55
+ var wrapped = (0, _getOrSet.getOrSet)(originalListener, flag, function () {
56
56
  var listener = {
57
57
  object: wrapHandleEvent,
58
58
  function: originalListener
@@ -7,7 +7,6 @@ exports.scopedEE = scopedEE;
7
7
  exports.wrapFetch = wrapFetch;
8
8
  var _contextualEe = require("../event-emitter/contextual-ee");
9
9
  var _runtime = require("../constants/runtime");
10
- var _observationContextManager = require("../context/observation-context-manager");
11
10
  /*
12
11
  * Copyright 2020 New Relic Corporation. All rights reserved.
13
12
  * SPDX-License-Identifier: Apache-2.0
@@ -79,7 +78,7 @@ function wrapFetch(sharedEE) {
79
78
  // we are wrapping args in an array so we can preserve the reference
80
79
  ee.emit(prefix + 'before-start', [args], ctx);
81
80
  var dtPayload;
82
- if (ctx[_observationContextManager.ObservationContextManager.contextId] && ctx[_observationContextManager.ObservationContextManager.contextId].dt) dtPayload = ctx[_observationContextManager.ObservationContextManager.contextId].dt;
81
+ if (ctx[_contextualEe.contextId] && ctx[_contextualEe.contextId].dt) dtPayload = ctx[_contextualEe.contextId].dt;
83
82
  var origPromiseFromFetch = fn.apply(this, args);
84
83
  ee.emit(prefix + 'start', [args, dtPayload], origPromiseFromFetch);
85
84
 
@@ -4,9 +4,9 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.createWrapperWithEmitter = createWrapperWithEmitter;
7
- exports.default = void 0;
7
+ exports.flag = exports.default = void 0;
8
8
  var _contextualEe = require("../event-emitter/contextual-ee");
9
- var _observationContextManager = require("../context/observation-context-manager");
9
+ var _bundleId = require("../ids/bundle-id");
10
10
  /*
11
11
  * Copyright 2020 New Relic Corporation. All rights reserved.
12
12
  * SPDX-License-Identifier: Apache-2.0
@@ -15,6 +15,8 @@ var _observationContextManager = require("../context/observation-context-manager
15
15
  * @file Provides helper functions for wrapping functions in various scenarios.
16
16
  */
17
17
 
18
+ const flag = exports.flag = "nr@original:".concat(_bundleId.bundleId);
19
+
18
20
  /**
19
21
  * A convenience alias of `hasOwnProperty`.
20
22
  * @type {function}
@@ -44,7 +46,7 @@ function createWrapperWithEmitter(emitter, always) {
44
46
  * As a property on a wrapped function, contains the original function.
45
47
  * @type {string}
46
48
  */
47
- wrapFn.flag = _observationContextManager.ObservationContextManager.contextOriginalId;
49
+ wrapFn.flag = flag;
48
50
  return wrapFn;
49
51
 
50
52
  /**
@@ -60,7 +62,7 @@ function createWrapperWithEmitter(emitter, always) {
60
62
  // Unless fn is both wrappable and unwrapped, return it unchanged.
61
63
  if (notWrappable(fn)) return fn;
62
64
  if (!prefix) prefix = '';
63
- nrWrapper[_observationContextManager.ObservationContextManager.contextOriginalId] = fn;
65
+ nrWrapper[flag] = fn;
64
66
  copy(fn, nrWrapper, emitter);
65
67
  return nrWrapper;
66
68
 
@@ -214,5 +216,5 @@ function copy(from, to, emitter) {
214
216
  * @returns {boolean} Whether the passed function is ineligible to be wrapped.
215
217
  */
216
218
  function notWrappable(fn) {
217
- return !(fn && typeof fn === 'function' && fn.apply && !fn[_observationContextManager.ObservationContextManager.contextOriginalId]);
219
+ return !(fn && typeof fn === 'function' && fn.apply && !fn[flag]);
218
220
  }
@@ -8,7 +8,6 @@ exports.wrapPromise = wrapPromise;
8
8
  var _wrapFunction = require("./wrap-function");
9
9
  var _contextualEe = require("../event-emitter/contextual-ee");
10
10
  var _runtime = require("../constants/runtime");
11
- var _observationContextManager = require("../context/observation-context-manager");
12
11
  /*
13
12
  * Copyright 2020 New Relic Corporation. All rights reserved.
14
13
  * SPDX-License-Identifier: Apache-2.0
@@ -126,7 +125,7 @@ function wrapPromise(sharedEE) {
126
125
  promiseEE.emit('propagate', [originalThis, true], origFnCallWithThis, false, false);
127
126
  return origFnCallWithThis;
128
127
  };
129
- prevPromiseObj.prototype.then[_observationContextManager.ObservationContextManager.contextOriginalId] = prevPromiseOrigThen;
128
+ prevPromiseObj.prototype.then[_wrapFunction.flag] = prevPromiseOrigThen;
130
129
  promiseEE.on('executor-start', function (args) {
131
130
  args[0] = promiseWrapper(args[0], 'resolve-', this, null, false);
132
131
  args[1] = promiseWrapper(args[1], 'resolve-', this, null, false);
@@ -27,12 +27,15 @@ class Aggregate extends _aggregateBase.AggregateBase {
27
27
  constructor(agentIdentifier, aggregator) {
28
28
  super(agentIdentifier, aggregator, _constants.FEATURE_NAME);
29
29
  const agentInit = (0, _config.getConfiguration)(agentIdentifier);
30
- const allAjaxIsEnabled = agentInit.ajax.enabled !== false;
31
30
  (0, _registerHandler.registerHandler)('xhr', storeXhr, this.featureName, this.ee);
32
- if (!allAjaxIsEnabled) {
31
+ this.waitForFlags([]).then(() => {
32
+ const scheduler = new _harvestScheduler.HarvestScheduler('events', {
33
+ onFinished: onEventsHarvestFinished,
34
+ getPayload: prepareHarvest
35
+ }, this);
36
+ scheduler.startTimer(harvestTimeSeconds);
33
37
  this.drain();
34
- return; // feature will only collect timeslice metrics & ajax trace nodes if it's not fully enabled
35
- }
38
+ });
36
39
  const denyList = (0, _config.getRuntime)(agentIdentifier).denyList;
37
40
  (0, _denyList.setDenyList)(denyList);
38
41
  let ajaxEvents = [];
@@ -68,14 +71,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
68
71
  (0, _registerHandler.registerHandler)('returnAjax', event => ajaxEvents.push(event), this.featureName, this.ee);
69
72
  // --- ^
70
73
 
71
- const scheduler = new _harvestScheduler.HarvestScheduler('events', {
72
- onFinished: onEventsHarvestFinished,
73
- getPayload: prepareHarvest
74
- }, this);
75
- ee.on("drain-".concat(this.featureName), () => {
76
- scheduler.startTimer(harvestTimeSeconds);
77
- });
78
- this.drain();
79
74
  const beacon = (0, _config.getInfo)(agentIdentifier).errorBeacon;
80
75
  const proxyBeacon = agentInit.proxy.beacon;
81
76
  function storeXhr(params, metrics, startTime, endTime, type) {
@@ -95,7 +90,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
95
90
  if (shouldCollect || !ajaxMetricDenyListEnabled) {
96
91
  aggregator.store('xhr', hash, params, metrics);
97
92
  }
98
- if (!allAjaxIsEnabled) return;
99
93
  if (!shouldCollect) {
100
94
  if (params.hostname === beacon || proxyBeacon && params.hostname === proxyBeacon) {
101
95
  // This doesn't make a distinction if the same-domain request is going to a different port or path...