From 86954ac4ed1068246d9f0ef340f1650b9d9bbfc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Zugmeyer?= Date: Fri, 20 Aug 2021 11:40:22 +0200 Subject: [PATCH 1/3] [RUMF-996] update rum-event-formats --- packages/rum-core/src/rumEvent.types.ts | 54 ++++++++++++++++++++++--- rum-events-format | 2 +- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/packages/rum-core/src/rumEvent.types.ts b/packages/rum-core/src/rumEvent.types.ts index 02dd38523f..f5a35add65 100644 --- a/packages/rum-core/src/rumEvent.types.ts +++ b/packages/rum-core/src/rumEvent.types.ts @@ -14,7 +14,7 @@ export type RumActionEvent = CommonProperties & { /** * RUM event type */ - readonly type: string + readonly type: 'action' /** * Action properties */ @@ -102,7 +102,7 @@ export type RumErrorEvent = CommonProperties & { /** * RUM event type */ - readonly type: string + readonly type: 'error' /** * Error properties */ @@ -220,7 +220,7 @@ export type RumLongTaskEvent = CommonProperties & { /** * RUM event type */ - readonly type: string + readonly type: 'long_task' /** * Long Task properties */ @@ -233,6 +233,10 @@ export type RumLongTaskEvent = CommonProperties & { * Duration in ns of the long task */ readonly duration: number + /** + * Whether this long task is considered a frozen frame + */ + readonly is_frozen_frame?: boolean [k: string]: unknown } /** @@ -254,7 +258,7 @@ export type RumResourceEvent = CommonProperties & { /** * RUM event type */ - readonly type: string + readonly type: 'resource' /** * Resource properties */ @@ -438,7 +442,7 @@ export type RumViewEvent = CommonProperties & { /** * RUM event type */ - readonly type: string + readonly type: 'view' /** * View properties */ @@ -509,6 +513,10 @@ export type RumViewEvent = CommonProperties & { * Whether the View corresponding to this event is considered active */ readonly is_active?: boolean + /** + * Whether the View had a low average refresh rate + */ + readonly is_slow_rendered?: boolean /** * Properties of the actions of the view */ @@ -549,6 +557,16 @@ export type RumViewEvent = CommonProperties & { readonly count: number [k: string]: unknown } + /** + * Properties of the frozen frames of the view + */ + readonly frozen_frame?: { + /** + * Number of frozen frames that occurred on the view + */ + readonly count: number + [k: string]: unknown + } /** * Properties of the resources of the view */ @@ -730,6 +748,20 @@ export interface CommonProperties { } [k: string]: unknown } + /** + * Synthetics properties + */ + readonly synthetics?: { + /** + * The identifier of the current Synthetics test + */ + readonly test_id: string + /** + * The identifier of the current Synthetics test results + */ + readonly result_id: string + [k: string]: unknown + } /** * Internal properties */ @@ -737,7 +769,17 @@ export interface CommonProperties { /** * Version of the RUM event format */ - readonly format_version: number + readonly format_version: 2 + /** + * Session-related internal properties + */ + session?: { + /** + * Session plan: 1 is the 'lite' plan, 2 is the 'replay' plan + */ + plan: 1 | 2 + [k: string]: unknown + } [k: string]: unknown } /** diff --git a/rum-events-format b/rum-events-format index fcd5662c40..2d27327153 160000 --- a/rum-events-format +++ b/rum-events-format @@ -1 +1 @@ -Subproject commit fcd5662c4007a3225ce9abb443bbb898b513b8b1 +Subproject commit 2d27327153d8e109954c201f3bd2d213cb598bc2 From 096f5a08f74a8ec29df4ef837fc0679b367cd991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Zugmeyer?= Date: Fri, 20 Aug 2021 14:01:18 +0200 Subject: [PATCH 2/3] =?UTF-8?q?=E2=9C=A8=20[RUMF-996]=20set=20synthetics?= =?UTF-8?q?=20ids=20on=20RUM=20events?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/rum-core/src/domain/assembly.spec.ts | 39 ++++++++++++++++++- packages/rum-core/src/domain/assembly.ts | 19 +++++++-- packages/rum-core/src/rawRumEvent.types.ts | 4 ++ 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/packages/rum-core/src/domain/assembly.spec.ts b/packages/rum-core/src/domain/assembly.spec.ts index 3659b8c39f..b8682306e3 100644 --- a/packages/rum-core/src/domain/assembly.spec.ts +++ b/packages/rum-core/src/domain/assembly.spec.ts @@ -516,7 +516,8 @@ describe('rum assembly', () => { }) it('should detect synthetics sessions from global', () => { - ;(window as BrowserWindow)._DATADOG_SYNTHETICS_BROWSER = true + ;(window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID = 'foo' + ;(window as BrowserWindow)._DATADOG_SYNTHETICS_RESULT_ID = 'bar' const { lifeCycle } = setupBuilder.build() notifyRawRumEvent(lifeCycle, { @@ -525,7 +526,8 @@ describe('rum assembly', () => { expect(serverRumEvents[0].session.type).toEqual('synthetics') - delete (window as BrowserWindow)._DATADOG_SYNTHETICS_BROWSER + delete (window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID + delete (window as BrowserWindow)._DATADOG_SYNTHETICS_RESULT_ID }) it('should set the session.has_replay attribute if it is defined in the common context', () => { @@ -549,6 +551,39 @@ describe('rum assembly', () => { }) }) + describe('synthetics context', () => { + it('sets the synthetics context defined by global variables', () => { + ;(window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID = 'foo' + ;(window as BrowserWindow)._DATADOG_SYNTHETICS_RESULT_ID = 'bar' + + const { lifeCycle } = setupBuilder.build() + notifyRawRumEvent(lifeCycle, { + rawRumEvent: createRawRumEvent(RumEventType.VIEW), + }) + + expect(serverRumEvents[0].synthetics).toEqual({ + test_id: 'foo', + result_id: 'bar', + }) + + delete (window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID + delete (window as BrowserWindow)._DATADOG_SYNTHETICS_RESULT_ID + }) + + it('does not set synthetics context if one global variable is undefined', () => { + ;(window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID = 'foo' + + const { lifeCycle } = setupBuilder.build() + notifyRawRumEvent(lifeCycle, { + rawRumEvent: createRawRumEvent(RumEventType.VIEW), + }) + + expect(serverRumEvents[0].synthetics).toBeUndefined() + + delete (window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID + }) + }) + describe('error events limitation', () => { const notifiedRawErrors: RawError[] = [] diff --git a/packages/rum-core/src/domain/assembly.ts b/packages/rum-core/src/domain/assembly.ts index 49e21b631e..bd816e594a 100644 --- a/packages/rum-core/src/domain/assembly.ts +++ b/packages/rum-core/src/domain/assembly.ts @@ -30,7 +30,8 @@ import { ParentContexts } from './parentContexts' import { RumSession, RumSessionPlan } from './rumSession' export interface BrowserWindow extends Window { - _DATADOG_SYNTHETICS_BROWSER?: unknown + _DATADOG_SYNTHETICS_PUBLIC_ID?: string + _DATADOG_SYNTHETICS_RESULT_ID?: string } enum SessionType { @@ -93,6 +94,7 @@ export function startRumAssembly( // must be computed on each event because synthetics instrumentation can be done after sdk execution type: getSessionType(), }, + synthetics: getSyntheticsContext(), } const serverRumEvent = (needToAssembleWithAction(rawRumEvent) ? combine(rumContext, viewContext, actionContext, rawRumEvent) @@ -162,8 +164,19 @@ function needToAssembleWithAction( } function getSessionType() { - return navigator.userAgent.indexOf('DatadogSynthetics') === -1 && - (window as BrowserWindow)._DATADOG_SYNTHETICS_BROWSER === undefined + return navigator.userAgent.indexOf('DatadogSynthetics') === -1 && !getSyntheticsContext() ? SessionType.USER : SessionType.SYNTHETICS } + +function getSyntheticsContext() { + const testId = (window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID + const resultId = (window as BrowserWindow)._DATADOG_SYNTHETICS_RESULT_ID + + if (testId && resultId) { + return { + test_id: testId, + result_id: resultId, + } + } +} diff --git a/packages/rum-core/src/rawRumEvent.types.ts b/packages/rum-core/src/rawRumEvent.types.ts index 531944c3db..104d2af171 100644 --- a/packages/rum-core/src/rawRumEvent.types.ts +++ b/packages/rum-core/src/rawRumEvent.types.ts @@ -179,6 +179,10 @@ export interface RumContext { type: string has_replay?: boolean } + synthetics?: { + test_id: string + result_id: string + } _dd: { format_version: 2 drift: number From 90f03b28a26400e7bccfc020c596f35fd6e57002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Zugmeyer?= Date: Fri, 20 Aug 2021 17:18:32 +0200 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=91=8C=20ensure=20ids=20are=20strings?= =?UTF-8?q?=20and=20add=20a=20helper=20for=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/rum-core/src/domain/assembly.spec.ts | 36 ++++++++++++------- packages/rum-core/src/domain/assembly.ts | 2 +- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/packages/rum-core/src/domain/assembly.spec.ts b/packages/rum-core/src/domain/assembly.spec.ts index b8682306e3..dd139740c6 100644 --- a/packages/rum-core/src/domain/assembly.spec.ts +++ b/packages/rum-core/src/domain/assembly.spec.ts @@ -51,6 +51,7 @@ describe('rum assembly', () => { afterEach(() => { setupBuilder.cleanup() + cleanupSyntheticsGlobals() }) describe('beforeSend', () => { @@ -516,8 +517,7 @@ describe('rum assembly', () => { }) it('should detect synthetics sessions from global', () => { - ;(window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID = 'foo' - ;(window as BrowserWindow)._DATADOG_SYNTHETICS_RESULT_ID = 'bar' + setSyntheticsGlobals('foo', 'bar') const { lifeCycle } = setupBuilder.build() notifyRawRumEvent(lifeCycle, { @@ -525,9 +525,6 @@ describe('rum assembly', () => { }) expect(serverRumEvents[0].session.type).toEqual('synthetics') - - delete (window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID - delete (window as BrowserWindow)._DATADOG_SYNTHETICS_RESULT_ID }) it('should set the session.has_replay attribute if it is defined in the common context', () => { @@ -553,8 +550,7 @@ describe('rum assembly', () => { describe('synthetics context', () => { it('sets the synthetics context defined by global variables', () => { - ;(window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID = 'foo' - ;(window as BrowserWindow)._DATADOG_SYNTHETICS_RESULT_ID = 'bar' + setSyntheticsGlobals('foo', 'bar') const { lifeCycle } = setupBuilder.build() notifyRawRumEvent(lifeCycle, { @@ -565,13 +561,10 @@ describe('rum assembly', () => { test_id: 'foo', result_id: 'bar', }) - - delete (window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID - delete (window as BrowserWindow)._DATADOG_SYNTHETICS_RESULT_ID }) it('does not set synthetics context if one global variable is undefined', () => { - ;(window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID = 'foo' + setSyntheticsGlobals('foo') const { lifeCycle } = setupBuilder.build() notifyRawRumEvent(lifeCycle, { @@ -579,8 +572,17 @@ describe('rum assembly', () => { }) expect(serverRumEvents[0].synthetics).toBeUndefined() + }) + + it('does not set synthetics context if global variables are not strings', () => { + setSyntheticsGlobals(1, 2) + + const { lifeCycle } = setupBuilder.build() + notifyRawRumEvent(lifeCycle, { + rawRumEvent: createRawRumEvent(RumEventType.VIEW), + }) - delete (window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID + expect(serverRumEvents[0].synthetics).toBeUndefined() }) }) @@ -664,3 +666,13 @@ function notifyRawRumEvent( } lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, fullData) } + +function setSyntheticsGlobals(publicId: any, resultId?: any) { + ;(window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID = publicId + ;(window as BrowserWindow)._DATADOG_SYNTHETICS_RESULT_ID = resultId +} + +function cleanupSyntheticsGlobals() { + delete (window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID + delete (window as BrowserWindow)._DATADOG_SYNTHETICS_RESULT_ID +} diff --git a/packages/rum-core/src/domain/assembly.ts b/packages/rum-core/src/domain/assembly.ts index bd816e594a..83b5313c7c 100644 --- a/packages/rum-core/src/domain/assembly.ts +++ b/packages/rum-core/src/domain/assembly.ts @@ -173,7 +173,7 @@ function getSyntheticsContext() { const testId = (window as BrowserWindow)._DATADOG_SYNTHETICS_PUBLIC_ID const resultId = (window as BrowserWindow)._DATADOG_SYNTHETICS_RESULT_ID - if (testId && resultId) { + if (typeof testId === 'string' && typeof resultId === 'string') { return { test_id: testId, result_id: resultId,