Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Soft Navigations trial #808

Merged
merged 114 commits into from
Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
c31d1ad
bones in place
metal-messiah Jul 21, 2023
c6d577d
progress decorating other events
metal-messiah Jul 24, 2023
17a0811
remove unused bit
metal-messiah Jul 25, 2023
90cc7a0
minor cleanup
metal-messiah Jul 25, 2023
49fa39a
add interaction id to errors in aggregator
metal-messiah Jul 25, 2023
cd6730a
hold from sending if interaction is in progress
metal-messiah Jul 25, 2023
31888aa
minor clean up
metal-messiah Jul 25, 2023
d6f9fd4
route changes create ixns
metal-messiah Jul 25, 2023
549a139
add harvesting and minor cleanup
metal-messiah Jul 26, 2023
f1f22dc
add better handling
metal-messiah Jul 26, 2023
1344f3c
use dom update and paint cycle to determine ixn end
metal-messiah Aug 1, 2023
7e37dbd
merge with main
metal-messiah Aug 1, 2023
2a678cb
set querypack back to main branch
metal-messiah Aug 1, 2023
16ec88c
compare side-by-side
metal-messiah Aug 7, 2023
ec0949f
merge with main
metal-messiah Sep 7, 2023
998404d
fix merge conflict
metal-messiah Sep 7, 2023
4aff4db
fix merge conflicts
metal-messiah Sep 7, 2023
e63f05f
remove console logs before publishing experiment
metal-messiah Sep 7, 2023
694040c
add console logging
metal-messiah Sep 7, 2023
73b7895
temporarily place in spa loader for experiment, revert when CI change…
metal-messiah Sep 7, 2023
3744536
try setting callbackEnd to end
metal-messiah Sep 8, 2023
66072f0
fix drain typo
metal-messiah Sep 8, 2023
cfb0239
try adding ajax children
metal-messiah Sep 8, 2023
4682da1
add logging
metal-messiah Sep 8, 2023
7aede1e
allow interaction to end itself after 30s
metal-messiah Sep 8, 2023
9dc2294
refining behavior -- adjusting timestamps
metal-messiah Sep 8, 2023
8e7de0e
try to fix metadata initial page load
metal-messiah Sep 8, 2023
f414835
try fixing timestamps
metal-messiah Sep 9, 2023
b3d01b0
add metadata on when needed
metal-messiah Sep 9, 2023
4ce4409
isolate metadata
metal-messiah Sep 9, 2023
ac12f93
messing with ajax passing
metal-messiah Sep 11, 2023
00b28f3
basic cleanup work
metal-messiah Sep 11, 2023
3467200
capture interactions after evaluating tti
metal-messiah Sep 11, 2023
b18910d
save
metal-messiah Sep 12, 2023
9f6b02f
timeToInteractive module
metal-messiah Sep 12, 2023
f9c82e2
cbduration
metal-messiah Sep 12, 2023
ea10a49
clean up invalid children
metal-messiah Sep 13, 2023
60d22f4
refinements
metal-messiah Sep 13, 2023
87be003
merge main
metal-messiah Sep 13, 2023
5928384
move promise out of constructor and cancel tti if node cancels
metal-messiah Sep 13, 2023
45f8401
also clear tti timeout
metal-messiah Sep 13, 2023
c09ee6e
Merge commit 'c919abbefc63969cc106bf3d5a51db2a2fbc6501' into basic-sp…
cwli24 Oct 19, 2023
740a148
Revert aggregator change
cwli24 Oct 19, 2023
f1ade41
Revert bel-serializer addCustomAttributes
cwli24 Oct 21, 2023
56079f6
Remove time to interactive
cwli24 Oct 21, 2023
65c73c4
Rename basic spa to soft nav
cwli24 Oct 22, 2023
5d14965
Replace initializedagents entries with the agent class itself
cwli24 Oct 23, 2023
cd7dc86
Fix alreadySetOnce logic
cwli24 Oct 23, 2023
7e4fc9d
Merge commit 'cd7dc8641c1b29c07062cfa0d80e85a5b84c0b21' into basic-sp…
cwli24 Oct 23, 2023
81cdfa2
pr comments
cwli24 Oct 24, 2023
f37a784
Fix tests
cwli24 Oct 24, 2023
3d1951d
Fix unit tests
cwli24 Oct 24, 2023
00c744c
Merge commit 'e0e2af6e19c58f2e71d49d2871f832924c1deb89' into rewire-i…
cwli24 Oct 24, 2023
cd7644f
fix unit test setup for real
cwli24 Oct 24, 2023
8806631
Merge branch 'rewire-initializedagents' into basic-spa-poc
cwli24 Oct 24, 2023
253beaa
Determine which spa to turn on
cwli24 Oct 25, 2023
19de096
Update ajax for both spa
cwli24 Oct 27, 2023
846a0b3
Split gosNREUMinitializedagents into getter & setter
cwli24 Oct 27, 2023
b5aa83a
Merge commit '846a0b36427275ac22595be96cba437b573ecb9e' into basic-sp…
cwli24 Oct 27, 2023
a6879ff
Combine spa interactionSaved and interactionDiscarded events
cwli24 Oct 31, 2023
14a46f0
Trim set custom attributes on error data
cwli24 Oct 31, 2023
9f31926
Add soft nav consideration into jserror
cwli24 Oct 31, 2023
c8f448a
Rename constants
cwli24 Nov 1, 2023
0ee6f74
Mod soft nav instrument
cwli24 Nov 2, 2023
2ff8600
initialpageload audit
cwli24 Nov 3, 2023
19d88c6
Audit Interaction class and serialization
cwli24 Nov 6, 2023
b2f3627
belnode audit
cwli24 Nov 6, 2023
f3f6daf
audit ajax node & nested serialize
cwli24 Nov 7, 2023
da143d6
Mod soft nav aggregate
cwli24 Nov 8, 2023
f4f21d6
link ajax and soft nav data flow
cwli24 Nov 8, 2023
d6ac7f0
Fix returnAjax event
cwli24 Nov 8, 2023
d975e4d
link jserror and soft nav data flow
cwli24 Nov 9, 2023
8ec820e
Fix soft nav imported without feat flag
cwli24 Nov 9, 2023
a18faee
Fix serialization string & other issues
cwli24 Nov 9, 2023
77ce8be
Fix illegal invoc for RAF
cwli24 Nov 9, 2023
77b0d2c
Change harvest to wait for flag
cwli24 Nov 10, 2023
d87f5d3
Fixed route change ixn fail harvest
cwli24 Nov 10, 2023
03b7582
Fix var typo & ajax node creation
cwli24 Nov 10, 2023
3243e55
Merge branch 'main' into basic-spa-feat
patrickhousley Nov 15, 2023
2d4e8ea
Setup first interaction() / get()
cwli24 Nov 28, 2023
1639231
Add .save, .ignore, and integrate api-started ixn
cwli24 Dec 1, 2023
fe8e38b
Add .end and customEnd node
cwli24 Dec 4, 2023
bc6ec8b
Add .getContext, .onEnd, and .setCurrentRouteName
cwli24 Dec 4, 2023
c4df477
Add .setName & .setAttribute
cwli24 Dec 6, 2023
e222ffe
Add .actionText
cwli24 Dec 6, 2023
da4d117
Exclude .createTracer support
cwli24 Dec 7, 2023
b410d9e
Include a keepOpen functionality to .interaction and .end
cwli24 Dec 8, 2023
173bfec
Fixing some typo issues
cwli24 Dec 9, 2023
9ecd7c3
Remove customEnd node redundant
cwli24 Dec 9, 2023
da372b8
Fix api test cases
cwli24 Dec 13, 2023
68f1722
Fix ixn finish time & child length, reduce dom spam
cwli24 Dec 18, 2023
21cb3b9
Unit tests
cwli24 Dec 26, 2023
ffab888
Data correctness bug fixes & partial component tests
cwli24 Dec 30, 2023
0098410
Remaining api jest tests
cwli24 Jan 3, 2024
6ef8b9d
Wdio tests, chrome & edge pass
cwli24 Jan 5, 2024
d0d70c2
PR comment, firefox pass too
cwli24 Jan 5, 2024
12b54ea
Merge commit 'cb23dbd0705df7928bbea21ac3e905b6a254b4da' into basic-sp…
cwli24 Jan 5, 2024
c18c74e
Add sm for softnav
cwli24 Jan 9, 2024
0b4fcdd
Fix wdio for safari and IE, all passing
cwli24 Jan 16, 2024
9843f58
Include softnav feat flag in experiment
cwli24 Jan 19, 2024
db8b53b
Remove wrap-raf that's no longer used
cwli24 Jan 19, 2024
9747b66
PR comment changes
cwli24 Jan 20, 2024
3ea95c5
Add expect in .end test for domObserver to be disconnected
cwli24 Jan 20, 2024
5f3a3a3
remove main on publish experiment step2
cwli24 Jan 24, 2024
466bdcc
remove RAF from originals
cwli24 Jan 24, 2024
921165a
Merge branch 'main' into basic-spa-feat
cwli24 Jan 26, 2024
d521684
Merge remote-tracking branch 'nr-root/main' into basic-spa-feat
cwli24 Jan 30, 2024
b04f3c7
Fix typo bug for old spa found via ajax-events.browser.js
cwli24 Jan 30, 2024
f21f20c
domobserver only observe body
cwli24 Feb 1, 2024
282e938
Add soft_nav ff to latest template
cwli24 Feb 1, 2024
98ba1cd
add no op listeners to ui events
cwli24 Feb 2, 2024
84cad92
Include ipl when fetching ixn for .interaction()
cwli24 Feb 2, 2024
3dac1f7
Merge branch 'main' into basic-spa-feat
cwli24 Mar 12, 2024
7b995d2
bc IE sucks
cwli24 Mar 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/build-ab/templates/latest.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ window.NREUM.loader_config.licenseKey = '{{{args.abLicenseKey}}}'
window.NREUM.info.applicationID = '{{{args.abAppId}}}'
window.NREUM.info.licenseKey = '{{{args.abLicenseKey}}}'
window.NREUM.init.proxy.assets = 'https://staging-js-agent.newrelic.com/dev'
window.NREUM.init.feature_flags = ['ajax_metrics_deny_list']
window.NREUM.init.feature_flags = ['soft_nav','ajax_metrics_deny_list']

{{{latestScript}}}
2 changes: 0 additions & 2 deletions .github/workflows/publish-experiment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ jobs:
shell: bash
steps:
- uses: actions/checkout@v3
with:
ref: main
- uses: actions/setup-node@v3
with:
node-version: lts/*
Expand Down
6 changes: 4 additions & 2 deletions src/cdn/experimental.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import { Instrument as InstrumentErrors } from '../features/jserrors/instrument'
import { Instrument as InstrumentXhr } from '../features/ajax/instrument'
import { Instrument as InstrumentSessionTrace } from '../features/session_trace/instrument'
import { Instrument as InstrumentSessionReplay } from '../features/session_replay/instrument'
import { Instrument as InstrumentSpa } from '../features/spa/instrument'
// import { Instrument as InstrumentSpa } from '../features/spa/instrument'
import { Instrument as InstrumentSoftNav } from '../features/soft_navigations/instrument'
import { Instrument as InstrumentPageAction } from '../features/page_action/instrument'

new Agent({
Expand All @@ -30,7 +31,8 @@ new Agent({
InstrumentMetrics,
InstrumentPageAction,
InstrumentErrors,
InstrumentSpa
// InstrumentSpa,
InstrumentSoftNav
],
loaderType: 'experimental'
})
4 changes: 3 additions & 1 deletion src/cdn/spa.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Instrument as InstrumentErrors } from '../features/jserrors/instrument'
import { Instrument as InstrumentXhr } from '../features/ajax/instrument'
import { Instrument as InstrumentSessionTrace } from '../features/session_trace/instrument'
import { Instrument as InstrumentSessionReplay } from '../features/session_replay/instrument'
import { Instrument as InstrumentSoftNav } from '../features/soft_navigations/instrument'
import { Instrument as InstrumentSpa } from '../features/spa/instrument'
import { Instrument as InstrumentPageAction } from '../features/page_action/instrument'

Expand All @@ -24,7 +25,8 @@ new Agent({
InstrumentMetrics,
InstrumentPageAction,
InstrumentErrors,
InstrumentSpa
InstrumentSoftNav,
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
],
loaderType: 'spa'
})
13 changes: 2 additions & 11 deletions src/common/aggregate/aggregator.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ export class Aggregator extends SharedContext {
var hasData = false
for (var i = 0; i < types.length; i++) {
type = types[i]
results[type] = toArray(this.aggregatedData[type])
results[type] = Object.values(this.aggregatedData[type] || {})

if (results[type].length) hasData = true
delete this.aggregatedData[type]
}
Expand Down Expand Up @@ -159,13 +160,3 @@ function createMetricObject (value) {
c: 1
}
}

function toArray (obj) {
if (typeof obj !== 'object') return []

return mapOwn(obj, getValue)
}

function getValue (key, value) {
return value
}
3 changes: 2 additions & 1 deletion src/common/config/state/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ const model = () => {
else warn('An invalid session_replay.mask_input_option was provided and will not be used', val)
}
},
spa: { enabled: true, harvestTimeSeconds: 10, autoStart: true }
spa: { enabled: true, harvestTimeSeconds: 10, autoStart: true },
soft_navigations: { enabled: true, harvestTimeSeconds: 10, autoStart: true }
}
}

Expand Down
10 changes: 7 additions & 3 deletions src/common/timing/nav-timing.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var RESPONSE = 'response'
var LOAD_EVENT = 'loadEvent'
var DOM_CONTENT_LOAD_EVENT = 'domContentLoadedEvent'

export var navTimingValues = []
export const navTimingValues = []

function getPntType (type) {
if (typeof type === 'number') return type
Expand Down Expand Up @@ -72,6 +72,10 @@ export function addPN (pn, v) {
return v
}

/**
* By side effect, this modifies 'obj' with a mapping of the 'prop' provided to a 'value', and invalid values are not added.
* On the other hand, the local navTimingValues array gets the value appended if valid and 'undefined' appended if invalid, regardless.
*/
function handleValue (value, obj, prop, isOldApi) {
/*
For L2 Timing API, the value will already be a relative-to-previous-document DOMHighResTimeStamp.
Expand All @@ -85,6 +89,6 @@ function handleValue (value, obj, prop, isOldApi) {
}
value = Math.round(value)
obj[prop] = value
}
navTimingValues.push(value)
navTimingValues.push(value)
} else navTimingValues.push(undefined)
}
2 changes: 1 addition & 1 deletion src/common/timing/now.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@

// This is our own layer around performance.now. It's not strictly necessary, but we keep it in case of future mod-ing of the value for refactor purpose.
export function now () {
return Math.round(performance.now())
return Math.floor(performance.now())
}
2 changes: 1 addition & 1 deletion src/common/util/feature-flags.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const bucketMap = {
stn: [FEATURE_NAMES.sessionTrace],
err: [FEATURE_NAMES.jserrors, FEATURE_NAMES.metrics],
ins: [FEATURE_NAMES.pageAction],
spa: [FEATURE_NAMES.spa],
spa: [FEATURE_NAMES.spa, FEATURE_NAMES.softNav],
sr: [FEATURE_NAMES.sessionReplay, FEATURE_NAMES.sessionTrace]
}

Expand Down
8 changes: 4 additions & 4 deletions src/common/util/feature-flags.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ test('emits the right events when feature flag = 1', () => {

const sharedEE = jest.mocked(eventEmitterModule.ee.get).mock.results[0].value

// each flag gets emitted to each of its mapped features, and a feat- AND a rumresp- for every emit, so (1+2+1+1+2)*2 = 14
expect(handleModule.handle).toHaveBeenCalledTimes(14)
// each flag gets emitted to each of its mapped features, and a feat- AND a rumresp- for every emit, so (1+2+1+1+2+2)*2 = 16
expect(handleModule.handle).toHaveBeenCalledTimes(16)
expect(handleModule.handle).toHaveBeenNthCalledWith(1, 'feat-stn', [], undefined, FEATURE_NAMES.sessionTrace, sharedEE)
expect(handleModule.handle).toHaveBeenLastCalledWith('rumresp-sr', [true], undefined, FEATURE_NAMES.sessionTrace, sharedEE)

Expand All @@ -65,8 +65,8 @@ test('emits the right events when feature flag = 0', () => {

const sharedEE = jest.mocked(eventEmitterModule.ee.get).mock.results[0].value

// each flag gets emitted to each of its mapped features, and a block- AND a rumresp- for every emit, so (1+2+1+1+2)*2 = 14
expect(handleModule.handle).toHaveBeenCalledTimes(14)
// each flag gets emitted to each of its mapped features, and a block- AND a rumresp- for every emit, so (1+2+1+1+2+2)*2 = 16
expect(handleModule.handle).toHaveBeenCalledTimes(16)
expect(handleModule.handle).toHaveBeenNthCalledWith(1, 'block-stn', [], undefined, FEATURE_NAMES.sessionTrace, sharedEE)
expect(handleModule.handle).toHaveBeenLastCalledWith('rumresp-sr', [false], undefined, FEATURE_NAMES.sessionTrace, sharedEE)

Expand Down
3 changes: 1 addition & 2 deletions src/common/wrap/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ import { wrapHistory } from './wrap-history'
import { wrapJsonP } from './wrap-jsonp'
import { wrapMutation } from './wrap-mutation'
import { wrapPromise } from './wrap-promise'
import { wrapRaf } from './wrap-raf'
import { wrapTimer } from './wrap-timer'
import { wrapXhr } from './wrap-xhr'

export {
wrapEvents, wrapFetch, wrapHistory, wrapJsonP, wrapMutation, wrapPromise, wrapRaf, wrapTimer, wrapXhr
wrapEvents, wrapFetch, wrapHistory, wrapJsonP, wrapMutation, wrapPromise, wrapTimer, wrapXhr
}
52 changes: 0 additions & 52 deletions src/common/wrap/wrap-raf.js

This file was deleted.

37 changes: 21 additions & 16 deletions src/features/ajax/aggregate/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright 2020 New Relic Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/
import { registerHandler as register } from '../../../common/event-emitter/register-handler'
import { registerHandler } from '../../../common/event-emitter/register-handler'
import { stringify } from '../../../common/util/stringify'
import { nullable, numeric, getAddStringContext, addCustomAttributes } from '../../../common/serialize/bel-serializer'
import { handle } from '../../../common/event-emitter/handle'
Expand All @@ -14,6 +14,7 @@
import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants'
import { AggregateBase } from '../../utils/aggregate-base'
import { parseGQL } from './gql'
import { getNREUMInitializedAgent } from '../../../common/window/nreum'

export class Aggregate extends AggregateBase {
static featureName = FEATURE_NAME
Expand All @@ -22,7 +23,7 @@
const agentInit = getConfiguration(agentIdentifier)
const allAjaxIsEnabled = agentInit.ajax.enabled !== false

register('xhr', storeXhr, this.featureName, this.ee)
registerHandler('xhr', storeXhr, this.featureName, this.ee)

Check warning on line 26 in src/features/ajax/aggregate/index.js

View check run for this annotation

Codecov / codecov/patch

src/features/ajax/aggregate/index.js#L26

Added line #L26 was not covered by tests
if (!allAjaxIsEnabled) {
this.drain()
return // feature will only collect timeslice metrics & ajax trace nodes if it's not fully enabled
Expand All @@ -44,20 +45,21 @@
this.prepareHarvest = prepareHarvest
this.getStoredEvents = function () { return { ajaxEvents, spaAjaxEvents } }

ee.on('interactionSaved', (interaction) => {
if (!spaAjaxEvents[interaction.id]) return
// remove from the spaAjaxEvents buffer, and let spa harvest it
delete spaAjaxEvents[interaction.id]
})
ee.on('interactionDiscarded', (interaction) => {
// --- v Used by old spa feature
ee.on('interactionDone', (interaction, wasSaved) => {
if (!spaAjaxEvents[interaction.id]) return

spaAjaxEvents[interaction.id].forEach(function (item) {
// move it from the spaAjaxEvents buffer to the ajaxEvents buffer for harvesting here
ajaxEvents.push(item)
})
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
spaAjaxEvents[interaction.id].forEach(function (item) {
ajaxEvents.push(item)
})
}
delete spaAjaxEvents[interaction.id]
})
// --- ^
// --- v Used by new soft nav
registerHandler('returnAjax', event => ajaxEvents.push(event), this.featureName, this.ee)
// --- ^

const scheduler = new HarvestScheduler('events', {
onFinished: onEventsHarvestFinished,
Expand Down Expand Up @@ -138,12 +140,14 @@
body: this.body,
query: this?.parsedOrigin?.search
})

if (event.gql) handle(SUPPORTABILITY_METRIC_CHANNEL, ['Ajax/Events/GraphQL/Bytes-Added', stringify(event.gql).length], undefined, FEATURE_NAMES.metrics, ee)

// if the ajax happened inside an interaction, hold it until the interaction finishes
if (this.spaNode) {
var interactionId = this.spaNode.interaction.id
const softNavInUse = Boolean(getNREUMInitializedAgent(agentIdentifier)?.features?.[FEATURE_NAMES.softNav])

Check warning on line 145 in src/features/ajax/aggregate/index.js

View check run for this annotation

Codecov / codecov/patch

src/features/ajax/aggregate/index.js#L145

Added line #L145 was not covered by tests

if (softNavInUse) { // For newer soft nav (when running), pass the event to it for evaluation -- either part of an interaction or is given back
handle('ajax', [event], undefined, FEATURE_NAMES.softNav, ee)
} else if (this.spaNode) { // For old spa (when running), if the ajax happened inside an interaction, hold it until the interaction finishes
const interactionId = this.spaNode.interaction.id

Check warning on line 150 in src/features/ajax/aggregate/index.js

View check run for this annotation

Codecov / codecov/patch

src/features/ajax/aggregate/index.js#L150

Added line #L150 was not covered by tests
spaAjaxEvents[interactionId] = spaAjaxEvents[interactionId] || []
spaAjaxEvents[interactionId].push(event)
} else {
Expand Down Expand Up @@ -222,6 +226,7 @@

for (var i = 0; i < events.length; i++) {
var event = events[i]

var fields = [
numeric(event.startTime),
numeric(event.endTime - event.startTime),
Expand Down
Loading
Loading