Skip to content

Commit

Permalink
feat: migrate sdk-node away from getEnv(), introduce diagLogLevelFrom…
Browse files Browse the repository at this point in the history
…String() util (#5475)

Co-authored-by: Trent Mick <[email protected]>
  • Loading branch information
pichlermarc and trentm authored Feb 17, 2025
1 parent c27fbc6 commit 5b988c8
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ For semantic convention package changes, see the [semconv CHANGELOG](packages/se
* 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
* refactor(exporter-jaeger): migrate away from getEnv() [#5464](https://github.com/open-telemetry/opentelemetry-js/pull/5464) @pichlermarc
* feat(core): add `diagLogLevelFromString` utility [#5475](https://github.com/open-telemetry/opentelemetry-js/pull/5475) @pichlermarc

### :bug: (Bug Fix)

Expand Down
1 change: 1 addition & 0 deletions experimental/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ All notable changes to experimental packages in this project will be documented
* refactor(exporter-prometheus): remove unnecessary isNaN() check [#5377](https://github.com/open-telemetry/opentelemetry-js/pull/5377) @cjihrig
* refactor(sdk-node): move code to auto-instantiate propagators into utils [#5355](https://github.com/open-telemetry/opentelemetry-js/pull/5355) @pichlermarc
* chore: unpin `@opentelemetry/semantic-conventions` dep to allow better de-duplication in installs [#5439](https://github.com/open-telemetry/opentelemetry-js/pull/5439) @trentm
* refactor(sdk-node): migrate away from getEnv() [#5475](https://github.com/open-telemetry/opentelemetry-js/pull/5475) @pichlermarc

## 0.57.0

Expand Down
18 changes: 9 additions & 9 deletions experimental/packages/opentelemetry-sdk-node/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ import {
} from '@opentelemetry/sdk-trace-node';
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
import { NodeSDKConfiguration } from './types';
import { getEnv, getEnvWithoutDefaults } from '@opentelemetry/core';
import {
getBooleanFromEnv,
getStringFromEnv,
diagLogLevelFromString,
} from '@opentelemetry/core';
import {
getResourceDetectorsFromEnv,
getSpanProcessorsFromEnv,
Expand Down Expand Up @@ -226,20 +230,16 @@ export class NodeSDK {
* Create a new NodeJS SDK instance
*/
public constructor(configuration: Partial<NodeSDKConfiguration> = {}) {
const env = getEnv();
const envWithoutDefaults = getEnvWithoutDefaults();

if (env.OTEL_SDK_DISABLED) {
if (getBooleanFromEnv('OTEL_SDK_DISABLED')) {
this._disabled = true;
// Functions with possible side-effects are set
// to no-op via the _disabled flag
}

// Default is INFO, use environment without defaults to check
// if the user originally set the environment variable.
if (envWithoutDefaults.OTEL_LOG_LEVEL) {
const logLevel = getStringFromEnv('OTEL_LOG_LEVEL');
if (logLevel != null) {
diag.setLogger(new DiagConsoleLogger(), {
logLevel: envWithoutDefaults.OTEL_LOG_LEVEL,
logLevel: diagLogLevelFromString(logLevel),
});
}

Expand Down
23 changes: 9 additions & 14 deletions experimental/packages/opentelemetry-sdk-node/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
import { diag, TextMapPropagator } from '@opentelemetry/api';
import {
CompositePropagator,
getEnv,
getEnvWithoutDefaults,
getStringFromEnv,
getStringListFromEnv,
W3CTraceContextPropagator,
} from '@opentelemetry/core';
import { OTLPTraceExporter as OTLPProtoTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
Expand Down Expand Up @@ -86,13 +86,10 @@ export function filterBlanksAndNulls(list: string[]): string[] {
}

export function getOtlpProtocolFromEnv(): string {
const parsedEnvValues = getEnvWithoutDefaults();

return (
parsedEnvValues.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL ??
parsedEnvValues.OTEL_EXPORTER_OTLP_PROTOCOL ??
getEnv().OTEL_EXPORTER_OTLP_TRACES_PROTOCOL ??
getEnv().OTEL_EXPORTER_OTLP_PROTOCOL
getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_PROTOCOL') ??
getStringFromEnv('OTEL_EXPORTER_OTLP_PROTOCOL') ??
'http/protobuf'
);
}

Expand Down Expand Up @@ -139,7 +136,7 @@ export function getSpanProcessorsFromEnv(): SpanProcessor[] {
const exporters: SpanExporter[] = [];
const processors: SpanProcessor[] = [];
let traceExportersList = filterBlanksAndNulls(
Array.from(new Set(getEnv().OTEL_TRACES_EXPORTER.split(',')))
Array.from(new Set(getStringListFromEnv('OTEL_TRACES_EXPORTER')))
);

if (traceExportersList[0] === 'none') {
Expand Down Expand Up @@ -193,10 +190,8 @@ export function getSpanProcessorsFromEnv(): SpanProcessor[] {
*/
export function getPropagatorFromEnv(): TextMapPropagator | null | undefined {
// Empty and undefined MUST be treated equal.
if (
process.env.OTEL_PROPAGATORS === undefined ||
process.env.OTEL_PROPAGATORS?.trim() === ''
) {
const propagatorsEnvVarValue = getStringListFromEnv('OTEL_PROPAGATORS');
if (propagatorsEnvVarValue == null) {
// return undefined to fall back to default
return undefined;
}
Expand All @@ -215,7 +210,7 @@ export function getPropagatorFromEnv(): TextMapPropagator | null | undefined {
]);

// Values MUST be deduplicated in order to register a Propagator only once.
const uniquePropagatorNames = Array.from(new Set(getEnv().OTEL_PROPAGATORS));
const uniquePropagatorNames = Array.from(new Set(propagatorsEnvVarValue));

const propagators = uniquePropagatorNames.map(name => {
const propagator = propagatorsFactory.get(name)?.();
Expand Down
1 change: 1 addition & 0 deletions packages/opentelemetry-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export { merge } from './utils/merge';
export { TimeoutError, callWithTimeout } from './utils/timeout';
export { isUrlIgnored, urlMatches } from './utils/url';
export { BindOnceFuture } from './utils/callback';
export { diagLogLevelFromString } from './utils/configuration';
import { _export } from './internal/exporter';
export const internal = {
_export,
Expand Down
51 changes: 51 additions & 0 deletions packages/opentelemetry-core/src/utils/configuration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* 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 { diag, DiagLogLevel } from '@opentelemetry/api';
import { inspect } from 'util';

const logLevelMap: { [key: string]: DiagLogLevel } = {
ALL: DiagLogLevel.ALL,
VERBOSE: DiagLogLevel.VERBOSE,
DEBUG: DiagLogLevel.DEBUG,
INFO: DiagLogLevel.INFO,
WARN: DiagLogLevel.WARN,
ERROR: DiagLogLevel.ERROR,
NONE: DiagLogLevel.NONE,
};

/**
* Convert a string to a {@link DiagLogLevel}, defaults to {@link DiagLogLevel} if the log level does not exist or undefined if the input is undefined.
* @param value
*/
export function diagLogLevelFromString(
value: string | undefined
): DiagLogLevel | undefined {
if (value == null) {
// don't fall back to default - no value set has different semantics for ús than an incorrect value (do not set vs. fall back to default)
return undefined;
}

const resolvedLogLevel = logLevelMap[value.toUpperCase()];

if (resolvedLogLevel == null) {
diag.warn(
`Unknown log level ${inspect(value)}, expected one of ${inspect(Object.keys(logLevelMap))}, using default`
);
return DiagLogLevel.INFO;
}

return resolvedLogLevel;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* 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 { diagLogLevelFromString } from '../../../src';
import * as assert from 'assert';
import * as sinon from 'sinon';
import { diag, DiagLogLevel } from '@opentelemetry/api';

describe('stringToLogLevel', function () {
afterEach(function () {
sinon.restore();
});

it('should map valid string to log level', function () {
assert.strictEqual(diagLogLevelFromString('ALL'), DiagLogLevel.ALL);
assert.strictEqual(diagLogLevelFromString('VERBOSE'), DiagLogLevel.VERBOSE);
assert.strictEqual(diagLogLevelFromString('DEBUG'), DiagLogLevel.DEBUG);
assert.strictEqual(diagLogLevelFromString('INFO'), DiagLogLevel.INFO);
assert.strictEqual(diagLogLevelFromString('WARN'), DiagLogLevel.WARN);
assert.strictEqual(diagLogLevelFromString('ERROR'), DiagLogLevel.ERROR);
assert.strictEqual(diagLogLevelFromString('NONE'), DiagLogLevel.NONE);
});

it('should ignore casing when resolving', function () {
assert.strictEqual(diagLogLevelFromString('error'), DiagLogLevel.ERROR);
assert.strictEqual(diagLogLevelFromString('eRRoR'), DiagLogLevel.ERROR);
});

it('should return undefined on undefined input', function () {
assert.strictEqual(diagLogLevelFromString(undefined), undefined);
});

it('should fall back to INFO and warn on input that cannot be mapped', function () {
const warnStub = sinon.stub(diag, 'warn');
assert.strictEqual(
diagLogLevelFromString('does not exist'),
DiagLogLevel.INFO
);
sinon.assert.calledOnceWithMatch(warnStub, 'Unknown');
});
});

0 comments on commit 5b988c8

Please sign in to comment.