@newrelic/browser-agent 1.301.0-rc.0 → 1.301.0-rc.2

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 (133) hide show
  1. package/dist/cjs/common/config/init-types.js +1 -1
  2. package/dist/cjs/common/config/init.js +7 -1
  3. package/dist/cjs/common/config/runtime.js +1 -1
  4. package/dist/cjs/common/constants/agent-constants.js +11 -2
  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 +1 -1
  8. package/dist/cjs/common/harvest/harvester.js +30 -39
  9. package/dist/cjs/common/util/mfe.js +45 -0
  10. package/dist/cjs/features/generic_events/aggregate/index.js +9 -8
  11. package/dist/cjs/features/generic_events/constants.js +3 -1
  12. package/dist/cjs/features/jserrors/aggregate/index.js +18 -17
  13. package/dist/cjs/features/logging/aggregate/index.js +19 -15
  14. package/dist/cjs/features/logging/shared/utils.js +3 -3
  15. package/dist/cjs/features/page_view_event/aggregate/index.js +3 -33
  16. package/dist/cjs/features/session_replay/aggregate/index.js +13 -13
  17. package/dist/cjs/features/session_replay/shared/recorder.js +3 -2
  18. package/dist/cjs/features/session_trace/aggregate/index.js +0 -2
  19. package/dist/cjs/features/soft_navigations/aggregate/index.js +1 -2
  20. package/dist/cjs/features/utils/aggregate-base.js +45 -47
  21. package/dist/cjs/loaders/api/addPageAction.js +2 -2
  22. package/dist/cjs/loaders/api/log.js +2 -2
  23. package/dist/cjs/loaders/api/noticeError.js +2 -2
  24. package/dist/cjs/loaders/api/register-api-types.js +5 -5
  25. package/dist/cjs/loaders/api/register.js +80 -97
  26. package/dist/esm/common/config/init-types.js +1 -1
  27. package/dist/esm/common/config/init.js +7 -1
  28. package/dist/esm/common/config/runtime.js +1 -1
  29. package/dist/esm/common/constants/agent-constants.js +9 -1
  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/drain/drain.js +1 -1
  33. package/dist/esm/common/harvest/harvester.js +30 -39
  34. package/dist/esm/common/util/mfe.js +38 -0
  35. package/dist/esm/features/generic_events/aggregate/index.js +9 -8
  36. package/dist/esm/features/generic_events/constants.js +3 -1
  37. package/dist/esm/features/jserrors/aggregate/index.js +18 -17
  38. package/dist/esm/features/logging/aggregate/index.js +19 -15
  39. package/dist/esm/features/logging/shared/utils.js +3 -3
  40. package/dist/esm/features/page_view_event/aggregate/index.js +3 -33
  41. package/dist/esm/features/session_replay/aggregate/index.js +13 -13
  42. package/dist/esm/features/session_replay/shared/recorder.js +3 -2
  43. package/dist/esm/features/session_trace/aggregate/index.js +0 -2
  44. package/dist/esm/features/soft_navigations/aggregate/index.js +1 -2
  45. package/dist/esm/features/utils/aggregate-base.js +46 -48
  46. package/dist/esm/loaders/api/addPageAction.js +2 -2
  47. package/dist/esm/loaders/api/log.js +2 -2
  48. package/dist/esm/loaders/api/noticeError.js +2 -2
  49. package/dist/esm/loaders/api/register-api-types.js +5 -5
  50. package/dist/esm/loaders/api/register.js +80 -97
  51. package/dist/tsconfig.tsbuildinfo +1 -1
  52. package/dist/types/common/config/init-types.d.ts +4 -1
  53. package/dist/types/common/config/init-types.d.ts.map +1 -1
  54. package/dist/types/common/config/init.d.ts.map +1 -1
  55. package/dist/types/common/constants/agent-constants.d.ts +7 -4
  56. package/dist/types/common/constants/agent-constants.d.ts.map +1 -1
  57. package/dist/types/common/harvest/harvester.d.ts +2 -2
  58. package/dist/types/common/harvest/harvester.d.ts.map +1 -1
  59. package/dist/types/common/util/mfe.d.ts +20 -0
  60. package/dist/types/common/util/mfe.d.ts.map +1 -0
  61. package/dist/types/features/generic_events/aggregate/index.d.ts +2 -2
  62. package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
  63. package/dist/types/features/generic_events/constants.d.ts +1 -0
  64. package/dist/types/features/jserrors/aggregate/index.d.ts +3 -3
  65. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  66. package/dist/types/features/logging/aggregate/index.d.ts +3 -3
  67. package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
  68. package/dist/types/features/logging/shared/utils.d.ts +2 -2
  69. package/dist/types/features/logging/shared/utils.d.ts.map +1 -1
  70. package/dist/types/features/page_view_event/aggregate/index.d.ts +2 -4
  71. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  72. package/dist/types/features/session_replay/aggregate/index.d.ts +13 -4
  73. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  74. package/dist/types/features/session_replay/shared/recorder.d.ts +1 -0
  75. package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
  76. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  77. package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
  78. package/dist/types/features/utils/aggregate-base.d.ts +13 -5
  79. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
  80. package/dist/types/loaders/api/addPageAction.d.ts +1 -1
  81. package/dist/types/loaders/api/addPageAction.d.ts.map +1 -1
  82. package/dist/types/loaders/api/log.d.ts +1 -1
  83. package/dist/types/loaders/api/log.d.ts.map +1 -1
  84. package/dist/types/loaders/api/noticeError.d.ts +1 -1
  85. package/dist/types/loaders/api/noticeError.d.ts.map +1 -1
  86. package/dist/types/loaders/api/register-api-types.d.ts +4 -4
  87. package/dist/types/loaders/api/register-api-types.d.ts.map +1 -1
  88. package/dist/types/loaders/api/register.d.ts +8 -1
  89. package/dist/types/loaders/api/register.d.ts.map +1 -1
  90. package/package.json +1 -1
  91. package/src/common/config/init-types.js +1 -1
  92. package/src/common/config/init.js +3 -1
  93. package/src/common/config/runtime.js +1 -1
  94. package/src/common/constants/agent-constants.js +10 -0
  95. package/src/common/drain/drain.js +1 -1
  96. package/src/common/harvest/harvester.js +27 -32
  97. package/src/common/util/mfe.js +35 -0
  98. package/src/features/generic_events/aggregate/index.js +9 -8
  99. package/src/features/generic_events/constants.js +3 -1
  100. package/src/features/jserrors/aggregate/index.js +17 -17
  101. package/src/features/logging/aggregate/index.js +20 -13
  102. package/src/features/logging/shared/utils.js +3 -3
  103. package/src/features/page_view_event/aggregate/index.js +3 -28
  104. package/src/features/session_replay/aggregate/index.js +12 -10
  105. package/src/features/session_replay/shared/recorder.js +3 -2
  106. package/src/features/session_trace/aggregate/index.js +0 -2
  107. package/src/features/soft_navigations/aggregate/index.js +1 -2
  108. package/src/features/utils/aggregate-base.js +47 -42
  109. package/src/loaders/api/addPageAction.js +2 -2
  110. package/src/loaders/api/log.js +2 -2
  111. package/src/loaders/api/noticeError.js +2 -2
  112. package/src/loaders/api/register-api-types.js +5 -5
  113. package/src/loaders/api/register.js +62 -89
  114. package/dist/cjs/common/util/target.js +0 -34
  115. package/dist/cjs/features/utils/entity-manager.js +0 -46
  116. package/dist/cjs/features/utils/event-store-manager.js +0 -174
  117. package/dist/cjs/loaders/api/register-api.js +0 -165
  118. package/dist/esm/common/util/target.js +0 -27
  119. package/dist/esm/features/utils/entity-manager.js +0 -39
  120. package/dist/esm/features/utils/event-store-manager.js +0 -166
  121. package/dist/esm/loaders/api/register-api.js +0 -159
  122. package/dist/types/common/util/target.d.ts +0 -18
  123. package/dist/types/common/util/target.d.ts.map +0 -1
  124. package/dist/types/features/utils/entity-manager.d.ts +0 -11
  125. package/dist/types/features/utils/entity-manager.d.ts.map +0 -1
  126. package/dist/types/features/utils/event-store-manager.d.ts +0 -85
  127. package/dist/types/features/utils/event-store-manager.d.ts.map +0 -1
  128. package/dist/types/loaders/api/register-api.d.ts +0 -14
  129. package/dist/types/loaders/api/register-api.d.ts.map +0 -1
  130. package/src/common/util/target.js +0 -27
  131. package/src/features/utils/entity-manager.js +0 -45
  132. package/src/features/utils/event-store-manager.js +0 -165
  133. package/src/loaders/api/register-api.js +0 -152
@@ -14,6 +14,16 @@ export class AggregateBase extends FeatureBase {
14
14
  isRetrying: boolean;
15
15
  harvestOpts: {};
16
16
  events: any;
17
+ /** @type {Boolean} indicates if the feature supports registered entities and the harvest requirements therein. Also read by getter "harvestEndpointVersion". Controlled by feature flag in pre-release phase. */
18
+ get supportsRegisteredEntities(): boolean;
19
+ /**
20
+ * the endpoint version the feature uses during harvests
21
+ * @type {number}
22
+ * @returns {boolean}
23
+ */
24
+ get harvestEndpointVersion(): number;
25
+ waitForDrain(): void;
26
+ drained: boolean | undefined;
17
27
  /**
18
28
  * Evaluates whether a harvest should be made early by estimating the size of the current payload. Currently, this only happens if the event storage is EventBuffer, since that triggers this method directly.
19
29
  * If conditions are met, a new harvest will be triggered immediately.
@@ -30,26 +40,24 @@ export class AggregateBase extends FeatureBase {
30
40
  * Stages the feature to be drained
31
41
  */
32
42
  drain(): void;
33
- drained: boolean | undefined;
34
43
  preHarvestChecks(opts: any): boolean;
35
44
  /**
36
45
  * Return harvest payload. A "serializer" function can be defined on a derived class to format the payload.
37
46
  * @param {Boolean} shouldRetryOnFail - harvester flag to backup payload for retry later if harvest request fails; this should be moved to harvester logic
38
47
  * @param {object|undefined} opts - opts passed from the harvester to help form the payload
39
- * @param {string} opts.targetEntityGuid - the entity guid of the target app
48
+ * @param {string} opts.target - the target app metadata
40
49
  * @returns {Array} Final payload tagged with their targeting browser app. The value of `payload` can be undefined if there are no pending events for an app. This should be a minimum length of 1.
41
50
  */
42
51
  makeHarvestPayload(shouldRetryOnFail?: boolean, opts?: object | undefined): any[];
43
52
  /**
44
53
  * Cleanup task after a harvest.
45
54
  * @param {object} result - the cbResult object from the harvester's send method
46
- * @param {object=} result.targetApp - the target app object that was used to point the harvest to the correct app
47
- * @param {string=} result.targetApp.entityGuid - the entity guid of the target app
48
55
  * @param {boolean=} result.sent - whether the harvest was sent successfully
49
56
  * @param {boolean=} result.retry - whether the harvest should be retried
50
57
  */
51
58
  postHarvestCleanup(result?: {
52
- targetApp?: object | undefined;
59
+ sent?: boolean | undefined;
60
+ retry?: boolean | undefined;
53
61
  }): void;
54
62
  /**
55
63
  * Checks for additional `jsAttributes` items to support backward compatibility with implementations of the agent where
@@ -1 +1 @@
1
- {"version":3,"file":"aggregate-base.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/aggregate-base.js"],"names":[],"mappings":"AAsBA;IACE;;;;OAIG;IACH,sBAHW,MAAM,eACN,MAAM,EA2BhB;IAvBC,iBAAwB;IAIxB,uOAAuO;IACvO,qCAAwC;IACxC,gLAAgL;IAChL,yBAA2B;IAC3B,sFAAsF;IACtF,oBAAuB;IAEvB,gBAAqB;IA4BjB,YAAwJ;IAW9J;;;;OAIG;IACH,2BAOC;IAED;;;;OAIG;IACH,yBAHW,MAAM,EAAE,gBAwBlB;IAED;;OAEG;IACH,cAGC;IADC,6BAAmB;IAGrB,qCAEC;IAED;;;;;;OAMG;IACH,uDAJW,MAAM,GAAC,SAAS,SAyB1B;IAED;;;;;;;OAOG;IACH,4BALG;QAAwB,SAAS,GAAzB,MAAM,YAAC;KACf,QAQF;IAED;;;OAGG;IACH,6CAsBC;IAED;;;OAGG;IACH,2CAOC;IALC,gBAA6C;IAO/C;;;;OAIG;IACH,uCAHW,GAAC,UACD,GAAC,QAIX;;CACF;4BA/N2B,gBAAgB"}
1
+ {"version":3,"file":"aggregate-base.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/aggregate-base.js"],"names":[],"mappings":"AAmBA;IACE;;;;OAIG;IACH,sBAHW,MAAM,eACN,MAAM,EAoBhB;IAhBC,iBAAwB;IAIxB,uOAAuO;IACvO,qCAAwC;IACxC,gLAAgL;IAChL,yBAA2B;IAC3B,sFAAsF;IACtF,oBAAuB;IAEvB,gBAAqB;IAqBjB,YAAsE;IAW5E,iNAAiN;IACjN,0CAEC;IAED;;;;OAIG;IACH,8BAHU,MAAM,CAKf;IAED,qBAOC;IAFG,6BAAmB;IAIvB;;;;OAIG;IACH,2BAOC;IAED;;;;OAIG;IACH,yBAHW,MAAM,EAAE,gBAwBlB;IAED;;OAEG;IACH,cAEC;IAED,qCAEC;IAED;;;;;;OAMG;IACH,uDAJW,MAAM,GAAC,SAAS,SAsB1B;IAED;;;;;OAKG;IACH,4BAHG;QAAyB,IAAI,GAArB,OAAO,YAAC;QACS,KAAK,GAAtB,OAAO,YAAC;KAClB,QAKA;IAED;;;OAGG;IACH,6CAsBC;IAED;;;OAGG;IACH,2CAKC;IAHC,gBAA6C;IAK/C;;;;OAIG;IACH,uCAHW,GAAC,UACD,GAAC,QAIX;;CACF;4BApO2B,gBAAgB"}
@@ -1,3 +1,3 @@
1
1
  export function setupAddPageActionAPI(agent: any): void;
2
- export function addPageAction(name: any, attributes: any, agentRef: any, targetEntityGuid: any, timestamp?: number): void;
2
+ export function addPageAction(name: any, attributes: any, agentRef: any, target: any, timestamp?: number): void;
3
3
  //# sourceMappingURL=addPageAction.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"addPageAction.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/addPageAction.js"],"names":[],"mappings":"AAUA,wDAEC;AAED,0HAEC"}
1
+ {"version":3,"file":"addPageAction.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/addPageAction.js"],"names":[],"mappings":"AAUA,wDAEC;AAED,gHAEC"}
@@ -2,5 +2,5 @@ export function setupLogAPI(agent: any): void;
2
2
  export function log(message: any, { customAttributes, level }: {
3
3
  customAttributes?: {} | undefined;
4
4
  level?: string | undefined;
5
- } | undefined, agentRef: any, targetEntityGuid: any, timestamp?: number): void;
5
+ } | undefined, agentRef: any, target: any, timestamp?: number): void;
6
6
  //# sourceMappingURL=log.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/log.js"],"names":[],"mappings":"AAWA,8CAEC;AAED;;;+EAEC"}
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/log.js"],"names":[],"mappings":"AAWA,8CAEC;AAED;;;qEAEC"}
@@ -1,3 +1,3 @@
1
1
  export function setupNoticeErrorAPI(agent: any): void;
2
- export function noticeError(err: any, customAttributes: any, agentRef: any, targetEntityGuid: any, timestamp?: number): void;
2
+ export function noticeError(err: any, customAttributes: any, agentRef: any, target: any, timestamp?: number): void;
3
3
  //# sourceMappingURL=noticeError.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"noticeError.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/noticeError.js"],"names":[],"mappings":"AAUA,sDAEC;AAED,6HAIC"}
1
+ {"version":3,"file":"noticeError.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/noticeError.js"],"names":[],"mappings":"AAUA,sDAEC;AAED,mHAIC"}
@@ -35,8 +35,8 @@ export type RegisterAPIConstructor = {
35
35
  * - The options for the registered entity.
36
36
  */
37
37
  opts: {
38
- licenseKey: string;
39
- applicationID: string;
38
+ id: string;
39
+ name: string;
40
40
  };
41
41
  };
42
42
  export type RegisterAPIMetadata = {
@@ -49,8 +49,8 @@ export type RegisterAPIMetadata = {
49
49
  */
50
50
  target: {
51
51
  licenseKey: string;
52
- applicationID: string;
53
- entityGuid: string;
52
+ id: string;
53
+ name: string;
54
54
  };
55
55
  };
56
56
  //# sourceMappingURL=register-api-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"register-api-types.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/register-api-types.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAac,mBAAmB;;;;;;UAM9B;QAAwB,UAAU,EAAvB,MAAM;QACO,aAAa,EAA1B,MAAM;KACnB;;;;;;sBAIa,MAAM;;;;YAEjB;QAA0B,UAAU,EAAzB,MAAM;QACS,aAAa,EAA5B,MAAM;QACS,UAAU,EAAzB,MAAM;KACnB"}
1
+ {"version":3,"file":"register-api-types.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/register-api-types.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAac,mBAAmB;;;;;;UAM9B;QAAwB,EAAE,EAAf,MAAM;QACO,IAAI,EAAjB,MAAM;KACnB;;;;;;sBAIa,MAAM;;;;YAEjB;QAA0B,UAAU,EAAzB,MAAM;QACS,EAAE,EAAjB,MAAM;QACS,IAAI,EAAnB,MAAM;KACnB"}
@@ -13,8 +13,15 @@ export function setupRegisterAPI(agent: any): void;
13
13
  * @param {Object} agentRef the reference to the base agent instance
14
14
  * @param {Object} handlers the shared handlers to be used by both the base agent's API and the external target's API
15
15
  * @param {Object} target the target information to be used by the external target's API to send data to the correct location
16
+ * @param {string} [target.licenseKey] the license key of the target to report data to
17
+ * @param {string} target.id the entity ID of the target to report data to
18
+ * @param {string} target.name the entity name of the target to report data to
16
19
  * @returns {RegisterAPI} the api object to be returned from the register api method
17
20
  */
18
- export function buildRegisterApi(agentRef: Object, target: Object): RegisterAPI;
21
+ export function buildRegisterApi(agentRef: Object, target: {
22
+ licenseKey?: string | undefined;
23
+ id: string;
24
+ name: string;
25
+ }): RegisterAPI;
19
26
  export type RegisterAPI = import("./register-api-types").RegisterAPI;
20
27
  //# sourceMappingURL=register.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/register.js"],"names":[],"mappings":"AAgBA;;GAEG;AAEH;;;;GAIG;AACH,mDAIC;AAED;;;;;;;GAOG;AACH,2CALW,MAAM,UAEN,MAAM,GACJ,WAAW,CAkIvB;0BAtJY,OAAO,sBAAsB,EAAE,WAAW"}
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/register.js"],"names":[],"mappings":"AAiBA;;GAEG;AAEH;;;;GAIG;AACH,mDAIC;AAED;;;;;;;;;;GAUG;AACH,2CARW,MAAM,UAGd;IAAwB,UAAU;IACX,EAAE,EAAjB,MAAM;IACS,IAAI,EAAnB,MAAM;CACd,GAAU,WAAW,CAmGvB;0BA1HY,OAAO,sBAAsB,EAAE,WAAW"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newrelic/browser-agent",
3
- "version": "1.301.0-rc.0",
3
+ "version": "1.301.0-rc.2",
4
4
  "private": false,
5
5
  "author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
6
6
  "description": "New Relic Browser Agent",
@@ -35,7 +35,7 @@
35
35
  * @property {Object} [metrics]
36
36
  * @property {boolean} [metrics.enabled] - Turn on/off the metrics feature (on by default).
37
37
  * @property {boolean} [metrics.autoStart] - If true, the agent will automatically start the metrics feature. Otherwise, it will be in a deferred state until the `start` API method is called.
38
- * @property {Array<Object>} [obfuscate] - Array of regexp and corresponding replacement patterns for obfuscating data.
38
+ * @property {{regex: RegExp | string, replacement: string}[]} [obfuscate] - Array of regexp and corresponding replacement patterns for obfuscating data.
39
39
  * @property {Object} [page_action]
40
40
  * @property {boolean} [page_action.enabled] - Must be true to allow PageAction events to be captured.
41
41
  * @property {Object} [page_view_event]
@@ -21,6 +21,7 @@ const InitModelFn = () => {
21
21
  const hiddenState = {
22
22
  feature_flags: [],
23
23
  experimental: {
24
+ allow_registered_children: false,
24
25
  resources: false
25
26
  },
26
27
  mask_selector: '*',
@@ -48,7 +49,8 @@ const InitModelFn = () => {
48
49
  return {
49
50
  ajax: { deny_list: undefined, block_internal: true, enabled: true, autoStart: true },
50
51
  api: {
51
- allow_registered_children: true,
52
+ get allow_registered_children () { return hiddenState.feature_flags.includes(FEATURE_FLAGS.REGISTER) || hiddenState.experimental.allow_registered_children },
53
+ set allow_registered_children (val) { hiddenState.experimental.allow_registered_children = val },
52
54
  duplicate_registered_data: false
53
55
  },
54
56
  distributed_tracing: {
@@ -25,7 +25,6 @@ const RuntimeModel = {
25
25
  customTransaction: undefined,
26
26
  denyList: undefined,
27
27
  disabled: false,
28
- entityManager: undefined,
29
28
  harvester: undefined,
30
29
  isolatedBacklog: false,
31
30
  isRecording: false, // true when actively recording, false when paused or stopped
@@ -37,6 +36,7 @@ const RuntimeModel = {
37
36
  releaseIds: {},
38
37
  session: undefined,
39
38
  timeKeeper: undefined,
39
+ registeredEntities: [],
40
40
  /** a proxy is set in agent-session to track jsAttributes changes for harvesting mechanics */
41
41
  jsAttributesMetadata: { bytes: 0 },
42
42
  get harvestCount () { return ++_harvestCount }
@@ -2,7 +2,17 @@
2
2
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
+ import { FEATURE_NAMES } from '../../loaders/features/features'
6
+
5
7
  export const IDEAL_PAYLOAD_SIZE = 16000
6
8
  export const MAX_PAYLOAD_SIZE = 1000000
7
9
  export const DEFAULT_KEY = 'NR_CONTAINER_AGENT'
8
10
  export const SESSION_ERROR = 'SESSION_ERROR'
11
+
12
+ export const SUPPORTS_REGISTERED_ENTITIES = {
13
+ [FEATURE_NAMES.logging]: true,
14
+ // flip other features here when they are supported by DEM consumers
15
+ [FEATURE_NAMES.genericEvents]: false,
16
+ [FEATURE_NAMES.jserrors]: false,
17
+ [FEATURE_NAMES.ajax]: false
18
+ }
@@ -123,7 +123,7 @@ function drainGroup (agentIdentifier, group, activateGroup = true) {
123
123
 
124
124
  if (!baseEE.isolatedBacklog) delete handlers[group]
125
125
  baseEE.backlog[group] = null
126
- baseEE.emit('drain-' + group, []) // TODO: Code exists purely for a unit test and needs to be refined
126
+ baseEE.emit('drain-' + group, []) // Informs the feature that it has drained its backlog of events, this kicks off an immediate harvest to capture any load-driven events that were buffered.
127
127
  }
128
128
 
129
129
  /**
@@ -55,34 +55,30 @@ export class Harvester {
55
55
  * @returns {boolean} True if 1+ network call was made. Note that this does not mean or guarantee that it was successful (or that all were in the case of more than 1).
56
56
  */
57
57
  triggerHarvestFor (aggregateInst, localOpts = {}) {
58
- if (aggregateInst.blocked) return false
58
+ const output = { ranSend: false, payload: undefined, endpointVersion: aggregateInst.harvestEndpointVersion || 1 }
59
+ if (aggregateInst.blocked) return output
59
60
 
60
61
  const submitMethod = getSubmitMethod(localOpts)
61
- if (!submitMethod) return false
62
+ if (!submitMethod) return output
62
63
 
63
64
  const shouldRetryOnFail = !localOpts.isFinalHarvest && submitMethod === xhrMethod // always retry all features harvests except for final
64
- let dataToSendArr; let ranSend = false
65
- if (!localOpts.directSend) { // primarily used by rum call to bypass makeHarvestPayload by providing payload directly
66
- dataToSendArr = aggregateInst.makeHarvestPayload(shouldRetryOnFail, localOpts) // be sure the 'this' of makeHarvestPayload is the aggregate w/ access to its harvestOpts
67
- if (!dataToSendArr) return false // can be undefined if storage is empty or preharvest checks failed
68
- } else dataToSendArr = [localOpts.directSend]
69
-
70
- dataToSendArr.forEach(({ targetApp, payload }) => {
71
- if (!payload) return
72
-
73
- send(this.agentRef, {
74
- endpoint: FEATURE_TO_ENDPOINT[aggregateInst.featureName],
75
- targetApp,
76
- payload,
77
- localOpts,
78
- submitMethod,
79
- cbFinished,
80
- raw: aggregateInst.harvestOpts.raw,
81
- featureName: aggregateInst.featureName
82
- })
83
- ranSend = true
65
+ output.payload = !localOpts.directSend ? aggregateInst.makeHarvestPayload(shouldRetryOnFail, localOpts) : localOpts.directSend?.payload // features like PVE can define the payload directly, bypassing the makeHarvestPayload logic
66
+
67
+ if (!output.payload) return output
68
+
69
+ send(this.agentRef, {
70
+ endpoint: FEATURE_TO_ENDPOINT[aggregateInst.featureName],
71
+ payload: output.payload,
72
+ localOpts,
73
+ submitMethod,
74
+ cbFinished,
75
+ raw: aggregateInst.harvestOpts.raw,
76
+ featureName: aggregateInst.featureName,
77
+ endpointVersion: output.endpointVersion
84
78
  })
85
- return ranSend
79
+ output.ranSend = true
80
+
81
+ return output
86
82
 
87
83
  /**
88
84
  * This is executed immediately after harvest sends the data via XHR, or if there's nothing to send. Note that this excludes on unloading / sendBeacon.
@@ -112,13 +108,13 @@ const warnings = {}
112
108
  * @param {NetworkSendSpec} param0 Specification for sending data
113
109
  * @returns {boolean} True if a network call was made. Note that this does not mean or guarantee that it was successful.
114
110
  */
115
- export function send (agentRef, { endpoint, targetApp, payload, localOpts = {}, submitMethod, cbFinished, raw, featureName }) {
111
+ export function send (agentRef, { endpoint, payload, localOpts = {}, submitMethod, cbFinished, raw, featureName, endpointVersion = 1 }) {
116
112
  if (!agentRef.info.errorBeacon) return false
117
113
 
118
114
  let { body, qs } = cleanPayload(payload)
119
115
 
120
116
  if (Object.keys(body).length === 0 && !localOpts.sendEmptyBody) { // if there's no body to send, just run onfinish stuff and return
121
- if (cbFinished) cbFinished({ sent: false, targetApp })
117
+ if (cbFinished) cbFinished({ sent: false })
122
118
  return false
123
119
  }
124
120
 
@@ -126,8 +122,8 @@ export function send (agentRef, { endpoint, targetApp, payload, localOpts = {},
126
122
  const perceivedBeacon = agentRef.init.proxy.beacon || agentRef.info.errorBeacon
127
123
  const url = raw
128
124
  ? `${protocol}://${perceivedBeacon}/${endpoint}`
129
- : `${protocol}://${perceivedBeacon}${endpoint !== RUM ? '/' + endpoint : ''}/1/${targetApp.licenseKey}`
130
- const baseParams = !raw ? baseQueryString(agentRef, qs, endpoint, targetApp.applicationID) : ''
125
+ : `${protocol}://${perceivedBeacon}${endpoint !== RUM ? '/' + endpoint : ''}/${endpointVersion}/${agentRef.info.licenseKey}`
126
+ const baseParams = !raw ? baseQueryString(agentRef, qs, endpoint) : ''
131
127
  let payloadParams = obj(qs, agentRef.runtime.maxBytes)
132
128
  if (baseParams === '' && payloadParams.startsWith('&')) {
133
129
  payloadParams = payloadParams.substring(1)
@@ -159,7 +155,7 @@ export function send (agentRef, { endpoint, targetApp, payload, localOpts = {},
159
155
  result.addEventListener('loadend', function () {
160
156
  // `this` here in block refers to the XHR object in this scope, do not change the anon function to an arrow function
161
157
  // status 0 refers to a local error, such as CORS or network failure, or a blocked request by the browser (e.g. adblocker)
162
- const cbResult = { sent: this.status !== 0, status: this.status, retry: shouldRetry(this.status), fullUrl, xhr: this, targetApp }
158
+ const cbResult = { sent: this.status !== 0, status: this.status, retry: shouldRetry(this.status), fullUrl, xhr: this }
163
159
  if (localOpts.needResponse) cbResult.responseText = this.responseText
164
160
  cbFinished(cbResult)
165
161
 
@@ -169,7 +165,7 @@ export function send (agentRef, { endpoint, targetApp, payload, localOpts = {},
169
165
  } else if (submitMethod === fetchMethod) {
170
166
  result.then(async function (response) {
171
167
  const status = response.status
172
- const cbResult = { sent: true, status, retry: shouldRetry(status), fullUrl, fetchResponse: response, targetApp }
168
+ const cbResult = { sent: true, status, retry: shouldRetry(status), fullUrl, fetchResponse: response }
173
169
  if (localOpts.needResponse) cbResult.responseText = await response.text()
174
170
  cbFinished(cbResult)
175
171
  /** temporary audit of consistency of harvest metadata flags */
@@ -207,7 +203,6 @@ export function send (agentRef, { endpoint, targetApp, payload, localOpts = {},
207
203
  data: {
208
204
  endpoint,
209
205
  headers,
210
- targetApp,
211
206
  payload,
212
207
  submitMethod: getSubmitMethodName(),
213
208
  raw,
@@ -264,14 +259,14 @@ function cleanPayload (payload = {}) {
264
259
  }
265
260
 
266
261
  // The stuff that gets sent every time.
267
- function baseQueryString (agentRef, qs, endpoint, applicationID) {
262
+ function baseQueryString (agentRef, qs, endpoint) {
268
263
  const ref = agentRef.runtime.obfuscator.obfuscateString(cleanURL('' + globalScope.location))
269
264
  const session = agentRef.runtime.session
270
265
  const hr = !!session?.state.sessionReplaySentFirstChunk && session?.state.sessionReplayMode === 1 && endpoint !== JSERRORS
271
266
  const ht = !!session?.state.traceHarvestStarted && session?.state.sessionTraceMode === 1 && ![LOGS, BLOBS].includes(endpoint)
272
267
 
273
268
  const qps = [
274
- 'a=' + applicationID,
269
+ 'a=' + agentRef.info.applicationID,
275
270
  param('sa', (agentRef.info.sa ? '' + agentRef.info.sa : '')),
276
271
  param('v', VERSION),
277
272
  transactionNameParam(),
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Copyright 2020-2025 New Relic, Inc. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ /**
7
+ * @param {Object} [target] - the target to be validated
8
+ * @returns {boolean}
9
+ */
10
+ export function isValidMFETarget (target = {}) {
11
+ return !!(target.id && target.name)
12
+ }
13
+
14
+ /**
15
+ * When given a valid target, returns an object with the MFE payload attributes. Returns an empty object otherwise.
16
+ * @param {Object} [target] the registered target
17
+ * @param {AggregateInstance} [aggregateInstance] the aggregate instance calling the method
18
+ * @returns {{'mfe.id': *, 'mfe.name': String}|{}} returns an empty object if args are not supplied or the aggregate instance is not supporting version 2
19
+ */
20
+ export function getVersion2Attributes (target, aggregateInstance) {
21
+ if (aggregateInstance?.harvestEndpointVersion !== 2) return {}
22
+ const containerAgentEntityGuid = aggregateInstance.agentRef.runtime.appMetadata.agents[0].entityGuid
23
+ if (!isValidMFETarget(target)) {
24
+ return {
25
+ 'entity.guid': containerAgentEntityGuid,
26
+ appId: aggregateInstance.agentRef.info.applicationID
27
+ }
28
+ }
29
+ return {
30
+ 'mfe.id': target.id, // these field names may change as the schema is finalized
31
+ 'mfe.name': target.name, // these field names may change as the schema is finalized
32
+ eventSource: 'MicroFrontendBrowserAgent', // these field names may change as the schema is finalized
33
+ 'parent.id': containerAgentEntityGuid
34
+ }
35
+ }
@@ -14,6 +14,7 @@ import { applyFnToProps } from '../../../common/util/traverse'
14
14
  import { UserActionsAggregator } from './user-actions/user-actions-aggregator'
15
15
  import { isIFrameWindow } from '../../../common/dom/iframe'
16
16
  import { isPureObject } from '../../../common/util/type-check'
17
+ import { getVersion2Attributes } from '../../../common/util/mfe'
17
18
 
18
19
  export class Aggregate extends AggregateBase {
19
20
  static featureName = FEATURE_NAME
@@ -42,8 +43,7 @@ export class Aggregate extends AggregateBase {
42
43
  }, this.featureName, this.ee)
43
44
 
44
45
  if (agentRef.init.page_action.enabled) {
45
- registerHandler('api-addPageAction', (timestamp, name, attributes, targetEntityGuid) => {
46
- if (!this.agentRef.runtime.entityManager.get(targetEntityGuid)) return warn(56, this.featureName)
46
+ registerHandler('api-addPageAction', (timestamp, name, attributes, target) => {
47
47
  this.addEvent({
48
48
  ...attributes,
49
49
  eventType: 'PageAction',
@@ -55,7 +55,7 @@ export class Aggregate extends AggregateBase {
55
55
  browserWidth: window.document.documentElement?.clientWidth,
56
56
  browserHeight: window.document.documentElement?.clientHeight
57
57
  })
58
- }, targetEntityGuid)
58
+ }, target)
59
59
  }, this.featureName, this.ee)
60
60
  }
61
61
 
@@ -242,7 +242,6 @@ export class Aggregate extends AggregateBase {
242
242
  this.addEvent(event)
243
243
  }, this.featureName, this.ee)
244
244
 
245
- agentRef.runtime.harvester.triggerHarvestFor(this)
246
245
  this.drain()
247
246
  })
248
247
  }
@@ -258,10 +257,10 @@ export class Aggregate extends AggregateBase {
258
257
  * * sessionTraceId: set by the `ptid=` query param
259
258
  * * userAgent*: set by the userAgent header
260
259
  * @param {object=} obj the event object for storing in the event buffer
261
- * @param {string=} targetEntityGuid the target entity guid for the event to scope buffering and harvesting. Defaults to agent config if undefined
260
+ * @param {string=} target the target metadata for the event to scope buffering and harvesting. Defaults to container agent config if undefined
262
261
  * @returns void
263
262
  */
264
- addEvent (obj = {}, targetEntityGuid) {
263
+ addEvent (obj = {}, target) {
265
264
  if (!obj || !Object.keys(obj).length) return
266
265
  if (!obj.eventType) {
267
266
  warn(44)
@@ -278,7 +277,9 @@ export class Aggregate extends AggregateBase {
278
277
  timestamp: Math.floor(this.agentRef.runtime.timeKeeper.correctRelativeTimestamp(now())),
279
278
  /** all generic events require pageUrl(s) */
280
279
  pageUrl: cleanURL('' + initialLocation),
281
- currentUrl: cleanURL('' + location)
280
+ currentUrl: cleanURL('' + location),
281
+ /** Specific attributes only supplied if harvesting to endpoint version 2 */
282
+ ...(getVersion2Attributes(target, this))
282
283
  }
283
284
 
284
285
  const eventAttributes = {
@@ -290,7 +291,7 @@ export class Aggregate extends AggregateBase {
290
291
  ...obj
291
292
  }
292
293
 
293
- this.events.add(eventAttributes, targetEntityGuid)
294
+ this.events.add(eventAttributes)
294
295
  }
295
296
 
296
297
  serializer (eventBuffer) {
@@ -17,5 +17,7 @@ export const FRUSTRATION_TIMEOUT_MS = 2000
17
17
  export const RESERVED_EVENT_TYPES = ['PageAction', 'UserAction', 'BrowserPerformance']
18
18
 
19
19
  export const FEATURE_FLAGS = {
20
- RESOURCES: 'experimental.resources'
20
+ RESOURCES: 'experimental.resources',
21
+ REGISTER: 'register'
22
+ // register.jserrors and register.generic_events are also used, but not referenced directly so no need to represent here
21
23
  }
@@ -19,8 +19,7 @@ import { AggregateBase } from '../../utils/aggregate-base'
19
19
  import { now } from '../../../common/timing/now'
20
20
  import { applyFnToProps } from '../../../common/util/traverse'
21
21
  import { evaluateInternalError } from './internal-errors'
22
- import { isContainerAgentTarget } from '../../../common/util/target'
23
- import { warn } from '../../../common/util/console'
22
+ import { getVersion2Attributes } from '../../../common/util/mfe'
24
23
  import { buildCauseString } from './cause-string'
25
24
 
26
25
  /**
@@ -32,6 +31,8 @@ export class Aggregate extends AggregateBase {
32
31
  constructor (agentRef) {
33
32
  super(agentRef, FEATURE_NAME)
34
33
 
34
+ /** set up agg-level behaviors specific to this feature */
35
+ this.harvestOpts.aggregatorTypes = ['err', 'ierr', 'xhr'] // the types in EventAggregator this feature cares about
35
36
  this.stackReported = {}
36
37
  this.observedAt = {}
37
38
  this.pageviewReported = {}
@@ -46,8 +47,6 @@ export class Aggregate extends AggregateBase {
46
47
  register('softNavFlush', (interactionId, wasFinished, softNavAttrs, interactionEndTime) =>
47
48
  this.onSoftNavNotification(interactionId, wasFinished, softNavAttrs, interactionEndTime), this.featureName, this.ee) // when an ixn is done or cancelled
48
49
 
49
- this.harvestOpts.aggregatorTypes = ['err', 'ierr', 'xhr'] // the types in EventAggregator this feature cares about
50
-
51
50
  // 0 == off, 1 == on
52
51
  this.waitForFlags(['err']).then(([errFlag]) => {
53
52
  if (errFlag) {
@@ -113,10 +112,8 @@ export class Aggregate extends AggregateBase {
113
112
  * @param {object=} target the target to buffer and harvest to, if undefined the default configuration target is used
114
113
  * @returns
115
114
  */
116
- storeError (err, time, internal, customAttributes, hasReplay, swallowReason, targetEntityGuid) {
115
+ storeError (err, time, internal, customAttributes, hasReplay, swallowReason, target) {
117
116
  if (!err) return
118
- const target = this.agentRef.runtime.entityManager.get(targetEntityGuid)
119
- if (!target) return warn(56, this.featureName)
120
117
  // are we in an interaction
121
118
  time = time || now()
122
119
  let filterOutput
@@ -155,7 +152,7 @@ export class Aggregate extends AggregateBase {
155
152
  if (filterOutput?.group) params.errorGroup = filterOutput.group
156
153
 
157
154
  // Should only decorate "hasReplay" for the container agent, so check if the target matches the config
158
- if (hasReplay && isContainerAgentTarget(target, this.agentRef)) params.hasReplay = hasReplay
155
+ if (hasReplay && !target) params.hasReplay = hasReplay
159
156
  /**
160
157
  * The bucketHash is different from the params.stackHash because the params.stackHash is based on the canonicalized
161
158
  * stack trace and is used downstream in NR1 to attempt to group the same errors across different browsers. However,
@@ -191,7 +188,7 @@ export class Aggregate extends AggregateBase {
191
188
 
192
189
  // Trace sends the error in its payload, and both trace & replay simply listens for any error to occur.
193
190
  const jsErrorEvent = [type, bucketHash, params, newMetrics, customAttributes]
194
- if (this.shouldAllowMainAgentToCapture(targetEntityGuid)) handle('trace-jserror', jsErrorEvent, undefined, FEATURE_NAMES.sessionTrace, this.ee)
191
+ if (this.shouldAllowMainAgentToCapture(target)) handle('trace-jserror', jsErrorEvent, undefined, FEATURE_NAMES.sessionTrace, this.ee)
195
192
  // still send EE events for other features such as above, but stop this one from aggregating internal data
196
193
  if (this.blocked) return
197
194
 
@@ -200,7 +197,7 @@ export class Aggregate extends AggregateBase {
200
197
  params._interactionNodeId = err.__newrelic[this.agentIdentifier].interactionNodeId
201
198
  }
202
199
 
203
- if (this.shouldAllowMainAgentToCapture(targetEntityGuid)) {
200
+ if (this.shouldAllowMainAgentToCapture(target)) {
204
201
  const softNavInUse = Boolean(this.agentRef.features?.[FEATURE_NAMES.softNav])
205
202
  // Note: the following are subject to potential race cond wherein if the other feature aren't fully initialized, it'll be treated as there being no associated interaction.
206
203
  // They each will also tack on their respective properties to the params object as part of the decision flow.
@@ -221,12 +218,15 @@ export class Aggregate extends AggregateBase {
221
218
  }
222
219
 
223
220
  // always add directly if scoped to a sub-entity, the other pathways above will be deterministic if the main agent should procede
224
- if (targetEntityGuid) this.#storeJserrorForHarvest([...jsErrorEvent, targetEntityGuid], false, params._softNavAttributes)
221
+ if (target) this.#storeJserrorForHarvest([...jsErrorEvent, target], false, params._softNavAttributes)
225
222
  }
226
223
 
227
224
  #storeJserrorForHarvest (errorInfoArr, softNavOccurredFinished, softNavCustomAttrs = {}) {
228
- let [type, bucketHash, params, newMetrics, localAttrs, targetEntityGuid] = errorInfoArr
229
- const allCustomAttrs = {}
225
+ let [type, bucketHash, params, newMetrics, localAttrs, target] = errorInfoArr
226
+ const allCustomAttrs = {
227
+ /** MFE specific attributes if in "multiple" mode (ie consumer version 2) */
228
+ ...getVersion2Attributes(target, this)
229
+ }
230
230
 
231
231
  if (softNavOccurredFinished) {
232
232
  Object.entries(softNavCustomAttrs).forEach(([k, v]) => setCustom(k, v)) // when an ixn finishes, it'll include stuff in jsAttributes + attrs specific to the ixn
@@ -243,7 +243,7 @@ export class Aggregate extends AggregateBase {
243
243
  const jsAttributesHash = stringHashCode(stringify(allCustomAttrs))
244
244
  const aggregateHash = bucketHash + ':' + jsAttributesHash
245
245
 
246
- this.events.add([type, aggregateHash, params, newMetrics, allCustomAttrs], targetEntityGuid)
246
+ this.events.add([type, aggregateHash, params, newMetrics, allCustomAttrs])
247
247
 
248
248
  function setCustom (key, val) {
249
249
  allCustomAttrs[key] = (val && typeof val === 'object' ? stringify(val) : val)
@@ -253,11 +253,11 @@ export class Aggregate extends AggregateBase {
253
253
  /**
254
254
  * If the event lacks an entityGuid (the default behavior), the main agent should capture the data. If the data is assigned to a sub-entity target
255
255
  * the main agent should not capture events unless it is configured to do so.
256
- * @param {string} entityGuid - the context object for the event
256
+ * @param {string} target - the context object for the event
257
257
  * @returns {boolean} - whether the main agent should capture the event to its internal target
258
258
  */
259
- shouldAllowMainAgentToCapture (entityGuid) {
260
- return (!entityGuid || this.agentRef.init.api.duplicate_registered_data)
259
+ shouldAllowMainAgentToCapture (target) {
260
+ return (!target || this.agentRef.init.api.duplicate_registered_data)
261
261
  }
262
262
 
263
263
  // TO-DO: Remove this function when old spa is taken out. #storeJserrorForHarvest handles the work with the softnav feature.