Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat(core): add more scalable replacements for getEnv(), getEnvWithoutDefaults() #5443

Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ For semantic convention package changes, see the [semconv CHANGELOG](packages/se
* feat(sdk-trace-web): do not throw when passing extra options [#5357](https://github.com/open-telemetry/opentelemetry-js/pull/5357) @pichlermarc
* `WebTracerProvider` constructor now does not throw anymore when `contextManager` or `propagator` are passed as extra options to the constructor
* feat(sdk-trace-base): add stack trace warning to debug instrumentation [#5363](https://github.com/open-telemetry/opentelemetry-js/pull/5363) @neilfordyce
* feat(core): add more scalable replacements for getEnv(), getEnvWithoutDefaults() [#5443](https://github.com/open-telemetry/opentelemetry-js/pull/5443) @pichlermarc

### :bug: (Bug Fix)

Expand Down
16 changes: 10 additions & 6 deletions packages/opentelemetry-core/karma.conf.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/*!
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
Expand All @@ -17,8 +17,12 @@
const karmaWebpackConfig = require('../../karma.webpack');
const karmaBaseConfig = require('../../karma.base');

module.exports = (config) => {
config.set(Object.assign({}, karmaBaseConfig, {
webpack: karmaWebpackConfig,
}))
module.exports = config => {
config.set(
Object.assign({}, karmaBaseConfig, {
webpack: karmaWebpackConfig,
files: ['test/browser/index-webpack.ts'],
preprocessors: { 'test/browser/index-webpack.ts': ['webpack'] },
})
);
};
2 changes: 1 addition & 1 deletion packages/opentelemetry-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"prepublishOnly": "npm run compile",
"compile": "tsc --build tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"clean": "tsc --build --clean tsconfig.json tsconfig.esm.json tsconfig.esnext.json",
"test": "nyc mocha test/**/*.test.ts --exclude 'test/platform/browser/**/*.ts'",
"test": "nyc mocha 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'",
"test:browser": "karma start --single-run",
"tdd": "npm run tdd:node",
"tdd:node": "npm run test -- --watch-extensions ts --watch",
Expand Down
4 changes: 4 additions & 0 deletions packages/opentelemetry-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ export {
_globalThis,
getEnv,
getEnvWithoutDefaults,
getStringFromEnv,
getBooleanFromEnv,
getNumberFromEnv,
getStringListFromEnv,
otperformance,
unrefTimer,
} from './platform';
Expand Down
16 changes: 16 additions & 0 deletions packages/opentelemetry-core/src/platform/browser/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ export function getEnv(): Required<ENVIRONMENT> {
return Object.assign({}, DEFAULT_ENVIRONMENT, globalEnv);
}

export function getStringFromEnv(_: string): string | undefined {
return undefined;
}

export function getBooleanFromEnv(_: string): boolean | undefined {
return undefined;
}

export function getNumberFromEnv(_: string): boolean | undefined {
return undefined;
}

export function getStringListFromEnv(_: string): string[] | undefined {
return undefined;
}

export function getEnvWithoutDefaults(): ENVIRONMENT {
return parseEnvironment(_globalThis as typeof globalThis & RAW_ENVIRONMENT);
}
9 changes: 8 additions & 1 deletion packages/opentelemetry-core/src/platform/browser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@
* limitations under the License.
*/

export { getEnvWithoutDefaults, getEnv } from './environment';
export {
getEnvWithoutDefaults,
getEnv,
getStringFromEnv,
getBooleanFromEnv,
getNumberFromEnv,
getStringListFromEnv,
} from './environment';
export { _globalThis } from './globalThis';
export { otperformance } from './performance';
export { SDK_INFO } from './sdk-info';
Expand Down
4 changes: 4 additions & 0 deletions packages/opentelemetry-core/src/platform/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ export {
getEnvWithoutDefaults,
otperformance,
unrefTimer,
getBooleanFromEnv,
getStringFromEnv,
getNumberFromEnv,
getStringListFromEnv,
} from './node';
87 changes: 87 additions & 0 deletions packages/opentelemetry-core/src/platform/node/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import {
RAW_ENVIRONMENT,
parseEnvironment,
} from '../../utils/environment';
import { diag } from '@opentelemetry/api';
import { inspect } from 'util';

/**
* Gets the environment variables
Expand All @@ -29,6 +31,91 @@ export function getEnv(): Required<ENVIRONMENT> {
return Object.assign({}, DEFAULT_ENVIRONMENT, processEnv);
}

/**
* Retrieves a number from an environment variable.
* - Trims leading and trailing whitespace.
* - Returns `undefined` if the environment variable is empty, unset, contains only whitespace, or is not a number.
* - Returns a number in all other cases.
*
* @param {string} key - The name of the environment variable to retrieve.
* @returns {number | undefined} - The number value or `undefined`.
*/
export function getNumberFromEnv(key: string): number | undefined {
const raw = process.env[key];
if (raw == null || raw.trim() === '') {
return undefined;
}

const value = Number(raw);
if (isNaN(value)) {
diag.warn(
`Unknown value ${inspect(raw)} for ${key}, expected a number, using defaults`
);
return undefined;
}

return value;
}

/**
* Retrieves a string from an environment variable.
* - Returns `undefined` if the environment variable is empty, unset, or contains only whitespace.
*
* @param {string} key - The name of the environment variable to retrieve.
* @returns {string | undefined} - The string value or `undefined`.
*/
export function getStringFromEnv(key: string): string | undefined {
const raw = process.env[key];
if (raw == null || raw.trim() === '') {
return undefined;
}
return raw;
}

/**
* Retrieves a boolean value from an environment variable.
* - Trims leading and trailing whitespace and ignores casing.
* - Returns `undefined` if the environment variable is empty, unset, or contains only whitespace.
* - Returns `undefined` for strings that cannot be mapped to a boolean.
*
* @param {string} key - The name of the environment variable to retrieve.
* @returns {boolean | undefined} - The boolean value or `undefined`.
*/
export function getBooleanFromEnv(key: string): boolean | undefined {
const raw = process.env[key]?.trim().toLowerCase();
if (raw == null || raw === '') {
return undefined;
}
if (raw === 'true') {
return true;
} else if (raw === 'false') {
return false;
} else {
diag.warn(
`Unknown value ${inspect(raw)} for ${key}, expected 'true' or 'false', using defaults`
);
return undefined;
}
}

/**
* Retrieves a list of strings from an environment variable.
* - Uses ',' as the delimiter.
* - Trims leading and trailing whitespace from each entry.
* - Excludes empty entries.
* - Returns `undefined` if the environment variable is empty or contains only whitespace.
* - Returns an empty array if all entries are empty or whitespace.
*
* @param {string} key - The name of the environment variable to retrieve.
* @returns {string[] | undefined} - The list of strings or `undefined`.
*/
export function getStringListFromEnv(key: string): string[] | undefined {
return getStringFromEnv(key)
?.split(',')
.map(v => v.trim())
.filter(s => s !== '');
}
Comment on lines +114 to +119
Copy link
Member Author

@pichlermarc pichlermarc Feb 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for reviewers: this is not in the spec but it has proven useful in quite a few places OTEL_PROPAGATORS, OTEL_SEMCONV_STABILITY_OPT_IN, ...


export function getEnvWithoutDefaults(): ENVIRONMENT {
return parseEnvironment(process.env as RAW_ENVIRONMENT);
}
9 changes: 8 additions & 1 deletion packages/opentelemetry-core/src/platform/node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@
* limitations under the License.
*/

export { getEnvWithoutDefaults, getEnv } from './environment';
export {
getEnvWithoutDefaults,
getEnv,
getStringFromEnv,
getBooleanFromEnv,
getNumberFromEnv,
getStringListFromEnv,
} from './environment';
export { _globalThis } from './globalThis';
export { otperformance } from './performance';
export { SDK_INFO } from './sdk-info';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

import * as assert from 'assert';
import { getEnv } from '../../../src/platform/browser/environment';
import { getEnv } from '../../src/platform/browser/environment';

describe('getEnv', () => {
it('get environments variables in a browser', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const testsContextCommon = require.context('.', true, /test$/);
const testsContext = require.context('../browser', true, /test$/);
testsContext.keys().forEach(testsContext);

const testsContextCommon = require.context('../common', true, /test$/);
testsContextCommon.keys().forEach(testsContextCommon);

const srcContext = require.context('.', true, /src$/);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import {
} from '@opentelemetry/api';
import { ROOT_CONTEXT } from '@opentelemetry/api';
import * as assert from 'assert';
import { W3CBaggagePropagator } from '../../src/baggage/propagation/W3CBaggagePropagator';
import { BAGGAGE_HEADER } from '../../src/baggage/constants';
import { W3CBaggagePropagator } from '../../../src/baggage/propagation/W3CBaggagePropagator';
import { BAGGAGE_HEADER } from '../../../src/baggage/constants';

describe('W3CBaggagePropagator', () => {
const httpBaggagePropagator = new W3CBaggagePropagator();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

import * as assert from 'assert';
import * as sinon from 'sinon';
import { ExportResult, ExportResultCode } from '../../src';
import * as suppress from '../../src/trace/suppress-tracing';
import { _export } from '../../src/internal/exporter';
import { ExportResult, ExportResultCode } from '../../../src';
import * as suppress from '../../../src/trace/suppress-tracing';
import { _export } from '../../../src/internal/exporter';

describe('exporter', () => {
const sandbox = sinon.createSandbox();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

import * as assert from 'assert';
import { validateKey, validateValue } from '../../src/internal/validators';
import { validateKey, validateValue } from '../../../src/internal/validators';

describe('validators', () => {
describe('validateKey', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ import {
} from '@opentelemetry/api';
import { Context, ROOT_CONTEXT } from '@opentelemetry/api';
import * as assert from 'assert';
import { CompositePropagator, W3CTraceContextPropagator } from '../../src';
import { CompositePropagator, W3CTraceContextPropagator } from '../../../src';
import {
TRACE_PARENT_HEADER,
TRACE_STATE_HEADER,
} from '../../src/trace/W3CTraceContextPropagator';
import { TraceState } from '../../src/trace/TraceState';
} from '../../../src/trace/W3CTraceContextPropagator';
import { TraceState } from '../../../src/trace/TraceState';

class DummyPropagator implements TextMapPropagator {
inject(context: Context, carrier: any, setter: TextMapSetter<any>): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ import {
W3CTraceContextPropagator,
TRACE_PARENT_HEADER,
TRACE_STATE_HEADER,
} from '../../src/trace/W3CTraceContextPropagator';
import { suppressTracing } from '../../src/trace/suppress-tracing';
import { TraceState } from '../../src/trace/TraceState';
} from '../../../src/trace/W3CTraceContextPropagator';
import { suppressTracing } from '../../../src/trace/suppress-tracing';
import { TraceState } from '../../../src/trace/TraceState';

describe('W3CTraceContextPropagator', () => {
const httpTraceContext = new W3CTraceContextPropagator();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

import * as assert from 'assert';
import { TraceState } from '../../src/trace/TraceState';
import { TraceState } from '../../../src/trace/TraceState';

describe('TraceState', () => {
describe('.serialize()', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

import * as assert from 'assert';
import * as sinon from 'sinon';
import { BindOnceFuture } from '../../src';
import { assertRejects } from '../test-utils';
import { BindOnceFuture } from '../../../src';
import { assertRejects } from '../../test-utils';

describe('callback', () => {
describe('BindOnceFuture', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
* limitations under the License.
*/

import { getEnv } from '../../src/platform';
import { getEnv } from '../../../src/platform';
import {
DEFAULT_ENVIRONMENT,
ENVIRONMENT,
RAW_ENVIRONMENT,
} from '../../src/utils/environment';
} from '../../../src/utils/environment';
import * as assert from 'assert';
import * as sinon from 'sinon';
import { DiagLogLevel } from '@opentelemetry/api';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/
import * as assert from 'assert';
import { merge } from '../../src/utils/merge';
import { merge } from '../../../src/utils/merge';

const tests: TestResult[] = [];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
*/

import * as assert from 'assert';
import { Deferred } from '../../src/utils/promise';
import { assertRejects } from '../test-utils';
import { Deferred } from '../../../src/utils/promise';
import { assertRejects } from '../../test-utils';

describe('promise', () => {
describe('Deferred', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import * as assert from 'assert';

import { isUrlIgnored } from '../../src';
import { isUrlIgnored } from '../../../src';

const urlIgnored = 'url should be ignored';
const urlNotIgnored = 'url should NOT be ignored';
Expand Down
Loading