Skip to content

Commit

Permalink
Add platform agnostic way to read environment variables (open-telemet…
Browse files Browse the repository at this point in the history
…ry#1191)

Co-authored-by: Mayur Kale <mayurkale@google.com>
  • Loading branch information
obecny and mayurkale22 authored Jun 26, 2020
1 parent bf2f617 commit e19a0db
Show file tree
Hide file tree
Showing 6 changed files with 253 additions and 1 deletion.
31 changes: 31 additions & 0 deletions packages/opentelemetry-core/src/platform/browser/environment.ts
Original file line number Diff line number Diff line change
@@ -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);
}
1 change: 1 addition & 0 deletions packages/opentelemetry-core/src/platform/browser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

export * from './BasePlugin';
export * from './environment';
export * from './hex-to-base64';
export * from './id';
export * from './performance';
Expand Down
30 changes: 30 additions & 0 deletions packages/opentelemetry-core/src/platform/node/environment.ts
Original file line number Diff line number Diff line change
@@ -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);
}
3 changes: 2 additions & 1 deletion packages/opentelemetry-core/src/platform/node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
97 changes: 97 additions & 0 deletions packages/opentelemetry-core/src/utils/environment.ts
Original file line number Diff line number Diff line change
@@ -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<keyof ENVIRONMENT>[] = [
'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;
}
92 changes: 92 additions & 0 deletions packages/opentelemetry-core/test/utils/environment.test.ts
Original file line number Diff line number Diff line change
@@ -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`
);
});
});
});
});

0 comments on commit e19a0db

Please sign in to comment.