Skip to content

Commit

Permalink
♻️ Set the experimental feature flags as early as possible (#2796)
Browse files Browse the repository at this point in the history
  • Loading branch information
amortemousque authored Jun 6, 2024
1 parent ceef0dd commit 81981c0
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 16 deletions.
5 changes: 0 additions & 5 deletions packages/core/src/domain/configuration/configuration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@ describe('validateAndBuildConfiguration', () => {
delete (ExperimentalFeature as any).FOO
})

it('updates experimental feature flags', () => {
validateAndBuildConfiguration({ clientToken, enableExperimentalFeatures: ['foo'] })
expect(isExperimentalFeatureEnabled(TEST_FEATURE_FLAG)).toBeTrue()
})

it('ignores unknown experimental features', () => {
validateAndBuildConfiguration({
clientToken,
Expand Down
10 changes: 0 additions & 10 deletions packages/core/src/domain/configuration/configuration.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { catchUserErrors } from '../../tools/catchUserErrors'
import { DOCS_ORIGIN, display } from '../../tools/display'
import type { RawTelemetryConfiguration } from '../telemetry'
import { ExperimentalFeature, addExperimentalFeatures } from '../../tools/experimentalFeatures'
import type { Duration } from '../../tools/utils/timeUtils'
import { ONE_SECOND } from '../../tools/utils/timeUtils'
import { isPercentage } from '../../tools/utils/numberUtils'
Expand Down Expand Up @@ -260,15 +259,6 @@ export function validateAndBuildConfiguration(initConfiguration: InitConfigurati
return
}

// Set the experimental feature flags as early as possible, so we can use them in most places
if (Array.isArray(initConfiguration.enableExperimentalFeatures)) {
addExperimentalFeatures(
initConfiguration.enableExperimentalFeatures.filter((flag): flag is ExperimentalFeature =>
objectHasValue(ExperimentalFeature, flag)
)
)
}

return assign(
{
beforeSend:
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 @@ -17,6 +17,7 @@ export {
addExperimentalFeatures,
resetExperimentalFeatures,
getExperimentalFeatures,
initFeatureFlags,
ExperimentalFeature,
} from './tools/experimentalFeatures'
export { trackRuntimeError } from './domain/error/trackRuntimeError'
Expand Down
28 changes: 27 additions & 1 deletion packages/core/src/tools/experimentalFeatures.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ExperimentalFeature } from './experimentalFeatures'
import {
ExperimentalFeature,
addExperimentalFeatures,
initFeatureFlags,
isExperimentalFeatureEnabled,
resetExperimentalFeatures,
} from './experimentalFeatures'
Expand Down Expand Up @@ -32,3 +33,28 @@ describe('experimentalFeatures', () => {
expect(isExperimentalFeatureEnabled(TEST_FEATURE_FLAG_TWO)).toBeTrue()
})
})

describe('initFeatureFlags', () => {
beforeEach(() => {
;(ExperimentalFeature as any).FOO = TEST_FEATURE_FLAG_ONE
})

afterEach(() => {
delete (ExperimentalFeature as any).FOO
resetExperimentalFeatures()
})

it('ignores unknown experimental features', () => {
initFeatureFlags(['bar', undefined as any, null as any, 11 as any])

expect(isExperimentalFeatureEnabled('bar' as any)).toBeFalse()
expect(isExperimentalFeatureEnabled(undefined as any)).toBeFalse()
expect(isExperimentalFeatureEnabled(null as any)).toBeFalse()
expect(isExperimentalFeatureEnabled(11 as any)).toBeFalse()
})

it('updates experimental feature flags', () => {
initFeatureFlags(['foo'])
expect(isExperimentalFeatureEnabled(TEST_FEATURE_FLAG_ONE)).toBeTrue()
})
})
13 changes: 13 additions & 0 deletions packages/core/src/tools/experimentalFeatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
*/
// We want to use a real enum (i.e. not a const enum) here, to be able to check whether an arbitrary
// string is an expected feature flag

import { objectHasValue } from './utils/objectUtils'

// eslint-disable-next-line no-restricted-syntax
export enum ExperimentalFeature {
WRITABLE_RESOURCE_GRAPHQL = 'writable_resource_graphql',
Expand All @@ -19,6 +22,16 @@ export enum ExperimentalFeature {

const enabledExperimentalFeatures: Set<ExperimentalFeature> = new Set()

export function initFeatureFlags(enableExperimentalFeatures?: string[] | undefined) {
if (Array.isArray(enableExperimentalFeatures)) {
addExperimentalFeatures(
enableExperimentalFeatures.filter((flag): flag is ExperimentalFeature =>
objectHasValue(ExperimentalFeature, flag)
)
)
}
}

export function addExperimentalFeatures(enabledFeatures: ExperimentalFeature[]): void {
enabledFeatures.forEach((flag) => {
enabledExperimentalFeatures.add(flag)
Expand Down
3 changes: 3 additions & 0 deletions packages/logs/src/boot/preStartLogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
canUseEventBridge,
display,
displayAlreadyInitializedError,
initFeatureFlags,
noop,
timeStampNow,
} from '@datadog/browser-core'
Expand Down Expand Up @@ -44,6 +45,8 @@ export function createPreStartStrategy(
display.error('Missing configuration')
return
}
// Set the experimental feature flags as early as possible, so we can use them in most places
initFeatureFlags(initConfiguration.enableExperimentalFeatures)

if (canUseEventBridge()) {
initConfiguration = overrideInitConfigurationForBridge(initConfiguration)
Expand Down
4 changes: 4 additions & 0 deletions packages/rum-core/src/boot/preStartRum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
clocksNow,
assign,
getEventBridge,
initFeatureFlags,
} from '@datadog/browser-core'
import type { TrackingConsentState, DeflateWorker } from '@datadog/browser-core'
import {
Expand Down Expand Up @@ -78,6 +79,9 @@ export function createPreStartStrategy(
return
}

// Set the experimental feature flags as early as possible, so we can use them in most places
initFeatureFlags(initConfiguration.enableExperimentalFeatures)

const eventBridgeAvailable = canUseEventBridge()
if (eventBridgeAvailable) {
initConfiguration = overrideInitConfigurationForBridge(initConfiguration)
Expand Down

0 comments on commit 81981c0

Please sign in to comment.