@newrelic/browser-agent 1.252.1 → 1.254.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 +25 -0
- package/README.md +2 -2
- package/dist/cjs/cdn/experimental.js +6 -2
- package/dist/cjs/cdn/polyfills.js +2 -1
- package/dist/cjs/cdn/spa.js +5 -3
- package/dist/cjs/common/aggregate/aggregator.js +1 -8
- package/dist/cjs/common/config/state/init.js +7 -0
- package/dist/cjs/common/config/state/runtime.js +4 -1
- package/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/drain/drain.js +41 -27
- package/dist/cjs/common/event-emitter/contextual-ee.js +17 -12
- package/dist/cjs/common/harvest/harvest.js +5 -1
- package/dist/cjs/common/session/constants.js +2 -1
- package/dist/cjs/common/timing/nav-timing.js +8 -3
- package/dist/cjs/common/timing/now.js +1 -1
- package/dist/cjs/common/timing/time-keeper.js +94 -0
- package/dist/cjs/common/util/feature-flags.js +14 -31
- package/dist/cjs/common/wrap/index.js +0 -7
- package/dist/cjs/features/ajax/aggregate/index.js +41 -29
- package/dist/cjs/features/jserrors/aggregate/index.js +96 -84
- package/dist/cjs/features/metrics/aggregate/index.js +25 -24
- package/dist/cjs/features/page_action/aggregate/index.js +6 -4
- package/dist/cjs/features/page_view_event/aggregate/index.js +23 -3
- package/dist/cjs/features/page_view_event/aggregate/initialized-features.js +1 -0
- package/dist/cjs/features/page_view_timing/aggregate/index.js +15 -16
- package/dist/cjs/features/session_replay/aggregate/index.js +102 -92
- package/dist/cjs/features/session_replay/constants.js +5 -1
- package/dist/cjs/features/session_replay/instrument/index.js +24 -8
- package/dist/cjs/features/session_replay/shared/utils.js +26 -0
- package/dist/cjs/features/session_trace/aggregate/index.js +11 -8
- package/dist/cjs/features/soft_navigations/aggregate/ajax-node.js +50 -0
- package/dist/cjs/features/soft_navigations/aggregate/bel-node.js +29 -0
- package/dist/cjs/features/soft_navigations/aggregate/index.js +268 -0
- package/dist/cjs/features/soft_navigations/aggregate/initial-page-load-interaction.js +62 -0
- package/dist/cjs/features/soft_navigations/aggregate/interaction.js +146 -0
- package/dist/cjs/features/soft_navigations/constants.js +31 -0
- package/dist/cjs/features/soft_navigations/index.js +12 -0
- package/dist/cjs/features/soft_navigations/instrument/index.js +79 -0
- package/dist/cjs/features/spa/aggregate/index.js +23 -18
- package/dist/cjs/features/utils/agent-session.js +2 -1
- package/dist/cjs/features/utils/aggregate-base.js +18 -5
- package/dist/cjs/features/utils/feature-base.js +2 -0
- package/dist/cjs/features/utils/instrument-base.js +7 -9
- package/dist/cjs/features/utils/lazy-feature-loader.js +2 -0
- package/dist/cjs/loaders/agent-base.js +13 -3
- package/dist/cjs/loaders/agent.js +19 -22
- package/dist/cjs/loaders/api/api-methods.js +2 -1
- package/dist/cjs/loaders/api/api.js +15 -12
- package/dist/cjs/loaders/configure/configure.js +5 -2
- package/dist/cjs/loaders/configure/nonce.cdn.js +13 -0
- package/dist/cjs/loaders/configure/nonce.js +2 -13
- package/dist/cjs/loaders/configure/public-path.cdn.js +16 -0
- package/dist/cjs/loaders/configure/public-path.js +2 -8
- package/dist/cjs/loaders/features/enabled-features.js +1 -1
- package/dist/cjs/loaders/features/features.js +3 -1
- package/dist/esm/cdn/experimental.js +5 -2
- package/dist/esm/cdn/polyfills.js +2 -1
- package/dist/esm/cdn/spa.js +3 -1
- package/dist/esm/common/aggregate/aggregator.js +1 -8
- package/dist/esm/common/config/state/init.js +7 -0
- package/dist/esm/common/config/state/runtime.js +4 -1
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/drain/drain.js +40 -27
- package/dist/esm/common/event-emitter/contextual-ee.js +17 -12
- package/dist/esm/common/harvest/harvest.js +5 -1
- package/dist/esm/common/session/constants.js +1 -0
- package/dist/esm/common/timing/nav-timing.js +8 -3
- package/dist/esm/common/timing/now.js +1 -1
- package/dist/esm/common/timing/time-keeper.js +88 -0
- package/dist/esm/common/util/feature-flags.js +14 -31
- package/dist/esm/common/wrap/index.js +1 -2
- package/dist/esm/features/ajax/aggregate/index.js +43 -31
- package/dist/esm/features/jserrors/aggregate/index.js +96 -84
- package/dist/esm/features/metrics/aggregate/index.js +25 -24
- package/dist/esm/features/page_action/aggregate/index.js +6 -4
- package/dist/esm/features/page_view_event/aggregate/index.js +23 -3
- package/dist/esm/features/page_view_event/aggregate/initialized-features.js +1 -0
- package/dist/esm/features/page_view_timing/aggregate/index.js +15 -16
- package/dist/esm/features/session_replay/aggregate/index.js +103 -93
- package/dist/esm/features/session_replay/constants.js +4 -0
- package/dist/esm/features/session_replay/instrument/index.js +25 -9
- package/dist/esm/features/session_replay/shared/utils.js +17 -0
- package/dist/esm/features/session_trace/aggregate/index.js +11 -8
- package/dist/esm/features/soft_navigations/aggregate/ajax-node.js +43 -0
- package/dist/esm/features/soft_navigations/aggregate/bel-node.js +22 -0
- package/dist/esm/features/soft_navigations/aggregate/index.js +261 -0
- package/dist/esm/features/soft_navigations/aggregate/initial-page-load-interaction.js +55 -0
- package/dist/esm/features/soft_navigations/aggregate/interaction.js +140 -0
- package/dist/esm/features/soft_navigations/constants.js +25 -0
- package/dist/esm/features/soft_navigations/index.js +1 -0
- package/dist/esm/features/soft_navigations/instrument/index.js +73 -0
- package/dist/esm/features/spa/aggregate/index.js +23 -18
- package/dist/esm/features/utils/agent-session.js +2 -1
- package/dist/esm/features/utils/aggregate-base.js +18 -5
- package/dist/esm/features/utils/feature-base.js +2 -0
- package/dist/esm/features/utils/instrument-base.js +8 -10
- package/dist/esm/features/utils/lazy-feature-loader.js +2 -0
- package/dist/esm/loaders/agent-base.js +13 -3
- package/dist/esm/loaders/agent.js +19 -22
- package/dist/esm/loaders/api/api-methods.js +2 -1
- package/dist/esm/loaders/api/api.js +15 -12
- package/dist/esm/loaders/configure/configure.js +5 -2
- package/dist/esm/loaders/configure/nonce.cdn.js +11 -0
- package/dist/esm/loaders/configure/nonce.js +1 -11
- package/dist/esm/loaders/configure/public-path.cdn.js +9 -0
- package/dist/esm/loaders/configure/public-path.js +2 -8
- package/dist/esm/loaders/features/enabled-features.js +1 -1
- package/dist/esm/loaders/features/features.js +3 -1
- package/dist/types/common/aggregate/aggregator.d.ts.map +1 -1
- package/dist/types/common/config/state/init.d.ts.map +1 -1
- package/dist/types/common/config/state/runtime.d.ts.map +1 -1
- package/dist/types/common/drain/drain.d.ts +6 -0
- package/dist/types/common/drain/drain.d.ts.map +1 -1
- package/dist/types/common/event-emitter/contextual-ee.d.ts +2 -1
- package/dist/types/common/event-emitter/contextual-ee.d.ts.map +1 -1
- package/dist/types/common/harvest/harvest.d.ts.map +1 -1
- package/dist/types/common/session/constants.d.ts +1 -0
- package/dist/types/common/session/constants.d.ts.map +1 -1
- package/dist/types/common/timing/nav-timing.d.ts.map +1 -1
- package/dist/types/common/timing/time-keeper.d.ts +31 -0
- package/dist/types/common/timing/time-keeper.d.ts.map +1 -0
- package/dist/types/common/util/feature-flags.d.ts +11 -2
- package/dist/types/common/util/feature-flags.d.ts.map +1 -1
- package/dist/types/common/wrap/index.d.ts +1 -2
- package/dist/types/common/wrap/index.d.ts.map +1 -1
- package/dist/types/features/ajax/aggregate/index.d.ts +5 -5
- package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts +4 -3
- package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_action/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/initialized-features.d.ts.map +1 -1
- package/dist/types/features/page_view_timing/aggregate/index.d.ts +0 -2
- package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/constants.d.ts +4 -0
- package/dist/types/features/session_replay/constants.d.ts.map +1 -1
- package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/utils.d.ts +4 -0
- package/dist/types/features/session_replay/shared/utils.d.ts.map +1 -0
- package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts +19 -0
- package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts.map +1 -0
- package/dist/types/features/soft_navigations/aggregate/bel-node.d.ts +16 -0
- package/dist/types/features/soft_navigations/aggregate/bel-node.d.ts.map +1 -0
- package/dist/types/features/soft_navigations/aggregate/index.d.ts +34 -0
- package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -0
- package/dist/types/features/soft_navigations/aggregate/initial-page-load-interaction.d.ts +12 -0
- package/dist/types/features/soft_navigations/aggregate/initial-page-load-interaction.d.ts.map +1 -0
- package/dist/types/features/soft_navigations/aggregate/interaction.d.ts +50 -0
- package/dist/types/features/soft_navigations/aggregate/interaction.d.ts.map +1 -0
- package/dist/types/features/soft_navigations/constants.d.ts +20 -0
- package/dist/types/features/soft_navigations/constants.d.ts.map +1 -0
- package/dist/types/features/soft_navigations/index.d.ts +2 -0
- package/dist/types/features/soft_navigations/index.d.ts.map +1 -0
- package/dist/types/features/soft_navigations/instrument/index.d.ts +7 -0
- package/dist/types/features/soft_navigations/instrument/index.d.ts.map +1 -0
- package/dist/types/features/spa/aggregate/index.d.ts +2 -0
- package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/utils/agent-session.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 +1 -0
- package/dist/types/features/utils/feature-base.d.ts.map +1 -1
- package/dist/types/features/utils/instrument-base.d.ts +1 -7
- package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
- package/dist/types/features/utils/lazy-feature-loader.d.ts.map +1 -1
- package/dist/types/loaders/agent-base.d.ts +5 -1
- package/dist/types/loaders/agent-base.d.ts.map +1 -1
- package/dist/types/loaders/agent.d.ts +2 -2
- package/dist/types/loaders/agent.d.ts.map +1 -1
- package/dist/types/loaders/api/api-methods.d.ts.map +1 -1
- package/dist/types/loaders/api/api.d.ts +3 -5
- package/dist/types/loaders/api/api.d.ts.map +1 -1
- package/dist/types/loaders/configure/configure.d.ts.map +1 -1
- package/dist/types/loaders/configure/public-path.d.ts +1 -1
- package/dist/types/loaders/configure/public-path.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/dist/types/loaders/micro-agent.d.ts +0 -1
- package/dist/types/loaders/micro-agent.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cdn/experimental.js +4 -2
- package/src/cdn/polyfills.js +1 -0
- package/src/cdn/spa.js +3 -1
- package/src/common/aggregate/aggregator.js +2 -11
- package/src/common/config/state/init.js +3 -1
- package/src/common/config/state/runtime.js +4 -1
- package/src/common/drain/drain.js +41 -28
- package/src/common/event-emitter/contextual-ee.js +21 -13
- package/src/common/harvest/harvest.js +4 -1
- package/src/common/session/constants.js +1 -0
- package/src/common/timing/nav-timing.js +7 -3
- package/src/common/timing/now.js +1 -1
- package/src/common/timing/time-keeper.js +96 -0
- package/src/common/util/feature-flags.js +13 -31
- package/src/common/wrap/index.js +1 -2
- package/src/features/ajax/aggregate/index.js +43 -33
- package/src/features/jserrors/aggregate/index.js +82 -87
- package/src/features/metrics/aggregate/index.js +18 -17
- package/src/features/page_action/aggregate/index.js +6 -5
- package/src/features/page_view_event/aggregate/index.js +19 -3
- package/src/features/page_view_event/aggregate/initialized-features.js +1 -0
- package/src/features/page_view_timing/aggregate/index.js +15 -15
- package/src/features/session_replay/aggregate/index.js +95 -92
- package/src/features/session_replay/constants.js +5 -0
- package/src/features/session_replay/instrument/index.js +24 -9
- package/src/features/session_replay/shared/utils.js +19 -0
- package/src/features/session_trace/aggregate/index.js +2 -2
- package/src/features/soft_navigations/aggregate/ajax-node.js +57 -0
- package/src/features/soft_navigations/aggregate/bel-node.js +26 -0
- package/src/features/soft_navigations/aggregate/index.js +256 -0
- package/src/features/soft_navigations/aggregate/initial-page-load-interaction.js +53 -0
- package/src/features/soft_navigations/aggregate/interaction.js +159 -0
- package/src/features/soft_navigations/constants.js +29 -0
- package/src/features/soft_navigations/index.js +1 -0
- package/src/features/soft_navigations/instrument/index.js +67 -0
- package/src/features/spa/aggregate/index.js +20 -17
- package/src/features/utils/agent-session.js +2 -1
- package/src/features/utils/aggregate-base.js +16 -8
- package/src/features/utils/feature-base.js +3 -0
- package/src/features/utils/instrument-base.js +8 -10
- package/src/features/utils/lazy-feature-loader.js +2 -0
- package/src/loaders/agent-base.js +13 -3
- package/src/loaders/agent.js +20 -19
- package/src/loaders/api/api-methods.js +4 -1
- package/src/loaders/api/api.js +15 -13
- package/src/loaders/configure/configure.js +4 -1
- package/src/loaders/configure/nonce.cdn.js +12 -0
- package/src/loaders/configure/nonce.js +1 -12
- package/src/loaders/configure/public-path.cdn.js +9 -0
- package/src/loaders/configure/public-path.js +2 -8
- package/src/loaders/features/enabled-features.js +1 -1
- package/src/loaders/features/features.js +3 -1
- package/dist/cjs/common/wrap/wrap-raf.js +0 -55
- package/dist/cjs/loaders/configure/nonce.npm.js +0 -2
- package/dist/cjs/loaders/configure/public-path.npm.js +0 -10
- package/dist/esm/common/wrap/wrap-raf.js +0 -48
- package/dist/esm/loaders/configure/nonce.npm.js +0 -1
- package/dist/esm/loaders/configure/public-path.npm.js +0 -3
- package/dist/types/common/wrap/wrap-raf.d.ts +0 -16
- package/dist/types/common/wrap/wrap-raf.d.ts.map +0 -1
- package/dist/types/loaders/configure/nonce.npm.d.ts +0 -1
- package/dist/types/loaders/configure/nonce.npm.d.ts.map +0 -1
- package/dist/types/loaders/configure/public-path.npm.d.ts +0 -2
- package/dist/types/loaders/configure/public-path.npm.d.ts.map +0 -1
- package/src/common/wrap/wrap-raf.js +0 -52
- package/src/loaders/configure/nonce.npm.js +0 -1
- package/src/loaders/configure/public-path.npm.js +0 -3
package/src/cdn/experimental.js
CHANGED
|
@@ -17,7 +17,8 @@ import { Instrument as InstrumentErrors } from '../features/jserrors/instrument'
|
|
|
17
17
|
import { Instrument as InstrumentXhr } from '../features/ajax/instrument'
|
|
18
18
|
import { Instrument as InstrumentSessionTrace } from '../features/session_trace/instrument'
|
|
19
19
|
import { Instrument as InstrumentSessionReplay } from '../features/session_replay/instrument'
|
|
20
|
-
import { Instrument as InstrumentSpa } from '../features/spa/instrument'
|
|
20
|
+
// import { Instrument as InstrumentSpa } from '../features/spa/instrument'
|
|
21
|
+
import { Instrument as InstrumentSoftNav } from '../features/soft_navigations/instrument'
|
|
21
22
|
import { Instrument as InstrumentPageAction } from '../features/page_action/instrument'
|
|
22
23
|
|
|
23
24
|
new Agent({
|
|
@@ -30,7 +31,8 @@ new Agent({
|
|
|
30
31
|
InstrumentMetrics,
|
|
31
32
|
InstrumentPageAction,
|
|
32
33
|
InstrumentErrors,
|
|
33
|
-
InstrumentSpa
|
|
34
|
+
// InstrumentSpa,
|
|
35
|
+
InstrumentSoftNav
|
|
34
36
|
],
|
|
35
37
|
loaderType: 'experimental'
|
|
36
38
|
})
|
package/src/cdn/polyfills.js
CHANGED
package/src/cdn/spa.js
CHANGED
|
@@ -11,6 +11,7 @@ import { Instrument as InstrumentErrors } from '../features/jserrors/instrument'
|
|
|
11
11
|
import { Instrument as InstrumentXhr } from '../features/ajax/instrument'
|
|
12
12
|
import { Instrument as InstrumentSessionTrace } from '../features/session_trace/instrument'
|
|
13
13
|
import { Instrument as InstrumentSessionReplay } from '../features/session_replay/instrument'
|
|
14
|
+
import { Instrument as InstrumentSoftNav } from '../features/soft_navigations/instrument'
|
|
14
15
|
import { Instrument as InstrumentSpa } from '../features/spa/instrument'
|
|
15
16
|
import { Instrument as InstrumentPageAction } from '../features/page_action/instrument'
|
|
16
17
|
|
|
@@ -24,7 +25,8 @@ new Agent({
|
|
|
24
25
|
InstrumentMetrics,
|
|
25
26
|
InstrumentPageAction,
|
|
26
27
|
InstrumentErrors,
|
|
27
|
-
|
|
28
|
+
InstrumentSoftNav,
|
|
29
|
+
InstrumentSpa // either the softnav or the old spa will be used (not both), but we still need to pack both to avoid dynamic import for instrument files
|
|
28
30
|
],
|
|
29
31
|
loaderType: 'spa'
|
|
30
32
|
})
|
|
@@ -82,7 +82,8 @@ export class Aggregator extends SharedContext {
|
|
|
82
82
|
var hasData = false
|
|
83
83
|
for (var i = 0; i < types.length; i++) {
|
|
84
84
|
type = types[i]
|
|
85
|
-
results[type] =
|
|
85
|
+
results[type] = Object.values(this.aggregatedData[type] || {})
|
|
86
|
+
|
|
86
87
|
if (results[type].length) hasData = true
|
|
87
88
|
delete this.aggregatedData[type]
|
|
88
89
|
}
|
|
@@ -159,13 +160,3 @@ function createMetricObject (value) {
|
|
|
159
160
|
c: 1
|
|
160
161
|
}
|
|
161
162
|
}
|
|
162
|
-
|
|
163
|
-
function toArray (obj) {
|
|
164
|
-
if (typeof obj !== 'object') return []
|
|
165
|
-
|
|
166
|
-
return mapOwn(obj, getValue)
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function getValue (key, value) {
|
|
170
|
-
return value
|
|
171
|
-
}
|
|
@@ -64,6 +64,7 @@ const model = () => {
|
|
|
64
64
|
autoStart: true,
|
|
65
65
|
enabled: false,
|
|
66
66
|
harvestTimeSeconds: 60,
|
|
67
|
+
preload: false, // if true, enables the agent to load rrweb immediately instead of waiting to do so after the window.load event
|
|
67
68
|
sampling_rate: 10, // float from 0 - 100
|
|
68
69
|
error_sampling_rate: 100, // float from 0 - 100
|
|
69
70
|
collect_fonts: false, // serialize fonts for collection without public asset url, this is currently broken in RRWeb -- https://github.com/rrweb-io/rrweb/issues/1304. When fixed, revisit with test cases
|
|
@@ -100,7 +101,8 @@ const model = () => {
|
|
|
100
101
|
else warn('An invalid session_replay.mask_input_option was provided and will not be used', val)
|
|
101
102
|
}
|
|
102
103
|
},
|
|
103
|
-
spa: { enabled: true, harvestTimeSeconds: 10, autoStart: true }
|
|
104
|
+
spa: { enabled: true, harvestTimeSeconds: 10, autoStart: true },
|
|
105
|
+
soft_navigations: { enabled: true, harvestTimeSeconds: 10, autoStart: true }
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
|
|
@@ -18,10 +18,13 @@ const model = {
|
|
|
18
18
|
origin: '' + globalScope.location,
|
|
19
19
|
ptid: undefined,
|
|
20
20
|
releaseIds: {},
|
|
21
|
+
/** Agent-specific metadata found in the RUM call response. ex. entityGuid */
|
|
22
|
+
appMetadata: {},
|
|
21
23
|
session: undefined,
|
|
22
24
|
xhrWrappable: typeof globalScope.XMLHttpRequest?.prototype?.addEventListener === 'function',
|
|
23
25
|
version: VERSION,
|
|
24
|
-
denyList: undefined
|
|
26
|
+
denyList: undefined,
|
|
27
|
+
harvestCount: 0
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
const _cache = {}
|
|
@@ -26,13 +26,24 @@ export function registerDrain (agentIdentifier, group) {
|
|
|
26
26
|
if (!registry[agentIdentifier].get(group)) registry[agentIdentifier].set(group, item)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Removes an item from the registry and immediately re-checks if the registry is ready to "drain all"
|
|
31
|
+
* @param {*} agentIdentifier - A 16 character string uniquely identifying the agent.
|
|
32
|
+
* @param {*} group - The named "bucket" to be removed from the registry
|
|
33
|
+
*/
|
|
34
|
+
export function deregisterDrain (agentIdentifier, group) {
|
|
35
|
+
curateRegistry(agentIdentifier)
|
|
36
|
+
if (registry[agentIdentifier].get(group)) registry[agentIdentifier].delete(group)
|
|
37
|
+
if (registry[agentIdentifier].size) checkCanDrainAll(agentIdentifier)
|
|
38
|
+
}
|
|
39
|
+
|
|
29
40
|
/**
|
|
30
41
|
* Registers the specified agent with the centralized event buffer registry if it is not already registered.
|
|
31
42
|
* Agents without an identifier (as in the case of some tests) will be excluded from the registry.
|
|
32
43
|
* @param {string} agentIdentifier - A 16 character string uniquely identifying an agent.
|
|
33
44
|
*/
|
|
34
45
|
function curateRegistry (agentIdentifier) {
|
|
35
|
-
if (!agentIdentifier)
|
|
46
|
+
if (!agentIdentifier) throw new Error('agentIdentifier required')
|
|
36
47
|
if (!registry[agentIdentifier]) registry[agentIdentifier] = new Map()
|
|
37
48
|
}
|
|
38
49
|
|
|
@@ -48,54 +59,56 @@ export function drain (agentIdentifier = '', featureName = 'feature', force = fa
|
|
|
48
59
|
// If the feature for the specified agent is not in the registry, that means the instrument file was bypassed.
|
|
49
60
|
// This could happen in tests, or loaders that directly import the aggregator. In these cases it is safe to
|
|
50
61
|
// drain the feature group immediately rather than waiting to drain all at once.
|
|
51
|
-
if (!agentIdentifier || !registry[agentIdentifier].get(featureName) || force) return drainGroup(featureName)
|
|
62
|
+
if (!agentIdentifier || !registry[agentIdentifier].get(featureName) || force) return drainGroup(agentIdentifier, featureName)
|
|
52
63
|
|
|
53
64
|
// When `drain` is called, this feature is ready to drain (staged).
|
|
54
65
|
registry[agentIdentifier].get(featureName).staged = true
|
|
55
66
|
|
|
56
|
-
|
|
67
|
+
checkCanDrainAll(agentIdentifier)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Checks all items in the registry to see if they have been "staged". If ALL items are staged, it will drain all registry items (drainGroup). It not, nothing will happen */
|
|
71
|
+
function checkCanDrainAll (agentIdentifier) {
|
|
72
|
+
// Only when the event-groups for all features are ready to drain (staged) do we execute the drain. This has the effect
|
|
57
73
|
// that the last feature to call drain triggers drain for all features.
|
|
58
74
|
const items = [...registry[agentIdentifier]]
|
|
59
75
|
if (items.every(([key, values]) => values.staged)) {
|
|
60
76
|
items.sort((a, b) => a[1].priority - b[1].priority)
|
|
61
77
|
items.forEach(([group]) => {
|
|
62
78
|
registry[agentIdentifier].delete(group)
|
|
63
|
-
drainGroup(group)
|
|
79
|
+
drainGroup(agentIdentifier, group)
|
|
64
80
|
})
|
|
65
81
|
}
|
|
82
|
+
}
|
|
66
83
|
|
|
67
|
-
|
|
84
|
+
/**
|
|
68
85
|
* Drains all the buffered (backlog) events for a particular feature's event-group by emitting each event to each of
|
|
69
86
|
* the subscribed handlers for the group.
|
|
70
87
|
* @param {*} group - The name of a particular feature's event "bucket".
|
|
71
88
|
*/
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
89
|
+
function drainGroup (agentIdentifier, group) {
|
|
90
|
+
const baseEE = agentIdentifier ? ee.get(agentIdentifier) : ee
|
|
91
|
+
const handlers = defaultRegister.handlers // other storage in registerHandler
|
|
92
|
+
if (!baseEE.backlog || !handlers) return
|
|
76
93
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
mapOwn(groupHandlers, function (eventType, handlerRegistrationList) {
|
|
86
|
-
mapOwn(handlerRegistrationList, function (i, registration) {
|
|
87
|
-
// registration is an array of: [targetEE, eventHandler]
|
|
88
|
-
registration[0].on(eventType, registration[1])
|
|
89
|
-
})
|
|
90
|
-
})
|
|
94
|
+
var bufferedEventsInGroup = baseEE.backlog[group]
|
|
95
|
+
var groupHandlers = handlers[group] // each group in the registerHandler storage
|
|
96
|
+
if (groupHandlers) {
|
|
97
|
+
// We don't cache the length of the buffer while looping because events might still be added while processing.
|
|
98
|
+
for (var i = 0; bufferedEventsInGroup && i < bufferedEventsInGroup.length; ++i) { // eslint-disable-line no-unmodified-loop-condition
|
|
99
|
+
emitEvent(bufferedEventsInGroup[i], groupHandlers)
|
|
91
100
|
}
|
|
92
101
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
102
|
+
mapOwn(groupHandlers, function (eventType, handlerRegistrationList) {
|
|
103
|
+
mapOwn(handlerRegistrationList, function (i, registration) {
|
|
104
|
+
// registration is an array of: [targetEE, eventHandler]
|
|
105
|
+
registration[0].on(eventType, registration[1])
|
|
106
|
+
})
|
|
107
|
+
})
|
|
98
108
|
}
|
|
109
|
+
if (!baseEE.isolatedBacklog) delete handlers[group]
|
|
110
|
+
baseEE.backlog[group] = null
|
|
111
|
+
baseEE.emit('drain-' + group, [])
|
|
99
112
|
}
|
|
100
113
|
|
|
101
114
|
/**
|
|
@@ -49,13 +49,32 @@ function ee (old, debugId) {
|
|
|
49
49
|
context,
|
|
50
50
|
buffer: bufferEventsByGroup,
|
|
51
51
|
abort,
|
|
52
|
-
aborted: false,
|
|
53
52
|
isBuffering,
|
|
54
53
|
debugId,
|
|
55
|
-
backlog: isolatedBacklog ? {} : old && typeof old.backlog === 'object' ? old.backlog : {}
|
|
54
|
+
backlog: isolatedBacklog ? {} : old && typeof old.backlog === 'object' ? old.backlog : {},
|
|
55
|
+
isolatedBacklog
|
|
56
|
+
}
|
|
56
57
|
|
|
58
|
+
function abort () {
|
|
59
|
+
emitter._aborted = true
|
|
60
|
+
Object.keys(emitter.backlog).forEach(key => {
|
|
61
|
+
delete emitter.backlog[key]
|
|
62
|
+
})
|
|
57
63
|
}
|
|
58
64
|
|
|
65
|
+
Object.defineProperty(emitter, 'aborted', {
|
|
66
|
+
get: () => {
|
|
67
|
+
let aborted = emitter._aborted || false
|
|
68
|
+
|
|
69
|
+
if (aborted) return aborted
|
|
70
|
+
else if (old) {
|
|
71
|
+
aborted = old.aborted
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return aborted
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
|
|
59
78
|
return emitter
|
|
60
79
|
|
|
61
80
|
function context (contextOrStore) {
|
|
@@ -141,14 +160,3 @@ function ee (old, debugId) {
|
|
|
141
160
|
return emitter.backlog
|
|
142
161
|
}
|
|
143
162
|
}
|
|
144
|
-
|
|
145
|
-
function abort () {
|
|
146
|
-
globalInstance.aborted = true
|
|
147
|
-
// The global backlog can be referenced directly by other emitters,
|
|
148
|
-
// so we need to delete its contents as opposed to replacing it.
|
|
149
|
-
// Otherwise, these references to the old backlog would still exist
|
|
150
|
-
// and the keys will not be garbage collected.
|
|
151
|
-
Object.keys(globalInstance.backlog).forEach(key => {
|
|
152
|
-
delete globalInstance.backlog[key]
|
|
153
|
-
})
|
|
154
|
-
}
|
|
@@ -145,7 +145,7 @@ export class Harvest extends SharedContext {
|
|
|
145
145
|
result.addEventListener('loadend', function () {
|
|
146
146
|
// `this` refers to the XHR object in this scope, do not change this to a fat arrow
|
|
147
147
|
// status 0 refers to a local error, such as CORS or network failure, or a blocked request by the browser (e.g. adblocker)
|
|
148
|
-
const cbResult = { sent: this.status !== 0, status: this.status }
|
|
148
|
+
const cbResult = { sent: this.status !== 0, status: this.status, xhr: this, fullUrl }
|
|
149
149
|
if (this.status === 429) {
|
|
150
150
|
cbResult.retry = true
|
|
151
151
|
cbResult.delay = harvestScope.tooManyRequestsDelay
|
|
@@ -160,6 +160,9 @@ export class Harvest extends SharedContext {
|
|
|
160
160
|
}, eventListenerOpts(false))
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
const runtime = getRuntime(this.sharedContext.agentIdentifier)
|
|
164
|
+
runtime.harvestCount++
|
|
165
|
+
|
|
163
166
|
return result
|
|
164
167
|
}
|
|
165
168
|
|
|
@@ -25,7 +25,7 @@ var RESPONSE = 'response'
|
|
|
25
25
|
var LOAD_EVENT = 'loadEvent'
|
|
26
26
|
var DOM_CONTENT_LOAD_EVENT = 'domContentLoadedEvent'
|
|
27
27
|
|
|
28
|
-
export
|
|
28
|
+
export const navTimingValues = []
|
|
29
29
|
|
|
30
30
|
function getPntType (type) {
|
|
31
31
|
if (typeof type === 'number') return type
|
|
@@ -72,6 +72,10 @@ export function addPN (pn, v) {
|
|
|
72
72
|
return v
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* By side effect, this modifies 'obj' with a mapping of the 'prop' provided to a 'value', and invalid values are not added.
|
|
77
|
+
* On the other hand, the local navTimingValues array gets the value appended if valid and 'undefined' appended if invalid, regardless.
|
|
78
|
+
*/
|
|
75
79
|
function handleValue (value, obj, prop, isOldApi) {
|
|
76
80
|
/*
|
|
77
81
|
For L2 Timing API, the value will already be a relative-to-previous-document DOMHighResTimeStamp.
|
|
@@ -85,6 +89,6 @@ function handleValue (value, obj, prop, isOldApi) {
|
|
|
85
89
|
}
|
|
86
90
|
value = Math.round(value)
|
|
87
91
|
obj[prop] = value
|
|
88
|
-
|
|
89
|
-
navTimingValues.push(
|
|
92
|
+
navTimingValues.push(value)
|
|
93
|
+
} else navTimingValues.push(undefined)
|
|
90
94
|
}
|
package/src/common/timing/now.js
CHANGED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { gosNREUM } from '../window/nreum'
|
|
2
|
+
import { globalScope } from '../constants/runtime'
|
|
3
|
+
import { getRuntime } from '../config/config'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Class used to adjust the timestamp of harvested data to New Relic server time. This
|
|
7
|
+
* is done by tracking the performance timings of the RUM call and applying a calculation
|
|
8
|
+
* to the harvested data event offset time.
|
|
9
|
+
*/
|
|
10
|
+
export class TimeKeeper {
|
|
11
|
+
#agent
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Represents the browser origin time corrected to NR server time.
|
|
15
|
+
* @type {number}
|
|
16
|
+
*/
|
|
17
|
+
#correctedOriginTime
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Represents the difference in milliseconds between the calculated NR server time and
|
|
21
|
+
* the local time.
|
|
22
|
+
* @type {number}
|
|
23
|
+
*/
|
|
24
|
+
#localTimeDiff
|
|
25
|
+
|
|
26
|
+
constructor (agent) {
|
|
27
|
+
this.#agent = agent
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static getTimeKeeperByAgentIdentifier (agentIdentifier) {
|
|
31
|
+
const nr = gosNREUM()
|
|
32
|
+
return Object.keys(nr?.initializedAgents || {}).indexOf(agentIdentifier) > -1
|
|
33
|
+
? nr.initializedAgents[agentIdentifier].timeKeeper
|
|
34
|
+
: undefined
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get correctedPageOriginTime () {
|
|
38
|
+
return this.#correctedOriginTime
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Process a rum request to calculate NR server time.
|
|
43
|
+
* @param rumRequest {XMLHttpRequest} The xhr for the rum request
|
|
44
|
+
* @param rumRequestUrl {string} The full url of the rum request
|
|
45
|
+
*/
|
|
46
|
+
processRumRequest (rumRequest, rumRequestUrl) {
|
|
47
|
+
const responseDateHeader = rumRequest.getResponseHeader('Date')
|
|
48
|
+
if (!responseDateHeader) {
|
|
49
|
+
throw new Error('Missing date header on rum response.')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const resourceEntries = globalScope.performance.getEntriesByName(rumRequestUrl, 'resource')
|
|
53
|
+
if (!Array.isArray((resourceEntries)) || resourceEntries.length === 0) {
|
|
54
|
+
throw new Error('Missing rum request performance entry.')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let medianRumOffset = 0
|
|
58
|
+
let serverOffset = 0
|
|
59
|
+
if (typeof resourceEntries[0].responseStart === 'number' && resourceEntries[0].responseStart !== 0) {
|
|
60
|
+
// Cors is enabled and we can make a more accurate calculation of NR server time
|
|
61
|
+
medianRumOffset = (resourceEntries[0].responseStart - resourceEntries[0].requestStart) / 2
|
|
62
|
+
serverOffset = Math.floor(resourceEntries[0].requestStart + medianRumOffset)
|
|
63
|
+
} else {
|
|
64
|
+
// Cors is disabled or erred, we need to use a less accurate calculation
|
|
65
|
+
medianRumOffset = (resourceEntries[0].responseEnd - resourceEntries[0].fetchStart) / 2
|
|
66
|
+
serverOffset = Math.floor(resourceEntries[0].fetchStart + medianRumOffset)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Corrected page origin time
|
|
70
|
+
this.#correctedOriginTime = Math.floor(Date.parse(responseDateHeader) - serverOffset)
|
|
71
|
+
this.#localTimeDiff = getRuntime(this.#agent.agentIdentifier).offset - this.#correctedOriginTime
|
|
72
|
+
|
|
73
|
+
if (Number.isNaN(this.#correctedOriginTime)) {
|
|
74
|
+
throw new Error('Date header invalid format.')
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Converts a page origin relative time to an absolute timestamp
|
|
80
|
+
* corrected to NR server time.
|
|
81
|
+
* @param relativeTime {number} The relative time of the event in milliseconds
|
|
82
|
+
* @returns {number} The correct timestamp as a unix/epoch timestamp value
|
|
83
|
+
*/
|
|
84
|
+
convertRelativeTimestamp (relativeTime) {
|
|
85
|
+
return this.#correctedOriginTime + relativeTime
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Corrects an event timestamp to NR server time.
|
|
90
|
+
* @param timestamp {number} The unix/epoch timestamp of the event with milliseconds
|
|
91
|
+
* @return {number} Corrected unix/epoch timestamp
|
|
92
|
+
*/
|
|
93
|
+
correctAbsoluteTimestamp (timestamp) {
|
|
94
|
+
return Math.floor(timestamp - this.#localTimeDiff)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -3,49 +3,31 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
import { ee } from '../event-emitter/contextual-ee'
|
|
6
|
-
import { handle } from '../event-emitter/handle'
|
|
7
|
-
import { FEATURE_NAMES } from '../../loaders/features/features'
|
|
8
6
|
import { dispatchGlobalEvent } from '../dispatch/global-event'
|
|
9
7
|
|
|
10
|
-
const bucketMap = {
|
|
11
|
-
stn: [FEATURE_NAMES.sessionTrace],
|
|
12
|
-
err: [FEATURE_NAMES.jserrors, FEATURE_NAMES.metrics],
|
|
13
|
-
ins: [FEATURE_NAMES.pageAction],
|
|
14
|
-
spa: [FEATURE_NAMES.spa],
|
|
15
|
-
sr: [FEATURE_NAMES.sessionReplay, FEATURE_NAMES.sessionTrace]
|
|
16
|
-
}
|
|
17
|
-
|
|
18
8
|
const sentIds = new Set()
|
|
19
9
|
|
|
20
|
-
/**
|
|
10
|
+
/** A map of feature flags and their values as provided by the rum call -- scoped by agent ID */
|
|
11
|
+
export const activatedFeatures = {}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Sets the activatedFeatures object, dispatches the global loaded event,
|
|
15
|
+
* and emits the rumresp flag to features
|
|
16
|
+
* @param {{[key:string]:number}} flags key-val pair of flag names and numeric
|
|
17
|
+
* @param {string} agentIdentifier agent instance identifier
|
|
18
|
+
* @returns {void}
|
|
19
|
+
*/
|
|
21
20
|
export function activateFeatures (flags, agentIdentifier) {
|
|
22
21
|
const sharedEE = ee.get(agentIdentifier)
|
|
22
|
+
activatedFeatures[agentIdentifier] ??= {}
|
|
23
23
|
if (!(flags && typeof flags === 'object')) return
|
|
24
24
|
if (sentIds.has(agentIdentifier)) return
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
bucketMap[flag].forEach(feat => {
|
|
29
|
-
if (!num) handle('block-' + flag, [], undefined, feat, sharedEE)
|
|
30
|
-
else handle('feat-' + flag, [], undefined, feat, sharedEE)
|
|
31
|
-
handle('rumresp-' + flag, [Boolean(num)], undefined, feat, sharedEE) // this is a duplicate of feat-/block- but makes awaiting for 1 event easier than 2
|
|
32
|
-
})
|
|
33
|
-
} else if (num) handle('feat-' + flag, [], undefined, undefined, sharedEE) // not sure what other flags are overlooked, but there's a test for ones not in the map --
|
|
34
|
-
activatedFeatures[flag] = Boolean(num)
|
|
35
|
-
})
|
|
26
|
+
sharedEE.emit('rumresp', [flags])
|
|
27
|
+
activatedFeatures[agentIdentifier] = flags
|
|
36
28
|
|
|
37
|
-
// Let the features waiting on their respective flags know that RUM response was received and that any missing flags are interpreted as bad entitlement / "off".
|
|
38
|
-
// Hence, those features will not be hanging forever if their flags aren't included in the response.
|
|
39
|
-
Object.keys(bucketMap).forEach(flag => {
|
|
40
|
-
if (activatedFeatures[flag] === undefined) {
|
|
41
|
-
bucketMap[flag]?.forEach(feat => handle('rumresp-' + flag, [false], undefined, feat, sharedEE))
|
|
42
|
-
activatedFeatures[flag] = false
|
|
43
|
-
}
|
|
44
|
-
})
|
|
45
29
|
sentIds.add(agentIdentifier)
|
|
46
30
|
|
|
47
31
|
// let any window level subscribers know that the agent is running
|
|
48
32
|
dispatchGlobalEvent({ loaded: true })
|
|
49
33
|
}
|
|
50
|
-
|
|
51
|
-
export const activatedFeatures = {}
|
package/src/common/wrap/index.js
CHANGED
|
@@ -8,10 +8,9 @@ import { wrapHistory } from './wrap-history'
|
|
|
8
8
|
import { wrapJsonP } from './wrap-jsonp'
|
|
9
9
|
import { wrapMutation } from './wrap-mutation'
|
|
10
10
|
import { wrapPromise } from './wrap-promise'
|
|
11
|
-
import { wrapRaf } from './wrap-raf'
|
|
12
11
|
import { wrapTimer } from './wrap-timer'
|
|
13
12
|
import { wrapXhr } from './wrap-xhr'
|
|
14
13
|
|
|
15
14
|
export {
|
|
16
|
-
wrapEvents, wrapFetch, wrapHistory, wrapJsonP, wrapMutation, wrapPromise,
|
|
15
|
+
wrapEvents, wrapFetch, wrapHistory, wrapJsonP, wrapMutation, wrapPromise, wrapTimer, wrapXhr
|
|
17
16
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright 2020 New Relic Corporation. All rights reserved.
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
|
-
import { registerHandler
|
|
5
|
+
import { registerHandler } from '../../../common/event-emitter/register-handler'
|
|
6
6
|
import { stringify } from '../../../common/util/stringify'
|
|
7
7
|
import { nullable, numeric, getAddStringContext, addCustomAttributes } from '../../../common/serialize/bel-serializer'
|
|
8
8
|
import { handle } from '../../../common/event-emitter/handle'
|
|
@@ -14,19 +14,24 @@ import { FEATURE_NAMES } from '../../../loaders/features/features'
|
|
|
14
14
|
import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants'
|
|
15
15
|
import { AggregateBase } from '../../utils/aggregate-base'
|
|
16
16
|
import { parseGQL } from './gql'
|
|
17
|
+
import { getNREUMInitializedAgent } from '../../../common/window/nreum'
|
|
17
18
|
|
|
18
19
|
export class Aggregate extends AggregateBase {
|
|
19
20
|
static featureName = FEATURE_NAME
|
|
20
21
|
constructor (agentIdentifier, aggregator) {
|
|
21
22
|
super(agentIdentifier, aggregator, FEATURE_NAME)
|
|
22
23
|
const agentInit = getConfiguration(agentIdentifier)
|
|
23
|
-
const allAjaxIsEnabled = agentInit.ajax.enabled !== false
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
registerHandler('xhr', storeXhr, this.featureName, this.ee)
|
|
26
|
+
|
|
27
|
+
this.waitForFlags(([])).then(() => {
|
|
28
|
+
const scheduler = new HarvestScheduler('events', {
|
|
29
|
+
onFinished: onEventsHarvestFinished,
|
|
30
|
+
getPayload: prepareHarvest
|
|
31
|
+
}, this)
|
|
32
|
+
scheduler.startTimer(harvestTimeSeconds)
|
|
27
33
|
this.drain()
|
|
28
|
-
|
|
29
|
-
}
|
|
34
|
+
})
|
|
30
35
|
|
|
31
36
|
const denyList = getRuntime(agentIdentifier).denyList
|
|
32
37
|
setDenyList(denyList)
|
|
@@ -44,29 +49,21 @@ export class Aggregate extends AggregateBase {
|
|
|
44
49
|
this.prepareHarvest = prepareHarvest
|
|
45
50
|
this.getStoredEvents = function () { return { ajaxEvents, spaAjaxEvents } }
|
|
46
51
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
// remove from the spaAjaxEvents buffer, and let spa harvest it
|
|
50
|
-
delete spaAjaxEvents[interaction.id]
|
|
51
|
-
})
|
|
52
|
-
ee.on('interactionDiscarded', (interaction) => {
|
|
52
|
+
// --- v Used by old spa feature
|
|
53
|
+
ee.on('interactionDone', (interaction, wasSaved) => {
|
|
53
54
|
if (!spaAjaxEvents[interaction.id]) return
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
if (!wasSaved) { // if the ixn was saved, then its ajax reqs are part of the payload whereas if it was discarded, it should still be harvested in the ajax feature itself
|
|
57
|
+
spaAjaxEvents[interaction.id].forEach(function (item) {
|
|
58
|
+
ajaxEvents.push(item)
|
|
59
|
+
})
|
|
60
|
+
}
|
|
59
61
|
delete spaAjaxEvents[interaction.id]
|
|
60
62
|
})
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}, this)
|
|
66
|
-
|
|
67
|
-
ee.on(`drain-${this.featureName}`, () => { scheduler.startTimer(harvestTimeSeconds) })
|
|
68
|
-
|
|
69
|
-
this.drain()
|
|
63
|
+
// --- ^
|
|
64
|
+
// --- v Used by new soft nav
|
|
65
|
+
registerHandler('returnAjax', event => ajaxEvents.push(event), this.featureName, this.ee)
|
|
66
|
+
// --- ^
|
|
70
67
|
|
|
71
68
|
const beacon = getInfo(agentIdentifier).errorBeacon
|
|
72
69
|
const proxyBeacon = agentInit.proxy.beacon
|
|
@@ -82,17 +79,28 @@ export class Aggregate extends AggregateBase {
|
|
|
82
79
|
hash = stringify([params.status, params.host, params.pathname])
|
|
83
80
|
}
|
|
84
81
|
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
const shouldCollect = shouldCollectEvent(params)
|
|
83
|
+
const ajaxMetricDenyListEnabled = agentInit.feature_flags?.includes('ajax_metrics_deny_list')
|
|
87
84
|
|
|
88
|
-
|
|
85
|
+
// store as metric
|
|
86
|
+
if (shouldCollect || !ajaxMetricDenyListEnabled) {
|
|
87
|
+
aggregator.store('xhr', hash, params, metrics)
|
|
88
|
+
}
|
|
89
89
|
|
|
90
|
-
if (!
|
|
90
|
+
if (!shouldCollect) {
|
|
91
91
|
if (params.hostname === beacon || (proxyBeacon && params.hostname === proxyBeacon)) {
|
|
92
92
|
// This doesn't make a distinction if the same-domain request is going to a different port or path...
|
|
93
93
|
handle(SUPPORTABILITY_METRIC_CHANNEL, ['Ajax/Events/Excluded/Agent'], undefined, FEATURE_NAMES.metrics, ee)
|
|
94
|
+
|
|
95
|
+
if (ajaxMetricDenyListEnabled) {
|
|
96
|
+
handle(SUPPORTABILITY_METRIC_CHANNEL, ['Ajax/Metrics/Excluded/Agent'], undefined, FEATURE_NAMES.metrics, ee)
|
|
97
|
+
}
|
|
94
98
|
} else {
|
|
95
99
|
handle(SUPPORTABILITY_METRIC_CHANNEL, ['Ajax/Events/Excluded/App'], undefined, FEATURE_NAMES.metrics, ee)
|
|
100
|
+
|
|
101
|
+
if (ajaxMetricDenyListEnabled) {
|
|
102
|
+
handle(SUPPORTABILITY_METRIC_CHANNEL, ['Ajax/Metrics/Excluded/App'], undefined, FEATURE_NAMES.metrics, ee)
|
|
103
|
+
}
|
|
96
104
|
}
|
|
97
105
|
return
|
|
98
106
|
}
|
|
@@ -125,12 +133,13 @@ export class Aggregate extends AggregateBase {
|
|
|
125
133
|
body: this.body,
|
|
126
134
|
query: this?.parsedOrigin?.search
|
|
127
135
|
})
|
|
128
|
-
|
|
129
136
|
if (event.gql) handle(SUPPORTABILITY_METRIC_CHANNEL, ['Ajax/Events/GraphQL/Bytes-Added', stringify(event.gql).length], undefined, FEATURE_NAMES.metrics, ee)
|
|
130
137
|
|
|
131
|
-
|
|
132
|
-
if (
|
|
133
|
-
|
|
138
|
+
const softNavInUse = Boolean(getNREUMInitializedAgent(agentIdentifier)?.features?.[FEATURE_NAMES.softNav])
|
|
139
|
+
if (softNavInUse) { // For newer soft nav (when running), pass the event to it for evaluation -- either part of an interaction or is given back
|
|
140
|
+
handle('ajax', [event], undefined, FEATURE_NAMES.softNav, ee)
|
|
141
|
+
} else if (this.spaNode) { // For old spa (when running), if the ajax happened inside an interaction, hold it until the interaction finishes
|
|
142
|
+
const interactionId = this.spaNode.interaction.id
|
|
134
143
|
spaAjaxEvents[interactionId] = spaAjaxEvents[interactionId] || []
|
|
135
144
|
spaAjaxEvents[interactionId].push(event)
|
|
136
145
|
} else {
|
|
@@ -209,6 +218,7 @@ export class Aggregate extends AggregateBase {
|
|
|
209
218
|
|
|
210
219
|
for (var i = 0; i < events.length; i++) {
|
|
211
220
|
var event = events[i]
|
|
221
|
+
|
|
212
222
|
var fields = [
|
|
213
223
|
numeric(event.startTime),
|
|
214
224
|
numeric(event.endTime - event.startTime),
|