Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into propagaion-api-fields
Browse files Browse the repository at this point in the history
dyladan authored Jan 13, 2021
2 parents 7497dbe + 139d9db commit c89ce15
Showing 15 changed files with 272 additions and 113 deletions.
Original file line number Diff line number Diff line change
@@ -17,15 +17,15 @@
import {
DEFAULT_ENVIRONMENT,
ENVIRONMENT,
ENVIRONMENT_MAP,
RAW_ENVIRONMENT,
parseEnvironment,
} from '../../utils/environment';

/**
* Gets the environment variables
*/
export function getEnv(): Required<ENVIRONMENT> {
const _window = window as typeof window & ENVIRONMENT_MAP;
const _window = window as typeof window & RAW_ENVIRONMENT;
const globalEnv = parseEnvironment(_window);
return Object.assign({}, DEFAULT_ENVIRONMENT, globalEnv);
}
13 changes: 10 additions & 3 deletions packages/opentelemetry-core/src/platform/node/environment.ts
Original file line number Diff line number Diff line change
@@ -14,17 +14,24 @@
* limitations under the License.
*/

import * as os from 'os';
import {
DEFAULT_ENVIRONMENT,
ENVIRONMENT,
ENVIRONMENT_MAP,
RAW_ENVIRONMENT,
parseEnvironment,
} from '../../utils/environment';

/**
* Gets the environment variables
*/
export function getEnv(): Required<ENVIRONMENT> {
const processEnv = parseEnvironment(process.env as ENVIRONMENT_MAP);
return Object.assign({}, DEFAULT_ENVIRONMENT, processEnv);
const processEnv = parseEnvironment(process.env as RAW_ENVIRONMENT);
return Object.assign(
{
HOSTNAME: os.hostname(),
},
DEFAULT_ENVIRONMENT,
processEnv
);
}
117 changes: 90 additions & 27 deletions packages/opentelemetry-core/src/utils/environment.ts
Original file line number Diff line number Diff line change
@@ -16,37 +16,78 @@

import { LogLevel } from '../common/types';

export type ENVIRONMENT_MAP = { [key: string]: string | number };
const DEFAULT_LIST_SEPARATOR = ',';

/**
* Environment interface to define all names
*/
export interface ENVIRONMENT {
OTEL_LOG_LEVEL?: LogLevel;
OTEL_NO_PATCH_MODULES?: string;
OTEL_SAMPLING_PROBABILITY?: number;
OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT?: number;
OTEL_SPAN_EVENT_COUNT_LIMIT?: number;
OTEL_SPAN_LINK_COUNT_LIMIT?: number;
OTEL_BSP_MAX_BATCH_SIZE?: number;
OTEL_BSP_SCHEDULE_DELAY_MILLIS?: number;
}

const ENVIRONMENT_NUMBERS: Partial<keyof ENVIRONMENT>[] = [
const ENVIRONMENT_NUMBERS_KEYS = [
'OTEL_BSP_MAX_BATCH_SIZE',
'OTEL_BSP_SCHEDULE_DELAY_MILLIS',
'OTEL_SAMPLING_PROBABILITY',
'OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT',
'OTEL_SPAN_EVENT_COUNT_LIMIT',
'OTEL_SPAN_LINK_COUNT_LIMIT',
'OTEL_BSP_MAX_BATCH_SIZE',
'OTEL_BSP_SCHEDULE_DELAY_MILLIS',
];
] as const;

type ENVIRONMENT_NUMBERS = {
[K in typeof ENVIRONMENT_NUMBERS_KEYS[number]]?: number;
};

function isEnvVarANumber(key: unknown): key is keyof ENVIRONMENT_NUMBERS {
return (
ENVIRONMENT_NUMBERS_KEYS.indexOf(key as keyof ENVIRONMENT_NUMBERS) > -1
);
}

const ENVIRONMENT_LISTS_KEYS = ['OTEL_NO_PATCH_MODULES'] as const;

type ENVIRONMENT_LISTS = {
[K in typeof ENVIRONMENT_LISTS_KEYS[number]]?: string[];
};

function isEnvVarAList(key: unknown): key is keyof ENVIRONMENT_LISTS {
return ENVIRONMENT_LISTS_KEYS.indexOf(key as keyof ENVIRONMENT_LISTS) > -1;
}

export type ENVIRONMENT = {
CONTAINER_NAME?: string;
ECS_CONTAINER_METADATA_URI_V4?: string;
ECS_CONTAINER_METADATA_URI?: string;
HOSTNAME?: string;
KUBERNETES_SERVICE_HOST?: string;
NAMESPACE?: string;
OTEL_EXPORTER_JAEGER_AGENT_HOST?: string;
OTEL_EXPORTER_JAEGER_ENDPOINT?: string;
OTEL_EXPORTER_JAEGER_PASSWORD?: string;
OTEL_EXPORTER_JAEGER_USER?: string;
OTEL_LOG_LEVEL?: LogLevel;
OTEL_RESOURCE_ATTRIBUTES?: string;
} & ENVIRONMENT_NUMBERS &
ENVIRONMENT_LISTS;

export type RAW_ENVIRONMENT = {
[key: string]: string | number | undefined | string[];
};

/**
* Default environment variables
*/
export const DEFAULT_ENVIRONMENT: Required<ENVIRONMENT> = {
OTEL_NO_PATCH_MODULES: '',
CONTAINER_NAME: '',
ECS_CONTAINER_METADATA_URI_V4: '',
ECS_CONTAINER_METADATA_URI: '',
HOSTNAME: '',
KUBERNETES_SERVICE_HOST: '',
NAMESPACE: '',
OTEL_EXPORTER_JAEGER_AGENT_HOST: '',
OTEL_EXPORTER_JAEGER_ENDPOINT: '',
OTEL_EXPORTER_JAEGER_PASSWORD: '',
OTEL_EXPORTER_JAEGER_USER: '',
OTEL_LOG_LEVEL: LogLevel.INFO,
OTEL_NO_PATCH_MODULES: [],
OTEL_RESOURCE_ATTRIBUTES: '',
OTEL_SAMPLING_PROBABILITY: 1,
OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT: 1000,
OTEL_SPAN_EVENT_COUNT_LIMIT: 1000,
@@ -64,15 +105,14 @@ export const DEFAULT_ENVIRONMENT: Required<ENVIRONMENT> = {
* @param max
*/
function parseNumber(
name: keyof ENVIRONMENT,
environment: ENVIRONMENT_MAP | ENVIRONMENT,
values: ENVIRONMENT_MAP,
name: keyof ENVIRONMENT_NUMBERS,
environment: ENVIRONMENT,
values: RAW_ENVIRONMENT,
min = -Infinity,
max = Infinity
) {
if (typeof values[name] !== 'undefined') {
const value = Number(values[name] as string);

if (!isNaN(value)) {
if (value < min) {
environment[name] = min;
@@ -85,6 +125,25 @@ function parseNumber(
}
}

/**
* Parses list-like strings from input into output.
* @param name
* @param environment
* @param values
* @param separator
*/
function parseStringList(
name: keyof ENVIRONMENT_LISTS,
output: ENVIRONMENT,
input: RAW_ENVIRONMENT,
separator = DEFAULT_LIST_SEPARATOR
) {
const givenValue = input[name];
if (typeof givenValue === 'string') {
output[name] = givenValue.split(separator).map(v => v.trim());
}
}

/**
* Environmentally sets log level if valid log level string is provided
* @param key
@@ -93,8 +152,8 @@ function parseNumber(
*/
function setLogLevelFromEnv(
key: keyof ENVIRONMENT,
environment: ENVIRONMENT_MAP | ENVIRONMENT,
values: ENVIRONMENT_MAP
environment: RAW_ENVIRONMENT | ENVIRONMENT,
values: RAW_ENVIRONMENT
) {
const value = values[key];
switch (typeof value === 'string' ? value.toUpperCase() : value) {
@@ -124,11 +183,12 @@ function setLogLevelFromEnv(
* Parses environment values
* @param values
*/
export function parseEnvironment(values: ENVIRONMENT_MAP): ENVIRONMENT {
const environment: ENVIRONMENT_MAP = {};
export function parseEnvironment(values: RAW_ENVIRONMENT): ENVIRONMENT {
const environment: ENVIRONMENT = {};

for (const env in DEFAULT_ENVIRONMENT) {
const key = env as keyof ENVIRONMENT;

switch (key) {
case 'OTEL_SAMPLING_PROBABILITY':
parseNumber(key, environment, values, 0, 1);
@@ -139,11 +199,14 @@ export function parseEnvironment(values: ENVIRONMENT_MAP): ENVIRONMENT {
break;

default:
if (ENVIRONMENT_NUMBERS.indexOf(key) >= 0) {
if (isEnvVarANumber(key)) {
parseNumber(key, environment, values);
} else if (isEnvVarAList(key)) {
parseStringList(key, environment, values);
} else {
if (typeof values[key] !== 'undefined') {
environment[key] = values[key];
const value = values[key];
if (typeof value !== 'undefined' && value !== null) {
environment[key] = String(value);
}
}
}
49 changes: 40 additions & 9 deletions packages/opentelemetry-core/test/utils/environment.test.ts
Original file line number Diff line number Diff line change
@@ -18,26 +18,26 @@ import { getEnv } from '../../src/platform';
import {
DEFAULT_ENVIRONMENT,
ENVIRONMENT,
ENVIRONMENT_MAP,
RAW_ENVIRONMENT,
} from '../../src/utils/environment';
import * as assert from 'assert';
import * as sinon from 'sinon';
import { LogLevel } from '../../src';

let lastMock: ENVIRONMENT_MAP = {};
let lastMock: RAW_ENVIRONMENT = {};

/**
* Mocks environment used for tests.
*/
export function mockEnvironment(values: ENVIRONMENT_MAP) {
export function mockEnvironment(values: RAW_ENVIRONMENT) {
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]);
((window as unknown) as RAW_ENVIRONMENT)[key] = String(values[key]);
});
}
}
@@ -52,7 +52,7 @@ export function removeMockEnvironment() {
});
} else {
Object.keys(lastMock).forEach(key => {
delete ((window as unknown) as ENVIRONMENT_MAP)[key];
delete ((window as unknown) as RAW_ENVIRONMENT)[key];
});
}
lastMock = {};
@@ -73,23 +73,54 @@ describe('environment', () => {
describe('parseEnvironment', () => {
it('should parse environment variables', () => {
mockEnvironment({
CONTAINER_NAME: 'container-1',
ECS_CONTAINER_METADATA_URI_V4: 'https://ecs.uri/v4',
ECS_CONTAINER_METADATA_URI: 'https://ecs.uri/',
FOO: '1',
OTEL_NO_PATCH_MODULES: 'a,b,c',
HOSTNAME: 'hostname',
KUBERNETES_SERVICE_HOST: 'https://k8s.host/',
NAMESPACE: 'namespace',
OTEL_BSP_MAX_BATCH_SIZE: 40,
OTEL_BSP_SCHEDULE_DELAY_MILLIS: 50,
OTEL_EXPORTER_JAEGER_AGENT_HOST: 'host.domain.com',
OTEL_EXPORTER_JAEGER_ENDPOINT: 'https://example.com/endpoint',
OTEL_EXPORTER_JAEGER_PASSWORD: 'secret',
OTEL_EXPORTER_JAEGER_USER: 'whoami',
OTEL_LOG_LEVEL: 'ERROR',
OTEL_NO_PATCH_MODULES: 'a,b,c',
OTEL_RESOURCE_ATTRIBUTES: '<attrs>',
OTEL_SAMPLING_PROBABILITY: '0.5',
OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT: 10,
OTEL_SPAN_EVENT_COUNT_LIMIT: 20,
OTEL_SPAN_LINK_COUNT_LIMIT: 30,
OTEL_BSP_MAX_BATCH_SIZE: 40,
OTEL_BSP_SCHEDULE_DELAY_MILLIS: 50,
});
const env = getEnv();
assert.strictEqual(env.OTEL_NO_PATCH_MODULES, 'a,b,c');
assert.deepStrictEqual(env.OTEL_NO_PATCH_MODULES, ['a', 'b', 'c']);
assert.strictEqual(env.OTEL_LOG_LEVEL, LogLevel.ERROR);
assert.strictEqual(env.OTEL_SAMPLING_PROBABILITY, 0.5);
assert.strictEqual(env.OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT, 10);
assert.strictEqual(env.OTEL_SPAN_EVENT_COUNT_LIMIT, 20);
assert.strictEqual(env.OTEL_SPAN_LINK_COUNT_LIMIT, 30);
assert.strictEqual(
env.OTEL_EXPORTER_JAEGER_ENDPOINT,
'https://example.com/endpoint'
);
assert.strictEqual(env.OTEL_EXPORTER_JAEGER_USER, 'whoami');
assert.strictEqual(env.OTEL_EXPORTER_JAEGER_PASSWORD, 'secret');
assert.strictEqual(
env.OTEL_EXPORTER_JAEGER_AGENT_HOST,
'host.domain.com'
);
assert.strictEqual(
env.ECS_CONTAINER_METADATA_URI_V4,
'https://ecs.uri/v4'
);
assert.strictEqual(env.ECS_CONTAINER_METADATA_URI, 'https://ecs.uri/');
assert.strictEqual(env.NAMESPACE, 'namespace');
assert.strictEqual(env.HOSTNAME, 'hostname');
assert.strictEqual(env.CONTAINER_NAME, 'container-1');
assert.strictEqual(env.KUBERNETES_SERVICE_HOST, 'https://k8s.host/');
assert.strictEqual(env.OTEL_RESOURCE_ATTRIBUTES, '<attrs>');
assert.strictEqual(env.OTEL_BSP_MAX_BATCH_SIZE, 40);
assert.strictEqual(env.OTEL_BSP_SCHEDULE_DELAY_MILLIS, 50);
});
2 changes: 1 addition & 1 deletion packages/opentelemetry-exporter-jaeger/README.md
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ npm install --save @opentelemetry/exporter-jaeger
Install the exporter on your application and pass the options, it must contain a service name.

Furthermore, the `host` option (which defaults to `localhost`), can instead be set by the
`JAEGER_AGENT_HOST` environment variable to reduce in-code config. If both are
`OTEL_EXPORTER_JAEGER_AGENT_HOST` environment variable to reduce in-code config. If both are
set, the value set by the option in code is authoritative.

```js
23 changes: 14 additions & 9 deletions packages/opentelemetry-exporter-jaeger/src/jaeger.ts
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@
*/

import * as api from '@opentelemetry/api';
import { ExportResult, ExportResultCode } from '@opentelemetry/core';
import { ExportResult, ExportResultCode, getEnv } from '@opentelemetry/core';
import { ReadableSpan, SpanExporter } from '@opentelemetry/tracing';
import { Socket } from 'dgram';
import { spanToThrift } from './transform';
@@ -43,14 +43,19 @@ export class JaegerExporter implements SpanExporter {
: 2000;

// https://github.com/jaegertracing/jaeger-client-node#environment-variables
// By default, the client sends traces via UDP to the agent at localhost:6832. Use JAEGER_AGENT_HOST and
// JAEGER_AGENT_PORT to send UDP traces to a different host:port. If JAEGER_ENDPOINT is set, the client sends traces
// to the endpoint via HTTP, making the JAEGER_AGENT_HOST and JAEGER_AGENT_PORT unused. If JAEGER_ENDPOINT is secured,
// HTTP basic authentication can be performed by setting the JAEGER_USER and JAEGER_PASSWORD environment variables.
localConfig.endpoint = localConfig.endpoint || process.env.JAEGER_ENDPOINT;
localConfig.username = localConfig.username || process.env.JAEGER_USER;
localConfig.password = localConfig.password || process.env.JAEGER_PASSWORD;
localConfig.host = localConfig.host || process.env.JAEGER_AGENT_HOST;
// By default, the client sends traces via UDP to the agent at localhost:6832. Use OTEL_EXPORTER_JAEGER_AGENT_HOST and
// JAEGER_AGENT_PORT to send UDP traces to a different host:port. If OTEL_EXPORTER_JAEGER_ENDPOINT is set, the client sends traces
// to the endpoint via HTTP, making the OTEL_EXPORTER_JAEGER_AGENT_HOST and JAEGER_AGENT_PORT unused. If OTEL_EXPORTER_JAEGER_ENDPOINT is secured,
// HTTP basic authentication can be performed by setting the OTEL_EXPORTER_JAEGER_USER and OTEL_EXPORTER_JAEGER_PASSWORD environment variables.

const env = getEnv();
localConfig.endpoint =
localConfig.endpoint || env.OTEL_EXPORTER_JAEGER_ENDPOINT;
localConfig.username =
localConfig.username || env.OTEL_EXPORTER_JAEGER_USER;
localConfig.password =
localConfig.password || env.OTEL_EXPORTER_JAEGER_PASSWORD;
localConfig.host = localConfig.host || env.OTEL_EXPORTER_JAEGER_AGENT_HOST;
if (localConfig.endpoint) {
this._sender = new jaegerTypes.HTTPSender(localConfig);
} else {
Loading

0 comments on commit c89ce15

Please sign in to comment.