@newrelic/browser-agent 1.260.0 → 1.261.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/CHANGELOG.md +26 -0
  2. package/dist/cjs/cdn/experimental.js +2 -1
  3. package/dist/cjs/cdn/polyfills/pro.js +2 -1
  4. package/dist/cjs/cdn/polyfills/spa.js +2 -1
  5. package/dist/cjs/cdn/pro.js +2 -1
  6. package/dist/cjs/cdn/spa.js +2 -1
  7. package/dist/cjs/common/config/state/init.js +31 -24
  8. package/dist/cjs/common/constants/env.cdn.js +1 -1
  9. package/dist/cjs/common/constants/env.js +1 -1
  10. package/dist/cjs/common/constants/env.npm.js +1 -1
  11. package/dist/cjs/common/constants/runtime.js +2 -1
  12. package/dist/cjs/common/deny-list/deny-list.js +1 -1
  13. package/dist/cjs/common/harvest/harvest-scheduler.js +1 -1
  14. package/dist/cjs/common/harvest/harvest.js +1 -1
  15. package/dist/cjs/common/session/session-entity.js +7 -1
  16. package/dist/cjs/common/timing/time-keeper.js +2 -2
  17. package/dist/cjs/common/wrap/wrap-logger.js +54 -0
  18. package/dist/cjs/features/ajax/aggregate/index.js +1 -1
  19. package/dist/cjs/features/logging/aggregate/index.js +102 -0
  20. package/dist/cjs/features/logging/constants.js +20 -0
  21. package/dist/cjs/features/logging/index.js +12 -0
  22. package/dist/cjs/features/logging/instrument/index.js +28 -0
  23. package/dist/cjs/features/logging/shared/log.js +39 -0
  24. package/dist/cjs/features/logging/shared/utils.js +50 -0
  25. package/dist/cjs/features/page_view_event/aggregate/index.js +1 -1
  26. package/dist/cjs/features/page_view_event/instrument/index.js +1 -1
  27. package/dist/cjs/features/page_view_timing/aggregate/index.js +1 -2
  28. package/dist/cjs/features/session_replay/aggregate/index.js +4 -3
  29. package/dist/cjs/features/session_replay/instrument/index.js +1 -1
  30. package/dist/cjs/features/session_trace/aggregate/index.js +16 -8
  31. package/dist/cjs/features/session_trace/aggregate/trace/storage.js +1 -1
  32. package/dist/cjs/features/session_trace/instrument/index.js +1 -1
  33. package/dist/cjs/features/soft_navigations/aggregate/bel-node.js +1 -2
  34. package/dist/cjs/features/soft_navigations/aggregate/index.js +1 -1
  35. package/dist/cjs/features/soft_navigations/aggregate/interaction.js +5 -4
  36. package/dist/cjs/features/spa/aggregate/index.js +2 -2
  37. package/dist/cjs/features/spa/instrument/index.js +1 -1
  38. package/dist/cjs/features/utils/instrument-base.js +1 -1
  39. package/dist/cjs/features/utils/lazy-feature-loader.js +3 -1
  40. package/dist/cjs/loaders/agent-base.js +23 -2
  41. package/dist/cjs/loaders/api/api-methods.js +1 -1
  42. package/dist/cjs/loaders/api/api.js +29 -2
  43. package/dist/cjs/loaders/features/features.js +7 -5
  44. package/dist/cjs/loaders/micro-agent.js +1 -1
  45. package/dist/esm/cdn/experimental.js +2 -1
  46. package/dist/esm/cdn/polyfills/pro.js +2 -1
  47. package/dist/esm/cdn/polyfills/spa.js +2 -1
  48. package/dist/esm/cdn/pro.js +2 -1
  49. package/dist/esm/cdn/spa.js +2 -1
  50. package/dist/esm/common/config/state/init.js +30 -23
  51. package/dist/esm/common/constants/env.cdn.js +1 -1
  52. package/dist/esm/common/constants/env.npm.js +1 -1
  53. package/dist/esm/common/constants/runtime.js +3 -1
  54. package/dist/esm/common/deny-list/deny-list.js +1 -1
  55. package/dist/esm/common/session/session-entity.js +8 -2
  56. package/dist/esm/common/timing/time-keeper.js +2 -2
  57. package/dist/esm/common/wrap/wrap-logger.js +48 -0
  58. package/dist/esm/features/logging/aggregate/index.js +95 -0
  59. package/dist/esm/features/logging/constants.js +14 -0
  60. package/dist/esm/features/logging/index.js +1 -0
  61. package/dist/esm/features/logging/instrument/index.js +21 -0
  62. package/dist/esm/features/logging/shared/log.js +32 -0
  63. package/dist/esm/features/logging/shared/utils.js +44 -0
  64. package/dist/esm/features/page_view_timing/aggregate/index.js +1 -2
  65. package/dist/esm/features/session_replay/aggregate/index.js +3 -2
  66. package/dist/esm/features/session_trace/aggregate/index.js +16 -8
  67. package/dist/esm/features/session_trace/aggregate/trace/storage.js +1 -1
  68. package/dist/esm/features/soft_navigations/aggregate/bel-node.js +1 -2
  69. package/dist/esm/features/soft_navigations/aggregate/index.js +1 -1
  70. package/dist/esm/features/soft_navigations/aggregate/interaction.js +5 -4
  71. package/dist/esm/features/spa/aggregate/index.js +1 -1
  72. package/dist/esm/features/utils/lazy-feature-loader.js +2 -0
  73. package/dist/esm/loaders/agent-base.js +23 -2
  74. package/dist/esm/loaders/api/api-methods.js +1 -1
  75. package/dist/esm/loaders/api/api.js +28 -1
  76. package/dist/esm/loaders/features/features.js +7 -5
  77. package/dist/types/common/config/state/init.d.ts.map +1 -1
  78. package/dist/types/common/constants/runtime.d.ts +0 -6
  79. package/dist/types/common/constants/runtime.d.ts.map +1 -1
  80. package/dist/types/common/drain/drain.d.ts.map +1 -1
  81. package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
  82. package/dist/types/common/harvest/harvest.d.ts +5 -5
  83. package/dist/types/common/harvest/types.d.ts +2 -2
  84. package/dist/types/common/harvest/types.d.ts.map +1 -1
  85. package/dist/types/common/ids/id.d.ts.map +1 -1
  86. package/dist/types/common/ids/unique-id.d.ts.map +1 -1
  87. package/dist/types/common/session/session-entity.d.ts.map +1 -1
  88. package/dist/types/common/util/console.d.ts.map +1 -1
  89. package/dist/types/common/util/data-size.d.ts.map +1 -1
  90. package/dist/types/common/util/feature-flags.d.ts.map +1 -1
  91. package/dist/types/common/util/get-or-set.d.ts.map +1 -1
  92. package/dist/types/common/util/invoke.d.ts.map +1 -1
  93. package/dist/types/common/util/stringify.d.ts.map +1 -1
  94. package/dist/types/common/util/submit-data.d.ts.map +1 -1
  95. package/dist/types/common/util/type-check.d.ts.map +1 -1
  96. package/dist/types/common/wrap/wrap-logger.d.ts +17 -0
  97. package/dist/types/common/wrap/wrap-logger.d.ts.map +1 -0
  98. package/dist/types/features/jserrors/aggregate/compute-stack-trace.d.ts.map +1 -1
  99. package/dist/types/features/jserrors/aggregate/index.d.ts +1 -1
  100. package/dist/types/features/logging/aggregate/index.d.ts +40 -0
  101. package/dist/types/features/logging/aggregate/index.d.ts.map +1 -0
  102. package/dist/types/features/logging/constants.d.ts +14 -0
  103. package/dist/types/features/logging/constants.d.ts.map +1 -0
  104. package/dist/types/features/logging/index.d.ts +2 -0
  105. package/dist/types/features/logging/index.d.ts.map +1 -0
  106. package/dist/types/features/logging/instrument/index.d.ts +6 -0
  107. package/dist/types/features/logging/instrument/index.d.ts.map +1 -0
  108. package/dist/types/features/logging/shared/log.d.ts +18 -0
  109. package/dist/types/features/logging/shared/log.d.ts.map +1 -0
  110. package/dist/types/features/logging/shared/utils.d.ts +16 -0
  111. package/dist/types/features/logging/shared/utils.d.ts.map +1 -0
  112. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  113. package/dist/types/features/session_replay/aggregate/index.d.ts +1 -1
  114. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  115. package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
  116. package/dist/types/features/session_trace/aggregate/index.d.ts +9 -6
  117. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  118. package/dist/types/features/session_trace/aggregate/trace/storage.d.ts.map +1 -1
  119. package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts +0 -1
  120. package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts.map +1 -1
  121. package/dist/types/features/soft_navigations/aggregate/bel-node.d.ts +1 -1
  122. package/dist/types/features/soft_navigations/aggregate/bel-node.d.ts.map +1 -1
  123. package/dist/types/features/soft_navigations/aggregate/interaction.d.ts +0 -1
  124. package/dist/types/features/soft_navigations/aggregate/interaction.d.ts.map +1 -1
  125. package/dist/types/features/utils/feature-base.d.ts +1 -1
  126. package/dist/types/features/utils/feature-base.d.ts.map +1 -1
  127. package/dist/types/features/utils/instrument-base.d.ts +2 -2
  128. package/dist/types/features/utils/lazy-feature-loader.d.ts.map +1 -1
  129. package/dist/types/loaders/agent-base.d.ts +25 -4
  130. package/dist/types/loaders/agent-base.d.ts.map +1 -1
  131. package/dist/types/loaders/api/api.d.ts +8 -0
  132. package/dist/types/loaders/api/api.d.ts.map +1 -1
  133. package/dist/types/loaders/api/interaction-types.d.ts.map +1 -1
  134. package/dist/types/loaders/features/features.d.ts +1 -0
  135. package/dist/types/loaders/features/features.d.ts.map +1 -1
  136. package/dist/types/loaders/micro-agent.d.ts.map +1 -1
  137. package/package.json +16 -28
  138. package/src/cdn/experimental.js +2 -0
  139. package/src/cdn/polyfills/pro.js +3 -1
  140. package/src/cdn/polyfills/spa.js +2 -0
  141. package/src/cdn/pro.js +3 -1
  142. package/src/cdn/spa.js +2 -0
  143. package/src/common/config/state/init.js +17 -15
  144. package/src/common/constants/runtime.js +3 -1
  145. package/src/common/deny-list/deny-list.js +1 -1
  146. package/src/common/session/session-entity.js +7 -2
  147. package/src/common/timing/time-keeper.js +2 -2
  148. package/src/common/wrap/wrap-logger.js +49 -0
  149. package/src/features/logging/aggregate/index.js +101 -0
  150. package/src/features/logging/constants.js +19 -0
  151. package/src/features/logging/index.js +1 -0
  152. package/src/features/logging/instrument/index.js +18 -0
  153. package/src/features/logging/shared/log.js +28 -0
  154. package/src/features/logging/shared/utils.js +43 -0
  155. package/src/features/page_view_timing/aggregate/index.js +1 -2
  156. package/src/features/session_replay/aggregate/index.js +3 -3
  157. package/src/features/session_trace/aggregate/index.js +15 -8
  158. package/src/features/session_trace/aggregate/trace/storage.js +1 -2
  159. package/src/features/soft_navigations/aggregate/bel-node.js +1 -3
  160. package/src/features/soft_navigations/aggregate/index.js +1 -1
  161. package/src/features/soft_navigations/aggregate/interaction.js +5 -4
  162. package/src/features/spa/aggregate/index.js +1 -1
  163. package/src/features/utils/lazy-feature-loader.js +2 -0
  164. package/src/loaders/agent-base.js +23 -2
  165. package/src/loaders/api/api-methods.js +1 -1
  166. package/src/loaders/api/api.js +19 -1
  167. package/src/loaders/features/features.js +7 -5
@@ -12,7 +12,7 @@ export class InstrumentBase extends FeatureBase {
12
12
  * of its pooled instrumentation data handled by the agent's centralized drain functionality, rather than draining
13
13
  * immediately. Primarily useful for fine-grained control in tests.
14
14
  */
15
- constructor(agentIdentifier: string, aggregator: import('../../common/aggregate/aggregator').Aggregator, featureName: string, auto?: boolean | undefined);
15
+ constructor(agentIdentifier: string, aggregator: import("../../common/aggregate/aggregator").Aggregator, featureName: string, auto?: boolean | undefined);
16
16
  auto: boolean;
17
17
  /** @type {Function | undefined} This should be set by any derived Instrument class if it has things to do when feature fails or is killed. */
18
18
  abortHandler: Function | undefined;
@@ -20,7 +20,7 @@ export class InstrumentBase extends FeatureBase {
20
20
  * @type {import('./aggregate-base').AggregateBase} Holds the reference to the feature's aggregate module counterpart, if and after it has been initialized. This may not be assigned until after page loads!
21
21
  * The only purpose of this for now is to expose it to the NREUM interface, as the feature's instrument instance is already exposed.
22
22
  */
23
- featAggregate: import('./aggregate-base').AggregateBase;
23
+ featAggregate: import("./aggregate-base").AggregateBase;
24
24
  /**
25
25
  * @type {Promise} Assigned immediately after @see importAggregator runs. Serves as a signal for when the inner async fn finishes execution. Useful for features to await
26
26
  * one another if there are inter-features dependencies.
@@ -1 +1 @@
1
- {"version":3,"file":"lazy-feature-loader.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/lazy-feature-loader.js"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,uEAFa,QAAQ,+BAA2B,IAAI,CAAC,CA6BpD"}
1
+ {"version":3,"file":"lazy-feature-loader.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/lazy-feature-loader.js"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,uEAFa,OAAO,CAAC,cAAc,GAAC,WAAW,GAAC,IAAI,CAAC,CA+BpD"}
@@ -23,10 +23,10 @@ export class AgentBase {
23
23
  * Adds a user-defined attribute name and value to subsequent events on the page.
24
24
  * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/setcustomattribute/}
25
25
  * @param {string} name Name of the attribute. Appears as column in the PageView event. It will also appear as a column in the PageAction event if you are using it.
26
- * @param {string|number|null} value Value of the attribute. Appears as the value in the named attribute column in the PageView event. It will appear as a column in the PageAction event if you are using it. Custom attribute values cannot be complex objects, only simple types such as Strings and Integers.
27
- * @param {boolean} [persist] Default false. f set to true, the name-value pair will also be set into the browser's storage API. Then on the following instrumented pages that load within the same session, the pair will be re-applied as a custom attribute.
26
+ * @param {string|number|boolean|null} value Value of the attribute. Appears as the value in the named attribute column in the PageView event. It will appear as a column in the PageAction event if you are using it. Custom attribute values cannot be complex objects, only simple types such as Strings, Integers and Booleans. Passing a null value unsets any existing attribute of the same name.
27
+ * @param {boolean} [persist] Default false. If set to true, the name-value pair will also be set into the browser's storage API. Then on the following instrumented pages that load within the same session, the pair will be re-applied as a custom attribute.
28
28
  */
29
- setCustomAttribute(name: string, value: string | number | null, persist?: boolean | undefined): any;
29
+ setCustomAttribute(name: string, value: string | number | boolean | null, persist?: boolean | undefined): any;
30
30
  /**
31
31
  * Identifies a browser error without disrupting your app's operations.
32
32
  * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/noticeerror/}
@@ -121,7 +121,28 @@ export class AgentBase {
121
121
  * - Note: Does not apply to MicroAgent
122
122
  */
123
123
  interaction(): InteractionInstance;
124
+ /**
125
+ * Capture a single log.
126
+ * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/loginfo/}
127
+ * @param {string} message String to be captured as log message
128
+ * @param {{customAttributes?: object, level?: 'ERROR'|'TRACE'|'DEBUG'|'INFO'|'WARN'}} [options] customAttributes defaults to `{}` if not assigned, level defaults to `info` if not assigned.
129
+ */
130
+ log(message: string, options?: {
131
+ customAttributes?: object;
132
+ level?: "ERROR" | "TRACE" | "DEBUG" | "INFO" | "WARN";
133
+ } | undefined): any;
134
+ /**
135
+ * Wrap a logger function to capture a log each time the function is invoked with the message and arguments passed
136
+ * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/wraplogger/}
137
+ * @param {object} parent The parent object containing the logger method
138
+ * @param {string} functionName The property name of the function in the parent object to be wrapped
139
+ * @param {{customAttributes?: object, level?: 'ERROR'|'TRACE'|'DEBUG'|'INFO'|'WARN'}} [options] customAttributes defaults to `{}` if not assigned, level defaults to `info` if not assigned.
140
+ */
141
+ wrapLogger(parent: object, functionName: string, options?: {
142
+ customAttributes?: object;
143
+ level?: "ERROR" | "TRACE" | "DEBUG" | "INFO" | "WARN";
144
+ } | undefined): any;
124
145
  #private;
125
146
  }
126
- export type InteractionInstance = import('./api/interaction-types').InteractionInstance;
147
+ export type InteractionInstance = import("./api/interaction-types").InteractionInstance;
127
148
  //# sourceMappingURL=agent-base.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-base.d.ts","sourceRoot":"","sources":["../../../src/loaders/agent-base.js"],"names":[],"mappings":"AAOA;;GAEG;AAEH;IAGE,sCAKC;IAPD,wBAAe;IAMb,QAAiC;IAanC;;;;;OAKG;IACH,oBAHW,MAAM,wCAKhB;IAED;;;;;OAKG;IACH,sBAHW,MAAM,kCAKhB;IAED;;;;;;OAMG;IACH,yBAJW,MAAM,SACN,MAAM,GAAC,MAAM,GAAC,IAAI,sCAK5B;IAED;;;;;OAKG;IACH,mBAHW,KAAK,GAAC,MAAM,8CAKtB;IAED;;;;OAIG;IACH,iBAFW,MAAM,GAAC,IAAI,OAIrB;IAED;;;;;;;OAOG;IACH,6BAJW,MAAM,GAAC,IAAI,OAMrB;IAED;;;;OAIG;IACH,kCAFmB,KAAK,GAAC,MAAM,KAAK,OAAO,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,OAI9D;IAED;;;;OAIG;IACH,8CAEC;IAED;;;;;OAKG;IACH,iBAHW,MAAM,MACN,MAAM,OAIhB;IAED;;;;OAIG;IACH,yDAEC;IAED;;;;OAIG;IACH,oBAEC;IAED;;;;;OAKG;IACH,mBAEC;IAED;;;;;;;;;;OAUG;IACH,6BARW;QAAC,MAAM,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAC,OAUrF;IAED;;;;;OAKG;IACH,0BAHW,MAAM,OAKhB;IAED;;;;;MAKE;IACF,eAHa,mBAAmB,CAK/B;;CACF;kCA/KY,OAAO,yBAAyB,EAAE,mBAAmB"}
1
+ {"version":3,"file":"agent-base.d.ts","sourceRoot":"","sources":["../../../src/loaders/agent-base.js"],"names":[],"mappings":"AAOA;;GAEG;AAEH;IAGE,sCAKC;IAPD,wBAAe;IAMb,QAAiC;IAanC;;;;;OAKG;IACH,oBAHW,MAAM,wCAKhB;IAED;;;;;OAKG;IACH,sBAHW,MAAM,kCAKhB;IAED;;;;;;OAMG;IACH,yBAJW,MAAM,SACN,MAAM,GAAC,MAAM,GAAC,OAAO,GAAC,IAAI,sCAKpC;IAED;;;;;OAKG;IACH,mBAHW,KAAK,GAAC,MAAM,8CAKtB;IAED;;;;OAIG;IACH,iBAFW,MAAM,GAAC,IAAI,OAIrB;IAED;;;;;;;OAOG;IACH,6BAJW,MAAM,GAAC,IAAI,OAMrB;IAED;;;;OAIG;IACH,0BAFW,CAAC,KAAK,EAAE,KAAK,GAAC,MAAM,KAAK,OAAO,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,OAI9D;IAED;;;;OAIG;IACH,8CAEC;IAED;;;;;OAKG;IACH,iBAHW,MAAM,MACN,MAAM,OAIhB;IAED;;;;OAIG;IACH,yDAEC;IAED;;;;OAIG;IACH,oBAEC;IAED;;;;;OAKG;IACH,mBAEC;IAED;;;;;;;;;;OAUG;IACH,6BARW;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAC,OAUrF;IAED;;;;;OAKG;IACH,0BAHW,MAAM,OAKhB;IAED;;;;;MAKE;IACF,eAHa,mBAAmB,CAK/B;IAED;;;;;MAKE;IACF,aAHW,MAAM;2BACc,MAAM;gBAAU,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,MAAM,GAAC,MAAM;wBAInF;IAED;;;;;;MAME;IACF,mBAJW,MAAM,gBACN,MAAM;2BACc,MAAM;gBAAU,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,MAAM,GAAC,MAAM;wBAInF;;CACF;kCApMY,OAAO,yBAAyB,EAAE,mBAAmB"}
@@ -1,5 +1,13 @@
1
1
  export function setTopLevelCallers(): void;
2
2
  export function setAPI(agentIdentifier: any, forceDrain: any, runSoftNavOverSpa?: boolean): {
3
+ log(message: any, { customAttributes, level }?: {
4
+ customAttributes?: {} | undefined;
5
+ level?: string | undefined;
6
+ }): void;
7
+ wrapLogger(parent: any, functionName: any, { customAttributes, level }?: {
8
+ customAttributes?: {} | undefined;
9
+ level?: string | undefined;
10
+ }): void;
3
11
  addPageAction: (...args: any[]) => any;
4
12
  setPageViewName(name: any, host: any): any;
5
13
  setCustomAttribute(name: any, value: any, persistAttribute?: boolean): any;
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/api.js"],"names":[],"mappings":"AAmBA,2CAeC;AAID;;;;IAuDE;;;;OAIG;qBAFQ,MAAM;IAWjB;;;;OAIG;iCAFQ,MAAM,GAAC,IAAI;;;;;EAiGvB"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/api.js"],"names":[],"mappings":"AAsBA,2CAeC;AAID;;;;;;;;;;;;IAsEE;;;;OAIG;qBAFQ,MAAM;IAWjB;;;;OAIG;iCAFQ,MAAM,GAAC,IAAI;;;;;EAiGvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"interaction-types.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/interaction-types.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;GAMG;AAEH;;;;;;;GAOG;AAEH;;;;;GAKG;AAEH;;;;;;GAMG;AAEH;;;;;GAKG;AAEH;;;;;;GAMG;AAEH;;;;;GAKG;AAEH;;;;;;;GAOG;AAEH;;;;;;;GAOG;AAGH,wBAAwB;;gBApFV,UAAU;kBACV,YAAY;SACZ,GAAG;gBACH,UAAU;YACV,MAAM;WACN,KAAK;UACL,IAAI;kBACJ,YAAY;aACZ,OAAO;;;;;;iCAOV,MAAM,KACJ,mBAAmB;;;;;kCAOrB,MAAM,wBACI,GAAG,EAAE,KAAK,GAAG,4BACX,GAAG,EAAE,KAAK,GAAG;;;;;wBAOvB,mBAAmB;;;;;0CAOf,MAAM,KAAK,IAAI,KACnB,mBAAmB;;;;;2BAOnB,mBAAmB;;;;;qCAOf,MAAM,KAAK,IAAI,KACnB,mBAAmB;;;;;yBAOnB,mBAAmB;;;;;iCAOrB,MAAM,SACN,GAAG,KACD,mBAAmB;;;;;6BAOrB,MAAM,mCAEJ,mBAAmB"}
1
+ {"version":3,"file":"interaction-types.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/interaction-types.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;GAMG;AAEH;;;;;;;GAOG;AAEH;;;;;GAKG;AAEH;;;;;;GAMG;AAEH;;;;;GAKG;AAEH;;;;;;GAMG;AAEH;;;;;GAKG;AAEH;;;;;;;GAOG;AAEH;;;;;;;GAOG;AAGH,wBAAwB;;gBApFV,UAAU;kBACV,YAAY;SACZ,GAAG;gBACH,UAAU;YACV,MAAM;WACN,KAAK;UACL,IAAI;kBACJ,YAAY;aACZ,OAAO;;;;;;iCAOV,MAAM,KACJ,mBAAmB;;;;;kCAOrB,MAAM,wBACI,GAAG,EAAE,KAAK,GAAG,kBACrB,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG;;;;;wBAOvB,mBAAmB;;;;;oCAOrB,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,KACnB,mBAAmB;;;;;2BAOnB,mBAAmB;;;;;+BAOrB,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,KACnB,mBAAmB;;;;;yBAOnB,mBAAmB;;;;;iCAOrB,MAAM,SACN,GAAG,KACD,mBAAmB;;;;;6BAOrB,MAAM,mCAEJ,mBAAmB"}
@@ -1,6 +1,7 @@
1
1
  export namespace FEATURE_NAMES {
2
2
  let ajax: string;
3
3
  let jserrors: string;
4
+ let logging: string;
4
5
  let metrics: string;
5
6
  let pageAction: string;
6
7
  let pageViewEvent: string;
@@ -1 +1 @@
1
- {"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../../../src/loaders/features/features.js"],"names":[],"mappings":";;;;;;;;;;;;AAaA;;;GAGG;AACH;;EAWC"}
1
+ {"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../../../src/loaders/features/features.js"],"names":[],"mappings":";;;;;;;;;;;;;AAcA;;;GAGG;AACH;;EAYC"}
@@ -1 +1 @@
1
- {"version":3,"file":"micro-agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/micro-agent.js"],"names":[],"mappings":"AAmBA;;;;GAIG;AACH;IACE;;;OAGG;IACH,qBAHW,MAAM,oBACN,MAAM,cAmBhB;IAdC,6BAAiF;IACjF,aAAkB;IAMlB;;;;OAIG;IACH,yCAA2C;IAI7C;;;;;MAOC;IAED,mCAyCC;CACF;0BAxFyB,cAAc;2BANb,gCAAgC"}
1
+ {"version":3,"file":"micro-agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/micro-agent.js"],"names":[],"mappings":"AAmBA;;;;GAIG;AACH;IACE;;;OAGG;IACH,qBAHW,MAAM,oBACN,MAAM,YAAC,EAmBjB;IAdC,6BAAiF;IACjF,aAAkB;IAMlB;;;;OAIG;IACH,yCAA2C;IAI7C;;;;;MAOC;IAED,mCAyCC;CACF;0BAxFyB,cAAc;2BANb,gCAAgC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newrelic/browser-agent",
3
- "version": "1.260.0",
3
+ "version": "1.261.0",
4
4
  "private": false,
5
5
  "author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
6
6
  "description": "New Relic Browser Agent",
@@ -35,6 +35,9 @@
35
35
  "features/jserrors": [
36
36
  "dist/types/features/jserrors/index.d.ts"
37
37
  ],
38
+ "features/logging": [
39
+ "dist/types/features/logging/index.d.ts"
40
+ ],
38
41
  "features/metrics": [
39
42
  "dist/types/features/metrics/index.d.ts"
40
43
  ],
@@ -91,6 +94,11 @@
91
94
  "require": "./dist/cjs/features/jserrors/index.js",
92
95
  "default": "./dist/esm/features/jserrors/index.js"
93
96
  },
97
+ "./features/logging": {
98
+ "types": "./dist/types/features/logging/index.d.ts",
99
+ "require": "./dist/cjs/features/logging/index.js",
100
+ "default": "./dist/esm/features/logging/index.js"
101
+ },
94
102
  "./features/metrics": {
95
103
  "types": "./dist/types/features/metrics/index.d.ts",
96
104
  "require": "./dist/cjs/features/metrics/index.js",
@@ -134,11 +142,8 @@
134
142
  "test:component": "jest --selectProjects component",
135
143
  "test:types": "tsd -f ./tests/dts/**/*.ts",
136
144
  "wdio": "node --max-old-space-size=8192 tools/wdio/bin/cli.js",
137
- "jil": "tools/jil/bin/cli.js",
138
145
  "build:all": "npm run cdn:build:local && npm run build:npm && npm run tools:test-builds",
139
146
  "build:npm": "npm run npm:build:esm && npm run npm:build:cjs && npm run npm:build:types && npm run npm:pack",
140
- "build:browser-tests": "npm --prefix ./tools/test-builds/browser-tests run build",
141
- "watch:browser-tests": "jung -r ./src -F '.*\\.test\\.js' --run -- npm run build:browser-tests",
142
147
  "cdn:build": "npm run cdn:build:prod",
143
148
  "cdn:build:local": "npm run cdn:webpack",
144
149
  "cdn:build:prod": "npm run cdn:webpack -- --env mode=prod",
@@ -146,17 +151,16 @@
146
151
  "cdn:build:experiment": "npm run cdn:webpack -- --env mode=experiment",
147
152
  "cdn:webpack": "npx webpack --progress --config ./tools/webpack/index.mjs",
148
153
  "cdn:watch": "jung -r ./src -F '.*\\.test\\.js' --run -- npm run cdn:build:local",
149
- "cdn:cleanup": "node ./tools/webpack/scripts/cleanup.mjs",
150
154
  "test-server": "node ./tools/wdio/bin/server",
151
- "sauce:connect": "node ./tools/saucelabs/bin.mjs",
152
- "sauce:get-browsers": "node ./tools/browsers-lists/sauce-browsers.mjs",
155
+ "lt:update-browsers": "node ./tools/browsers-lists/lt-update-supported.mjs",
153
156
  "tools:test-builds": "npm --prefix ./tools/test-builds run build-all",
154
157
  "third-party-updates": "oss third-party manifest --includeOptDeps && oss third-party notices --includeOptDeps",
155
158
  "prepare": "husky install",
156
159
  "npm:build:esm": "npx babel --env-name npm-esm --out-dir dist/esm --out-file-extension .js ./src",
157
160
  "npm:build:cjs": "npx babel --env-name npm-cjs --out-dir dist/cjs --out-file-extension .js ./src",
158
161
  "npm:build:types": "npx tsc -b",
159
- "npm:pack": "mkdir -p temp && export PKG_NAME=$(npm pack --pack-destination temp) && echo ./temp/$PKG_NAME"
162
+ "npm:pack": "mkdir -p temp && export PKG_NAME=$(npm pack --pack-destination temp) && echo ./temp/$PKG_NAME",
163
+ "publish:nrdb:stage": "npm --prefix .github/actions install && node .github/actions/nr-upload/index.js --environment=stage --loader-version=$npm_package_version --stage-api-key=$STAGE_API_KEY && node .github/actions/nr-verify/index.js --loader-version=$npm_package_version"
160
164
  },
161
165
  "config": {
162
166
  "unsafe-perm": true
@@ -194,17 +198,11 @@
194
198
  "@wdio/local-runner": "^8.27.0",
195
199
  "@wdio/logger": "^8.24.12",
196
200
  "@wdio/mocha-framework": "^8.27.0",
197
- "@wdio/sauce-service": "^8.27.0",
198
201
  "@wdio/spec-reporter": "^8.27.0",
199
202
  "babel-jest": "^29.7.0",
200
203
  "babel-loader": "^9.1.3",
201
204
  "babel-plugin-transform-inline-environment-variables": "^0.4.4",
202
- "babelify": "^10.0.0",
203
- "browserify": "^13.3.0",
204
- "charm": "^1.0.2",
205
- "concat-stream": "^1.5.1",
206
205
  "deepmerge-ts": "^5.1.0",
207
- "defined": "^1.0.0",
208
206
  "dotenv-webpack": "^8.0.1",
209
207
  "eslint": "^8.56.0",
210
208
  "eslint-config-standard": "^17.1.0",
@@ -214,9 +212,9 @@
214
212
  "eslint-plugin-sonarjs": "^0.23.0",
215
213
  "fastify": "^4.25.2",
216
214
  "fastify-plugin": "^4.5.1",
215
+ "form-data": "^4.0.0",
217
216
  "fs-extra": "^11.2.0",
218
- "function-bind": "^1.1.1",
219
- "glob": "^10.2.5",
217
+ "glob": "^10.4.2",
220
218
  "html-webpack-plugin": "^5.6.0",
221
219
  "husky": "^8.0.3",
222
220
  "istanbul-lib-coverage": "^3.2.2",
@@ -227,30 +225,20 @@
227
225
  "jest-environment-jsdom": "29.7.0",
228
226
  "jest-extended": "^4.0.2",
229
227
  "jung": "^2.1.0",
230
- "just-debounce": "^1.0.0",
231
228
  "node-fetch": "^3.3.2",
232
229
  "npm-run-all": "^4.1.5",
233
- "object-inspect": "^1.5.0",
234
- "path-browserify": "^1.0.1",
235
- "preprocessify": "0.0.6",
236
- "process": "^0.11.10",
237
- "saucelabs": "^7.5.0",
238
230
  "semver": "^7.5.4",
239
231
  "serialize-anything": "^1.2.3",
240
- "stream-browserify": "^3.0.0",
241
- "tap-parser": "^1.2.2",
242
- "tape": "^4.8.0",
243
- "through": "^2.3.8",
232
+ "terser-webpack-plugin": "^5.3.10",
244
233
  "tsd": "^0.30.0",
245
234
  "typescript": "^5.3.3",
246
235
  "util": "^0.12.5",
247
236
  "uuid": "^9.0.1",
248
237
  "wait-on": "^7.2.0",
249
- "wd": "^1.11.2",
238
+ "wdio-lambdatest-service": "^2.1.3",
250
239
  "webpack": "^5.89.0",
251
240
  "webpack-bundle-analyzer": "^4.10.1",
252
241
  "webpack-cli": "^5.1.4",
253
- "webpack-stream": "^7.0.0",
254
242
  "yargs": "^17.7.2"
255
243
  },
256
244
  "files": [
@@ -20,6 +20,7 @@ import { Instrument as InstrumentSessionReplay } from '../features/session_repla
20
20
  // import { Instrument as InstrumentSpa } from '../features/spa/instrument'
21
21
  import { Instrument as InstrumentSoftNav } from '../features/soft_navigations/instrument'
22
22
  import { Instrument as InstrumentPageAction } from '../features/page_action/instrument'
23
+ import { Instrument as InstrumentLogs } from '../features/logging/instrument'
23
24
 
24
25
  new Agent({
25
26
  features: [
@@ -31,6 +32,7 @@ new Agent({
31
32
  InstrumentMetrics,
32
33
  InstrumentPageAction,
33
34
  InstrumentErrors,
35
+ InstrumentLogs,
34
36
  // InstrumentSpa,
35
37
  InstrumentSoftNav
36
38
  ],
@@ -13,6 +13,7 @@ import { Instrument as InstrumentErrors } from '../../features/jserrors/instrume
13
13
  import { Instrument as InstrumentXhr } from '../../features/ajax/instrument'
14
14
  import { Instrument as InstrumentSessionTrace } from '../../features/session_trace/instrument'
15
15
  import { Instrument as InstrumentPageAction } from '../../features/page_action/instrument'
16
+ import { Instrument as InstrumentLogs } from '../../features/logging/instrument'
16
17
 
17
18
  new Agent({
18
19
  features: [
@@ -22,7 +23,8 @@ new Agent({
22
23
  InstrumentXhr,
23
24
  InstrumentMetrics,
24
25
  InstrumentPageAction,
25
- InstrumentErrors
26
+ InstrumentErrors,
27
+ InstrumentLogs
26
28
  ],
27
29
  loaderType: 'pro-polyfills'
28
30
  })
@@ -14,6 +14,7 @@ import { Instrument as InstrumentXhr } from '../../features/ajax/instrument'
14
14
  import { Instrument as InstrumentSessionTrace } from '../../features/session_trace/instrument'
15
15
  import { Instrument as InstrumentSpa } from '../../features/spa/instrument'
16
16
  import { Instrument as InstrumentPageAction } from '../../features/page_action/instrument'
17
+ import { Instrument as InstrumentLogs } from '../../features/logging/instrument'
17
18
 
18
19
  new Agent({
19
20
  features: [
@@ -24,6 +25,7 @@ new Agent({
24
25
  InstrumentMetrics,
25
26
  InstrumentPageAction,
26
27
  InstrumentErrors,
28
+ InstrumentLogs,
27
29
  InstrumentSpa
28
30
  ],
29
31
  loaderType: 'spa-polyfills'
package/src/cdn/pro.js CHANGED
@@ -13,6 +13,7 @@ import { Instrument as InstrumentXhr } from '../features/ajax/instrument'
13
13
  import { Instrument as InstrumentSessionTrace } from '../features/session_trace/instrument'
14
14
  import { Instrument as InstrumentSessionReplay } from '../features/session_replay/instrument'
15
15
  import { Instrument as InstrumentPageAction } from '../features/page_action/instrument'
16
+ import { Instrument as InstrumentLogs } from '../features/logging/instrument'
16
17
 
17
18
  new Agent({
18
19
  features: [
@@ -23,7 +24,8 @@ new Agent({
23
24
  InstrumentXhr,
24
25
  InstrumentMetrics,
25
26
  InstrumentPageAction,
26
- InstrumentErrors
27
+ InstrumentErrors,
28
+ InstrumentLogs
27
29
  ],
28
30
  loaderType: 'pro'
29
31
  })
package/src/cdn/spa.js CHANGED
@@ -14,6 +14,7 @@ import { Instrument as InstrumentSessionReplay } from '../features/session_repla
14
14
  import { Instrument as InstrumentSoftNav } from '../features/soft_navigations/instrument'
15
15
  import { Instrument as InstrumentSpa } from '../features/spa/instrument'
16
16
  import { Instrument as InstrumentPageAction } from '../features/page_action/instrument'
17
+ import { Instrument as InstrumentLogs } from '../features/logging/instrument'
17
18
 
18
19
  new Agent({
19
20
  features: [
@@ -25,6 +26,7 @@ new Agent({
25
26
  InstrumentMetrics,
26
27
  InstrumentPageAction,
27
28
  InstrumentErrors,
29
+ InstrumentLogs,
28
30
  InstrumentSoftNav,
29
31
  InstrumentSpa // either the softnav or the old spa will be used (not both), but we still need to pack both to avoid dynamic import for instrument files
30
32
  ],
@@ -1,3 +1,4 @@
1
+ import { LOG_LEVELS } from '../../../features/logging/constants'
1
2
  import { isValidSelector } from '../../dom/query-selector'
2
3
  import { DEFAULT_EXPIRES_MS, DEFAULT_INACTIVE_MS } from '../../session/constants'
3
4
  import { warn } from '../../util/console'
@@ -31,12 +32,6 @@ const model = () => {
31
32
  }
32
33
  }
33
34
  return {
34
- feature_flags: [],
35
- proxy: {
36
- assets: undefined, // if this value is set, it will be used to overwrite the webpack asset path used to fetch assets
37
- beacon: undefined // likewise for the url to which we send analytics
38
- },
39
- privacy: { cookies_enabled: true }, // *cli - per discussion, default should be true
40
35
  ajax: { deny_list: undefined, block_internal: true, enabled: true, harvestTimeSeconds: 10, autoStart: true },
41
36
  distributed_tracing: {
42
37
  enabled: undefined,
@@ -45,19 +40,24 @@ const model = () => {
45
40
  cors_use_tracecontext_headers: undefined,
46
41
  allowed_origins: undefined
47
42
  },
48
- session: {
49
- expiresMs: DEFAULT_EXPIRES_MS,
50
- inactiveMs: DEFAULT_INACTIVE_MS
51
- },
52
- ssl: undefined,
53
- obfuscate: undefined,
43
+ feature_flags: [],
44
+ harvest: { tooManyRequestsDelay: 60 },
54
45
  jserrors: { enabled: true, harvestTimeSeconds: 10, autoStart: true },
46
+ logging: { enabled: true, harvestTimeSeconds: 10, autoStart: true, level: LOG_LEVELS.INFO },
55
47
  metrics: { enabled: true, autoStart: true },
48
+ obfuscate: undefined,
56
49
  page_action: { enabled: true, harvestTimeSeconds: 30, autoStart: true },
57
50
  page_view_event: { enabled: true, autoStart: true },
58
51
  page_view_timing: { enabled: true, harvestTimeSeconds: 30, long_task: false, autoStart: true },
59
- session_trace: { enabled: true, harvestTimeSeconds: 10, autoStart: true },
60
- harvest: { tooManyRequestsDelay: 60 },
52
+ privacy: { cookies_enabled: true }, // *cli - per discussion, default should be true
53
+ proxy: {
54
+ assets: undefined, // if this value is set, it will be used to overwrite the webpack asset path used to fetch assets
55
+ beacon: undefined // likewise for the url to which we send analytics
56
+ },
57
+ session: {
58
+ expiresMs: DEFAULT_EXPIRES_MS,
59
+ inactiveMs: DEFAULT_INACTIVE_MS
60
+ },
61
61
  session_replay: {
62
62
  // feature settings
63
63
  autoStart: true,
@@ -100,8 +100,10 @@ const model = () => {
100
100
  else warn('An invalid session_replay.mask_input_option was provided and will not be used', val)
101
101
  }
102
102
  },
103
+ session_trace: { enabled: true, harvestTimeSeconds: 10, autoStart: true },
104
+ soft_navigations: { enabled: true, harvestTimeSeconds: 10, autoStart: true },
103
105
  spa: { enabled: true, harvestTimeSeconds: 10, autoStart: true },
104
- soft_navigations: { enabled: true, harvestTimeSeconds: 10, autoStart: true }
106
+ ssl: undefined
105
107
  }
106
108
  }
107
109
 
@@ -5,6 +5,8 @@
5
5
  * @license Apache-2.0
6
6
  */
7
7
 
8
+ import { now } from '../timing/now'
9
+
8
10
  /**
9
11
  * Indicates if the agent is running within a normal browser window context.
10
12
  */
@@ -79,4 +81,4 @@ export const supportsSendBeacon = !!globalScope.navigator?.sendBeacon
79
81
  * according to the browser's local clock.
80
82
  * @type {number}
81
83
  */
82
- export const originTime = Math.floor(Date.now() - performance.now())
84
+ export const originTime = Date.now() - now()
@@ -10,7 +10,7 @@ var denyList = []
10
10
  * @returns {boolean} `true` if request does not match any entries of {@link denyList|deny list}; else `false`
11
11
  */
12
12
  export function shouldCollectEvent (params) {
13
- if (hasUndefinedHostname(params)) return false
13
+ if (!params || hasUndefinedHostname(params)) return false
14
14
 
15
15
  if (denyList.length === 0) return true
16
16
 
@@ -3,7 +3,7 @@ import { warn } from '../util/console'
3
3
  import { stringify } from '../util/stringify'
4
4
  import { ee } from '../event-emitter/contextual-ee'
5
5
  import { Timer } from '../timer/timer'
6
- import { isBrowserScope } from '../constants/runtime'
6
+ import { isBrowserScope, isIE } from '../constants/runtime'
7
7
  import { DEFAULT_EXPIRES_MS, DEFAULT_INACTIVE_MS, MODE, PREFIX, SESSION_EVENTS, SESSION_EVENT_TYPES } from './constants'
8
8
  import { InteractionTimer } from '../timer/interaction-timer'
9
9
  import { wrapEvents } from '../wrap'
@@ -52,7 +52,12 @@ export class SessionEntity {
52
52
  wrapEvents(this.ee)
53
53
  this.setup(opts)
54
54
 
55
- if (isBrowserScope) {
55
+ /**
56
+ * Do not emit session storage events for IE11, because IE11 is unable to determine
57
+ * if the event was spawned on the current page or an adjacent page, and the behavior tied
58
+ * to storage events is critical to apply only to cross-tab behavior
59
+ * */
60
+ if (isBrowserScope && !isIE) {
56
61
  windowAddEventListener('storage', (event) => {
57
62
  if (event.key === this.lookupKey) {
58
63
  const obj = typeof event.newValue === 'string' ? JSON.parse(event.newValue) : event.newValue
@@ -61,7 +61,7 @@ export class TimeKeeper {
61
61
  }
62
62
 
63
63
  const medianRumOffset = (endTime - startTime) / 2
64
- const serverOffset = Math.floor(startTime + medianRumOffset)
64
+ const serverOffset = startTime + medianRumOffset
65
65
 
66
66
  // Corrected page origin time
67
67
  this.#correctedOriginTime = Math.floor(Date.parse(responseDateHeader) - serverOffset)
@@ -82,7 +82,7 @@ export class TimeKeeper {
82
82
  * @returns {number} Corrected unix/epoch timestamp
83
83
  */
84
84
  convertRelativeTimestamp (relativeTime) {
85
- return this.#correctedOriginTime + relativeTime
85
+ return Math.floor(this.#correctedOriginTime + relativeTime)
86
86
  }
87
87
 
88
88
  /**
@@ -0,0 +1,49 @@
1
+ /*
2
+ * Copyright 2020 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ /**
6
+ * @file Wraps native timeout and interval methods for instrumentation.
7
+ * This module is used by: jserrors, spa.
8
+ */
9
+
10
+ import { ee as baseEE, contextId } from '../event-emitter/contextual-ee'
11
+ import { EventContext } from '../event-emitter/event-context'
12
+ import { createWrapperWithEmitter as wfn } from './wrap-function'
13
+
14
+ /**
15
+ * Wraps a supplied function and adds emitter events under the `-wrap-logger-` prefix
16
+ * @param {Object} sharedEE - The shared event emitter on which a new scoped event emitter will be based.
17
+ * @param {Object} parent - The parent object housing the logger function
18
+ * @param {string} loggerFn - The name of the function in the parent object to wrap
19
+ * @returns {Object} Scoped event emitter with a debug ID of `logger`.
20
+ */
21
+ // eslint-disable-next-line
22
+ export function wrapLogger(sharedEE, parent, loggerFn, context) {
23
+ const ee = scopedEE(sharedEE)
24
+ const wrapFn = wfn(ee)
25
+
26
+ /**
27
+ * This section contains the context that will be shared across all invoked calls of the wrapped function,
28
+ * which will be used to decorate the log data later at agg time
29
+ */
30
+ const ctx = new EventContext(contextId)
31
+ ctx.level = context.level
32
+ ctx.customAttributes = context.customAttributes
33
+
34
+ /** observe calls to <loggerFn> and emit events prefixed with `wrap-logger-` */
35
+ wrapFn.inPlace(parent, [loggerFn], 'wrap-logger-', ctx)
36
+
37
+ return ee
38
+ }
39
+
40
+ /**
41
+ * Returns an event emitter scoped specifically for the `logger` context. This scoping is a remnant from when all the
42
+ * features shared the same group in the event, to isolate events between features. It will likely be revisited.
43
+ * @param {Object} sharedEE - Optional event emitter on which to base the scoped emitter.
44
+ * Uses `ee` on the global scope if undefined).
45
+ * @returns {Object} Scoped event emitter with a debug ID of 'logger'.
46
+ */
47
+ export function scopedEE (sharedEE) {
48
+ return (sharedEE || baseEE).get('logger')
49
+ }
@@ -0,0 +1,101 @@
1
+ import { getConfigurationValue, getInfo, getRuntime } from '../../../common/config/config'
2
+ import { handle } from '../../../common/event-emitter/handle'
3
+ import { registerHandler } from '../../../common/event-emitter/register-handler'
4
+ import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
5
+ import { warn } from '../../../common/util/console'
6
+ import { stringify } from '../../../common/util/stringify'
7
+ import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants'
8
+ import { AggregateBase } from '../../utils/aggregate-base'
9
+ import { FEATURE_NAME, LOGGING_EVENT_EMITTER_CHANNEL, LOGGING_IGNORED, MAX_PAYLOAD_SIZE } from '../constants'
10
+ import { Log } from '../shared/log'
11
+
12
+ export class Aggregate extends AggregateBase {
13
+ static featureName = FEATURE_NAME
14
+ #agentRuntime
15
+ #agentInfo
16
+ constructor (agentIdentifier, aggregator) {
17
+ super(agentIdentifier, aggregator, FEATURE_NAME)
18
+
19
+ /** held logs before sending */
20
+ this.bufferedLogs = []
21
+ /** held logs during sending, for retries */
22
+ this.outgoingLogs = []
23
+ /** the estimated bytes of log data waiting to be sent -- triggers a harvest if adding a new log will exceed limit */
24
+ this.estimatedBytes = 0
25
+
26
+ this.#agentRuntime = getRuntime(this.agentIdentifier)
27
+ this.#agentInfo = getInfo(this.agentIdentifier)
28
+
29
+ this.harvestTimeSeconds = getConfigurationValue(this.agentIdentifier, 'logging.harvestTimeSeconds')
30
+
31
+ this.waitForFlags([]).then(() => {
32
+ this.scheduler = new HarvestScheduler('browser/logs', {
33
+ onFinished: this.onHarvestFinished.bind(this),
34
+ retryDelay: this.harvestTimeSeconds,
35
+ getPayload: this.prepareHarvest.bind(this),
36
+ raw: true
37
+ }, this)
38
+ /** harvest immediately once started to purge pre-load logs collected */
39
+ this.scheduler.startTimer(this.harvestTimeSeconds, 0)
40
+ /** emitted by instrument class (wrapped loggers) or the api methods directly */
41
+ registerHandler(LOGGING_EVENT_EMITTER_CHANNEL, this.handleLog.bind(this), this.featureName, this.ee)
42
+ this.drain()
43
+ })
44
+ }
45
+
46
+ handleLog (timestamp, message, attributes, level) {
47
+ if (this.blocked) return
48
+ const log = new Log(
49
+ this.#agentRuntime.timeKeeper.convertRelativeTimestamp(timestamp),
50
+ message,
51
+ attributes,
52
+ level
53
+ )
54
+ const logBytes = log.message.length + stringify(log.attributes).length + log.level.length + 10 // timestamp == 10 chars
55
+ if (logBytes > MAX_PAYLOAD_SIZE) {
56
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Failed/Seen', logBytes])
57
+ return warn(LOGGING_IGNORED + '> ' + MAX_PAYLOAD_SIZE + ' bytes', log.message.slice(0, 25) + '...')
58
+ }
59
+
60
+ if (this.estimatedBytes + logBytes >= MAX_PAYLOAD_SIZE) {
61
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Early/Seen', this.estimatedBytes + logBytes])
62
+ this.scheduler.runHarvest({})
63
+ }
64
+ this.estimatedBytes += logBytes
65
+ this.bufferedLogs.push(log)
66
+ }
67
+
68
+ prepareHarvest () {
69
+ if (this.blocked || !(this.bufferedLogs.length || this.outgoingLogs.length)) return
70
+ /** populate outgoing array while also clearing main buffer */
71
+ this.outgoingLogs.push(...this.bufferedLogs.splice(0))
72
+ this.estimatedBytes = 0
73
+ /** see https://source.datanerd.us/agents/rum-specs/blob/main/browser/Log for logging spec */
74
+ return {
75
+ qs: {
76
+ browser_monitoring_key: this.#agentInfo.licenseKey
77
+ },
78
+ body: [{
79
+ common: {
80
+ /** Attributes in the `common` section are added to `all` logs generated in the payload */
81
+ attributes: {
82
+ 'entity.guid': this.#agentRuntime.appMetadata?.agents?.[0]?.entityGuid, // browser entity guid as provided from RUM response
83
+ session: this.#agentRuntime?.session?.state.value || '0', // The session ID that we generate and keep across page loads
84
+ hasReplay: this.#agentRuntime?.session?.state.sessionReplayMode === 1, // True if a session replay recording is running
85
+ hasTrace: this.#agentRuntime?.session?.state.sessionTraceMode === 1, // True if a session trace recording is running
86
+ ptid: this.#agentRuntime.ptid, // page trace id
87
+ appId: this.#agentInfo.applicationID, // Application ID from info object,
88
+ standalone: Boolean(this.#agentInfo.sa), // copy paste (true) vs APM (false)
89
+ agentVersion: this.#agentRuntime.version // browser agent version
90
+ }
91
+ },
92
+ /** logs section contains individual unique log entries */
93
+ logs: this.outgoingLogs
94
+ }]
95
+ }
96
+ }
97
+
98
+ onHarvestFinished (result) {
99
+ if (!result.retry) this.outgoingLogs = []
100
+ }
101
+ }
@@ -0,0 +1,19 @@
1
+ import { FEATURE_NAMES } from '../../loaders/features/features'
2
+
3
+ export const LOG_LEVELS = {
4
+ ERROR: 'ERROR',
5
+ WARN: 'WARN',
6
+ INFO: 'INFO',
7
+ DEBUG: 'DEBUG',
8
+ TRACE: 'TRACE'
9
+ }
10
+
11
+ export const LOGGING_EVENT_EMITTER_CHANNEL = 'log'
12
+
13
+ export const FEATURE_NAME = FEATURE_NAMES.logging
14
+
15
+ export const MAX_PAYLOAD_SIZE = 1000000
16
+
17
+ export const LOGGING_FAILURE_MESSAGE = 'failed to wrap logger: '
18
+ export const LOGGING_LEVEL_FAILURE_MESSAGE = 'invalid log level: '
19
+ export const LOGGING_IGNORED = 'ignored log: '