Skip to content

Commit

Permalink
⚡[batch] upsert view events
Browse files Browse the repository at this point in the history
  • Loading branch information
bcaudan committed Jan 9, 2020
1 parent 6e6c503 commit 07c1753
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 49 deletions.
7 changes: 6 additions & 1 deletion packages/rum/src/rum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export function startRum(
() => globalContext
)

trackView(window.location, lifeCycle, session, batch.addRumEvent, batch.beforeFlushOnUnload)
trackView(window.location, lifeCycle, session, batch.upsertRumEvent, batch.beforeFlushOnUnload)
trackErrors(lifeCycle, batch.addRumEvent)
trackRequests(configuration, lifeCycle, session, batch.addRumEvent)
trackPerformanceTiming(configuration, lifeCycle, batch.addRumEvent)
Expand Down Expand Up @@ -203,6 +203,11 @@ function startRumBatch(
}
},
beforeFlushOnUnload: (handler: () => void) => batch.beforeFlushOnUnload(handler),
upsertRumEvent: (event: RumEvent, key: string) => {
if (session.isTracked()) {
batch.upsert(withSnakeCaseKeys(event as Context), key)
}
},
}
}

Expand Down
69 changes: 36 additions & 33 deletions packages/rum/src/viewTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,22 @@ export function trackView(
location: Location,
lifeCycle: LifeCycle,
session: RumSession,
addRumEvent: (event: RumEvent) => void,
upsertRumEvent: (event: RumEvent, key: string) => void,
beforeFlushOnUnload: (handler: () => void) => void
) {
const scheduleViewUpdate = throttle(monitor(() => updateView(addRumEvent)), THROTTLE_VIEW_UPDATE_PERIOD, {
const scheduleViewUpdate = throttle(monitor(() => updateView(upsertRumEvent)), THROTTLE_VIEW_UPDATE_PERIOD, {
leading: false,
})

newView(location, session, addRumEvent)
trackHistory(location, session, addRumEvent)
newView(location, session, upsertRumEvent)
trackHistory(location, session, upsertRumEvent)
trackMeasures(lifeCycle, scheduleViewUpdate)
trackRenewSession(location, lifeCycle, session, addRumEvent)
trackRenewSession(location, lifeCycle, session, upsertRumEvent)

beforeFlushOnUnload(() => updateView(addRumEvent))
beforeFlushOnUnload(() => updateView(upsertRumEvent))
}

function newView(location: Location, session: RumSession, addRumEvent: (event: RumEvent) => void) {
function newView(location: Location, session: RumSession, upsertRumEvent: (event: RumEvent, key: string) => void) {
viewContext = {
id: generateUUID(),
location: { ...location },
Expand All @@ -64,50 +64,53 @@ function newView(location: Location, session: RumSession, addRumEvent: (event: R
resourceCount: 0,
userActionCount: 0,
}
addViewEvent(addRumEvent)
upsertViewEvent(upsertRumEvent)
}

function updateView(addRumEvent: (event: RumEvent) => void) {
function updateView(upsertRumEvent: (event: RumEvent, key: string) => void) {
documentVersion += 1
addViewEvent(addRumEvent)
upsertViewEvent(upsertRumEvent)
}

function addViewEvent(addRumEvent: (event: RumEvent) => void) {
addRumEvent({
date: startTimestamp,
duration: msToNs(performance.now() - startOrigin),
evt: {
category: RumEventCategory.VIEW,
function upsertViewEvent(upsertRumEvent: (event: RumEvent, key: string) => void) {
upsertRumEvent(
{
date: startTimestamp,
duration: msToNs(performance.now() - startOrigin),
evt: {
category: RumEventCategory.VIEW,
},
rum: {
documentVersion,
},
view: {
measures: viewMeasures,
},
},
rum: {
documentVersion,
},
view: {
measures: viewMeasures,
},
})
viewContext.id
)
}

function trackHistory(location: Location, session: RumSession, addRumEvent: (event: RumEvent) => void) {
function trackHistory(location: Location, session: RumSession, upsertRumEvent: (event: RumEvent, key: string) => void) {
const originalPushState = history.pushState
history.pushState = monitor(function(this: History['pushState']) {
originalPushState.apply(this, arguments as any)
onUrlChange(location, session, addRumEvent)
onUrlChange(location, session, upsertRumEvent)
})
const originalReplaceState = history.replaceState
history.replaceState = monitor(function(this: History['replaceState']) {
originalReplaceState.apply(this, arguments as any)
onUrlChange(location, session, addRumEvent)
onUrlChange(location, session, upsertRumEvent)
})
window.addEventListener('popstate', () => {
onUrlChange(location, session, addRumEvent)
onUrlChange(location, session, upsertRumEvent)
})
}

function onUrlChange(location: Location, session: RumSession, addRumEvent: (event: RumEvent) => void) {
function onUrlChange(location: Location, session: RumSession, upsertRumEvent: (event: RumEvent, key: string) => void) {
if (areDifferentViews(viewContext.location, location)) {
updateView(addRumEvent)
newView(location, session, addRumEvent)
updateView(upsertRumEvent)
newView(location, session, upsertRumEvent)
}
}

Expand Down Expand Up @@ -175,10 +178,10 @@ function trackRenewSession(
location: Location,
lifeCycle: LifeCycle,
session: RumSession,
addRumEvent: (event: RumEvent) => void
upsertRumEvent: (event: RumEvent, key: string) => void
) {
lifeCycle.subscribe(LifeCycleEventType.SESSION_RENEWED, () => {
updateView(addRumEvent)
newView(location, session, addRumEvent)
updateView(upsertRumEvent)
newView(location, session, upsertRumEvent)
})
}
11 changes: 4 additions & 7 deletions test/e2e/scenario/agents.scenario.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { LogsGlobal } from '@datadog/browser-logs'
import { RumEvent, RumEventCategory, RumResourceEvent, RumViewEvent } from '@datadog/browser-rum'
import { RumEvent, RumEventCategory, RumResourceEvent } from '@datadog/browser-rum'
import {
browserExecute,
browserExecuteAsync,
findLastEvent,
flushBrowserLogs,
flushEvents,
renewSession,
retrieveInitialViewEvents,
retrieveLogs,
retrieveLogsMessages,
retrieveRumEvents,
retrieveRumEventsTypes,
retrieveViewEvents,
sortByMessage,
tearDown,
withBrowserLogs,
Expand Down Expand Up @@ -103,9 +102,7 @@ describe('rum', () => {

it('should send performance timings along the view events', async () => {
await flushEvents()
const events = await retrieveRumEvents()

const viewEvent = findLastEvent(events, (event) => event.evt.category === 'view') as RumViewEvent
const viewEvent = (await retrieveViewEvents())[0]

expect(viewEvent as any).not.toBe(undefined)
const measures = viewEvent.view.measures
Expand All @@ -119,7 +116,7 @@ describe('rum', () => {
await renewSession()
await flushEvents()

const viewEvents = await retrieveInitialViewEvents()
const viewEvents = await retrieveViewEvents()

expect(viewEvents.length).toBe(2)
expect(viewEvents[0].session_id).not.toBe(viewEvents[1].session_id)
Expand Down
10 changes: 2 additions & 8 deletions test/e2e/scenario/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,9 @@ export async function retrieveMonitoringErrors() {
return fetch('/monitoring').then((monitoringErrors: string) => JSON.parse(monitoringErrors) as MonitoringMessage[])
}

export async function retrieveInitialViewEvents() {
export async function retrieveViewEvents() {
const events = await retrieveRumEvents()
return events.filter(
(event) => event.evt.category === 'view' && (event as ServerRumViewEvent).rum.document_version === 1
) as ServerRumViewEvent[]
return events.filter((event) => event.evt.category === 'view') as ServerRumViewEvent[]
}

export async function resetServerState() {
Expand Down Expand Up @@ -126,10 +124,6 @@ export function sortByMessage(a: { message: string }, b: { message: string }) {
return 0
}

export function findLastEvent(events: RumEvent[], predicate: (event: RumEvent) => boolean) {
return events.reduce<RumEvent | undefined>((olderEvent, event) => (predicate(event) ? event : olderEvent), undefined)
}

export async function renewSession() {
await deleteAllCookies()
expect(await findSessionCookie()).not.toBeDefined()
Expand Down

0 comments on commit 07c1753

Please sign in to comment.