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-998] introduce the initialPrivacyLevel configuration option #1004

Merged
merged 19 commits into from
Aug 27, 2021
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
9b047dd
[RUMF-998] implement a shouldMaskNode function
BenoitZugmeyer Aug 19, 2021
e4539c5
[RUMF-998] remove remap function
BenoitZugmeyer Aug 19, 2021
cd0d20a
[RUMF-998] rename NodePrivacyLevelInternal to NodePrivacyLevel
BenoitZugmeyer Aug 19, 2021
cbcdb9e
[RUMF-998] getNodePrivacyLevel takes the initialPrivacyLevel as argument
BenoitZugmeyer Aug 19, 2021
0a92809
[RUMF-998] remove the "NOT_SET" privacy level variant
BenoitZugmeyer Aug 19, 2021
e9724b7
[RUMF-998] ensure only a subset of privacy levels can be inherited
BenoitZugmeyer Aug 19, 2021
540324a
[RUMF-998] make initial privacy level arguments required
BenoitZugmeyer Aug 19, 2021
e557515
[RUMF-998] rename NodePrivacyLevel values to match public configuration
BenoitZugmeyer Aug 19, 2021
a541c0a
✨ [RUMF-998] introduce the initialPrivacyLevel configuration option
BenoitZugmeyer Aug 19, 2021
279e300
[RUMF-998] adjust some comments and typos
BenoitZugmeyer Aug 19, 2021
7c0a10a
👌 [RUMF-998] add a few tests to ensure the setting is correctly applied
BenoitZugmeyer Aug 20, 2021
c4f6ea9
👌 improve configuration value check
BenoitZugmeyer Aug 24, 2021
8a2a611
👌 use the InitialPrivacyLevel to declare the NodePrivacyLevel constants
BenoitZugmeyer Aug 24, 2021
5c5e764
[RUMF-998] export the InitialPrivacyLevel constants
BenoitZugmeyer Aug 24, 2021
bd54d8b
🚩 [RUMF-998] put the option behind a feature flag
BenoitZugmeyer Aug 24, 2021
664f4ac
👌 rename derivePrivacyLevelGivenParent to reducePrivacyLevel
BenoitZugmeyer Aug 26, 2021
07b8ebd
👌 early return in `getNodePrivacyLevel`
BenoitZugmeyer Aug 26, 2021
5659520
📝👌 adjust comments and doc
BenoitZugmeyer Aug 26, 2021
6837279
Merge branch 'main' into benoit/implement-initial-privacy-level-option
BenoitZugmeyer Aug 26, 2021
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
18 changes: 17 additions & 1 deletion packages/core/src/domain/configuration.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { BuildEnv } from '../boot/init'
import { CookieOptions, getCurrentSite } from '../browser/cookie'
import { catchUserErrors } from '../tools/catchUserErrors'
import { includes, ONE_KILO_BYTE, ONE_SECOND } from '../tools/utils'
import { includes, objectValues, ONE_KILO_BYTE, ONE_SECOND } from '../tools/utils'
import { computeTransportConfiguration } from './transportConfiguration'

export const InitialPrivacyLevel = {
ALLOW: 'allow',
MASK: 'mask',
MASK_FORMS_ONLY: 'mask-forms-only',
} as const
export type InitialPrivacyLevel = typeof InitialPrivacyLevel[keyof typeof InitialPrivacyLevel]
BenoitZugmeyer marked this conversation as resolved.
Show resolved Hide resolved

export const DEFAULT_CONFIGURATION = {
allowedTracingOrigins: [] as Array<string | RegExp>,
maxErrorsByMinute: 3000,
Expand All @@ -13,6 +20,7 @@ export const DEFAULT_CONFIGURATION = {
silentMultipleInit: false,
trackInteractions: false,
trackViewsManually: false,
initialPrivacyLevel: InitialPrivacyLevel.ALLOW as InitialPrivacyLevel,

/**
* arbitrary value, byte precision not needed
Expand Down Expand Up @@ -53,6 +61,7 @@ export interface InitConfiguration {
trackViewsManually?: boolean
proxyHost?: string
beforeSend?: BeforeSendCallback
initialPrivacyLevel?: InitialPrivacyLevel

service?: string
env?: string
Expand Down Expand Up @@ -143,6 +152,13 @@ export function buildConfiguration(initConfiguration: InitConfiguration, buildEn
configuration.actionNameAttribute = initConfiguration.actionNameAttribute
}

if (
'initialPrivacyLevel' in initConfiguration &&
objectValues(InitialPrivacyLevel).indexOf(initConfiguration.initialPrivacyLevel) >= 0
) {
configuration.initialPrivacyLevel = initConfiguration.initialPrivacyLevel!
BenoitZugmeyer marked this conversation as resolved.
Show resolved Hide resolved
}

return configuration
}

Expand Down
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export {
InitConfiguration,
buildCookieOptions,
BeforeSendCallback,
InitialPrivacyLevel,
} from './domain/configuration'
export { trackConsoleError } from './domain/error/trackConsoleError'
export { trackRuntimeError } from './domain/error/trackRuntimeError'
Expand Down
30 changes: 28 additions & 2 deletions packages/rum-core/src/boot/rumPublicApi.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ONE_SECOND, RelativeTime, getTimeStamp, display, TimeStamp } from '@datadog/browser-core'
import { ONE_SECOND, RelativeTime, getTimeStamp, display, TimeStamp, InitialPrivacyLevel } from '@datadog/browser-core'
import { noopRecorderApi, setup, TestSetupBuilder } from '../../test/specHelper'
import { ActionType } from '../rawRumEvent.types'
import { makeRumPublicApi, RumPublicApi, RumInitConfiguration, StartRum } from './rumPublicApi'
import { makeRumPublicApi, RumPublicApi, RumInitConfiguration, StartRum, RecorderApi } from './rumPublicApi'

const noopStartRum = (): ReturnType<StartRum> => ({
addAction: () => undefined,
Expand Down Expand Up @@ -652,4 +652,30 @@ describe('rum public api', () => {
})
})
})

describe('recording', () => {
let recorderApiOnRumStartSpy: jasmine.Spy<RecorderApi['onRumStart']>
let setupBuilder: TestSetupBuilder
let rumPublicApi: RumPublicApi

beforeEach(() => {
recorderApiOnRumStartSpy = jasmine.createSpy('recorderApiOnRumStart')
rumPublicApi = makeRumPublicApi(noopStartRum, { ...noopRecorderApi, onRumStart: recorderApiOnRumStartSpy })
setupBuilder = setup()
})

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

it('recording is started with the default initialPrivacyLevel', () => {
rumPublicApi.init(DEFAULT_INIT_CONFIGURATION)
expect(recorderApiOnRumStartSpy.calls.mostRecent().args[2].initialPrivacyLevel).toBe(InitialPrivacyLevel.ALLOW)
})

it('recording is started with the configured initialPrivacyLevel', () => {
rumPublicApi.init({ ...DEFAULT_INIT_CONFIGURATION, initialPrivacyLevel: InitialPrivacyLevel.MASK })
expect(recorderApiOnRumStartSpy.calls.mostRecent().args[2].initialPrivacyLevel).toBe(InitialPrivacyLevel.MASK)
})
})
})
2 changes: 2 additions & 0 deletions packages/rum-core/src/boot/rumPublicApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
InternalMonitoring,
callMonitored,
createHandlingStack,
InitialPrivacyLevel,
} from '@datadog/browser-core'
import { LifeCycle } from '../domain/lifeCycle'
import { ParentContexts } from '../domain/parentContexts'
Expand All @@ -31,6 +32,7 @@ import { startRum } from './startRum'
export interface RumInitConfiguration extends InitConfiguration {
applicationId: string
beforeSend?: (event: RumEvent, context: RumEventDomainContext) => void | boolean
initialPrivacyLevel?: InitialPrivacyLevel
}

export type RumPublicApi = ReturnType<typeof makeRumPublicApi>
Expand Down
1 change: 1 addition & 0 deletions packages/rum/src/boot/startRecording.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export function startRecording(

const { stop: stopRecording, takeFullSnapshot, flushMutations } = record({
emit: addRawRecord,
initialPrivacyLevel: configuration.initialPrivacyLevel,
})

lifeCycle.subscribe(LifeCycleEventType.VIEW_ENDED, flushMutations)
Expand Down
19 changes: 6 additions & 13 deletions packages/rum/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
export const NodePrivacyLevel = {
BenoitZugmeyer marked this conversation as resolved.
Show resolved Hide resolved
IGNORE: 'IGNORE',
ALLOW: 'ALLOW',
MASK: 'MASK',
HIDDEN: 'HIDDEN',
IGNORE: 'ignore',
ALLOW: 'allow',
MASK: 'mask',
HIDDEN: 'hidden',
MASK_FORMS_ONLY: 'mask-forms-only',
} as const
export type NodePrivacyLevel = typeof NodePrivacyLevel[keyof typeof NodePrivacyLevel]

export const NodePrivacyLevelInternal = {
// INTERNAL USE: not to be used by the general codebase
NOT_SET: 'NOT_SET',
MASK_FORMS_ONLY: 'MASK_FORMS_ONLY',
...NodePrivacyLevel,
} as const
export type NodePrivacyLevelInternal = typeof NodePrivacyLevelInternal[keyof typeof NodePrivacyLevelInternal]

export const PRIVACY_ATTR_NAME = 'data-dd-privacy'

// Deprecate via temporariy Alias
// Deprecate via temporary Alias
export const PRIVACY_CLASS_INPUT_IGNORED = 'dd-privacy-input-ignored' // DEPRECATED, aliased to mask-forms-only
export const PRIVACY_CLASS_INPUT_MASKED = 'dd-privacy-input-masked' // DEPRECATED, aliased to mask-forms-only
export const PRIVACY_ATTR_VALUE_INPUT_IGNORED = 'input-ignored' // DEPRECATED, aliased to mask-forms-only
Expand Down
Loading