Skip to content

Commit 73b5218

Browse files
committed
fix(core): ensured env vars take precedence over in-code config
1 parent b8c0e30 commit 73b5218

6 files changed

Lines changed: 145 additions & 91 deletions

File tree

packages/core/src/config/configNormalizers/disable.js

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,33 +19,56 @@ exports.init = function init(_config) {
1919
* Handles environment variables, and array inputs.
2020
*
2121
* Precedence order (highest to lowest):
22-
* 1. `tracing.disable`
23-
* 2. Environment variables (`INSTANA_TRACING_DISABLE*`)
22+
* 1. Environment variables (`INSTANA_TRACING_DISABLE*`)
23+
* 2. In-code tracing.disable
2424
*
2525
* @param {import('../../config').InstanaConfig} config
2626
*/
2727
exports.normalize = function normalize(config) {
2828
if (!config?.tracing) config.tracing = {};
2929
try {
30-
// Disable all tracing if explicitly set 'disable' to true
30+
const envDisableConfig = getDisableFromEnv();
31+
32+
if (envDisableConfig !== null) {
33+
if (envDisableConfig === true) {
34+
logger?.debug('[config] env:INSTANA_TRACING_DISABLE = true');
35+
return true;
36+
}
37+
38+
if (envDisableConfig === false) {
39+
logger?.debug('[config] env:INSTANA_TRACING_DISABLE = false (overrides in-code config)');
40+
return {};
41+
}
42+
43+
if (envDisableConfig.instrumentations?.length || envDisableConfig.groups?.length) {
44+
logger?.debug(`[config] env:INSTANA_TRACING_DISABLE* = ${JSON.stringify(envDisableConfig)}`);
45+
46+
if (envDisableConfig.instrumentations) {
47+
envDisableConfig.instrumentations = normalizeArray(envDisableConfig.instrumentations);
48+
}
49+
if (envDisableConfig.groups) {
50+
envDisableConfig.groups = normalizeArray(envDisableConfig.groups);
51+
}
52+
53+
return envDisableConfig;
54+
}
55+
}
56+
3157
if (config.tracing.disable === true) {
3258
logger?.debug('[config] incode:tracing.disable = true');
33-
3459
return true;
3560
}
61+
3662
const hasDisableConfig = isDisableConfigNonEmpty(config);
3763

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

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

4570
if (!disableConfig) return {};
4671

47-
if (disableConfig === true) return true;
48-
4972
// Normalize instrumentations and groups
5073
if (disableConfig?.instrumentations) {
5174
disableConfig.instrumentations = normalizeArray(disableConfig.instrumentations);
@@ -90,7 +113,7 @@ exports.normalizeExternalConfig = function normalizeExternalConfig(config) {
90113
* 2. INSTANA_TRACING_DISABLE_INSTRUMENTATIONS / INSTANA_TRACING_DISABLE_GROUPS
91114
* 3. INSTANA_TRACING_DISABLE=list
92115
*
93-
* @returns {import('../../config/types').Disable}
116+
* @returns {import('../../config/types').Disable | boolean | null}
94117
*/
95118
function getDisableFromEnv() {
96119
const disable = {};
@@ -104,7 +127,12 @@ function getDisableFromEnv() {
104127
return true;
105128
}
106129

107-
if (envVarValue !== 'false' && envVarValue !== '') {
130+
if (envVarValue === 'false') {
131+
logger?.debug('[config] env:INSTANA_TRACING_DISABLE = false');
132+
return false;
133+
}
134+
135+
if (envVarValue !== '') {
108136
const categorized = categorizeDisableEntries(parseEnvVar(envVarValue));
109137
if (categorized?.instrumentations?.length) {
110138
disable.instrumentations = categorized.instrumentations;

packages/core/src/config/configNormalizers/stackTrace.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ exports.normalizeStackTraceMode = function (config) {
2525

2626
/**
2727
* Normalizes stack trace length configuration based on precedence.
28-
* Precedence: global config > config > env var > default
28+
* Precedence: env var > global config > config > default
2929
* @param {import('../../config').InstanaConfig} config
3030
* @returns {number} - Normalized value
3131
*/

packages/core/src/config/index.js

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,12 @@ module.exports.normalize = ({ userConfig = {}, finalConfigBase = {}, defaultsOve
185185
function normalizeServiceName({ userConfig = {}, defaultConfig = {}, finalConfig = {} } = {}) {
186186
const userValue = userConfig.serviceName;
187187

188+
if (process.env.INSTANA_SERVICE_NAME) {
189+
finalConfig.serviceName = process.env.INSTANA_SERVICE_NAME;
190+
logger.debug(`[config] env:INSTANA_SERVICE_NAME = ${process.env.INSTANA_SERVICE_NAME}`);
191+
return;
192+
}
193+
188194
if (userValue != null) {
189195
if (typeof userValue === 'string') {
190196
finalConfig.serviceName = userValue;
@@ -193,12 +199,10 @@ function normalizeServiceName({ userConfig = {}, defaultConfig = {}, finalConfig
193199
logger.warn(`Invalid configuration: config.serviceName is not a string, the value will be ignored: ${userValue}`);
194200
finalConfig.serviceName = defaultConfig.serviceName;
195201
}
196-
} else if (process.env.INSTANA_SERVICE_NAME) {
197-
finalConfig.serviceName = process.env.INSTANA_SERVICE_NAME;
198-
logger.debug(`[config] env:INSTANA_SERVICE_NAME = ${process.env.INSTANA_SERVICE_NAME}`);
199-
} else {
200-
finalConfig.serviceName = defaultConfig.serviceName;
202+
return;
201203
}
204+
205+
finalConfig.serviceName = defaultConfig.serviceName;
202206
}
203207

204208
/**
@@ -207,6 +211,14 @@ function normalizeServiceName({ userConfig = {}, defaultConfig = {}, finalConfig
207211
function normalizePackageJsonPath({ userConfig = {}, defaultConfig = {}, finalConfig = {} } = {}) {
208212
const userValue = userConfig.packageJsonPath;
209213

214+
// Priority 1: Environment variable
215+
if (process.env.INSTANA_PACKAGE_JSON_PATH) {
216+
finalConfig.packageJsonPath = process.env.INSTANA_PACKAGE_JSON_PATH;
217+
logger.debug(`[config] env:INSTANA_PACKAGE_JSON_PATH = ${process.env.INSTANA_PACKAGE_JSON_PATH}`);
218+
return;
219+
}
220+
221+
// Priority 2: In-code configuration
210222
if (userValue != null) {
211223
if (typeof userValue === 'string') {
212224
finalConfig.packageJsonPath = userValue;
@@ -217,12 +229,11 @@ function normalizePackageJsonPath({ userConfig = {}, defaultConfig = {}, finalCo
217229
);
218230
finalConfig.packageJsonPath = defaultConfig.packageJsonPath;
219231
}
220-
} else if (process.env.INSTANA_PACKAGE_JSON_PATH) {
221-
finalConfig.packageJsonPath = process.env.INSTANA_PACKAGE_JSON_PATH;
222-
logger.debug(`[config] env:INSTANA_PACKAGE_JSON_PATH = ${process.env.INSTANA_PACKAGE_JSON_PATH}`);
223-
} else {
224-
finalConfig.packageJsonPath = defaultConfig.packageJsonPath;
232+
return;
225233
}
234+
235+
// Priority 3: Default value
236+
finalConfig.packageJsonPath = defaultConfig.packageJsonPath;
226237
}
227238

228239
/**
@@ -707,14 +718,7 @@ function normalizeIgnoreEndpoints({ userConfig = {}, defaultConfig = {}, finalCo
707718
return;
708719
}
709720

710-
// Case 1: Use in-code configuration if available
711-
if (userIgnoreEndpoints && Object.keys(userIgnoreEndpoints).length) {
712-
finalConfig.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.normalizeConfig(userIgnoreEndpoints);
713-
logger.debug('[config] incode:config.tracing.ignoreEndpoints');
714-
return;
715-
}
716-
717-
// Case 2: Load from a YAML file if `INSTANA_IGNORE_ENDPOINTS_PATH` is set
721+
// Priority 1: Load from a YAML file if `INSTANA_IGNORE_ENDPOINTS_PATH` is set
718722
// Introduced in Phase 2 for advanced filtering based on both methods and endpoints.
719723
// Also supports basic filtering for endpoints.
720724
if (process.env.INSTANA_IGNORE_ENDPOINTS_PATH) {
@@ -725,7 +729,7 @@ function normalizeIgnoreEndpoints({ userConfig = {}, defaultConfig = {}, finalCo
725729
return;
726730
}
727731

728-
// Case 3: Load from the `INSTANA_IGNORE_ENDPOINTS` environment variable
732+
// Priority 2: Load from the `INSTANA_IGNORE_ENDPOINTS` environment variable
729733
// Introduced in Phase 1 for basic filtering based only on operations (e.g., `redis.get`, `kafka.consume`).
730734
// Provides a simple way to configure ignored operations via environment variables.
731735
if (process.env.INSTANA_IGNORE_ENDPOINTS) {
@@ -736,6 +740,13 @@ function normalizeIgnoreEndpoints({ userConfig = {}, defaultConfig = {}, finalCo
736740
return;
737741
}
738742

743+
// Priority 3: Use in-code configuration if available
744+
if (userIgnoreEndpoints && Object.keys(userIgnoreEndpoints).length) {
745+
finalConfig.tracing.ignoreEndpoints = configNormalizers.ignoreEndpoints.normalizeConfig(userIgnoreEndpoints);
746+
logger.debug('[config] incode:config.tracing.ignoreEndpoints');
747+
return;
748+
}
749+
739750
finalConfig.tracing.ignoreEndpoints = defaultConfig.tracing.ignoreEndpoints;
740751
}
741752

packages/core/src/config/util.js

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,20 @@ function parseBooleanFromEnv(envValue) {
8585
* @returns {boolean}
8686
*/
8787
exports.resolveBooleanConfig = function resolveBooleanConfig({ envVar, configValue, defaultValue, configPath }) {
88+
// Priority 1: Environment variable
89+
const envValue = process.env[envVar];
90+
const envParsed = parseBooleanFromEnv(envValue);
91+
92+
if (envParsed !== undefined) {
93+
logger.debug(`[config] env:${envVar} = ${envParsed}`);
94+
return envParsed;
95+
}
96+
97+
if (envValue != null) {
98+
logger.warn(`Invalid boolean value for ${envVar}: "${envValue}". Checking in-code config.`);
99+
}
100+
101+
// Priority 2: In-code configuration
88102
if (typeof configValue === 'boolean') {
89103
logger.debug(`[config] incode:${configPath} = ${configValue}`);
90104
return configValue;
@@ -98,18 +112,7 @@ exports.resolveBooleanConfig = function resolveBooleanConfig({ envVar, configVal
98112
);
99113
}
100114

101-
const envValue = process.env[envVar];
102-
const envParsed = parseBooleanFromEnv(envValue);
103-
104-
if (envParsed !== undefined) {
105-
logger.debug(`[config] env:${envVar} = ${envParsed}`);
106-
return envParsed;
107-
}
108-
109-
if (envValue != null) {
110-
logger.warn(`Invalid boolean value for ${envValue}: "${envValue}".`);
111-
}
112-
115+
// Priority 3: Default value
113116
return defaultValue;
114117
};
115118

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

136-
return configValue;
140+
if (envParsed !== undefined) {
141+
const invertedValue = !envParsed;
142+
logger.debug(`[config] env:${envVar} = ${envParsed} (inverted to ${invertedValue})`);
143+
return invertedValue;
137144
}
138145

139-
const envValue = process.env[envVar];
140-
if (envValue === 'true') {
141-
logger.debug(`[config] env:${envVar} = true (inverted to false)`);
142-
return false;
146+
if (envValue != null) {
147+
logger.warn(`Invalid boolean value for ${envVar}: "${envValue}". Checking in-code config.`);
148+
}
149+
150+
// Priority 2: In-code configuration
151+
if (typeof configValue === 'boolean') {
152+
logger.debug(`[config] incode:${configPath} = ${configValue}`);
153+
return configValue;
143154
}
144155

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

164+
// Priority 3: Default value
153165
return defaultValue;
154166
};
155167

@@ -170,16 +182,19 @@ exports.resolveBooleanConfigWithTruthyEnv = function resolveBooleanConfigWithTru
170182
defaultValue,
171183
configPath
172184
}) {
173-
if (typeof configValue === 'boolean') {
174-
logger.debug(`[config] incode:${configPath} = ${configValue}`);
175-
return configValue;
176-
}
177-
185+
// Priority 1: Environment variable (truthy check)
178186
const envValue = process.env[envVar];
179187
if (envValue) {
180188
logger.debug(`[config] env:${envVar} = ${envValue}`);
181189
return true;
182190
}
183191

192+
// Priority 2: In-code configuration
193+
if (typeof configValue === 'boolean') {
194+
logger.debug(`[config] incode:${configPath} = ${configValue}`);
195+
return configValue;
196+
}
197+
198+
// Priority 3: Default value
184199
return defaultValue;
185200
};

packages/core/test/config/configNormalizers/disable_test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ describe('util.configNormalizers.disable', () => {
288288
expect(result).to.deep.equal({});
289289
});
290290

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

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

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

307307
const config = {

0 commit comments

Comments
 (0)