From 77ab6cec663b2196662ce4599d3ba5c057c15c99 Mon Sep 17 00:00:00 2001 From: Arya Date: Mon, 30 Mar 2026 17:29:34 +0530 Subject: [PATCH 1/4] refactor: build config from userConfig instead of mutating pre-filled object --- packages/core/src/config/index.js | 341 +++++++++++++++++------------- 1 file changed, 192 insertions(+), 149 deletions(-) diff --git a/packages/core/src/config/index.js b/packages/core/src/config/index.js index d8d769d8de..bddba31b00 100644 --- a/packages/core/src/config/index.js +++ b/packages/core/src/config/index.js @@ -157,143 +157,158 @@ module.exports.normalize = (userConfig, defaultsOverride = {}) => { } /** @type InstanaConfig */ - let targetConfig = {}; - - // NOTE: Do not modify the original object - if (userConfig !== null) { - targetConfig = Object.assign({}, userConfig); - } + const config = {}; // TODO: remove this and forward the logger via init fn. - targetConfig.logger = logger; - - normalizeServiceName(targetConfig); - normalizePackageJsonPath(targetConfig); - normalizeMetricsConfig(targetConfig); - normalizeTracingConfig(targetConfig); - normalizeSecrets(targetConfig); - normalizePreloadOpentelemetry(targetConfig); - return targetConfig; + config.logger = logger; + + // Each normalize function receives userConfig (read-only) and config (write target) + normalizeServiceName(userConfig, config); + normalizePackageJsonPath(userConfig, config); + normalizeMetricsConfig(userConfig, config); + normalizeTracingConfig(userConfig, config); + normalizeSecrets(userConfig, config); + normalizePreloadOpentelemetry(userConfig, config); + + return config; }; /** + * @param {InstanaConfig|null} userConfig * @param {InstanaConfig} config */ -function normalizeServiceName(config) { - if (config.serviceName == null && process.env.INSTANA_SERVICE_NAME) { +function normalizeServiceName(userConfig, config) { + const userValue = userConfig?.serviceName; + + if (userValue != null) { + if (typeof userValue === 'string') { + config.serviceName = userValue; + } else { + logger.warn(`Invalid configuration: config.serviceName is not a string, the value will be ignored: ${userValue}`); + config.serviceName = defaults.serviceName; + } + } else if (process.env.INSTANA_SERVICE_NAME) { config.serviceName = process.env.INSTANA_SERVICE_NAME; - } - if (config.serviceName != null && typeof config.serviceName !== 'string') { - logger.warn( - `Invalid configuration: config.serviceName is not a string, the value will be ignored: ${config.serviceName}` - ); + } else { config.serviceName = defaults.serviceName; } } /** + * @param {InstanaConfig|null} userConfig * @param {InstanaConfig} config */ -function normalizePackageJsonPath(config) { - if (config.packageJsonPath == null && process.env.INSTANA_PACKAGE_JSON_PATH) { +function normalizePackageJsonPath(userConfig, config) { + const userValue = userConfig?.packageJsonPath; + + if (userValue != null) { + if (typeof userValue === 'string') { + config.packageJsonPath = userValue; + } else { + logger.warn( + // eslint-disable-next-line max-len + `Invalid configuration: config.packageJsonPath is not a string, the value will be ignored: ${userValue}` + ); + config.packageJsonPath = null; + } + } else if (process.env.INSTANA_PACKAGE_JSON_PATH) { config.packageJsonPath = process.env.INSTANA_PACKAGE_JSON_PATH; - } - if (config.packageJsonPath != null && typeof config.packageJsonPath !== 'string') { - logger.warn( - // eslint-disable-next-line max-len - `Invalid configuration: config.packageJsonPath is not a string, the value will be ignored: ${config.packageJsonPath}` - ); + } else { config.packageJsonPath = null; } } /** + * @param {InstanaConfig|null} userConfig * @param {InstanaConfig} config */ -function normalizeMetricsConfig(config) { - if (config.metrics == null) { - config.metrics = {}; - } +function normalizeMetricsConfig(userConfig, config) { + const userMetrics = userConfig?.metrics; + + config.metrics = {}; config.metrics.transmissionDelay = util.resolveNumericConfig({ envVar: 'INSTANA_METRICS_TRANSMISSION_DELAY', - configValue: config.metrics.transmissionDelay, + configValue: userMetrics?.transmissionDelay, defaultValue: defaults.metrics.transmissionDelay, configPath: 'config.metrics.transmissionDelay' }); config.metrics.timeBetweenHealthcheckCalls = - config.metrics.timeBetweenHealthcheckCalls || defaults.metrics.timeBetweenHealthcheckCalls; + userMetrics?.timeBetweenHealthcheckCalls || defaults.metrics.timeBetweenHealthcheckCalls; } /** - * + + * @param {InstanaConfig|null} userConfig * @param {InstanaConfig} config */ -function normalizeTracingConfig(config) { - if (config.tracing == null) { - config.tracing = {}; - } - normalizeTracingEnabled(config); - normalizeUseOpentelemetry(config); - normalizeDisableTracing(config); - normalizeAutomaticTracingEnabled(config); - normalizeActivateImmediately(config); - normalizeTracingTransmission(config); - normalizeTracingHttp(config); - normalizeTracingStackTrace(config); - normalizeSpanBatchingEnabled(config); - normalizeDisableW3cTraceCorrelation(config); - normalizeTracingKafka(config); - normalizeAllowRootExitSpan(config); - normalizeIgnoreEndpoints(config); - normalizeIgnoreEndpointsDisableSuppression(config); - normalizeDisableEOLEvents(config); +function normalizeTracingConfig(userConfig, config) { + const userTracingConfig = userConfig?.tracing; + + config.tracing = {}; + + normalizeTracingEnabled(userTracingConfig, config); + normalizeUseOpentelemetry(userTracingConfig, config); + normalizeDisableTracing(userConfig, config); + normalizeAutomaticTracingEnabled(userTracingConfig, config); + normalizeActivateImmediately(userTracingConfig, config); + normalizeTracingTransmission(userTracingConfig, config); + normalizeTracingHttp(userTracingConfig, config); + normalizeTracingStackTrace(userConfig, config); + normalizeSpanBatchingEnabled(userTracingConfig, config); + normalizeDisableW3cTraceCorrelation(userTracingConfig, config); + normalizeTracingKafka(userTracingConfig, config); + normalizeAllowRootExitSpan(userTracingConfig, config); + normalizeIgnoreEndpoints(userTracingConfig, config); + normalizeIgnoreEndpointsDisableSuppression(userTracingConfig, config); + normalizeDisableEOLEvents(userTracingConfig, config); } /** - * + * @param {InstanaTracingOption} userTracingConfig * @param {InstanaConfig} config */ -function normalizeTracingEnabled(config) { +function normalizeTracingEnabled(userTracingConfig, config) { config.tracing.enabled = util.resolveBooleanConfigWithInvertedEnv({ envVar: 'INSTANA_TRACING_DISABLE', - configValue: config.tracing.enabled, + configValue: userTracingConfig?.enabled, defaultValue: defaults.tracing.enabled, configPath: 'config.tracing.enabled' }); } /** - * + * @param {InstanaTracingOption} userTracingConfig * @param {InstanaConfig} config */ -function normalizeAllowRootExitSpan(config) { +function normalizeAllowRootExitSpan(userTracingConfig, config) { config.tracing.allowRootExitSpan = util.resolveBooleanConfig({ envVar: 'INSTANA_ALLOW_ROOT_EXIT_SPAN', - configValue: config.tracing.allowRootExitSpan, + configValue: userTracingConfig?.allowRootExitSpan, defaultValue: defaults.tracing.allowRootExitSpan, configPath: 'config.tracing.allowRootExitSpan' }); } /** - * + * @param {InstanaTracingOption} userTracingConfig * @param {InstanaConfig} config */ -function normalizeUseOpentelemetry(config) { +function normalizeUseOpentelemetry(userTracingConfig, config) { config.tracing.useOpentelemetry = util.resolveBooleanConfigWithInvertedEnv({ envVar: 'INSTANA_DISABLE_USE_OPENTELEMETRY', - configValue: config.tracing.useOpentelemetry, + configValue: userTracingConfig?.useOpentelemetry, defaultValue: defaults.tracing.useOpentelemetry, configPath: 'config.tracing.useOpentelemetry' }); } /** + * @param {InstanaTracingOption} userTracingConfig * @param {InstanaConfig} config */ -function normalizeAutomaticTracingEnabled(config) { +function normalizeAutomaticTracingEnabled(userTracingConfig, config) { if (!config.tracing.enabled) { logger.info('Not enabling automatic tracing as tracing in general is explicitly disabled via config.'); config.tracing.automaticTracingEnabled = false; @@ -302,16 +317,17 @@ function normalizeAutomaticTracingEnabled(config) { config.tracing.automaticTracingEnabled = util.resolveBooleanConfigWithInvertedEnv({ envVar: 'INSTANA_DISABLE_AUTO_INSTR', - configValue: config.tracing.automaticTracingEnabled, + configValue: userTracingConfig?.automaticTracingEnabled, defaultValue: defaults.tracing.automaticTracingEnabled, configPath: 'config.tracing.automaticTracingEnabled' }); } /** + * @param {InstanaTracingOption} userTracingConfig * @param {InstanaConfig} config */ -function normalizeActivateImmediately(config) { +function normalizeActivateImmediately(userTracingConfig, config) { if (!config.tracing.enabled) { config.tracing.activateImmediately = false; return; @@ -319,35 +335,36 @@ function normalizeActivateImmediately(config) { config.tracing.activateImmediately = util.resolveBooleanConfig({ envVar: 'INSTANA_TRACE_IMMEDIATELY', - configValue: config.tracing.activateImmediately, + configValue: userTracingConfig?.activateImmediately, defaultValue: defaults.tracing.activateImmediately, configPath: 'config.tracing.activateImmediately' }); } /** + * @param {InstanaTracingOption} userTracingConfig * @param {InstanaConfig} config */ -function normalizeTracingTransmission(config) { - config.tracing.maxBufferedSpans = config.tracing.maxBufferedSpans || defaults.tracing.maxBufferedSpans; +function normalizeTracingTransmission(userTracingConfig, config) { + config.tracing.maxBufferedSpans = userTracingConfig?.maxBufferedSpans || defaults.tracing.maxBufferedSpans; config.tracing.transmissionDelay = util.resolveNumericConfig({ envVar: 'INSTANA_TRACING_TRANSMISSION_DELAY', - configValue: config.tracing.transmissionDelay, + configValue: userTracingConfig?.transmissionDelay, defaultValue: defaults.tracing.transmissionDelay, configPath: 'config.tracing.transmissionDelay' }); config.tracing.forceTransmissionStartingAt = util.resolveNumericConfig({ envVar: 'INSTANA_FORCE_TRANSMISSION_STARTING_AT', - configValue: config.tracing.forceTransmissionStartingAt, + configValue: userTracingConfig?.forceTransmissionStartingAt, defaultValue: defaults.tracing.forceTransmissionStartingAt, configPath: 'config.tracing.forceTransmissionStartingAt' }); config.tracing.initialTransmissionDelay = util.resolveNumericConfig({ envVar: 'INSTANA_TRACING_INITIAL_TRANSMISSION_DELAY', - configValue: config.tracing.initialTransmissionDelay, + configValue: userTracingConfig?.initialTransmissionDelay, defaultValue: defaults.tracing.initialTransmissionDelay, configPath: 'config.tracing.initialTransmissionDelay' }); @@ -358,38 +375,40 @@ function normalizeTracingTransmission(config) { * because it involves complex multi-step processing: * Future improvement: Consider refactoring to use a more generic resolver pattern. * + * @param {InstanaTracingOption} userTracingConfig * @param {InstanaConfig} config */ -function normalizeTracingHttp(config) { - config.tracing.http = config.tracing.http || {}; +function normalizeTracingHttp(userTracingConfig, config) { + const userHttp = userTracingConfig?.http; + config.tracing.http = {}; let fromEnvVar; if (process.env.INSTANA_EXTRA_HTTP_HEADERS) { fromEnvVar = parseHeadersEnvVar(process.env.INSTANA_EXTRA_HTTP_HEADERS); } - if (!config.tracing.http.extraHttpHeadersToCapture && !fromEnvVar) { + const userHeaders = userHttp?.extraHttpHeadersToCapture; + + if (!userHeaders && !fromEnvVar) { config.tracing.http.extraHttpHeadersToCapture = defaults.tracing.http.extraHttpHeadersToCapture; return; - } else if (!config.tracing.http.extraHttpHeadersToCapture && fromEnvVar) { + } else if (!userHeaders && fromEnvVar) { config.tracing.http.extraHttpHeadersToCapture = fromEnvVar; + return; } - if (!Array.isArray(config.tracing.http.extraHttpHeadersToCapture)) { + + if (!Array.isArray(userHeaders)) { logger.warn( // eslint-disable-next-line max-len `Invalid configuration: config.tracing.http.extraHttpHeadersToCapture is not an array, the value will be ignored: ${JSON.stringify( - config.tracing.http.extraHttpHeadersToCapture + userHeaders )}` ); config.tracing.http.extraHttpHeadersToCapture = defaults.tracing.http.extraHttpHeadersToCapture; return; } - config.tracing.http.extraHttpHeadersToCapture = config.tracing.http.extraHttpHeadersToCapture.map( - ( - s // Node.js HTTP API turns all incoming HTTP headers into lowercase. - ) => s.toLowerCase() - ); + config.tracing.http.extraHttpHeadersToCapture = userHeaders.map(s => s.toLowerCase()); } /** @@ -399,7 +418,7 @@ function normalizeTracingHttp(config) { function parseHeadersEnvVar(envVarValue) { return envVarValue .split(/[;,]/) - .map(header => header.trim()) + .map(header => header.trim().toLowerCase()) .filter(header => header !== ''); } @@ -410,10 +429,13 @@ function parseHeadersEnvVar(envVarValue) { * because it involves complex multi-step processing: * Future improvement: Consider refactoring to use a more generic resolver pattern. * + * + * @param {InstanaConfig|null} userConfig * @param {InstanaConfig} config */ -function normalizeTracingStackTrace(config) { - const tracing = config.tracing; +function normalizeTracingStackTrace(userConfig, config) { + const userTracingConfig = userConfig?.tracing; + const userGlobal = userTracingConfig?.global; const envStackTrace = process.env.INSTANA_STACK_TRACE; const envStackTraceLength = process.env.INSTANA_STACK_TRACE_LENGTH; @@ -424,34 +446,34 @@ function normalizeTracingStackTrace(config) { if (result.isValid) { const normalized = configNormalizers.stackTrace.normalizeStackTraceModeFromEnv(envStackTrace); if (normalized !== null) { - tracing.stackTrace = normalized; + config.tracing.stackTrace = normalized; } else { - tracing.stackTrace = defaults.tracing.stackTrace; + config.tracing.stackTrace = defaults.tracing.stackTrace; } } else { logger.warn(`Invalid env INSTANA_STACK_TRACE: ${result.error}`); - tracing.stackTrace = defaults.tracing.stackTrace; + config.tracing.stackTrace = defaults.tracing.stackTrace; } - } else if (tracing.global?.stackTrace !== undefined) { - const result = validateStackTraceMode(tracing.global.stackTrace); + } else if (userGlobal?.stackTrace !== undefined) { + const result = validateStackTraceMode(userGlobal.stackTrace); if (result.isValid) { - const normalized = configNormalizers.stackTrace.normalizeStackTraceMode(config); + const normalized = configNormalizers.stackTrace.normalizeStackTraceMode(userConfig); if (normalized !== null) { - tracing.stackTrace = normalized; + config.tracing.stackTrace = normalized; } else { - tracing.stackTrace = defaults.tracing.stackTrace; + config.tracing.stackTrace = defaults.tracing.stackTrace; } } else { logger.warn(`Invalid config.tracing.global.stackTrace: ${result.error}`); - tracing.stackTrace = defaults.tracing.stackTrace; + config.tracing.stackTrace = defaults.tracing.stackTrace; } } else { - tracing.stackTrace = defaults.tracing.stackTrace; + config.tracing.stackTrace = defaults.tracing.stackTrace; } - const isLegacyLengthDefined = tracing.stackTraceLength !== undefined; - const stackTraceConfigValue = tracing.global?.stackTraceLength || tracing.stackTraceLength; + const isLegacyLengthDefined = userTracingConfig?.stackTraceLength !== undefined; + const stackTraceConfigValue = userGlobal?.stackTraceLength || userTracingConfig?.stackTraceLength; if (envStackTraceLength !== undefined) { const result = validateStackTraceLength(envStackTraceLength); @@ -459,13 +481,13 @@ function normalizeTracingStackTrace(config) { if (result.isValid) { const normalized = configNormalizers.stackTrace.normalizeStackTraceLengthFromEnv(envStackTraceLength); if (normalized !== null) { - tracing.stackTraceLength = normalized; + config.tracing.stackTraceLength = normalized; } else { - tracing.stackTraceLength = defaults.tracing.stackTraceLength; + config.tracing.stackTraceLength = defaults.tracing.stackTraceLength; } } else { logger.warn(`Invalid env INSTANA_STACK_TRACE_LENGTH: ${result.error}`); - tracing.stackTraceLength = defaults.tracing.stackTraceLength; + config.tracing.stackTraceLength = defaults.tracing.stackTraceLength; } } else if (stackTraceConfigValue !== undefined) { if (isLegacyLengthDefined) { @@ -479,18 +501,18 @@ function normalizeTracingStackTrace(config) { const result = validateStackTraceLength(stackTraceConfigValue); if (result.isValid) { - const normalized = configNormalizers.stackTrace.normalizeStackTraceLength(config); + const normalized = configNormalizers.stackTrace.normalizeStackTraceLength(userConfig); if (normalized !== null) { - tracing.stackTraceLength = normalized; + config.tracing.stackTraceLength = normalized; } else { - tracing.stackTraceLength = defaults.tracing.stackTraceLength; + config.tracing.stackTraceLength = defaults.tracing.stackTraceLength; } } else { logger.warn(`Invalid stackTraceLength value: ${result.error}`); - tracing.stackTraceLength = defaults.tracing.stackTraceLength; + config.tracing.stackTraceLength = defaults.tracing.stackTraceLength; } } else { - tracing.stackTraceLength = defaults.tracing.stackTraceLength; + config.tracing.stackTraceLength = defaults.tracing.stackTraceLength; } } @@ -499,10 +521,15 @@ function normalizeTracingStackTrace(config) { * because it involves complex multi-step processing: * Future improvement: Consider refactoring to use a more generic resolver pattern. * + * @param {InstanaConfig|null} userConfig * @param {InstanaConfig} config */ -function normalizeDisableTracing(config) { - const disableConfig = configNormalizers.disable.normalize(config); +function normalizeDisableTracing(userConfig, config) { + const tempConfig = { + tracing: userConfig?.tracing ? { ...userConfig.tracing } : {} + }; + + const disableConfig = configNormalizers.disable.normalize(tempConfig); // If tracing is globally disabled (via `disable: true` or INSTANA_TRACING_DISABLE=true ), // mark `tracing.enabled` as false and clear any specific disable rules. @@ -520,37 +547,41 @@ function normalizeDisableTracing(config) { } /** + * @param {InstanaTracingOption} userTracingConfig * @param {InstanaConfig} config */ -function normalizeSpanBatchingEnabled(config) { +function normalizeSpanBatchingEnabled(userTracingConfig, config) { config.tracing.spanBatchingEnabled = util.resolveBooleanConfig({ envVar: 'INSTANA_SPANBATCHING_ENABLED', - configValue: config.tracing.spanBatchingEnabled, + configValue: userTracingConfig?.spanBatchingEnabled, defaultValue: defaults.tracing.spanBatchingEnabled, configPath: 'config.tracing.spanBatchingEnabled' }); } /** + * @param {InstanaTracingOption} userTracingConfig * @param {InstanaConfig} config */ -function normalizeDisableW3cTraceCorrelation(config) { +function normalizeDisableW3cTraceCorrelation(userTracingConfig, config) { config.tracing.disableW3cTraceCorrelation = util.resolveBooleanConfigWithTruthyEnv({ envVar: 'INSTANA_DISABLE_W3C_TRACE_CORRELATION', - configValue: config.tracing.disableW3cTraceCorrelation, + configValue: userTracingConfig?.disableW3cTraceCorrelation, defaultValue: defaults.tracing.disableW3cTraceCorrelation }); } /** + * @param {InstanaTracingOption} userTracingConfig * @param {InstanaConfig} config */ -function normalizeTracingKafka(config) { - config.tracing.kafka = config.tracing.kafka || {}; +function normalizeTracingKafka(userTracingConfig, config) { + const userKafka = userTracingConfig?.kafka; + config.tracing.kafka = {}; config.tracing.kafka.traceCorrelation = util.resolveBooleanConfig({ envVar: 'INSTANA_KAFKA_TRACE_CORRELATION', - configValue: config.tracing.kafka.traceCorrelation, + configValue: userKafka?.traceCorrelation, defaultValue: defaults.tracing.kafka.traceCorrelation, configPath: 'config.tracing.kafka.traceCorrelation' }); @@ -561,12 +592,12 @@ function normalizeTracingKafka(config) { * because it involves complex multi-step processing: * Future improvement: Consider refactoring to use a more generic resolver pattern. * + * @param {InstanaConfig|null} userConfig * @param {InstanaConfig} config */ -function normalizeSecrets(config) { - if (config.secrets == null) { - config.secrets = {}; - } +function normalizeSecrets(userConfig, config) { + const userSecrets = userConfig?.secrets; + config.secrets = {}; /** @type {InstanaSecretsOption} */ let fromEnvVar = {}; @@ -574,28 +605,36 @@ function normalizeSecrets(config) { fromEnvVar = parseSecretsEnvVar(process.env.INSTANA_SECRETS); } - config.secrets.matcherMode = config.secrets.matcherMode || fromEnvVar.matcherMode || defaults.secrets.matcherMode; - config.secrets.keywords = config.secrets.keywords || fromEnvVar.keywords || defaults.secrets.keywords; + const matcherMode = userSecrets?.matcherMode || fromEnvVar.matcherMode || defaults.secrets.matcherMode; + + const keywords = userSecrets?.keywords || fromEnvVar.keywords || defaults.secrets.keywords; - if (typeof config.secrets.matcherMode !== 'string') { + if (typeof matcherMode !== 'string') { logger.warn( // eslint-disable-next-line max-len - `The value of config.secrets.matcherMode ("${config.secrets.matcherMode}") is not a string. Assuming the default value ${defaults.secrets.matcherMode}.` + `The value of config.secrets.matcherMode ("${matcherMode}") is not a string. Assuming the default value ${defaults.secrets.matcherMode}.` ); config.secrets.matcherMode = defaults.secrets.matcherMode; - } else if (validSecretsMatcherModes.indexOf(config.secrets.matcherMode) < 0) { + } else if (validSecretsMatcherModes.indexOf(matcherMode) < 0) { logger.warn( // eslint-disable-next-line max-len - `The value of config.secrets.matcherMode (or the matcher mode parsed from INSTANA_SECRETS) (${config.secrets.matcherMode}) is not a supported matcher mode. Assuming the default value ${defaults.secrets.matcherMode}.` + `The value of config.secrets.matcherMode (or the matcher mode parsed from INSTANA_SECRETS) (${matcherMode}) is not a supported matcher mode. Assuming the default value ${defaults.secrets.matcherMode}.` ); config.secrets.matcherMode = defaults.secrets.matcherMode; - } else if (!Array.isArray(config.secrets.keywords)) { + } else { + config.secrets.matcherMode = matcherMode; + } + + if (!Array.isArray(keywords)) { logger.warn( // eslint-disable-next-line max-len - `The value of config.secrets.keywords (${config.secrets.keywords}) is not an array. Assuming the default value ${defaults.secrets.keywords}.` + `The value of config.secrets.keywords (${keywords}) is not an array. Assuming the default value ${defaults.secrets.keywords}.` ); config.secrets.keywords = defaults.secrets.keywords; + } else { + config.secrets.keywords = keywords; } + if (config.secrets.matcherMode === 'none') { config.secrets.keywords = []; } @@ -653,27 +692,25 @@ function parseSecretsEnvVar(envVarValue) { * because it involves complex multi-step processing: * Future improvement: Consider refactoring to use a more generic resolver pattern. * + * @param {InstanaTracingOption} userTracingConfig * @param {InstanaConfig} config */ -function normalizeIgnoreEndpoints(config) { - if (!config.tracing.ignoreEndpoints) { - config.tracing.ignoreEndpoints = {}; - } +function normalizeIgnoreEndpoints(userTracingConfig, config) { + const userIgnoreEndpoints = userTracingConfig?.ignoreEndpoints; - const ignoreEndpointsConfig = config.tracing.ignoreEndpoints; - - if (typeof ignoreEndpointsConfig !== 'object' || Array.isArray(ignoreEndpointsConfig)) { + if (userIgnoreEndpoints && (typeof userIgnoreEndpoints !== 'object' || Array.isArray(userIgnoreEndpoints))) { logger.warn( `Invalid tracing.ignoreEndpoints configuration. Expected an object, but received: ${JSON.stringify( - ignoreEndpointsConfig + userIgnoreEndpoints )}` ); config.tracing.ignoreEndpoints = {}; return; } + // Case 1: Use in-code configuration if available - if (Object.keys(ignoreEndpointsConfig).length) { - config.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.normalizeConfig(ignoreEndpointsConfig); + if (userIgnoreEndpoints && Object.keys(userIgnoreEndpoints).length) { + config.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.normalizeConfig(userIgnoreEndpoints); logger.debug(`Ignore endpoints have been configured: ${JSON.stringify(config.tracing.ignoreEndpoints)}`); return; } @@ -685,7 +722,6 @@ function normalizeIgnoreEndpoints(config) { config.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.fromYaml( process.env.INSTANA_IGNORE_ENDPOINTS_PATH ); - logger.debug(`Ignore endpoints have been configured: ${JSON.stringify(config.tracing.ignoreEndpoints)}`); return; } @@ -696,40 +732,47 @@ function normalizeIgnoreEndpoints(config) { if (process.env.INSTANA_IGNORE_ENDPOINTS) { config.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.fromEnv(process.env.INSTANA_IGNORE_ENDPOINTS); logger.debug(`Ignore endpoints have been configured: ${JSON.stringify(config.tracing.ignoreEndpoints)}`); + return; } + + config.tracing.ignoreEndpoints = {}; } /** + * @param {InstanaTracingOption} userTracingConfig * @param {InstanaConfig} config */ -function normalizeIgnoreEndpointsDisableSuppression(config) { +function normalizeIgnoreEndpointsDisableSuppression(userTracingConfig, config) { config.tracing.ignoreEndpointsDisableSuppression = util.resolveBooleanConfig({ envVar: 'INSTANA_IGNORE_ENDPOINTS_DISABLE_SUPPRESSION', - configValue: config.tracing.ignoreEndpointsDisableSuppression, + configValue: userTracingConfig?.ignoreEndpointsDisableSuppression, defaultValue: defaults.tracing.ignoreEndpointsDisableSuppression, configPath: 'config.tracing.ignoreEndpointsDisableSuppression' }); } /** + + * @param {InstanaTracingOption} userTracingConfig * @param {InstanaConfig} config */ -function normalizeDisableEOLEvents(config) { +function normalizeDisableEOLEvents(userTracingConfig, config) { config.tracing.disableEOLEvents = util.resolveBooleanConfig({ envVar: 'INSTANA_TRACING_DISABLE_EOL_EVENTS', - configValue: config.tracing.disableEOLEvents, + configValue: userTracingConfig?.disableEOLEvents, defaultValue: defaults.tracing.disableEOLEvents, configPath: 'config.tracing.disableEOLEvents' }); } /** + * @param {InstanaConfig|null} userConfig * @param {InstanaConfig} config */ -function normalizePreloadOpentelemetry(config) { - if (config.preloadOpentelemetry === true) { - return; +function normalizePreloadOpentelemetry(userConfig, config) { + if (userConfig?.preloadOpentelemetry === true) { + config.preloadOpentelemetry = true; + } else { + config.preloadOpentelemetry = defaults.preloadOpentelemetry; } - - config.preloadOpentelemetry = defaults.preloadOpentelemetry; } From 16f2407d273a12d5e50917f63a73aa2921cfe778 Mon Sep 17 00:00:00 2001 From: Arya Date: Tue, 31 Mar 2026 16:53:24 +0530 Subject: [PATCH 2/4] chore: refactor --- packages/core/src/config/index.js | 402 ++++++++++++++++-------------- 1 file changed, 210 insertions(+), 192 deletions(-) diff --git a/packages/core/src/config/index.js b/packages/core/src/config/index.js index bddba31b00..4cd80baefd 100644 --- a/packages/core/src/config/index.js +++ b/packages/core/src/config/index.js @@ -157,215 +157,221 @@ module.exports.normalize = (userConfig, defaultsOverride = {}) => { } /** @type InstanaConfig */ - const config = {}; + const finalConfig = {}; // TODO: remove this and forward the logger via init fn. - config.logger = logger; + finalConfig.logger = logger; - // Each normalize function receives userConfig (read-only) and config (write target) - normalizeServiceName(userConfig, config); - normalizePackageJsonPath(userConfig, config); - normalizeMetricsConfig(userConfig, config); - normalizeTracingConfig(userConfig, config); - normalizeSecrets(userConfig, config); - normalizePreloadOpentelemetry(userConfig, config); + normalizeServiceName(userConfig, defaults, finalConfig); + normalizePackageJsonPath(userConfig, defaults, finalConfig); + normalizeMetricsConfig(userConfig, defaults, finalConfig); + normalizeTracingConfig(userConfig, defaults, finalConfig); + normalizeSecrets(userConfig, defaults, finalConfig); + normalizePreloadOpentelemetry(userConfig, defaults, finalConfig); - return config; + return finalConfig; }; /** * @param {InstanaConfig|null} userConfig - * @param {InstanaConfig} config + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeServiceName(userConfig, config) { +function normalizeServiceName(userConfig, defaultConfig, finalConfig) { const userValue = userConfig?.serviceName; if (userValue != null) { if (typeof userValue === 'string') { - config.serviceName = userValue; + finalConfig.serviceName = userValue; } else { logger.warn(`Invalid configuration: config.serviceName is not a string, the value will be ignored: ${userValue}`); - config.serviceName = defaults.serviceName; + finalConfig.serviceName = defaultConfig.serviceName; } } else if (process.env.INSTANA_SERVICE_NAME) { - config.serviceName = process.env.INSTANA_SERVICE_NAME; + finalConfig.serviceName = process.env.INSTANA_SERVICE_NAME; } else { - config.serviceName = defaults.serviceName; + finalConfig.serviceName = defaultConfig.serviceName; } } /** * @param {InstanaConfig|null} userConfig - * @param {InstanaConfig} config + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizePackageJsonPath(userConfig, config) { +function normalizePackageJsonPath(userConfig, defaultConfig, finalConfig) { const userValue = userConfig?.packageJsonPath; if (userValue != null) { if (typeof userValue === 'string') { - config.packageJsonPath = userValue; + finalConfig.packageJsonPath = userValue; } else { logger.warn( - // eslint-disable-next-line max-len `Invalid configuration: config.packageJsonPath is not a string, the value will be ignored: ${userValue}` ); - config.packageJsonPath = null; + finalConfig.packageJsonPath = defaultConfig.packageJsonPath; } } else if (process.env.INSTANA_PACKAGE_JSON_PATH) { - config.packageJsonPath = process.env.INSTANA_PACKAGE_JSON_PATH; + finalConfig.packageJsonPath = process.env.INSTANA_PACKAGE_JSON_PATH; } else { - config.packageJsonPath = null; + finalConfig.packageJsonPath = defaultConfig.packageJsonPath; } } /** * @param {InstanaConfig|null} userConfig - * @param {InstanaConfig} config + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeMetricsConfig(userConfig, config) { +function normalizeMetricsConfig(userConfig, defaultConfig, finalConfig) { const userMetrics = userConfig?.metrics; - config.metrics = {}; + finalConfig.metrics = {}; - config.metrics.transmissionDelay = util.resolveNumericConfig({ + finalConfig.metrics.transmissionDelay = util.resolveNumericConfig({ envVar: 'INSTANA_METRICS_TRANSMISSION_DELAY', configValue: userMetrics?.transmissionDelay, - defaultValue: defaults.metrics.transmissionDelay, + defaultValue: defaultConfig.metrics.transmissionDelay, configPath: 'config.metrics.transmissionDelay' }); - config.metrics.timeBetweenHealthcheckCalls = - userMetrics?.timeBetweenHealthcheckCalls || defaults.metrics.timeBetweenHealthcheckCalls; + finalConfig.metrics.timeBetweenHealthcheckCalls = + userMetrics?.timeBetweenHealthcheckCalls || defaultConfig.metrics.timeBetweenHealthcheckCalls; } /** - * @param {InstanaConfig|null} userConfig - * @param {InstanaConfig} config - */ -function normalizeTracingConfig(userConfig, config) { - const userTracingConfig = userConfig?.tracing; - - config.tracing = {}; - - normalizeTracingEnabled(userTracingConfig, config); - normalizeUseOpentelemetry(userTracingConfig, config); - normalizeDisableTracing(userConfig, config); - normalizeAutomaticTracingEnabled(userTracingConfig, config); - normalizeActivateImmediately(userTracingConfig, config); - normalizeTracingTransmission(userTracingConfig, config); - normalizeTracingHttp(userTracingConfig, config); - normalizeTracingStackTrace(userConfig, config); - normalizeSpanBatchingEnabled(userTracingConfig, config); - normalizeDisableW3cTraceCorrelation(userTracingConfig, config); - normalizeTracingKafka(userTracingConfig, config); - normalizeAllowRootExitSpan(userTracingConfig, config); - normalizeIgnoreEndpoints(userTracingConfig, config); - normalizeIgnoreEndpointsDisableSuppression(userTracingConfig, config); - normalizeDisableEOLEvents(userTracingConfig, config); + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig + */ +function normalizeTracingConfig(userConfig, defaultConfig, finalConfig) { + finalConfig.tracing = {}; + + normalizeTracingEnabled(userConfig, defaultConfig, finalConfig); + normalizeUseOpentelemetry(userConfig, defaultConfig, finalConfig); + normalizeDisableTracing(userConfig, defaultConfig, finalConfig); + normalizeAutomaticTracingEnabled(userConfig, defaultConfig, finalConfig); + normalizeActivateImmediately(userConfig, defaultConfig, finalConfig); + normalizeTracingTransmission(userConfig, defaultConfig, finalConfig); + normalizeTracingHttp(userConfig, defaultConfig, finalConfig); + normalizeTracingStackTrace(userConfig, defaultConfig, finalConfig); + normalizeSpanBatchingEnabled(userConfig, defaultConfig, finalConfig); + normalizeDisableW3cTraceCorrelation(userConfig, defaultConfig, finalConfig); + normalizeTracingKafka(userConfig, defaultConfig, finalConfig); + normalizeAllowRootExitSpan(userConfig, defaultConfig, finalConfig); + normalizeIgnoreEndpoints(userConfig, defaultConfig, finalConfig); + normalizeIgnoreEndpointsDisableSuppression(userConfig, defaultConfig, finalConfig); + normalizeDisableEOLEvents(userConfig, defaultConfig, finalConfig); } /** - * @param {InstanaTracingOption} userTracingConfig - * @param {InstanaConfig} config + * @param {InstanaConfig|null} userConfig + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeTracingEnabled(userTracingConfig, config) { - config.tracing.enabled = util.resolveBooleanConfigWithInvertedEnv({ +function normalizeTracingEnabled(userConfig, defaultConfig, finalConfig) { + finalConfig.tracing.enabled = util.resolveBooleanConfigWithInvertedEnv({ envVar: 'INSTANA_TRACING_DISABLE', - configValue: userTracingConfig?.enabled, - defaultValue: defaults.tracing.enabled, + configValue: userConfig?.tracing?.enabled, + defaultValue: defaultConfig.tracing.enabled, configPath: 'config.tracing.enabled' }); } /** - * @param {InstanaTracingOption} userTracingConfig - * @param {InstanaConfig} config + * @param {InstanaConfig|null} userConfig + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeAllowRootExitSpan(userTracingConfig, config) { - config.tracing.allowRootExitSpan = util.resolveBooleanConfig({ +function normalizeAllowRootExitSpan(userConfig, defaultConfig, finalConfig) { + finalConfig.tracing.allowRootExitSpan = util.resolveBooleanConfig({ envVar: 'INSTANA_ALLOW_ROOT_EXIT_SPAN', - configValue: userTracingConfig?.allowRootExitSpan, - defaultValue: defaults.tracing.allowRootExitSpan, + configValue: userConfig?.tracing?.allowRootExitSpan, + defaultValue: defaultConfig.tracing.allowRootExitSpan, configPath: 'config.tracing.allowRootExitSpan' }); } /** - * @param {InstanaTracingOption} userTracingConfig - * @param {InstanaConfig} config + * @param {InstanaConfig|null} userConfig + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeUseOpentelemetry(userTracingConfig, config) { - config.tracing.useOpentelemetry = util.resolveBooleanConfigWithInvertedEnv({ +function normalizeUseOpentelemetry(userConfig, defaultConfig, finalConfig) { + finalConfig.tracing.useOpentelemetry = util.resolveBooleanConfigWithInvertedEnv({ envVar: 'INSTANA_DISABLE_USE_OPENTELEMETRY', - configValue: userTracingConfig?.useOpentelemetry, - defaultValue: defaults.tracing.useOpentelemetry, + configValue: userConfig?.tracing?.useOpentelemetry, + defaultValue: defaultConfig.tracing.useOpentelemetry, configPath: 'config.tracing.useOpentelemetry' }); } /** - * @param {InstanaTracingOption} userTracingConfig - * @param {InstanaConfig} config + * @param {InstanaConfig|null} userConfig + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeAutomaticTracingEnabled(userTracingConfig, config) { - if (!config.tracing.enabled) { - logger.info('Not enabling automatic tracing as tracing in general is explicitly disabled via config.'); - config.tracing.automaticTracingEnabled = false; +function normalizeAutomaticTracingEnabled(userConfig, defaultConfig, finalConfig) { + if (!finalConfig.tracing.enabled) { + logger.info('Not enabling automatic tracing as tracing in general is explicitly disabled via finalConfig.'); + finalConfig.tracing.automaticTracingEnabled = false; return; } - config.tracing.automaticTracingEnabled = util.resolveBooleanConfigWithInvertedEnv({ + finalConfig.tracing.automaticTracingEnabled = util.resolveBooleanConfigWithInvertedEnv({ envVar: 'INSTANA_DISABLE_AUTO_INSTR', - configValue: userTracingConfig?.automaticTracingEnabled, - defaultValue: defaults.tracing.automaticTracingEnabled, + configValue: userConfig?.tracing?.automaticTracingEnabled, + defaultValue: defaultConfig.tracing.automaticTracingEnabled, configPath: 'config.tracing.automaticTracingEnabled' }); } /** - * @param {InstanaTracingOption} userTracingConfig - * @param {InstanaConfig} config + * @param {InstanaConfig|null} userConfig + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeActivateImmediately(userTracingConfig, config) { - if (!config.tracing.enabled) { - config.tracing.activateImmediately = false; +function normalizeActivateImmediately(userConfig, defaultConfig, finalConfig) { + if (!finalConfig.tracing.enabled) { + finalConfig.tracing.activateImmediately = false; return; } - config.tracing.activateImmediately = util.resolveBooleanConfig({ + finalConfig.tracing.activateImmediately = util.resolveBooleanConfig({ envVar: 'INSTANA_TRACE_IMMEDIATELY', - configValue: userTracingConfig?.activateImmediately, - defaultValue: defaults.tracing.activateImmediately, + configValue: userConfig?.tracing?.activateImmediately, + defaultValue: defaultConfig.tracing.activateImmediately, configPath: 'config.tracing.activateImmediately' }); } /** - * @param {InstanaTracingOption} userTracingConfig - * @param {InstanaConfig} config + * @param {InstanaConfig|null} userConfig + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeTracingTransmission(userTracingConfig, config) { - config.tracing.maxBufferedSpans = userTracingConfig?.maxBufferedSpans || defaults.tracing.maxBufferedSpans; +function normalizeTracingTransmission(userConfig, defaultConfig, finalConfig) { + finalConfig.tracing.maxBufferedSpans = + userConfig?.tracing?.maxBufferedSpans || defaultConfig.tracing.maxBufferedSpans; - config.tracing.transmissionDelay = util.resolveNumericConfig({ + finalConfig.tracing.transmissionDelay = util.resolveNumericConfig({ envVar: 'INSTANA_TRACING_TRANSMISSION_DELAY', - configValue: userTracingConfig?.transmissionDelay, - defaultValue: defaults.tracing.transmissionDelay, + configValue: userConfig?.tracing?.transmissionDelay, + defaultValue: defaultConfig.tracing.transmissionDelay, configPath: 'config.tracing.transmissionDelay' }); - config.tracing.forceTransmissionStartingAt = util.resolveNumericConfig({ + finalConfig.tracing.forceTransmissionStartingAt = util.resolveNumericConfig({ envVar: 'INSTANA_FORCE_TRANSMISSION_STARTING_AT', - configValue: userTracingConfig?.forceTransmissionStartingAt, - defaultValue: defaults.tracing.forceTransmissionStartingAt, + configValue: userConfig?.tracing?.forceTransmissionStartingAt, + defaultValue: defaultConfig.tracing.forceTransmissionStartingAt, configPath: 'config.tracing.forceTransmissionStartingAt' }); - config.tracing.initialTransmissionDelay = util.resolveNumericConfig({ + finalConfig.tracing.initialTransmissionDelay = util.resolveNumericConfig({ envVar: 'INSTANA_TRACING_INITIAL_TRANSMISSION_DELAY', - configValue: userTracingConfig?.initialTransmissionDelay, - defaultValue: defaults.tracing.initialTransmissionDelay, + configValue: userConfig?.tracing?.initialTransmissionDelay, + defaultValue: defaultConfig.tracing.initialTransmissionDelay, configPath: 'config.tracing.initialTransmissionDelay' }); } @@ -375,12 +381,13 @@ function normalizeTracingTransmission(userTracingConfig, config) { * because it involves complex multi-step processing: * Future improvement: Consider refactoring to use a more generic resolver pattern. * - * @param {InstanaTracingOption} userTracingConfig - * @param {InstanaConfig} config + * @param {InstanaConfig|null} userConfig + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeTracingHttp(userTracingConfig, config) { - const userHttp = userTracingConfig?.http; - config.tracing.http = {}; +function normalizeTracingHttp(userConfig, defaultConfig, finalConfig) { + const userHttp = userConfig?.tracing?.http; + finalConfig.tracing.http = {}; let fromEnvVar; if (process.env.INSTANA_EXTRA_HTTP_HEADERS) { @@ -390,10 +397,10 @@ function normalizeTracingHttp(userTracingConfig, config) { const userHeaders = userHttp?.extraHttpHeadersToCapture; if (!userHeaders && !fromEnvVar) { - config.tracing.http.extraHttpHeadersToCapture = defaults.tracing.http.extraHttpHeadersToCapture; + finalConfig.tracing.http.extraHttpHeadersToCapture = defaultConfig.tracing.http.extraHttpHeadersToCapture; return; } else if (!userHeaders && fromEnvVar) { - config.tracing.http.extraHttpHeadersToCapture = fromEnvVar; + finalConfig.tracing.http.extraHttpHeadersToCapture = fromEnvVar; return; } @@ -404,11 +411,11 @@ function normalizeTracingHttp(userTracingConfig, config) { userHeaders )}` ); - config.tracing.http.extraHttpHeadersToCapture = defaults.tracing.http.extraHttpHeadersToCapture; + finalConfig.tracing.http.extraHttpHeadersToCapture = defaultConfig.tracing.http.extraHttpHeadersToCapture; return; } - config.tracing.http.extraHttpHeadersToCapture = userHeaders.map(s => s.toLowerCase()); + finalConfig.tracing.http.extraHttpHeadersToCapture = userHeaders.map(s => s.toLowerCase()); } /** @@ -431,9 +438,10 @@ function parseHeadersEnvVar(envVarValue) { * * * @param {InstanaConfig|null} userConfig - * @param {InstanaConfig} config + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeTracingStackTrace(userConfig, config) { +function normalizeTracingStackTrace(userConfig, defaultConfig, finalConfig) { const userTracingConfig = userConfig?.tracing; const userGlobal = userTracingConfig?.global; @@ -446,13 +454,13 @@ function normalizeTracingStackTrace(userConfig, config) { if (result.isValid) { const normalized = configNormalizers.stackTrace.normalizeStackTraceModeFromEnv(envStackTrace); if (normalized !== null) { - config.tracing.stackTrace = normalized; + finalConfig.tracing.stackTrace = normalized; } else { - config.tracing.stackTrace = defaults.tracing.stackTrace; + finalConfig.tracing.stackTrace = defaultConfig.tracing.stackTrace; } } else { logger.warn(`Invalid env INSTANA_STACK_TRACE: ${result.error}`); - config.tracing.stackTrace = defaults.tracing.stackTrace; + finalConfig.tracing.stackTrace = defaultConfig.tracing.stackTrace; } } else if (userGlobal?.stackTrace !== undefined) { const result = validateStackTraceMode(userGlobal.stackTrace); @@ -460,16 +468,16 @@ function normalizeTracingStackTrace(userConfig, config) { if (result.isValid) { const normalized = configNormalizers.stackTrace.normalizeStackTraceMode(userConfig); if (normalized !== null) { - config.tracing.stackTrace = normalized; + finalConfig.tracing.stackTrace = normalized; } else { - config.tracing.stackTrace = defaults.tracing.stackTrace; + finalConfig.tracing.stackTrace = defaultConfig.tracing.stackTrace; } } else { logger.warn(`Invalid config.tracing.global.stackTrace: ${result.error}`); - config.tracing.stackTrace = defaults.tracing.stackTrace; + finalConfig.tracing.stackTrace = defaultConfig.tracing.stackTrace; } } else { - config.tracing.stackTrace = defaults.tracing.stackTrace; + finalConfig.tracing.stackTrace = defaultConfig.tracing.stackTrace; } const isLegacyLengthDefined = userTracingConfig?.stackTraceLength !== undefined; @@ -481,13 +489,13 @@ function normalizeTracingStackTrace(userConfig, config) { if (result.isValid) { const normalized = configNormalizers.stackTrace.normalizeStackTraceLengthFromEnv(envStackTraceLength); if (normalized !== null) { - config.tracing.stackTraceLength = normalized; + finalConfig.tracing.stackTraceLength = normalized; } else { - config.tracing.stackTraceLength = defaults.tracing.stackTraceLength; + finalConfig.tracing.stackTraceLength = defaultConfig.tracing.stackTraceLength; } } else { logger.warn(`Invalid env INSTANA_STACK_TRACE_LENGTH: ${result.error}`); - config.tracing.stackTraceLength = defaults.tracing.stackTraceLength; + finalConfig.tracing.stackTraceLength = defaultConfig.tracing.stackTraceLength; } } else if (stackTraceConfigValue !== undefined) { if (isLegacyLengthDefined) { @@ -503,16 +511,16 @@ function normalizeTracingStackTrace(userConfig, config) { if (result.isValid) { const normalized = configNormalizers.stackTrace.normalizeStackTraceLength(userConfig); if (normalized !== null) { - config.tracing.stackTraceLength = normalized; + finalConfig.tracing.stackTraceLength = normalized; } else { - config.tracing.stackTraceLength = defaults.tracing.stackTraceLength; + finalConfig.tracing.stackTraceLength = defaultConfig.tracing.stackTraceLength; } } else { logger.warn(`Invalid stackTraceLength value: ${result.error}`); - config.tracing.stackTraceLength = defaults.tracing.stackTraceLength; + finalConfig.tracing.stackTraceLength = defaultConfig.tracing.stackTraceLength; } } else { - config.tracing.stackTraceLength = defaults.tracing.stackTraceLength; + finalConfig.tracing.stackTraceLength = defaultConfig.tracing.stackTraceLength; } } @@ -522,9 +530,10 @@ function normalizeTracingStackTrace(userConfig, config) { * Future improvement: Consider refactoring to use a more generic resolver pattern. * * @param {InstanaConfig|null} userConfig - * @param {InstanaConfig} config + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeDisableTracing(userConfig, config) { +function normalizeDisableTracing(userConfig, defaultConfig, finalConfig) { const tempConfig = { tracing: userConfig?.tracing ? { ...userConfig.tracing } : {} }; @@ -534,55 +543,58 @@ function normalizeDisableTracing(userConfig, config) { // If tracing is globally disabled (via `disable: true` or INSTANA_TRACING_DISABLE=true ), // mark `tracing.enabled` as false and clear any specific disable rules. if (disableConfig === true) { - config.tracing.enabled = false; - config.tracing.disable = {}; + finalConfig.tracing.enabled = false; + finalConfig.tracing.disable = {}; return; } if (typeof disableConfig === 'object' && (disableConfig.instrumentations?.length || disableConfig.groups?.length)) { - config.tracing.disable = disableConfig; + finalConfig.tracing.disable = disableConfig; return; } - config.tracing.disable = defaults.tracing.disable; + finalConfig.tracing.disable = defaultConfig.tracing.disable; } /** - * @param {InstanaTracingOption} userTracingConfig - * @param {InstanaConfig} config + * @param {InstanaConfig|null} userConfig + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeSpanBatchingEnabled(userTracingConfig, config) { - config.tracing.spanBatchingEnabled = util.resolveBooleanConfig({ +function normalizeSpanBatchingEnabled(userConfig, defaultConfig, finalConfig) { + finalConfig.tracing.spanBatchingEnabled = util.resolveBooleanConfig({ envVar: 'INSTANA_SPANBATCHING_ENABLED', - configValue: userTracingConfig?.spanBatchingEnabled, - defaultValue: defaults.tracing.spanBatchingEnabled, + configValue: userConfig?.tracing?.spanBatchingEnabled, + defaultValue: defaultConfig.tracing.spanBatchingEnabled, configPath: 'config.tracing.spanBatchingEnabled' }); } /** - * @param {InstanaTracingOption} userTracingConfig - * @param {InstanaConfig} config + * @param {InstanaConfig|null} userConfig + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeDisableW3cTraceCorrelation(userTracingConfig, config) { - config.tracing.disableW3cTraceCorrelation = util.resolveBooleanConfigWithTruthyEnv({ +function normalizeDisableW3cTraceCorrelation(userConfig, defaultConfig, finalConfig) { + finalConfig.tracing.disableW3cTraceCorrelation = util.resolveBooleanConfigWithTruthyEnv({ envVar: 'INSTANA_DISABLE_W3C_TRACE_CORRELATION', - configValue: userTracingConfig?.disableW3cTraceCorrelation, - defaultValue: defaults.tracing.disableW3cTraceCorrelation + configValue: userConfig?.tracing?.disableW3cTraceCorrelation, + defaultValue: defaultConfig.tracing.disableW3cTraceCorrelation }); } /** - * @param {InstanaTracingOption} userTracingConfig - * @param {InstanaConfig} config + * @param {InstanaConfig|null} userConfig + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeTracingKafka(userTracingConfig, config) { - const userKafka = userTracingConfig?.kafka; - config.tracing.kafka = {}; +function normalizeTracingKafka(userConfig, defaultConfig, finalConfig) { + const userKafka = userConfig?.tracing?.kafka; + finalConfig.tracing.kafka = {}; - config.tracing.kafka.traceCorrelation = util.resolveBooleanConfig({ + finalConfig.tracing.kafka.traceCorrelation = util.resolveBooleanConfig({ envVar: 'INSTANA_KAFKA_TRACE_CORRELATION', configValue: userKafka?.traceCorrelation, - defaultValue: defaults.tracing.kafka.traceCorrelation, + defaultValue: defaultConfig.tracing.kafka.traceCorrelation, configPath: 'config.tracing.kafka.traceCorrelation' }); } @@ -593,11 +605,12 @@ function normalizeTracingKafka(userTracingConfig, config) { * Future improvement: Consider refactoring to use a more generic resolver pattern. * * @param {InstanaConfig|null} userConfig - * @param {InstanaConfig} config + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeSecrets(userConfig, config) { +function normalizeSecrets(userConfig, defaultConfig, finalConfig) { const userSecrets = userConfig?.secrets; - config.secrets = {}; + finalConfig.secrets = {}; /** @type {InstanaSecretsOption} */ let fromEnvVar = {}; @@ -605,24 +618,24 @@ function normalizeSecrets(userConfig, config) { fromEnvVar = parseSecretsEnvVar(process.env.INSTANA_SECRETS); } - const matcherMode = userSecrets?.matcherMode || fromEnvVar.matcherMode || defaults.secrets.matcherMode; + const matcherMode = userSecrets?.matcherMode || fromEnvVar.matcherMode || defaultConfig.secrets.matcherMode; - const keywords = userSecrets?.keywords || fromEnvVar.keywords || defaults.secrets.keywords; + const keywords = userSecrets?.keywords || fromEnvVar.keywords || defaultConfig.secrets.keywords; if (typeof matcherMode !== 'string') { logger.warn( // eslint-disable-next-line max-len `The value of config.secrets.matcherMode ("${matcherMode}") is not a string. Assuming the default value ${defaults.secrets.matcherMode}.` ); - config.secrets.matcherMode = defaults.secrets.matcherMode; + finalConfig.secrets.matcherMode = defaultConfig.secrets.matcherMode; } else if (validSecretsMatcherModes.indexOf(matcherMode) < 0) { logger.warn( // eslint-disable-next-line max-len `The value of config.secrets.matcherMode (or the matcher mode parsed from INSTANA_SECRETS) (${matcherMode}) is not a supported matcher mode. Assuming the default value ${defaults.secrets.matcherMode}.` ); - config.secrets.matcherMode = defaults.secrets.matcherMode; + finalConfig.secrets.matcherMode = defaultConfig.secrets.matcherMode; } else { - config.secrets.matcherMode = matcherMode; + finalConfig.secrets.matcherMode = matcherMode; } if (!Array.isArray(keywords)) { @@ -630,13 +643,13 @@ function normalizeSecrets(userConfig, config) { // eslint-disable-next-line max-len `The value of config.secrets.keywords (${keywords}) is not an array. Assuming the default value ${defaults.secrets.keywords}.` ); - config.secrets.keywords = defaults.secrets.keywords; + finalConfig.secrets.keywords = defaultConfig.secrets.keywords; } else { - config.secrets.keywords = keywords; + finalConfig.secrets.keywords = keywords; } - if (config.secrets.matcherMode === 'none') { - config.secrets.keywords = []; + if (finalConfig.secrets.matcherMode === 'none') { + finalConfig.secrets.keywords = []; } } @@ -692,11 +705,12 @@ function parseSecretsEnvVar(envVarValue) { * because it involves complex multi-step processing: * Future improvement: Consider refactoring to use a more generic resolver pattern. * - * @param {InstanaTracingOption} userTracingConfig - * @param {InstanaConfig} config + * @param {InstanaConfig|null} userConfig + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeIgnoreEndpoints(userTracingConfig, config) { - const userIgnoreEndpoints = userTracingConfig?.ignoreEndpoints; +function normalizeIgnoreEndpoints(userConfig, defaultConfig, finalConfig) { + const userIgnoreEndpoints = userConfig?.tracing?.ignoreEndpoints; if (userIgnoreEndpoints && (typeof userIgnoreEndpoints !== 'object' || Array.isArray(userIgnoreEndpoints))) { logger.warn( @@ -704,14 +718,14 @@ function normalizeIgnoreEndpoints(userTracingConfig, config) { userIgnoreEndpoints )}` ); - config.tracing.ignoreEndpoints = {}; + finalConfig.tracing.ignoreEndpoints = {}; return; } // Case 1: Use in-code configuration if available if (userIgnoreEndpoints && Object.keys(userIgnoreEndpoints).length) { - config.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.normalizeConfig(userIgnoreEndpoints); - logger.debug(`Ignore endpoints have been configured: ${JSON.stringify(config.tracing.ignoreEndpoints)}`); + finalConfig.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.normalizeConfig(userIgnoreEndpoints); + logger.debug(`Ignore endpoints have been configured: ${JSON.stringify(finalConfig.tracing.ignoreEndpoints)}`); return; } @@ -719,10 +733,10 @@ function normalizeIgnoreEndpoints(userTracingConfig, config) { // Introduced in Phase 2 for advanced filtering based on both methods and endpoints. // Also supports basic filtering for endpoints. if (process.env.INSTANA_IGNORE_ENDPOINTS_PATH) { - config.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.fromYaml( + finalConfig.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.fromYaml( process.env.INSTANA_IGNORE_ENDPOINTS_PATH ); - logger.debug(`Ignore endpoints have been configured: ${JSON.stringify(config.tracing.ignoreEndpoints)}`); + logger.debug(`Ignore endpoints have been configured: ${JSON.stringify(finalConfig.tracing.ignoreEndpoints)}`); return; } @@ -730,49 +744,53 @@ function normalizeIgnoreEndpoints(userTracingConfig, config) { // Introduced in Phase 1 for basic filtering based only on operations (e.g., `redis.get`, `kafka.consume`). // Provides a simple way to configure ignored operations via environment variables. if (process.env.INSTANA_IGNORE_ENDPOINTS) { - config.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.fromEnv(process.env.INSTANA_IGNORE_ENDPOINTS); - logger.debug(`Ignore endpoints have been configured: ${JSON.stringify(config.tracing.ignoreEndpoints)}`); + finalConfig.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.fromEnv( + process.env.INSTANA_IGNORE_ENDPOINTS + ); + logger.debug(`Ignore endpoints have been configured: ${JSON.stringify(finalConfig.tracing.ignoreEndpoints)}`); return; } - config.tracing.ignoreEndpoints = {}; + finalConfig.tracing.ignoreEndpoints = defaultConfig.tracing.ignoreEndpoints; } /** - * @param {InstanaTracingOption} userTracingConfig - * @param {InstanaConfig} config + * @param {InstanaConfig|null} userConfig + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeIgnoreEndpointsDisableSuppression(userTracingConfig, config) { - config.tracing.ignoreEndpointsDisableSuppression = util.resolveBooleanConfig({ +function normalizeIgnoreEndpointsDisableSuppression(userConfig, defaultConfig, finalConfig) { + finalConfig.tracing.ignoreEndpointsDisableSuppression = util.resolveBooleanConfig({ envVar: 'INSTANA_IGNORE_ENDPOINTS_DISABLE_SUPPRESSION', - configValue: userTracingConfig?.ignoreEndpointsDisableSuppression, - defaultValue: defaults.tracing.ignoreEndpointsDisableSuppression, + configValue: userConfig?.tracing?.ignoreEndpointsDisableSuppression, + defaultValue: defaultConfig.tracing.ignoreEndpointsDisableSuppression, configPath: 'config.tracing.ignoreEndpointsDisableSuppression' }); } /** - - * @param {InstanaTracingOption} userTracingConfig - * @param {InstanaConfig} config + * @param {InstanaConfig|null} userConfig + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizeDisableEOLEvents(userTracingConfig, config) { - config.tracing.disableEOLEvents = util.resolveBooleanConfig({ +function normalizeDisableEOLEvents(userConfig, defaultConfig, finalConfig) { + finalConfig.tracing.disableEOLEvents = util.resolveBooleanConfig({ envVar: 'INSTANA_TRACING_DISABLE_EOL_EVENTS', - configValue: userTracingConfig?.disableEOLEvents, - defaultValue: defaults.tracing.disableEOLEvents, + configValue: userConfig?.tracing?.disableEOLEvents, + defaultValue: defaultConfig.tracing.disableEOLEvents, configPath: 'config.tracing.disableEOLEvents' }); } /** * @param {InstanaConfig|null} userConfig - * @param {InstanaConfig} config + * @param {InstanaConfig} defaultConfig + * @param {InstanaConfig} finalConfig */ -function normalizePreloadOpentelemetry(userConfig, config) { +function normalizePreloadOpentelemetry(userConfig, defaultConfig, finalConfig) { if (userConfig?.preloadOpentelemetry === true) { - config.preloadOpentelemetry = true; + finalConfig.preloadOpentelemetry = true; } else { - config.preloadOpentelemetry = defaults.preloadOpentelemetry; + finalConfig.preloadOpentelemetry = defaultConfig.preloadOpentelemetry; } } From d3caf5b3e26807b939f66c3c1bf377e34e39ebf4 Mon Sep 17 00:00:00 2001 From: Arya Date: Wed, 1 Apr 2026 13:13:25 +0530 Subject: [PATCH 3/4] chore: updated --- packages/core/src/config/index.js | 50 +++++++++++++++++-------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/packages/core/src/config/index.js b/packages/core/src/config/index.js index 4cd80baefd..ab5e94d6a0 100644 --- a/packages/core/src/config/index.js +++ b/packages/core/src/config/index.js @@ -156,18 +156,22 @@ module.exports.normalize = (userConfig, defaultsOverride = {}) => { defaults = deepMerge(defaults, defaultsOverride); } + let normalizedUserConfig; + if (userConfig !== null) { + normalizedUserConfig = Object.assign({}, userConfig); + } /** @type InstanaConfig */ const finalConfig = {}; // TODO: remove this and forward the logger via init fn. finalConfig.logger = logger; - normalizeServiceName(userConfig, defaults, finalConfig); - normalizePackageJsonPath(userConfig, defaults, finalConfig); - normalizeMetricsConfig(userConfig, defaults, finalConfig); - normalizeTracingConfig(userConfig, defaults, finalConfig); - normalizeSecrets(userConfig, defaults, finalConfig); - normalizePreloadOpentelemetry(userConfig, defaults, finalConfig); + normalizeServiceName(normalizedUserConfig, defaults, finalConfig); + normalizePackageJsonPath(normalizedUserConfig, defaults, finalConfig); + normalizeMetricsConfig(normalizedUserConfig, defaults, finalConfig); + normalizeTracingConfig(normalizedUserConfig, defaults, finalConfig); + normalizeSecrets(normalizedUserConfig, defaults, finalConfig); + normalizePreloadOpentelemetry(normalizedUserConfig, defaults, finalConfig); return finalConfig; }; @@ -247,6 +251,8 @@ function normalizeMetricsConfig(userConfig, defaultConfig, finalConfig) { function normalizeTracingConfig(userConfig, defaultConfig, finalConfig) { finalConfig.tracing = {}; + userConfig.tracing = userConfig?.tracing || {}; + normalizeTracingEnabled(userConfig, defaultConfig, finalConfig); normalizeUseOpentelemetry(userConfig, defaultConfig, finalConfig); normalizeDisableTracing(userConfig, defaultConfig, finalConfig); @@ -272,7 +278,7 @@ function normalizeTracingConfig(userConfig, defaultConfig, finalConfig) { function normalizeTracingEnabled(userConfig, defaultConfig, finalConfig) { finalConfig.tracing.enabled = util.resolveBooleanConfigWithInvertedEnv({ envVar: 'INSTANA_TRACING_DISABLE', - configValue: userConfig?.tracing?.enabled, + configValue: userConfig.tracing.enabled, defaultValue: defaultConfig.tracing.enabled, configPath: 'config.tracing.enabled' }); @@ -286,7 +292,7 @@ function normalizeTracingEnabled(userConfig, defaultConfig, finalConfig) { function normalizeAllowRootExitSpan(userConfig, defaultConfig, finalConfig) { finalConfig.tracing.allowRootExitSpan = util.resolveBooleanConfig({ envVar: 'INSTANA_ALLOW_ROOT_EXIT_SPAN', - configValue: userConfig?.tracing?.allowRootExitSpan, + configValue: userConfig.tracing.allowRootExitSpan, defaultValue: defaultConfig.tracing.allowRootExitSpan, configPath: 'config.tracing.allowRootExitSpan' }); @@ -300,7 +306,7 @@ function normalizeAllowRootExitSpan(userConfig, defaultConfig, finalConfig) { function normalizeUseOpentelemetry(userConfig, defaultConfig, finalConfig) { finalConfig.tracing.useOpentelemetry = util.resolveBooleanConfigWithInvertedEnv({ envVar: 'INSTANA_DISABLE_USE_OPENTELEMETRY', - configValue: userConfig?.tracing?.useOpentelemetry, + configValue: userConfig.tracing.useOpentelemetry, defaultValue: defaultConfig.tracing.useOpentelemetry, configPath: 'config.tracing.useOpentelemetry' }); @@ -320,7 +326,7 @@ function normalizeAutomaticTracingEnabled(userConfig, defaultConfig, finalConfig finalConfig.tracing.automaticTracingEnabled = util.resolveBooleanConfigWithInvertedEnv({ envVar: 'INSTANA_DISABLE_AUTO_INSTR', - configValue: userConfig?.tracing?.automaticTracingEnabled, + configValue: userConfig.tracing.automaticTracingEnabled, defaultValue: defaultConfig.tracing.automaticTracingEnabled, configPath: 'config.tracing.automaticTracingEnabled' }); @@ -339,7 +345,7 @@ function normalizeActivateImmediately(userConfig, defaultConfig, finalConfig) { finalConfig.tracing.activateImmediately = util.resolveBooleanConfig({ envVar: 'INSTANA_TRACE_IMMEDIATELY', - configValue: userConfig?.tracing?.activateImmediately, + configValue: userConfig.tracing.activateImmediately, defaultValue: defaultConfig.tracing.activateImmediately, configPath: 'config.tracing.activateImmediately' }); @@ -352,25 +358,25 @@ function normalizeActivateImmediately(userConfig, defaultConfig, finalConfig) { */ function normalizeTracingTransmission(userConfig, defaultConfig, finalConfig) { finalConfig.tracing.maxBufferedSpans = - userConfig?.tracing?.maxBufferedSpans || defaultConfig.tracing.maxBufferedSpans; + userConfig.tracing.maxBufferedSpans || defaultConfig.tracing.maxBufferedSpans; finalConfig.tracing.transmissionDelay = util.resolveNumericConfig({ envVar: 'INSTANA_TRACING_TRANSMISSION_DELAY', - configValue: userConfig?.tracing?.transmissionDelay, + configValue: userConfig.tracing.transmissionDelay, defaultValue: defaultConfig.tracing.transmissionDelay, configPath: 'config.tracing.transmissionDelay' }); finalConfig.tracing.forceTransmissionStartingAt = util.resolveNumericConfig({ envVar: 'INSTANA_FORCE_TRANSMISSION_STARTING_AT', - configValue: userConfig?.tracing?.forceTransmissionStartingAt, + configValue: userConfig.tracing.forceTransmissionStartingAt, defaultValue: defaultConfig.tracing.forceTransmissionStartingAt, configPath: 'config.tracing.forceTransmissionStartingAt' }); finalConfig.tracing.initialTransmissionDelay = util.resolveNumericConfig({ envVar: 'INSTANA_TRACING_INITIAL_TRANSMISSION_DELAY', - configValue: userConfig?.tracing?.initialTransmissionDelay, + configValue: userConfig.tracing.initialTransmissionDelay, defaultValue: defaultConfig.tracing.initialTransmissionDelay, configPath: 'config.tracing.initialTransmissionDelay' }); @@ -386,7 +392,7 @@ function normalizeTracingTransmission(userConfig, defaultConfig, finalConfig) { * @param {InstanaConfig} finalConfig */ function normalizeTracingHttp(userConfig, defaultConfig, finalConfig) { - const userHttp = userConfig?.tracing?.http; + const userHttp = userConfig.tracing.http; finalConfig.tracing.http = {}; let fromEnvVar; @@ -563,7 +569,7 @@ function normalizeDisableTracing(userConfig, defaultConfig, finalConfig) { function normalizeSpanBatchingEnabled(userConfig, defaultConfig, finalConfig) { finalConfig.tracing.spanBatchingEnabled = util.resolveBooleanConfig({ envVar: 'INSTANA_SPANBATCHING_ENABLED', - configValue: userConfig?.tracing?.spanBatchingEnabled, + configValue: userConfig.tracing.spanBatchingEnabled, defaultValue: defaultConfig.tracing.spanBatchingEnabled, configPath: 'config.tracing.spanBatchingEnabled' }); @@ -577,7 +583,7 @@ function normalizeSpanBatchingEnabled(userConfig, defaultConfig, finalConfig) { function normalizeDisableW3cTraceCorrelation(userConfig, defaultConfig, finalConfig) { finalConfig.tracing.disableW3cTraceCorrelation = util.resolveBooleanConfigWithTruthyEnv({ envVar: 'INSTANA_DISABLE_W3C_TRACE_CORRELATION', - configValue: userConfig?.tracing?.disableW3cTraceCorrelation, + configValue: userConfig.tracing.disableW3cTraceCorrelation, defaultValue: defaultConfig.tracing.disableW3cTraceCorrelation }); } @@ -588,7 +594,7 @@ function normalizeDisableW3cTraceCorrelation(userConfig, defaultConfig, finalCon * @param {InstanaConfig} finalConfig */ function normalizeTracingKafka(userConfig, defaultConfig, finalConfig) { - const userKafka = userConfig?.tracing?.kafka; + const userKafka = userConfig.tracing.kafka; finalConfig.tracing.kafka = {}; finalConfig.tracing.kafka.traceCorrelation = util.resolveBooleanConfig({ @@ -710,7 +716,7 @@ function parseSecretsEnvVar(envVarValue) { * @param {InstanaConfig} finalConfig */ function normalizeIgnoreEndpoints(userConfig, defaultConfig, finalConfig) { - const userIgnoreEndpoints = userConfig?.tracing?.ignoreEndpoints; + const userIgnoreEndpoints = userConfig.tracing.ignoreEndpoints; if (userIgnoreEndpoints && (typeof userIgnoreEndpoints !== 'object' || Array.isArray(userIgnoreEndpoints))) { logger.warn( @@ -762,7 +768,7 @@ function normalizeIgnoreEndpoints(userConfig, defaultConfig, finalConfig) { function normalizeIgnoreEndpointsDisableSuppression(userConfig, defaultConfig, finalConfig) { finalConfig.tracing.ignoreEndpointsDisableSuppression = util.resolveBooleanConfig({ envVar: 'INSTANA_IGNORE_ENDPOINTS_DISABLE_SUPPRESSION', - configValue: userConfig?.tracing?.ignoreEndpointsDisableSuppression, + configValue: userConfig.tracing.ignoreEndpointsDisableSuppression, defaultValue: defaultConfig.tracing.ignoreEndpointsDisableSuppression, configPath: 'config.tracing.ignoreEndpointsDisableSuppression' }); @@ -776,7 +782,7 @@ function normalizeIgnoreEndpointsDisableSuppression(userConfig, defaultConfig, f function normalizeDisableEOLEvents(userConfig, defaultConfig, finalConfig) { finalConfig.tracing.disableEOLEvents = util.resolveBooleanConfig({ envVar: 'INSTANA_TRACING_DISABLE_EOL_EVENTS', - configValue: userConfig?.tracing?.disableEOLEvents, + configValue: userConfig.tracing.disableEOLEvents, defaultValue: defaultConfig.tracing.disableEOLEvents, configPath: 'config.tracing.disableEOLEvents' }); From 71a1f103823387e9734efc4754238ba88c5883de Mon Sep 17 00:00:00 2001 From: Arya Date: Wed, 1 Apr 2026 18:10:08 +0530 Subject: [PATCH 4/4] chore: refactor --- packages/aws-lambda/src/wrapper.js | 4 +- packages/collector/src/index.js | 7 +- packages/core/src/config/index.js | 25 +- .../core/test/config/normalizeConfig_test.js | 451 +++++++++++------- packages/core/test/tracing/index_test.js | 2 +- 5 files changed, 305 insertions(+), 184 deletions(-) diff --git a/packages/aws-lambda/src/wrapper.js b/packages/aws-lambda/src/wrapper.js index 76a9d1e7b6..b668c1de35 100644 --- a/packages/aws-lambda/src/wrapper.js +++ b/packages/aws-lambda/src/wrapper.js @@ -36,7 +36,7 @@ const latestRuntime = semver.gte(process.version, '24.0.0'); const logger = serverlessLogger.init(); coreConfig.init(logger); -let config = coreConfig.normalize({}, lambdaConfigDefaults); +let config = coreConfig.normalize({ defaultsOverride: lambdaConfigDefaults }); let coldStart = true; // Initialize instrumentations early to allow for require statements after our @@ -286,7 +286,7 @@ function init(event, arnInfo, _config) { // - late env variables (less likely) // - custom logger // - we always renormalize unconditionally to ensure safety. - config = coreConfig.normalize(userConfig, lambdaConfigDefaults); + config = coreConfig.normalize({ userConfig, defaultsOverride: lambdaConfigDefaults }); if (!config.tracing.enabled) { return false; diff --git a/packages/collector/src/index.js b/packages/collector/src/index.js index 05b5e3c475..195859600d 100644 --- a/packages/collector/src/index.js +++ b/packages/collector/src/index.js @@ -158,8 +158,11 @@ function init(userConfig = {}) { log.init(userConfig); } - config = normalizeCollectorConfig(userConfig); - config = instanaNodeJsCore.coreConfig.normalize(config); + const collectorConfig = normalizeCollectorConfig(userConfig); + config = instanaNodeJsCore.coreConfig.normalize({ + userConfig, + extraFinalConfig: collectorConfig + }); agentConnection = require('./agentConnection'); const agentOpts = require('./agent/opts'); diff --git a/packages/core/src/config/index.js b/packages/core/src/config/index.js index ab5e94d6a0..2f8757e1be 100644 --- a/packages/core/src/config/index.js +++ b/packages/core/src/config/index.js @@ -144,24 +144,28 @@ module.exports.init = _logger => { /** * Merges the config that was passed to the init function with environment variables and default values. - */ - -/** - * @param {InstanaConfig} [userConfig] - * @param {InstanaConfig} [defaultsOverride] + * @param {Object} [options] + * @param {InstanaConfig} [options.userConfig] + * @param {Object} [options.extraFinalConfig] + * @param {InstanaConfig} [options.defaultsOverride] * @returns {InstanaConfig} */ -module.exports.normalize = (userConfig, defaultsOverride = {}) => { - if (defaultsOverride && typeof defaultsOverride === 'object') { +module.exports.normalize = ({ userConfig = {}, extraFinalConfig = {}, defaultsOverride = {} } = {}) => { + if (defaultsOverride && typeof defaultsOverride === 'object' && Object.keys(defaultsOverride).length > 0) { defaults = deepMerge(defaults, defaultsOverride); } let normalizedUserConfig; - if (userConfig !== null) { + if (userConfig !== null && userConfig !== undefined) { normalizedUserConfig = Object.assign({}, userConfig); + } else { + normalizedUserConfig = {}; } + + // Preserve extraFinalConfig in the finalConfig to allow additional config values + // that are not part of the core config schema. Eg: collector config needs to be preserved. /** @type InstanaConfig */ - const finalConfig = {}; + const finalConfig = extraFinalConfig ? Object.assign({}, extraFinalConfig) : {}; // TODO: remove this and forward the logger via init fn. finalConfig.logger = logger; @@ -357,8 +361,7 @@ function normalizeActivateImmediately(userConfig, defaultConfig, finalConfig) { * @param {InstanaConfig} finalConfig */ function normalizeTracingTransmission(userConfig, defaultConfig, finalConfig) { - finalConfig.tracing.maxBufferedSpans = - userConfig.tracing.maxBufferedSpans || defaultConfig.tracing.maxBufferedSpans; + finalConfig.tracing.maxBufferedSpans = userConfig.tracing.maxBufferedSpans || defaultConfig.tracing.maxBufferedSpans; finalConfig.tracing.transmissionDelay = util.resolveNumericConfig({ envVar: 'INSTANA_TRACING_TRANSMISSION_DELAY', diff --git a/packages/core/test/config/normalizeConfig_test.js b/packages/core/test/config/normalizeConfig_test.js index 03eed33cdb..1c02e04533 100644 --- a/packages/core/test/config/normalizeConfig_test.js +++ b/packages/core/test/config/normalizeConfig_test.js @@ -50,15 +50,15 @@ describe('config.normalizeConfig', () => { describe('default configuration', () => { it('should apply all defaults', () => { checkDefaults(coreConfig.normalize()); - checkDefaults(coreConfig.normalize({})); - checkDefaults(coreConfig.normalize({ tracing: {}, metrics: {} })); - checkDefaults(coreConfig.normalize({ unknowConfigOption: 13 })); + checkDefaults(coreConfig.normalize({ userConfig: { userConfig: {} } })); + checkDefaults(coreConfig.normalize({ userConfig: { userConfig: { tracing: {}, metrics: {} } } })); + checkDefaults(coreConfig.normalize({ userConfig: { userConfig: { unknowConfigOption: 13 } } })); }); }); describe('service name configuration', () => { it('should accept service name', () => { - const config = coreConfig.normalize({ serviceName: 'custom-service-name' }); + const config = coreConfig.normalize({ userConfig: { serviceName: 'custom-service-name' } }); expect(config.serviceName).to.equal('custom-service-name'); }); @@ -69,18 +69,18 @@ describe('config.normalizeConfig', () => { }); it('should not accept non-string service name', () => { - const config = coreConfig.normalize({ serviceName: 42 }); + const config = coreConfig.normalize({ userConfig: { serviceName: 42 } }); expect(config.serviceName).to.not.exist; }); it.skip('should use config when env not set', () => { - const config = coreConfig.normalize({ serviceName: 'config-service-name' }); + const config = coreConfig.normalize({ userConfig: { serviceName: 'config-service-name' } }); expect(config.serviceName).to.equal('config-service-name'); }); it.skip('should give precedence to INSTANA_SERVICE_NAME env var over config', () => { process.env.INSTANA_SERVICE_NAME = 'env-service'; - const config = coreConfig.normalize({ serviceName: 'config-service' }); + const config = coreConfig.normalize({ userConfig: { serviceName: 'config-service' } }); expect(config.serviceName).to.equal('env-service'); }); }); @@ -88,8 +88,10 @@ describe('config.normalizeConfig', () => { describe('metrics configuration', () => { it('should use custom metrics transmission settings from config', () => { const config = coreConfig.normalize({ - metrics: { - transmissionDelay: 9753 + userConfig: { + metrics: { + transmissionDelay: 9753 + } } }); expect(config.metrics.transmissionDelay).to.equal(9753); @@ -114,26 +116,28 @@ describe('config.normalizeConfig', () => { it.skip('should give precedence to INSTANA_METRICS_TRANSMISSION_DELAY env var over config', () => { process.env.INSTANA_METRICS_TRANSMISSION_DELAY = '3000'; - const config = coreConfig.normalize({ metrics: { transmissionDelay: 5000 } }); + const config = coreConfig.normalize({ userConfig: { metrics: { transmissionDelay: 5000 } } }); expect(config.metrics.transmissionDelay).to.equal(3000); }); it('should fall back to config when env var is invalid', () => { process.env.INSTANA_METRICS_TRANSMISSION_DELAY = 'invalid'; - const config = coreConfig.normalize({ metrics: { transmissionDelay: 5000 } }); + const config = coreConfig.normalize({ userConfig: { metrics: { transmissionDelay: 5000 } } }); expect(config.metrics.transmissionDelay).to.equal(5000); }); it('should fall back to default when both env and config are invalid', () => { process.env.INSTANA_METRICS_TRANSMISSION_DELAY = 'invalid'; - const config = coreConfig.normalize({ metrics: { transmissionDelay: 'also-invalid' } }); + const config = coreConfig.normalize({ userConfig: { metrics: { transmissionDelay: 'also-invalid' } } }); expect(config.metrics.transmissionDelay).to.equal(1000); }); it('should use custom config.metrics.timeBetweenHealthcheckCalls', () => { const config = coreConfig.normalize({ - metrics: { - timeBetweenHealthcheckCalls: 9876 + userConfig: { + metrics: { + timeBetweenHealthcheckCalls: 9876 + } } }); expect(config.metrics.timeBetweenHealthcheckCalls).to.equal(9876); @@ -143,19 +147,19 @@ describe('config.normalizeConfig', () => { describe('tracing configuration', () => { describe('enabling and disabling tracing', () => { it('should disable tracing with enabled: false', () => { - const config = coreConfig.normalize({ tracing: { enabled: false } }); + const config = coreConfig.normalize({ userConfig: { tracing: { enabled: false } } }); expect(config.tracing.enabled).to.be.false; expect(config.tracing.automaticTracingEnabled).to.be.false; }); it('should disable tracing with disable: true', () => { - const config = coreConfig.normalize({ tracing: { enabled: false } }); + const config = coreConfig.normalize({ userConfig: { tracing: { enabled: false } } }); expect(config.tracing.enabled).to.be.false; expect(config.tracing.automaticTracingEnabled).to.be.false; }); it('should disable automatic tracing', () => { - const config = coreConfig.normalize({ tracing: { automaticTracingEnabled: false } }); + const config = coreConfig.normalize({ userConfig: { tracing: { automaticTracingEnabled: false } } }); expect(config.tracing.enabled).to.be.true; expect(config.tracing.automaticTracingEnabled).to.be.false; }); @@ -168,9 +172,11 @@ describe('config.normalizeConfig', () => { }); it('should not enable automatic tracing when tracing is disabled in general', () => { const config = coreConfig.normalize({ - tracing: { - enabled: false, - automaticTracingEnabled: true + userConfig: { + tracing: { + enabled: false, + automaticTracingEnabled: true + } } }); expect(config.tracing.enabled).to.be.false; @@ -184,13 +190,13 @@ describe('config.normalizeConfig', () => { it.skip('should give precedence to INSTANA_TRACING_DISABLE env var set to true over config set to true', () => { process.env.INSTANA_TRACING_DISABLE = 'true'; - const config = coreConfig.normalize({ tracing: { enabled: true } }); + const config = coreConfig.normalize({ userConfig: { tracing: { enabled: true } } }); expect(config.tracing.enabled).to.be.false; }); it.skip('should give precedence to INSTANA_TRACING_DISABLE env var set to false over config set to false', () => { process.env.INSTANA_TRACING_DISABLE = 'false'; - const config = coreConfig.normalize({ tracing: { enabled: false } }); + const config = coreConfig.normalize({ userConfig: { tracing: { enabled: false } } }); expect(config.tracing.enabled).to.be.true; }); @@ -207,13 +213,13 @@ describe('config.normalizeConfig', () => { it.skip('should give precedence to INSTANA_DISABLE_AUTO_INSTR env var set to true over config set to true', () => { process.env.INSTANA_DISABLE_AUTO_INSTR = 'true'; - const config = coreConfig.normalize({ tracing: { automaticTracingEnabled: true } }); + const config = coreConfig.normalize({ userConfig: { tracing: { automaticTracingEnabled: true } } }); expect(config.tracing.automaticTracingEnabled).to.be.false; }); it.skip('should give precedence to INSTANA_DISABLE_AUTO_INSTR env var set to false over config set to false', () => { process.env.INSTANA_DISABLE_AUTO_INSTR = 'false'; - const config = coreConfig.normalize({ tracing: { automaticTracingEnabled: false } }); + const config = coreConfig.normalize({ userConfig: { tracing: { automaticTracingEnabled: false } } }); expect(config.tracing.automaticTracingEnabled).to.be.true; }); @@ -226,7 +232,7 @@ describe('config.normalizeConfig', () => { describe('immediate activation', () => { it('should enable immediate tracing activation', () => { - const config = coreConfig.normalize({ tracing: { activateImmediately: true } }); + const config = coreConfig.normalize({ userConfig: { tracing: { activateImmediately: true } } }); expect(config.tracing.activateImmediately).to.be.true; }); @@ -238,9 +244,11 @@ describe('config.normalizeConfig', () => { it('should not enable immediate tracing activation when tracing is disabled in general', () => { const config = coreConfig.normalize({ - tracing: { - enabled: false, - activateImmediately: true + userConfig: { + tracing: { + enabled: false, + activateImmediately: true + } } }); expect(config.tracing.enabled).to.be.false; @@ -254,13 +262,13 @@ describe('config.normalizeConfig', () => { it.skip('should give precedence to INSTANA_TRACE_IMMEDIATELY env var set to true over config set to false', () => { process.env.INSTANA_TRACE_IMMEDIATELY = 'true'; - const config = coreConfig.normalize({ tracing: { activateImmediately: false } }); + const config = coreConfig.normalize({ userConfig: { tracing: { activateImmediately: false } } }); expect(config.tracing.activateImmediately).to.be.true; }); it.skip('should give precedence to INSTANA_TRACE_IMMEDIATELY env var set to false over config set to true', () => { process.env.INSTANA_TRACE_IMMEDIATELY = 'false'; - const config = coreConfig.normalize({ tracing: { activateImmediately: true } }); + const config = coreConfig.normalize({ userConfig: { tracing: { activateImmediately: true } } }); expect(config.tracing.activateImmediately).to.be.false; }); }); @@ -268,10 +276,12 @@ describe('config.normalizeConfig', () => { describe('transmission settings', () => { it('should use custom tracing transmission settings from config', () => { const config = coreConfig.normalize({ - tracing: { - maxBufferedSpans: 13, - forceTransmissionStartingAt: 2, - transmissionDelay: 9753 + userConfig: { + tracing: { + maxBufferedSpans: 13, + forceTransmissionStartingAt: 2, + transmissionDelay: 9753 + } } }); expect(config.tracing.maxBufferedSpans).to.equal(13); @@ -297,25 +307,25 @@ describe('config.normalizeConfig', () => { it.skip('should give precedence to INSTANA_TRACING_TRANSMISSION_DELAY env var over config', () => { process.env.INSTANA_TRACING_TRANSMISSION_DELAY = '4000'; - const config = coreConfig.normalize({ tracing: { transmissionDelay: 2000 } }); + const config = coreConfig.normalize({ userConfig: { tracing: { transmissionDelay: 2000 } } }); expect(config.tracing.transmissionDelay).to.equal(4000); }); it.skip('should give precedence to INSTANA_FORCE_TRANSMISSION_STARTING_AT env var over config', () => { process.env.INSTANA_FORCE_TRANSMISSION_STARTING_AT = '700'; - const config = coreConfig.normalize({ tracing: { forceTransmissionStartingAt: 300 } }); + const config = coreConfig.normalize({ userConfig: { tracing: { forceTransmissionStartingAt: 300 } } }); expect(config.tracing.forceTransmissionStartingAt).to.equal(700); }); it('should fall back to config when env var is invalid for transmissionDelay', () => { process.env.INSTANA_TRACING_TRANSMISSION_DELAY = 'invalid'; - const config = coreConfig.normalize({ tracing: { transmissionDelay: 5000 } }); + const config = coreConfig.normalize({ userConfig: { tracing: { transmissionDelay: 5000 } } }); expect(config.tracing.transmissionDelay).to.equal(5000); }); it('should fall back to default when both env and config are invalid for transmissionDelay', () => { process.env.INSTANA_TRACING_TRANSMISSION_DELAY = 'invalid'; - const config = coreConfig.normalize({ tracing: { transmissionDelay: 'also-invalid' } }); + const config = coreConfig.normalize({ userConfig: { tracing: { transmissionDelay: 'also-invalid' } } }); expect(config.tracing.transmissionDelay).to.equal(1000); }); }); @@ -323,9 +333,11 @@ describe('config.normalizeConfig', () => { describe('HTTP headers configuration', () => { it('should use extra http headers (and normalize to lower case)', () => { const config = coreConfig.normalize({ - tracing: { - http: { - extraHttpHeadersToCapture: ['yo', 'LO'] + userConfig: { + tracing: { + http: { + extraHttpHeadersToCapture: ['yo', 'LO'] + } } } }); @@ -334,9 +346,11 @@ describe('config.normalizeConfig', () => { it('should reject non-array extra http headers configuration value', () => { const config = coreConfig.normalize({ - tracing: { - http: { - extraHttpHeadersToCapture: 'yolo' + userConfig: { + tracing: { + http: { + extraHttpHeadersToCapture: 'yolo' + } } } }); @@ -359,36 +373,36 @@ describe('config.normalizeConfig', () => { describe('stack trace configuration', () => { it('should accept numerical custom stack trace length', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: 666 } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: 666 } } }); expect(config.tracing.stackTraceLength).to.equal(500); }); it('should normalize numbers for custom stack trace length', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: -28.08 } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: -28.08 } } }); expect(config.tracing.stackTraceLength).to.be.a('number'); expect(config.tracing.stackTraceLength).to.equal(28); }); it('should accept number-like strings for custom stack trace length', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: '1302' } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: '1302' } } }); expect(config.tracing.stackTraceLength).to.be.a('number'); expect(config.tracing.stackTraceLength).to.equal(500); }); it('should normalize number-like strings for custom stack trace length', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: '-16.04' } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: '-16.04' } } }); expect(config.tracing.stackTraceLength).to.be.a('number'); expect(config.tracing.stackTraceLength).to.equal(16); }); it('should reject non-numerical strings for custom stack trace length', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: 'three' } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: 'three' } } }); expect(config.tracing.stackTraceLength).to.be.a('number'); expect(config.tracing.stackTraceLength).to.equal(10); }); it('should reject custom stack trace length which is neither a number nor a string', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: false } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: false } } }); expect(config.tracing.stackTraceLength).to.be.a('number'); expect(config.tracing.stackTraceLength).to.equal(10); }); @@ -401,7 +415,7 @@ describe('config.normalizeConfig', () => { it.skip('should give precedence to INSTANA_STACK_TRACE_LENGTH over config', () => { process.env.INSTANA_STACK_TRACE_LENGTH = '5'; - const normalizedConfig = coreConfig.normalize({ tracing: { stackTraceLength: 20 } }); + const normalizedConfig = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: 20 } } }); expect(normalizedConfig.tracing.stackTraceLength).to.equal(5); delete process.env.INSTANA_STACK_TRACE_LENGTH; }); @@ -412,17 +426,17 @@ describe('config.normalizeConfig', () => { }); it('should accept valid stack trace mode from config', () => { - const config = coreConfig.normalize({ tracing: { global: { stackTrace: 'error' } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { global: { stackTrace: 'error' } } } }); expect(config.tracing.stackTrace).to.equal('error'); }); it('should accept "none" stack trace mode from config', () => { - const config = coreConfig.normalize({ tracing: { global: { stackTrace: 'none' } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { global: { stackTrace: 'none' } } } }); expect(config.tracing.stackTrace).to.equal('none'); }); it('should normalize stack trace mode to lowercase from config', () => { - const config = coreConfig.normalize({ tracing: { global: { stackTrace: 'ERROR' } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { global: { stackTrace: 'ERROR' } } } }); expect(config.tracing.stackTrace).to.equal('error'); }); @@ -440,12 +454,12 @@ describe('config.normalizeConfig', () => { it.skip('should give precedence to env INSTANA_STACK_TRACE over config', () => { process.env.INSTANA_STACK_TRACE = 'none'; - const config = coreConfig.normalize({ tracing: { global: { stackTrace: 'all' } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { global: { stackTrace: 'all' } } } }); expect(config.tracing.stackTrace).to.equal('none'); }); it('should reject invalid stack trace mode from config and fallback to default', () => { - const config = coreConfig.normalize({ tracing: { global: { stackTrace: 'invalid' } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { global: { stackTrace: 'invalid' } } } }); expect(config.tracing.stackTrace).to.equal('all'); }); @@ -456,102 +470,102 @@ describe('config.normalizeConfig', () => { }); it('should reject non-string stack trace mode from config', () => { - const config = coreConfig.normalize({ tracing: { global: { stackTrace: 123 } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { global: { stackTrace: 123 } } } }); expect(config.tracing.stackTrace).to.equal('all'); }); it('should handle null stack trace mode from config', () => { - const config = coreConfig.normalize({ tracing: { global: { stackTrace: null } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { global: { stackTrace: null } } } }); expect(config.tracing.stackTrace).to.equal('all'); }); it('should handle undefined stack trace mode from config', () => { - const config = coreConfig.normalize({ tracing: { global: { stackTrace: undefined } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { global: { stackTrace: undefined } } } }); expect(config.tracing.stackTrace).to.equal('all'); }); it('should handle empty string stack trace mode from config', () => { - const config = coreConfig.normalize({ tracing: { global: { stackTrace: '' } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { global: { stackTrace: '' } } } }); expect(config.tracing.stackTrace).to.equal('all'); }); it('should handle boolean stack trace mode from config', () => { - const config = coreConfig.normalize({ tracing: { global: { stackTrace: true } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { global: { stackTrace: true } } } }); expect(config.tracing.stackTrace).to.equal('all'); }); it('should handle object stack trace mode from config', () => { - const config = coreConfig.normalize({ tracing: { global: { stackTrace: {} } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { global: { stackTrace: {} } } } }); expect(config.tracing.stackTrace).to.equal('all'); }); it('should handle array stack trace mode from config', () => { - const config = coreConfig.normalize({ tracing: { global: { stackTrace: ['error'] } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { global: { stackTrace: ['error'] } } } }); expect(config.tracing.stackTrace).to.equal('all'); }); it('should accept zero as valid stack trace length', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: 0 } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: 0 } } }); expect(config.tracing.stackTraceLength).to.equal(0); }); it('should handle negative stack trace length', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: -10 } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: -10 } } }); expect(config.tracing.stackTraceLength).to.equal(10); }); it('should handle very large negative stack trace length', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: -100 } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: -100 } } }); expect(config.tracing.stackTraceLength).to.equal(100); }); it('should handle stack trace length as positive float', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: 15.9 } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: 15.9 } } }); expect(config.tracing.stackTraceLength).to.equal(16); }); it('should handle stack trace length as negative float', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: -15.9 } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: -15.9 } } }); expect(config.tracing.stackTraceLength).to.equal(16); }); it('should handle stack trace length as string with leading zeros', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: '007' } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: '007' } } }); expect(config.tracing.stackTraceLength).to.equal(7); }); it('should handle stack trace length as string with whitespace', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: ' 25 ' } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: ' 25 ' } } }); expect(config.tracing.stackTraceLength).to.equal(25); }); it('should handle stack trace length as string with plus sign', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: '+30' } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: '+30' } } }); expect(config.tracing.stackTraceLength).to.equal(30); }); it('should reject stack trace length as null', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: null } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: null } } }); expect(config.tracing.stackTraceLength).to.equal(10); }); it('should reject stack trace length as undefined', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: undefined } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: undefined } } }); expect(config.tracing.stackTraceLength).to.equal(10); }); it('should reject stack trace length as empty string', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: '' } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: '' } } }); expect(config.tracing.stackTraceLength).to.equal(10); }); it('should reject stack trace length as object', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: {} } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: {} } } }); expect(config.tracing.stackTraceLength).to.equal(10); }); it('should reject stack trace length as array', () => { - const config = coreConfig.normalize({ tracing: { stackTraceLength: [10] } }); + const config = coreConfig.normalize({ userConfig: { tracing: { stackTraceLength: [10] } } }); expect(config.tracing.stackTraceLength).to.equal(10); }); @@ -608,7 +622,7 @@ describe('config.normalizeConfig', () => { const original = stackTraceNormalizers.normalizeStackTraceMode; stackTraceNormalizers.normalizeStackTraceMode = () => null; - const config = coreConfig.normalize({ tracing: { global: { stackTrace: 'all' } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { global: { stackTrace: 'all' } } } }); expect(config.tracing.stackTrace).to.equal('all'); stackTraceNormalizers.normalizeStackTraceMode = original; @@ -631,7 +645,7 @@ describe('config.normalizeConfig', () => { const original = stackTraceNormalizers.normalizeStackTraceLength; stackTraceNormalizers.normalizeStackTraceLength = () => null; - const config = coreConfig.normalize({ tracing: { global: { stackTraceLength: 20 } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { global: { stackTraceLength: 20 } } } }); expect(config.tracing.stackTraceLength).to.equal(10); stackTraceNormalizers.normalizeStackTraceLength = original; @@ -651,9 +665,11 @@ describe('config.normalizeConfig', () => { it('should return null from normalizeStackTraceLength when value is valid but normalized is null', () => { const config = coreConfig.normalize({ - tracing: { - global: { - stackTraceLength: Infinity + userConfig: { + tracing: { + global: { + stackTraceLength: Infinity + } } } }); @@ -670,10 +686,12 @@ describe('config.normalizeConfig', () => { it('should handle config with both stackTrace and stackTraceLength', () => { const config = coreConfig.normalize({ - tracing: { - global: { - stackTrace: 'none', - stackTraceLength: 30 + userConfig: { + tracing: { + global: { + stackTrace: 'none', + stackTraceLength: 30 + } } } }); @@ -685,10 +703,12 @@ describe('config.normalizeConfig', () => { process.env.INSTANA_STACK_TRACE = 'error'; process.env.INSTANA_STACK_TRACE_LENGTH = '15'; const config = coreConfig.normalize({ - tracing: { - global: { - stackTrace: 'all', - stackTraceLength: 40 + userConfig: { + tracing: { + global: { + stackTrace: 'all', + stackTraceLength: 40 + } } } }); @@ -711,8 +731,10 @@ describe('config.normalizeConfig', () => { }); it('should disable individual instrumentations via disable config', () => { const config = coreConfig.normalize({ - tracing: { - disable: ['graphQL', 'GRPC'] + userConfig: { + tracing: { + disable: ['graphQL', 'GRPC'] + } } }); expect(config.tracing.disable.instrumentations).to.deep.equal(['graphql', 'grpc']); @@ -720,8 +742,10 @@ describe('config.normalizeConfig', () => { it('should disable individual instrumentations via disable.instrumentations config', () => { const config = coreConfig.normalize({ - tracing: { - disable: { instrumentations: ['graphQL', 'GRPC'] } + userConfig: { + tracing: { + disable: { instrumentations: ['graphQL', 'GRPC'] } + } } }); expect(config.tracing.disable.instrumentations).to.deep.equal(['graphql', 'grpc']); @@ -730,8 +754,10 @@ describe('config.normalizeConfig', () => { it('config should take precedence over INSTANA_TRACING_DISABLE_INSTRUMENTATIONS for config', () => { process.env.INSTANA_TRACING_DISABLE_INSTRUMENTATIONS = 'foo, bar'; const config = coreConfig.normalize({ - tracing: { - disable: { instrumentations: ['baz', 'fizz'] } + userConfig: { + tracing: { + disable: { instrumentations: ['baz', 'fizz'] } + } } }); expect(config.tracing.disable.instrumentations).to.deep.equal(['baz', 'fizz']); @@ -757,8 +783,10 @@ describe('config.normalizeConfig', () => { it('should disable individual groups via disable config', () => { const config = coreConfig.normalize({ - tracing: { - disable: { groups: ['logging'] } + userConfig: { + tracing: { + disable: { groups: ['logging'] } + } } }); expect(config.tracing.disable.groups).to.deep.equal(['logging']); @@ -773,8 +801,10 @@ describe('config.normalizeConfig', () => { it('config should take precedence over INSTANA_TRACING_DISABLE_GROUPS when disabling groups', () => { process.env.INSTANA_TRACING_DISABLE_GROUPS = 'frameworks, databases'; const config = coreConfig.normalize({ - tracing: { - disable: { groups: ['LOGGING'] } + userConfig: { + tracing: { + disable: { groups: ['LOGGING'] } + } } }); expect(config.tracing.disable.groups).to.deep.equal(['logging']); @@ -782,8 +812,10 @@ describe('config.normalizeConfig', () => { it('should disable instrumentations and groups when both configured', () => { const config = coreConfig.normalize({ - tracing: { - disable: { groups: ['LOGGING'], instrumentations: ['redis', 'kafka'] } + userConfig: { + tracing: { + disable: { groups: ['LOGGING'], instrumentations: ['redis', 'kafka'] } + } } }); expect(config.tracing.disable.groups).to.deep.equal(['logging']); @@ -808,8 +840,10 @@ describe('config.normalizeConfig', () => { it('should disable all tracing via config tracing.disable', () => { const config = coreConfig.normalize({ - tracing: { - disable: true + userConfig: { + tracing: { + disable: true + } } }); expect(config.tracing.enabled).to.be.false; @@ -821,7 +855,7 @@ describe('config.normalizeConfig', () => { describe('span batching', () => { // delete this test when we switch to opt-out it('should enable span batching via config in transition phase', () => { - const config = coreConfig.normalize({ tracing: { spanBatchingEnabled: true } }); + const config = coreConfig.normalize({ userConfig: { tracing: { spanBatchingEnabled: true } } }); expect(config.tracing.spanBatchingEnabled).to.be.true; }); @@ -833,14 +867,14 @@ describe('config.normalizeConfig', () => { }); it('should ignore non-boolean span batching config value', () => { - const config = coreConfig.normalize({ tracing: { spanBatchingEnabled: 73 } }); + const config = coreConfig.normalize({ userConfig: { tracing: { spanBatchingEnabled: 73 } } }); // test needs to be updated once we switch to opt-out expect(config.tracing.spanBatchingEnabled).to.be.false; }); it('should disable span batching', () => { // test only becomes relevant once we switch to opt-out - const config = coreConfig.normalize({ tracing: { spanBatchingEnabled: false } }); + const config = coreConfig.normalize({ userConfig: { tracing: { spanBatchingEnabled: false } } }); expect(config.tracing.spanBatchingEnabled).to.be.false; }); @@ -858,20 +892,20 @@ describe('config.normalizeConfig', () => { it.skip('should give precedence to INSTANA_SPANBATCHING_ENABLED env var set to true over config set to false', () => { process.env.INSTANA_SPANBATCHING_ENABLED = 'true'; - const config = coreConfig.normalize({ tracing: { spanBatchingEnabled: false } }); + const config = coreConfig.normalize({ userConfig: { tracing: { spanBatchingEnabled: false } } }); expect(config.tracing.spanBatchingEnabled).to.be.true; }); it.skip('should give precedence to INSTANA_SPANBATCHING_ENABLED env var set to false over config set to true', () => { process.env.INSTANA_SPANBATCHING_ENABLED = 'false'; - const config = coreConfig.normalize({ tracing: { spanBatchingEnabled: true } }); + const config = coreConfig.normalize({ userConfig: { tracing: { spanBatchingEnabled: true } } }); expect(config.tracing.spanBatchingEnabled).to.be.false; }); }); describe('W3C trace correlation', () => { it('should disable W3C trace correlation', () => { - const config = coreConfig.normalize({ tracing: { disableW3cTraceCorrelation: true } }); + const config = coreConfig.normalize({ userConfig: { tracing: { disableW3cTraceCorrelation: true } } }); expect(config.tracing.disableW3cTraceCorrelation).to.be.true; }); @@ -888,14 +922,14 @@ describe('config.normalizeConfig', () => { it.skip('should give precedence to INSTANA_DISABLE_W3C_TRACE_CORRELATION env var over config (truthy env)', () => { process.env.INSTANA_DISABLE_W3C_TRACE_CORRELATION = 'any-value'; - const config = coreConfig.normalize({ tracing: { disableW3cTraceCorrelation: false } }); + const config = coreConfig.normalize({ userConfig: { tracing: { disableW3cTraceCorrelation: false } } }); expect(config.tracing.disableW3cTraceCorrelation).to.be.true; }); }); describe('Kafka trace correlation', () => { it('should disable Kafka trace correlation', () => { - const config = coreConfig.normalize({ tracing: { kafka: { traceCorrelation: false } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { kafka: { traceCorrelation: false } } } }); expect(config.tracing.kafka.traceCorrelation).to.be.false; }); @@ -912,13 +946,13 @@ describe('config.normalizeConfig', () => { it.skip('should give precedence to INSTANA_KAFKA_TRACE_CORRELATION env var set to false over config set to true', () => { process.env.INSTANA_KAFKA_TRACE_CORRELATION = 'false'; - const config = coreConfig.normalize({ tracing: { kafka: { traceCorrelation: true } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { kafka: { traceCorrelation: true } } } }); expect(config.tracing.kafka.traceCorrelation).to.be.false; }); it.skip('should give precedence to INSTANA_KAFKA_TRACE_CORRELATION env var set to true over config set to false', () => { process.env.INSTANA_KAFKA_TRACE_CORRELATION = 'true'; - const config = coreConfig.normalize({ tracing: { kafka: { traceCorrelation: false } } }); + const config = coreConfig.normalize({ userConfig: { tracing: { kafka: { traceCorrelation: false } } } }); expect(config.tracing.kafka.traceCorrelation).to.be.true; }); }); @@ -926,14 +960,18 @@ describe('config.normalizeConfig', () => { describe('OpenTelemetry configuration', () => { it('should disable opentelemetry if config is set', () => { const config = coreConfig.normalize({ - tracing: { useOpentelemetry: false } + userConfig: { + tracing: { useOpentelemetry: false } + } }); expect(config.tracing.useOpentelemetry).to.equal(false); }); it('should enable opentelemetry if config is set', () => { const config = coreConfig.normalize({ - tracing: { useOpentelemetry: true } + userConfig: { + tracing: { useOpentelemetry: true } + } }); expect(config.tracing.useOpentelemetry).to.equal(true); }); @@ -957,13 +995,13 @@ describe('config.normalizeConfig', () => { it.skip('should give precedence to INSTANA_DISABLE_USE_OPENTELEMETRY env var set to true over config set to true', () => { process.env.INSTANA_DISABLE_USE_OPENTELEMETRY = 'true'; - const config = coreConfig.normalize({ tracing: { useOpentelemetry: true } }); + const config = coreConfig.normalize({ userConfig: { tracing: { useOpentelemetry: true } } }); expect(config.tracing.useOpentelemetry).to.be.false; }); it.skip('should give precedence to INSTANA_DISABLE_USE_OPENTELEMETRY env var set to false over config set to false', () => { process.env.INSTANA_DISABLE_USE_OPENTELEMETRY = 'false'; - const config = coreConfig.normalize({ tracing: { useOpentelemetry: false } }); + const config = coreConfig.normalize({ userConfig: { tracing: { useOpentelemetry: false } } }); expect(config.tracing.useOpentelemetry).to.be.true; }); }); @@ -971,9 +1009,11 @@ describe('config.normalizeConfig', () => { describe('secrets configuration', () => { it('should accept custom secrets config', () => { const config = coreConfig.normalize({ - secrets: { - matcherMode: 'equals', - keywords: ['custom-secret', 'sheesh'] + userConfig: { + secrets: { + matcherMode: 'equals', + keywords: ['custom-secret', 'sheesh'] + } } }); expect(config.secrets.matcherMode).to.equal('equals'); @@ -982,8 +1022,10 @@ describe('config.normalizeConfig', () => { it("should set keywords to empty array for matcher mode 'none'", () => { const config = coreConfig.normalize({ - secrets: { - matcherMode: 'none' + userConfig: { + secrets: { + matcherMode: 'none' + } } }); expect(config.secrets.matcherMode).to.equal('none'); @@ -991,19 +1033,19 @@ describe('config.normalizeConfig', () => { }); it('should reject non-string matcher mode', () => { - const config = coreConfig.normalize({ secrets: { matcherMode: 43 } }); + const config = coreConfig.normalize({ userConfig: { secrets: { matcherMode: 43 } } }); expect(config.secrets.matcherMode).to.equal('contains-ignore-case'); expect(config.secrets.keywords).to.deep.equal(['key', 'pass', 'secret']); }); it('should reject unknown matcher mode from config', () => { - const config = coreConfig.normalize({ secrets: { matcherMode: 'whatever' } }); + const config = coreConfig.normalize({ userConfig: { secrets: { matcherMode: 'whatever' } } }); expect(config.secrets.matcherMode).to.equal('contains-ignore-case'); expect(config.secrets.keywords).to.deep.equal(['key', 'pass', 'secret']); }); it('should reject non-array keywords', () => { - const config = coreConfig.normalize({ secrets: { keywords: 'yes' } }); + const config = coreConfig.normalize({ userConfig: { secrets: { keywords: 'yes' } } }); expect(config.secrets.matcherMode).to.equal('contains-ignore-case'); expect(config.secrets.keywords).to.deep.equal(['key', 'pass', 'secret']); }); @@ -1039,12 +1081,12 @@ describe('config.normalizeConfig', () => { describe('package.json path configuration', () => { it('should accept packageJsonPath', () => { - const config = coreConfig.normalize({ packageJsonPath: './something' }); + const config = coreConfig.normalize({ userConfig: { packageJsonPath: './something' } }); expect(config.packageJsonPath).to.equal('./something'); }); it('should not accept packageJsonPath', () => { - const config = coreConfig.normalize({ packageJsonPath: 1234 }); + const config = coreConfig.normalize({ userConfig: { packageJsonPath: 1234 } }); expect(config.packageJsonPath).to.not.exist; }); @@ -1061,7 +1103,7 @@ describe('config.normalizeConfig', () => { it.skip('should give precedence to INSTANA_PACKAGE_JSON_PATH env var over config', () => { process.env.INSTANA_PACKAGE_JSON_PATH = '/env/path/package.json'; - const config = coreConfig.normalize({ packageJsonPath: '/config/path/package.json' }); + const config = coreConfig.normalize({ userConfig: { packageJsonPath: '/config/path/package.json' } }); expect(config.packageJsonPath).to.equal('/env/path/package.json'); }); }); @@ -1069,14 +1111,18 @@ describe('config.normalizeConfig', () => { describe('allow root exit span', () => { it('should disable allow root exit span if config is set to false', () => { const config = coreConfig.normalize({ - tracing: { allowRootExitSpan: false } + userConfig: { + tracing: { allowRootExitSpan: false } + } }); expect(config.tracing.allowRootExitSpan).to.equal(false); }); it('should enable allow root exit span if config is set to true', () => { const config = coreConfig.normalize({ - tracing: { allowRootExitSpan: true } + userConfig: { + tracing: { allowRootExitSpan: true } + } }); expect(config.tracing.allowRootExitSpan).to.equal(true); }); @@ -1099,13 +1145,13 @@ describe('config.normalizeConfig', () => { it.skip('should give precedence to INSTANA_ALLOW_ROOT_EXIT_SPAN env var set to true over config set to false', () => { process.env.INSTANA_ALLOW_ROOT_EXIT_SPAN = 'true'; - const config = coreConfig.normalize({ tracing: { allowRootExitSpan: false } }); + const config = coreConfig.normalize({ userConfig: { tracing: { allowRootExitSpan: false } } }); expect(config.tracing.allowRootExitSpan).to.be.true; }); it.skip('should give precedence to INSTANA_ALLOW_ROOT_EXIT_SPAN env var set to false over config set to true', () => { process.env.INSTANA_ALLOW_ROOT_EXIT_SPAN = 'false'; - const config = coreConfig.normalize({ tracing: { allowRootExitSpan: true } }); + const config = coreConfig.normalize({ userConfig: { tracing: { allowRootExitSpan: true } } }); expect(config.tracing.allowRootExitSpan).to.be.false; }); }); @@ -1140,24 +1186,30 @@ describe('config.normalizeConfig', () => { it('should apply ignore endpoints via config', () => { const config = coreConfig.normalize({ - tracing: { - ignoreEndpoints: { redis: ['get'] } + userConfig: { + tracing: { + ignoreEndpoints: { redis: ['get'] } + } } }); expect(config.tracing.ignoreEndpoints).to.deep.equal({ redis: [{ methods: ['get'] }] }); }); it('should apply multiple ignore endpoints via config', () => { const config = coreConfig.normalize({ - tracing: { - ignoreEndpoints: { redis: ['GET', 'TYPE'] } + userConfig: { + tracing: { + ignoreEndpoints: { redis: ['GET', 'TYPE'] } + } } }); expect(config.tracing.ignoreEndpoints).to.deep.equal({ redis: [{ methods: ['get', 'type'] }] }); }); it('should apply ignore endpoints via config for multiple packages', () => { const config = coreConfig.normalize({ - tracing: { - ignoreEndpoints: { redis: ['get'], dynamodb: ['querey'] } + userConfig: { + tracing: { + ignoreEndpoints: { redis: ['get'], dynamodb: ['querey'] } + } } }); expect(config.tracing.ignoreEndpoints).to.deep.equal({ @@ -1168,10 +1220,12 @@ describe('config.normalizeConfig', () => { it('should normalize case and trim spaces in method names and endpoint paths', () => { const config = coreConfig.normalize({ - tracing: { - ignoreEndpoints: { - redis: [' GET ', 'TyPe'], - kafka: [{ methods: [' PUBLISH '], endpoints: [' Topic1 ', 'TOPIC2 '] }] + userConfig: { + tracing: { + ignoreEndpoints: { + redis: [' GET ', 'TyPe'], + kafka: [{ methods: [' PUBLISH '], endpoints: [' Topic1 ', 'TOPIC2 '] }] + } } } }); @@ -1183,8 +1237,10 @@ describe('config.normalizeConfig', () => { it('should return an empty list if all configurations are invalid', () => { const config = coreConfig.normalize({ - tracing: { - ignoreEndpoints: { redis: {}, kafka: true, mysql: null } + userConfig: { + tracing: { + ignoreEndpoints: { redis: {}, kafka: true, mysql: null } + } } }); expect(config.tracing.ignoreEndpoints).to.deep.equal({ @@ -1196,10 +1252,12 @@ describe('config.normalizeConfig', () => { it('should normalize objects when unsupported additional fields applied', () => { const config = coreConfig.normalize({ - tracing: { - ignoreEndpoints: { - redis: [{ extra: 'data' }], - kafka: [{ methods: ['publish'], extra: 'info' }] + userConfig: { + tracing: { + ignoreEndpoints: { + redis: [{ extra: 'data' }], + kafka: [{ methods: ['publish'], extra: 'info' }] + } } } }); @@ -1211,9 +1269,11 @@ describe('config.normalizeConfig', () => { it('should normalize objects with only methods and no endpoints', () => { const config = coreConfig.normalize({ - tracing: { - ignoreEndpoints: { - kafka: [{ methods: ['PUBLISH'] }] + userConfig: { + tracing: { + ignoreEndpoints: { + kafka: [{ methods: ['PUBLISH'] }] + } } } }); @@ -1224,9 +1284,11 @@ describe('config.normalizeConfig', () => { it('should normalize objects with only endpoints and no methods', () => { const config = coreConfig.normalize({ - tracing: { - ignoreEndpoints: { - kafka: [{ endpoints: ['Topic1'] }] + userConfig: { + tracing: { + ignoreEndpoints: { + kafka: [{ endpoints: ['Topic1'] }] + } } } }); @@ -1237,9 +1299,11 @@ describe('config.normalizeConfig', () => { it('should normalize objects where methods or endpoints are invalid types', () => { const config = coreConfig.normalize({ - tracing: { - ignoreEndpoints: { - kafka: [{ methods: 123, endpoints: 'invalid' }] + userConfig: { + tracing: { + ignoreEndpoints: { + kafka: [{ methods: 123, endpoints: 'invalid' }] + } } } }); @@ -1248,8 +1312,10 @@ describe('config.normalizeConfig', () => { it('should handle ignoreEndpoints when config is an array instead of object', () => { const config = coreConfig.normalize({ - tracing: { - ignoreEndpoints: ['redis', 'kafka'] + userConfig: { + tracing: { + ignoreEndpoints: ['redis', 'kafka'] + } } }); expect(config.tracing.ignoreEndpoints).to.deep.equal({}); @@ -1257,8 +1323,10 @@ describe('config.normalizeConfig', () => { it('should handle ignoreEndpoints when config is a non-object type', () => { const config = coreConfig.normalize({ - tracing: { - ignoreEndpoints: 'invalid-string' + userConfig: { + tracing: { + ignoreEndpoints: 'invalid-string' + } } }); expect(config.tracing.ignoreEndpoints).to.deep.equal({}); @@ -1282,13 +1350,13 @@ describe('config.normalizeConfig', () => { it.skip('should give precedence to INSTANA_IGNORE_ENDPOINTS_DISABLE_SUPPRESSION env var set to true over config set to false', () => { process.env.INSTANA_IGNORE_ENDPOINTS_DISABLE_SUPPRESSION = 'true'; - const config = coreConfig.normalize({ tracing: { ignoreEndpointsDisableSuppression: false } }); + const config = coreConfig.normalize({ userConfig: { tracing: { ignoreEndpointsDisableSuppression: false } } }); expect(config.tracing.ignoreEndpointsDisableSuppression).to.be.true; }); it.skip('should give precedence to INSTANA_IGNORE_ENDPOINTS_DISABLE_SUPPRESSION env var set to false over config set to true', () => { process.env.INSTANA_IGNORE_ENDPOINTS_DISABLE_SUPPRESSION = 'false'; - const config = coreConfig.normalize({ tracing: { ignoreEndpointsDisableSuppression: true } }); + const config = coreConfig.normalize({ userConfig: { tracing: { ignoreEndpointsDisableSuppression: true } } }); expect(config.tracing.ignoreEndpointsDisableSuppression).to.be.false; }); @@ -1341,7 +1409,9 @@ describe('config.normalizeConfig', () => { it('preloadOpentelemetry should accept true value', () => { const config = coreConfig.normalize({ - preloadOpentelemetry: true + userConfig: { + preloadOpentelemetry: true + } }); expect(config.preloadOpentelemetry).to.be.true; }); @@ -1353,7 +1423,7 @@ describe('config.normalizeConfig', () => { forceTransmissionStartingAt: 25 } }; - const config = coreConfig.normalize({}, customDefaults); + const config = coreConfig.normalize({ defaultsOverride: customDefaults }); expect(config.preloadOpentelemetry).to.be.true; expect(config.tracing.forceTransmissionStartingAt).to.equal(25); }); @@ -1388,24 +1458,69 @@ describe('config.normalizeConfig', () => { }); it('should use config value when env is not set', () => { - const config = coreConfig.normalize({ tracing: { disableEOLEvents: true } }); + const config = coreConfig.normalize({ userConfig: { tracing: { disableEOLEvents: true } } }); expect(config.tracing.disableEOLEvents).to.be.true; }); it.skip('should give precedence to INSTANA_TRACING_DISABLE_EOL_EVENTS env var set to true over config set to false', () => { process.env.INSTANA_TRACING_DISABLE_EOL_EVENTS = 'true'; - const config = coreConfig.normalize({ tracing: { disableEOLEvents: false } }); + const config = coreConfig.normalize({ userConfig: { tracing: { disableEOLEvents: false } } }); expect(config.tracing.disableEOLEvents).to.be.true; }); it.skip('should give precedence to INSTANA_TRACING_DISABLE_EOL_EVENTS env var set to false over config set to true', () => { process.env.INSTANA_TRACING_DISABLE_EOL_EVENTS = 'false'; - const config = coreConfig.normalize({ tracing: { disableEOLEvents: true } }); + const config = coreConfig.normalize({ userConfig: { tracing: { disableEOLEvents: true } } }); expect(config.tracing.disableEOLEvents).to.be.false; }); }); }); + describe('extraFinalConfig parameter', () => { + it('should always preserve extraFinalConfig', () => { + const extraFinalConfig = { + agentHost: '192.168.1.100', + agentPort: 3000, + agentRequestTimeout: 10000 + }; + const config = coreConfig.normalize({ extraFinalConfig }); + expect(config.agentHost).to.equal('192.168.1.100'); + expect(config.agentPort).to.equal(3000); + expect(config.agentRequestTimeout).to.equal(10000); + }); + + it('should merge extraFinalConfig with userConfig', () => { + const extraFinalConfig = { + agentHost: '192.168.1.100', + agentPort: 3000, + agentRequestTimeout: 5000 + }; + const userConfig = { + serviceName: 'my-app', + tracing: { + enabled: true + } + }; + const config = coreConfig.normalize({ userConfig, extraFinalConfig }); + expect(config.agentHost).to.equal('192.168.1.100'); + expect(config.agentPort).to.equal(3000); + expect(config.agentRequestTimeout).to.equal(5000); + expect(config.serviceName).to.equal('my-app'); + expect(config.tracing.enabled).to.be.true; + }); + + it('should work with empty extraFinalConfig', () => { + const config = coreConfig.normalize({ extraFinalConfig: {} }); + expect(config.serviceName).to.be.null; + expect(config.tracing.enabled).to.be.true; + }); + + it('should work without extraFinalConfig parameter', () => { + const config = coreConfig.normalize({ userConfig: { serviceName: 'test' } }); + expect(config.serviceName).to.equal('test'); + }); + }); + function checkDefaults(config) { expect(config).to.be.an('object'); diff --git a/packages/core/test/tracing/index_test.js b/packages/core/test/tracing/index_test.js index c31325e113..a89e45b816 100644 --- a/packages/core/test/tracing/index_test.js +++ b/packages/core/test/tracing/index_test.js @@ -273,7 +273,7 @@ mochaSuiteFn('[UNIT] tracing/index', function () { function initAndActivate(initConfig, extraConfigForActivate) { const logger = testUtils.createFakeLogger(); coreConfig.init(logger); - const config = coreConfig.normalize(initConfig); + const config = coreConfig.normalize({ userConfig: initConfig }); util.init(config); tracing.init(config); tracing.activate(extraConfigForActivate);