From 2b185dc27abc7c02d4be545253bd331ad4a90070 Mon Sep 17 00:00:00 2001 From: Marc Pichler Date: Tue, 10 Sep 2024 17:25:54 +0200 Subject: [PATCH] test(otlp-exporter-base): test config functions --- .../otlp-http-env-configuration.ts | 3 +- .../src/configuration/shared-configuration.ts | 43 +--- .../configuration/shared-env-configuration.ts | 39 +++- .../otlp-http-configuration.test.ts | 109 +++++++++ .../shared-configuration.test.ts | 136 ++++++++++++ .../otlp-http-env-configuration.test.ts | 206 ++++++++++++++++++ .../shared-env-configuration.test.ts | 155 +++++++++++++ 7 files changed, 647 insertions(+), 44 deletions(-) create mode 100644 experimental/packages/otlp-exporter-base/test/common/configuration/otlp-http-configuration.test.ts create mode 100644 experimental/packages/otlp-exporter-base/test/common/configuration/shared-configuration.test.ts create mode 100644 experimental/packages/otlp-exporter-base/test/node/configuration/otlp-http-env-configuration.test.ts create mode 100644 experimental/packages/otlp-exporter-base/test/node/configuration/shared-env-configuration.test.ts diff --git a/experimental/packages/otlp-exporter-base/src/configuration/otlp-http-env-configuration.ts b/experimental/packages/otlp-exporter-base/src/configuration/otlp-http-env-configuration.ts index ba4bd6c5951..5b75c9df0fd 100644 --- a/experimental/packages/otlp-exporter-base/src/configuration/otlp-http-env-configuration.ts +++ b/experimental/packages/otlp-exporter-base/src/configuration/otlp-http-env-configuration.ts @@ -26,7 +26,8 @@ function getHeadersFromEnv(signalIdentifier: string) { return undefined; } - // headers are combined instead, with the non-specific headers taking precedence over the more specific ones. + // headers are combined instead of overwritten, with the non-specific headers taking precedence over + // the more specific ones. return Object.assign( {}, baggageUtils.parseKeyPairsIntoRecord(envNonSignalSpecificHeaders), diff --git a/experimental/packages/otlp-exporter-base/src/configuration/shared-configuration.ts b/experimental/packages/otlp-exporter-base/src/configuration/shared-configuration.ts index c85fe998131..17244b833c5 100644 --- a/experimental/packages/otlp-exporter-base/src/configuration/shared-configuration.ts +++ b/experimental/packages/otlp-exporter-base/src/configuration/shared-configuration.ts @@ -14,39 +14,20 @@ * limitations under the License. */ -import { diag } from '@opentelemetry/api'; - /** * Configuration shared across all OTLP exporters + * + * Implementation note: anything added here MUST be + * - platform-agnostic + * - signal-agnostic + * - transport-agnostic */ export interface OtlpSharedConfiguration { - // Implementation note: anything added here MUST be - // - platform-agnostic - // - signal-agnostic - // - transport-agnostic timeoutMillis: number; concurrencyLimit: number; compression: 'gzip' | 'none'; } -export function parseTimeout(timeoutEnvVar: string): number | undefined { - const envTimeout = process.env[timeoutEnvVar]; - if (envTimeout != null && envTimeout !== '') { - const definedTimeout = Number(envTimeout); - if ( - !Number.isNaN(definedTimeout) && - Number.isFinite(definedTimeout) && - definedTimeout > 0 - ) { - return definedTimeout; - } - diag.warn( - `Configuration: ${timeoutEnvVar} is invalid, expected number greater than 0 (actual: ${envTimeout})` - ); - } - return undefined; -} - export function validateTimeoutMillis(timeoutMillis: number) { if ( !Number.isNaN(timeoutMillis) && @@ -60,20 +41,6 @@ export function validateTimeoutMillis(timeoutMillis: number) { ); } -export function parseCompression( - compressionEnvVar: string -): 'none' | 'gzip' | undefined { - const compression = process.env[compressionEnvVar]; - - if (compression == null || compression === 'none' || compression === 'gzip') { - return compression; - } - diag.warn( - `Configuration: ${compressionEnvVar} is invalid, expected 'none' or 'gzip' (actual: '${compression}')` - ); - return undefined; -} - /** * @param userProvidedConfiguration Configuration options provided by the user in code. * @param fallbackConfiguration Fallback to use when the {@link userProvidedConfiguration} does not specify an option. diff --git a/experimental/packages/otlp-exporter-base/src/configuration/shared-env-configuration.ts b/experimental/packages/otlp-exporter-base/src/configuration/shared-env-configuration.ts index 07cbd17c5d3..263044ff549 100644 --- a/experimental/packages/otlp-exporter-base/src/configuration/shared-env-configuration.ts +++ b/experimental/packages/otlp-exporter-base/src/configuration/shared-env-configuration.ts @@ -13,11 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { - OtlpSharedConfiguration, - parseCompression, - parseTimeout, -} from './shared-configuration'; +import { OtlpSharedConfiguration } from './shared-configuration'; +import { diag } from '@opentelemetry/api'; + +function parseTimeout(timeoutEnvVar: string): number | undefined { + const envTimeout = process.env[timeoutEnvVar]; + if (envTimeout != null && envTimeout !== '') { + const definedTimeout = Number(envTimeout); + if ( + !Number.isNaN(definedTimeout) && + Number.isFinite(definedTimeout) && + definedTimeout > 0 + ) { + return definedTimeout; + } + diag.warn( + `Configuration: ${timeoutEnvVar} is invalid, expected number greater than 0 (actual: ${envTimeout})` + ); + } + return undefined; +} function determineTimeout(signalIdentifier: string) { const specificTimeout = parseTimeout( @@ -28,6 +43,20 @@ function determineTimeout(signalIdentifier: string) { return specificTimeout ?? nonSpecificTimeout; } +function parseCompression( + compressionEnvVar: string +): 'none' | 'gzip' | undefined { + const compression = process.env[compressionEnvVar]; + + if (compression == null || compression === 'none' || compression === 'gzip') { + return compression; + } + diag.warn( + `Configuration: ${compressionEnvVar} is invalid, expected 'none' or 'gzip' (actual: '${compression}')` + ); + return undefined; +} + function determineCompression( signalIdentifier: string ): 'none' | 'gzip' | undefined { diff --git a/experimental/packages/otlp-exporter-base/test/common/configuration/otlp-http-configuration.test.ts b/experimental/packages/otlp-exporter-base/test/common/configuration/otlp-http-configuration.test.ts new file mode 100644 index 00000000000..1d74ecf8293 --- /dev/null +++ b/experimental/packages/otlp-exporter-base/test/common/configuration/otlp-http-configuration.test.ts @@ -0,0 +1,109 @@ +/* + * 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 { + mergeOtlpHttpConfigurationWithDefaults, + OtlpHttpConfiguration, +} from '../../../src/configuration/otlp-http-configuration'; +import * as assert from 'assert'; +import { testSharedConfigBehavior } from './shared-configuration.test'; + +describe('mergeOtlpHttpConfigurationWithDefaults', function () { + const testDefaults: OtlpHttpConfiguration = { + url: 'default-url', + timeoutMillis: 1, + compression: 'none', + concurrencyLimit: 2, + headers: { 'User-Agent': 'default-user-agent' }, + }; + + describe('headers', function () { + it('merges headers instead of overriding', function () { + const config = mergeOtlpHttpConfigurationWithDefaults( + { + headers: { foo: 'user' }, + }, + { + headers: { foo: 'fallback', bar: 'fallback' }, + }, + testDefaults + ); + assert.deepEqual(config.headers, { + 'User-Agent': 'default-user-agent', + foo: 'user', + bar: 'fallback', + }); + }); + it('does not override default (required) header', function () { + const config = mergeOtlpHttpConfigurationWithDefaults( + { + headers: { 'User-Agent': 'custom' }, + }, + { + headers: { 'User-Agent': 'custom-fallback' }, + }, + { + url: 'default-url', + timeoutMillis: 1, + compression: 'none', + concurrencyLimit: 2, + headers: { 'User-Agent': 'default-user-agent' }, + } + ); + assert.deepEqual(config.headers, { + 'User-Agent': 'default-user-agent', + }); + }); + }); + + describe('url', function () { + it('uses user provided url over fallback', () => { + const config = mergeOtlpHttpConfigurationWithDefaults( + { + url: 'https://example.com/user-provided', + }, + { + url: 'https://example.com/fallback', + }, + testDefaults + ); + assert.deepEqual(config.url, 'https://example.com/user-provided'); + }); + it('uses fallback url over default', () => { + const config = mergeOtlpHttpConfigurationWithDefaults( + {}, + { + url: 'https://example.com/fallback', + }, + testDefaults + ); + assert.deepEqual(config.url, 'https://example.com/fallback'); + }); + it('uses default if none other are specified', () => { + const config = mergeOtlpHttpConfigurationWithDefaults( + {}, + {}, + testDefaults + ); + assert.deepEqual(config.url, testDefaults.url); + }); + }); + + testSharedConfigBehavior( + mergeOtlpHttpConfigurationWithDefaults, + testDefaults + ); +}); diff --git a/experimental/packages/otlp-exporter-base/test/common/configuration/shared-configuration.test.ts b/experimental/packages/otlp-exporter-base/test/common/configuration/shared-configuration.test.ts new file mode 100644 index 00000000000..413ec5e5e6a --- /dev/null +++ b/experimental/packages/otlp-exporter-base/test/common/configuration/shared-configuration.test.ts @@ -0,0 +1,136 @@ +/* + * 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 * as assert from 'assert'; +import { + mergeOtlpSharedConfigurationWithDefaults, + OtlpSharedConfiguration, +} from '../../../src'; + +export function testSharedConfigBehavior( + sut: ( + userProvidedConfiguration: Partial, + fallbackConfiguration: Partial, + defaultConfiguration: T + ) => OtlpSharedConfiguration, + defaults: T +): void { + // copy so that we don't modify the original and pollute other tests. + const testDefaults = Object.assign({}, defaults); + + testDefaults.timeoutMillis = 1; + testDefaults.compression = 'none'; + testDefaults.concurrencyLimit = 2; + + describe('timeout', function () { + it('uses user provided timeout over fallback', () => { + const config = sut( + { + timeoutMillis: 222, + }, + { + timeoutMillis: 333, + }, + testDefaults + ); + assert.deepEqual(config.timeoutMillis, 222); + }); + it('uses fallback timeout over default', () => { + const config = sut( + {}, + { + timeoutMillis: 444, + }, + testDefaults + ); + assert.deepEqual(config.timeoutMillis, 444); + }); + it('uses default if none other are specified', () => { + const config = sut({}, {}, testDefaults); + assert.deepEqual(config.timeoutMillis, testDefaults.timeoutMillis); + }); + + it('throws when value is negative', function () { + assert.throws(() => sut({ timeoutMillis: -1 }, {}, testDefaults)); + }); + }); + + describe('compression', function () { + it('uses user provided compression over fallback', () => { + const config = sut( + { + compression: 'gzip', + }, + { + compression: 'none', + }, + testDefaults + ); + assert.deepEqual(config.compression, 'gzip'); + }); + it('uses fallback compression over default', () => { + const config = sut( + {}, + { + compression: 'gzip', + }, + testDefaults + ); + assert.deepEqual(config.compression, 'gzip'); + }); + it('uses default if none other are specified', () => { + const config = sut({}, {}, testDefaults); + assert.deepEqual(config.compression, testDefaults.compression); + }); + }); + + describe('concurrency limit', function () { + it('uses user provided limit over fallback', () => { + const config = sut( + { + concurrencyLimit: 20, + }, + { + concurrencyLimit: 40, + }, + testDefaults + ); + assert.deepEqual(config.concurrencyLimit, 20); + }); + it('uses fallback limit over default', () => { + const config = sut( + {}, + { + concurrencyLimit: 50, + }, + testDefaults + ); + assert.deepEqual(config.concurrencyLimit, 50); + }); + it('uses default if none other are specified', () => { + const config = sut({}, {}, testDefaults); + assert.deepEqual(config.concurrencyLimit, testDefaults.concurrencyLimit); + }); + }); +} + +describe('mergeOtlpSharedConfigurationWithDefaults', function () { + testSharedConfigBehavior(mergeOtlpSharedConfigurationWithDefaults, { + timeoutMillis: 1, + compression: 'none', + concurrencyLimit: 2, + }); +}); diff --git a/experimental/packages/otlp-exporter-base/test/node/configuration/otlp-http-env-configuration.test.ts b/experimental/packages/otlp-exporter-base/test/node/configuration/otlp-http-env-configuration.test.ts new file mode 100644 index 00000000000..52bc382b276 --- /dev/null +++ b/experimental/packages/otlp-exporter-base/test/node/configuration/otlp-http-env-configuration.test.ts @@ -0,0 +1,206 @@ +/* + * 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 * as assert from 'assert'; +import * as sinon from 'sinon'; + +import { diag } from '@opentelemetry/api'; + +import { getHttpConfigurationFromEnvironment } from '../../../src/configuration/otlp-http-env-configuration'; +import { testSharedConfigurationFromEnvironment } from './shared-env-configuration.test'; + +describe('getHttpConfigurationFromEnvironment', function () { + describe('headers', function () { + afterEach(function () { + delete process.env.OTEL_EXPORTER_OTLP_HEADERS; + delete process.env.OTEL_EXPORTER_OTLP_METRICS_HEADERS; + }); + + it('unset if env vars are not set', function () { + // ensure both are not set + delete process.env.OTEL_EXPORTER_OTLP_HEADERS; + delete process.env.OTEL_EXPORTER_OTLP_METRICS_HEADERS; + + const config = getHttpConfigurationFromEnvironment( + 'METRICS', + 'v1/metrics' + ); + assert.strictEqual(config.headers, undefined); + }); + + it('merges headers instead of overriding', function () { + process.env.OTEL_EXPORTER_OTLP_HEADERS = 'key1=value1,key2=value2'; + process.env.OTEL_EXPORTER_OTLP_METRICS_HEADERS = 'key1=metrics'; + + const config = getHttpConfigurationFromEnvironment( + 'METRICS', + 'v1/metrics' + ); + assert.deepEqual(config.headers, { + key1: 'metrics', + key2: 'value2', + }); + }); + + it('allows non-specific only headers', function () { + process.env.OTEL_EXPORTER_OTLP_HEADERS = 'key1=value1,key2=value2'; + + const config = getHttpConfigurationFromEnvironment( + 'METRICS', + 'v1/metrics' + ); + assert.deepEqual(config.headers, { + key1: 'value1', + key2: 'value2', + }); + }); + + it('allows specific only headers', function () { + process.env.OTEL_EXPORTER_OTLP_METRICS_HEADERS = + 'key1=value1,key2=value2'; + + const config = getHttpConfigurationFromEnvironment( + 'METRICS', + 'v1/metrics' + ); + assert.deepEqual(config.headers, { + key1: 'value1', + key2: 'value2', + }); + }); + }); + + describe('url', function () { + afterEach(function () { + delete process.env.OTEL_EXPORTER_OTLP_ENDPOINT; + delete process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT; + sinon.restore(); + }); + + it('should use url defined in env that ends with root path and append version and signal path', function () { + process.env.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/'; + const config = getHttpConfigurationFromEnvironment( + 'METRICS', + 'v1/metrics' + ); + assert.strictEqual( + config.url, + `${process.env.OTEL_EXPORTER_OTLP_ENDPOINT}v1/metrics` + ); + }); + it('should use url defined in env without checking if path is already present', function () { + process.env.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/v1/metrics'; + const config = getHttpConfigurationFromEnvironment( + 'METRICS', + 'v1/metrics' + ); + assert.strictEqual( + config.url, + `${process.env.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/metrics` + ); + }); + it('should use url defined in env and append version and signal', function () { + process.env.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; + const config = getHttpConfigurationFromEnvironment( + 'METRICS', + 'v1/metrics' + ); + assert.strictEqual( + config.url, + `${process.env.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/metrics` + ); + }); + it('should override global exporter url with signal url defined in env', function () { + process.env.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/'; + process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.metrics/'; + const config = getHttpConfigurationFromEnvironment( + 'METRICS', + 'v1/metrics' + ); + assert.strictEqual( + config.url, + process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT + ); + }); + it('should add root path when signal url defined in env contains no path and no root path', function () { + process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.bar'; + const config = getHttpConfigurationFromEnvironment( + 'METRICS', + 'v1/metrics' + ); + assert.strictEqual( + config.url, + `${process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT}/` + ); + }); + it('should not add root path when signal url defined in env contains root path but no path', function () { + process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.bar/'; + const config = getHttpConfigurationFromEnvironment( + 'METRICS', + 'v1/metrics' + ); + assert.strictEqual( + config.url, + `${process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT}` + ); + }); + it('should not add root path when signal url defined in env contains path', function () { + process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = + 'http://foo.bar/v1/metrics'; + const config = getHttpConfigurationFromEnvironment( + 'METRICS', + 'v1/metrics' + ); + assert.strictEqual( + config.url, + `${process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT}` + ); + }); + it('should not add root path when signal url defined in env contains path and ends in /', function () { + process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = + 'http://foo.bar/v1/metrics/'; + const config = getHttpConfigurationFromEnvironment( + 'METRICS', + 'v1/metrics' + ); + assert.strictEqual( + config.url, + `${process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT}` + ); + }); + + it('should warn on invalid url', function () { + const spyLoggerWarn = sinon.stub(diag, 'warn'); + process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'not a url'; + const config = getHttpConfigurationFromEnvironment( + 'METRICS', + 'v1/metrics' + ); + assert.strictEqual( + config.url, + process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT + ); + assert.strictEqual( + spyLoggerWarn.args[0]?.[0], + "Configuration: Could not parse export URL: 'not a url', falling back to undefined" + ); + }); + }); + + testSharedConfigurationFromEnvironment(signalIdentifier => + getHttpConfigurationFromEnvironment(signalIdentifier, 'v1/metrics') + ); +}); diff --git a/experimental/packages/otlp-exporter-base/test/node/configuration/shared-env-configuration.test.ts b/experimental/packages/otlp-exporter-base/test/node/configuration/shared-env-configuration.test.ts new file mode 100644 index 00000000000..b4347c38571 --- /dev/null +++ b/experimental/packages/otlp-exporter-base/test/node/configuration/shared-env-configuration.test.ts @@ -0,0 +1,155 @@ +/* + * 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 * as assert from 'assert'; +import * as sinon from 'sinon'; +import { diag } from '@opentelemetry/api'; +import * as process from 'process'; +import { + getSharedConfigurationFromEnvironment, + OtlpSharedConfiguration, +} from '../../../src'; + +export function testSharedConfigurationFromEnvironment( + sut: (signalIdentifier: string) => Partial +): void { + describe('timeout', function () { + afterEach(function () { + delete process.env.OTEL_EXPORTER_OTLP_TIMEOUT; + delete process.env.OTEL_EXPORTER_OTLP_METRICS_TIMEOUT; + sinon.restore(); + }); + + it('should not define timeoutMillis if no env var is set', function () { + const config = sut('METRICS'); + assert.strictEqual(config.timeoutMillis, undefined); + }); + + it('should use specific timeout value', function () { + process.env.OTEL_EXPORTER_OTLP_METRICS_TIMEOUT = '15000'; + const config = sut('METRICS'); + assert.strictEqual(config.timeoutMillis, 15000); + }); + + it('should not define timeoutMillis when specific timeout value is negative', function () { + process.env.OTEL_EXPORTER_OTLP_METRICS_TIMEOUT = '-15000'; + const config = sut('METRICS'); + assert.strictEqual(config.timeoutMillis, undefined); + }); + + it('should not define timeoutMillis when specific and non-specific timeout values are negative', function () { + const spyLoggerWarn = sinon.stub(diag, 'warn'); + process.env.OTEL_EXPORTER_OTLP_METRICS_TIMEOUT = '-11000'; + process.env.OTEL_EXPORTER_OTLP_TIMEOUT = '-9000'; + const config = sut('METRICS'); + assert.strictEqual( + spyLoggerWarn.args[0]?.[0], + 'Configuration: OTEL_EXPORTER_OTLP_METRICS_TIMEOUT is invalid, expected number greater than 0 (actual: -11000)' + ); + assert.strictEqual( + spyLoggerWarn.args[1]?.[0], + 'Configuration: OTEL_EXPORTER_OTLP_TIMEOUT is invalid, expected number greater than 0 (actual: -9000)' + ); + + assert.strictEqual(config.timeoutMillis, undefined); + }); + + it('should not define timeoutMillis when specific and non-specific timeout values are NaN', function () { + const spyLoggerWarn = sinon.stub(diag, 'warn'); + process.env.OTEL_EXPORTER_OTLP_METRICS_TIMEOUT = 'NaN'; + process.env.OTEL_EXPORTER_OTLP_TIMEOUT = 'foo'; + const config = sut('METRICS'); + assert.strictEqual( + spyLoggerWarn.args[0]?.[0], + 'Configuration: OTEL_EXPORTER_OTLP_METRICS_TIMEOUT is invalid, expected number greater than 0 (actual: NaN)' + ); + assert.strictEqual( + spyLoggerWarn.args[1]?.[0], + 'Configuration: OTEL_EXPORTER_OTLP_TIMEOUT is invalid, expected number greater than 0 (actual: foo)' + ); + + assert.strictEqual(config.timeoutMillis, undefined); + }); + it('should not define timeoutMillis when specific and non-specific timeout values are infinite', function () { + const spyLoggerWarn = sinon.stub(diag, 'warn'); + process.env.OTEL_EXPORTER_OTLP_METRICS_TIMEOUT = '-Infinitiy'; + process.env.OTEL_EXPORTER_OTLP_TIMEOUT = 'Infinity'; + const config = sut('METRICS'); + assert.strictEqual( + spyLoggerWarn.args[0]?.[0], + 'Configuration: OTEL_EXPORTER_OTLP_METRICS_TIMEOUT is invalid, expected number greater than 0 (actual: -Infinitiy)' + ); + assert.strictEqual( + spyLoggerWarn.args[1]?.[0], + 'Configuration: OTEL_EXPORTER_OTLP_TIMEOUT is invalid, expected number greater than 0 (actual: Infinity)' + ); + + assert.strictEqual(config.timeoutMillis, undefined); + }); + }); + + describe('compression', function () { + afterEach(function () { + delete process.env.OTEL_EXPORTER_OTLP_COMPRESSION; + delete process.env.OTEL_EXPORTER_OTLP_METRICS_COMPRESSION; + sinon.restore(); + }); + + it('should not define compression if no env var is set', function () { + const config = sut('METRICS'); + assert.strictEqual(config.compression, undefined); + }); + it('should use specific compression value', function () { + process.env.OTEL_EXPORTER_OTLP_METRICS_COMPRESSION = 'gzip'; + const config = sut('METRICS'); + assert.strictEqual(config.compression, 'gzip'); + }); + + it('should not define when specific compression value is invalid', function () { + const spyLoggerWarn = sinon.stub(diag, 'warn'); + process.env.OTEL_EXPORTER_OTLP_METRICS_COMPRESSION = 'bla'; + const config = sut('METRICS'); + assert.strictEqual( + spyLoggerWarn.args[0]?.[0], + "Configuration: OTEL_EXPORTER_OTLP_METRICS_COMPRESSION is invalid, expected 'none' or 'gzip' (actual: 'bla')" + ); + assert.strictEqual(config.compression, undefined); + }); + + it('should not define when non-specific compression value is invalid', function () { + const spyLoggerWarn = sinon.stub(diag, 'warn'); + process.env.OTEL_EXPORTER_OTLP_COMPRESSION = 'bla'; + const config = sut('METRICS'); + assert.strictEqual( + spyLoggerWarn.args[0]?.[0], + "Configuration: OTEL_EXPORTER_OTLP_COMPRESSION is invalid, expected 'none' or 'gzip' (actual: 'bla')" + ); + assert.strictEqual(config.compression, undefined); + }); + + it('should use signal specific over non-specific', function () { + process.env.OTEL_EXPORTER_OTLP_COMPRESSION = 'none'; + process.env.OTEL_EXPORTER_OTLP_METRICS_COMPRESSION = 'gzip'; + + const config = sut('METRICS'); + assert.strictEqual(config.compression, 'gzip'); + }); + }); +} + +describe('getSharedConfigurationFromEnvironment', function () { + testSharedConfigurationFromEnvironment(getSharedConfigurationFromEnvironment); +});