From 7d552bd7eaf736b276c0d5e425ebc2fee319f338 Mon Sep 17 00:00:00 2001 From: Aymeric Mortemousque Date: Mon, 22 Jul 2024 11:59:37 +0200 Subject: [PATCH] Simplify configuration validation --- .../configuration/configuration.spec.ts | 4 +- .../src/domain/configuration/configuration.ts | 66 +++++++------------ .../core/src/domain/configuration/index.ts | 1 + packages/core/src/index.ts | 1 + .../src/domain/configuration/configuration.ts | 63 ++++++++---------- 5 files changed, 56 insertions(+), 79 deletions(-) diff --git a/packages/core/src/domain/configuration/configuration.spec.ts b/packages/core/src/domain/configuration/configuration.spec.ts index 900420f480..b4cb2aa2e3 100644 --- a/packages/core/src/domain/configuration/configuration.spec.ts +++ b/packages/core/src/domain/configuration/configuration.spec.ts @@ -1,7 +1,7 @@ import type { RumEvent } from '../../../../rum-core/src' import { EXHAUSTIVE_INIT_CONFIGURATION, SERIALIZED_EXHAUSTIVE_INIT_CONFIGURATION } from '../../../test' import type { ExtractTelemetryConfiguration, MapInitConfigurationKey } from '../../../test' -import { DOCS_ORIGIN, display } from '../../tools/display' +import { DOCS_ORIGIN, MORE_DETAILS, display } from '../../tools/display' import { ExperimentalFeature, isExperimentalFeatureEnabled, @@ -209,7 +209,7 @@ describe('validateAndBuildConfiguration', () => { it('should validate the site parameter', () => { validateAndBuildConfiguration({ clientToken, site: 'foo.com' }) expect(displaySpy).toHaveBeenCalledOnceWith( - `Site should be a valid Datadog site. Learn more here: ${DOCS_ORIGIN}/getting_started/site/.` + `Site should be a valid Datadog site. ${MORE_DETAILS} ${DOCS_ORIGIN}/getting_started/site/.` ) }) }) diff --git a/packages/core/src/domain/configuration/configuration.ts b/packages/core/src/domain/configuration/configuration.ts index eb2773827e..aa7a145f91 100644 --- a/packages/core/src/domain/configuration/configuration.ts +++ b/packages/core/src/domain/configuration/configuration.ts @@ -1,5 +1,5 @@ import { catchUserErrors } from '../../tools/catchUserErrors' -import { DOCS_ORIGIN, display } from '../../tools/display' +import { DOCS_ORIGIN, MORE_DETAILS, display } from '../../tools/display' import type { RawTelemetryConfiguration } from '../telemetry' import type { Duration } from '../../tools/utils/timeUtils' import { ONE_SECOND } from '../../tools/utils/timeUtils' @@ -191,7 +191,7 @@ export interface Configuration extends TransportConfiguration { messageBytesLimit: number } -function checkIfString(tag: unknown, tagName: string): tag is string | undefined | null { +function isString(tag: unknown, tagName: string): tag is string | undefined | null { if (tag !== undefined && tag !== null && typeof tag !== 'string') { display.error(`${tagName} must be defined as a string`) return false @@ -199,8 +199,20 @@ function checkIfString(tag: unknown, tagName: string): tag is string | undefined return true } -function isDatadogSite(site: string) { - return /(datadog|ddog|datad0g|dd0g)/.test(site) +function isDatadogSite(site: unknown) { + if (site && typeof site === 'string' && !/(datadog|ddog|datad0g|dd0g)/.test(site)) { + display.error(`Site should be a valid Datadog site. ${MORE_DETAILS} ${DOCS_ORIGIN}/getting_started/site/.`) + return false + } + return true +} + +export function isSampleRate(sampleRate: unknown, name: string) { + if (sampleRate !== undefined && !isPercentage(sampleRate)) { + display.error(`${name} Sample Rate should be a number between 0 and 100`) + return false + } + return true } export function validateAndBuildConfiguration(initConfiguration: InitConfiguration): Configuration | undefined { @@ -209,41 +221,16 @@ export function validateAndBuildConfiguration(initConfiguration: InitConfigurati return } - if (initConfiguration.sessionSampleRate !== undefined && !isPercentage(initConfiguration.sessionSampleRate)) { - display.error('Session Sample Rate should be a number between 0 and 100') - return - } - - if (initConfiguration.telemetrySampleRate !== undefined && !isPercentage(initConfiguration.telemetrySampleRate)) { - display.error('Telemetry Sample Rate should be a number between 0 and 100') - return - } - if ( - initConfiguration.telemetryConfigurationSampleRate !== undefined && - !isPercentage(initConfiguration.telemetryConfigurationSampleRate) + !isDatadogSite(initConfiguration.site) || + !isSampleRate(initConfiguration.sessionSampleRate, 'Session') || + !isSampleRate(initConfiguration.telemetrySampleRate, 'Telemetry') || + !isSampleRate(initConfiguration.telemetryConfigurationSampleRate, 'Telemetry Configuration') || + !isSampleRate(initConfiguration.telemetryUsageSampleRate, 'Telemetry Usage') || + !isString(initConfiguration.version, 'Version') || + !isString(initConfiguration.env, 'Env') || + !isString(initConfiguration.service, 'Service') ) { - display.error('Telemetry Configuration Sample Rate should be a number between 0 and 100') - return - } - - if ( - initConfiguration.telemetryUsageSampleRate !== undefined && - !isPercentage(initConfiguration.telemetryUsageSampleRate) - ) { - display.error('Telemetry Usage Sample Rate should be a number between 0 and 100') - return - } - - if (!checkIfString(initConfiguration.version, 'Version')) { - return - } - - if (!checkIfString(initConfiguration.env, 'Env')) { - return - } - - if (!checkIfString(initConfiguration.service, 'Service')) { return } @@ -255,11 +242,6 @@ export function validateAndBuildConfiguration(initConfiguration: InitConfigurati return } - if (initConfiguration.site && !isDatadogSite(initConfiguration.site)) { - display.error(`Site should be a valid Datadog site. Learn more here: ${DOCS_ORIGIN}/getting_started/site/.`) - return - } - return assign( { beforeSend: diff --git a/packages/core/src/domain/configuration/index.ts b/packages/core/src/domain/configuration/index.ts index a9871b222d..2eb661436c 100644 --- a/packages/core/src/domain/configuration/index.ts +++ b/packages/core/src/domain/configuration/index.ts @@ -3,6 +3,7 @@ export { InitConfiguration, DefaultPrivacyLevel, TraceContextInjection, + isSampleRate, validateAndBuildConfiguration, serializeConfiguration, } from './configuration' diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 61ede06dcf..51fb29eb00 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -6,6 +6,7 @@ export { TraceContextInjection, EndpointBuilder, serializeConfiguration, + isSampleRate, INTAKE_SITE_STAGING, INTAKE_SITE_US1, INTAKE_SITE_US1_FED, diff --git a/packages/rum-core/src/domain/configuration/configuration.ts b/packages/rum-core/src/domain/configuration/configuration.ts index 401dd98ded..109c5a45ce 100644 --- a/packages/rum-core/src/domain/configuration/configuration.ts +++ b/packages/rum-core/src/domain/configuration/configuration.ts @@ -8,9 +8,9 @@ import { DefaultPrivacyLevel, TraceContextInjection, display, - isPercentage, objectHasValue, validateAndBuildConfiguration, + isSampleRate, } from '@datadog/browser-core' import type { RumEventDomainContext } from '../../domainContext.types' import type { RumEvent } from '../../rumEvent.types' @@ -167,15 +167,9 @@ export function validateAndBuildRumConfiguration( } if ( - initConfiguration.sessionReplaySampleRate !== undefined && - !isPercentage(initConfiguration.sessionReplaySampleRate) + !isSampleRate(initConfiguration.sessionReplaySampleRate, 'Session Replay') || + !isSampleRate(initConfiguration.traceSampleRate, 'Trace') ) { - display.error('Session Replay Sample Rate should be a number between 0 and 100') - return - } - - if (initConfiguration.traceSampleRate !== undefined && !isPercentage(initConfiguration.traceSampleRate)) { - display.error('Trace Sample Rate should be a number between 0 and 100') return } @@ -229,34 +223,33 @@ export function validateAndBuildRumConfiguration( * Validates allowedTracingUrls and converts match options to tracing options */ function validateAndBuildTracingOptions(initConfiguration: RumInitConfiguration): TracingOption[] | undefined { - if (initConfiguration.allowedTracingUrls !== undefined) { - if (!Array.isArray(initConfiguration.allowedTracingUrls)) { - display.error('Allowed Tracing URLs should be an array') - return - } - if (initConfiguration.allowedTracingUrls.length !== 0 && initConfiguration.service === undefined) { - display.error('Service needs to be configured when tracing is enabled') - return - } - // Convert from (MatchOption | TracingOption) to TracingOption, remove unknown properties - const tracingOptions: TracingOption[] = [] - initConfiguration.allowedTracingUrls.forEach((option) => { - if (isMatchOption(option)) { - tracingOptions.push({ match: option, propagatorTypes: DEFAULT_PROPAGATOR_TYPES }) - } else if (isTracingOption(option)) { - tracingOptions.push(option) - } else { - display.warn( - 'Allowed Tracing Urls parameters should be a string, RegExp, function, or an object. Ignoring parameter', - option - ) - } - }) - - return tracingOptions + if (initConfiguration.allowedTracingUrls === undefined) { + return [] + } + if (!Array.isArray(initConfiguration.allowedTracingUrls)) { + display.error('Allowed Tracing URLs should be an array') + return } + if (initConfiguration.allowedTracingUrls.length !== 0 && initConfiguration.service === undefined) { + display.error('Service needs to be configured when tracing is enabled') + return + } + // Convert from (MatchOption | TracingOption) to TracingOption, remove unknown properties + const tracingOptions: TracingOption[] = [] + initConfiguration.allowedTracingUrls.forEach((option) => { + if (isMatchOption(option)) { + tracingOptions.push({ match: option, propagatorTypes: DEFAULT_PROPAGATOR_TYPES }) + } else if (isTracingOption(option)) { + tracingOptions.push(option) + } else { + display.warn( + 'Allowed Tracing Urls parameters should be a string, RegExp, function, or an object. Ignoring parameter', + option + ) + } + }) - return [] + return tracingOptions } /**