diff --git a/packages/opentelemetry-core/src/platform/browser/environment.ts b/packages/opentelemetry-core/src/platform/browser/environment.ts new file mode 100644 index 0000000000..54a2a6c571 --- /dev/null +++ b/packages/opentelemetry-core/src/platform/browser/environment.ts @@ -0,0 +1,31 @@ +/* + * 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 + * + * 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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + DEFAULT_ENVIRONMENT, + ENVIRONMENT, + ENVIRONMENT_MAP, + parseEnvironment, +} from '../../utils/environment'; + +/** + * Gets the environment variables + */ +export function getEnv(): ENVIRONMENT { + const _window = window as typeof window & ENVIRONMENT_MAP; + const globalEnv = parseEnvironment(_window); + return Object.assign({}, DEFAULT_ENVIRONMENT, globalEnv); +} diff --git a/packages/opentelemetry-core/src/platform/browser/index.ts b/packages/opentelemetry-core/src/platform/browser/index.ts index d066951cf9..20c47613e6 100644 --- a/packages/opentelemetry-core/src/platform/browser/index.ts +++ b/packages/opentelemetry-core/src/platform/browser/index.ts @@ -15,6 +15,7 @@ */ export * from './BasePlugin'; +export * from './environment'; export * from './hex-to-base64'; export * from './id'; export * from './performance'; diff --git a/packages/opentelemetry-core/src/platform/node/environment.ts b/packages/opentelemetry-core/src/platform/node/environment.ts new file mode 100644 index 0000000000..f3595cd9af --- /dev/null +++ b/packages/opentelemetry-core/src/platform/node/environment.ts @@ -0,0 +1,30 @@ +/* + * 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 + * + * 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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + DEFAULT_ENVIRONMENT, + ENVIRONMENT, + ENVIRONMENT_MAP, + parseEnvironment, +} from '../../utils/environment'; + +/** + * Gets the environment variables + */ +export function getEnv(): ENVIRONMENT { + const processEnv = parseEnvironment(process.env as ENVIRONMENT_MAP); + return Object.assign({}, DEFAULT_ENVIRONMENT, processEnv); +} diff --git a/packages/opentelemetry-core/src/platform/node/index.ts b/packages/opentelemetry-core/src/platform/node/index.ts index 693bef3145..20c47613e6 100644 --- a/packages/opentelemetry-core/src/platform/node/index.ts +++ b/packages/opentelemetry-core/src/platform/node/index.ts @@ -15,8 +15,9 @@ */ export * from './BasePlugin'; +export * from './environment'; +export * from './hex-to-base64'; export * from './id'; export * from './performance'; export * from './sdk-info'; export * from './timer-util'; -export * from './hex-to-base64'; diff --git a/packages/opentelemetry-core/src/utils/environment.ts b/packages/opentelemetry-core/src/utils/environment.ts new file mode 100644 index 0000000000..be56f892c0 --- /dev/null +++ b/packages/opentelemetry-core/src/utils/environment.ts @@ -0,0 +1,97 @@ +/* + * 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 + * + * 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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { LogLevel } from '../common/types'; + +export type ENVIRONMENT_MAP = { [key: string]: string | number }; + +/** + * Environment interface to define all names + */ +export interface ENVIRONMENT { + OTEL_LOG_LEVEL?: LogLevel; + OTEL_NO_PATCH_MODULES?: string; + OTEL_SAMPLING_PROBABILITY?: number; +} + +const ENVIRONMENT_NUMBERS: Partial[] = [ + 'OTEL_LOG_LEVEL', + 'OTEL_SAMPLING_PROBABILITY', +]; + +/** + * Default environment variables + */ +export const DEFAULT_ENVIRONMENT: ENVIRONMENT = { + OTEL_NO_PATCH_MODULES: '', + OTEL_LOG_LEVEL: LogLevel.ERROR, + OTEL_SAMPLING_PROBABILITY: 1, +}; + +/** + * Parses a variable as number with number validation + * @param name + * @param environment + * @param values + * @param min + * @param max + */ +function parseNumber( + name: keyof ENVIRONMENT, + environment: ENVIRONMENT_MAP | ENVIRONMENT, + values: ENVIRONMENT_MAP, + min = -Infinity, + max = Infinity +) { + if (typeof values[name] !== 'undefined') { + const value = Number(values[name] as string); + if (!isNaN(value) && value >= min && value <= max) { + environment[name] = value; + } + } +} + +/** + * Parses environment values + * @param values + */ +export function parseEnvironment(values: ENVIRONMENT_MAP): ENVIRONMENT { + const environment: ENVIRONMENT_MAP = {}; + + for (const env in DEFAULT_ENVIRONMENT) { + const key = env as keyof ENVIRONMENT; + switch (key) { + case 'OTEL_SAMPLING_PROBABILITY': + parseNumber(key, environment, values, 0, 1); + break; + + case 'OTEL_LOG_LEVEL': + parseNumber(key, environment, values, LogLevel.ERROR, LogLevel.DEBUG); + break; + + default: + if (ENVIRONMENT_NUMBERS.indexOf(key) >= 0) { + parseNumber(key, environment, values); + } else { + if (typeof values[key] !== 'undefined') { + environment[key] = values[key]; + } + } + } + } + + return environment; +} diff --git a/packages/opentelemetry-core/test/utils/environment.test.ts b/packages/opentelemetry-core/test/utils/environment.test.ts new file mode 100644 index 0000000000..267a6bf285 --- /dev/null +++ b/packages/opentelemetry-core/test/utils/environment.test.ts @@ -0,0 +1,92 @@ +/* + * 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 + * + * 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, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getEnv } from '../../src/platform'; +import { + DEFAULT_ENVIRONMENT, + ENVIRONMENT, + ENVIRONMENT_MAP, +} from '../../src/utils/environment'; +import * as assert from 'assert'; +import * as sinon from 'sinon'; + +let lastMock: ENVIRONMENT_MAP = {}; + +function mockEnvironment(values: ENVIRONMENT_MAP) { + lastMock = values; + if (typeof process !== 'undefined') { + Object.keys(values).forEach(key => { + process.env[key] = String(values[key]); + }); + } else { + Object.keys(values).forEach(key => { + ((window as unknown) as ENVIRONMENT_MAP)[key] = String(values[key]); + }); + } +} + +function removeMockEnvironment() { + if (typeof process !== 'undefined') { + Object.keys(lastMock).forEach(key => { + delete process.env[key]; + }); + } else { + Object.keys(lastMock).forEach(key => { + delete ((window as unknown) as ENVIRONMENT_MAP)[key]; + }); + } + lastMock = {}; +} + +describe('environment', () => { + let sandbox: sinon.SinonSandbox; + + beforeEach(() => { + sandbox = sinon.createSandbox(); + }); + + afterEach(() => { + removeMockEnvironment(); + sandbox.restore(); + }); + + describe('parseEnvironment', () => { + it('should parse environment variables', () => { + mockEnvironment({ + FOO: '1', + OTEL_NO_PATCH_MODULES: 'a,b,c', + OTEL_LOG_LEVEL: '1', + OTEL_SAMPLING_PROBABILITY: '0.5', + }); + const env = getEnv(); + assert.strictEqual(env.OTEL_NO_PATCH_MODULES, 'a,b,c'); + assert.strictEqual(env.OTEL_LOG_LEVEL, 1); + assert.strictEqual(env.OTEL_SAMPLING_PROBABILITY, 0.5); + }); + + it('should parse environment variables and use defaults', () => { + const env = getEnv(); + Object.keys(DEFAULT_ENVIRONMENT).forEach(envKey => { + const key = envKey as keyof ENVIRONMENT; + assert.strictEqual( + env[key as keyof ENVIRONMENT], + DEFAULT_ENVIRONMENT[key], + `Variable '${key}' doesn't match` + ); + }); + }); + }); +});