Skip to content

Commit

Permalink
✨ allow to not track views automatically
Browse files Browse the repository at this point in the history
WIP missing tests
  • Loading branch information
bcaudan committed Jun 1, 2021
1 parent 045a697 commit ca8a08a
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ describe('rum view referrer', () => {
initialViewCreatedEvent = event
subscription.unsubscribe()
})
return trackViews(location, lifeCycle)
return trackViews(location, lifeCycle, true)
})
createSpy = jasmine.createSpy('create')
})
Expand Down Expand Up @@ -128,7 +128,7 @@ describe('rum track renew session', () => {
initialViewId = id
subscription.unsubscribe()
})
return trackViews(location, lifeCycle)
return trackViews(location, lifeCycle, true)
})
})

Expand Down Expand Up @@ -171,7 +171,7 @@ describe('rum track loading type', () => {
.withFakeLocation('/foo')
.beforeBuild(({ location, lifeCycle }) => {
lifeCycle.subscribe(LifeCycleEventType.VIEW_UPDATED, handler)
return trackViews(location, lifeCycle)
return trackViews(location, lifeCycle, true)
})
})

Expand Down Expand Up @@ -207,7 +207,7 @@ describe('rum track view is active', () => {
.withFakeLocation('/foo')
.beforeBuild(({ location, lifeCycle }) => {
lifeCycle.subscribe(LifeCycleEventType.VIEW_UPDATED, handler)
return trackViews(location, lifeCycle)
return trackViews(location, lifeCycle, true)
})
})

Expand Down Expand Up @@ -247,7 +247,7 @@ describe('rum view timings', () => {
.withFakeLocation('/foo')
.beforeBuild(({ location, lifeCycle }) => {
lifeCycle.subscribe(LifeCycleEventType.VIEW_UPDATED, handler)
return trackViews(location, lifeCycle)
return trackViews(location, lifeCycle, true)
})
})

Expand Down Expand Up @@ -375,7 +375,7 @@ describe('rum track custom timings', () => {
.withFakeClock()
.beforeBuild(({ location, lifeCycle }) => {
lifeCycle.subscribe(LifeCycleEventType.VIEW_UPDATED, handler)
;({ addTiming } = trackViews(location, lifeCycle))
;({ addTiming } = trackViews(location, lifeCycle, true))
})
})

Expand Down Expand Up @@ -472,7 +472,7 @@ describe('track hasReplay', () => {
.withFakeClock()
.beforeBuild(({ location, lifeCycle }) => {
lifeCycle.subscribe(LifeCycleEventType.VIEW_UPDATED, handler)
return trackViews(location, lifeCycle)
return trackViews(location, lifeCycle, true)
})
})

Expand Down Expand Up @@ -540,7 +540,7 @@ describe('rum start view', () => {

setupBuilder = setup().beforeBuild(({ location, lifeCycle }) => {
lifeCycle.subscribe(LifeCycleEventType.VIEW_UPDATED, handler)
;({ startView } = trackViews(location, lifeCycle))
;({ startView } = trackViews(location, lifeCycle, true))
})
})

Expand Down
137 changes: 83 additions & 54 deletions packages/rum-core/src/domain/rumEventsCollection/view/trackViews.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,62 +53,43 @@ export interface ViewEndedEvent {
export const THROTTLE_VIEW_UPDATE_PERIOD = 3000
export const SESSION_KEEP_ALIVE_INTERVAL = 5 * ONE_MINUTE

export function trackViews(location: Location, lifeCycle: LifeCycle) {
type View = ReturnType<typeof newView>

export function trackViews(location: Location, lifeCycle: LifeCycle, areViewsTrackedAutomatically: boolean) {
let isRecording = false
let hasInitialView = false
let currentView: View
let stopInitialViewTracking: () => void
let stopViewLifeCycle: () => void
let stopLocationChangesTracking: (() => void) | undefined

// eslint-disable-next-line prefer-const
let { stop: stopInitialViewTracking, initialView: currentView } = trackInitialView()
const { stop: stopLocationChangesTracking } = trackLocationChanges(() => {
if (areDifferentLocation(currentView.getLocation(), location)) {
// Renew view on location changes
currentView.end()
currentView.triggerUpdate()
currentView = trackViewChange()
return
}
currentView.updateLocation(location)
currentView.triggerUpdate()
})

// Renew view on session renewal
lifeCycle.subscribe(LifeCycleEventType.SESSION_RENEWED, () => {
// do not trigger view update to avoid wrong data
currentView.end()
currentView = trackViewChange()
})

// End the current view on page unload
lifeCycle.subscribe(LifeCycleEventType.BEFORE_UNLOAD, () => {
currentView.end()
currentView.triggerUpdate()
})

lifeCycle.subscribe(LifeCycleEventType.RECORD_STARTED, () => {
isRecording = true
currentView.updateHasReplay(true)
})

lifeCycle.subscribe(LifeCycleEventType.RECORD_STOPPED, () => {
isRecording = false
})

// Session keep alive
const keepAliveInterval = window.setInterval(
monitor(() => {
if (areViewsTrackedAutomatically) {
;({ stop: stopInitialViewTracking, initialView: currentView } = trackInitialView())
;({ stop: stopViewLifeCycle } = startViewLifeCycle())
;({ stop: stopLocationChangesTracking } = trackLocationChanges(() => {
if (areDifferentLocation(currentView.getLocation(), location)) {
// Renew view on location changes
currentView.end()
currentView.triggerUpdate()
currentView = trackViewChange()
return
}
currentView.updateLocation(location)
currentView.triggerUpdate()
}),
SESSION_KEEP_ALIVE_INTERVAL
)
}))
}

function trackInitialView() {
function trackInitialView(name?: string) {
const initialView = newView(
lifeCycle,
location,
isRecording,
ViewLoadingType.INITIAL_LOAD,
document.referrer,
clocksOrigin()
clocksOrigin(),
name
)
hasInitialView = true
const { stop } = trackInitialViewTimings(lifeCycle, (timings) => {
initialView.updateTimings(timings)
initialView.scheduleUpdate()
Expand All @@ -120,21 +101,69 @@ export function trackViews(location: Location, lifeCycle: LifeCycle) {
return newView(lifeCycle, location, isRecording, ViewLoadingType.ROUTE_CHANGE, currentView.url, startClocks, name)
}

function startViewLifeCycle() {
lifeCycle.subscribe(LifeCycleEventType.SESSION_RENEWED, () => {
// do not trigger view update to avoid wrong data
currentView.end()
if (areViewsTrackedAutomatically) {
// Renew view on session renewal
currentView = trackViewChange()
}
})

// End the current view on page unload
lifeCycle.subscribe(LifeCycleEventType.BEFORE_UNLOAD, () => {
currentView.end()
currentView.triggerUpdate()
})

lifeCycle.subscribe(LifeCycleEventType.RECORD_STARTED, () => {
isRecording = true
currentView.updateHasReplay(true)
})

lifeCycle.subscribe(LifeCycleEventType.RECORD_STOPPED, () => {
isRecording = false
})

// Session keep alive
const keepAliveInterval = window.setInterval(
monitor(() => {
currentView.triggerUpdate()
}),
SESSION_KEEP_ALIVE_INTERVAL
)
return {
stop: () => {
clearInterval(keepAliveInterval)
},
}
}

return {
addTiming: (name: string, time = timeStampNow()) => {
currentView.addTiming(name, time)
currentView.triggerUpdate()
if (hasInitialView) {
currentView.addTiming(name, time)
currentView.triggerUpdate()
}
},
startView: (name?: string, startClocks?: ClocksState) => {
currentView.end(startClocks)
currentView.triggerUpdate()
currentView = trackViewChange(startClocks, name)
if (!hasInitialView) {
;({ stop: stopInitialViewTracking, initialView: currentView } = trackInitialView(name))
;({ stop: stopViewLifeCycle } = startViewLifeCycle())
} else {
currentView.end(startClocks)
currentView.triggerUpdate()
currentView = trackViewChange(startClocks, name)
}
},
stop: () => {
stopInitialViewTracking()
stopLocationChangesTracking()
currentView.end()
clearInterval(keepAliveInterval)
stopLocationChangesTracking && stopLocationChangesTracking()
if (hasInitialView) {
stopInitialViewTracking()
stopViewLifeCycle()
currentView.end()
}
},
}
}
Expand Down

0 comments on commit ca8a08a

Please sign in to comment.