Skip to content

Commit

Permalink
[RUM] use a lifeCycle event for document unload
Browse files Browse the repository at this point in the history
This change is a first step to decouple the view logic from the Batch
implementation.
  • Loading branch information
BenoitZugmeyer committed Apr 17, 2020
1 parent 61429be commit 96be7d4
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 18 deletions.
12 changes: 4 additions & 8 deletions packages/core/src/transport.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import lodashMerge from 'lodash.merge'

import { monitor } from './internalMonitoring'
import { Context, DOM_EVENT, jsonStringify, objectValues } from './utils'
import { Context, DOM_EVENT, jsonStringify, noop, objectValues } from './utils'

/**
* Use POST request without content type to:
Expand Down Expand Up @@ -45,7 +45,8 @@ export class Batch<T> {
private bytesLimit: number,
private maxMessageSize: number,
private flushTimeout: number,
private contextProvider: () => Context
private contextProvider: () => Context,
private willUnloadCallback: () => void = noop
) {
this.flushOnVisibilityHidden()
this.flushPeriodically()
Expand Down Expand Up @@ -160,12 +161,7 @@ export class Batch<T> {
* register first to be sure to be called before flush on beforeunload
* caveat: unload can still be canceled by another listener
*/
window.addEventListener(
DOM_EVENT.BEFORE_UNLOAD,
monitor(() => {
this.beforeFlushOnUnloadHandlers.forEach((handler) => handler())
})
)
window.addEventListener(DOM_EVENT.BEFORE_UNLOAD, monitor(this.willUnloadCallback))

/**
* Only event that guarantee to fire on mobile devices when the page transitions to background state
Expand Down
5 changes: 4 additions & 1 deletion packages/rum/src/lifeCycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export enum LifeCycleEventType {
SESSION_RENEWED,
RESOURCE_ADDED_TO_BATCH,
DOM_MUTATED,
WILL_UNLOAD,
}

export interface Subscription {
Expand All @@ -31,6 +32,7 @@ export class LifeCycle {
| LifeCycleEventType.SESSION_RENEWED
| LifeCycleEventType.RESOURCE_ADDED_TO_BATCH
| LifeCycleEventType.DOM_MUTATED
| LifeCycleEventType.WILL_UNLOAD
): void
notify(eventType: LifeCycleEventType, data?: any) {
const eventCallbacks = this.callbacks[eventType]
Expand All @@ -55,7 +57,8 @@ export class LifeCycle {
| LifeCycleEventType.SESSION_WILL_RENEW
| LifeCycleEventType.SESSION_RENEWED
| LifeCycleEventType.RESOURCE_ADDED_TO_BATCH
| LifeCycleEventType.DOM_MUTATED,
| LifeCycleEventType.DOM_MUTATED
| LifeCycleEventType.WILL_UNLOAD,
callback: () => void
): Subscription
subscribe(eventType: LifeCycleEventType, callback: (data?: any) => void) {
Expand Down
12 changes: 7 additions & 5 deletions packages/rum/src/rum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,11 @@ export function startRum(
url: viewContext.location.href,
},
}),
() => globalContext
() => globalContext,
() => lifeCycle.notify(LifeCycleEventType.WILL_UNLOAD)
)

trackView(window.location, lifeCycle, batch.upsertRumEvent, batch.beforeFlushOnUnload)
trackView(window.location, lifeCycle, batch.upsertRumEvent)
trackErrors(lifeCycle, batch.addRumEvent)
trackRequests(configuration, lifeCycle, session, batch.addRumEvent)
trackPerformanceTiming(configuration, lifeCycle, batch.addRumEvent)
Expand Down Expand Up @@ -221,23 +222,24 @@ function startRumBatch(
configuration: Configuration,
session: RumSession,
rumContextProvider: () => Context,
globalContextProvider: () => Context
globalContextProvider: () => Context,
willUnloadCallback: () => void
) {
const batch = new Batch<Context>(
new HttpRequest(configuration.rumEndpoint, configuration.batchBytesLimit, true),
configuration.maxBatchSize,
configuration.batchBytesLimit,
configuration.maxMessageSize,
configuration.flushTimeout,
() => lodashMerge(withSnakeCaseKeys(rumContextProvider()), globalContextProvider())
() => lodashMerge(withSnakeCaseKeys(rumContextProvider()), globalContextProvider()),
willUnloadCallback
)
return {
addRumEvent: (event: RumEvent, context?: Context) => {
if (session.isTracked()) {
batch.add({ ...context, ...withSnakeCaseKeys((event as unknown) as Context) })
}
},
beforeFlushOnUnload: (handler: () => void) => batch.beforeFlushOnUnload(handler),
upsertRumEvent: (event: RumEvent, key: string) => {
if (session.isTracked()) {
batch.upsert(withSnakeCaseKeys((event as unknown) as Context), key)
Expand Down
5 changes: 2 additions & 3 deletions packages/rum/src/viewCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ let viewMeasures: ViewMeasures
export function trackView(
location: Location,
lifeCycle: LifeCycle,
upsertRumEvent: (event: RumEvent, key: string) => void,
beforeFlushOnUnload: (handler: () => void) => void
upsertRumEvent: (event: RumEvent, key: string) => void
) {
const scheduleViewUpdate = throttle(monitor(() => updateView(upsertRumEvent)), THROTTLE_VIEW_UPDATE_PERIOD, {
leading: false,
Expand All @@ -47,7 +46,7 @@ export function trackView(
trackTimings(lifeCycle, scheduleViewUpdate)
trackRenewSession(location, lifeCycle, resetEventCounts, upsertRumEvent)

beforeFlushOnUnload(() => updateView(upsertRumEvent))
lifeCycle.subscribe(LifeCycleEventType.WILL_UNLOAD, () => updateView(upsertRumEvent))
}

function newView(
Expand Down
2 changes: 1 addition & 1 deletion packages/rum/test/viewCollection.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function setup({
fakeLocation.hash = getHash(url)
})
const fakeLocation: Partial<Location> = { pathname: '/foo' }
trackView(fakeLocation as Location, lifeCycle || new LifeCycle(), addRumEvent || (() => undefined), () => undefined)
trackView(fakeLocation as Location, lifeCycle || new LifeCycle(), addRumEvent || (() => undefined))
}

describe('rum track url change', () => {
Expand Down

0 comments on commit 96be7d4

Please sign in to comment.