Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 38 additions & 10 deletions packages/core/src/config/configNormalizers/disable.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,56 @@ exports.init = function init(_config) {
* Handles environment variables, and array inputs.
*
* Precedence order (highest to lowest):
* 1. `tracing.disable`
* 2. Environment variables (`INSTANA_TRACING_DISABLE*`)
* 1. Environment variables (`INSTANA_TRACING_DISABLE*`)
* 2. In-code tracing.disable
*
* @param {import('../../config').InstanaConfig} config
*/
exports.normalize = function normalize(config) {
if (!config?.tracing) config.tracing = {};
try {
// Disable all tracing if explicitly set 'disable' to true
const envDisableConfig = getDisableFromEnv();

if (envDisableConfig !== null) {
if (envDisableConfig === true) {
logger?.debug('[config] env:INSTANA_TRACING_DISABLE = true');
return true;
}

if (envDisableConfig === false) {
logger?.debug('[config] env:INSTANA_TRACING_DISABLE = false (overrides in-code config)');
return {};
}

if (envDisableConfig.instrumentations?.length || envDisableConfig.groups?.length) {
logger?.debug(`[config] env:INSTANA_TRACING_DISABLE* = ${JSON.stringify(envDisableConfig)}`);

if (envDisableConfig.instrumentations) {
envDisableConfig.instrumentations = normalizeArray(envDisableConfig.instrumentations);
}
if (envDisableConfig.groups) {
envDisableConfig.groups = normalizeArray(envDisableConfig.groups);
}

return envDisableConfig;
}
}

if (config.tracing.disable === true) {
logger?.debug('[config] incode:tracing.disable = true');

return true;
}

const hasDisableConfig = isDisableConfigNonEmpty(config);

if (hasDisableConfig) {
logger?.debug(`[config] incode:tracing.disable = ${JSON.stringify(config.tracing.disable)}`);
}

// Fallback to environment variables if `disable` is not explicitly configured
const disableConfig = isDisableConfigNonEmpty(config) ? config.tracing.disable : getDisableFromEnv();
const disableConfig = isDisableConfigNonEmpty(config) ? config.tracing.disable : null;

if (!disableConfig) return {};

if (disableConfig === true) return true;

// Normalize instrumentations and groups
if (disableConfig?.instrumentations) {
disableConfig.instrumentations = normalizeArray(disableConfig.instrumentations);
Expand Down Expand Up @@ -90,7 +113,7 @@ exports.normalizeExternalConfig = function normalizeExternalConfig(config) {
* 2. INSTANA_TRACING_DISABLE_INSTRUMENTATIONS / INSTANA_TRACING_DISABLE_GROUPS
* 3. INSTANA_TRACING_DISABLE=list
*
* @returns {import('../../config/types').Disable}
* @returns {import('../../config/types').Disable | boolean | null}
*/
function getDisableFromEnv() {
const disable = {};
Expand All @@ -104,7 +127,12 @@ function getDisableFromEnv() {
return true;
}

if (envVarValue !== 'false' && envVarValue !== '') {
if (envVarValue === 'false') {
logger?.debug('[config] env:INSTANA_TRACING_DISABLE = false');
return false;
}

if (envVarValue !== '') {
const categorized = categorizeDisableEntries(parseEnvVar(envVarValue));
if (categorized?.instrumentations?.length) {
disable.instrumentations = categorized.instrumentations;
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/config/configNormalizers/stackTrace.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ exports.normalizeStackTraceMode = function (config) {

/**
* Normalizes stack trace length configuration based on precedence.
* Precedence: global config > config > env var > default
* Precedence: env var > global config > config > default
* @param {import('../../config').InstanaConfig} config
* @returns {number} - Normalized value
*/
Expand Down
86 changes: 46 additions & 40 deletions packages/core/src/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,12 @@ module.exports.normalize = ({ userConfig = {}, finalConfigBase = {}, defaultsOve
function normalizeServiceName(userConfig, defaultConfig, finalConfig) {
const userValue = userConfig.serviceName;

if (process.env.INSTANA_SERVICE_NAME) {
finalConfig.serviceName = process.env.INSTANA_SERVICE_NAME;
logger.debug(`[config] env:INSTANA_SERVICE_NAME = ${process.env.INSTANA_SERVICE_NAME}`);
return;
}

if (userValue != null) {
if (typeof userValue === 'string') {
finalConfig.serviceName = userValue;
Expand All @@ -198,12 +204,10 @@ function normalizeServiceName(userConfig, defaultConfig, finalConfig) {
logger.warn(`Invalid configuration: config.serviceName is not a string, the value will be ignored: ${userValue}`);
finalConfig.serviceName = defaultConfig.serviceName;
}
} else if (process.env.INSTANA_SERVICE_NAME) {
finalConfig.serviceName = process.env.INSTANA_SERVICE_NAME;
logger.debug(`[config] env:INSTANA_SERVICE_NAME = ${process.env.INSTANA_SERVICE_NAME}`);
} else {
finalConfig.serviceName = defaultConfig.serviceName;
return;
}

finalConfig.serviceName = defaultConfig.serviceName;
}

/**
Expand All @@ -214,6 +218,14 @@ function normalizeServiceName(userConfig, defaultConfig, finalConfig) {
function normalizePackageJsonPath(userConfig, defaultConfig, finalConfig) {
const userValue = userConfig.packageJsonPath;

// Priority 1: Environment variable
if (process.env.INSTANA_PACKAGE_JSON_PATH) {
finalConfig.packageJsonPath = process.env.INSTANA_PACKAGE_JSON_PATH;
logger.debug(`[config] env:INSTANA_PACKAGE_JSON_PATH = ${process.env.INSTANA_PACKAGE_JSON_PATH}`);
return;
}

// Priority 2: In-code configuration
if (userValue != null) {
if (typeof userValue === 'string') {
finalConfig.packageJsonPath = userValue;
Expand All @@ -224,12 +236,11 @@ function normalizePackageJsonPath(userConfig, defaultConfig, finalConfig) {
);
finalConfig.packageJsonPath = defaultConfig.packageJsonPath;
}
} else if (process.env.INSTANA_PACKAGE_JSON_PATH) {
finalConfig.packageJsonPath = process.env.INSTANA_PACKAGE_JSON_PATH;
logger.debug(`[config] env:INSTANA_PACKAGE_JSON_PATH = ${process.env.INSTANA_PACKAGE_JSON_PATH}`);
} else {
finalConfig.packageJsonPath = defaultConfig.packageJsonPath;
return;
}

// Priority 3: Default value
finalConfig.packageJsonPath = defaultConfig.packageJsonPath;
}

/**
Expand Down Expand Up @@ -404,36 +415,31 @@ function normalizeTracingHttp(userConfig, defaultConfig, finalConfig) {
const userHttp = userConfig.tracing.http;
finalConfig.tracing.http = {};

let fromEnvVar;
if (process.env.INSTANA_EXTRA_HTTP_HEADERS) {
fromEnvVar = parseHeadersEnvVar(process.env.INSTANA_EXTRA_HTTP_HEADERS);
}

const userHeaders = userHttp?.extraHttpHeadersToCapture;

if (!userHeaders && !fromEnvVar) {
finalConfig.tracing.http.extraHttpHeadersToCapture = defaultConfig.tracing.http.extraHttpHeadersToCapture;
return;
} else if (!userHeaders && fromEnvVar) {
const fromEnvVar = parseHeadersEnvVar(process.env.INSTANA_EXTRA_HTTP_HEADERS);
finalConfig.tracing.http.extraHttpHeadersToCapture = fromEnvVar;
logger.debug(`[config] env:INSTANA_EXTRA_HTTP_HEADERS = ${process.env.INSTANA_EXTRA_HTTP_HEADERS}`);
return;
} else if (finalConfig.tracing.http.extraHttpHeadersToCapture) {
logger.debug('[config] incode: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(
userHeaders
)}`
);
finalConfig.tracing.http.extraHttpHeadersToCapture = defaultConfig.tracing.http.extraHttpHeadersToCapture;
const userHeaders = userHttp?.extraHttpHeadersToCapture;
if (userHeaders != null) {
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(
userHeaders
)}`
);
finalConfig.tracing.http.extraHttpHeadersToCapture = defaultConfig.tracing.http.extraHttpHeadersToCapture;
return;
}
finalConfig.tracing.http.extraHttpHeadersToCapture = userHeaders.map(s => s.toLowerCase());
logger.debug('[config] incode:config.tracing.http.extraHttpHeadersToCapture');
return;
}

finalConfig.tracing.http.extraHttpHeadersToCapture = userHeaders.map(s => s.toLowerCase());
finalConfig.tracing.http.extraHttpHeadersToCapture = defaultConfig.tracing.http.extraHttpHeadersToCapture;
}

/**
Expand Down Expand Up @@ -748,14 +754,7 @@ function normalizeIgnoreEndpoints(userConfig, defaultConfig, finalConfig) {
return;
}

// Case 1: Use in-code configuration if available
if (userIgnoreEndpoints && Object.keys(userIgnoreEndpoints).length) {
finalConfig.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.normalizeConfig(userIgnoreEndpoints);
logger.debug('[config] incode:config.tracing.ignoreEndpoints');
return;
}

// Case 2: Load from a YAML file if `INSTANA_IGNORE_ENDPOINTS_PATH` is set
// Priority 1: Load from a YAML file if `INSTANA_IGNORE_ENDPOINTS_PATH` is set
// 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) {
Expand All @@ -766,7 +765,7 @@ function normalizeIgnoreEndpoints(userConfig, defaultConfig, finalConfig) {
return;
}

// Case 3: Load from the `INSTANA_IGNORE_ENDPOINTS` environment variable
// Priority 2: Load from the `INSTANA_IGNORE_ENDPOINTS` environment variable
// 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) {
Expand All @@ -777,6 +776,13 @@ function normalizeIgnoreEndpoints(userConfig, defaultConfig, finalConfig) {
return;
}

// Priority 3: Use in-code configuration if available
if (userIgnoreEndpoints && Object.keys(userIgnoreEndpoints).length) {
finalConfig.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.normalizeConfig(userIgnoreEndpoints);
logger.debug('[config] incode:config.tracing.ignoreEndpoints');
return;
}

finalConfig.tracing.ignoreEndpoints = defaultConfig.tracing.ignoreEndpoints;
}

Expand Down
63 changes: 39 additions & 24 deletions packages/core/src/config/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,20 @@ function parseBooleanFromEnv(envValue) {
* @returns {boolean}
*/
exports.resolveBooleanConfig = function resolveBooleanConfig({ envVar, configValue, defaultValue, configPath }) {
// Priority 1: Environment variable
const envValue = process.env[envVar];
const envParsed = parseBooleanFromEnv(envValue);

if (envParsed !== undefined) {
logger.debug(`[config] env:${envVar} = ${envParsed}`);
return envParsed;
}

if (envValue != null) {
logger.warn(`Invalid boolean value for ${envVar}: "${envValue}". Checking in-code config.`);
}

// Priority 2: In-code configuration
if (typeof configValue === 'boolean') {
logger.debug(`[config] incode:${configPath} = ${configValue}`);
return configValue;
Expand All @@ -98,18 +112,7 @@ exports.resolveBooleanConfig = function resolveBooleanConfig({ envVar, configVal
);
}

const envValue = process.env[envVar];
const envParsed = parseBooleanFromEnv(envValue);

if (envParsed !== undefined) {
logger.debug(`[config] env:${envVar} = ${envParsed}`);
return envParsed;
}

if (envValue != null) {
logger.warn(`Invalid boolean value for ${envValue}: "${envValue}".`);
}

// Priority 3: Default value
return defaultValue;
};

Expand All @@ -130,16 +133,24 @@ exports.resolveBooleanConfigWithInvertedEnv = function resolveBooleanConfigWithI
defaultValue,
configPath
}) {
if (typeof configValue === 'boolean') {
logger.debug(`[config] incode:${configPath} = ${configValue}`);
// Priority 1: Environment variable
const envValue = process.env[envVar];
const envParsed = parseBooleanFromEnv(envValue);

return configValue;
if (envParsed !== undefined) {
const invertedValue = !envParsed;
logger.debug(`[config] env:${envVar} = ${envParsed} (inverted to ${invertedValue})`);
return invertedValue;
}

const envValue = process.env[envVar];
if (envValue === 'true') {
logger.debug(`[config] env:${envVar} = true (inverted to false)`);
return false;
if (envValue != null) {
logger.warn(`Invalid boolean value for ${envVar}: "${envValue}". Checking in-code config.`);
}

// Priority 2: In-code configuration
if (typeof configValue === 'boolean') {
logger.debug(`[config] incode:${configPath} = ${configValue}`);
return configValue;
}

if (configValue != null && configPath) {
Expand All @@ -150,6 +161,7 @@ exports.resolveBooleanConfigWithInvertedEnv = function resolveBooleanConfigWithI
);
}

// Priority 3: Default value
return defaultValue;
};

Expand All @@ -170,16 +182,19 @@ exports.resolveBooleanConfigWithTruthyEnv = function resolveBooleanConfigWithTru
defaultValue,
configPath
}) {
if (typeof configValue === 'boolean') {
logger.debug(`[config] incode:${configPath} = ${configValue}`);
return configValue;
}

// Priority 1: Environment variable (truthy check)
const envValue = process.env[envVar];
if (envValue) {
logger.debug(`[config] env:${envVar} = ${envValue}`);
return true;
}

// Priority 2: In-code configuration
if (typeof configValue === 'boolean') {
logger.debug(`[config] incode:${configPath} = ${configValue}`);
return configValue;
}

// Priority 3: Default value
return defaultValue;
};
4 changes: 2 additions & 2 deletions packages/core/test/config/configNormalizers/disable_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ describe('util.configNormalizers.disable', () => {
expect(result).to.deep.equal({});
});

it.skip('should give precedence to INSTANA_TRACING_DISABLE=false over config.tracing.disable=true', () => {
it('should give precedence to INSTANA_TRACING_DISABLE=false over config.tracing.disable=true', () => {
process.env.INSTANA_TRACING_DISABLE = 'false';

const config = {
Expand All @@ -301,7 +301,7 @@ describe('util.configNormalizers.disable', () => {
expect(result).to.deep.equal({});
});

it.skip('should give precedence to INSTANA_TRACING_DISABLE=false over config with instrumentations', () => {
it('should give precedence to INSTANA_TRACING_DISABLE=false over config with instrumentations', () => {
process.env.INSTANA_TRACING_DISABLE = 'false';

const config = {
Expand Down
Loading