@newrelic/browser-agent 1.302.0-rc.7 → 1.302.0-rc.9

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 (81) hide show
  1. package/dist/cjs/common/config/init-types.js +2 -0
  2. package/dist/cjs/common/config/init.js +3 -0
  3. package/dist/cjs/common/constants/env.cdn.js +1 -1
  4. package/dist/cjs/common/constants/env.npm.js +1 -1
  5. package/dist/cjs/common/harvest/harvester.js +1 -0
  6. package/dist/cjs/common/session/session-entity.js +4 -2
  7. package/dist/cjs/features/generic_events/aggregate/index.js +2 -2
  8. package/dist/cjs/features/page_view_event/aggregate/index.js +4 -2
  9. package/dist/cjs/features/page_view_event/instrument/index.js +0 -4
  10. package/dist/cjs/features/utils/agent-session.js +13 -0
  11. package/dist/cjs/features/utils/instrument-base.js +7 -8
  12. package/dist/cjs/interfaces/registered-entity.js +11 -0
  13. package/dist/cjs/loaders/agent.js +2 -0
  14. package/dist/cjs/loaders/api/consent.js +24 -0
  15. package/dist/cjs/loaders/api/constants.js +3 -2
  16. package/dist/cjs/loaders/api/measure.js +36 -35
  17. package/dist/cjs/loaders/api/register-api-types.js +1 -0
  18. package/dist/cjs/loaders/api/register.js +8 -0
  19. package/dist/cjs/loaders/api-base.js +11 -1
  20. package/dist/esm/common/config/init-types.js +2 -0
  21. package/dist/esm/common/config/init.js +3 -0
  22. package/dist/esm/common/constants/env.cdn.js +1 -1
  23. package/dist/esm/common/constants/env.npm.js +1 -1
  24. package/dist/esm/common/harvest/harvester.js +1 -0
  25. package/dist/esm/common/session/session-entity.js +4 -2
  26. package/dist/esm/features/generic_events/aggregate/index.js +2 -2
  27. package/dist/esm/features/page_view_event/aggregate/index.js +4 -2
  28. package/dist/esm/features/page_view_event/instrument/index.js +0 -4
  29. package/dist/esm/features/utils/agent-session.js +13 -0
  30. package/dist/esm/features/utils/instrument-base.js +7 -8
  31. package/dist/esm/interfaces/registered-entity.js +11 -0
  32. package/dist/esm/loaders/agent.js +2 -0
  33. package/dist/esm/loaders/api/consent.js +17 -0
  34. package/dist/esm/loaders/api/constants.js +2 -1
  35. package/dist/esm/loaders/api/measure.js +35 -35
  36. package/dist/esm/loaders/api/register-api-types.js +1 -0
  37. package/dist/esm/loaders/api/register.js +8 -0
  38. package/dist/esm/loaders/api-base.js +12 -2
  39. package/dist/tsconfig.tsbuildinfo +1 -1
  40. package/dist/types/common/config/init-types.d.ts +6 -0
  41. package/dist/types/common/config/init.d.ts.map +1 -1
  42. package/dist/types/common/harvest/harvester.d.ts.map +1 -1
  43. package/dist/types/common/session/session-entity.d.ts.map +1 -1
  44. package/dist/types/features/page_view_event/aggregate/index.d.ts +1 -0
  45. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  46. package/dist/types/features/page_view_event/instrument/index.d.ts.map +1 -1
  47. package/dist/types/features/utils/agent-session.d.ts.map +1 -1
  48. package/dist/types/features/utils/instrument-base.d.ts +1 -0
  49. package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
  50. package/dist/types/interfaces/registered-entity.d.ts +18 -0
  51. package/dist/types/interfaces/registered-entity.d.ts.map +1 -1
  52. package/dist/types/loaders/agent.d.ts.map +1 -1
  53. package/dist/types/loaders/api/consent.d.ts +2 -0
  54. package/dist/types/loaders/api/consent.d.ts.map +1 -0
  55. package/dist/types/loaders/api/constants.d.ts +1 -0
  56. package/dist/types/loaders/api/constants.d.ts.map +1 -1
  57. package/dist/types/loaders/api/measure.d.ts +3 -0
  58. package/dist/types/loaders/api/measure.d.ts.map +1 -1
  59. package/dist/types/loaders/api/register-api-types.d.ts +9 -0
  60. package/dist/types/loaders/api/register-api-types.d.ts.map +1 -1
  61. package/dist/types/loaders/api/register.d.ts.map +1 -1
  62. package/dist/types/loaders/api-base.d.ts +14 -2
  63. package/dist/types/loaders/api-base.d.ts.map +1 -1
  64. package/package.json +1 -1
  65. package/src/common/config/init-types.js +2 -0
  66. package/src/common/config/init.js +1 -0
  67. package/src/common/harvest/harvester.js +1 -0
  68. package/src/common/session/session-entity.js +6 -2
  69. package/src/features/generic_events/aggregate/index.js +2 -2
  70. package/src/features/page_view_event/aggregate/index.js +5 -2
  71. package/src/features/page_view_event/instrument/index.js +0 -4
  72. package/src/features/utils/agent-session.js +12 -0
  73. package/src/features/utils/instrument-base.js +7 -9
  74. package/src/interfaces/registered-entity.js +11 -0
  75. package/src/loaders/agent.js +2 -0
  76. package/src/loaders/api/consent.js +18 -0
  77. package/src/loaders/api/constants.js +1 -0
  78. package/src/loaders/api/measure.js +34 -33
  79. package/src/loaders/api/register-api-types.js +1 -0
  80. package/src/loaders/api/register.js +2 -0
  81. package/src/loaders/api-base.js +12 -2
@@ -56,6 +56,18 @@ export function setupAgentSession (agentRef) {
56
56
  agentRef.runtime.session.syncCustomAttribute(key, value)
57
57
  }, 'session', sharedEE)
58
58
 
59
+ registerHandler('api-consent', (accept) => {
60
+ agentRef.runtime.session.write({ consent: accept === undefined ? true : accept })
61
+
62
+ // call sendRum if it wasn't called yet
63
+ agentRef.features.page_view_event.onAggregateImported.then((loaded) => {
64
+ const pveAgg = agentRef.features.page_view_event.featAggregate
65
+ if (loaded && !pveAgg.sentRum) {
66
+ pveAgg.sendRum()
67
+ }
68
+ })
69
+ }, 'session', sharedEE)
70
+
59
71
  drain(agentRef.agentIdentifier, 'session')
60
72
 
61
73
  return agentRef.runtime.session
@@ -49,7 +49,10 @@ export class InstrumentBase extends FeatureBase {
49
49
  * @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
50
50
  * one another if there are inter-features dependencies.
51
51
  */
52
- this.onAggregateImported = undefined
52
+ this.loadedSuccessfully = undefined
53
+ this.onAggregateImported = new Promise(resolve => {
54
+ this.loadedSuccessfully = resolve
55
+ })
53
56
 
54
57
  /**
55
58
  * used in conjunction with newrelic.start() to defer harvesting in features
@@ -83,11 +86,6 @@ export class InstrumentBase extends FeatureBase {
83
86
  importAggregator (agentRef, fetchAggregator, argsObjFromInstrument = {}) {
84
87
  if (this.featAggregate) return
85
88
 
86
- let loadedSuccessfully
87
- this.onAggregateImported = new Promise(resolve => {
88
- loadedSuccessfully = resolve
89
- })
90
-
91
89
  const importLater = async () => {
92
90
  // wait for the deferred promise to resolve before proceeding
93
91
  // this will resolve immediately if the feature is auto-started,
@@ -113,20 +111,20 @@ export class InstrumentBase extends FeatureBase {
113
111
  try {
114
112
  if (!this.#shouldImportAgg(this.featureName, session, agentRef.init)) {
115
113
  drain(this.agentIdentifier, this.featureName)
116
- loadedSuccessfully(false) // aggregate module isn't loaded at all
114
+ this.loadedSuccessfully(false) // aggregate module isn't loaded at all
117
115
  return
118
116
  }
119
117
  const { Aggregate } = await fetchAggregator()
120
118
  this.featAggregate = new Aggregate(agentRef, argsObjFromInstrument)
121
119
 
122
120
  agentRef.runtime.harvester.initializedAggregates.push(this.featAggregate) // "subscribe" the feature to future harvest intervals (PVE will start the timer)
123
- loadedSuccessfully(true)
121
+ this.loadedSuccessfully(true)
124
122
  } catch (e) {
125
123
  warn(34, e)
126
124
  this.abortHandler?.() // undo any important alterations made to the page
127
125
  // not supported yet but nice to do: "abort" this agent's EE for this feature specifically
128
126
  drain(this.agentIdentifier, this.featureName, true)
129
- loadedSuccessfully(false)
127
+ this.loadedSuccessfully(false)
130
128
  if (this.ee) this.ee.abort()
131
129
  }
132
130
  }
@@ -58,6 +58,17 @@ export class RegisteredEntity {
58
58
  warn(35, 'recordCustomEvent')
59
59
  }
60
60
 
61
+ /**
62
+ * Measures a task that is recorded as a BrowserPerformance event.
63
+ * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/measure/}
64
+ * @param {string} name The name of the task
65
+ * @param {{start: number, end: number, duration: number, customAttributes: object}} [options] An object used to control the way the measure API operates
66
+ * @returns {{start: number, end: number, duration: number, customAttributes: object}} Measurement details
67
+ */
68
+ measure (name, options) {
69
+ warn(35, 'measure')
70
+ }
71
+
61
72
  /**
62
73
  * Adds a user-defined attribute name and value to subsequent events on the page for the registered target. Note -- the persist flag does not work with the register API.
63
74
  * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/setcustomattribute/}
@@ -23,6 +23,7 @@ import { setupSetCustomAttributeAPI } from './api/setCustomAttribute'
23
23
  import { setupSetUserIdAPI } from './api/setUserId'
24
24
  import { setupSetApplicationVersionAPI } from './api/setApplicationVersion'
25
25
  import { setupStartAPI } from './api/start'
26
+ import { setupConsentAPI } from './api/consent'
26
27
 
27
28
  /**
28
29
  * @typedef {Object} AgentOptions
@@ -70,6 +71,7 @@ export class Agent extends AgentBase {
70
71
  setupSetUserIdAPI(this)
71
72
  setupSetApplicationVersionAPI(this)
72
73
  setupStartAPI(this)
74
+ setupConsentAPI(this)
73
75
 
74
76
  this.run()
75
77
  }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright 2020-2025 New Relic, Inc. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { prefix, CONSENT } from './constants'
6
+ import { setupAPI } from './sharedHandlers'
7
+ import { handle } from '../../common/event-emitter/handle'
8
+ import { warn } from '../../common/util/console'
9
+
10
+ export function setupConsentAPI (agent) {
11
+ setupAPI(CONSENT, function (accept) {
12
+ if (accept !== undefined && typeof accept !== 'boolean') {
13
+ warn(65, typeof accept)
14
+ return
15
+ }
16
+ handle(prefix + CONSENT, [accept], undefined, 'session', agent.ee)
17
+ }, agent)
18
+ }
@@ -25,3 +25,4 @@ export const SET_USER_ID = 'setUserId'
25
25
  export const START = 'start'
26
26
  export const WRAP_LOGGER = 'wrapLogger'
27
27
  export const MEASURE = 'measure'
28
+ export const CONSENT = 'consent'
@@ -10,44 +10,45 @@ import { prefix, MEASURE } from './constants'
10
10
  import { setupAPI } from './sharedHandlers'
11
11
 
12
12
  export function setupMeasureAPI (agent) {
13
- setupAPI(MEASURE, function (name, options) {
14
- const n = now()
15
- const { start, end, customAttributes } = options || {}
16
- const returnObj = { customAttributes: customAttributes || {} }
13
+ setupAPI(MEASURE, (name, options) => measure(name, options, agent), agent)
14
+ }
15
+
16
+ export function measure (name, options, agentRef, target, timestamp = now()) {
17
+ const { start, end, customAttributes } = options || {}
18
+ const returnObj = { customAttributes: customAttributes || {} }
17
19
 
18
- if (typeof returnObj.customAttributes !== 'object' || typeof name !== 'string' || name.length === 0) {
19
- warn(57)
20
- return
21
- }
20
+ if (typeof returnObj.customAttributes !== 'object' || typeof name !== 'string' || name.length === 0) {
21
+ warn(57)
22
+ return
23
+ }
22
24
 
23
- /**
25
+ /**
24
26
  * getValueFromTiming - Helper function to extract a numeric value from a supplied option.
25
27
  * @param {Number|PerformanceMark} [timing] The timing value
26
28
  * @param {Number} [d] The default value to return if timing is invalid
27
29
  * @returns {Number} The timing value or the default value
28
30
  */
29
- const getValueFromTiming = (timing, d) => {
30
- if (timing == null) return d
31
- if (typeof timing === 'number') return timing
32
- if (timing instanceof PerformanceMark) return timing.startTime
33
- return Number.NaN
34
- }
35
-
36
- returnObj.start = getValueFromTiming(start, 0)
37
- returnObj.end = getValueFromTiming(end, n)
38
- if (Number.isNaN(returnObj.start) || Number.isNaN(returnObj.end)) {
39
- warn(57)
40
- return
41
- }
42
-
43
- returnObj.duration = returnObj.end - returnObj.start
44
- if (returnObj.duration < 0) {
45
- warn(58)
46
- return
47
- }
48
-
49
- handle(prefix + MEASURE, [returnObj, name], undefined, FEATURE_NAMES.genericEvents, agent.ee)
50
-
51
- return returnObj
52
- }, agent)
31
+ const getValueFromTiming = (timing, d) => {
32
+ if (timing == null) return d
33
+ if (typeof timing === 'number') return timing
34
+ if (timing instanceof PerformanceMark) return timing.startTime
35
+ return Number.NaN
36
+ }
37
+
38
+ returnObj.start = getValueFromTiming(start, 0)
39
+ returnObj.end = getValueFromTiming(end, timestamp)
40
+ if (Number.isNaN(returnObj.start) || Number.isNaN(returnObj.end)) {
41
+ warn(57)
42
+ return
43
+ }
44
+
45
+ returnObj.duration = returnObj.end - returnObj.start
46
+ if (returnObj.duration < 0) {
47
+ warn(58)
48
+ return
49
+ }
50
+
51
+ handle(prefix + MEASURE, [returnObj, name, target], undefined, FEATURE_NAMES.genericEvents, agentRef.ee)
52
+
53
+ return returnObj
53
54
  }
@@ -9,6 +9,7 @@
9
9
  * @property {(message: string, options?: { customAttributes?: object, level?: 'ERROR' | 'TRACE' | 'DEBUG' | 'INFO' | 'WARN'}) => void} log - Capture a log for the registered entity.
10
10
  * @property {(error: Error | string, customAttributes?: object) => void} noticeError - Notice an error for the registered entity.
11
11
  * @property {(eventType: string, attributes?: Object) => void} recordCustomEvent - Record a custom event for the registered entity.
12
+ * @property {(eventType: string, options?: {start: number, end: number, duration: number, customAttributes: object}) => {{start: number, end: number, duration: number, customAttributes: object}}} measure - Measures a task that is recorded as a BrowserPerformance event.
12
13
  * @property {(value: string | null) => void} setApplicationVersion - Add an application.version attribute to all outgoing data for the registered entity.
13
14
  * @property {(name: string, value: string | number | boolean | null, persist?: boolean) => void} setCustomAttribute - Add a custom attribute to outgoing data for the registered entity.
14
15
  * @property {(value: string | null) => void} setUserId - Add an enduser.id attribute to all outgoing API data for the registered entity.
@@ -14,6 +14,7 @@ import { log } from './log'
14
14
  import { addPageAction } from './addPageAction'
15
15
  import { noticeError } from './noticeError'
16
16
  import { single } from '../../common/util/invoke'
17
+ import { measure } from './measure'
17
18
  import { recordCustomEvent } from './recordCustomEvent'
18
19
 
19
20
  /**
@@ -79,6 +80,7 @@ export function buildRegisterApi (agentRef, target) {
79
80
  const api = {
80
81
  addPageAction: (name, attributes = {}) => report(addPageAction, [name, { ...attrs, ...attributes }, agentRef], target),
81
82
  log: (message, options = {}) => report(log, [message, { ...options, customAttributes: { ...attrs, ...(options.customAttributes || {}) } }, agentRef], target),
83
+ measure: (name, options = {}) => report(measure, [name, { ...options, customAttributes: { ...attrs, ...(options.customAttributes || {}) } }, agentRef], target),
82
84
  noticeError: (error, attributes = {}) => report(noticeError, [error, { ...attrs, ...attributes }, agentRef], target),
83
85
  recordCustomEvent: (eventType, attributes = {}) => report(recordCustomEvent, [eventType, { ...attrs, ...attributes }, agentRef], target),
84
86
  setApplicationVersion: (value) => setLocalValue('application.version', value),
@@ -3,7 +3,7 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import { warn } from '../common/util/console'
6
- import { ADD_PAGE_ACTION, ADD_RELEASE, ADD_TO_TRACE, FINISHED, INTERACTION, LOG, NOTICE_ERROR, PAUSE_REPLAY, RECORD_CUSTOM_EVENT, RECORD_REPLAY, REGISTER, SET_APPLICATION_VERSION, SET_CURRENT_ROUTE_NAME, SET_CUSTOM_ATTRIBUTE, SET_ERROR_HANDLER, SET_PAGE_VIEW_NAME, SET_USER_ID, START, WRAP_LOGGER, MEASURE } from './api/constants'
6
+ import { ADD_PAGE_ACTION, ADD_RELEASE, ADD_TO_TRACE, CONSENT, FINISHED, INTERACTION, LOG, NOTICE_ERROR, PAUSE_REPLAY, RECORD_CUSTOM_EVENT, RECORD_REPLAY, REGISTER, SET_APPLICATION_VERSION, SET_CURRENT_ROUTE_NAME, SET_CUSTOM_ATTRIBUTE, SET_ERROR_HANDLER, SET_PAGE_VIEW_NAME, SET_USER_ID, START, WRAP_LOGGER, MEASURE } from './api/constants'
7
7
 
8
8
  /**
9
9
  * @typedef {import('./api/interaction-types').InteractionInstance} InteractionInstance
@@ -219,10 +219,20 @@ export class ApiBase {
219
219
  * Measures a task that is recorded as a BrowserPerformance event.
220
220
  * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/measure/}
221
221
  * @param {string} name The name of the task
222
- * @param {object?} options An object used to control the way the measure API operates
222
+ * @param {{start: number, end: number, duration: number, customAttributes: object}} [options] An object used to control the way the measure API operates
223
223
  * @returns {{start: number, end: number, duration: number, customAttributes: object}} Measurement details
224
224
  */
225
225
  measure (name, options) {
226
226
  return this.#callMethod(MEASURE, name, options)
227
227
  }
228
+
229
+ /**
230
+ * Accepts or rejects consent when the agent is configured to require consent before harvesting.
231
+ * The consent state is stored in session storage inside the NRBA_SESSION object.
232
+ * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/consent/}
233
+ * @param {boolean?} accept Whether to accept or reject consent. Defaults to true (accept) if left undefined.
234
+ */
235
+ consent (accept) {
236
+ return this.#callMethod(CONSENT, accept)
237
+ }
228
238
  }