@newrelic/browser-agent 1.269.0 → 1.270.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.
- package/CHANGELOG.md +11 -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/constants/runtime.js +1 -2
- package/dist/cjs/common/harvest/harvest-scheduler.js +3 -4
- package/dist/cjs/common/unload/eol.js +2 -5
- package/dist/cjs/common/util/submit-data.js +1 -1
- package/dist/cjs/features/ajax/aggregate/index.js +8 -17
- package/dist/cjs/features/ajax/instrument/index.js +8 -10
- package/dist/cjs/features/generic_events/aggregate/index.js +15 -22
- package/dist/cjs/features/generic_events/instrument/index.js +5 -8
- package/dist/cjs/features/jserrors/aggregate/index.js +17 -22
- package/dist/cjs/features/jserrors/instrument/index.js +3 -3
- package/dist/cjs/features/logging/aggregate/index.js +16 -23
- package/dist/cjs/features/logging/instrument/index.js +3 -3
- package/dist/cjs/features/metrics/aggregate/index.js +13 -16
- package/dist/cjs/features/metrics/instrument/index.js +3 -3
- package/dist/cjs/features/page_view_event/aggregate/index.js +15 -29
- package/dist/cjs/features/page_view_event/instrument/index.js +3 -3
- package/dist/cjs/features/page_view_timing/aggregate/index.js +6 -23
- package/dist/cjs/features/page_view_timing/instrument/index.js +3 -3
- package/dist/cjs/features/session_replay/aggregate/index.js +15 -29
- package/dist/cjs/features/session_replay/instrument/index.js +7 -5
- package/dist/cjs/features/session_trace/aggregate/index.js +25 -31
- package/dist/cjs/features/session_trace/instrument/index.js +4 -5
- package/dist/cjs/features/soft_navigations/aggregate/index.js +6 -11
- package/dist/cjs/features/soft_navigations/instrument/index.js +3 -3
- package/dist/cjs/features/spa/aggregate/index.js +19 -30
- package/dist/cjs/features/spa/instrument/index.js +4 -4
- package/dist/cjs/features/utils/aggregate-base.js +11 -12
- package/dist/cjs/features/utils/feature-base.js +5 -3
- package/dist/cjs/features/utils/instrument-base.js +18 -10
- package/dist/cjs/loaders/agent.js +1 -5
- package/dist/cjs/loaders/micro-agent.js +6 -9
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/constants/runtime.js +0 -1
- package/dist/esm/common/harvest/harvest-scheduler.js +3 -4
- package/dist/esm/common/unload/eol.js +2 -5
- package/dist/esm/common/util/submit-data.js +2 -2
- package/dist/esm/features/ajax/aggregate/index.js +8 -17
- package/dist/esm/features/ajax/instrument/index.js +8 -10
- package/dist/esm/features/generic_events/aggregate/index.js +11 -18
- package/dist/esm/features/generic_events/instrument/index.js +5 -8
- package/dist/esm/features/jserrors/aggregate/index.js +15 -20
- package/dist/esm/features/jserrors/instrument/index.js +3 -3
- package/dist/esm/features/logging/aggregate/index.js +16 -23
- package/dist/esm/features/logging/instrument/index.js +3 -3
- package/dist/esm/features/metrics/aggregate/index.js +8 -11
- package/dist/esm/features/metrics/instrument/index.js +3 -3
- package/dist/esm/features/page_view_event/aggregate/index.js +16 -30
- package/dist/esm/features/page_view_event/instrument/index.js +3 -3
- package/dist/esm/features/page_view_timing/aggregate/index.js +6 -23
- package/dist/esm/features/page_view_timing/instrument/index.js +3 -3
- package/dist/esm/features/session_replay/aggregate/index.js +13 -27
- package/dist/esm/features/session_replay/instrument/index.js +7 -5
- package/dist/esm/features/session_trace/aggregate/index.js +22 -28
- package/dist/esm/features/session_trace/instrument/index.js +4 -5
- package/dist/esm/features/soft_navigations/aggregate/index.js +6 -11
- package/dist/esm/features/soft_navigations/instrument/index.js +3 -3
- package/dist/esm/features/spa/aggregate/index.js +17 -28
- package/dist/esm/features/spa/instrument/index.js +4 -4
- package/dist/esm/features/utils/aggregate-base.js +13 -14
- package/dist/esm/features/utils/feature-base.js +5 -3
- package/dist/esm/features/utils/instrument-base.js +18 -10
- package/dist/esm/loaders/agent.js +1 -5
- package/dist/esm/loaders/micro-agent.js +6 -9
- package/dist/types/common/constants/runtime.d.ts +0 -1
- package/dist/types/common/constants/runtime.d.ts.map +1 -1
- package/dist/types/common/harvest/harvest-scheduler.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/features/ajax/aggregate/index.d.ts +1 -1
- package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/ajax/instrument/index.d.ts +1 -1
- package/dist/types/features/ajax/instrument/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/aggregate/index.d.ts +1 -2
- package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/instrument/index.d.ts +1 -1
- package/dist/types/features/generic_events/instrument/index.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/jserrors/instrument/index.d.ts +1 -1
- package/dist/types/features/jserrors/instrument/index.d.ts.map +1 -1
- package/dist/types/features/logging/aggregate/index.d.ts +1 -2
- package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/logging/instrument/index.d.ts +1 -1
- package/dist/types/features/logging/instrument/index.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/index.d.ts +1 -1
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/metrics/instrument/index.d.ts +1 -1
- package/dist/types/features/metrics/instrument/index.d.ts.map +1 -1
- package/dist/types/features/page_action/instrument/index.d.ts +1 -0
- package/dist/types/features/page_action/instrument/index.d.ts.map +1 -1
- package/dist/types/features/page_view_event/aggregate/index.d.ts +1 -1
- 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 +1 -1
- 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 +1 -5
- package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_timing/instrument/index.d.ts +1 -1
- package/dist/types/features/page_view_timing/instrument/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts +0 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/instrument/index.d.ts +1 -1
- package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/index.d.ts +1 -3
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/instrument/index.d.ts +1 -1
- package/dist/types/features/session_trace/instrument/index.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/index.d.ts +1 -1
- package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/instrument/index.d.ts +1 -1
- package/dist/types/features/soft_navigations/instrument/index.d.ts.map +1 -1
- package/dist/types/features/spa/aggregate/index.d.ts +1 -1
- package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/spa/instrument/index.d.ts +1 -1
- package/dist/types/features/spa/instrument/index.d.ts.map +1 -1
- package/dist/types/features/utils/aggregate-base.d.ts +2 -2
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
- package/dist/types/features/utils/feature-base.d.ts +2 -3
- package/dist/types/features/utils/feature-base.d.ts.map +1 -1
- package/dist/types/features/utils/instrument-base.d.ts +3 -3
- package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
- package/dist/types/loaders/agent.d.ts +0 -2
- package/dist/types/loaders/agent.d.ts.map +1 -1
- package/dist/types/loaders/micro-agent.d.ts +0 -2
- package/dist/types/loaders/micro-agent.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/common/constants/__mocks__/runtime.js +0 -1
- package/src/common/constants/runtime.js +0 -2
- package/src/common/harvest/harvest-scheduler.js +3 -4
- package/src/common/unload/eol.js +2 -5
- package/src/common/util/submit-data.js +2 -2
- package/src/features/ajax/aggregate/index.js +8 -18
- package/src/features/ajax/instrument/index.js +8 -10
- package/src/features/generic_events/aggregate/index.js +11 -20
- package/src/features/generic_events/instrument/index.js +7 -10
- package/src/features/jserrors/aggregate/index.js +15 -20
- package/src/features/jserrors/instrument/index.js +3 -4
- package/src/features/logging/aggregate/index.js +15 -23
- package/src/features/logging/instrument/index.js +3 -3
- package/src/features/metrics/aggregate/index.js +8 -11
- package/src/features/metrics/instrument/index.js +3 -3
- package/src/features/page_view_event/aggregate/index.js +16 -22
- package/src/features/page_view_event/instrument/index.js +3 -3
- package/src/features/page_view_timing/aggregate/index.js +6 -23
- package/src/features/page_view_timing/instrument/index.js +3 -3
- package/src/features/session_replay/aggregate/index.js +13 -21
- package/src/features/session_replay/instrument/index.js +7 -5
- package/src/features/session_trace/aggregate/index.js +22 -28
- package/src/features/session_trace/instrument/index.js +4 -5
- package/src/features/soft_navigations/aggregate/index.js +6 -8
- package/src/features/soft_navigations/instrument/index.js +3 -3
- package/src/features/spa/aggregate/index.js +17 -26
- package/src/features/spa/instrument/index.js +4 -4
- package/src/features/utils/__mocks__/feature-base.js +1 -2
- package/src/features/utils/aggregate-base.js +13 -14
- package/src/features/utils/feature-base.js +6 -3
- package/src/features/utils/instrument-base.js +16 -10
- package/src/loaders/agent.js +1 -3
- package/src/loaders/micro-agent.js +7 -9
|
@@ -7,8 +7,6 @@ import { nullable, numeric, getAddStringContext, addCustomAttributes } from '../
|
|
|
7
7
|
import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
|
|
8
8
|
import { registerHandler } from '../../../common/event-emitter/register-handler'
|
|
9
9
|
import { handle } from '../../../common/event-emitter/handle'
|
|
10
|
-
import { getInfo } from '../../../common/config/info'
|
|
11
|
-
import { getConfigurationValue } from '../../../common/config/init'
|
|
12
10
|
import { FEATURE_NAME } from '../constants'
|
|
13
11
|
import { FEATURE_NAMES } from '../../../loaders/features/features'
|
|
14
12
|
import { AggregateBase } from '../../utils/aggregate-base'
|
|
@@ -30,16 +28,17 @@ export class Aggregate extends AggregateBase {
|
|
|
30
28
|
this.addTiming(name, value, attrs)
|
|
31
29
|
}
|
|
32
30
|
|
|
33
|
-
constructor (
|
|
34
|
-
super(
|
|
31
|
+
constructor (agentRef) {
|
|
32
|
+
super(agentRef, FEATURE_NAME)
|
|
35
33
|
|
|
36
34
|
this.timings = new EventBuffer()
|
|
37
35
|
this.curSessEndRecorded = false
|
|
38
36
|
|
|
39
37
|
registerHandler('docHidden', msTimestamp => this.endCurrentSession(msTimestamp), this.featureName, this.ee)
|
|
40
|
-
|
|
38
|
+
// Add the time of _window pagehide event_ firing to the next PVT harvest == NRDB windowUnload attr:
|
|
39
|
+
registerHandler('winPagehide', msTimestamp => this.addTiming('unload', msTimestamp, null), this.featureName, this.ee)
|
|
41
40
|
|
|
42
|
-
const harvestTimeSeconds =
|
|
41
|
+
const harvestTimeSeconds = agentRef.init.page_view_timing.harvestTimeSeconds || 30
|
|
43
42
|
|
|
44
43
|
this.waitForFlags(([])).then(() => {
|
|
45
44
|
/* It's important that CWV api, like "onLCP", is called before the **scheduler** is initialized. The reason is because they listen to the same
|
|
@@ -82,21 +81,6 @@ export class Aggregate extends AggregateBase {
|
|
|
82
81
|
}
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
/**
|
|
86
|
-
* Add the time of _window pagehide event_ firing to the next PVT harvest == NRDB windowUnload attr.
|
|
87
|
-
*/
|
|
88
|
-
recordPageUnload (timestamp) {
|
|
89
|
-
this.addTiming('unload', timestamp, null)
|
|
90
|
-
/*
|
|
91
|
-
Issue: Because window's pageHide commonly fires BEFORE vis change and "final" harvest would happen at the former in this case, we also have to add our vis-change event now or it may not be sent.
|
|
92
|
-
Affected: Safari < v14.1/.5 ; versions that don't support 'visiilitychange' event
|
|
93
|
-
Impact: For affected w/o this, NR 'pageHide' attribute may not be sent. For other browsers w/o this, NR 'pageHide' gets fragmented into its own harvest call on page unloading because of dual EoL logic.
|
|
94
|
-
Mitigation: NR 'unload' and 'pageHide' are both recorded when window pageHide fires, rather than only recording 'unload'.
|
|
95
|
-
Future: When EoL can become the singular subscribeToVisibilityChange, it's likely endCurrentSession isn't needed here as 'unload'-'pageHide' can be untangled.
|
|
96
|
-
*/
|
|
97
|
-
this.endCurrentSession(timestamp)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
84
|
addTiming (name, value, attrs) {
|
|
101
85
|
attrs = attrs || {}
|
|
102
86
|
addConnectionAttributes(attrs) // network conditions may differ from the actual for VitalMetrics when they were captured
|
|
@@ -129,11 +113,10 @@ export class Aggregate extends AggregateBase {
|
|
|
129
113
|
|
|
130
114
|
appendGlobalCustomAttributes (timing) {
|
|
131
115
|
var timingAttributes = timing.attrs || {}
|
|
132
|
-
var customAttributes = getInfo(this.agentIdentifier).jsAttributes || {}
|
|
133
116
|
|
|
134
117
|
var reservedAttributes = ['size', 'eid', 'cls', 'type', 'fid', 'elTag', 'elUrl', 'net-type',
|
|
135
118
|
'net-etype', 'net-rtt', 'net-dlink']
|
|
136
|
-
Object.entries(
|
|
119
|
+
Object.entries(this.agentRef.info.jsAttributes || {}).forEach(([key, val]) => {
|
|
137
120
|
if (reservedAttributes.indexOf(key) < 0) {
|
|
138
121
|
timingAttributes[key] = val
|
|
139
122
|
}
|
|
@@ -12,8 +12,8 @@ import { now } from '../../../common/timing/now'
|
|
|
12
12
|
|
|
13
13
|
export class Instrument extends InstrumentBase {
|
|
14
14
|
static featureName = FEATURE_NAME
|
|
15
|
-
constructor (
|
|
16
|
-
super(
|
|
15
|
+
constructor (agentRef, auto = true) {
|
|
16
|
+
super(agentRef, FEATURE_NAME, auto)
|
|
17
17
|
if (!isBrowserScope) return // CWV is irrelevant outside web context
|
|
18
18
|
|
|
19
19
|
// While we try to replicate web-vital's visibilitywatcher logic in an effort to defer that library to post-pageload, this isn't perfect and doesn't consider prerendering.
|
|
@@ -22,7 +22,7 @@ export class Instrument extends InstrumentBase {
|
|
|
22
22
|
// Window fires its pagehide event (typically on navigation--this occurrence is a *subset* of vis change); don't defer this unless it's guarantee it cannot happen before load(?)
|
|
23
23
|
windowAddEventListener('pagehide', () => handle('winPagehide', [now()], undefined, FEATURE_NAME, this.ee))
|
|
24
24
|
|
|
25
|
-
this.importAggregator()
|
|
25
|
+
this.importAggregator(agentRef)
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -9,9 +9,6 @@
|
|
|
9
9
|
import { registerHandler } from '../../../common/event-emitter/register-handler'
|
|
10
10
|
import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
|
|
11
11
|
import { ABORT_REASONS, FEATURE_NAME, QUERY_PARAM_PADDING, RRWEB_EVENT_TYPES, SR_EVENT_EMITTER_TYPES, TRIGGERS } from '../constants'
|
|
12
|
-
import { getInfo } from '../../../common/config/info'
|
|
13
|
-
import { getConfigurationValue } from '../../../common/config/init'
|
|
14
|
-
import { getRuntime } from '../../../common/config/runtime'
|
|
15
12
|
import { AggregateBase } from '../../utils/aggregate-base'
|
|
16
13
|
import { sharedChannel } from '../../../common/constants/shared-channel'
|
|
17
14
|
import { obj as encodeObj } from '../../../common/url/encode'
|
|
@@ -24,7 +21,6 @@ import { RRWEB_VERSION } from '../../../common/constants/env'
|
|
|
24
21
|
import { MODE, SESSION_EVENTS, SESSION_EVENT_TYPES } from '../../../common/session/constants'
|
|
25
22
|
import { stringify } from '../../../common/util/stringify'
|
|
26
23
|
import { stylesheetEvaluator } from '../shared/stylesheet-evaluator'
|
|
27
|
-
import { deregisterDrain } from '../../../common/drain/drain'
|
|
28
24
|
import { now } from '../../../common/timing/now'
|
|
29
25
|
import { buildNRMetaNode } from '../shared/utils'
|
|
30
26
|
import { MAX_PAYLOAD_SIZE } from '../../../common/constants/agent-constants'
|
|
@@ -35,10 +31,10 @@ export class Aggregate extends AggregateBase {
|
|
|
35
31
|
mode = MODE.OFF
|
|
36
32
|
|
|
37
33
|
// pass the recorder into the aggregator
|
|
38
|
-
constructor (
|
|
39
|
-
super(
|
|
34
|
+
constructor (agentRef, args) {
|
|
35
|
+
super(agentRef, FEATURE_NAME)
|
|
40
36
|
/** The interval to harvest at. This gets overridden if the size of the payload exceeds certain thresholds */
|
|
41
|
-
this.harvestTimeSeconds =
|
|
37
|
+
this.harvestTimeSeconds = agentRef.init.session_replay.harvestTimeSeconds || 60
|
|
42
38
|
/** Set once the recorder has fully initialized after flag checks and sampling */
|
|
43
39
|
this.initialized = false
|
|
44
40
|
/** Set once the feature has been "aborted" to prevent other side-effects from continuing */
|
|
@@ -77,8 +73,7 @@ export class Aggregate extends AggregateBase {
|
|
|
77
73
|
this.ee.on(SESSION_EVENTS.RESUME, () => {
|
|
78
74
|
if (!this.recorder) return
|
|
79
75
|
// if the mode changed on a different tab, it needs to update this instance to match
|
|
80
|
-
|
|
81
|
-
this.mode = session.state.sessionReplayMode
|
|
76
|
+
this.mode = agentRef.runtime.session.state.sessionReplayMode
|
|
82
77
|
if (!this.initialized || this.mode === MODE.OFF) return
|
|
83
78
|
this.recorder?.startRecording()
|
|
84
79
|
})
|
|
@@ -105,12 +100,12 @@ export class Aggregate extends AggregateBase {
|
|
|
105
100
|
this.handleError(e)
|
|
106
101
|
}, this.featureName, this.ee)
|
|
107
102
|
|
|
108
|
-
const { error_sampling_rate, sampling_rate, autoStart, block_selector, mask_text_selector, mask_all_inputs, inline_images, collect_fonts } =
|
|
103
|
+
const { error_sampling_rate, sampling_rate, autoStart, block_selector, mask_text_selector, mask_all_inputs, inline_images, collect_fonts } = agentRef.init.session_replay
|
|
109
104
|
|
|
110
105
|
this.waitForFlags(['srs', 'sr']).then(([srMode, entitled]) => {
|
|
111
106
|
this.entitled = !!entitled
|
|
112
107
|
if (!this.entitled) {
|
|
113
|
-
deregisterDrain(
|
|
108
|
+
this.deregisterDrain()
|
|
114
109
|
if (this.recorder?.recording) {
|
|
115
110
|
this.abort(ABORT_REASONS.ENTITLEMENTS)
|
|
116
111
|
handle(SUPPORTABILITY_METRIC_CHANNEL, ['SessionReplay/EnabledNotEntitled/Detected'], undefined, FEATURE_NAMES.metrics, this.ee)
|
|
@@ -178,7 +173,7 @@ export class Aggregate extends AggregateBase {
|
|
|
178
173
|
// we are not actively recording SR... DO NOT import or run the recording library
|
|
179
174
|
// session replay samples can only be decided on the first load of a session
|
|
180
175
|
// session replays can continue if already in progress
|
|
181
|
-
const { session, timeKeeper } =
|
|
176
|
+
const { session, timeKeeper } = this.agentRef.runtime
|
|
182
177
|
this.timeKeeper = timeKeeper
|
|
183
178
|
if (this.recorder?.parent.trigger === TRIGGERS.API && this.recorder?.recording) {
|
|
184
179
|
this.mode = MODE.FULL
|
|
@@ -285,8 +280,7 @@ export class Aggregate extends AggregateBase {
|
|
|
285
280
|
return
|
|
286
281
|
}
|
|
287
282
|
// TODO -- Gracefully handle the buffer for retries.
|
|
288
|
-
|
|
289
|
-
if (!session.state.sessionReplaySentFirstChunk) this.syncWithSessionManager({ sessionReplaySentFirstChunk: true })
|
|
283
|
+
if (!this.agentRef.runtime.session.state.sessionReplaySentFirstChunk) this.syncWithSessionManager({ sessionReplaySentFirstChunk: true })
|
|
290
284
|
this.recorder.clearBuffer()
|
|
291
285
|
if (recorderEvents.type === 'preloaded') this.scheduler.runHarvest(opts)
|
|
292
286
|
return [payload]
|
|
@@ -301,9 +295,8 @@ export class Aggregate extends AggregateBase {
|
|
|
301
295
|
getHarvestContents (recorderEvents) {
|
|
302
296
|
recorderEvents ??= this.recorder.getEvents()
|
|
303
297
|
let events = recorderEvents.events
|
|
304
|
-
const agentRuntime =
|
|
305
|
-
const
|
|
306
|
-
const endUserId = info.jsAttributes?.['enduser.id']
|
|
298
|
+
const agentRuntime = this.agentRef.runtime
|
|
299
|
+
const endUserId = this.agentRef.info.jsAttributes?.['enduser.id']
|
|
307
300
|
|
|
308
301
|
// do not let the first node be a full snapshot node, since this NEEDS to be preceded by a meta node
|
|
309
302
|
// we will manually inject it if this happens
|
|
@@ -335,9 +328,9 @@ export class Aggregate extends AggregateBase {
|
|
|
335
328
|
|
|
336
329
|
return {
|
|
337
330
|
qs: {
|
|
338
|
-
browser_monitoring_key: info.licenseKey,
|
|
331
|
+
browser_monitoring_key: this.agentRef.info.licenseKey,
|
|
339
332
|
type: 'SessionReplay',
|
|
340
|
-
app_id: info.applicationID,
|
|
333
|
+
app_id: this.agentRef.info.applicationID,
|
|
341
334
|
protocol_version: '0',
|
|
342
335
|
timestamp: firstTimestamp,
|
|
343
336
|
attributes: encodeObj({
|
|
@@ -407,7 +400,6 @@ export class Aggregate extends AggregateBase {
|
|
|
407
400
|
}
|
|
408
401
|
|
|
409
402
|
syncWithSessionManager (state = {}) {
|
|
410
|
-
|
|
411
|
-
session.write(state)
|
|
403
|
+
this.agentRef.runtime.session.write(state)
|
|
412
404
|
}
|
|
413
405
|
}
|
|
@@ -16,15 +16,17 @@ export class Instrument extends InstrumentBase {
|
|
|
16
16
|
static featureName = FEATURE_NAME
|
|
17
17
|
|
|
18
18
|
#mode
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
#agentRef
|
|
20
|
+
constructor (agentRef, auto = true) {
|
|
21
|
+
super(agentRef, FEATURE_NAME, auto)
|
|
21
22
|
let session
|
|
22
23
|
this.replayRunning = false
|
|
24
|
+
this.#agentRef = agentRef
|
|
23
25
|
try {
|
|
24
26
|
session = JSON.parse(localStorage.getItem(`${PREFIX}_${DEFAULT_KEY}`))
|
|
25
27
|
} catch (err) { }
|
|
26
28
|
|
|
27
|
-
if (hasReplayPrerequisite(agentIdentifier)) {
|
|
29
|
+
if (hasReplayPrerequisite(agentRef.agentIdentifier)) {
|
|
28
30
|
this.ee.on(SR_EVENT_EMITTER_TYPES.RECORD, () => this.#apiStartOrRestartReplay())
|
|
29
31
|
}
|
|
30
32
|
|
|
@@ -32,7 +34,7 @@ export class Instrument extends InstrumentBase {
|
|
|
32
34
|
this.#mode = session?.sessionReplayMode
|
|
33
35
|
this.#preloadStartRecording()
|
|
34
36
|
} else {
|
|
35
|
-
this.importAggregator()
|
|
37
|
+
this.importAggregator(agentRef)
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
/** If the recorder is running, we can pass error events on to the agg to help it switch to full mode later */
|
|
@@ -79,7 +81,7 @@ export class Instrument extends InstrumentBase {
|
|
|
79
81
|
this.recorder.startRecording()
|
|
80
82
|
this.abortHandler = this.recorder.stopRecording
|
|
81
83
|
} catch (e) {}
|
|
82
|
-
this.importAggregator({ recorder: this.recorder, errorNoticed: this.errorNoticed })
|
|
84
|
+
this.importAggregator(this.#agentRef, { recorder: this.recorder, errorNoticed: this.errorNoticed })
|
|
83
85
|
}
|
|
84
86
|
|
|
85
87
|
/**
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { registerHandler } from '../../../common/event-emitter/register-handler'
|
|
2
2
|
import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
|
|
3
|
-
import { getInfo } from '../../../common/config/info'
|
|
4
|
-
import { getConfigurationValue } from '../../../common/config/init'
|
|
5
|
-
import { getRuntime } from '../../../common/config/runtime'
|
|
6
3
|
import { FEATURE_NAME } from '../constants'
|
|
7
4
|
import { AggregateBase } from '../../utils/aggregate-base'
|
|
8
5
|
import { TraceStorage } from './trace/storage'
|
|
9
6
|
import { obj as encodeObj } from '../../../common/url/encode'
|
|
10
|
-
import { deregisterDrain } from '../../../common/drain/drain'
|
|
11
7
|
import { globalScope } from '../../../common/constants/runtime'
|
|
12
8
|
import { MODE, SESSION_EVENTS } from '../../../common/session/constants'
|
|
13
9
|
import { applyFnToProps } from '../../../common/util/traverse'
|
|
@@ -19,14 +15,12 @@ const QUERY_PARAM_PADDING = 5000
|
|
|
19
15
|
export class Aggregate extends AggregateBase {
|
|
20
16
|
static featureName = FEATURE_NAME
|
|
21
17
|
|
|
22
|
-
constructor (
|
|
23
|
-
super(
|
|
24
|
-
this.agentRuntime = getRuntime(agentIdentifier)
|
|
25
|
-
this.agentInfo = getInfo(agentIdentifier)
|
|
18
|
+
constructor (agentRef) {
|
|
19
|
+
super(agentRef, FEATURE_NAME)
|
|
26
20
|
|
|
27
21
|
/** A buffer to hold on to harvested traces in the case that a retry must be made later */
|
|
28
22
|
this.sentTrace = null
|
|
29
|
-
this.harvestTimeSeconds =
|
|
23
|
+
this.harvestTimeSeconds = agentRef.init.session_trace.harvestTimeSeconds || 30
|
|
30
24
|
/** Tied to the entitlement flag response from BCS. Will short circuit operations of the agg if false */
|
|
31
25
|
this.entitled = undefined
|
|
32
26
|
/** A flag used to decide if the 30 node threshold should be ignored on the first harvest to ensure sending on the first payload */
|
|
@@ -43,13 +37,13 @@ export class Aggregate extends AggregateBase {
|
|
|
43
37
|
/** Sets up event listeners, and initializes this module to run in the correct "mode". Can be triggered from a few places, but makes an effort to only set up listeners once */
|
|
44
38
|
initialize (stMode, stEntitled, ignoreSession) {
|
|
45
39
|
this.entitled ??= stEntitled
|
|
46
|
-
if (this.blocked || !this.entitled) return deregisterDrain(
|
|
40
|
+
if (this.blocked || !this.entitled) return this.deregisterDrain()
|
|
47
41
|
|
|
48
42
|
if (!this.initialized) {
|
|
49
43
|
this.initialized = true
|
|
50
44
|
/** Store session identifiers at initialization time to be cross-checked later at harvest time for session changes that are subject to race conditions */
|
|
51
|
-
this.ptid = this.
|
|
52
|
-
this.sessionId = this.
|
|
45
|
+
this.ptid = this.agentRef.runtime.ptid
|
|
46
|
+
this.sessionId = this.agentRef.runtime.session?.state.value
|
|
53
47
|
// The SessionEntity class can emit a message indicating the session was cleared and reset (expiry, inactivity). This feature must abort and never resume if that occurs.
|
|
54
48
|
this.ee.on(SESSION_EVENTS.RESET, () => {
|
|
55
49
|
if (this.blocked) return
|
|
@@ -74,14 +68,14 @@ export class Aggregate extends AggregateBase {
|
|
|
74
68
|
|
|
75
69
|
/** ST/SR sampling flow in BCS - https://drive.google.com/file/d/19hwt2oft-8Hh4RrjpLqEXfpP_9wYBLcq/view?usp=sharing */
|
|
76
70
|
/** ST will run in the mode provided by BCS if the session IS NEW. If not... it will use the state of the session entity to determine what mode to run in */
|
|
77
|
-
if (!this.
|
|
71
|
+
if (!this.agentRef.runtime.session.isNew && !ignoreSession) this.mode = this.agentRef.runtime.session.state.sessionTraceMode
|
|
78
72
|
else this.mode = stMode
|
|
79
73
|
|
|
80
74
|
/** If the mode is off, we do not want to hold up draining for other features, so we deregister the feature for now.
|
|
81
75
|
* If it drains later (due to a mode change), data and handlers will instantly drain instead of waiting for the registry. */
|
|
82
|
-
if (this.mode === MODE.OFF) return deregisterDrain(
|
|
76
|
+
if (this.mode === MODE.OFF) return this.deregisterDrain()
|
|
83
77
|
|
|
84
|
-
this.timeKeeper ??= this.
|
|
78
|
+
this.timeKeeper ??= this.agentRef.runtime.timeKeeper
|
|
85
79
|
|
|
86
80
|
this.scheduler = new HarvestScheduler('browser/blobs', {
|
|
87
81
|
onFinished: this.onHarvestFinished.bind(this),
|
|
@@ -107,7 +101,7 @@ export class Aggregate extends AggregateBase {
|
|
|
107
101
|
if (this.mode === MODE.ERROR) this.switchToFull()
|
|
108
102
|
}, this.featureName, this.ee)
|
|
109
103
|
}
|
|
110
|
-
this.
|
|
104
|
+
this.agentRef.runtime.session.write({ sessionTraceMode: this.mode })
|
|
111
105
|
this.drain()
|
|
112
106
|
}
|
|
113
107
|
|
|
@@ -123,7 +117,7 @@ export class Aggregate extends AggregateBase {
|
|
|
123
117
|
this.traceStorage.prevStoredEvents.clear() // release references to past events for GC
|
|
124
118
|
if (!this.timeKeeper?.ready) return // this should likely never happen, but just to be safe, we should never harvest if we cant correct time
|
|
125
119
|
if (this.blocked || this.mode !== MODE.FULL || this.traceStorage.nodeCount === 0) return
|
|
126
|
-
if (this.sessionId !== this.
|
|
120
|
+
if (this.sessionId !== this.agentRef.runtime.session?.state.value || this.ptid !== this.agentRef.runtime.ptid) return this.abort(3) // if something unexpected happened and we somehow still got to the point of harvesting after a session identifier changed, we should force-exit instead of harvesting
|
|
127
121
|
/** Get the ST nodes from the traceStorage buffer. This also returns helpful metadata about the payload. */
|
|
128
122
|
const { stns, earliestTimeStamp, latestTimeStamp } = this.traceStorage.takeSTNs()
|
|
129
123
|
if (!stns) return // there are no trace nodes
|
|
@@ -131,11 +125,11 @@ export class Aggregate extends AggregateBase {
|
|
|
131
125
|
this.sentTrace = stns
|
|
132
126
|
}
|
|
133
127
|
|
|
134
|
-
const firstSessionHarvest = !this.
|
|
135
|
-
if (firstSessionHarvest) this.
|
|
128
|
+
const firstSessionHarvest = !this.agentRef.runtime.session.state.traceHarvestStarted
|
|
129
|
+
if (firstSessionHarvest) this.agentRef.runtime.session.write({ traceHarvestStarted: true })
|
|
136
130
|
|
|
137
|
-
const hasReplay = this.
|
|
138
|
-
const endUserId = this.
|
|
131
|
+
const hasReplay = this.agentRef.runtime.session?.state.sessionReplayMode === 1
|
|
132
|
+
const endUserId = this.agentRef.info?.jsAttributes?.['enduser.id']
|
|
139
133
|
|
|
140
134
|
this.everHarvested = true
|
|
141
135
|
|
|
@@ -148,17 +142,17 @@ export class Aggregate extends AggregateBase {
|
|
|
148
142
|
*
|
|
149
143
|
* For data that does not fit the schema of the above, it should be url-encoded and placed into `attributes`
|
|
150
144
|
*/
|
|
151
|
-
const agentMetadata = this.
|
|
145
|
+
const agentMetadata = this.agentRef.runtime.appMetadata?.agents?.[0] || {}
|
|
152
146
|
return {
|
|
153
147
|
qs: {
|
|
154
|
-
browser_monitoring_key: this.
|
|
148
|
+
browser_monitoring_key: this.agentRef.info.licenseKey,
|
|
155
149
|
type: 'BrowserSessionChunk',
|
|
156
|
-
app_id: this.
|
|
150
|
+
app_id: this.agentRef.info.applicationID,
|
|
157
151
|
protocol_version: '0',
|
|
158
152
|
timestamp: Math.floor(this.timeKeeper.correctRelativeTimestamp(earliestTimeStamp)),
|
|
159
153
|
attributes: encodeObj({
|
|
160
154
|
...(agentMetadata.entityGuid && { entityGuid: agentMetadata.entityGuid }),
|
|
161
|
-
harvestId: `${this.
|
|
155
|
+
harvestId: `${this.agentRef.runtime.session?.state.value}_${this.agentRef.runtime.ptid}_${this.agentRef.runtime.harvestCount}`,
|
|
162
156
|
// this section of attributes must be controllable and stay below the query param padding limit -- see QUERY_PARAM_PADDING
|
|
163
157
|
// if not, data could be lost to truncation at time of sending, potentially breaking parsing / API behavior in NR1
|
|
164
158
|
// trace payload metadata
|
|
@@ -167,7 +161,7 @@ export class Aggregate extends AggregateBase {
|
|
|
167
161
|
'trace.nodes': stns.length,
|
|
168
162
|
'trace.originTimestamp': this.timeKeeper.correctedOriginTime,
|
|
169
163
|
// other payload metadata
|
|
170
|
-
agentVersion: this.
|
|
164
|
+
agentVersion: this.agentRef.runtime.version,
|
|
171
165
|
...(firstSessionHarvest && { firstSessionHarvest }),
|
|
172
166
|
...(hasReplay && { hasReplay }),
|
|
173
167
|
ptid: `${this.ptid}`,
|
|
@@ -197,7 +191,7 @@ export class Aggregate extends AggregateBase {
|
|
|
197
191
|
if (this.mode === MODE.FULL || !this.entitled || this.blocked) return
|
|
198
192
|
const prevMode = this.mode
|
|
199
193
|
this.mode = MODE.FULL
|
|
200
|
-
this.
|
|
194
|
+
this.agentRef.runtime.session.write({ sessionTraceMode: this.mode })
|
|
201
195
|
if (prevMode === MODE.OFF || !this.initialized) return this.initialize(this.mode, this.entitled)
|
|
202
196
|
if (this.initialized) {
|
|
203
197
|
this.traceStorage.trimSTNs(ERROR_MODE_SECONDS_WINDOW) // up until now, Trace would've been just buffering nodes up to max, which needs to be trimmed to last X seconds
|
|
@@ -209,7 +203,7 @@ export class Aggregate extends AggregateBase {
|
|
|
209
203
|
abort (reason) {
|
|
210
204
|
this.blocked = true
|
|
211
205
|
this.mode = MODE.OFF
|
|
212
|
-
this.
|
|
206
|
+
this.agentRef.runtime.session.write({ sessionTraceMode: this.mode })
|
|
213
207
|
this.scheduler?.stopTimer()
|
|
214
208
|
}
|
|
215
209
|
}
|
|
@@ -8,7 +8,6 @@ import { wrapEvents } from '../../../common/wrap/wrap-events'
|
|
|
8
8
|
import { InstrumentBase } from '../../utils/instrument-base'
|
|
9
9
|
import * as CONSTANTS from '../constants'
|
|
10
10
|
import { FEATURE_NAMES } from '../../../loaders/features/features'
|
|
11
|
-
import { deregisterDrain } from '../../../common/drain/drain'
|
|
12
11
|
import { canEnableSessionTracking } from '../../utils/feature-gates'
|
|
13
12
|
import { now } from '../../../common/timing/now'
|
|
14
13
|
|
|
@@ -18,11 +17,11 @@ const {
|
|
|
18
17
|
|
|
19
18
|
export class Instrument extends InstrumentBase {
|
|
20
19
|
static featureName = FEATURE_NAME
|
|
21
|
-
constructor (
|
|
22
|
-
super(
|
|
20
|
+
constructor (agentRef, auto = true) {
|
|
21
|
+
super(agentRef, FEATURE_NAME, auto)
|
|
23
22
|
const canTrackSession = canEnableSessionTracking(this.agentIdentifier)
|
|
24
23
|
if (!canTrackSession) {
|
|
25
|
-
deregisterDrain(
|
|
24
|
+
this.deregisterDrain()
|
|
26
25
|
return
|
|
27
26
|
}
|
|
28
27
|
|
|
@@ -59,7 +58,7 @@ export class Instrument extends InstrumentBase {
|
|
|
59
58
|
// Per NEWRELIC-8525, we don't have a fallback for capturing resources for older versions that don't support PO at this time.
|
|
60
59
|
}
|
|
61
60
|
|
|
62
|
-
this.importAggregator({ resourceObserver: observer })
|
|
61
|
+
this.importAggregator(agentRef, { resourceObserver: observer })
|
|
63
62
|
}
|
|
64
63
|
}
|
|
65
64
|
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { getConfigurationValue } from '../../../common/config/init'
|
|
2
|
-
import { deregisterDrain } from '../../../common/drain/drain'
|
|
3
1
|
import { handle } from '../../../common/event-emitter/handle'
|
|
4
2
|
import { registerHandler } from '../../../common/event-emitter/register-handler'
|
|
5
3
|
import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
|
|
@@ -16,14 +14,14 @@ import { Interaction } from './interaction'
|
|
|
16
14
|
|
|
17
15
|
export class Aggregate extends AggregateBase {
|
|
18
16
|
static featureName = FEATURE_NAME
|
|
19
|
-
constructor (
|
|
20
|
-
super(
|
|
17
|
+
constructor (agentRef, { domObserver }) {
|
|
18
|
+
super(agentRef, FEATURE_NAME)
|
|
21
19
|
|
|
22
|
-
const harvestTimeSeconds =
|
|
20
|
+
const harvestTimeSeconds = agentRef.init.soft_navigations.harvestTimeSeconds || 10
|
|
23
21
|
this.interactionsToHarvest = new EventBuffer()
|
|
24
22
|
this.domObserver = domObserver
|
|
25
23
|
|
|
26
|
-
this.initialPageLoadInteraction = new InitialPageLoadInteraction(agentIdentifier)
|
|
24
|
+
this.initialPageLoadInteraction = new InitialPageLoadInteraction(agentRef.agentIdentifier)
|
|
27
25
|
timeToFirstByte.subscribe(({ attrs }) => {
|
|
28
26
|
const loadEventTime = attrs.navigationEntry.loadEventEnd
|
|
29
27
|
this.initialPageLoadInteraction.forceSave = true
|
|
@@ -45,12 +43,12 @@ export class Aggregate extends AggregateBase {
|
|
|
45
43
|
onFinished: this.onHarvestFinished.bind(this),
|
|
46
44
|
retryDelay: harvestTimeSeconds,
|
|
47
45
|
onUnload: () => this.interactionInProgress?.done() // return any held ajax or jserr events so they can be sent with EoL harvest
|
|
48
|
-
},
|
|
46
|
+
}, this)
|
|
49
47
|
scheduler.harvest.on('events', this.onHarvestStarted.bind(this))
|
|
50
48
|
scheduler.startTimer(harvestTimeSeconds, 0)
|
|
51
49
|
} else {
|
|
52
50
|
this.blocked = true // if rum response determines that customer lacks entitlements for spa endpoint, this feature shouldn't harvest
|
|
53
|
-
deregisterDrain(
|
|
51
|
+
this.deregisterDrain()
|
|
54
52
|
}
|
|
55
53
|
})
|
|
56
54
|
|
|
@@ -18,8 +18,8 @@ const UI_WAIT_INTERVAL = 1 / 10 * 1000 // assume 10 fps
|
|
|
18
18
|
|
|
19
19
|
export class Instrument extends InstrumentBase {
|
|
20
20
|
static featureName = FEATURE_NAME
|
|
21
|
-
constructor (
|
|
22
|
-
super(
|
|
21
|
+
constructor (agentRef, auto = true) {
|
|
22
|
+
super(agentRef, FEATURE_NAME, auto)
|
|
23
23
|
if (!isBrowserScope || !gosNREUMOriginals().o.MO) return // soft navigations is not supported outside web env or browsers without the mutation observer API
|
|
24
24
|
|
|
25
25
|
const historyEE = wrapHistory(this.ee)
|
|
@@ -58,7 +58,7 @@ export class Instrument extends InstrumentBase {
|
|
|
58
58
|
for (let eventType of INTERACTION_TRIGGERS) document.addEventListener(eventType, () => { /* no-op, this ensures the UI events are monitored by our callback above */ })
|
|
59
59
|
|
|
60
60
|
this.abortHandler = abort
|
|
61
|
-
this.importAggregator({ domObserver })
|
|
61
|
+
this.importAggregator(agentRef, { domObserver })
|
|
62
62
|
|
|
63
63
|
function abort () {
|
|
64
64
|
this.removeOnAbort?.abort()
|
|
@@ -9,8 +9,6 @@ import { shouldCollectEvent } from '../../../common/deny-list/deny-list'
|
|
|
9
9
|
import { navTimingValues as navTiming } from '../../../common/timing/nav-timing'
|
|
10
10
|
import { generateUuid } from '../../../common/ids/unique-id'
|
|
11
11
|
import { Interaction } from './interaction'
|
|
12
|
-
import { getConfigurationValue } from '../../../common/config/init'
|
|
13
|
-
import { getRuntime } from '../../../common/config/runtime'
|
|
14
12
|
import { eventListenerOpts } from '../../../common/event-listener/event-listener-opts'
|
|
15
13
|
import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
|
|
16
14
|
import { Serializer } from './serializer'
|
|
@@ -24,7 +22,6 @@ import { bundleId } from '../../../common/ids/bundle-id'
|
|
|
24
22
|
import { loadedAsDeferredBrowserScript } from '../../../common/constants/runtime'
|
|
25
23
|
import { handle } from '../../../common/event-emitter/handle'
|
|
26
24
|
import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants'
|
|
27
|
-
import { deregisterDrain } from '../../../common/drain/drain'
|
|
28
25
|
import { warn } from '../../../common/util/console'
|
|
29
26
|
import { EventBuffer } from '../../utils/event-buffer'
|
|
30
27
|
|
|
@@ -34,13 +31,12 @@ const {
|
|
|
34
31
|
} = CONSTANTS
|
|
35
32
|
export class Aggregate extends AggregateBase {
|
|
36
33
|
static featureName = FEATURE_NAME
|
|
37
|
-
constructor (
|
|
38
|
-
super(
|
|
34
|
+
constructor (agentRef) {
|
|
35
|
+
super(agentRef, FEATURE_NAME)
|
|
39
36
|
|
|
40
|
-
const agentRuntime = getRuntime(agentIdentifier)
|
|
41
37
|
this.state = {
|
|
42
|
-
initialPageURL:
|
|
43
|
-
lastSeenUrl:
|
|
38
|
+
initialPageURL: agentRef.runtime.origin,
|
|
39
|
+
lastSeenUrl: agentRef.runtime.origin,
|
|
44
40
|
lastSeenRouteName: null,
|
|
45
41
|
timerMap: {},
|
|
46
42
|
timerBudget: MAX_TIMER_BUDGET,
|
|
@@ -51,10 +47,10 @@ export class Aggregate extends AggregateBase {
|
|
|
51
47
|
pageLoaded: false,
|
|
52
48
|
childTime: 0,
|
|
53
49
|
depth: 0,
|
|
54
|
-
harvestTimeSeconds:
|
|
50
|
+
harvestTimeSeconds: agentRef.init.spa.harvestTimeSeconds || 10,
|
|
55
51
|
interactionsToHarvest: new EventBuffer(),
|
|
56
52
|
// The below feature flag is used to disable the SPA ajax fix for specific customers, see https://new-relic.atlassian.net/browse/NR-172169
|
|
57
|
-
disableSpaFix: (
|
|
53
|
+
disableSpaFix: (agentRef.init.feature_flags || []).indexOf('disable-spa-fix') > -1
|
|
58
54
|
}
|
|
59
55
|
|
|
60
56
|
let scheduler
|
|
@@ -62,7 +58,7 @@ export class Aggregate extends AggregateBase {
|
|
|
62
58
|
|
|
63
59
|
const { state, serializer } = this
|
|
64
60
|
|
|
65
|
-
const baseEE = ee.get(agentIdentifier) // <-- parent baseEE
|
|
61
|
+
const baseEE = ee.get(agentRef.agentIdentifier) // <-- parent baseEE
|
|
66
62
|
const mutationEE = baseEE.get('mutation')
|
|
67
63
|
const promiseEE = baseEE.get('promise')
|
|
68
64
|
const historyEE = baseEE.get('history')
|
|
@@ -110,18 +106,18 @@ export class Aggregate extends AggregateBase {
|
|
|
110
106
|
scheduler = new HarvestScheduler('events', {
|
|
111
107
|
onFinished: onHarvestFinished,
|
|
112
108
|
retryDelay: state.harvestTimeSeconds
|
|
113
|
-
},
|
|
109
|
+
}, this)
|
|
114
110
|
scheduler.harvest.on('events', onHarvestStarted)
|
|
115
111
|
this.drain()
|
|
116
112
|
} else {
|
|
117
113
|
this.blocked = true
|
|
118
|
-
deregisterDrain(
|
|
114
|
+
this.deregisterDrain()
|
|
119
115
|
}
|
|
120
116
|
})
|
|
121
117
|
|
|
122
|
-
if (
|
|
118
|
+
if (agentRef.init.spa.enabled !== true) return
|
|
123
119
|
|
|
124
|
-
state.initialPageLoad = new Interaction('initialPageLoad', 0, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier)
|
|
120
|
+
state.initialPageLoad = new Interaction('initialPageLoad', 0, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentRef.agentIdentifier)
|
|
125
121
|
state.initialPageLoad.save = true
|
|
126
122
|
state.prevInteraction = state.initialPageLoad
|
|
127
123
|
state.currentNode = state.initialPageLoad.root // hint
|
|
@@ -212,7 +208,7 @@ export class Aggregate extends AggregateBase {
|
|
|
212
208
|
// Otherwise, if no interaction is currently active, create a new node ID,
|
|
213
209
|
// and let the aggregator know that we entered a new event handler callback
|
|
214
210
|
// so that it has a chance to possibly start an interaction.
|
|
215
|
-
var ixn = new Interaction(evName, this[FN_START], state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier)
|
|
211
|
+
var ixn = new Interaction(evName, this[FN_START], state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentRef.agentIdentifier)
|
|
216
212
|
|
|
217
213
|
// Store the interaction as prevInteraction in case it is prematurely discarded
|
|
218
214
|
state.prevInteraction = ixn
|
|
@@ -310,7 +306,7 @@ export class Aggregate extends AggregateBase {
|
|
|
310
306
|
this.sent = true
|
|
311
307
|
node.dt = this.dt
|
|
312
308
|
if (node.dt?.timestamp) {
|
|
313
|
-
node.dt.timestamp =
|
|
309
|
+
node.dt.timestamp = agentRef.runtime.timeKeeper.correctAbsoluteTimestamp(node.dt.timestamp)
|
|
314
310
|
}
|
|
315
311
|
node.jsEnd = node.start = this.startTime
|
|
316
312
|
node[INTERACTION][REMAINING]++
|
|
@@ -410,7 +406,7 @@ export class Aggregate extends AggregateBase {
|
|
|
410
406
|
if (dtPayload && this[SPA_NODE]) {
|
|
411
407
|
this[SPA_NODE].dt = dtPayload
|
|
412
408
|
if (this[SPA_NODE].dt?.timestamp) {
|
|
413
|
-
this[SPA_NODE].dt.timestamp =
|
|
409
|
+
this[SPA_NODE].dt.timestamp = agentRef.runtime.timeKeeper.correctAbsoluteTimestamp(this[SPA_NODE].dt.timestamp)
|
|
414
410
|
}
|
|
415
411
|
}
|
|
416
412
|
}
|
|
@@ -548,7 +544,7 @@ export class Aggregate extends AggregateBase {
|
|
|
548
544
|
var interaction
|
|
549
545
|
if (state?.currentNode?.[INTERACTION]) interaction = this.ixn = state.currentNode[INTERACTION]
|
|
550
546
|
else if (state?.prevNode?.end === null && state?.prevNode?.[INTERACTION]?.root?.[INTERACTION]?.eventName !== 'initialPageLoad') interaction = this.ixn = state.prevNode[INTERACTION]
|
|
551
|
-
else interaction = this.ixn = new Interaction('api', t, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier)
|
|
547
|
+
else interaction = this.ixn = new Interaction('api', t, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentRef.agentIdentifier)
|
|
552
548
|
if (!state.currentNode) {
|
|
553
549
|
interaction.checkFinish()
|
|
554
550
|
if (state.depth) setCurrentNode(interaction.root)
|
|
@@ -702,9 +698,9 @@ export class Aggregate extends AggregateBase {
|
|
|
702
698
|
register('function-err', function (args, obj, error) {
|
|
703
699
|
if (!state.currentNode) return
|
|
704
700
|
error.__newrelic ??= {}
|
|
705
|
-
error.__newrelic[agentIdentifier] = { interactionId: state.currentNode.interaction.id }
|
|
701
|
+
error.__newrelic[agentRef.agentIdentifier] = { interactionId: state.currentNode.interaction.id }
|
|
706
702
|
if (state.currentNode.type && state.currentNode.type !== 'interaction') {
|
|
707
|
-
error.__newrelic[agentIdentifier].interactionNodeId = state.currentNode.id
|
|
703
|
+
error.__newrelic[agentRef.agentIdentifier].interactionNodeId = state.currentNode.id
|
|
708
704
|
}
|
|
709
705
|
}, this.featureName, baseEE)
|
|
710
706
|
|
|
@@ -751,10 +747,5 @@ export class Aggregate extends AggregateBase {
|
|
|
751
747
|
scheduler?.scheduleHarvest(0)
|
|
752
748
|
if (!scheduler) warn(19)
|
|
753
749
|
}
|
|
754
|
-
|
|
755
|
-
function isEnabled () {
|
|
756
|
-
var enabled = getConfigurationValue(agentIdentifier, 'spa.enabled')
|
|
757
|
-
return enabled !== false
|
|
758
|
-
}
|
|
759
750
|
}
|
|
760
751
|
}
|
|
@@ -25,8 +25,8 @@ const {
|
|
|
25
25
|
*/
|
|
26
26
|
export class Instrument extends InstrumentBase {
|
|
27
27
|
static featureName = FEATURE_NAME
|
|
28
|
-
constructor (
|
|
29
|
-
super(
|
|
28
|
+
constructor (agentRef, auto = true) {
|
|
29
|
+
super(agentRef, FEATURE_NAME, auto)
|
|
30
30
|
if (!isBrowserScope) return // SPA not supported outside web env
|
|
31
31
|
|
|
32
32
|
try {
|
|
@@ -54,7 +54,7 @@ export class Instrument extends InstrumentBase {
|
|
|
54
54
|
promiseEE.on(CB_END, endTimestamp)
|
|
55
55
|
jsonpEE.on(CB_END, endTimestamp)
|
|
56
56
|
|
|
57
|
-
this.ee.on('fn-err', (...args) => { if (!args[2]?.__newrelic?.[agentIdentifier]) handle('function-err', [...args], undefined, this.featureName, this.ee) })
|
|
57
|
+
this.ee.on('fn-err', (...args) => { if (!args[2]?.__newrelic?.[agentRef.agentIdentifier]) handle('function-err', [...args], undefined, this.featureName, this.ee) })
|
|
58
58
|
|
|
59
59
|
this.ee.buffer([FN_START, FN_END, 'xhr-resolved'], this.featureName)
|
|
60
60
|
eventsEE.buffer([FN_START], this.featureName)
|
|
@@ -110,7 +110,7 @@ export class Instrument extends InstrumentBase {
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
this.abortHandler = this.#abort
|
|
113
|
-
this.importAggregator()
|
|
113
|
+
this.importAggregator(agentRef)
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
/** Restoration and resource release tasks to be done if SPA loader is being aborted. Unwind changes to globals and subscription to DOM events. */
|