Skip to content

Commit

Permalink
Merge branch 'main' into benoit/implement-initial-privacy-level-option
Browse files Browse the repository at this point in the history
  • Loading branch information
BenoitZugmeyer authored Aug 26, 2021
2 parents 5659520 + 636989e commit 6837279
Show file tree
Hide file tree
Showing 27 changed files with 314 additions and 85 deletions.
2 changes: 1 addition & 1 deletion .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
variables:
APP: 'browser-sdk'
CURRENT_CI_IMAGE: 24
CURRENT_CI_IMAGE: 25
BUILD_STABLE_REGISTRY: '486234852809.dkr.ecr.us-east-1.amazonaws.com'
CI_IMAGE: '$BUILD_STABLE_REGISTRY/ci/$APP:$CURRENT_CI_IMAGE'

Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
---

## v3.1.3

- ⚗✨[REPLAY-336] Privacy by Default ([#951](https://github.com/DataDog/browser-sdk/pull/951))
- ⚗✨ [REPLAY-379] add replay stats on view (getter edition) ([#994](https://github.com/DataDog/browser-sdk/pull/994))
- 📝 Update Readme for v3 cdn links ([#999](https://github.com/DataDog/browser-sdk/pull/999))
- 🐛[RUMF-990] restore global check to detect synthetics sessions ([#997](https://github.com/DataDog/browser-sdk/pull/997))

## v3.1.2

-[RUMF-970] enable buffered PerformanceObserver ([#995](https://github.com/DataDog/browser-sdk/pull/995))
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ RUN apt-get update && apt-get install -y -q --no-install-recommends \

# Download and install Chrome
# Debian taken from https://www.ubuntuupdates.org/package/google_chrome/stable/main/base/google-chrome-stable
RUN curl --silent --show-error --fail http://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_90.0.4430.85-1_amd64.deb --output google-chrome.deb \
RUN curl --silent --show-error --fail http://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_92.0.4515.107-1_amd64.deb --output google-chrome.deb \
&& dpkg -i google-chrome.deb \
&& rm google-chrome.deb

Expand Down
2 changes: 1 addition & 1 deletion developer-extension/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@datadog/browser-sdk-developer-extension",
"version": "3.1.2",
"version": "3.1.3",
"private": true,
"scripts": {
"build": "rm -rf dist && webpack --mode production",
Expand Down
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"npmClient": "yarn",
"useWorkspaces": true,
"version": "3.1.2",
"version": "3.1.3",
"publishConfig": {
"access": "public"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@datadog/browser-core",
"version": "3.1.2",
"version": "3.1.3",
"license": "Apache-2.0",
"main": "cjs/index.js",
"module": "esm/index.js",
Expand Down
9 changes: 5 additions & 4 deletions packages/logs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,9 @@ If your Browser logs contain sensitive information that needs redacting, configu

The `beforeSend` callback function gives you access to each event collected by the Browser SDK before it is sent to Datadog, and lets you update commonly redacted properties.

For example, to redact email addresses from your web application URLs:
For examples of `beforeSend`, see [Enrich and control browser RUM data with beforeSend][5].

To redact email addresses from your web application URLs:

#### NPM

Expand Down Expand Up @@ -309,8 +311,7 @@ You can update the following event properties:
| `message` | String | The content of the log. |
| `error.stack` | String | The stack trace or complementary information about the error. |
| `http.url` | String | The HTTP URL. |

**Note**: The Browser SDK will ignore modifications made to event properties not listed above. For more information about event properties, see the [Browser SDK repository][5].
| `context` | String | Extra contextual attributes added with the logger. |

### Define multiple loggers

Expand Down Expand Up @@ -597,4 +598,4 @@ window.DD_LOGS && DD_LOGS.logger.setHandler(['<HANDLER1>', '<HANDLER2>'])
[2]: /account_management/api-app-keys/#client-tokens
[3]: https://www.npmjs.com/package/@datadog/browser-logs
[4]: https://github.com/DataDog/browser-sdk/blob/main/packages/logs/BROWSER_SUPPORT.md
[5]: https://github.com/DataDog/browser-sdk/blob/main/packages/logs/src/logsEvent.types.ts
[5]: /real_user_monitoring/guide/enrich-and-control-rum-data/
4 changes: 2 additions & 2 deletions packages/logs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@datadog/browser-logs",
"version": "3.1.2",
"version": "3.1.3",
"license": "Apache-2.0",
"main": "cjs/index.js",
"module": "esm/index.js",
Expand All @@ -13,7 +13,7 @@
"replace-build-env": "node ../../scripts/replace-build-env.js"
},
"dependencies": {
"@datadog/browser-core": "3.1.2",
"@datadog/browser-core": "3.1.3",
"tslib": "^1.10.0"
},
"devDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions packages/rum-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@datadog/browser-rum-core",
"version": "3.1.2",
"version": "3.1.3",
"license": "Apache-2.0",
"main": "cjs/index.js",
"module": "esm/index.js",
Expand All @@ -12,7 +12,7 @@
"replace-build-env": "node ../../scripts/replace-build-env.js"
},
"dependencies": {
"@datadog/browser-core": "3.1.2",
"@datadog/browser-core": "3.1.3",
"tslib": "^1.10.0"
},
"devDependencies": {
Expand Down
53 changes: 50 additions & 3 deletions packages/rum-core/src/domain/assembly.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ describe('rum assembly', () => {

afterEach(() => {
setupBuilder.cleanup()
cleanupSyntheticsGlobals()
})

describe('beforeSend', () => {
Expand Down Expand Up @@ -516,16 +517,14 @@ describe('rum assembly', () => {
})

it('should detect synthetics sessions from global', () => {
;(window as BrowserWindow)._DATADOG_SYNTHETICS_BROWSER = true
setSyntheticsGlobals('foo', 'bar')

const { lifeCycle } = setupBuilder.build()
notifyRawRumEvent(lifeCycle, {
rawRumEvent: createRawRumEvent(RumEventType.VIEW),
})

expect(serverRumEvents[0].session.type).toEqual('synthetics')

delete (window as BrowserWindow)._DATADOG_SYNTHETICS_BROWSER
})

it('should set the session.has_replay attribute if it is defined in the common context', () => {
Expand All @@ -549,6 +548,44 @@ describe('rum assembly', () => {
})
})

describe('synthetics context', () => {
it('sets the synthetics context defined by global variables', () => {
setSyntheticsGlobals('foo', 'bar')

const { lifeCycle } = setupBuilder.build()
notifyRawRumEvent(lifeCycle, {
rawRumEvent: createRawRumEvent(RumEventType.VIEW),
})

expect(serverRumEvents[0].synthetics).toEqual({
test_id: 'foo',
result_id: 'bar',
})
})

it('does not set synthetics context if one global variable is undefined', () => {
setSyntheticsGlobals('foo')

const { lifeCycle } = setupBuilder.build()
notifyRawRumEvent(lifeCycle, {
rawRumEvent: createRawRumEvent(RumEventType.VIEW),
})

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),
})

expect(serverRumEvents[0].synthetics).toBeUndefined()
})
})

describe('error events limitation', () => {
const notifiedRawErrors: RawError[] = []

Expand Down Expand Up @@ -629,3 +666,13 @@ function notifyRawRumEvent<E extends RawRumEvent>(
}
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
}
19 changes: 16 additions & 3 deletions packages/rum-core/src/domain/assembly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 (typeof testId === 'string' && typeof resultId === 'string') {
return {
test_id: testId,
result_id: resultId,
}
}
}
15 changes: 15 additions & 0 deletions packages/rum-core/src/domain/lifeCycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ export enum LifeCycleEventType {
VIEW_ENDED,
REQUEST_STARTED,
REQUEST_COMPLETED,

// The SESSION_EXPIRED lifecycle event has been introduced to represent when a session has expired
// and trigger cleanup tasks related to this, prior to renewing the session. Its implementation is
// slightly naive: it is not triggered as soon as the session is expired, but rather just before
// notifying that the session is renewed. Thus, the session id is already set to the newly renewed
// session.
//
// This implementation is "good enough" for our use-cases. Improving this is not trivial,
// primarily because multiple instances of the SDK may be managing the same session cookie at
// the same time, for example when using Logs and RUM on the same page, or opening multiple tabs
// on the same domain.
SESSION_EXPIRED,

SESSION_RENEWED,
BEFORE_UNLOAD,
RAW_RUM_EVENT_COLLECTED,
Expand All @@ -41,6 +54,7 @@ export class LifeCycle {
): void
notify(
eventType:
| LifeCycleEventType.SESSION_EXPIRED
| LifeCycleEventType.SESSION_RENEWED
| LifeCycleEventType.BEFORE_UNLOAD
| LifeCycleEventType.AUTO_ACTION_DISCARDED
Expand Down Expand Up @@ -77,6 +91,7 @@ export class LifeCycle {
): Subscription
subscribe(
eventType:
| LifeCycleEventType.SESSION_EXPIRED
| LifeCycleEventType.SESSION_RENEWED
| LifeCycleEventType.BEFORE_UNLOAD
| LifeCycleEventType.AUTO_ACTION_DISCARDED,
Expand Down
10 changes: 10 additions & 0 deletions packages/rum-core/src/domain/rumSession.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe('rum session', () => {
replaySampleRate: 50,
}
let lifeCycle: LifeCycle
let expireSessionSpy: jasmine.Spy
let renewSessionSpy: jasmine.Spy
let clock: Clock

Expand All @@ -33,8 +34,10 @@ describe('rum session', () => {
pending('no full rum support')
}
clock = mockClock()
expireSessionSpy = jasmine.createSpy('expireSessionSpy')
renewSessionSpy = jasmine.createSpy('renewSessionSpy')
lifeCycle = new LifeCycle()
lifeCycle.subscribe(LifeCycleEventType.SESSION_EXPIRED, expireSessionSpy)
lifeCycle.subscribe(LifeCycleEventType.SESSION_RENEWED, renewSessionSpy)
})

Expand All @@ -52,6 +55,7 @@ describe('rum session', () => {

startRumSession(configuration as Configuration, lifeCycle)

expect(expireSessionSpy).not.toHaveBeenCalled()
expect(renewSessionSpy).not.toHaveBeenCalled()
expect(getCookie(SESSION_COOKIE_NAME)).toContain(`${RUM_SESSION_KEY}=${RumTrackingType.TRACKED_REPLAY}`)
expect(getCookie(SESSION_COOKIE_NAME)).toMatch(/id=[a-f0-9-]/)
Expand All @@ -62,6 +66,7 @@ describe('rum session', () => {

startRumSession(configuration as Configuration, lifeCycle)

expect(expireSessionSpy).not.toHaveBeenCalled()
expect(renewSessionSpy).not.toHaveBeenCalled()
expect(getCookie(SESSION_COOKIE_NAME)).toContain(`${RUM_SESSION_KEY}=${RumTrackingType.TRACKED_LITE}`)
expect(getCookie(SESSION_COOKIE_NAME)).toMatch(/id=[a-f0-9-]/)
Expand All @@ -72,6 +77,7 @@ describe('rum session', () => {

startRumSession(configuration as Configuration, lifeCycle)

expect(expireSessionSpy).not.toHaveBeenCalled()
expect(renewSessionSpy).not.toHaveBeenCalled()
expect(getCookie(SESSION_COOKIE_NAME)).toContain(`${RUM_SESSION_KEY}=${RumTrackingType.NOT_TRACKED}`)
expect(getCookie(SESSION_COOKIE_NAME)).not.toContain('id=')
Expand All @@ -82,6 +88,7 @@ describe('rum session', () => {

startRumSession(configuration as Configuration, lifeCycle)

expect(expireSessionSpy).not.toHaveBeenCalled()
expect(renewSessionSpy).not.toHaveBeenCalled()
expect(getCookie(SESSION_COOKIE_NAME)).toContain(`${RUM_SESSION_KEY}=${RumTrackingType.TRACKED_REPLAY}`)
expect(getCookie(SESSION_COOKIE_NAME)).toContain('id=abcdef')
Expand All @@ -92,6 +99,7 @@ describe('rum session', () => {

startRumSession(configuration as Configuration, lifeCycle)

expect(expireSessionSpy).not.toHaveBeenCalled()
expect(renewSessionSpy).not.toHaveBeenCalled()
expect(getCookie(SESSION_COOKIE_NAME)).toContain(`${RUM_SESSION_KEY}=${RumTrackingType.NOT_TRACKED}`)
})
Expand All @@ -101,12 +109,14 @@ describe('rum session', () => {

setCookie(SESSION_COOKIE_NAME, '', DURATION)
expect(getCookie(SESSION_COOKIE_NAME)).toBeUndefined()
expect(expireSessionSpy).not.toHaveBeenCalled()
expect(renewSessionSpy).not.toHaveBeenCalled()
clock.tick(COOKIE_ACCESS_DELAY)

setupDraws({ tracked: true, trackedWithReplay: true })
document.dispatchEvent(new CustomEvent('click'))

expect(expireSessionSpy).toHaveBeenCalled()
expect(renewSessionSpy).toHaveBeenCalled()
expect(getCookie(SESSION_COOKIE_NAME)).toContain(`${RUM_SESSION_KEY}=${RumTrackingType.TRACKED_REPLAY}`)
expect(getCookie(SESSION_COOKIE_NAME)).toMatch(/id=[a-f0-9-]/)
Expand Down
1 change: 1 addition & 0 deletions packages/rum-core/src/domain/rumSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export function startRumSession(configuration: Configuration, lifeCycle: LifeCyc
)

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

Expand Down
4 changes: 4 additions & 0 deletions packages/rum-core/src/rawRumEvent.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit 6837279

Please sign in to comment.