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

[RUMF-729] validate rum events in e2e #597

Merged
merged 3 commits into from
Nov 2, 2020
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
12 changes: 6 additions & 6 deletions test/app/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@
# yarn lockfile v1


"@datadog/browser-core@1.22.0", "@datadog/browser-core@file:../../packages/core":
version "1.22.0"
"@datadog/browser-core@1.25.0", "@datadog/browser-core@file:../../packages/core":
version "1.25.0"
dependencies:
tslib "^1.10.0"

"@datadog/browser-logs@file:../../packages/logs":
version "1.22.0"
version "1.25.0"
dependencies:
"@datadog/browser-core" "1.22.0"
"@datadog/browser-core" "1.25.0"
tslib "^1.10.0"

"@datadog/browser-rum@file:../../packages/rum":
version "1.22.0"
version "1.25.0"
dependencies:
"@datadog/browser-core" "1.22.0"
"@datadog/browser-core" "1.25.0"
tslib "^1.10.0"

"@webassemblyjs/[email protected]":
Expand Down
6 changes: 4 additions & 2 deletions test/e2e/lib/framework/createTest.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { deleteAllCookies, withBrowserLogs } from '../helpers/browser'
import { flushEvents } from '../helpers/sdk'
import { validateFormat } from '../helpers/validation'
import { EventRegistry } from './eventsRegistry'
import { getTestServers, Servers, waitForServersIdle } from './httpServers'
import { log } from './logger'
Expand All @@ -9,12 +10,12 @@ import { createIntakeServerApp } from './serverApps/intake'
import { createMockServerApp } from './serverApps/mock'

const DEFAULT_RUM_OPTIONS = {
applicationId: 'appId',
applicationId: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee',
clientToken: 'token',
enableExperimentalFeatures: ['v2_format'],
}

const DEFAULT_LOGS_OPTIONS = {
applicationId: 'appId',
clientToken: 'token',
}

Expand Down Expand Up @@ -143,6 +144,7 @@ async function setUpTest({ baseUrl }: TestContext) {
async function tearDownTest({ events }: TestContext) {
await flushEvents()
expect(events.internalMonitoring).toEqual([])
validateFormat(events.rum)
await withBrowserLogs((logs) => {
logs.forEach((browserLog) => {
log(`Browser ${browserLog.source}: ${browserLog.level} ${browserLog.message}`)
Expand Down
30 changes: 30 additions & 0 deletions test/e2e/lib/helpers/validation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import ajv from 'ajv'
import rumEventsFormatJson from '../../../../rum-events-format/rum-events-format.json'
import _commonSchemaJson from '../../../../rum-events-format/schemas/_common-schema.json'
import actionSchemaJson from '../../../../rum-events-format/schemas/action-schema.json'
import errorSchemaJson from '../../../../rum-events-format/schemas/error-schema.json'
import long_taskSchemaJson from '../../../../rum-events-format/schemas/long_task-schema.json'
import resourceSchemaJson from '../../../../rum-events-format/schemas/resource-schema.json'
import viewSchemaJson from '../../../../rum-events-format/schemas/view-schema.json'
import { ServerRumEvent } from '../types/serverEvents'

export function validateFormat(events: ServerRumEvent[]) {
events.forEach((event) => {
const instance = new ajv({
allErrors: true,
})
instance
.addSchema(_commonSchemaJson, 'schemas/_common-schema.json')
.addSchema(viewSchemaJson, 'schemas/view-schema.json')
.addSchema(actionSchemaJson, 'schemas/action-schema.json')
.addSchema(resourceSchemaJson, 'schemas/resource-schema.json')
.addSchema(long_taskSchemaJson, 'schemas/long_task-schema.json')
.addSchema(errorSchemaJson, 'schemas/error-schema.json')
.addSchema(rumEventsFormatJson, 'rum-events-format.json')
.validate('rum-events-format.json', event)

if (instance.errors) {
instance.errors.map((error) => fail(`${error.dataPath || 'event'} ${error.message}`))
}
})
}
90 changes: 40 additions & 50 deletions test/e2e/lib/types/serverEvents.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
export type AnyServerEvent = ServerLogsMessage | ServerRumEvent | ServerInternalMonitoringMessage

export interface ServerLogsMessage {
message: string
application_id: string
Expand All @@ -25,9 +23,7 @@ export interface ServerInternalMonitoringMessage {

export interface ServerRumEvent {
date: number
evt: {
category: 'resource' | 'long_task' | 'user_action' | 'error' | 'view'
}
type: 'resource' | 'long_task' | 'action' | 'error' | 'view'
}

interface PerformanceTiming {
Expand All @@ -36,55 +32,53 @@ interface PerformanceTiming {
}

export interface ServerRumResourceEvent extends ServerRumEvent {
evt: {
category: 'resource'
}
http: {
type: 'resource'
resource: {
url: string
method: string
status_code: number
performance?: {
download: PerformanceTiming
redirect: PerformanceTiming
}
}
resource: {
kind: 'fetch' | 'xhr' | 'document'
download: PerformanceTiming
redirect: PerformanceTiming
type: 'fetch' | 'xhr' | 'document'
id?: string
duration: number
}
duration: number
_dd?: {
trace_id: string
span_id?: string
}
user_action?: {
action?: {
id: string
}
}

export function isRumResourceEvent(event: ServerRumEvent): event is ServerRumResourceEvent {
return event.evt.category === 'resource'
return event.type === 'resource'
}

export interface ServerRumUserActionEvent extends ServerRumEvent {
evt: {
category: 'user_action'
name: string
}
duration: number
user_action: {
export interface ServerRumActionEvent extends ServerRumEvent {
type: 'action'
action: {
loading_time: number
id?: string
type: 'click' | 'custom'
measures: {
resource_count: number
error_count: number
long_task_count: number
resource: {
count: number
}
error: {
count: number
}
long_task: {
count: number
}
target: {
name: string
}
}
}

export function isRumUserActionEvent(event: ServerRumEvent): event is ServerRumUserActionEvent {
return event.evt.category === 'user_action'
export function isRumUserActionEvent(event: ServerRumEvent): event is ServerRumActionEvent {
return event.type === 'action'
}

export enum ServerRumViewLoadingType {
Expand All @@ -93,39 +87,35 @@ export enum ServerRumViewLoadingType {
}

export interface ServerRumViewEvent extends ServerRumEvent {
evt: {
category: 'view'
}
rum: {
type: 'view'
_dd: {
document_version: number
}
session_id: string
session: {
id: string
}
view: {
id: string
loading_type: ServerRumViewLoadingType
measures: {
dom_complete: number
dom_content_loaded: number
dom_interactive: number
load_event_end: number
}
dom_complete: number
dom_content_loaded: number
dom_interactive: number
load_event_end: number
}
}

export function isRumViewEvent(event: ServerRumEvent): event is ServerRumViewEvent {
return event.evt.category === 'view'
return event.type === 'view'
}

export interface ServerRumErrorEvent extends ServerRumEvent {
evt: {
category: 'error'
}
message: string
type: 'error'
error: {
origin: string
message: string
source: string
}
}

export function isRumErrorEvent(event: ServerRumEvent): event is ServerRumErrorEvent {
return event.evt.category === 'error'
return event.type === 'error'
}
2 changes: 1 addition & 1 deletion test/e2e/scenario/logs.scenario.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe('logs', () => {
await flushEvents()
expect(events.logs.length).toBe(1)
expect(events.logs[0].view.id).toBeDefined()
expect(events.logs[0].application_id).toBe('appId')
expect(events.logs[0].application_id).toBe('aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee')
})

createTest('track fetch error')
Expand Down
44 changes: 28 additions & 16 deletions test/e2e/scenario/rum/actions.scenario.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,23 @@ describe('action collection', () => {
const actionEvents = events.rumActions

expect(actionEvents.length).toBe(1)
expect(actionEvents[0].user_action).toEqual({
expect(actionEvents[0].action).toEqual({
error: {
count: 0,
},
id: (jasmine.any(String) as unknown) as string,
measures: {
error_count: 0,
long_task_count: (jasmine.any(Number) as unknown) as number,
resource_count: 0,
loading_time: (jasmine.any(Number) as unknown) as number,
long_task: {
count: (jasmine.any(Number) as unknown) as number,
},
resource: {
count: 0,
},
target: {
name: 'click me',
},
type: 'click',
})
expect(actionEvents[0].evt.name).toBe('click me')
expect(actionEvents[0].duration).toBeGreaterThanOrEqual(0)
})

createTest('associate a request to its action')
Expand All @@ -54,22 +60,28 @@ describe('action collection', () => {
await waitForServersIdle()
await flushEvents()
const actionEvents = events.rumActions
const resourceEvents = events.rumResources.filter((event) => event.resource.kind === 'fetch')
const resourceEvents = events.rumResources.filter((event) => event.resource.type === 'fetch')

expect(actionEvents.length).toBe(1)
expect(actionEvents[0].user_action).toEqual({
expect(actionEvents[0].action).toEqual({
error: {
count: 0,
},
id: (jasmine.any(String) as unknown) as string,
measures: {
error_count: 0,
long_task_count: (jasmine.any(Number) as unknown) as number,
resource_count: 1,
loading_time: (jasmine.any(Number) as unknown) as number,
long_task: {
count: (jasmine.any(Number) as unknown) as number,
},
resource: {
count: 1,
},
target: {
name: 'click me',
},
type: 'click',
})
expect(actionEvents[0].evt.name).toBe('click me')
expect(actionEvents[0].duration).toBeGreaterThan(0)

expect(resourceEvents.length).toBe(1)
expect(resourceEvents[0].user_action!.id).toBe(actionEvents[0].user_action.id!)
expect(resourceEvents[0].action!.id).toBe(actionEvents[0].action.id!)
})
})
4 changes: 2 additions & 2 deletions test/e2e/scenario/rum/errors.scenario.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ describe('rum errors', () => {
})
await flushEvents()
expect(events.rumErrors.length).toBe(1)
expect(events.rumErrors[0].message).toBe('console error: oh snap')
expect(events.rumErrors[0].error.origin).toBe('console')
expect(events.rumErrors[0].error.message).toBe('console error: oh snap')
expect(events.rumErrors[0].error.source).toBe('console')
await withBrowserLogs((browserLogs) => {
expect(browserLogs.length).toEqual(1)
})
Expand Down
Loading