@newrelic/browser-agent 1.320.0 → 1.320.1-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/cjs/common/config/runtime.js +1 -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/event-listener/event-listener-opts.js +1 -1
- package/dist/cjs/common/harvest/connector.js +200 -0
- package/dist/cjs/common/harvest/harvester.js +5 -8
- package/dist/cjs/common/harvest/send.js +8 -7
- package/dist/cjs/common/payloads/payloads.js +3 -2
- package/dist/cjs/common/serialize/bel-serializer.js +17 -4
- package/dist/cjs/common/timer/interaction-timer.js +2 -2
- package/dist/cjs/common/unload/eol.js +3 -3
- package/dist/cjs/common/util/console.js +2 -1
- package/dist/cjs/common/util/feature-flags.js +2 -1
- package/dist/cjs/common/v2/mfe-vitals.js +34 -11
- package/dist/cjs/common/window/page-visibility.js +1 -1
- package/dist/cjs/features/ajax/aggregate/index.js +19 -8
- package/dist/cjs/features/page_view_event/aggregate/index.js +2 -6
- package/dist/cjs/features/page_view_event/aggregate_v2/index.js +109 -0
- package/dist/cjs/features/page_view_event/instrument/index.js +6 -1
- package/dist/cjs/features/page_view_timing/aggregate/index.js +33 -14
- package/dist/cjs/features/session_replay/instrument/index.js +9 -0
- package/dist/cjs/features/session_replay/shared/recorder.js +2 -1
- package/dist/cjs/features/soft_navigations/aggregate/ajax-node.js +16 -4
- package/dist/cjs/features/soft_navigations/aggregate/interaction.js +10 -3
- package/dist/cjs/features/utils/aggregate-base.js +0 -12
- package/dist/cjs/features/utils/instrument-base.js +72 -29
- package/dist/cjs/loaders/agent.js +2 -1
- package/dist/cjs/loaders/api/consent.js +2 -2
- package/dist/cjs/loaders/features/features.js +2 -1
- package/dist/esm/common/config/runtime.js +1 -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/event-listener/event-listener-opts.js +1 -1
- package/dist/esm/common/harvest/connector.js +193 -0
- package/dist/esm/common/harvest/harvester.js +5 -8
- package/dist/esm/common/harvest/send.js +10 -9
- package/dist/esm/common/payloads/payloads.js +3 -2
- package/dist/esm/common/serialize/bel-serializer.js +17 -4
- package/dist/esm/common/timer/interaction-timer.js +2 -2
- package/dist/esm/common/unload/eol.js +3 -3
- package/dist/esm/common/util/console.js +2 -1
- package/dist/esm/common/util/feature-flags.js +2 -1
- package/dist/esm/common/v2/mfe-vitals.js +34 -11
- package/dist/esm/common/window/page-visibility.js +1 -1
- package/dist/esm/features/ajax/aggregate/index.js +19 -8
- package/dist/esm/features/page_view_event/aggregate/index.js +2 -6
- package/dist/esm/features/page_view_event/aggregate_v2/index.js +100 -0
- package/dist/esm/features/page_view_event/instrument/index.js +6 -1
- package/dist/esm/features/page_view_timing/aggregate/index.js +33 -14
- package/dist/esm/features/session_replay/instrument/index.js +9 -0
- package/dist/esm/features/session_replay/shared/recorder.js +2 -1
- package/dist/esm/features/soft_navigations/aggregate/ajax-node.js +16 -4
- package/dist/esm/features/soft_navigations/aggregate/interaction.js +10 -3
- package/dist/esm/features/utils/aggregate-base.js +0 -12
- package/dist/esm/features/utils/instrument-base.js +71 -28
- package/dist/esm/loaders/agent.js +2 -1
- package/dist/esm/loaders/api/consent.js +2 -2
- package/dist/esm/loaders/features/features.js +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/common/config/runtime.d.ts.map +1 -1
- package/dist/types/common/event-listener/event-listener-opts.d.ts +1 -1
- package/dist/types/common/harvest/connector.d.ts +6 -0
- package/dist/types/common/harvest/connector.d.ts.map +1 -0
- package/dist/types/common/harvest/harvester.d.ts.map +1 -1
- package/dist/types/common/harvest/send.d.ts.map +1 -1
- package/dist/types/common/payloads/payloads.d.ts +3 -2
- package/dist/types/common/payloads/payloads.d.ts.map +1 -1
- package/dist/types/common/serialize/bel-serializer.d.ts +9 -1
- package/dist/types/common/serialize/bel-serializer.d.ts.map +1 -1
- package/dist/types/common/unload/eol.d.ts +1 -1
- package/dist/types/common/unload/eol.d.ts.map +1 -1
- package/dist/types/common/util/console.d.ts +2 -1
- package/dist/types/common/util/console.d.ts.map +1 -1
- package/dist/types/common/v2/mfe-vitals.d.ts.map +1 -1
- package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_event/aggregate_v2/index.d.ts +20 -0
- package/dist/types/features/page_view_event/aggregate_v2/index.d.ts.map +1 -0
- package/dist/types/features/page_view_event/instrument/index.d.ts.map +1 -1
- package/dist/types/features/page_view_timing/aggregate/index.d.ts +0 -1
- package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/instrument/index.d.ts +1 -0
- package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/interaction.d.ts.map +1 -1
- package/dist/types/features/utils/aggregate-base.d.ts +0 -5
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
- 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/features/features.d.ts +1 -0
- package/dist/types/loaders/features/features.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/common/config/runtime.js +1 -0
- package/src/common/event-listener/event-listener-opts.js +1 -1
- package/src/common/harvest/connector.js +168 -0
- package/src/common/harvest/harvester.js +7 -9
- package/src/common/harvest/send.js +9 -7
- package/src/common/payloads/payloads.js +3 -2
- package/src/common/serialize/bel-serializer.js +13 -4
- package/src/common/timer/interaction-timer.js +2 -2
- package/src/common/unload/eol.js +3 -3
- package/src/common/util/console.js +2 -1
- package/src/common/util/feature-flags.js +1 -1
- package/src/common/v2/mfe-vitals.js +39 -12
- package/src/common/window/page-visibility.js +1 -1
- package/src/features/ajax/aggregate/index.js +12 -9
- package/src/features/page_view_event/aggregate/index.js +2 -6
- package/src/features/page_view_event/aggregate_v2/index.js +97 -0
- package/src/features/page_view_event/instrument/index.js +6 -1
- package/src/features/page_view_timing/aggregate/index.js +24 -15
- package/src/features/session_replay/instrument/index.js +9 -0
- package/src/features/session_replay/shared/recorder.js +2 -1
- package/src/features/soft_navigations/aggregate/ajax-node.js +10 -7
- package/src/features/soft_navigations/aggregate/interaction.js +6 -5
- package/src/features/utils/aggregate-base.js +0 -12
- package/src/features/utils/instrument-base.js +71 -25
- package/src/loaders/agent.js +2 -1
- package/src/loaders/api/consent.js +2 -2
- package/src/loaders/features/features.js +1 -0
|
@@ -25,6 +25,7 @@ import { SESSION_ERROR } from '../../common/constants/agent-constants'
|
|
|
25
25
|
import { handle } from '../../common/event-emitter/handle'
|
|
26
26
|
|
|
27
27
|
const checkedAgents = new WeakSet()
|
|
28
|
+
const runtimeBootstrapPromises = new WeakMap()
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* Base class for instrumenting a feature.
|
|
@@ -103,28 +104,13 @@ export class InstrumentBase extends FeatureBase {
|
|
|
103
104
|
return
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if (canEnableSessionTracking(agentRef.init)) { // would require some setup before certain features start
|
|
109
|
-
const { setupAgentSession } = await import(/* webpackChunkName: "session-manager" */ './agent-session')
|
|
110
|
-
session = setupAgentSession(agentRef)
|
|
111
|
-
}
|
|
107
|
+
try { // in the interest of keeping loader file size small, some modules are lazy-loaded as part of the larger async chunk
|
|
108
|
+
await ensureRuntimeBootstrap(agentRef, this.ee, this.featureName)
|
|
112
109
|
} catch (e) {
|
|
113
|
-
warn(
|
|
114
|
-
this.ee.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (agentRef.init.api.register.allow_iframe_bridge) {
|
|
119
|
-
try {
|
|
120
|
-
// This chunk doesn't exist in the lite build (see webpack IgnorePlugin config) since none
|
|
121
|
-
// of lite's features wire up agent.register -- guard against that rather than letting an
|
|
122
|
-
// unhandled rejection surface if this flag is ever set on a lite page.
|
|
123
|
-
const { setupIframeMFEMessageListener } = await import(/* webpackChunkName: "iframe-message-handler" */ '../../loaders/configure/iframe-message-handler')
|
|
124
|
-
setupIframeMFEMessageListener(agentRef)
|
|
125
|
-
} catch (e) {
|
|
126
|
-
warn(23, e)
|
|
127
|
-
}
|
|
110
|
+
warn(79, e)
|
|
111
|
+
this.ee.abort() // failed Connector or Harvester will cause entire agent to shutdown
|
|
112
|
+
this.loadedSuccessfully(false)
|
|
113
|
+
return
|
|
128
114
|
}
|
|
129
115
|
|
|
130
116
|
/**
|
|
@@ -132,23 +118,24 @@ export class InstrumentBase extends FeatureBase {
|
|
|
132
118
|
* it's only responsible for aborting its one specific feature, rather than all.
|
|
133
119
|
*/
|
|
134
120
|
try {
|
|
135
|
-
if (!this.#shouldImportAgg(this.featureName, session, agentRef.init)) {
|
|
121
|
+
if (!this.#shouldImportAgg(this.featureName, agentRef.runtime.session, agentRef.init)) {
|
|
122
|
+
this.abortHandler?.()
|
|
136
123
|
drain(this.agentRef, this.featureName)
|
|
137
124
|
this.loadedSuccessfully(false) // aggregate module isn't loaded at all
|
|
138
125
|
return
|
|
139
126
|
}
|
|
140
127
|
const { Aggregate } = await fetchAggregator()
|
|
128
|
+
|
|
141
129
|
this.featAggregate = new Aggregate(agentRef, argsObjFromInstrument)
|
|
142
130
|
|
|
143
|
-
agentRef.runtime.harvester.initializedAggregates.push(this.featAggregate) // "subscribe" the feature to future harvest intervals
|
|
131
|
+
agentRef.runtime.harvester.initializedAggregates.push(this.featAggregate) // "subscribe" the feature to future harvest intervals
|
|
144
132
|
this.loadedSuccessfully(true)
|
|
145
133
|
} catch (e) {
|
|
146
134
|
warn(34, e)
|
|
147
|
-
this.abortHandler?.()
|
|
135
|
+
this.abortHandler?.()
|
|
148
136
|
// not supported yet but nice to do: "abort" this agent's EE for this feature specifically
|
|
149
137
|
drain(this.agentRef, this.featureName, true)
|
|
150
138
|
this.loadedSuccessfully(false)
|
|
151
|
-
if (this.ee) this.ee.abort()
|
|
152
139
|
}
|
|
153
140
|
}
|
|
154
141
|
|
|
@@ -206,3 +193,62 @@ export class InstrumentBase extends FeatureBase {
|
|
|
206
193
|
}
|
|
207
194
|
}
|
|
208
195
|
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Lazily initializes the shared runtime bootstrap for a given agent exactly once. This loads session setup, Connector, and
|
|
199
|
+
* Harvester through shared async chunks and returns the same in-flight Promise to any concurrent callers.
|
|
200
|
+
*
|
|
201
|
+
* Session setup failures are reported but do not stop bootstrap. Connector or Harvester failures are allowed to bubble so the caller can abort the agent.
|
|
202
|
+
*
|
|
203
|
+
* @param {Object} agentRef - The agent reference object.
|
|
204
|
+
* @param {Object} ee - The feature event emitter used for error reporting.
|
|
205
|
+
* @param {string} featureName - The feature name used when reporting session setup errors.
|
|
206
|
+
* @returns {Promise<void>} Resolves when the shared bootstrap completes.
|
|
207
|
+
*/
|
|
208
|
+
async function ensureRuntimeBootstrap (agentRef, ee, featureName) {
|
|
209
|
+
if (runtimeBootstrapPromises.has(agentRef)) return runtimeBootstrapPromises.get(agentRef)
|
|
210
|
+
|
|
211
|
+
const bootstrapPromise = (async () => {
|
|
212
|
+
if (canEnableSessionTracking(agentRef.init)) {
|
|
213
|
+
try {
|
|
214
|
+
const { setupAgentSession } = await import(/* webpackChunkName: "session-manager" */ './agent-session')
|
|
215
|
+
setupAgentSession(agentRef) // sets agentRef.runtime.session, if successful
|
|
216
|
+
} catch (e) {
|
|
217
|
+
warn(20, e)
|
|
218
|
+
ee.emit('internal-error', [e])
|
|
219
|
+
handle(SESSION_ERROR, [e], undefined, featureName, ee)
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (agentRef.init.api.register.allow_iframe_bridge) {
|
|
223
|
+
try {
|
|
224
|
+
// This chunk doesn't exist in the lite build (see webpack IgnorePlugin config) since none
|
|
225
|
+
// of lite's features wire up agent.register -- guard against that rather than letting an
|
|
226
|
+
// unhandled rejection surface if this flag is ever set on a lite page.
|
|
227
|
+
const { setupIframeMFEMessageListener } = await import(/* webpackChunkName: "iframe-message-handler" */ '../../loaders/configure/iframe-message-handler')
|
|
228
|
+
setupIframeMFEMessageListener(agentRef)
|
|
229
|
+
} catch (e) {
|
|
230
|
+
warn(23, e)
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const [{ Connector }, { Harvester }] = await Promise.all([
|
|
235
|
+
import(/* webpackChunkName: "connector" */ '../../common/harvest/connector'),
|
|
236
|
+
import(/* webpackChunkName: "harvester" */ '../../common/harvest/harvester')
|
|
237
|
+
])
|
|
238
|
+
agentRef.runtime.connector = new Connector(agentRef)
|
|
239
|
+
agentRef.runtime.harvester = new Harvester(agentRef)
|
|
240
|
+
|
|
241
|
+
/* Wait for auto-started features' aggregates to load before starting the harvest timer, so Harvester's EOL
|
|
242
|
+
listener registers after aggregate-level listeners like web-vitals' CWV APIs. Not awaited here to avoid
|
|
243
|
+
deadlock, since every feature awaits this same bootstrap promise before its own aggregate load.
|
|
244
|
+
Only auto-started features are waited on: an autoStart:false feature only registers in drainRegistry once
|
|
245
|
+
`start` is called, so filtering on that registry excludes any feature that's never started instead of
|
|
246
|
+
blocking startTimer() forever. */
|
|
247
|
+
const autoStartedFeatures = Object.values(agentRef.features).filter(feature => agentRef.runtime.drainRegistry.has(feature.featureName))
|
|
248
|
+
Promise.all(autoStartedFeatures.map(feature => feature.onAggregateImported))
|
|
249
|
+
.then(() => agentRef.runtime.harvester.startTimer())
|
|
250
|
+
})()
|
|
251
|
+
|
|
252
|
+
runtimeBootstrapPromises.set(agentRef, bootstrapPromise)
|
|
253
|
+
await bootstrapPromise
|
|
254
|
+
}
|
package/src/loaders/agent.js
CHANGED
|
@@ -93,10 +93,11 @@ export class Agent extends AgentBase {
|
|
|
93
93
|
try {
|
|
94
94
|
const enabledFeatures = getEnabledFeatures(this.init)
|
|
95
95
|
const featuresToStart = [...this.desiredFeatures]
|
|
96
|
+
const isRumV2Enabled = this.init.feature_flags.includes('rum_v2')
|
|
96
97
|
|
|
97
98
|
featuresToStart.sort((a, b) => featurePriority[a.featureName] - featurePriority[b.featureName])
|
|
98
99
|
featuresToStart.forEach(InstrumentCtor => {
|
|
99
|
-
if (!enabledFeatures[InstrumentCtor.featureName] && InstrumentCtor.featureName !== FEATURE_NAMES.pageViewEvent) return // PVE is required to run even if it's marked disabled
|
|
100
|
+
if (!enabledFeatures[InstrumentCtor.featureName] && (isRumV2Enabled || InstrumentCtor.featureName !== FEATURE_NAMES.pageViewEvent)) return // PVE is required to run even if it's marked disabled unless rum_v2 is enabled
|
|
100
101
|
|
|
101
102
|
const dependencies = getFeatureDependencyNames(InstrumentCtor.featureName)
|
|
102
103
|
const missingDependencies = dependencies.filter(featName => !(featName in this.features)) // any other feature(s) this depends on should've been initialized on prior iterations by priority order
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright 2020-
|
|
2
|
+
* Copyright 2020-2026 New Relic, Inc. All rights reserved.
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
import { prefix, CONSENT } from './constants'
|
|
@@ -23,7 +23,7 @@ export function setupConsentAPI (agent) {
|
|
|
23
23
|
pveInst.onAggregateImported.then((loaded) => {
|
|
24
24
|
const pveAgg = pveInst.featAggregate
|
|
25
25
|
if (loaded && !pveAgg.sentRum) {
|
|
26
|
-
pveAgg.sendRum()
|
|
26
|
+
pveAgg.sendRum?.() // only the old v1 aggregate has a sendRum method that acts as a blocker for the rest of the agent; v2 aggregate will auto report when harvester becomes unblocked
|
|
27
27
|
}
|
|
28
28
|
})
|
|
29
29
|
}
|