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

✨[RUM] add view resource count #189

Merged
merged 4 commits into from
Dec 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
34 changes: 19 additions & 15 deletions packages/rum/src/lifeCycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,37 @@ import { ErrorMessage, RequestDetails } from '@browser-sdk/core'
import { UserAction } from './rum'

export enum LifeCycleEventType {
error,
performance,
userAction,
request,
renewSession,
ERROR_COLLECTED,
PERFORMANCE_ENTRY_COLLECTED,
USER_ACTION_COLLECTED,
REQUEST_COLLECTED,
SESSION_RENEWED,
RESOURCE_ADDED_TO_BATCH,
}

export class LifeCycle {
private callbacks: { [key in LifeCycleEventType]?: Array<(data: any) => void> } = {}

notify(eventType: LifeCycleEventType.error, data: ErrorMessage): void
notify(eventType: LifeCycleEventType.performance, data: PerformanceEntry): void
notify(eventType: LifeCycleEventType.request, data: RequestDetails): void
notify(eventType: LifeCycleEventType.userAction, data: UserAction): void
notify(eventType: LifeCycleEventType.renewSession): void
notify(eventType: LifeCycleEventType.ERROR_COLLECTED, data: ErrorMessage): void
notify(eventType: LifeCycleEventType.PERFORMANCE_ENTRY_COLLECTED, data: PerformanceEntry): void
notify(eventType: LifeCycleEventType.REQUEST_COLLECTED, data: RequestDetails): void
notify(eventType: LifeCycleEventType.USER_ACTION_COLLECTED, data: UserAction): void
notify(eventType: LifeCycleEventType.SESSION_RENEWED | LifeCycleEventType.RESOURCE_ADDED_TO_BATCH): void
notify(eventType: LifeCycleEventType, data?: any) {
const eventCallbacks = this.callbacks[eventType]
if (eventCallbacks) {
eventCallbacks.forEach((callback) => callback(data))
}
}

subscribe(eventType: LifeCycleEventType.error, callback: (data: ErrorMessage) => void): void
subscribe(eventType: LifeCycleEventType.performance, callback: (data: PerformanceEntry) => void): void
subscribe(eventType: LifeCycleEventType.request, callback: (data: RequestDetails) => void): void
subscribe(eventType: LifeCycleEventType.userAction, callback: (data: UserAction) => void): void
subscribe(eventType: LifeCycleEventType.renewSession, callback: () => void): void
subscribe(eventType: LifeCycleEventType.ERROR_COLLECTED, callback: (data: ErrorMessage) => void): void
subscribe(eventType: LifeCycleEventType.PERFORMANCE_ENTRY_COLLECTED, callback: (data: PerformanceEntry) => void): void
subscribe(eventType: LifeCycleEventType.REQUEST_COLLECTED, callback: (data: RequestDetails) => void): void
subscribe(eventType: LifeCycleEventType.USER_ACTION_COLLECTED, callback: (data: UserAction) => void): void
subscribe(
eventType: LifeCycleEventType.SESSION_RENEWED | LifeCycleEventType.RESOURCE_ADDED_TO_BATCH,
callback: () => void
): void
subscribe(eventType: LifeCycleEventType, callback: (data?: any) => void) {
const eventCallbacks = this.callbacks[eventType]
if (eventCallbacks) {
Expand Down
2 changes: 1 addition & 1 deletion packages/rum/src/performanceCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function retrieveNavigationTimingWhenLoaded(callback: (timing: PerformanceNaviga

function handlePerformanceEntries(session: RumSession, lifeCycle: LifeCycle, entries: PerformanceEntry[]) {
function notify(entry: PerformanceEntry) {
lifeCycle.notify(LifeCycleEventType.performance, entry)
lifeCycle.notify(LifeCycleEventType.PERFORMANCE_ENTRY_COLLECTED, entry)
}

if (session.isTrackedWithResource()) {
Expand Down
6 changes: 4 additions & 2 deletions packages/rum/src/rum.entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,10 @@ datadogRum.init = monitor((userConfiguration: RumUserConfiguration) => {
const requestObservable = startRequestCollection()
startPerformanceCollection(lifeCycle, session)

errorObservable.subscribe((errorMessage) => lifeCycle.notify(LifeCycleEventType.error, errorMessage))
requestObservable.subscribe((requestDetails) => lifeCycle.notify(LifeCycleEventType.request, requestDetails))
errorObservable.subscribe((errorMessage) => lifeCycle.notify(LifeCycleEventType.ERROR_COLLECTED, errorMessage))
requestObservable.subscribe((requestDetails) =>
lifeCycle.notify(LifeCycleEventType.REQUEST_COLLECTED, requestDetails)
)

const globalApi = startRum(rumUserConfiguration.applicationId, lifeCycle, configuration, session)
lodashAssign(datadogRum, globalApi)
Expand Down
17 changes: 10 additions & 7 deletions packages/rum/src/rum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export function startRum(
globalContext[key] = value
}),
addUserAction: monitor((name: string, context?: Context) => {
lifeCycle.notify(LifeCycleEventType.userAction, { name, context })
lifeCycle.notify(LifeCycleEventType.USER_ACTION_COLLECTED, { name, context })
}),
getInternalContext: monitor(() => {
return {
Expand Down Expand Up @@ -213,7 +213,7 @@ function startRumBatch(
}

function trackErrors(lifeCycle: LifeCycle, addRumEvent: (event: RumEvent) => void) {
lifeCycle.subscribe(LifeCycleEventType.error, ({ message, context }: ErrorMessage) => {
lifeCycle.subscribe(LifeCycleEventType.ERROR_COLLECTED, ({ message, context }: ErrorMessage) => {
addRumEvent({
message,
evt: {
Expand All @@ -228,7 +228,7 @@ function trackErrors(lifeCycle: LifeCycle, addRumEvent: (event: RumEvent) => voi
}

function trackUserAction(lifeCycle: LifeCycle, addUserEvent: (event: RumUserAction) => void) {
lifeCycle.subscribe(LifeCycleEventType.userAction, ({ name, context }) => {
lifeCycle.subscribe(LifeCycleEventType.USER_ACTION_COLLECTED, ({ name, context }) => {
addUserEvent({
...context,
evt: {
Expand All @@ -245,7 +245,7 @@ export function trackRequests(
session: RumSession,
addRumEvent: (event: RumEvent) => void
) {
lifeCycle.subscribe(LifeCycleEventType.request, (requestDetails: RequestDetails) => {
lifeCycle.subscribe(LifeCycleEventType.REQUEST_COLLECTED, (requestDetails: RequestDetails) => {
if (!session.isTrackedWithResource()) {
return
}
Expand Down Expand Up @@ -276,6 +276,7 @@ export function trackRequests(
},
traceId: requestDetails.traceId,
})
lifeCycle.notify(LifeCycleEventType.RESOURCE_ADDED_TO_BATCH)
})
}

Expand All @@ -284,10 +285,10 @@ function trackPerformanceTiming(
lifeCycle: LifeCycle,
addRumEvent: (event: RumEvent) => void
) {
lifeCycle.subscribe(LifeCycleEventType.performance, (entry) => {
lifeCycle.subscribe(LifeCycleEventType.PERFORMANCE_ENTRY_COLLECTED, (entry) => {
switch (entry.entryType) {
case 'resource':
handleResourceEntry(configuration, entry as PerformanceResourceTiming, addRumEvent)
handleResourceEntry(configuration, entry as PerformanceResourceTiming, addRumEvent, lifeCycle)
break
case 'longtask':
handleLongTaskEntry(entry as PerformanceLongTaskTiming, addRumEvent)
Expand All @@ -301,7 +302,8 @@ function trackPerformanceTiming(
export function handleResourceEntry(
configuration: Configuration,
entry: PerformanceResourceTiming,
addRumEvent: (event: RumEvent) => void
addRumEvent: (event: RumEvent) => void,
lifeCycle: LifeCycle
) {
if (!isValidResource(entry.name, configuration)) {
return
Expand All @@ -326,6 +328,7 @@ export function handleResourceEntry(
kind: resourceKind,
},
})
lifeCycle.notify(LifeCycleEventType.RESOURCE_ADDED_TO_BATCH)
}

export function handleLongTaskEntry(entry: PerformanceLongTaskTiming, addRumEvent: (event: RumEvent) => void) {
Expand Down
2 changes: 1 addition & 1 deletion packages/rum/src/rumSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function startRumSession(configuration: Configuration, lifeCycle: LifeCyc
const session = startSessionManagement(RUM_COOKIE_NAME, (rawType) => computeSessionState(configuration, rawType))

session.renewObservable.subscribe(() => {
lifeCycle.notify(LifeCycleEventType.renewSession)
lifeCycle.notify(LifeCycleEventType.SESSION_RENEWED)
})

return {
Expand Down
18 changes: 12 additions & 6 deletions packages/rum/src/viewTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ export interface ViewMeasures {
domContentLoaded?: number
domComplete?: number
loadEventEnd?: number
userActionCount: number
errorCount: number
resourceCount: number
longTaskCount: number
userActionCount: number
}

export let viewId: string
Expand Down Expand Up @@ -49,6 +50,7 @@ function newView(location: Location, addRumEvent: (event: RumEvent) => void) {
viewMeasures = {
errorCount: 0,
longTaskCount: 0,
resourceCount: 0,
userActionCount: 0,
}
viewLocation = { ...location }
Expand Down Expand Up @@ -104,7 +106,7 @@ function areDifferentViews(previous: Location, current: Location) {
}

function trackMeasures(lifeCycle: LifeCycle, scheduleViewUpdate: () => void) {
lifeCycle.subscribe(LifeCycleEventType.performance, (entry) => {
lifeCycle.subscribe(LifeCycleEventType.PERFORMANCE_ENTRY_COLLECTED, (entry) => {
if (entry.entryType === 'navigation') {
const navigationEntry = entry as PerformanceNavigationTiming
viewMeasures = {
Expand All @@ -124,24 +126,28 @@ function trackMeasures(lifeCycle: LifeCycle, scheduleViewUpdate: () => void) {
scheduleViewUpdate()
}
})
lifeCycle.subscribe(LifeCycleEventType.error, () => {
lifeCycle.subscribe(LifeCycleEventType.ERROR_COLLECTED, () => {
viewMeasures.errorCount += 1
scheduleViewUpdate()
})
lifeCycle.subscribe(LifeCycleEventType.userAction, () => {
lifeCycle.subscribe(LifeCycleEventType.USER_ACTION_COLLECTED, () => {
viewMeasures.userActionCount += 1
scheduleViewUpdate()
})
lifeCycle.subscribe(LifeCycleEventType.performance, (entry) => {
lifeCycle.subscribe(LifeCycleEventType.PERFORMANCE_ENTRY_COLLECTED, (entry) => {
if (entry.entryType === 'longtask') {
viewMeasures.longTaskCount += 1
scheduleViewUpdate()
}
})
lifeCycle.subscribe(LifeCycleEventType.RESOURCE_ADDED_TO_BATCH, () => {
viewMeasures.resourceCount += 1
scheduleViewUpdate()
})
}

function trackRenewSession(location: Location, lifeCycle: LifeCycle, addRumEvent: (event: RumEvent) => void) {
lifeCycle.subscribe(LifeCycleEventType.renewSession, () => {
lifeCycle.subscribe(LifeCycleEventType.SESSION_RENEWED, () => {
updateView(addRumEvent)
newView(location, addRumEvent)
})
Expand Down
53 changes: 34 additions & 19 deletions packages/rum/test/rum.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,12 @@ describe('rum handle performance entry', () => {
expectEntryToBeAdded: boolean
}) => {
it(description, () => {
handleResourceEntry(configuration as Configuration, entry as PerformanceResourceTiming, addRumEvent)
handleResourceEntry(
configuration as Configuration,
entry as PerformanceResourceTiming,
addRumEvent,
new LifeCycle()
)
const entryAdded = (addRumEvent as jasmine.Spy).calls.all().length !== 0
expect(entryAdded).toEqual(expectEntryToBeAdded)
})
Expand Down Expand Up @@ -115,7 +120,12 @@ describe('rum handle performance entry', () => {
it(`should compute resource kind: ${description}`, () => {
const entry: Partial<PerformanceResourceTiming> = { initiatorType, name: url, entryType: 'resource' }

handleResourceEntry(configuration as Configuration, entry as PerformanceResourceTiming, addRumEvent)
handleResourceEntry(
configuration as Configuration,
entry as PerformanceResourceTiming,
addRumEvent,
new LifeCycle()
)
const resourceEvent = getEntry(addRumEvent, 0) as RumResourceEvent
expect(resourceEvent.resource.kind).toEqual(expected)
})
Expand All @@ -132,7 +142,12 @@ describe('rum handle performance entry', () => {
responseStart: 25,
}

handleResourceEntry(configuration as Configuration, entry as PerformanceResourceTiming, addRumEvent)
handleResourceEntry(
configuration as Configuration,
entry as PerformanceResourceTiming,
addRumEvent,
new LifeCycle()
)
const resourceEvent = getEntry(addRumEvent, 0) as RumResourceEvent
expect(resourceEvent.http.performance!.connect.duration).toEqual(7 * 1e6)
expect(resourceEvent.http.performance!.download.duration).toEqual(75 * 1e6)
Expand Down Expand Up @@ -175,9 +190,9 @@ describe('rum session', () => {
server.requests = []

stubBuilder.fakeEntry(FAKE_RESOURCE as PerformanceEntry, 'resource')
lifeCycle.notify(LifeCycleEventType.error, FAKE_ERROR as ErrorMessage)
lifeCycle.notify(LifeCycleEventType.request, FAKE_REQUEST as RequestDetails)
lifeCycle.notify(LifeCycleEventType.userAction, FAKE_USER_ACTION)
lifeCycle.notify(LifeCycleEventType.ERROR_COLLECTED, FAKE_ERROR as ErrorMessage)
lifeCycle.notify(LifeCycleEventType.REQUEST_COLLECTED, FAKE_REQUEST as RequestDetails)
lifeCycle.notify(LifeCycleEventType.USER_ACTION_COLLECTED, FAKE_USER_ACTION)

expect(server.requests.length).toEqual(4)
})
Expand All @@ -194,10 +209,10 @@ describe('rum session', () => {
server.requests = []

stubBuilder.fakeEntry(FAKE_RESOURCE as PerformanceEntry, 'resource')
lifeCycle.notify(LifeCycleEventType.request, FAKE_REQUEST as RequestDetails)
lifeCycle.notify(LifeCycleEventType.REQUEST_COLLECTED, FAKE_REQUEST as RequestDetails)
expect(server.requests.length).toEqual(0)

lifeCycle.notify(LifeCycleEventType.error, FAKE_ERROR as ErrorMessage)
lifeCycle.notify(LifeCycleEventType.ERROR_COLLECTED, FAKE_ERROR as ErrorMessage)
expect(server.requests.length).toEqual(1)
})

Expand All @@ -213,9 +228,9 @@ describe('rum session', () => {
server.requests = []

stubBuilder.fakeEntry(FAKE_RESOURCE as PerformanceEntry, 'resource')
lifeCycle.notify(LifeCycleEventType.request, FAKE_REQUEST as RequestDetails)
lifeCycle.notify(LifeCycleEventType.error, FAKE_ERROR as ErrorMessage)
lifeCycle.notify(LifeCycleEventType.userAction, FAKE_USER_ACTION)
lifeCycle.notify(LifeCycleEventType.REQUEST_COLLECTED, FAKE_REQUEST as RequestDetails)
lifeCycle.notify(LifeCycleEventType.ERROR_COLLECTED, FAKE_ERROR as ErrorMessage)
lifeCycle.notify(LifeCycleEventType.USER_ACTION_COLLECTED, FAKE_USER_ACTION)

expect(server.requests.length).toEqual(0)
})
Expand Down Expand Up @@ -256,15 +271,15 @@ describe('rum session', () => {
startPerformanceCollection(lifeCycle, session)
server.requests = []

lifeCycle.notify(LifeCycleEventType.request, FAKE_REQUEST as RequestDetails)
lifeCycle.notify(LifeCycleEventType.REQUEST_COLLECTED, FAKE_REQUEST as RequestDetails)
expect(server.requests.length).toEqual(1)

isTrackedWithResource = false
lifeCycle.notify(LifeCycleEventType.request, FAKE_REQUEST as RequestDetails)
lifeCycle.notify(LifeCycleEventType.REQUEST_COLLECTED, FAKE_REQUEST as RequestDetails)
expect(server.requests.length).toEqual(1)

isTrackedWithResource = true
lifeCycle.notify(LifeCycleEventType.request, FAKE_REQUEST as RequestDetails)
lifeCycle.notify(LifeCycleEventType.REQUEST_COLLECTED, FAKE_REQUEST as RequestDetails)
expect(server.requests.length).toEqual(2)
})
})
Expand Down Expand Up @@ -325,16 +340,16 @@ describe('rum global context', () => {

it('should be added to the request', () => {
RUM.setRumGlobalContext({ bar: 'foo' })
lifeCycle.notify(LifeCycleEventType.error, FAKE_ERROR as ErrorMessage)
lifeCycle.notify(LifeCycleEventType.ERROR_COLLECTED, FAKE_ERROR as ErrorMessage)

expect((getRumMessage(server, 0) as any).bar).toEqual('foo')
})

it('should be updatable', () => {
RUM.setRumGlobalContext({ bar: 'foo' })
lifeCycle.notify(LifeCycleEventType.error, FAKE_ERROR as ErrorMessage)
lifeCycle.notify(LifeCycleEventType.ERROR_COLLECTED, FAKE_ERROR as ErrorMessage)
RUM.setRumGlobalContext({ foo: 'bar' })
lifeCycle.notify(LifeCycleEventType.error, FAKE_ERROR as ErrorMessage)
lifeCycle.notify(LifeCycleEventType.ERROR_COLLECTED, FAKE_ERROR as ErrorMessage)

expect((getRumMessage(server, 0) as any).bar).toEqual('foo')
expect((getRumMessage(server, 1) as any).foo).toEqual('bar')
Expand All @@ -343,7 +358,7 @@ describe('rum global context', () => {

it('should not be automatically snake cased', () => {
RUM.setRumGlobalContext({ fooBar: 'foo' })
lifeCycle.notify(LifeCycleEventType.error, FAKE_ERROR as ErrorMessage)
lifeCycle.notify(LifeCycleEventType.ERROR_COLLECTED, FAKE_ERROR as ErrorMessage)

expect((getRumMessage(server, 0) as any).fooBar).toEqual('foo')
})
Expand All @@ -367,7 +382,7 @@ describe('rum user action', () => {
})

it('should not be automatically snake cased', () => {
lifeCycle.notify(LifeCycleEventType.userAction, { name: 'hello', context: { fooBar: 'foo' } })
lifeCycle.notify(LifeCycleEventType.USER_ACTION_COLLECTED, { name: 'hello', context: { fooBar: 'foo' } })

expect((getRumMessage(server, 0) as any).fooBar).toEqual('foo')
})
Expand Down
2 changes: 1 addition & 1 deletion packages/rum/test/rumSession.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('rum session', () => {
jasmine.clock().mockDate(new Date())
renewSessionSpy = jasmine.createSpy('renewSessionSpy')
lifeCycle = new LifeCycle()
lifeCycle.subscribe(LifeCycleEventType.renewSession, renewSessionSpy)
lifeCycle.subscribe(LifeCycleEventType.SESSION_RENEWED, renewSessionSpy)
})

afterEach(() => {
Expand Down
Loading