@newrelic/browser-agent 1.237.1 → 1.239.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/dist/cjs/common/config/state/init.js +21 -13
- package/dist/cjs/common/config/state/runtime.js +0 -4
- 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 +3 -3
- package/dist/cjs/common/constants/shared-channel.js +3 -1
- package/dist/cjs/common/deny-list/deny-list.js +3 -9
- package/dist/cjs/common/drain/drain.js +1 -1
- package/dist/cjs/common/event-emitter/contextual-ee.js +24 -32
- package/dist/cjs/common/event-emitter/event-context.js +12 -0
- package/dist/cjs/common/harvest/harvest-scheduler.js +2 -4
- package/dist/cjs/common/harvest/harvest.js +4 -7
- package/dist/cjs/common/ids/bundle-id.js +19 -0
- package/dist/cjs/common/serialize/bel-serializer.js +1 -1
- package/dist/cjs/common/session/session-entity.js +16 -12
- package/dist/cjs/common/storage/first-party-cookies.js +5 -4
- package/dist/cjs/common/storage/local-storage.js +3 -2
- package/dist/cjs/common/timer/interaction-timer.js +14 -6
- package/dist/cjs/common/timing/nav-timing.js +1 -1
- package/dist/cjs/common/unload/eol.js +4 -30
- package/dist/cjs/common/util/feature-flags.js +14 -15
- package/dist/cjs/common/util/invoke.js +3 -1
- package/dist/cjs/common/util/obfuscate.js +3 -5
- package/dist/cjs/common/util/traverse.js +1 -0
- package/dist/cjs/common/window/page-visibility.js +1 -2
- package/dist/cjs/common/wrap/wrap-events.js +3 -2
- package/dist/cjs/common/wrap/wrap-fetch.js +1 -3
- package/dist/cjs/common/wrap/wrap-function.js +15 -46
- package/dist/cjs/common/wrap/wrap-jsonp.js +1 -1
- package/dist/cjs/common/wrap/wrap-mutation.js +1 -2
- package/dist/cjs/common/wrap/wrap-promise.js +2 -3
- package/dist/cjs/common/wrap/wrap-xhr.js +23 -27
- package/dist/cjs/features/ajax/aggregate/index.js +5 -7
- package/dist/cjs/features/ajax/instrument/distributed-tracing.js +8 -12
- package/dist/cjs/features/ajax/instrument/index.js +66 -24
- package/dist/cjs/features/jserrors/aggregate/canonical-function-name.js +0 -1
- package/dist/cjs/features/jserrors/aggregate/compute-stack-trace.js +4 -4
- package/dist/cjs/features/jserrors/aggregate/index.js +4 -5
- package/dist/cjs/features/metrics/aggregate/framework-detection.js +103 -7
- package/dist/cjs/features/metrics/aggregate/index.js +20 -37
- package/dist/cjs/features/metrics/instrument/index.js +0 -2
- package/dist/cjs/features/page_action/aggregate/index.js +17 -19
- package/dist/cjs/features/page_view_event/aggregate/index.js +1 -2
- package/dist/cjs/features/page_view_event/instrument/index.js +4 -2
- package/dist/cjs/features/page_view_timing/aggregate/index.js +6 -7
- package/dist/cjs/features/session_replay/aggregate/index.js +5 -3
- package/dist/cjs/features/session_trace/aggregate/index.js +22 -16
- package/dist/cjs/features/spa/aggregate/index.js +14 -20
- package/dist/cjs/features/spa/aggregate/interaction.js +0 -2
- package/dist/cjs/features/spa/aggregate/serializer.js +1 -1
- package/dist/cjs/features/utils/aggregate-base.js +4 -0
- package/dist/cjs/features/utils/handler-cache.js +3 -1
- package/dist/cjs/features/utils/instrument-base.js +24 -6
- package/dist/cjs/loaders/agent-base.js +23 -0
- package/dist/cjs/loaders/agent.js +7 -7
- package/dist/cjs/loaders/api/api.js +34 -4
- package/dist/cjs/loaders/api/apiAsync.js +19 -20
- package/dist/cjs/loaders/api/interaction-types.js +11 -4
- package/dist/cjs/loaders/configure/configure.js +3 -0
- package/dist/cjs/loaders/micro-agent.js +20 -3
- package/dist/esm/common/config/state/init.js +21 -13
- package/dist/esm/common/config/state/runtime.js +0 -4
- 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 +1 -1
- package/dist/esm/common/constants/shared-channel.js +3 -1
- package/dist/esm/common/deny-list/deny-list.js +3 -9
- package/dist/esm/common/drain/drain.js +1 -1
- package/dist/esm/common/event-emitter/contextual-ee.js +22 -29
- package/dist/esm/common/event-emitter/event-context.js +5 -0
- package/dist/esm/common/harvest/harvest-scheduler.js +2 -4
- package/dist/esm/common/harvest/harvest.js +4 -7
- package/dist/esm/common/ids/bundle-id.js +13 -0
- package/dist/esm/common/serialize/bel-serializer.js +1 -1
- package/dist/esm/common/session/session-entity.js +16 -12
- package/dist/esm/common/storage/first-party-cookies.js +5 -4
- package/dist/esm/common/storage/local-storage.js +3 -2
- package/dist/esm/common/timer/interaction-timer.js +14 -6
- package/dist/esm/common/timing/nav-timing.js +1 -1
- package/dist/esm/common/unload/eol.js +5 -31
- package/dist/esm/common/util/feature-flags.js +14 -15
- package/dist/esm/common/util/invoke.js +3 -1
- package/dist/esm/common/util/obfuscate.js +3 -5
- package/dist/esm/common/util/traverse.js +1 -0
- package/dist/esm/common/window/page-visibility.js +1 -2
- package/dist/esm/common/wrap/wrap-events.js +4 -3
- package/dist/esm/common/wrap/wrap-fetch.js +2 -4
- package/dist/esm/common/wrap/wrap-function.js +15 -44
- package/dist/esm/common/wrap/wrap-jsonp.js +1 -1
- package/dist/esm/common/wrap/wrap-mutation.js +2 -3
- package/dist/esm/common/wrap/wrap-promise.js +3 -4
- package/dist/esm/common/wrap/wrap-xhr.js +23 -27
- package/dist/esm/features/ajax/aggregate/index.js +5 -7
- package/dist/esm/features/ajax/instrument/distributed-tracing.js +8 -12
- package/dist/esm/features/ajax/instrument/index.js +67 -25
- package/dist/esm/features/jserrors/aggregate/canonical-function-name.js +0 -1
- package/dist/esm/features/jserrors/aggregate/compute-stack-trace.js +4 -4
- package/dist/esm/features/jserrors/aggregate/index.js +4 -5
- package/dist/esm/features/metrics/aggregate/framework-detection.js +103 -7
- package/dist/esm/features/metrics/aggregate/index.js +22 -39
- package/dist/esm/features/metrics/instrument/index.js +1 -3
- package/dist/esm/features/page_action/aggregate/index.js +17 -19
- package/dist/esm/features/page_view_event/aggregate/index.js +1 -2
- package/dist/esm/features/page_view_event/instrument/index.js +4 -2
- package/dist/esm/features/page_view_timing/aggregate/index.js +7 -8
- package/dist/esm/features/session_replay/aggregate/index.js +4 -2
- package/dist/esm/features/session_trace/aggregate/index.js +22 -16
- package/dist/esm/features/spa/aggregate/index.js +14 -20
- package/dist/esm/features/spa/aggregate/interaction.js +0 -2
- package/dist/esm/features/spa/aggregate/serializer.js +1 -1
- package/dist/esm/features/utils/aggregate-base.js +4 -0
- package/dist/esm/features/utils/handler-cache.js +3 -1
- package/dist/esm/features/utils/instrument-base.js +24 -6
- package/dist/esm/loaders/agent-base.js +23 -0
- package/dist/esm/loaders/agent.js +7 -7
- package/dist/esm/loaders/api/api.js +34 -4
- package/dist/esm/loaders/api/apiAsync.js +19 -20
- package/dist/esm/loaders/api/interaction-types.js +11 -4
- package/dist/esm/loaders/configure/configure.js +3 -0
- package/dist/esm/loaders/features/enabled-features.js +1 -1
- package/dist/esm/loaders/micro-agent.js +21 -4
- 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/constants/runtime.d.ts +1 -1
- package/dist/types/common/constants/runtime.d.ts.map +1 -1
- package/dist/types/common/event-emitter/contextual-ee.d.ts +22 -2
- package/dist/types/common/event-emitter/contextual-ee.d.ts.map +1 -1
- package/dist/types/common/event-emitter/event-context.d.ts +5 -0
- package/dist/types/common/event-emitter/event-context.d.ts.map +1 -0
- package/dist/types/common/event-emitter/register-handler.d.ts +1 -1
- package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
- package/dist/types/common/harvest/harvest.d.ts.map +1 -1
- package/dist/types/common/ids/bundle-id.d.ts +5 -0
- package/dist/types/common/ids/bundle-id.d.ts.map +1 -0
- package/dist/types/common/session/session-entity.d.ts +12 -15
- package/dist/types/common/session/session-entity.d.ts.map +1 -1
- package/dist/types/common/storage/first-party-cookies.d.ts +1 -1
- package/dist/types/common/storage/first-party-cookies.d.ts.map +1 -1
- package/dist/types/common/storage/local-storage.d.ts.map +1 -1
- package/dist/types/common/timer/interaction-timer.d.ts +3 -0
- package/dist/types/common/timer/interaction-timer.d.ts.map +1 -1
- package/dist/types/common/unload/eol.d.ts +1 -2
- package/dist/types/common/unload/eol.d.ts.map +1 -1
- package/dist/types/common/util/feature-flags.d.ts.map +1 -1
- package/dist/types/common/util/obfuscate.d.ts.map +1 -1
- package/dist/types/common/util/traverse.d.ts.map +1 -1
- package/dist/types/common/window/nreum.d.ts +2 -2
- package/dist/types/common/window/page-visibility.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-events.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-fetch.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-function.d.ts +1 -19
- package/dist/types/common/wrap/wrap-function.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-mutation.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-promise.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-xhr.d.ts.map +1 -1
- package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/ajax/instrument/distributed-tracing.d.ts +1 -1
- package/dist/types/features/ajax/instrument/distributed-tracing.d.ts.map +1 -1
- package/dist/types/features/ajax/instrument/index.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/canonical-function-name.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/metrics/aggregate/framework-detection.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/metrics/instrument/index.d.ts.map +1 -1
- package/dist/types/features/page_action/aggregate/index.d.ts +2 -2
- 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_timing/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/index.d.ts +5 -0
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/spa/aggregate/interaction.d.ts.map +1 -1
- package/dist/types/features/utils/aggregate-base.d.ts +1 -0
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
- package/dist/types/features/utils/handler-cache.d.ts.map +1 -1
- package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
- package/dist/types/loaders/agent-base.d.ts +15 -0
- package/dist/types/loaders/agent-base.d.ts.map +1 -1
- package/dist/types/loaders/agent.d.ts +1 -1
- package/dist/types/loaders/agent.d.ts.map +1 -1
- package/dist/types/loaders/api/api.d.ts +7 -0
- package/dist/types/loaders/api/api.d.ts.map +1 -1
- package/dist/types/loaders/api/apiAsync.d.ts.map +1 -1
- package/dist/types/loaders/api/interaction-types.d.ts +18 -7
- package/dist/types/loaders/api/interaction-types.d.ts.map +1 -1
- package/dist/types/loaders/configure/configure.d.ts +2 -0
- package/dist/types/loaders/configure/configure.d.ts.map +1 -1
- package/dist/types/loaders/features/features.d.ts +9 -9
- package/dist/types/loaders/micro-agent.d.ts +7 -1
- package/dist/types/loaders/micro-agent.d.ts.map +1 -1
- package/package.json +62 -38
- package/src/common/aggregate/aggregator.test.js +107 -0
- package/src/common/config/state/configurable.test.js +73 -0
- package/src/common/config/state/info.test.js +31 -0
- package/src/common/config/state/init.js +13 -12
- package/src/common/config/state/init.test.js +28 -0
- package/src/common/config/state/loader-config.test.js +21 -0
- package/src/common/config/state/runtime.js +0 -2
- package/src/common/config/state/runtime.test.js +21 -0
- package/src/common/constants/__mocks__/runtime.js +1 -1
- package/src/common/constants/runtime.js +1 -1
- package/src/common/constants/runtime.test.js +2 -2
- package/src/common/constants/shared-channel.js +1 -1
- package/src/common/deny-list/deny-list.js +3 -11
- package/src/common/deny-list/deny-list.test.js +103 -30
- package/src/common/drain/drain.js +1 -1
- package/src/common/drain/drain.test.js +74 -0
- package/src/common/event-emitter/{contextual-ee.test.js → contextual-ee.component-test.js} +15 -32
- package/src/common/event-emitter/contextual-ee.js +26 -37
- package/src/common/event-emitter/event-context.js +5 -0
- package/src/common/harvest/harvest-scheduler.js +2 -5
- package/src/common/harvest/harvest-scheduler.test.js +2 -6
- package/src/common/harvest/harvest.js +4 -7
- package/src/common/harvest/harvest.test.js +1 -3
- package/src/common/ids/__mocks__/bundle-id.js +2 -0
- package/src/common/ids/__mocks__/unique-id.js +17 -0
- package/src/common/ids/bundle-id.js +13 -0
- package/src/common/ids/id.test.js +6 -6
- package/src/common/serialize/bel-serializer.js +1 -1
- package/src/common/session/session-entity.component-test.js +3 -2
- package/src/common/session/session-entity.js +11 -9
- package/src/common/storage/first-party-cookies.js +5 -4
- package/src/common/storage/local-storage.js +3 -2
- package/src/common/timer/interaction-timer.component-test.js +52 -7
- package/src/common/timer/interaction-timer.js +15 -6
- package/src/common/timer/timer.test.js +0 -1
- package/src/common/timing/nav-timing.js +1 -1
- package/src/common/unload/eol.js +5 -31
- package/src/common/url/__mocks__/parse-url.js +15 -0
- package/src/common/url/{encode.component-test.js → encode.test.js} +1 -0
- package/src/common/util/__mocks__/get-or-set.js +5 -0
- package/src/common/util/__mocks__/invoke.js +1 -0
- package/src/common/util/data-size.test.js +0 -1
- package/src/common/util/feature-flags.js +15 -17
- package/src/common/util/feature-flags.test.js +4 -8
- package/src/common/util/invoke.js +1 -1
- package/src/common/util/obfuscate.js +3 -5
- package/src/common/util/submit-data.test.js +1 -1
- package/src/common/util/traverse.js +1 -0
- package/src/common/window/__mocks__/nreum.js +12 -0
- package/src/common/window/page-visibility.js +1 -2
- package/src/common/wrap/wrap-events.js +4 -3
- package/src/common/wrap/wrap-fetch.js +2 -4
- package/src/common/wrap/wrap-function.js +16 -44
- package/src/common/wrap/wrap-jsonp.js +1 -1
- package/src/common/wrap/wrap-mutation.js +2 -3
- package/src/common/wrap/{wrap-promise.test.js → wrap-promise.component-test.js} +2 -32
- package/src/common/wrap/wrap-promise.js +3 -4
- package/src/common/wrap/wrap-xhr.js +24 -28
- package/src/features/ajax/aggregate/index.js +5 -7
- package/src/features/ajax/instrument/distributed-tracing.js +8 -12
- package/src/features/ajax/instrument/distributed-tracing.test.js +375 -0
- package/src/features/ajax/instrument/index.js +62 -27
- package/src/features/jserrors/aggregate/canonical-function-name.js +0 -2
- package/src/features/jserrors/aggregate/compute-stack-trace.js +4 -4
- package/src/features/jserrors/aggregate/compute-stack-trace.test.js +1 -1
- package/src/features/jserrors/aggregate/index.js +4 -5
- package/src/features/metrics/aggregate/framework-detection.js +129 -8
- package/src/features/metrics/aggregate/framework-detection.test.js +213 -82
- package/src/features/metrics/aggregate/index.js +22 -45
- package/src/features/metrics/instrument/index.js +1 -3
- package/src/features/page_action/aggregate/index.js +12 -13
- package/src/features/page_view_event/aggregate/index.js +1 -2
- package/src/features/page_view_event/instrument/index.js +2 -2
- package/src/features/page_view_timing/aggregate/index.js +7 -8
- package/src/features/session_replay/aggregate/index.component-test.js +3 -15
- package/src/features/session_replay/aggregate/index.js +4 -2
- package/src/features/session_trace/aggregate/index.js +22 -16
- package/src/features/spa/aggregate/index.js +14 -20
- package/src/features/spa/aggregate/interaction.js +0 -2
- package/src/features/spa/aggregate/serializer.js +1 -1
- package/src/features/utils/aggregate-base.js +5 -0
- package/src/features/utils/aggregate-base.test.js +2 -1
- package/src/features/utils/handler-cache.js +3 -2
- package/src/features/utils/instrument-base.js +25 -6
- package/src/features/utils/instrument-base.test.js +2 -2
- package/src/loaders/agent-base.js +23 -0
- package/src/loaders/agent.js +7 -7
- package/src/loaders/api/api.component-test.js +45 -0
- package/src/loaders/api/api.js +34 -4
- package/src/loaders/api/api.test.js +85 -0
- package/src/loaders/api/apiAsync.js +19 -20
- package/src/loaders/api/apiAsync.test.js +17 -0
- package/src/loaders/api/interaction-types.js +11 -4
- package/src/loaders/configure/configure.js +3 -0
- package/src/loaders/features/enabled-features.js +1 -1
- package/src/loaders/micro-agent.js +22 -4
- package/dist/cjs/features/metrics/aggregate/endpoint-map.js +0 -14
- package/dist/cjs/features/metrics/aggregate/polyfill-detection.es5.js +0 -14
- package/dist/cjs/features/metrics/aggregate/polyfill-detection.js +0 -53
- package/dist/esm/features/metrics/aggregate/endpoint-map.js +0 -7
- package/dist/esm/features/metrics/aggregate/polyfill-detection.es5.js +0 -8
- package/dist/esm/features/metrics/aggregate/polyfill-detection.js +0 -47
- package/dist/types/features/metrics/aggregate/endpoint-map.d.ts +0 -8
- package/dist/types/features/metrics/aggregate/endpoint-map.d.ts.map +0 -1
- package/dist/types/features/metrics/aggregate/polyfill-detection.d.ts +0 -6
- package/dist/types/features/metrics/aggregate/polyfill-detection.d.ts.map +0 -1
- package/dist/types/features/metrics/aggregate/polyfill-detection.es5.d.ts +0 -7
- package/dist/types/features/metrics/aggregate/polyfill-detection.es5.d.ts.map +0 -1
- package/src/features/metrics/aggregate/endpoint-map.js +0 -7
- package/src/features/metrics/aggregate/polyfill-detection.es5.js +0 -8
- package/src/features/metrics/aggregate/polyfill-detection.es5.test.js +0 -16
- package/src/features/metrics/aggregate/polyfill-detection.js +0 -48
- package/src/features/metrics/aggregate/polyfill-detection.test.js +0 -163
- /package/src/common/url/{protocol.component-test.js → protocol.test.js} +0 -0
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { InstrumentBase } from '../../utils/instrument-base'
|
|
2
|
-
import { FEATURE_NAME
|
|
3
|
-
import { handle } from '../../../common/event-emitter/handle'
|
|
4
|
-
import { FEATURE_NAMES } from '../../../loaders/features/features'
|
|
2
|
+
import { FEATURE_NAME } from '../constants'
|
|
5
3
|
|
|
6
4
|
export class Instrument extends InstrumentBase {
|
|
7
5
|
static featureName = FEATURE_NAME
|
|
@@ -10,7 +10,6 @@ import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
|
|
|
10
10
|
import { cleanURL } from '../../../common/url/clean-url'
|
|
11
11
|
import { getConfigurationValue, getInfo, getRuntime } from '../../../common/config/config'
|
|
12
12
|
import { FEATURE_NAME } from '../constants'
|
|
13
|
-
import { drain } from '../../../common/drain/drain'
|
|
14
13
|
import { isBrowserScope } from '../../../common/constants/runtime'
|
|
15
14
|
import { AggregateBase } from '../../utils/aggregate-base'
|
|
16
15
|
|
|
@@ -21,8 +20,8 @@ export class Aggregate extends AggregateBase {
|
|
|
21
20
|
this.eventsPerMinute = 240
|
|
22
21
|
this.harvestTimeSeconds = getConfigurationValue(this.agentIdentifier, 'page_action.harvestTimeSeconds') || getConfigurationValue(this.agentIdentifier, 'ins.harvestTimeSeconds') || 30
|
|
23
22
|
this.eventsPerHarvest = this.eventsPerMinute * this.harvestTimeSeconds / 60
|
|
24
|
-
this.referrerUrl
|
|
25
|
-
this.currentEvents
|
|
23
|
+
this.referrerUrl = undefined
|
|
24
|
+
this.currentEvents = undefined
|
|
26
25
|
|
|
27
26
|
this.events = []
|
|
28
27
|
|
|
@@ -32,17 +31,17 @@ export class Aggregate extends AggregateBase {
|
|
|
32
31
|
|
|
33
32
|
register('api-addPageAction', (...args) => this.addPageAction(...args), this.featureName, this.ee)
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
34
|
+
this.waitForFlags(['ins']).then(([enabled]) => {
|
|
35
|
+
if (enabled) {
|
|
36
|
+
const scheduler = new HarvestScheduler('ins', { onFinished: (...args) => this.onHarvestFinished(...args) }, this)
|
|
37
|
+
scheduler.harvest.on('ins', (...args) => this.onHarvestStarted(...args))
|
|
38
|
+
scheduler.startTimer(this.harvestTimeSeconds, 0)
|
|
39
|
+
} else {
|
|
40
|
+
this.blocked = true
|
|
41
|
+
}
|
|
42
|
+
})
|
|
44
43
|
|
|
45
|
-
drain(
|
|
44
|
+
this.drain()
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
onHarvestStarted (options) {
|
|
@@ -9,7 +9,6 @@ import { getConfigurationValue, getInfo, getRuntime } from '../../../common/conf
|
|
|
9
9
|
import { Harvest } from '../../../common/harvest/harvest'
|
|
10
10
|
import * as CONSTANTS from '../constants'
|
|
11
11
|
import { getActivatedFeaturesFlags } from './initialized-features'
|
|
12
|
-
import { drain } from '../../../common/drain/drain'
|
|
13
12
|
import { activateFeatures } from '../../../common/util/feature-flags'
|
|
14
13
|
import { warn } from '../../../common/util/console'
|
|
15
14
|
import { AggregateBase } from '../../utils/aggregate-base'
|
|
@@ -131,7 +130,7 @@ export class Aggregate extends AggregateBase {
|
|
|
131
130
|
|
|
132
131
|
try {
|
|
133
132
|
activateFeatures(JSON.parse(responseText), this.agentIdentifier)
|
|
134
|
-
drain(
|
|
133
|
+
this.drain()
|
|
135
134
|
} catch (err) {
|
|
136
135
|
this.ee.abort()
|
|
137
136
|
warn('RUM call failed. Agent shutting down.')
|
|
@@ -14,11 +14,11 @@ export class Instrument extends InstrumentBase {
|
|
|
14
14
|
|
|
15
15
|
if ((typeof PerformanceNavigationTiming === 'undefined' || isiOS) && typeof PerformanceTiming !== 'undefined') {
|
|
16
16
|
// For majority browser versions in which PNT exists, we can get load timings later from the nav entry (in the aggregate portion). At minimum, PT should exist for main window.
|
|
17
|
-
// *cli Mar'23 - iOS 15.2 & 15.4 testing in Sauce still fails with onTTFB. Hence, all iOS will fallback to this for now. Unknown if this is similar in nature to
|
|
17
|
+
// *cli Mar'23 - iOS 15.2 & 15.4 testing in Sauce still fails with onTTFB. Hence, all iOS will fallback to this for now. Unknown if this is similar in nature to iOSBelow16 bug.
|
|
18
18
|
const agentRuntime = getRuntime(agentIdentifier)
|
|
19
19
|
|
|
20
20
|
agentRuntime[CONSTANTS.TTFB] = Math.max(Date.now() - agentRuntime.offset, 0)
|
|
21
|
-
onDOMContentLoaded(() => agentRuntime[CONSTANTS.FBTDC] = Math.max(now() - agentRuntime[CONSTANTS.TTFB], 0))
|
|
21
|
+
onDOMContentLoaded(() => { agentRuntime[CONSTANTS.FBTDC] = Math.max(now() - agentRuntime[CONSTANTS.TTFB], 0) })
|
|
22
22
|
onWindowLoad(() => {
|
|
23
23
|
const timeNow = now()
|
|
24
24
|
agentRuntime[CONSTANTS.FBTWL] = Math.max(timeNow - agentRuntime[CONSTANTS.TTFB], 0)
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { onFCP, onFID, onLCP, onCLS, onINP } from 'web-vitals'
|
|
7
7
|
import { onFirstPaint } from '../first-paint'
|
|
8
8
|
import { onLongTask } from '../long-tasks'
|
|
9
|
-
import {
|
|
9
|
+
import { iOSBelow16 } from '../../../common/constants/runtime'
|
|
10
10
|
import { nullable, numeric, getAddStringContext, addCustomAttributes } from '../../../common/serialize/bel-serializer'
|
|
11
11
|
import { mapOwn } from '../../../common/util/map-own'
|
|
12
12
|
import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
|
|
@@ -15,7 +15,6 @@ import { cleanURL } from '../../../common/url/clean-url'
|
|
|
15
15
|
import { handle } from '../../../common/event-emitter/handle'
|
|
16
16
|
import { getInfo, getConfigurationValue, getRuntime } from '../../../common/config/config'
|
|
17
17
|
import { FEATURE_NAME } from '../constants'
|
|
18
|
-
import { drain } from '../../../common/drain/drain'
|
|
19
18
|
import { FEATURE_NAMES } from '../../../loaders/features/features'
|
|
20
19
|
import { AggregateBase } from '../../utils/aggregate-base'
|
|
21
20
|
|
|
@@ -41,7 +40,7 @@ export class Aggregate extends AggregateBase {
|
|
|
41
40
|
})
|
|
42
41
|
|
|
43
42
|
/* First Contentful Paint - As of WV v3, it still imperfectly tries to detect document vis state asap and isn't supposed to report if page starts hidden. */
|
|
44
|
-
if (
|
|
43
|
+
if (iOSBelow16) {
|
|
45
44
|
try {
|
|
46
45
|
if (!pageStartedHidden) { // see ios-version.js for detail on this following bug case; tldr: buffered flag doesn't work but getEntriesByType does
|
|
47
46
|
const paintEntries = performance.getEntriesByType('paint')
|
|
@@ -101,7 +100,7 @@ export class Aggregate extends AggregateBase {
|
|
|
101
100
|
|
|
102
101
|
/* Cumulative Layout Shift - We don't have to limit this callback since cls is stored as a state and only sent as attribute on other timings.
|
|
103
102
|
reportAllChanges ensures our tracked cls has the most recent rolling value to attach to 'unload' and 'pagehide'. */
|
|
104
|
-
onCLS(({ value }) => this.cls = value, { reportAllChanges: true })
|
|
103
|
+
onCLS(({ value }) => { this.cls = value }, { reportAllChanges: true })
|
|
105
104
|
|
|
106
105
|
/* Interaction-to-Next-Paint */
|
|
107
106
|
onINP(({ name, value, id }) => this.addTiming(name.toLowerCase(), value, { metricId: id }))
|
|
@@ -128,7 +127,7 @@ export class Aggregate extends AggregateBase {
|
|
|
128
127
|
// send initial data sooner, then start regular
|
|
129
128
|
this.ee.on(`drain-${this.featureName}`, () => { this.scheduler.startTimer(harvestTimeSeconds, initialHarvestSeconds) })
|
|
130
129
|
|
|
131
|
-
drain(
|
|
130
|
+
this.drain()
|
|
132
131
|
}
|
|
133
132
|
|
|
134
133
|
// takes an attributes object and appends connection attributes if available
|
|
@@ -185,9 +184,9 @@ export class Aggregate extends AggregateBase {
|
|
|
185
184
|
}
|
|
186
185
|
|
|
187
186
|
this.timings.push({
|
|
188
|
-
name
|
|
189
|
-
value
|
|
190
|
-
attrs
|
|
187
|
+
name,
|
|
188
|
+
value,
|
|
189
|
+
attrs
|
|
191
190
|
})
|
|
192
191
|
|
|
193
192
|
handle('pvtAdded', [name, value, attrs], undefined, FEATURE_NAMES.sessionTrace, this.ee)
|
|
@@ -13,6 +13,7 @@ class LocalMemory {
|
|
|
13
13
|
try {
|
|
14
14
|
return this.state[key]
|
|
15
15
|
} catch (err) {
|
|
16
|
+
// Error is ignored
|
|
16
17
|
return ''
|
|
17
18
|
}
|
|
18
19
|
}
|
|
@@ -22,7 +23,7 @@ class LocalMemory {
|
|
|
22
23
|
if (value === undefined || value === null) return this.remove(key)
|
|
23
24
|
this.state[key] = value
|
|
24
25
|
} catch (err) {
|
|
25
|
-
|
|
26
|
+
// Error is ignored
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
|
|
@@ -30,7 +31,7 @@ class LocalMemory {
|
|
|
30
31
|
try {
|
|
31
32
|
delete this.state[key]
|
|
32
33
|
} catch (err) {
|
|
33
|
-
|
|
34
|
+
// Error is ignored
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
}
|
|
@@ -102,7 +103,6 @@ describe('Session Replay', () => {
|
|
|
102
103
|
sr.ee.emit('rumresp-sr', [true])
|
|
103
104
|
await wait(1)
|
|
104
105
|
expect(session.state.sessionReplay).toEqual(sr.mode)
|
|
105
|
-
return
|
|
106
106
|
})
|
|
107
107
|
|
|
108
108
|
test('Session SR mode matches SR mode -- OFF', async () => {
|
|
@@ -110,7 +110,6 @@ describe('Session Replay', () => {
|
|
|
110
110
|
sr.ee.emit('rumresp-sr', [true])
|
|
111
111
|
await wait(1)
|
|
112
112
|
expect(session.state.sessionReplay).toEqual(sr.mode)
|
|
113
|
-
return
|
|
114
113
|
})
|
|
115
114
|
})
|
|
116
115
|
|
|
@@ -127,7 +126,6 @@ describe('Session Replay', () => {
|
|
|
127
126
|
await wait(1)
|
|
128
127
|
expect(sr.initialized).toEqual(true)
|
|
129
128
|
expect(sr.recording).toEqual(false)
|
|
130
|
-
return
|
|
131
129
|
})
|
|
132
130
|
|
|
133
131
|
test('Does not run if cookies_enabled is false', async () => {
|
|
@@ -137,7 +135,6 @@ describe('Session Replay', () => {
|
|
|
137
135
|
await wait(1)
|
|
138
136
|
expect(sr.initialized).toEqual(false)
|
|
139
137
|
expect(sr.recording).toEqual(false)
|
|
140
|
-
return
|
|
141
138
|
})
|
|
142
139
|
|
|
143
140
|
test('Does not run if session_trace is disabled', async () => {
|
|
@@ -147,7 +144,6 @@ describe('Session Replay', () => {
|
|
|
147
144
|
await wait(1)
|
|
148
145
|
expect(sr.initialized).toEqual(false)
|
|
149
146
|
expect(sr.recording).toEqual(false)
|
|
150
|
-
return
|
|
151
147
|
})
|
|
152
148
|
})
|
|
153
149
|
|
|
@@ -157,7 +153,6 @@ describe('Session Replay', () => {
|
|
|
157
153
|
sr.ee.emit('rumresp-sr', [true])
|
|
158
154
|
await wait(1)
|
|
159
155
|
expect(sr.mode).toEqual(MODE.FULL)
|
|
160
|
-
return
|
|
161
156
|
})
|
|
162
157
|
|
|
163
158
|
test('New Session -- Full 1 Error 0 === FULL', async () => {
|
|
@@ -165,7 +160,6 @@ describe('Session Replay', () => {
|
|
|
165
160
|
sr.ee.emit('rumresp-sr', [true])
|
|
166
161
|
await wait(1)
|
|
167
162
|
expect(sr.mode).toEqual(MODE.FULL)
|
|
168
|
-
return
|
|
169
163
|
})
|
|
170
164
|
|
|
171
165
|
test('New Session -- Full 0 Error 1 === ERROR', async () => {
|
|
@@ -173,7 +167,6 @@ describe('Session Replay', () => {
|
|
|
173
167
|
sr.ee.emit('rumresp-sr', [true])
|
|
174
168
|
await wait(1)
|
|
175
169
|
expect(sr.mode).toEqual(MODE.ERROR)
|
|
176
|
-
return
|
|
177
170
|
})
|
|
178
171
|
|
|
179
172
|
test('New Session -- Full 0 Error 0 === OFF', async () => {
|
|
@@ -181,7 +174,6 @@ describe('Session Replay', () => {
|
|
|
181
174
|
sr.ee.emit('rumresp-sr', [true])
|
|
182
175
|
await wait(1)
|
|
183
176
|
expect(sr.mode).toEqual(MODE.OFF)
|
|
184
|
-
return
|
|
185
177
|
})
|
|
186
178
|
|
|
187
179
|
test('Existing Session -- Should inherit mode from session entity and ignore samples', async () => {
|
|
@@ -194,7 +186,6 @@ describe('Session Replay', () => {
|
|
|
194
186
|
sr.ee.emit('rumresp-sr', [true])
|
|
195
187
|
await wait(1)
|
|
196
188
|
expect(sr.mode).toEqual(MODE.FULL)
|
|
197
|
-
return
|
|
198
189
|
})
|
|
199
190
|
})
|
|
200
191
|
|
|
@@ -206,7 +197,6 @@ describe('Session Replay', () => {
|
|
|
206
197
|
await wait(1)
|
|
207
198
|
expect(sr.mode).toEqual(MODE.FULL)
|
|
208
199
|
expect(sr.scheduler.started).toEqual(true)
|
|
209
|
-
return
|
|
210
200
|
})
|
|
211
201
|
|
|
212
202
|
test('An error AFTER rrweb import changes mode and starts harvester', async () => {
|
|
@@ -218,7 +208,6 @@ describe('Session Replay', () => {
|
|
|
218
208
|
sr.ee.emit('errorAgg')
|
|
219
209
|
expect(sr.mode).toEqual(MODE.FULL)
|
|
220
210
|
expect(sr.scheduler.started).toEqual(true)
|
|
221
|
-
return
|
|
222
211
|
})
|
|
223
212
|
})
|
|
224
213
|
|
|
@@ -296,7 +285,6 @@ describe('Session Replay', () => {
|
|
|
296
285
|
const spy = jest.spyOn(sr.scheduler, 'runHarvest')
|
|
297
286
|
setConfiguration(agentIdentifier, { ...init })
|
|
298
287
|
sr.payloadBytesEstimation = (MAX_PAYLOAD_SIZE + 1) / AVG_COMPRESSION
|
|
299
|
-
const before = Date.now()
|
|
300
288
|
sr.ee.emit('rumresp-sr', [true])
|
|
301
289
|
await wait(1)
|
|
302
290
|
expect(spy).not.toHaveBeenCalled()
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
* functionality is validated and a full user experience is curated.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { drain } from '../../../common/drain/drain'
|
|
14
13
|
import { registerHandler } from '../../../common/event-emitter/register-handler'
|
|
15
14
|
import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
|
|
16
15
|
import { FEATURE_NAME } from '../constants'
|
|
@@ -20,6 +19,7 @@ import { SESSION_EVENTS, MODE } from '../../../common/session/session-entity'
|
|
|
20
19
|
import { AggregateBase } from '../../utils/aggregate-base'
|
|
21
20
|
import { sharedChannel } from '../../../common/constants/shared-channel'
|
|
22
21
|
import { obj as encodeObj } from '../../../common/url/encode'
|
|
22
|
+
import { warn } from '../../../common/util/console'
|
|
23
23
|
|
|
24
24
|
// would be better to get this dynamically in some way
|
|
25
25
|
export const RRWEB_VERSION = '2.0.0-alpha.8'
|
|
@@ -127,7 +127,7 @@ export class Aggregate extends AggregateBase {
|
|
|
127
127
|
Math.random() < getConfigurationValue(this.agentIdentifier, 'session_replay.sampleRate')
|
|
128
128
|
)).then(() => sharedChannel.onReplayReady(this.mode)) // notify watchers that replay started with the mode
|
|
129
129
|
|
|
130
|
-
drain(
|
|
130
|
+
this.drain()
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
|
|
@@ -173,12 +173,14 @@ export class Aggregate extends AggregateBase {
|
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
try {
|
|
176
|
+
// Do not change the webpackChunkName or it will break the webpack nrba-chunking plugin
|
|
176
177
|
recorder = (await import(/* webpackChunkName: "recorder" */'rrweb')).record
|
|
177
178
|
} catch (err) {
|
|
178
179
|
return this.abort()
|
|
179
180
|
}
|
|
180
181
|
|
|
181
182
|
try {
|
|
183
|
+
// Do not change the webpackChunkName or it will break the webpack nrba-chunking plugin
|
|
182
184
|
const { gzipSync, strToU8 } = await import(/* webpackChunkName: "compressor" */'fflate')
|
|
183
185
|
gzipper = gzipSync
|
|
184
186
|
u8 = strToU8
|
|
@@ -8,7 +8,6 @@ import { parseUrl } from '../../../common/url/parse-url'
|
|
|
8
8
|
import { getConfigurationValue, getRuntime } from '../../../common/config/config'
|
|
9
9
|
import { now } from '../../../common/timing/now'
|
|
10
10
|
import { FEATURE_NAME } from '../constants'
|
|
11
|
-
import { drain } from '../../../common/drain/drain'
|
|
12
11
|
import { HandlerCache } from '../../utils/handler-cache'
|
|
13
12
|
import { MODE, SESSION_EVENTS } from '../../../common/session/session-entity'
|
|
14
13
|
import { getSessionReplayMode } from '../../session_replay/replay-mode'
|
|
@@ -50,9 +49,13 @@ export class Aggregate extends AggregateBase {
|
|
|
50
49
|
this.sentTrace = null
|
|
51
50
|
this.harvestTimeSeconds = getConfigurationValue(agentIdentifier, 'session_trace.harvestTimeSeconds') || 10
|
|
52
51
|
this.maxNodesPerHarvest = getConfigurationValue(agentIdentifier, 'session_trace.maxNodesPerHarvest') || 1000
|
|
52
|
+
/**
|
|
53
|
+
* Standalone (mode) refers to the legacy version of ST before the idea of 'session' or the Replay feature existed.
|
|
54
|
+
* It has some different behavior vs when used in tandem with replay. */
|
|
53
55
|
this.isStandalone = false
|
|
54
56
|
const operationalGate = new HandlerCache() // acts as a controller-intermediary that can enable or disable this feature's collection dynamically
|
|
55
57
|
const sessionEntity = this.agentRuntime.session
|
|
58
|
+
this.operationalGate = operationalGate
|
|
56
59
|
|
|
57
60
|
/* --- The following section deals with user sessions concept & contains non-trivial control flow. --- */
|
|
58
61
|
const controlTraceOp = (traceMode) => {
|
|
@@ -119,7 +122,7 @@ export class Aggregate extends AggregateBase {
|
|
|
119
122
|
else if (updatedTraceMode === MODE.FULL && this.#scheduler && !this.#scheduler.started) this.#scheduler.runHarvest({ needResponse: true })
|
|
120
123
|
mostRecentModeKnown = updatedTraceMode
|
|
121
124
|
})
|
|
122
|
-
this.ee.on(SESSION_EVENTS.PAUSE, () => mostRecentModeKnown = sessionEntity.state.sessionTraceMode)
|
|
125
|
+
this.ee.on(SESSION_EVENTS.PAUSE, () => { mostRecentModeKnown = sessionEntity.state.sessionTraceMode })
|
|
123
126
|
|
|
124
127
|
if (!sessionEntity.isNew) { // inherit the same mode as existing session's Trace
|
|
125
128
|
if (sessionEntity.state.sessionReplay === MODE.OFF) this.isStandalone = true
|
|
@@ -152,7 +155,7 @@ export class Aggregate extends AggregateBase {
|
|
|
152
155
|
registerHandler('bstApi', (...args) => operationalGate.settle(() => this.storeSTN(...args)), this.featureName, this.ee)
|
|
153
156
|
registerHandler('errorAgg', (...args) => operationalGate.settle(() => this.storeErrorAgg(...args)), this.featureName, this.ee)
|
|
154
157
|
registerHandler('pvtAdded', (...args) => operationalGate.settle(() => this.processPVT(...args)), this.featureName, this.ee)
|
|
155
|
-
drain(
|
|
158
|
+
this.drain()
|
|
156
159
|
}
|
|
157
160
|
|
|
158
161
|
startTracing (startupBuffer, dontStartHarvestYet = false) {
|
|
@@ -189,16 +192,16 @@ export class Aggregate extends AggregateBase {
|
|
|
189
192
|
}
|
|
190
193
|
|
|
191
194
|
#prepareHarvest (options) {
|
|
192
|
-
/* Standalone refers to the legacy version of ST before the idea of 'session' or the Replay feature existed.
|
|
193
|
-
It has a different behavior on returning a payload for harvest than when used in tandem with either of those concepts. */
|
|
194
195
|
if (this.isStandalone) {
|
|
195
|
-
if (now()
|
|
196
|
-
|
|
197
|
-
|
|
196
|
+
if (this.ptid && now() >= MAX_TRACE_DURATION) {
|
|
197
|
+
// Perform a final harvest once we hit or exceed the max session trace time
|
|
198
|
+
options.isFinalHarvest = true
|
|
199
|
+
this.operationalGate.permanentlyDecide(false)
|
|
200
|
+
this.#scheduler.stopTimer(true)
|
|
201
|
+
} else if (this.ptid && this.nodeCount <= REQ_THRESHOLD_TO_SEND && !options.isFinalHarvest) {
|
|
202
|
+
// Only harvest when more than some threshold of nodes are pending, after the very first harvest, with the exception of the last outgoing harvest.
|
|
198
203
|
return
|
|
199
204
|
}
|
|
200
|
-
// Only harvest when more than some threshold of nodes are pending, after the very first harvest.
|
|
201
|
-
if (this.ptid && this.nodeCount <= REQ_THRESHOLD_TO_SEND) return
|
|
202
205
|
} else {
|
|
203
206
|
// -- *cli May '26 - Update: Not rate limiting backgrounded pages either for now.
|
|
204
207
|
// if (this.ptid && document.visibilityState === 'hidden' && this.nodeCount <= REQ_THRESHOLD_TO_SEND) return
|
|
@@ -209,6 +212,7 @@ export class Aggregate extends AggregateBase {
|
|
|
209
212
|
if (currentMode === MODE.OFF && Object.keys(this.trace).length === 0) return
|
|
210
213
|
if (currentMode === MODE.ERROR) return // Trace in this mode should never be harvesting, even on unload
|
|
211
214
|
}
|
|
215
|
+
|
|
212
216
|
return this.takeSTNs(options.retry)
|
|
213
217
|
}
|
|
214
218
|
|
|
@@ -274,8 +278,7 @@ export class Aggregate extends AggregateBase {
|
|
|
274
278
|
const origin = this.evtOrigin(event.target, target)
|
|
275
279
|
if (event.type in ignoredEvents.global) return true
|
|
276
280
|
if (!!ignoredEvents[origin] && ignoredEvents[origin].ignoreAll) return true
|
|
277
|
-
|
|
278
|
-
return false
|
|
281
|
+
return !!(!!ignoredEvents[origin] && event.type in ignoredEvents[origin])
|
|
279
282
|
}
|
|
280
283
|
|
|
281
284
|
evtName (type) {
|
|
@@ -394,7 +397,11 @@ export class Aggregate extends AggregateBase {
|
|
|
394
397
|
if (this.nodeCount >= this.maxNodesPerHarvest) { // limit the amount of pending data awaiting next harvest
|
|
395
398
|
if (this.isStandalone || this.agentRuntime.session.state.sessionTraceMode !== MODE.ERROR) return
|
|
396
399
|
const openedSpace = this.trimSTNs(ERROR_MODE_SECONDS_WINDOW) // but maybe we could make some space by discarding irrelevant nodes if we're in sessioned Error mode
|
|
397
|
-
if (openedSpace
|
|
400
|
+
if (openedSpace === 0) return
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (this.isStandalone && now() >= MAX_TRACE_DURATION) {
|
|
404
|
+
return
|
|
398
405
|
}
|
|
399
406
|
|
|
400
407
|
if (this.trace[stn.n]) this.trace[stn.n].push(stn)
|
|
@@ -418,7 +425,7 @@ export class Aggregate extends AggregateBase {
|
|
|
418
425
|
* ASSUMPTION: all 'end' timings stored are relative to timeOrigin (DOMHighResTimeStamp) and not Unix epoch based. */
|
|
419
426
|
let cutoffIdx = nodeList.findIndex(node => cutoffHighResTime <= node.e)
|
|
420
427
|
|
|
421
|
-
if (cutoffIdx
|
|
428
|
+
if (cutoffIdx === 0) return
|
|
422
429
|
else if (cutoffIdx < 0) { // whole list falls outside lookback window and is irrelevant
|
|
423
430
|
cutoffIdx = nodeList.length
|
|
424
431
|
delete this.trace[nameCategory]
|
|
@@ -484,8 +491,7 @@ export class Aggregate extends AggregateBase {
|
|
|
484
491
|
|
|
485
492
|
function trivial (node) {
|
|
486
493
|
const limit = 4
|
|
487
|
-
|
|
488
|
-
else return false
|
|
494
|
+
return !!(node && typeof node.e === 'number' && typeof node.s === 'number' && (node.e - node.s) < limit)
|
|
489
495
|
}
|
|
490
496
|
}
|
|
491
497
|
}
|
|
@@ -17,7 +17,6 @@ import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
|
|
|
17
17
|
import { Serializer } from './serializer'
|
|
18
18
|
import { ee } from '../../../common/event-emitter/contextual-ee'
|
|
19
19
|
import * as CONSTANTS from '../constants'
|
|
20
|
-
import { drain } from '../../../common/drain/drain'
|
|
21
20
|
import { FEATURE_NAMES } from '../../../loaders/features/features'
|
|
22
21
|
import { AggregateBase } from '../../utils/aggregate-base'
|
|
23
22
|
|
|
@@ -122,8 +121,8 @@ export class Aggregate extends AggregateBase {
|
|
|
122
121
|
|
|
123
122
|
// register plugins
|
|
124
123
|
var pluginApi = {
|
|
125
|
-
getCurrentNode
|
|
126
|
-
setCurrentNode
|
|
124
|
+
getCurrentNode,
|
|
125
|
+
setCurrentNode
|
|
127
126
|
}
|
|
128
127
|
|
|
129
128
|
register('spa-register', function (init) {
|
|
@@ -197,23 +196,21 @@ export class Aggregate extends AggregateBase {
|
|
|
197
196
|
// If this event was emitted by an XHR, restore the node ID associated with
|
|
198
197
|
// that XHR.
|
|
199
198
|
setCurrentNode(baseEE.context(eventSource).spaNode)
|
|
200
|
-
} else if (!state.currentNode) {
|
|
199
|
+
} else if (!state.currentNode && INTERACTION_EVENTS.indexOf(evName) !== -1) {
|
|
201
200
|
// Otherwise, if no interaction is currently active, create a new node ID,
|
|
202
201
|
// and let the aggregator know that we entered a new event handler callback
|
|
203
202
|
// so that it has a chance to possibly start an interaction.
|
|
204
|
-
|
|
205
|
-
var ixn = new Interaction(evName, this[FN_START], state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier)
|
|
203
|
+
var ixn = new Interaction(evName, this[FN_START], state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier)
|
|
206
204
|
|
|
207
|
-
|
|
208
|
-
|
|
205
|
+
// Store the interaction as prevInteraction in case it is prematurely discarded
|
|
206
|
+
state.prevInteraction = ixn
|
|
209
207
|
|
|
210
|
-
|
|
208
|
+
setCurrentNode(ixn.root)
|
|
211
209
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}
|
|
210
|
+
if (evName === 'click') {
|
|
211
|
+
var value = getActionText(ev.target)
|
|
212
|
+
if (value) {
|
|
213
|
+
state.currentNode.attrs.custom.actionText = value
|
|
217
214
|
}
|
|
218
215
|
}
|
|
219
216
|
}
|
|
@@ -530,7 +527,7 @@ export class Aggregate extends AggregateBase {
|
|
|
530
527
|
register(INTERACTION_API + 'get', function (t) {
|
|
531
528
|
var interaction
|
|
532
529
|
if (state?.currentNode?.[INTERACTION]) interaction = this.ixn = state.currentNode[INTERACTION]
|
|
533
|
-
else if (state?.prevNode?.end === null && state?.prevNode?.[INTERACTION]?.root?.[INTERACTION]?.eventName
|
|
530
|
+
else if (state?.prevNode?.end === null && state?.prevNode?.[INTERACTION]?.root?.[INTERACTION]?.eventName !== 'initialPageLoad') interaction = this.ixn = state.prevNode[INTERACTION]
|
|
534
531
|
else interaction = this.ixn = new Interaction('api', t, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier)
|
|
535
532
|
if (!state.currentNode) {
|
|
536
533
|
interaction.checkFinish()
|
|
@@ -727,12 +724,9 @@ export class Aggregate extends AggregateBase {
|
|
|
727
724
|
|
|
728
725
|
function isEnabled () {
|
|
729
726
|
var enabled = getConfigurationValue(agentIdentifier, 'spa.enabled')
|
|
730
|
-
|
|
731
|
-
return false
|
|
732
|
-
}
|
|
733
|
-
return true
|
|
727
|
+
return enabled !== false
|
|
734
728
|
}
|
|
735
729
|
|
|
736
|
-
drain(
|
|
730
|
+
this.drain()
|
|
737
731
|
}
|
|
738
732
|
}
|
|
@@ -7,7 +7,6 @@ import { getInfo, getRuntime, originals } from '../../../common/config/config'
|
|
|
7
7
|
import { mapOwn } from '../../../common/util/map-own'
|
|
8
8
|
import { ee } from '../../../common/event-emitter/contextual-ee'
|
|
9
9
|
import { InteractionNode } from './interaction-node'
|
|
10
|
-
import { now } from '../../../common/timing/now'
|
|
11
10
|
|
|
12
11
|
var originalSetTimeout = originals.ST
|
|
13
12
|
var originalClearTimeout = originals.CT
|
|
@@ -95,7 +94,6 @@ InteractionPrototype.finish = function finishInteraction () {
|
|
|
95
94
|
var root = interaction.root
|
|
96
95
|
if (root.end !== null) return
|
|
97
96
|
var endTimestamp = Math.max(interaction.lastCb, interaction.lastFinish)
|
|
98
|
-
var delta = now() - endTimestamp
|
|
99
97
|
var attrs = root.attrs
|
|
100
98
|
var customAttrs = attrs.custom
|
|
101
99
|
|
|
@@ -176,7 +176,7 @@ export class Serializer extends SharedContext {
|
|
|
176
176
|
// (since its the same as interaction.start)
|
|
177
177
|
// and limit to just the first 20 values we know about
|
|
178
178
|
mapOwn(navTiming.slice(1, 21), function (i, v) {
|
|
179
|
-
if (v !==
|
|
179
|
+
if (v !== undefined) {
|
|
180
180
|
navTimingNode += seperator + numeric(v - prev)
|
|
181
181
|
seperator = ','
|
|
182
182
|
prev = v
|
|
@@ -3,6 +3,7 @@ import { FeatureBase } from './feature-base'
|
|
|
3
3
|
import { getInfo, isConfigured, getRuntime } from '../../common/config/config'
|
|
4
4
|
import { configure } from '../../loaders/configure/configure'
|
|
5
5
|
import { gosCDN } from '../../common/window/nreum'
|
|
6
|
+
import { drain } from '../../common/drain/drain'
|
|
6
7
|
|
|
7
8
|
export class AggregateBase extends FeatureBase {
|
|
8
9
|
constructor (...args) {
|
|
@@ -25,6 +26,10 @@ export class AggregateBase extends FeatureBase {
|
|
|
25
26
|
)
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
drain () {
|
|
30
|
+
drain(this.agentIdentifier, this.featureName)
|
|
31
|
+
}
|
|
32
|
+
|
|
28
33
|
/**
|
|
29
34
|
* Checks for additional `jsAttributes` items to support backward compatibility with implementations of the agent where
|
|
30
35
|
* loader configurations may appear after the loader code is executed.
|
|
@@ -31,7 +31,8 @@ jest.mock('../../loaders/configure/configure', () => ({
|
|
|
31
31
|
}))
|
|
32
32
|
jest.mock('../../common/window/nreum', () => ({
|
|
33
33
|
__esModule: true,
|
|
34
|
-
gosCDN: jest.fn().mockReturnValue({})
|
|
34
|
+
gosCDN: jest.fn().mockReturnValue({}),
|
|
35
|
+
gosNREUM: jest.fn().mockReturnValue({})
|
|
35
36
|
}))
|
|
36
37
|
|
|
37
38
|
let agentIdentifier
|
|
@@ -36,8 +36,9 @@ export class HandlerCache {
|
|
|
36
36
|
* @returns {void}
|
|
37
37
|
*/
|
|
38
38
|
settle (handler) {
|
|
39
|
-
if (this.#decision === false)
|
|
40
|
-
|
|
39
|
+
if (this.#decision === false) {
|
|
40
|
+
// Do nothing
|
|
41
|
+
} else if (this.#decision === undefined) this.#cache.push(handler)
|
|
41
42
|
else handler()
|
|
42
43
|
}
|
|
43
44
|
|
|
@@ -31,19 +31,24 @@ export class InstrumentBase extends FeatureBase {
|
|
|
31
31
|
this.auto = auto
|
|
32
32
|
|
|
33
33
|
/** @type {Function | undefined} This should be set by any derived Instrument class if it has things to do when feature fails or is killed. */
|
|
34
|
-
this.abortHandler
|
|
34
|
+
this.abortHandler = undefined
|
|
35
|
+
|
|
35
36
|
/**
|
|
36
37
|
* @type {Class} Holds the reference to the feature's aggregate module counterpart, if and after it has been initialized. This may not be assigned until after page loads!
|
|
37
38
|
* The only purpose of this for now is to expose it to the NREUM interface, as the feature's instrument instance is already exposed.
|
|
38
39
|
*/
|
|
39
|
-
this.featAggregate
|
|
40
|
+
this.featAggregate = undefined
|
|
41
|
+
|
|
40
42
|
/**
|
|
41
43
|
* @type {Promise} Assigned immediately after @see importAggregator runs. Serves as a signal for when the inner async fn finishes execution. Useful for features to await
|
|
42
44
|
* one another if there are inter-features dependencies.
|
|
43
45
|
*/
|
|
44
|
-
this.onAggregateImported
|
|
46
|
+
this.onAggregateImported = undefined
|
|
45
47
|
|
|
46
|
-
|
|
48
|
+
/** used in conjunction with newrelic.start() to defer harvesting in features */
|
|
49
|
+
if (getConfigurationValue(this.agentIdentifier, `${this.featureName}.autoStart`) === false) this.auto = false
|
|
50
|
+
/** if the feature requires opt-in (!auto-start), it will get registered once the api has been called */
|
|
51
|
+
if (this.auto) registerDrain(agentIdentifier, featureName)
|
|
47
52
|
}
|
|
48
53
|
|
|
49
54
|
/**
|
|
@@ -53,7 +58,21 @@ export class InstrumentBase extends FeatureBase {
|
|
|
53
58
|
* @returns void
|
|
54
59
|
*/
|
|
55
60
|
importAggregator (argsObjFromInstrument = {}) {
|
|
56
|
-
if (this.featAggregate
|
|
61
|
+
if (this.featAggregate) return
|
|
62
|
+
|
|
63
|
+
if (!this.auto) {
|
|
64
|
+
// this feature requires an opt in...
|
|
65
|
+
// wait for API to be called
|
|
66
|
+
this.ee.on(`${this.featureName}-opt-in`, () => {
|
|
67
|
+
// register the feature to drain only once the API has been called, it will drain when importAggregator finishes for all the features
|
|
68
|
+
// called by the api in that cycle
|
|
69
|
+
registerDrain(this.agentIdentifier, this.featureName)
|
|
70
|
+
this.auto = true
|
|
71
|
+
this.importAggregator()
|
|
72
|
+
})
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
|
|
57
76
|
const enableSessionTracking = isBrowserScope && getConfigurationValue(this.agentIdentifier, 'privacy.cookies_enabled') === true
|
|
58
77
|
let loadedSuccessfully
|
|
59
78
|
this.onAggregateImported = new Promise(resolve => {
|
|
@@ -72,7 +91,7 @@ export class InstrumentBase extends FeatureBase {
|
|
|
72
91
|
}
|
|
73
92
|
|
|
74
93
|
/**
|
|
75
|
-
* Note this try-catch differs from the one in Agent.
|
|
94
|
+
* Note this try-catch differs from the one in Agent.run() in that it's placed later in a page's lifecycle and
|
|
76
95
|
* it's only responsible for aborting its one specific feature, rather than all.
|
|
77
96
|
*/
|
|
78
97
|
try {
|
|
@@ -33,7 +33,7 @@ jest.mock('../../common/config/config', () => ({
|
|
|
33
33
|
}))
|
|
34
34
|
jest.mock('../../common/config/config', () => ({
|
|
35
35
|
__esModule: true,
|
|
36
|
-
getConfigurationValue: jest.fn(),
|
|
36
|
+
getConfigurationValue: jest.fn().mockReturnValue({}),
|
|
37
37
|
originals: {
|
|
38
38
|
MO: jest.fn()
|
|
39
39
|
}
|
|
@@ -79,7 +79,7 @@ test('should construct a new instrument', () => {
|
|
|
79
79
|
})
|
|
80
80
|
|
|
81
81
|
test('should not immediately drain', () => {
|
|
82
|
-
|
|
82
|
+
new InstrumentBase(agentIdentifier, aggregator, featureName, false)
|
|
83
83
|
|
|
84
84
|
expect(registerDrain).not.toHaveBeenCalled()
|
|
85
85
|
})
|