@newrelic/browser-agent 1.302.0-rc.6 → 1.302.0-rc.8
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.
- package/dist/cjs/common/config/init-types.js +2 -0
- package/dist/cjs/common/config/init.js +3 -0
- package/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/harvest/harvester.js +13 -9
- package/dist/cjs/common/harvest/types.js +0 -1
- package/dist/cjs/common/session/session-entity.js +4 -2
- package/dist/cjs/features/page_view_event/aggregate/index.js +36 -22
- package/dist/cjs/features/page_view_event/instrument/index.js +0 -4
- package/dist/cjs/features/utils/agent-session.js +13 -0
- package/dist/cjs/features/utils/instrument-base.js +7 -8
- package/dist/cjs/loaders/agent.js +2 -0
- package/dist/cjs/loaders/api/consent.js +24 -0
- package/dist/cjs/loaders/api/constants.js +3 -2
- package/dist/cjs/loaders/api-base.js +10 -0
- package/dist/esm/common/config/init-types.js +2 -0
- package/dist/esm/common/config/init.js +3 -0
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/harvest/harvester.js +13 -9
- package/dist/esm/common/harvest/types.js +0 -1
- package/dist/esm/common/session/session-entity.js +4 -2
- package/dist/esm/features/page_view_event/aggregate/index.js +36 -22
- package/dist/esm/features/page_view_event/instrument/index.js +0 -4
- package/dist/esm/features/utils/agent-session.js +13 -0
- package/dist/esm/features/utils/instrument-base.js +7 -8
- package/dist/esm/loaders/agent.js +2 -0
- package/dist/esm/loaders/api/consent.js +17 -0
- package/dist/esm/loaders/api/constants.js +2 -1
- package/dist/esm/loaders/api-base.js +11 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/common/config/init-types.d.ts +6 -0
- package/dist/types/common/config/init.d.ts.map +1 -1
- package/dist/types/common/harvest/harvester.d.ts.map +1 -1
- package/dist/types/common/harvest/types.d.ts +0 -2
- package/dist/types/common/harvest/types.d.ts.map +1 -1
- package/dist/types/common/session/session-entity.d.ts.map +1 -1
- package/dist/types/features/page_view_event/aggregate/index.d.ts +22 -3
- package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_event/instrument/index.d.ts.map +1 -1
- package/dist/types/features/utils/agent-session.d.ts.map +1 -1
- package/dist/types/features/utils/instrument-base.d.ts +1 -0
- package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
- package/dist/types/loaders/agent.d.ts.map +1 -1
- package/dist/types/loaders/api/consent.d.ts +2 -0
- package/dist/types/loaders/api/consent.d.ts.map +1 -0
- package/dist/types/loaders/api/constants.d.ts +1 -0
- package/dist/types/loaders/api/constants.d.ts.map +1 -1
- package/dist/types/loaders/api-base.d.ts +7 -0
- package/dist/types/loaders/api-base.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/common/config/init-types.js +2 -0
- package/src/common/config/init.js +1 -0
- package/src/common/harvest/harvester.js +11 -8
- package/src/common/harvest/types.js +0 -1
- package/src/common/session/session-entity.js +6 -2
- package/src/features/page_view_event/aggregate/index.js +29 -15
- package/src/features/page_view_event/instrument/index.js +0 -4
- package/src/features/utils/agent-session.js +12 -0
- package/src/features/utils/instrument-base.js +7 -9
- package/src/loaders/agent.js +2 -0
- package/src/loaders/api/consent.js +18 -0
- package/src/loaders/api/constants.js +1 -0
- package/src/loaders/api-base.js +11 -1
|
@@ -23,12 +23,16 @@ import { getSubmitMethod } from '../../../common/util/submit-data'
|
|
|
23
23
|
|
|
24
24
|
export class Aggregate extends AggregateBase {
|
|
25
25
|
static featureName = CONSTANTS.FEATURE_NAME
|
|
26
|
+
|
|
26
27
|
constructor (agentRef) {
|
|
27
28
|
super(agentRef, CONSTANTS.FEATURE_NAME)
|
|
28
29
|
|
|
30
|
+
this.sentRum = false // flag to facilitate calling sendRum() once externally (by the consent API in agent-session.js)
|
|
31
|
+
|
|
29
32
|
this.timeToFirstByte = 0
|
|
30
33
|
this.firstByteToWindowLoad = 0 // our "frontend" duration
|
|
31
34
|
this.firstByteToDomContent = 0 // our "dom processing" duration
|
|
35
|
+
this.retries = 0
|
|
32
36
|
|
|
33
37
|
if (!isValid(agentRef.info)) {
|
|
34
38
|
this.ee.abort()
|
|
@@ -55,9 +59,8 @@ export class Aggregate extends AggregateBase {
|
|
|
55
59
|
*
|
|
56
60
|
* @param {Function} cb A function to run once the RUM call has finished - Defaults to activateFeatures
|
|
57
61
|
* @param {*} customAttributes custom attributes to attach to the RUM call - Defaults to info.js
|
|
58
|
-
* @param {*} target The target to harvest to
|
|
59
62
|
*/
|
|
60
|
-
sendRum (customAttributes = this.agentRef.info.jsAttributes
|
|
63
|
+
sendRum (customAttributes = this.agentRef.info.jsAttributes) {
|
|
61
64
|
const info = this.agentRef.info
|
|
62
65
|
const measures = {}
|
|
63
66
|
|
|
@@ -110,24 +113,26 @@ export class Aggregate extends AggregateBase {
|
|
|
110
113
|
queryParameters.fp = firstPaint.current.value
|
|
111
114
|
queryParameters.fcp = firstContentfulPaint.current.value
|
|
112
115
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
+
this.queryStringsBuilder = () => { // this will be called by AggregateBase.makeHarvestPayload every time harvest is triggered to be qs
|
|
117
|
+
this.rumStartTime = now() // this should be reset at the beginning of each RUM call for proper timeKeeper calculation in coordination with postHarvestCleanup
|
|
118
|
+
const timeKeeper = this.agentRef.runtime.timeKeeper
|
|
119
|
+
if (timeKeeper?.ready) {
|
|
120
|
+
queryParameters.timestamp = Math.floor(timeKeeper.correctRelativeTimestamp(this.rumStartTime))
|
|
121
|
+
}
|
|
122
|
+
return queryParameters
|
|
116
123
|
}
|
|
124
|
+
this.events.add(body)
|
|
117
125
|
|
|
118
|
-
this.
|
|
119
|
-
|
|
120
|
-
this.agentRef.runtime.harvester.triggerHarvestFor(this, {
|
|
121
|
-
directSend: {
|
|
122
|
-
target,
|
|
123
|
-
payload: { qs: queryParameters, body }
|
|
124
|
-
},
|
|
125
|
-
needResponse: true,
|
|
126
|
+
if (this.agentRef.runtime.harvester.triggerHarvestFor(this, {
|
|
126
127
|
sendEmptyBody: true
|
|
127
|
-
})
|
|
128
|
+
}).ranSend) this.sentRum = true
|
|
128
129
|
}
|
|
129
130
|
|
|
130
|
-
|
|
131
|
+
serializer (eventBuffer) { // this is necessary because PVE sends a single item rather than an array; in the case of undefined, this prevents sending [null] as body
|
|
132
|
+
return eventBuffer[0]
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
postHarvestCleanup ({ sent, status, responseText, xhr, retry }) {
|
|
131
136
|
const rumEndTime = now()
|
|
132
137
|
let app, flags
|
|
133
138
|
try {
|
|
@@ -137,8 +142,16 @@ export class Aggregate extends AggregateBase {
|
|
|
137
142
|
warn(53, error)
|
|
138
143
|
}
|
|
139
144
|
|
|
145
|
+
super.postHarvestCleanup({ sent, retry }) // this will set isRetrying & re-buffer the body if request is to be retried
|
|
146
|
+
if (this.isRetrying && this.retries++ < 1) { // Only retry once
|
|
147
|
+
setTimeout(() => this.agentRef.runtime.harvester.triggerHarvestFor(this, {
|
|
148
|
+
sendEmptyBody: true
|
|
149
|
+
}), 5000) // Retry sending the RUM event after 5 seconds
|
|
150
|
+
return
|
|
151
|
+
}
|
|
140
152
|
if (status >= 400 || status === 0) {
|
|
141
153
|
warn(18, status)
|
|
154
|
+
this.blocked = true
|
|
142
155
|
|
|
143
156
|
// Get estimated payload size of our backlog
|
|
144
157
|
const textEncoder = new TextEncoder()
|
|
@@ -205,6 +218,7 @@ export class Aggregate extends AggregateBase {
|
|
|
205
218
|
}
|
|
206
219
|
} catch (error) {
|
|
207
220
|
this.ee.abort()
|
|
221
|
+
this.blocked = true
|
|
208
222
|
warn(17, error)
|
|
209
223
|
return
|
|
210
224
|
}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
|
-
import { handle } from '../../../common/event-emitter/handle'
|
|
6
5
|
import { setupSetPageViewNameAPI } from '../../../loaders/api/setPageViewName'
|
|
7
6
|
import { InstrumentBase } from '../../utils/instrument-base'
|
|
8
7
|
import * as CONSTANTS from '../constants'
|
|
@@ -21,9 +20,6 @@ export class Instrument extends InstrumentBase {
|
|
|
21
20
|
/** feature specific APIs */
|
|
22
21
|
setupSetPageViewNameAPI(agentRef)
|
|
23
22
|
|
|
24
|
-
/** messages from the register API that can trigger a new RUM call */
|
|
25
|
-
this.ee.on('api-send-rum', (attrs, target) => handle('send-rum', [attrs, target], undefined, this.featureName, this.ee))
|
|
26
|
-
|
|
27
23
|
this.importAggregator(agentRef, () => import(/* webpackChunkName: "page_view_event-aggregate" */ '../aggregate'))
|
|
28
24
|
}
|
|
29
25
|
|
|
@@ -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.
|
|
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
|
}
|
package/src/loaders/agent.js
CHANGED
|
@@ -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
|
+
}
|
package/src/loaders/api-base.js
CHANGED
|
@@ -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
|
|
@@ -225,4 +225,14 @@ export class ApiBase {
|
|
|
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
|
}
|