From 5df60a471bca53402c38e73f1345ea91b4b4d22d Mon Sep 17 00:00:00 2001 From: maryliag Date: Tue, 23 Sep 2025 14:29:14 -0400 Subject: [PATCH 01/27] parse attribute limits --- .../src/FileConfigProvider.ts | 15 +++++++++++++++ .../test/ConfigProvider.test.ts | 1 + 2 files changed, 16 insertions(+) diff --git a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts index 221a1470998..0e6f40e0b74 100644 --- a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts @@ -16,6 +16,7 @@ import { diagLogLevelFromString, getStringFromEnv } from '@opentelemetry/core'; import { + AttributeLimits, ConfigAttributes, ConfigurationModel, initializeDefaultConfiguration, @@ -98,6 +99,7 @@ function parseConfigFile(config: ConfigurationModel) { } setResourceAttributes(config, parsedContent['resource']?.['attributes']); + setAttributeLimits(config, parsedContent['attribute_limits']); } else { throw new Error( `Unsupported File Format: ${parsedContent['file_format']}. It must be one of the following: ${supportedFileVersions}` @@ -145,3 +147,16 @@ function setResourceAttributes( } } } + +function setAttributeLimits(config: ConfigurationModel, attrLimits: AttributeLimits) { + if (attrLimits) { + const lengthLimit = getNumberFromConfigFile(attrLimits['attribute_value_length_limit']); + if (lengthLimit) { + config.attribute_limits.attribute_value_length_limit = lengthLimit; + } + const countLimit = getNumberFromConfigFile(attrLimits['attribute_count_limit']); + if (countLimit) { + config.attribute_limits.attribute_count_limit = countLimit; + } + } +} diff --git a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts index 7b45b604602..0a2ed3b0a9f 100644 --- a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts +++ b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts @@ -164,6 +164,7 @@ const configFromFile: Configuration = { }, attribute_limits: { attribute_count_limit: 128, + attribute_value_length_limit: 4096, }, propagator: { composite: ['tracecontext', 'baggage'], From b2bfada634e0c9823adc90eaa8791ae5aa4710a5 Mon Sep 17 00:00:00 2001 From: maryliag Date: Tue, 23 Sep 2025 16:00:01 -0400 Subject: [PATCH 02/27] set propagators --- .../src/EnvironmentConfigProvider.ts | 14 +++--- .../src/FileConfigProvider.ts | 45 +++++++++++++++++-- .../opentelemetry-configuration/src/utils.ts | 29 +++++++++++- .../test/ConfigProvider.test.ts | 40 ++++++++++++----- 4 files changed, 105 insertions(+), 23 deletions(-) diff --git a/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts index a9ad8afbd4d..b355201d11a 100644 --- a/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts @@ -96,13 +96,13 @@ function setAttributeLimits(config: ConfigurationModel): void { } function setPropagators(config: ConfigurationModel): void { - const propagators = getStringListFromEnv('OTEL_PROPAGATORS'); - if (propagators) { - config.propagator = { - composite: propagators, - composite_list: - getStringFromEnv('OTEL_PROPAGATORS') || 'tracecontext,baggage', - }; + const composite = getStringListFromEnv('OTEL_PROPAGATORS'); + if (composite) { + config.propagator.composite = composite; + } + const compositeList = getStringFromEnv('OTEL_PROPAGATORS'); + if (compositeList) { + config.propagator.composite_list = compositeList; } } diff --git a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts index 0e6f40e0b74..7c3c4ce80b1 100644 --- a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts @@ -27,6 +27,7 @@ import * as yaml from 'yaml'; import { getBooleanFromConfigFile, getBooleanListFromConfigFile, + getListFromObjectsFromConfigFile, getNumberFromConfigFile, getNumberListFromConfigFile, getStringFromConfigFile, @@ -100,6 +101,7 @@ function parseConfigFile(config: ConfigurationModel) { setResourceAttributes(config, parsedContent['resource']?.['attributes']); setAttributeLimits(config, parsedContent['attribute_limits']); + setPropagator(config, parsedContent['propagator']); } else { throw new Error( `Unsupported File Format: ${parsedContent['file_format']}. It must be one of the following: ${supportedFileVersions}` @@ -148,15 +150,52 @@ function setResourceAttributes( } } -function setAttributeLimits(config: ConfigurationModel, attrLimits: AttributeLimits) { +function setAttributeLimits( + config: ConfigurationModel, + attrLimits: AttributeLimits +) { if (attrLimits) { - const lengthLimit = getNumberFromConfigFile(attrLimits['attribute_value_length_limit']); + const lengthLimit = getNumberFromConfigFile( + attrLimits['attribute_value_length_limit'] + ); if (lengthLimit) { config.attribute_limits.attribute_value_length_limit = lengthLimit; } - const countLimit = getNumberFromConfigFile(attrLimits['attribute_count_limit']); + const countLimit = getNumberFromConfigFile( + attrLimits['attribute_count_limit'] + ); if (countLimit) { config.attribute_limits.attribute_count_limit = countLimit; } } } + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function setPropagator(config: ConfigurationModel, propagator: any): void { + if (propagator) { + let composite = getListFromObjectsFromConfigFile(propagator['composite']); + const compositeList = getStringListFromConfigFile( + propagator['composite_list'] + ); + if (composite === undefined) { + composite = []; + } + if (compositeList) { + for (let i = 0; i < compositeList.length; i++) { + if (!composite.includes(compositeList[i])) { + composite.push(compositeList[i]); + } + } + } + + if (composite.length > 0) { + config.propagator.composite = composite; + } + const compositeListString = getStringFromConfigFile( + propagator['composite_list'] + ); + if (compositeListString) { + config.propagator.composite_list = compositeListString; + } + } +} diff --git a/experimental/packages/opentelemetry-configuration/src/utils.ts b/experimental/packages/opentelemetry-configuration/src/utils.ts index e317ba1dc62..87bae6cf605 100644 --- a/experimental/packages/opentelemetry-configuration/src/utils.ts +++ b/experimental/packages/opentelemetry-configuration/src/utils.ts @@ -156,12 +156,39 @@ export function getStringListFromConfigFile( .filter(s => s !== ''); } +/** + * Retrieves a list of strings from a configuration file parameter + * that is a list of objects. + * e.g. Parsing the value of `composite` such as + * composite: + * - tracecontext: + * - baggage: + * - b3: + * returns ['tracecontext', 'baggage', 'b3'] + * @param value - The value from the config file. + * @returns {string[] | undefined} - The list of strings or `undefined`. + */ +export function getListFromObjectsFromConfigFile( + value: object[] +): string[] | undefined { + if (value) { + const list: string[] = []; + for (let i = 0; i < value.length; i++) { + list.push(...Object.keys(value[i])); + } + if (list.length > 0) { + return list; + } + } + return undefined; +} + export function envVariableSubstitution(value: unknown): string | undefined { if (value == null) { return undefined; } - const matches = String(value).match(/\$\{[a-zA-Z0-9_:.-]*\}/g); + const matches = String(value).match(/\$\{[a-zA-Z0-9,=_:.-]*\}/g); if (matches) { let stringValue = String(value); for (const match of matches) { diff --git a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts index 506bca7bd30..0970442187f 100644 --- a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts +++ b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts @@ -167,8 +167,16 @@ const configFromFile: Configuration = { attribute_value_length_limit: 4096, }, propagator: { - composite: ['tracecontext', 'baggage'], - composite_list: 'tracecontext,baggage', + composite: [ + 'tracecontext', + 'baggage', + 'b3', + 'b3multi', + 'jaeger', + 'ottrace', + 'xray', + ], + composite_list: 'tracecontext,baggage,b3,b3multi,jaeger,ottrace,xray', }, tracer_provider: { processors: [ @@ -862,7 +870,7 @@ describe('ConfigProvider', function () { process.env.OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT = '29'; const configProvider = createConfigProvider(); const expectedConfig: Configuration = { - ...defaultConfig, + ...defaultConfigFromFileWithEnvVariables, resource: { attributes_list: 'attributes', attributes: [ @@ -873,6 +881,14 @@ describe('ConfigProvider', function () { }, ], }, + attribute_limits: { + attribute_count_limit: 7, + attribute_value_length_limit: 23, + }, + propagator: { + composite: ['prop'], + composite_list: 'prop', + }, }; assert.deepStrictEqual( @@ -881,15 +897,15 @@ describe('ConfigProvider', function () { ); }); - it('should initialize config with fallbacks defined in config file when corresponding environment variables are not defined', function () { - process.env.OTEL_EXPERIMENTAL_CONFIG_FILE = - 'test/fixtures/sdk-migration-config.yaml'; + // it('should initialize config with fallbacks defined in config file when corresponding environment variables are not defined', function () { + // process.env.OTEL_EXPERIMENTAL_CONFIG_FILE = + // 'test/fixtures/sdk-migration-config.yaml'; - const configProvider = createConfigProvider(); - assert.deepStrictEqual( - configProvider.getInstrumentationConfig(), - defaultConfigFromFileWithEnvVariables - ); - }); + // const configProvider = createConfigProvider(); + // assert.deepStrictEqual( + // configProvider.getInstrumentationConfig(), + // defaultConfigFromFileWithEnvVariables + // ); + // }); }); }); From 8f6096449662d2b6a331485f01558857c56ee7f7 Mon Sep 17 00:00:00 2001 From: maryliag Date: Tue, 23 Sep 2025 17:06:03 -0400 Subject: [PATCH 03/27] parse limit of tracer provider --- .../src/FileConfigProvider.ts | 59 +++++++++++++++++++ .../test/ConfigProvider.test.ts | 31 +++++++--- 2 files changed, 81 insertions(+), 9 deletions(-) diff --git a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts index 7c3c4ce80b1..86b147ed9ab 100644 --- a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts @@ -18,6 +18,7 @@ import { diagLogLevelFromString, getStringFromEnv } from '@opentelemetry/core'; import { AttributeLimits, ConfigAttributes, + ConfigTracerProvider, ConfigurationModel, initializeDefaultConfiguration, } from './configModel'; @@ -102,6 +103,7 @@ function parseConfigFile(config: ConfigurationModel) { setResourceAttributes(config, parsedContent['resource']?.['attributes']); setAttributeLimits(config, parsedContent['attribute_limits']); setPropagator(config, parsedContent['propagator']); + setTracerProvider(config, parsedContent['tracer_provider']); } else { throw new Error( `Unsupported File Format: ${parsedContent['file_format']}. It must be one of the following: ${supportedFileVersions}` @@ -199,3 +201,60 @@ function setPropagator(config: ConfigurationModel, propagator: any): void { } } } + +function setTracerProvider( + config: ConfigurationModel, + tracerProvider: ConfigTracerProvider +): void { + if (tracerProvider) { + // Limits + if (tracerProvider['limits']) { + const attributeValueLengthLimit = getNumberFromConfigFile( + tracerProvider['limits']['attribute_value_length_limit'] + ); + + if (attributeValueLengthLimit) { + config.tracer_provider.limits.attribute_value_length_limit = + attributeValueLengthLimit; + } + + const attributeCountLimit = getNumberFromConfigFile( + tracerProvider['limits']['attribute_count_limit'] + ); + if (attributeCountLimit) { + config.tracer_provider.limits.attribute_count_limit = + attributeCountLimit; + } + + const eventCountLimit = getNumberFromConfigFile( + tracerProvider['limits']['event_count_limit'] + ); + if (eventCountLimit) { + config.tracer_provider.limits.event_count_limit = eventCountLimit; + } + + const linkCountLimit = getNumberFromConfigFile( + tracerProvider['limits']['link_count_limit'] + ); + if (linkCountLimit) { + config.tracer_provider.limits.link_count_limit = linkCountLimit; + } + + const eventAttributeCountLimit = getNumberFromConfigFile( + tracerProvider['limits']['event_attribute_count_limit'] + ); + if (eventAttributeCountLimit) { + config.tracer_provider.limits.event_attribute_count_limit = + eventAttributeCountLimit; + } + + const linkAttributeCountLimit = getNumberFromConfigFile( + tracerProvider['limits']['link_attribute_count_limit'] + ); + if (linkAttributeCountLimit) { + config.tracer_provider.limits.link_attribute_count_limit = + linkAttributeCountLimit; + } + } + } +} diff --git a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts index 0970442187f..135489f98c8 100644 --- a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts +++ b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts @@ -197,6 +197,7 @@ const configFromFile: Configuration = { ], limits: { attribute_count_limit: 128, + attribute_value_length_limit: 4096, event_count_limit: 128, link_count_limit: 128, event_attribute_count_limit: 128, @@ -889,6 +890,18 @@ describe('ConfigProvider', function () { composite: ['prop'], composite_list: 'prop', }, + tracer_provider: { + ...defaultConfigFromFileWithEnvVariables.tracer_provider, + limits: { + ...defaultConfigFromFileWithEnvVariables.tracer_provider.limits, + attribute_value_length_limit: 14, + attribute_count_limit: 15, + event_count_limit: 16, + link_count_limit: 17, + event_attribute_count_limit: 18, + link_attribute_count_limit: 19, + }, + }, }; assert.deepStrictEqual( @@ -897,15 +910,15 @@ describe('ConfigProvider', function () { ); }); - // it('should initialize config with fallbacks defined in config file when corresponding environment variables are not defined', function () { - // process.env.OTEL_EXPERIMENTAL_CONFIG_FILE = - // 'test/fixtures/sdk-migration-config.yaml'; + it('should initialize config with fallbacks defined in config file when corresponding environment variables are not defined', function () { + process.env.OTEL_EXPERIMENTAL_CONFIG_FILE = + 'test/fixtures/sdk-migration-config.yaml'; - // const configProvider = createConfigProvider(); - // assert.deepStrictEqual( - // configProvider.getInstrumentationConfig(), - // defaultConfigFromFileWithEnvVariables - // ); - // }); + const configProvider = createConfigProvider(); + assert.deepStrictEqual( + configProvider.getInstrumentationConfig(), + defaultConfigFromFileWithEnvVariables + ); + }); }); }); From 6933b03c2740fbc802a24955845a2d9e0e41c4f4 Mon Sep 17 00:00:00 2001 From: maryliag Date: Tue, 23 Sep 2025 17:17:28 -0400 Subject: [PATCH 04/27] add meter and logger --- .../src/FileConfigProvider.ts | 43 +++++++++++++++++++ .../test/ConfigProvider.test.ts | 15 ++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts index 86b147ed9ab..bceaa52c26d 100644 --- a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts @@ -18,6 +18,8 @@ import { diagLogLevelFromString, getStringFromEnv } from '@opentelemetry/core'; import { AttributeLimits, ConfigAttributes, + ConfigLoggerProvider, + ConfigMeterProvider, ConfigTracerProvider, ConfigurationModel, initializeDefaultConfiguration, @@ -104,6 +106,8 @@ function parseConfigFile(config: ConfigurationModel) { setAttributeLimits(config, parsedContent['attribute_limits']); setPropagator(config, parsedContent['propagator']); setTracerProvider(config, parsedContent['tracer_provider']); + setMeterProvider(config, parsedContent['meter_provider']); + setLoggerProvider(config, parsedContent['logger_provider']); } else { throw new Error( `Unsupported File Format: ${parsedContent['file_format']}. It must be one of the following: ${supportedFileVersions}` @@ -258,3 +262,42 @@ function setTracerProvider( } } } + +function setMeterProvider( + config: ConfigurationModel, + meterProvider: ConfigMeterProvider +): void { + if (meterProvider) { + const exemplarFilter = getStringFromConfigFile(meterProvider['exemplar_filter']); + if ( + exemplarFilter && + (exemplarFilter === 'trace_based' || + exemplarFilter === 'always_on' || + exemplarFilter === 'always_off') + ) { + config.meter_provider.exemplar_filter = exemplarFilter; + } + } +} + +function setLoggerProvider( + config: ConfigurationModel, + loggerProvider: ConfigLoggerProvider +): void { + if (loggerProvider) { + const attributeValueLengthLimit = getNumberFromConfigFile( + loggerProvider['limits']['attribute_value_length_limit'] + ); + if (attributeValueLengthLimit) { + config.logger_provider.limits.attribute_value_length_limit = + attributeValueLengthLimit; + } + + const attributeCountLimit = getNumberFromConfigFile( + loggerProvider['limits']['attribute_count_limit'] + ); + if (attributeCountLimit) { + config.logger_provider.limits.attribute_count_limit = attributeCountLimit; + } + } +} diff --git a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts index 135489f98c8..db0f011ce76 100644 --- a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts +++ b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts @@ -251,6 +251,7 @@ const configFromFile: Configuration = { ], limits: { attribute_count_limit: 128, + attribute_value_length_limit: 4096, }, }, }; @@ -854,7 +855,7 @@ describe('ConfigProvider', function () { 'metric-temporality'; process.env.OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION = 'metric-hist-agg'; - process.env.OTEL_METRICS_EXEMPLAR_FILTER = 'metric-exemplar-filter'; + process.env.OTEL_METRICS_EXEMPLAR_FILTER = 'always_off'; process.env.OTEL_BLRP_SCHEDULE_DELAY = '23'; process.env.OTEL_BLRP_EXPORT_TIMEOUT = '24'; process.env.OTEL_BLRP_MAX_QUEUE_SIZE = '25'; @@ -893,7 +894,6 @@ describe('ConfigProvider', function () { tracer_provider: { ...defaultConfigFromFileWithEnvVariables.tracer_provider, limits: { - ...defaultConfigFromFileWithEnvVariables.tracer_provider.limits, attribute_value_length_limit: 14, attribute_count_limit: 15, event_count_limit: 16, @@ -902,6 +902,17 @@ describe('ConfigProvider', function () { link_attribute_count_limit: 19, }, }, + meter_provider: { + ...defaultConfigFromFileWithEnvVariables.meter_provider, + exemplar_filter: 'always_off', + }, + logger_provider: { + ...defaultConfigFromFileWithEnvVariables.logger_provider, + limits: { + attribute_value_length_limit: 28, + attribute_count_limit: 29, + } + }, }; assert.deepStrictEqual( From 9dec6abacea6c881b572ce66ae663e35206728f8 Mon Sep 17 00:00:00 2001 From: maryliag Date: Tue, 23 Sep 2025 17:19:18 -0400 Subject: [PATCH 05/27] fix lint --- .../src/FileConfigProvider.ts | 22 ++++++++++--------- .../test/ConfigProvider.test.ts | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts index bceaa52c26d..72cca89b163 100644 --- a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts @@ -268,15 +268,17 @@ function setMeterProvider( meterProvider: ConfigMeterProvider ): void { if (meterProvider) { - const exemplarFilter = getStringFromConfigFile(meterProvider['exemplar_filter']); - if ( - exemplarFilter && - (exemplarFilter === 'trace_based' || - exemplarFilter === 'always_on' || - exemplarFilter === 'always_off') - ) { - config.meter_provider.exemplar_filter = exemplarFilter; - } + const exemplarFilter = getStringFromConfigFile( + meterProvider['exemplar_filter'] + ); + if ( + exemplarFilter && + (exemplarFilter === 'trace_based' || + exemplarFilter === 'always_on' || + exemplarFilter === 'always_off') + ) { + config.meter_provider.exemplar_filter = exemplarFilter; + } } } @@ -292,7 +294,7 @@ function setLoggerProvider( config.logger_provider.limits.attribute_value_length_limit = attributeValueLengthLimit; } - + const attributeCountLimit = getNumberFromConfigFile( loggerProvider['limits']['attribute_count_limit'] ); diff --git a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts index db0f011ce76..5d62066b519 100644 --- a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts +++ b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts @@ -911,7 +911,7 @@ describe('ConfigProvider', function () { limits: { attribute_value_length_limit: 28, attribute_count_limit: 29, - } + }, }, }; From 01497abdba5a4cf0f5c116f0b87fd96066e0bfbc Mon Sep 17 00:00:00 2001 From: maryliag Date: Tue, 23 Sep 2025 17:24:46 -0400 Subject: [PATCH 06/27] add changelog --- experimental/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index 1a269baa17f..160e3cd2dbf 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -16,6 +16,7 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2 * feat(opentelemetry-configuration): Parse of Configuration File [#5875](https://github.com/open-telemetry/opentelemetry-js/pull/5875) @maryliag * feat(opentelemetry-configuration): parse of array objects on configuration file [#5947](https://github.com/open-telemetry/opentelemetry-js/pull/5947) @maryliag * feat(opentelemetry-configuration): parse of environment variables on configuration file [#5947](https://github.com/open-telemetry/opentelemetry-js/pull/5947) @maryliag +* feat(opentelemetry-configuration): parse more parameters from config file [#5955](https://github.com/open-telemetry/opentelemetry-js/pull/5955) @maryliag ### :bug: Bug Fixes From aaaed798d9a75f77780e3714148cb0326db5a2b8 Mon Sep 17 00:00:00 2001 From: maryliag Date: Thu, 2 Oct 2025 14:43:38 -0400 Subject: [PATCH 07/27] create check for propagator --- .../src/FileConfigProvider.ts | 10 +++--- .../opentelemetry-configuration/src/utils.ts | 32 ++++++++++++++++++- .../test/utils.test.ts | 17 ++++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts index 72cca89b163..51ec2d432e1 100644 --- a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts @@ -35,6 +35,7 @@ import { getNumberListFromConfigFile, getStringFromConfigFile, getStringListFromConfigFile, + isPropagator, } from './utils'; export class FileConfigProvider implements ConfigProvider { @@ -176,10 +177,11 @@ function setAttributeLimits( } } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function setPropagator(config: ConfigurationModel, propagator: any): void { - if (propagator) { - let composite = getListFromObjectsFromConfigFile(propagator['composite']); +function setPropagator(config: ConfigurationModel, propagator: unknown): void { + if (propagator && isPropagator(propagator)) { + let composite = getListFromObjectsFromConfigFile( + propagator['composite'] as unknown as object[] + ); const compositeList = getStringListFromConfigFile( propagator['composite_list'] ); diff --git a/experimental/packages/opentelemetry-configuration/src/utils.ts b/experimental/packages/opentelemetry-configuration/src/utils.ts index 87bae6cf605..27242cb2ae4 100644 --- a/experimental/packages/opentelemetry-configuration/src/utils.ts +++ b/experimental/packages/opentelemetry-configuration/src/utils.ts @@ -16,6 +16,7 @@ import { diag } from '@opentelemetry/api'; import { getStringFromEnv } from '@opentelemetry/core'; import { inspect } from 'util'; +import { ConfigPropagator } from './configModel'; /** * Retrieves a boolean value from a configuration file parameter. @@ -169,7 +170,7 @@ export function getStringListFromConfigFile( * @returns {string[] | undefined} - The list of strings or `undefined`. */ export function getListFromObjectsFromConfigFile( - value: object[] + value: object[] | undefined ): string[] | undefined { if (value) { const list: string[] = []; @@ -201,3 +202,32 @@ export function envVariableSubstitution(value: unknown): string | undefined { } return String(value); } + +export function isPropagator( + propagator: unknown +): propagator is Partial { + if (propagator == null) { + return false; + } + if (typeof propagator === 'object') { + if ('composite' in propagator) { + if (Array.isArray(propagator.composite)) { + for (let i = 0; i < propagator.composite.length; i++) { + const element = propagator.composite[i]; + if (typeof element !== 'object') { + return false; + } + } + } else { + return false; + } + } + if ('composite_list' in propagator) { + if (typeof propagator.composite_list !== 'string') { + return false; + } + } + return true; + } + return false; +} diff --git a/experimental/packages/opentelemetry-configuration/test/utils.test.ts b/experimental/packages/opentelemetry-configuration/test/utils.test.ts index 0b56a778397..bfd2ce5c1a2 100644 --- a/experimental/packages/opentelemetry-configuration/test/utils.test.ts +++ b/experimental/packages/opentelemetry-configuration/test/utils.test.ts @@ -25,6 +25,7 @@ import { getNumberListFromConfigFile, getStringFromConfigFile, getStringListFromConfigFile, + isPropagator, } from '../src/utils'; describe('config utils', function () { @@ -167,4 +168,20 @@ describe('config utils', function () { delete process.env.TEST2; delete process.env.TEST_LONG_NAME; }); + + it('should return correct values for isPropagator', function () { + assert.strictEqual(isPropagator(null), false); + assert.strictEqual(isPropagator('value'), false); + assert.strictEqual(isPropagator({}), true); + assert.strictEqual(isPropagator({ composite: 'value' }), false); + assert.strictEqual(isPropagator({ composite_list: true }), false); + assert.strictEqual(isPropagator({ composite: ['v1', 'v2'] }), false); + assert.strictEqual( + isPropagator({ + composite: [{ tracecontext: null }, { baggage: null }], + composite_list: 'tracecontext,baggage', + }), + true + ); + }); }); From 0ce328942deb253c063d9c1648aff6dd474f3bd2 Mon Sep 17 00:00:00 2001 From: maryliag Date: Tue, 7 Oct 2025 16:57:47 -0400 Subject: [PATCH 08/27] parse trace provider --- .../src/EnvironmentConfigProvider.ts | 28 +-- .../src/FileConfigProvider.ts | 198 ++++++++++++++++++ .../src/configModel.ts | 132 +++++++++++- .../opentelemetry-configuration/src/utils.ts | 2 +- .../test/ConfigProvider.test.ts | 109 +++++++++- .../test/utils.test.ts | 14 ++ 6 files changed, 465 insertions(+), 18 deletions(-) diff --git a/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts index b355201d11a..d801bd2a1a0 100644 --- a/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts @@ -173,45 +173,45 @@ function setTracerProvider(config: ConfigurationModel): void { } const endpoint = getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT'); - if (endpoint) { + if (endpoint && batch.exporter.otlp_http) { batch.exporter.otlp_http.endpoint = endpoint; } const certificateFile = getStringFromEnv( 'OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE' ); - if (certificateFile) { + if (certificateFile && batch.exporter.otlp_http) { batch.exporter.otlp_http.certificate_file = certificateFile; } const clientKeyFile = getStringFromEnv( 'OTEL_EXPORTER_OTLP_TRACES_CLIENT_KEY' ); - if (clientKeyFile) { + if (clientKeyFile && batch.exporter.otlp_http) { batch.exporter.otlp_http.client_key_file = clientKeyFile; } const clientCertificateFile = getStringFromEnv( 'OTEL_EXPORTER_OTLP_TRACES_CLIENT_CERTIFICATE' ); - if (clientCertificateFile) { + if (clientCertificateFile && batch.exporter.otlp_http) { batch.exporter.otlp_http.client_certificate_file = clientCertificateFile; } const compression = getStringFromEnv( 'OTEL_EXPORTER_OTLP_TRACES_COMPRESSION' ); - if (compression) { + if (compression && batch.exporter.otlp_http) { batch.exporter.otlp_http.compression = compression; } const timeout = getNumberFromEnv('OTEL_EXPORTER_OTLP_TRACES_TIMEOUT'); - if (timeout) { + if (timeout && batch.exporter.otlp_http) { batch.exporter.otlp_http.timeout = timeout; } const headersList = getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_HEADERS'); - if (headersList) { + if (headersList && batch.exporter.otlp_http) { batch.exporter.otlp_http.headers_list = headersList; } @@ -355,43 +355,43 @@ function setLoggerProvider(config: ConfigurationModel): void { } const endpoint = getStringFromEnv('OTEL_EXPORTER_OTLP_LOGS_ENDPOINT'); - if (endpoint) { + if (endpoint && batch.exporter.otlp_http) { batch.exporter.otlp_http.endpoint = endpoint; } const certificateFile = getStringFromEnv( 'OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE' ); - if (certificateFile) { + if (certificateFile && batch.exporter.otlp_http) { batch.exporter.otlp_http.certificate_file = certificateFile; } const clientKeyFile = getStringFromEnv( 'OTEL_EXPORTER_OTLP_LOGS_CLIENT_KEY' ); - if (clientKeyFile) { + if (clientKeyFile && batch.exporter.otlp_http) { batch.exporter.otlp_http.client_key_file = clientKeyFile; } const clientCertificateFile = getStringFromEnv( 'OTEL_EXPORTER_OTLP_LOGS_CLIENT_CERTIFICATE' ); - if (clientCertificateFile) { + if (clientCertificateFile && batch.exporter.otlp_http) { batch.exporter.otlp_http.client_certificate_file = clientCertificateFile; } const compression = getStringFromEnv('OTEL_EXPORTER_OTLP_LOGS_COMPRESSION'); - if (compression) { + if (compression && batch.exporter.otlp_http) { batch.exporter.otlp_http.compression = compression; } const timeout = getNumberFromEnv('OTEL_EXPORTER_OTLP_LOGS_TIMEOUT'); - if (timeout) { + if (timeout && batch.exporter.otlp_http) { batch.exporter.otlp_http.timeout = timeout; } const headersList = getStringFromEnv('OTEL_EXPORTER_OTLP_LOGS_HEADERS'); - if (headersList) { + if (headersList && batch.exporter.otlp_http) { batch.exporter.otlp_http.headers_list = headersList; } diff --git a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts index 51ec2d432e1..c7933a1ce88 100644 --- a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts @@ -18,8 +18,11 @@ import { diagLogLevelFromString, getStringFromEnv } from '@opentelemetry/core'; import { AttributeLimits, ConfigAttributes, + ConfigExporter, + ConfigHeader, ConfigLoggerProvider, ConfigMeterProvider, + ConfigProcessor, ConfigTracerProvider, ConfigurationModel, initializeDefaultConfiguration, @@ -208,6 +211,157 @@ function setPropagator(config: ConfigurationModel, propagator: unknown): void { } } +function getConfigHeaders(h?: ConfigHeader[]): ConfigHeader[] | null { + if (h) { + const headers: ConfigHeader[] = []; + for (let i = 0; i < h.length; i++) { + const element = h[i]; + headers.push({ + name: element['name'], + value: element['value'], + }); + } + if (headers.length > 0) { + return headers; + } + } + return null; +} + +function parseConfigExporter(exporter: ConfigExporter): ConfigExporter { + const exporterType = Object.keys(exporter)[0]; + let parsedExporter: ConfigExporter = {}; + let e; + let certFile; + let clientCertFile; + let clientKeyFile; + let compression; + let headers; + let headersList; + let insecure; + switch (exporterType) { + case 'otlp_http': + e = exporter['otlp_http']; + if (e) { + parsedExporter = { + otlp_http: { + endpoint: + getStringFromConfigFile(e['endpoint']) ?? + 'http://localhost:4318/v1/traces', + timeout: getNumberFromConfigFile(e['timeout']) ?? 10000, + encoding: + getStringFromConfigFile(e['encoding']) === 'json' + ? 'json' + : 'protobuf', + }, + }; + + certFile = getStringFromConfigFile(e['certificate_file']); + if (certFile && parsedExporter.otlp_http) { + parsedExporter.otlp_http.certificate_file = certFile; + } + clientCertFile = getStringFromConfigFile(e['client_certificate_file']); + if (clientCertFile && parsedExporter.otlp_http) { + parsedExporter.otlp_http.client_certificate_file = clientCertFile; + } + clientKeyFile = getStringFromConfigFile(e['client_key_file']); + if (clientKeyFile && parsedExporter.otlp_http) { + parsedExporter.otlp_http.client_key_file = clientKeyFile; + } + compression = getStringFromConfigFile(e['compression']); + if (compression && parsedExporter.otlp_http) { + parsedExporter.otlp_http.compression = compression; + } + headersList = getStringFromConfigFile(e['headers_list']); + if (headersList && parsedExporter.otlp_http) { + parsedExporter.otlp_http.headers_list = headersList; + } + headers = getConfigHeaders(e['headers']); + if (headers && parsedExporter.otlp_http) { + parsedExporter.otlp_http.headers = headers; + } + } + break; + + case 'otlp_grpc': + e = exporter['otlp_grpc']; + if (e) { + parsedExporter = { + otlp_grpc: { + endpoint: + getStringFromConfigFile(e['endpoint']) ?? + 'http://localhost:4318/v1/traces', + timeout: getNumberFromConfigFile(e['timeout']) ?? 10000, + }, + }; + + certFile = getStringFromConfigFile(e['certificate_file']); + if (certFile && parsedExporter.otlp_grpc) { + parsedExporter.otlp_grpc.certificate_file = certFile; + } + clientCertFile = getStringFromConfigFile(e['client_certificate_file']); + if (clientCertFile && parsedExporter.otlp_grpc) { + parsedExporter.otlp_grpc.client_certificate_file = clientCertFile; + } + clientKeyFile = getStringFromConfigFile(e['client_key_file']); + if (clientKeyFile && parsedExporter.otlp_grpc) { + parsedExporter.otlp_grpc.client_key_file = clientKeyFile; + } + compression = getStringFromConfigFile(e['compression']); + if (compression && parsedExporter.otlp_grpc) { + parsedExporter.otlp_grpc.compression = compression; + } + headersList = getStringFromConfigFile(e['headers_list']); + if (headersList && parsedExporter.otlp_grpc) { + parsedExporter.otlp_grpc.headers_list = headersList; + } + headers = getConfigHeaders(e['headers']); + if (headers && parsedExporter.otlp_grpc) { + parsedExporter.otlp_grpc.headers = headers; + } + insecure = getBooleanFromConfigFile(e['insecure']); + if ((insecure || insecure === false) && parsedExporter.otlp_grpc) { + parsedExporter.otlp_grpc.insecure = insecure; + } + } + break; + + case 'otlp_file/development': + e = exporter['otlp_file/development']; + if (e) { + parsedExporter = { + 'otlp_file/development': { + output_stream: + getStringFromConfigFile(e['output_stream']) ?? 'stdout', + }, + }; + } + break; + + case 'console': + parsedExporter = { + console: {}, + }; + break; + + case 'zipkin': + e = exporter['zipkin']; + if (e) { + parsedExporter = { + zipkin: { + endpoint: + getStringFromConfigFile(e['endpoint']) ?? + 'http://localhost:9411/api/v2/spans', + timeout: getNumberFromConfigFile(e['timeout']) ?? 10000, + }, + }; + } + break; + } + + return parsedExporter; +} + function setTracerProvider( config: ConfigurationModel, tracerProvider: ConfigTracerProvider @@ -262,6 +416,50 @@ function setTracerProvider( linkAttributeCountLimit; } } + + // Processors + if (tracerProvider['processors']) { + if (tracerProvider['processors'].length > 0) { + config.tracer_provider.processors = []; + } + for (let i = 0; i < tracerProvider['processors'].length; i++) { + const processorType = Object.keys(tracerProvider['processors'][i])[0]; + if (processorType === 'batch') { + const element = tracerProvider['processors'][i]['batch']; + if (element) { + const parsedExporter = parseConfigExporter(element['exporter']); + const batchConfig: ConfigProcessor = { + batch: { + schedule_delay: + getNumberFromConfigFile(element['schedule_delay']) ?? 5000, + export_timeout: + getNumberFromConfigFile(element['export_timeout']) ?? 30000, + max_queue_size: + getNumberFromConfigFile(element['max_queue_size']) ?? 2048, + max_export_batch_size: + getNumberFromConfigFile(element['max_export_batch_size']) ?? + 512, + exporter: parsedExporter, + }, + }; + + config.tracer_provider.processors.push(batchConfig); + } + } else if (processorType === 'simple') { + const element = tracerProvider['processors'][i]['simple']; + if (element) { + const parsedExporter = parseConfigExporter(element['exporter']); + const simpleConfig: ConfigProcessor = { + simple: { + exporter: parsedExporter, + }, + }; + + config.tracer_provider.processors.push(simpleConfig); + } + } + } + } } } diff --git a/experimental/packages/opentelemetry-configuration/src/configModel.ts b/experimental/packages/opentelemetry-configuration/src/configModel.ts index cda8468aba6..5a53ba9c239 100644 --- a/experimental/packages/opentelemetry-configuration/src/configModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/configModel.ts @@ -93,6 +93,7 @@ export function initializeDefaultConfiguration(): ConfigurationModel { otlp_http: { endpoint: 'http://localhost:4318/v1/traces', timeout: 10000, + encoding: 'protobuf', }, }, }, @@ -146,6 +147,7 @@ export function initializeDefaultConfiguration(): ConfigurationModel { otlp_http: { endpoint: 'http://localhost:4318/v1/logs', timeout: 10000, + encoding: 'protobuf', }, }, }, @@ -240,6 +242,12 @@ export interface ConfigPropagator { composite_list: string; } +export interface ConfigSimpleProcessor { + /** + * Configure exporter. + */ + exporter: ConfigExporter; +} export interface ConfigBatchProcessor { /** * Configure delay interval (in milliseconds) between two consecutive exports. @@ -277,7 +285,28 @@ export interface ConfigExporter { /** * Configure exporter to be OTLP with HTTP transport. */ - otlp_http: ConfigOTLPHttp; + otlp_http?: ConfigOTLPHttp; + + /** + * Configure exporter to be OTLP with gRPC transport. + */ + otlp_grpc?: ConfigOTLPGRPC; + + /** + * Configure exporter to be OTLP with file transport. + * This type is in development and subject to breaking changes in minor versions. + */ + 'otlp_file/development'?: ConfigOTLPFile; + + /** + * Configure exporter to be console. + */ + console?: object; + + /** + * Configure exporter to be zipkin. + */ + zipkin?: ConfigZipkin; } export interface ConfigMeterExporter { @@ -342,12 +371,111 @@ export interface ConfigOTLPHttp { * If omitted or null, no headers are added. */ headers_list?: string; + + /** + * Configure the encoding used for messages. + * Values include: protobuf, json. Implementations may not support json. + * If omitted or null, protobuf is used. + */ + encoding: 'protobuf' | 'json'; } + +export interface ConfigOTLPGRPC { + /** + * Configure endpoint. + * If omitted or null, http://localhost:4317 is used. + */ + endpoint: string; + + /** + * Configure certificate used to verify a server's TLS credentials. + * Absolute path to certificate file in PEM format. + * If omitted or null, system default certificate verification is used for secure connections. + */ + certificate_file?: string; + + /** + * Configure mTLS private client key. + * Absolute path to client key file in PEM format. If set, .client_certificate must also be set. + * If omitted or null, mTLS is not used. + */ + client_key_file?: string; + + /** + * Configure mTLS client certificate. + * Absolute path to client certificate file in PEM format. If set, .client_key must also be set. + * If omitted or null, mTLS is not used. + */ + client_certificate_file?: string; + + /** + * Configure headers. Entries have higher priority than entries from .headers_list. + * If an entry's .value is null, the entry is ignored. + */ + headers?: ConfigHeader[]; + + /** + * Configure headers. Entries have lower priority than entries from .headers. + * The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. + * If omitted or null, no headers are added. + */ + headers_list?: string; + + /** + * Configure compression. + * Values include: gzip, none. Implementations may support other compression algorithms. + * If omitted or null, none is used. + */ + compression?: string; + + /** + * Configure max time (in milliseconds) to wait for each export. + * Value must be non-negative. A value of 0 indicates no limit (infinity). + * If omitted or null, 10000 is used. + */ + timeout: number; + + /** + * Configure client transport security for the exporter's connection. + * Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. + * If omitted or null, false is used. + */ + insecure?: boolean; +} +export interface ConfigOTLPFile { + /** + * Configure output stream. + * Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. + * If omitted or null, stdout is used. + */ + output_stream: string; +} + +export interface ConfigZipkin { + /** + * Configure endpoint. + * If omitted or null, http://localhost:9411/api/v2/spans is used. + */ + endpoint: string; + + /** + * Configure max time (in milliseconds) to wait for each export. + * Value must be non-negative. A value of 0 indicates indefinite. + * If omitted or null, 10000 is used. + */ + timeout: number; +} + export interface ConfigProcessor { /** * Configure a batch span processor. */ - batch: ConfigBatchProcessor; + batch?: ConfigBatchProcessor; + + /** + * Configure a simple span processor. + */ + simple?: ConfigSimpleProcessor; } export interface ConfigHeader { diff --git a/experimental/packages/opentelemetry-configuration/src/utils.ts b/experimental/packages/opentelemetry-configuration/src/utils.ts index 27242cb2ae4..5a4b19b6a16 100644 --- a/experimental/packages/opentelemetry-configuration/src/utils.ts +++ b/experimental/packages/opentelemetry-configuration/src/utils.ts @@ -189,7 +189,7 @@ export function envVariableSubstitution(value: unknown): string | undefined { return undefined; } - const matches = String(value).match(/\$\{[a-zA-Z0-9,=_:.-]*\}/g); + const matches = String(value).match(/\$\{[a-zA-Z0-9,=/_:.-]*\}/g); if (matches) { let stringValue = String(value); for (const match of matches) { diff --git a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts index 5d62066b519..b430c5f32dc 100644 --- a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts +++ b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts @@ -43,6 +43,7 @@ const defaultConfig: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/traces', timeout: 10000, + encoding: 'protobuf', }, }, }, @@ -96,6 +97,7 @@ const defaultConfig: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/logs', timeout: 10000, + encoding: 'protobuf', }, }, }, @@ -190,11 +192,87 @@ const configFromFile: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/traces', timeout: 10000, + certificate_file: '/app/cert.pem', + client_key_file: '/app/cert.pem', + client_certificate_file: '/app/cert.pem', + headers: [{ name: 'api-key', value: '1234' }], + headers_list: 'api-key=1234', + compression: 'gzip', + encoding: 'protobuf', }, }, }, }, + { + batch: { + schedule_delay: 5000, + export_timeout: 30000, + max_queue_size: 2048, + max_export_batch_size: 512, + exporter: { + otlp_grpc: { + endpoint: 'http://localhost:4317', + timeout: 10000, + certificate_file: '/app/cert.pem', + client_key_file: '/app/cert.pem', + client_certificate_file: '/app/cert.pem', + headers: [{ name: 'api-key', value: '1234' }], + headers_list: 'api-key=1234', + compression: 'gzip', + insecure: false, + }, + }, + }, + }, + { + batch: { + schedule_delay: 5000, + export_timeout: 30000, + max_queue_size: 2048, + max_export_batch_size: 512, + exporter: { + 'otlp_file/development': { + output_stream: 'file:///var/log/traces.jsonl', + }, + }, + }, + }, + { + batch: { + schedule_delay: 5000, + export_timeout: 30000, + max_queue_size: 2048, + max_export_batch_size: 512, + exporter: { + 'otlp_file/development': { + output_stream: 'stdout', + }, + }, + }, + }, + { + batch: { + schedule_delay: 5000, + export_timeout: 30000, + max_queue_size: 2048, + max_export_batch_size: 512, + exporter: { + zipkin: { + endpoint: 'http://localhost:9411/api/v2/spans', + timeout: 10000, + }, + }, + }, + }, + { + simple: { + exporter: { + console: {}, + }, + }, + }, ], + limits: { attribute_count_limit: 128, attribute_value_length_limit: 4096, @@ -244,6 +322,7 @@ const configFromFile: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/logs', timeout: 10000, + encoding: 'protobuf', }, }, }, @@ -288,6 +367,8 @@ const defaultConfigFromFileWithEnvVariables: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/traces', timeout: 10000, + encoding: 'protobuf', + compression: 'gzip', }, }, }, @@ -341,6 +422,7 @@ const defaultConfigFromFileWithEnvVariables: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/logs', timeout: 10000, + encoding: 'protobuf', }, }, }, @@ -575,6 +657,7 @@ describe('ConfigProvider', function () { compression: 'gzip', timeout: 2000, headers_list: 'host=localhost', + encoding: 'protobuf', }, }, }, @@ -690,6 +773,7 @@ describe('ConfigProvider', function () { compression: 'gzip', timeout: 700, headers_list: 'host=localhost', + encoding: 'protobuf', }, }, }, @@ -827,7 +911,8 @@ describe('ConfigProvider', function () { process.env.OTEL_BSP_EXPORT_TIMEOUT = '456'; process.env.OTEL_BSP_MAX_QUEUE_SIZE = '789'; process.env.OTEL_BSP_MAX_EXPORT_BATCH_SIZE = '1011'; - process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'trace-endpoint'; + process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = + 'http://test.com:4318/v1/traces'; process.env.OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE = 'trace-certificate'; process.env.OTEL_EXPORTER_OTLP_TRACES_CLIENT_KEY = 'trace-client-key'; process.env.OTEL_EXPORTER_OTLP_TRACES_CLIENT_CERTIFICATE = @@ -901,6 +986,28 @@ describe('ConfigProvider', function () { event_attribute_count_limit: 18, link_attribute_count_limit: 19, }, + processors: [ + { + batch: { + export_timeout: 456, + max_export_batch_size: 1011, + max_queue_size: 789, + schedule_delay: 123, + exporter: { + otlp_http: { + certificate_file: 'trace-certificate', + client_certificate_file: 'trace-client-certificate', + client_key_file: 'trace-client-key', + compression: 'trace-compression', + encoding: 'protobuf', + endpoint: 'http://test.com:4318/v1/traces', + headers_list: 'trace-headers', + timeout: 1213, + }, + }, + }, + }, + ], }, meter_provider: { ...defaultConfigFromFileWithEnvVariables.meter_provider, diff --git a/experimental/packages/opentelemetry-configuration/test/utils.test.ts b/experimental/packages/opentelemetry-configuration/test/utils.test.ts index bfd2ce5c1a2..01d78f16ac6 100644 --- a/experimental/packages/opentelemetry-configuration/test/utils.test.ts +++ b/experimental/packages/opentelemetry-configuration/test/utils.test.ts @@ -150,6 +150,7 @@ describe('config utils', function () { process.env.TEST1 = 't1'; process.env.TEST2 = 't2'; process.env.TEST_LONG_NAME = '100'; + process.env.TEST_ENDPOINT = 'http://test.com:4318/v1/traces'; assert.deepStrictEqual(envVariableSubstitution(null), undefined); assert.deepStrictEqual(envVariableSubstitution(' '), ' '); assert.deepStrictEqual(envVariableSubstitution('${TEST1}'), 't1'); @@ -163,10 +164,23 @@ describe('config utils', function () { envVariableSubstitution('${TEST3:-backup}'), 'backup' ); + assert.deepStrictEqual( + envVariableSubstitution( + '${TEST_ENDPOINT:-http://localhost:4318/v1/traces}' + ), + 'http://test.com:4318/v1/traces' + ); + assert.deepStrictEqual( + envVariableSubstitution( + '${TEST_NON_EXISTING:-http://localhost:4318/v1/traces}' + ), + 'http://localhost:4318/v1/traces' + ); delete process.env.TEST1; delete process.env.TEST2; delete process.env.TEST_LONG_NAME; + delete process.env.TEST_ENDPOINT; }); it('should return correct values for isPropagator', function () { From 860aae10d085333c59ffd59772b646f1d7abaab7 Mon Sep 17 00:00:00 2001 From: maryliag Date: Tue, 7 Oct 2025 16:58:38 -0400 Subject: [PATCH 09/27] add changelog --- experimental/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index 67c4f20cbcd..6ddb5bfced5 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -28,6 +28,7 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2 * feat(opentelemetry-configuration): parse of environment variables on configuration file [#5947](https://github.com/open-telemetry/opentelemetry-js/pull/5947) @maryliag * feat(opentelemetry-configuration): parse more parameters from config file [#5955](https://github.com/open-telemetry/opentelemetry-js/pull/5955) @maryliag * feat(exporter-prometheus): support withoutTargetInfo option [#5962](https://github.com/open-telemetry/opentelemetry-js/pull/5962) @cjihrig +* feat(opentelemetry-configuration): parse trace provider from config file [#5955](https://github.com/open-telemetry/opentelemetry-js/pull/5955) @maryliag ### :bug: Bug Fixes From 2e06c42d1a0bd8cf39c190011aa0fc920a26deb7 Mon Sep 17 00:00:00 2001 From: maryliag Date: Tue, 7 Oct 2025 17:01:19 -0400 Subject: [PATCH 10/27] update changelog --- experimental/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index 6ddb5bfced5..e3f1c58c8f8 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -28,7 +28,7 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2 * feat(opentelemetry-configuration): parse of environment variables on configuration file [#5947](https://github.com/open-telemetry/opentelemetry-js/pull/5947) @maryliag * feat(opentelemetry-configuration): parse more parameters from config file [#5955](https://github.com/open-telemetry/opentelemetry-js/pull/5955) @maryliag * feat(exporter-prometheus): support withoutTargetInfo option [#5962](https://github.com/open-telemetry/opentelemetry-js/pull/5962) @cjihrig -* feat(opentelemetry-configuration): parse trace provider from config file [#5955](https://github.com/open-telemetry/opentelemetry-js/pull/5955) @maryliag +* feat(opentelemetry-configuration): parse trace provider from config file [#5992](https://github.com/open-telemetry/opentelemetry-js/pull/5992) @maryliag ### :bug: Bug Fixes From da7762ddad048aef94f2a91b986b14303dcefe05 Mon Sep 17 00:00:00 2001 From: maryliag Date: Wed, 8 Oct 2025 11:47:56 -0400 Subject: [PATCH 11/27] fix post merge --- .../opentelemetry-configuration/src/utils.ts | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/experimental/packages/opentelemetry-configuration/src/utils.ts b/experimental/packages/opentelemetry-configuration/src/utils.ts index 5a4b19b6a16..4aedf798d28 100644 --- a/experimental/packages/opentelemetry-configuration/src/utils.ts +++ b/experimental/packages/opentelemetry-configuration/src/utils.ts @@ -157,33 +157,6 @@ export function getStringListFromConfigFile( .filter(s => s !== ''); } -/** - * Retrieves a list of strings from a configuration file parameter - * that is a list of objects. - * e.g. Parsing the value of `composite` such as - * composite: - * - tracecontext: - * - baggage: - * - b3: - * returns ['tracecontext', 'baggage', 'b3'] - * @param value - The value from the config file. - * @returns {string[] | undefined} - The list of strings or `undefined`. - */ -export function getListFromObjectsFromConfigFile( - value: object[] | undefined -): string[] | undefined { - if (value) { - const list: string[] = []; - for (let i = 0; i < value.length; i++) { - list.push(...Object.keys(value[i])); - } - if (list.length > 0) { - return list; - } - } - return undefined; -} - export function envVariableSubstitution(value: unknown): string | undefined { if (value == null) { return undefined; From 2cd03d76766499a783ba4ec1f33d6e8c25eabfaa Mon Sep 17 00:00:00 2001 From: maryliag Date: Wed, 8 Oct 2025 11:51:18 -0400 Subject: [PATCH 12/27] fix pos merge --- .../opentelemetry-configuration/src/utils.ts | 30 ------------------- .../test/utils.test.ts | 17 ----------- 2 files changed, 47 deletions(-) diff --git a/experimental/packages/opentelemetry-configuration/src/utils.ts b/experimental/packages/opentelemetry-configuration/src/utils.ts index 4aedf798d28..5c3855d9546 100644 --- a/experimental/packages/opentelemetry-configuration/src/utils.ts +++ b/experimental/packages/opentelemetry-configuration/src/utils.ts @@ -16,7 +16,6 @@ import { diag } from '@opentelemetry/api'; import { getStringFromEnv } from '@opentelemetry/core'; import { inspect } from 'util'; -import { ConfigPropagator } from './configModel'; /** * Retrieves a boolean value from a configuration file parameter. @@ -175,32 +174,3 @@ export function envVariableSubstitution(value: unknown): string | undefined { } return String(value); } - -export function isPropagator( - propagator: unknown -): propagator is Partial { - if (propagator == null) { - return false; - } - if (typeof propagator === 'object') { - if ('composite' in propagator) { - if (Array.isArray(propagator.composite)) { - for (let i = 0; i < propagator.composite.length; i++) { - const element = propagator.composite[i]; - if (typeof element !== 'object') { - return false; - } - } - } else { - return false; - } - } - if ('composite_list' in propagator) { - if (typeof propagator.composite_list !== 'string') { - return false; - } - } - return true; - } - return false; -} diff --git a/experimental/packages/opentelemetry-configuration/test/utils.test.ts b/experimental/packages/opentelemetry-configuration/test/utils.test.ts index 01d78f16ac6..58eed2fcebd 100644 --- a/experimental/packages/opentelemetry-configuration/test/utils.test.ts +++ b/experimental/packages/opentelemetry-configuration/test/utils.test.ts @@ -25,7 +25,6 @@ import { getNumberListFromConfigFile, getStringFromConfigFile, getStringListFromConfigFile, - isPropagator, } from '../src/utils'; describe('config utils', function () { @@ -182,20 +181,4 @@ describe('config utils', function () { delete process.env.TEST_LONG_NAME; delete process.env.TEST_ENDPOINT; }); - - it('should return correct values for isPropagator', function () { - assert.strictEqual(isPropagator(null), false); - assert.strictEqual(isPropagator('value'), false); - assert.strictEqual(isPropagator({}), true); - assert.strictEqual(isPropagator({ composite: 'value' }), false); - assert.strictEqual(isPropagator({ composite_list: true }), false); - assert.strictEqual(isPropagator({ composite: ['v1', 'v2'] }), false); - assert.strictEqual( - isPropagator({ - composite: [{ tracecontext: null }, { baggage: null }], - composite_list: 'tracecontext,baggage', - }), - true - ); - }); }); From 6265f0f410f7e521d1360b3b1804fe15a8d28be6 Mon Sep 17 00:00:00 2001 From: maryliag Date: Wed, 8 Oct 2025 14:26:09 -0400 Subject: [PATCH 13/27] parse logger provider --- .../src/FileConfigProvider.ts | 165 ++++++++++++++++-- .../src/configModel.ts | 40 +++++ .../test/ConfigProvider.test.ts | 101 ++++++++++- 3 files changed, 285 insertions(+), 21 deletions(-) diff --git a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts index 0a0b8e8aaa8..d4154c19337 100644 --- a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts @@ -231,7 +231,16 @@ function getConfigHeaders(h?: ConfigHeader[]): ConfigHeader[] | null { return null; } -function parseConfigExporter(exporter: ConfigExporter): ConfigExporter { +enum ProviderType { + TRACER = 0, + METER = 1, + LOGGER = 2, +} + +function parseConfigExporter( + exporter: ConfigExporter, + providerType: ProviderType +): ConfigExporter { const exporterType = Object.keys(exporter)[0]; let parsedExporter: ConfigExporter = {}; let e; @@ -242,15 +251,27 @@ function parseConfigExporter(exporter: ConfigExporter): ConfigExporter { let headers; let headersList; let insecure; + let endpoint; + + switch (providerType) { + case ProviderType.TRACER: + endpoint = 'http://localhost:4318/v1/traces'; + break; + case ProviderType.METER: + endpoint = 'http://localhost:4318/v1/metrics'; + break; + case ProviderType.LOGGER: + endpoint = 'http://localhost:4318/v1/logs'; + break; + } + switch (exporterType) { case 'otlp_http': e = exporter['otlp_http']; if (e) { parsedExporter = { otlp_http: { - endpoint: - getStringFromConfigFile(e['endpoint']) ?? - 'http://localhost:4318/v1/traces', + endpoint: getStringFromConfigFile(e['endpoint']) ?? endpoint, timeout: getNumberFromConfigFile(e['timeout']) ?? 10000, encoding: getStringFromConfigFile(e['encoding']) === 'json' @@ -292,8 +313,7 @@ function parseConfigExporter(exporter: ConfigExporter): ConfigExporter { parsedExporter = { otlp_grpc: { endpoint: - getStringFromConfigFile(e['endpoint']) ?? - 'http://localhost:4318/v1/traces', + getStringFromConfigFile(e['endpoint']) ?? 'http://localhost:4317', timeout: getNumberFromConfigFile(e['timeout']) ?? 10000, }, }; @@ -430,7 +450,10 @@ function setTracerProvider( if (processorType === 'batch') { const element = tracerProvider['processors'][i]['batch']; if (element) { - const parsedExporter = parseConfigExporter(element['exporter']); + const parsedExporter = parseConfigExporter( + element['exporter'], + ProviderType.TRACER + ); const batchConfig: ConfigProcessor = { batch: { schedule_delay: @@ -451,7 +474,10 @@ function setTracerProvider( } else if (processorType === 'simple') { const element = tracerProvider['processors'][i]['simple']; if (element) { - const parsedExporter = parseConfigExporter(element['exporter']); + const parsedExporter = parseConfigExporter( + element['exporter'], + ProviderType.TRACER + ); const simpleConfig: ConfigProcessor = { simple: { exporter: parsedExporter, @@ -490,19 +516,120 @@ function setLoggerProvider( loggerProvider: ConfigLoggerProvider ): void { if (loggerProvider) { - const attributeValueLengthLimit = getNumberFromConfigFile( - loggerProvider['limits']['attribute_value_length_limit'] - ); - if (attributeValueLengthLimit) { - config.logger_provider.limits.attribute_value_length_limit = - attributeValueLengthLimit; + // Limits + if (loggerProvider['limits']) { + const attributeValueLengthLimit = getNumberFromConfigFile( + loggerProvider['limits']['attribute_value_length_limit'] + ); + if (attributeValueLengthLimit) { + config.logger_provider.limits.attribute_value_length_limit = + attributeValueLengthLimit; + } + + const attributeCountLimit = getNumberFromConfigFile( + loggerProvider['limits']['attribute_count_limit'] + ); + if (attributeCountLimit) { + config.logger_provider.limits.attribute_count_limit = + attributeCountLimit; + } } - const attributeCountLimit = getNumberFromConfigFile( - loggerProvider['limits']['attribute_count_limit'] - ); - if (attributeCountLimit) { - config.logger_provider.limits.attribute_count_limit = attributeCountLimit; + // Processors + if (loggerProvider['processors']) { + if (loggerProvider['processors'].length > 0) { + config.logger_provider.processors = []; + } + for (let i = 0; i < loggerProvider['processors'].length; i++) { + const processorType = Object.keys(loggerProvider['processors'][i])[0]; + if (processorType === 'batch') { + const element = loggerProvider['processors'][i]['batch']; + if (element) { + const parsedExporter = parseConfigExporter( + element['exporter'], + ProviderType.LOGGER + ); + const batchConfig: ConfigProcessor = { + batch: { + schedule_delay: + getNumberFromConfigFile(element['schedule_delay']) ?? 1000, + export_timeout: + getNumberFromConfigFile(element['export_timeout']) ?? 30000, + max_queue_size: + getNumberFromConfigFile(element['max_queue_size']) ?? 2048, + max_export_batch_size: + getNumberFromConfigFile(element['max_export_batch_size']) ?? + 512, + exporter: parsedExporter, + }, + }; + + config.logger_provider.processors.push(batchConfig); + } + } else if (processorType === 'simple') { + const element = loggerProvider['processors'][i]['simple']; + if (element) { + const parsedExporter = parseConfigExporter( + element['exporter'], + ProviderType.LOGGER + ); + const simpleConfig: ConfigProcessor = { + simple: { + exporter: parsedExporter, + }, + }; + + config.logger_provider.processors.push(simpleConfig); + } + } + } + } + + // logger_configurator/development + if (loggerProvider['logger_configurator/development']) { + const defaultConfigDisabled = getBooleanFromConfigFile( + loggerProvider['logger_configurator/development']['default_config']?.[ + 'disabled' + ] + ); + if (defaultConfigDisabled || defaultConfigDisabled === false) { + config.logger_provider['logger_configurator/development'] = { + default_config: { + disabled: defaultConfigDisabled, + }, + }; + } + + if ( + loggerProvider['logger_configurator/development'].loggers && + loggerProvider['logger_configurator/development'].loggers.length > 0 + ) { + const loggers = []; + for ( + let i = 0; + i < loggerProvider['logger_configurator/development'].loggers.length; + i++ + ) { + const logger = + loggerProvider['logger_configurator/development'].loggers[i]; + const disabled = + getBooleanFromConfigFile(logger['config']['disabled']) ?? false; + const name = getStringFromConfigFile(logger['name']); + if (name) { + loggers.push({ + name: name, + config: { + disabled: disabled, + }, + }); + } + } + if (config.logger_provider['logger_configurator/development'] == null) { + config.logger_provider['logger_configurator/development'] = {}; + } + config.logger_provider['logger_configurator/development'].loggers = + loggers; + } } } } diff --git a/experimental/packages/opentelemetry-configuration/src/configModel.ts b/experimental/packages/opentelemetry-configuration/src/configModel.ts index 4de7f04c3df..4d38f78484e 100644 --- a/experimental/packages/opentelemetry-configuration/src/configModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/configModel.ts @@ -703,4 +703,44 @@ export interface ConfigLoggerProvider { * Configure log record limits. See also attribute_limits. */ limits: AttributeLimits; + + /** + * Configure loggers. + * This type is in development and subject to breaking changes in minor versions. + */ + 'logger_configurator/development'?: LoggerConfigurator; +} + +export interface LoggerConfigurator { + /** + * Configure the default logger config used there is no matching entry in .logger_configurator/development.loggers. + */ + default_config?: DisabledConfig; + + /** + * Configure loggers. + */ + loggers?: LoggerMatcherAndConfig[]; +} + +export interface DisabledConfig { + /** + * Configure if the logger is enabled or not. + */ + disabled: boolean; +} + +export interface LoggerMatcherAndConfig { + /** + * Configure logger names to match, evaluated as follows: + * * If the logger name exactly matches. + * * If the logger name matches the wildcard pattern, where '?' matches any single character + * and '*' matches any number of characters including none. + */ + name: string; + + /** + * The logger config. + */ + config: DisabledConfig; } diff --git a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts index 1466da06afb..e3988c69750 100644 --- a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts +++ b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts @@ -314,7 +314,7 @@ const configFromFile: Configuration = { processors: [ { batch: { - schedule_delay: 1000, + schedule_delay: 5000, export_timeout: 30000, max_queue_size: 2048, max_export_batch_size: 512, @@ -323,15 +323,88 @@ const configFromFile: Configuration = { endpoint: 'http://localhost:4318/v1/logs', timeout: 10000, encoding: 'protobuf', + certificate_file: '/app/cert.pem', + client_key_file: '/app/cert.pem', + client_certificate_file: '/app/cert.pem', + headers: [{ name: 'api-key', value: '1234' }], + headers_list: 'api-key=1234', + compression: 'gzip', + }, + }, + }, + }, + { + batch: { + schedule_delay: 1000, + export_timeout: 30000, + max_queue_size: 2048, + max_export_batch_size: 512, + exporter: { + otlp_grpc: { + endpoint: 'http://localhost:4317', + timeout: 10000, + certificate_file: '/app/cert.pem', + client_key_file: '/app/cert.pem', + client_certificate_file: '/app/cert.pem', + headers: [{ name: 'api-key', value: '1234' }], + headers_list: 'api-key=1234', + compression: 'gzip', + insecure: false, + }, + }, + }, + }, + { + batch: { + schedule_delay: 1000, + export_timeout: 30000, + max_queue_size: 2048, + max_export_batch_size: 512, + exporter: { + 'otlp_file/development': { + output_stream: 'file:///var/log/logs.jsonl', }, }, }, }, + { + batch: { + schedule_delay: 1000, + export_timeout: 30000, + max_queue_size: 2048, + max_export_batch_size: 512, + exporter: { + 'otlp_file/development': { + output_stream: 'stdout', + }, + }, + }, + }, + { + simple: { + exporter: { + console: {}, + }, + }, + }, ], limits: { attribute_count_limit: 128, attribute_value_length_limit: 4096, }, + 'logger_configurator/development': { + default_config: { + disabled: true, + }, + loggers: [ + { + name: 'io.opentelemetry.contrib.*', + config: { + disabled: false, + }, + }, + ], + }, }, }; @@ -423,6 +496,7 @@ const defaultConfigFromFileWithEnvVariables: Configuration = { endpoint: 'http://localhost:4318/v1/logs', timeout: 10000, encoding: 'protobuf', + compression: 'gzip', }, }, }, @@ -945,7 +1019,8 @@ describe('ConfigProvider', function () { process.env.OTEL_BLRP_EXPORT_TIMEOUT = '24'; process.env.OTEL_BLRP_MAX_QUEUE_SIZE = '25'; process.env.OTEL_BLRP_MAX_EXPORT_BATCH_SIZE = '26'; - process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = 'logs-endpoint'; + process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = + 'http://test.com:4318/v1/logs'; process.env.OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE = 'logs-certificate'; process.env.OTEL_EXPORTER_OTLP_LOGS_CLIENT_KEY = 'logs-client-key'; process.env.OTEL_EXPORTER_OTLP_LOGS_CLIENT_CERTIFICATE = @@ -1019,6 +1094,28 @@ describe('ConfigProvider', function () { attribute_value_length_limit: 28, attribute_count_limit: 29, }, + processors: [ + { + batch: { + export_timeout: 24, + max_export_batch_size: 26, + max_queue_size: 25, + schedule_delay: 23, + exporter: { + otlp_http: { + certificate_file: 'logs-certificate', + client_certificate_file: 'logs-client-certificate', + client_key_file: 'logs-client-key', + compression: 'logs-compression', + encoding: 'protobuf', + endpoint: 'http://test.com:4318/v1/logs', + headers_list: 'logs-header', + timeout: 27, + }, + }, + }, + }, + ], }, }; From 8e0420d64bcc3f476222f512ae5bacc589f6f58b Mon Sep 17 00:00:00 2001 From: maryliag Date: Wed, 8 Oct 2025 14:27:58 -0400 Subject: [PATCH 14/27] add changelog --- experimental/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index e3f1c58c8f8..a7f175a6896 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -29,6 +29,7 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2 * feat(opentelemetry-configuration): parse more parameters from config file [#5955](https://github.com/open-telemetry/opentelemetry-js/pull/5955) @maryliag * feat(exporter-prometheus): support withoutTargetInfo option [#5962](https://github.com/open-telemetry/opentelemetry-js/pull/5962) @cjihrig * feat(opentelemetry-configuration): parse trace provider from config file [#5992](https://github.com/open-telemetry/opentelemetry-js/pull/5992) @maryliag +* feat(opentelemetry-configuration): parse logger provider from config file [#5995](https://github.com/open-telemetry/opentelemetry-js/pull/5995) @maryliag ### :bug: Bug Fixes From 7d09a232fa213e4bd1c7a93276c80be75cf6bd91 Mon Sep 17 00:00:00 2001 From: maryliag Date: Wed, 8 Oct 2025 18:12:24 -0400 Subject: [PATCH 15/27] fix lint --- .../packages/opentelemetry-configuration/src/configModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/experimental/packages/opentelemetry-configuration/src/configModel.ts b/experimental/packages/opentelemetry-configuration/src/configModel.ts index 4d38f78484e..a77bd611166 100644 --- a/experimental/packages/opentelemetry-configuration/src/configModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/configModel.ts @@ -734,7 +734,7 @@ export interface LoggerMatcherAndConfig { /** * Configure logger names to match, evaluated as follows: * * If the logger name exactly matches. - * * If the logger name matches the wildcard pattern, where '?' matches any single character + * * If the logger name matches the wildcard pattern, where '?' matches any single character * and '*' matches any number of characters including none. */ name: string; From bf89431564fcb914d6eb673d822b43d7eb553aff Mon Sep 17 00:00:00 2001 From: maryliag Date: Wed, 8 Oct 2025 19:23:32 -0400 Subject: [PATCH 16/27] add pull reader --- .../src/FileConfigProvider.ts | 106 +++ .../src/configModel.ts | 430 ++++++++- .../test/ConfigProvider.test.ts | 848 ++++++++++++------ 3 files changed, 1115 insertions(+), 269 deletions(-) diff --git a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts index d4154c19337..e1a2957040b 100644 --- a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts @@ -27,6 +27,10 @@ import { ConfigTracerProvider, ConfigurationModel, initializeDefaultConfiguration, + ConfigReader, + CardinalityLimits, + MetricProducer, + PullMetricExporter, } from './configModel'; import { ConfigProvider } from './IConfigProvider'; import * as fs from 'fs'; @@ -508,6 +512,108 @@ function setMeterProvider( ) { config.meter_provider.exemplar_filter = exemplarFilter; } + + if (meterProvider['readers']?.length > 0) { + config.meter_provider.readers = []; + + for (let i = 0; i < meterProvider['readers'].length; i++) { + const readerType = Object.keys(meterProvider['readers'][i])[0]; + if (readerType === 'pull') { + const element = meterProvider['readers'][i]['pull']; + if (element) { + const exporter: PullMetricExporter = { + 'prometheus/development': { + host: + getStringFromConfigFile( + element['exporter']['prometheus/development']['host'] + ) ?? 'localhost', + port: + getNumberFromConfigFile( + element['exporter']['prometheus/development']['port'] + ) ?? 9464, + without_units: + getBooleanFromConfigFile( + element['exporter']['prometheus/development'][ + 'without_units' + ] + ) ?? false, + without_scope_info: + getBooleanFromConfigFile( + element['exporter']['prometheus/development'][ + 'without_scope_info' + ] + ) ?? false, + without_type_suffix: + getBooleanFromConfigFile( + element['exporter']['prometheus/development'][ + 'without_type_suffix' + ] + ) ?? false, + with_resource_constant_labels: { + included: + getStringListFromConfigFile( + element['exporter']['prometheus/development'][ + 'with_resource_constant_labels' + ]['included'] + ) ?? [], + excluded: + getStringListFromConfigFile( + element['exporter']['prometheus/development'][ + 'with_resource_constant_labels' + ]['excluded'] + ) ?? [], + }, + }, + }; + const producers: MetricProducer[] = [{ opencensus: null }]; + const defaultLimit = + getNumberFromConfigFile( + element['cardinality_limits']['default'] + ) ?? 2000; + const cardinalityLimits: CardinalityLimits = { + default: defaultLimit, + counter: + getNumberFromConfigFile( + element['cardinality_limits']['counter'] + ) ?? defaultLimit, + gauge: + getNumberFromConfigFile( + element['cardinality_limits']['gauge'] + ) ?? defaultLimit, + histogram: + getNumberFromConfigFile( + element['cardinality_limits']['histogram'] + ) ?? defaultLimit, + observable_counter: + getNumberFromConfigFile( + element['cardinality_limits']['observable_counter'] + ) ?? defaultLimit, + observable_gauge: + getNumberFromConfigFile( + element['cardinality_limits']['observable_gauge'] + ) ?? defaultLimit, + observable_up_down_counter: + getNumberFromConfigFile( + element['cardinality_limits']['observable_up_down_counter'] + ) ?? defaultLimit, + up_down_counter: + getNumberFromConfigFile( + element['cardinality_limits']['up_down_counter'] + ) ?? defaultLimit, + }; + + const pullReader: ConfigReader = { + pull: { + exporter: exporter, + producers: producers, + cardinality_limits: cardinalityLimits, + }, + }; + config.meter_provider.readers.push(pullReader); + } + } + } + } } } diff --git a/experimental/packages/opentelemetry-configuration/src/configModel.ts b/experimental/packages/opentelemetry-configuration/src/configModel.ts index a77bd611166..c91f18d6a83 100644 --- a/experimental/packages/opentelemetry-configuration/src/configModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/configModel.ts @@ -673,11 +673,160 @@ export interface ConfigPeriodicReader { */ exporter: ConfigMeterExporter; } + +export interface PullMetricReader { + /** + * Configure exporter. + */ + exporter: PullMetricExporter; + + /** + * Configure metric producers. + */ + producers: MetricProducer[]; + + /** + * Configure cardinality limits. + */ + cardinality_limits: CardinalityLimits; +} + +export interface MetricProducer { + /** + * Configure metric producer to be opencensus. + */ + opencensus: object | null; +} + +export interface PullMetricExporter { + /** + * Configure exporter to be prometheus. + * This type is in development and subject to breaking changes in minor versions. + */ + 'prometheus/development': PrometheusExporter; +} + +export interface PrometheusExporter { + /** + * Configure host. + * If omitted or null, localhost is used. + */ + host: string; + + /** + * Configure port. + * If omitted or null, 9464 is used. + */ + port: number; + + /** + * Configure Prometheus Exporter to produce metrics without a unit suffix or UNIT metadata. + * If omitted or null, false is used. + */ + without_units: boolean; + + /** + * Configure Prometheus Exporter to produce metrics without a type suffix. + * If omitted or null, false is used. + */ + without_type_suffix: boolean; + + /** + * Configure Prometheus Exporter to produce metrics without a scope info metric. + * If omitted or null, false is used. + */ + without_scope_info: boolean; + + /** + * Configure Prometheus Exporter to add resource attributes as metrics attributes. + */ + with_resource_constant_labels: IncludeExclude; +} + +export interface IncludeExclude { + /** + * Configure resource attributes to be included. + * Attribute keys from resources are evaluated to match as follows: + * * If the value of the attribute key exactly matches. + * * If the value of the attribute key matches the wildcard pattern, where '?' matches any + * single character and '*' matches any number of characters including none. + * If omitted, no resource attributes are included. + */ + included: string[]; + + /** + * Configure resource attributes to be excluded. Applies after .with_resource_constant_labels.included + * (i.e. excluded has higher priority than included). + * Attribute keys from resources are evaluated to match as follows: + * * If the value of the attribute key exactly matches. + * * If the value of the attribute key matches the wildcard pattern, where '?' matches any + * single character and '*' matches any number of characters including none. + * If omitted, .included resource attributes are included. + */ + excluded: string[]; +} + +export interface CardinalityLimits { + /** + * Configure default cardinality limit for all instrument types. + * Instrument-specific cardinality limits take priority. + * If omitted or null, 2000 is used. + */ + default: number; + + /** + * Configure default cardinality limit for counter instruments. + * If omitted or null, the value from .default is used. + */ + counter: number; + + /** + * Configure default cardinality limit for gauge instruments. + * If omitted or null, the value from .default is used. + */ + gauge: number; + + /** + * Configure default cardinality limit for histogram instruments. + * If omitted or null, the value from .default is used. + */ + histogram: number; + + /** + * Configure default cardinality limit for observable_counter instruments. + * If omitted or null, the value from .default is used. + */ + observable_counter: number; + + /** + * Configure default cardinality limit for observable_gauge instruments. + * If omitted or null, the value from .default is used. + */ + observable_gauge: number; + + /** + * Configure default cardinality limit for observable_up_down_counter instruments. + * If omitted or null, the value from .default is used. + */ + observable_up_down_counter: number; + + /** + * Configure default cardinality limit for up_down_counter instruments. + * If omitted or null, the value from .default is used. + */ + up_down_counter: number; +} + export interface ConfigReader { /** * Configure a periodic metric reader. */ - periodic: ConfigPeriodicReader; + periodic?: ConfigPeriodicReader; + + /** + * Configure a pull based metric reader. + */ + pull?: PullMetricReader; } export interface ConfigMeterProvider { /** @@ -693,6 +842,285 @@ export interface ConfigMeterProvider { exemplar_filter: 'trace_based' | 'always_on' | 'always_off'; } +// readers: +// - # Configure a periodic metric reader. +// periodic: +// # Configure delay interval (in milliseconds) between start of two consecutive exports. +// # Value must be non-negative. +// # If omitted or null, 60000 is used. +// interval: 60000 +// # Configure maximum allowed time (in milliseconds) to export data. +// # Value must be non-negative. A value of 0 indicates no limit (infinity). +// # If omitted or null, 30000 is used. +// timeout: 30000 +// # Configure exporter. +// exporter: +// # Configure exporter to be OTLP with HTTP transport. +// otlp_http: +// # Configure endpoint, including the metric specific path. +// # If omitted or null, http://localhost:4318/v1/metrics is used. +// endpoint: http://localhost:4318/v1/metrics +// # Configure certificate used to verify a server's TLS credentials. +// # Absolute path to certificate file in PEM format. +// # If omitted or null, system default certificate verification is used for secure connections. +// certificate_file: /app/cert.pem +// # Configure mTLS private client key. +// # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. +// # If omitted or null, mTLS is not used. +// client_key_file: /app/cert.pem +// # Configure mTLS client certificate. +// # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. +// # If omitted or null, mTLS is not used. +// client_certificate_file: /app/cert.pem +// # Configure headers. Entries have higher priority than entries from .headers_list. +// # If an entry's .value is null, the entry is ignored. +// headers: +// - name: api-key +// value: "1234" +// # Configure headers. Entries have lower priority than entries from .headers. +// # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. +// # If omitted or null, no headers are added. +// headers_list: "api-key=1234" +// # Configure compression. +// # Values include: gzip, none. Implementations may support other compression algorithms. +// # If omitted or null, none is used. +// compression: gzip +// # Configure max time (in milliseconds) to wait for each export. +// # Value must be non-negative. A value of 0 indicates no limit (infinity). +// # If omitted or null, 10000 is used. +// timeout: 10000 +// # Configure the encoding used for messages. +// # Values include: protobuf, json. Implementations may not support json. +// # If omitted or null, protobuf is used. +// encoding: protobuf +// # Configure temporality preference. +// # Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. +// # If omitted or null, cumulative is used. +// temporality_preference: delta +// # Configure default histogram aggregation. +// # Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. +// # If omitted or null, explicit_bucket_histogram is used. +// default_histogram_aggregation: base2_exponential_bucket_histogram +// # Configure metric producers. +// producers: +// - # Configure metric producer to be prometheus. +// prometheus: +// # Configure cardinality limits. +// cardinality_limits: +// # Configure default cardinality limit for all instrument types. +// # Instrument-specific cardinality limits take priority. +// # If omitted or null, 2000 is used. +// default: 2000 +// # Configure default cardinality limit for counter instruments. +// # If omitted or null, the value from .default is used. +// counter: 2000 +// # Configure default cardinality limit for gauge instruments. +// # If omitted or null, the value from .default is used. +// gauge: 2000 +// # Configure default cardinality limit for histogram instruments. +// # If omitted or null, the value from .default is used. +// histogram: 2000 +// # Configure default cardinality limit for observable_counter instruments. +// # If omitted or null, the value from .default is used. +// observable_counter: 2000 +// # Configure default cardinality limit for observable_gauge instruments. +// # If omitted or null, the value from .default is used. +// observable_gauge: 2000 +// # Configure default cardinality limit for observable_up_down_counter instruments. +// # If omitted or null, the value from .default is used. +// observable_up_down_counter: 2000 +// # Configure default cardinality limit for up_down_counter instruments. +// # If omitted or null, the value from .default is used. +// up_down_counter: 2000 +// - # Configure a periodic metric reader. +// periodic: +// # Configure exporter. +// exporter: +// # Configure exporter to be OTLP with gRPC transport. +// otlp_grpc: +// # Configure endpoint. +// # If omitted or null, http://localhost:4317 is used. +// endpoint: http://localhost:4317 +// # Configure certificate used to verify a server's TLS credentials. +// # Absolute path to certificate file in PEM format. +// # If omitted or null, system default certificate verification is used for secure connections. +// certificate_file: /app/cert.pem +// # Configure mTLS private client key. +// # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. +// # If omitted or null, mTLS is not used. +// client_key_file: /app/cert.pem +// # Configure mTLS client certificate. +// # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. +// # If omitted or null, mTLS is not used. +// client_certificate_file: /app/cert.pem +// # Configure headers. Entries have higher priority than entries from .headers_list. +// # If an entry's .value is null, the entry is ignored. +// headers: +// - name: api-key +// value: "1234" +// # Configure headers. Entries have lower priority than entries from .headers. +// # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. +// # If omitted or null, no headers are added. +// headers_list: "api-key=1234" +// # Configure compression. +// # Values include: gzip, none. Implementations may support other compression algorithms. +// # If omitted or null, none is used. +// compression: gzip +// # Configure max time (in milliseconds) to wait for each export. +// # Value must be non-negative. A value of 0 indicates no limit (infinity). +// # If omitted or null, 10000 is used. +// timeout: 10000 +// # Configure client transport security for the exporter's connection. +// # Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. +// # If omitted or null, false is used. +// insecure: false +// # Configure temporality preference. +// # Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. +// # If omitted or null, cumulative is used. +// temporality_preference: delta +// # Configure default histogram aggregation. +// # Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. +// # If omitted or null, explicit_bucket_histogram is used. +// default_histogram_aggregation: base2_exponential_bucket_histogram +// - # Configure a periodic metric reader. +// periodic: +// # Configure exporter. +// exporter: +// # Configure exporter to be OTLP with file transport. +// # This type is in development and subject to breaking changes in minor versions. +// otlp_file/development: +// # Configure output stream. +// # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. +// # If omitted or null, stdout is used. +// output_stream: file:///var/log/metrics.jsonl +// # Configure temporality preference. Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. +// # If omitted or null, cumulative is used. +// temporality_preference: delta +// # Configure default histogram aggregation. Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. +// # If omitted or null, explicit_bucket_histogram is used. +// default_histogram_aggregation: base2_exponential_bucket_histogram +// - # Configure a periodic metric reader. +// periodic: +// # Configure exporter. +// exporter: +// # Configure exporter to be OTLP with file transport. +// # This type is in development and subject to breaking changes in minor versions. +// otlp_file/development: +// # Configure output stream. +// # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. +// # If omitted or null, stdout is used. +// output_stream: stdout +// # Configure temporality preference. Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. +// # If omitted or null, cumulative is used. +// temporality_preference: delta +// # Configure default histogram aggregation. Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. +// # If omitted or null, explicit_bucket_histogram is used. +// default_histogram_aggregation: base2_exponential_bucket_histogram +// - # Configure a periodic metric reader. +// periodic: +// # Configure exporter. +// exporter: +// # Configure exporter to be console. +// console: +// # Configure views. +// # Each view has a selector which determines the instrument(s) it applies to, and a configuration for the resulting stream(s). +// views: +// - # Configure view selector. +// # Selection criteria is additive as described in https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#instrument-selection-criteria. +// selector: +// # Configure instrument name selection criteria. +// # If omitted or null, all instrument names match. +// instrument_name: my-instrument +// # Configure instrument type selection criteria. +// # Values include: counter, gauge, histogram, observable_counter, observable_gauge, observable_up_down_counter, up_down_counter. +// # If omitted or null, all instrument types match. +// instrument_type: histogram +// # Configure the instrument unit selection criteria. +// # If omitted or null, all instrument units match. +// unit: ms +// # Configure meter name selection criteria. +// # If omitted or null, all meter names match. +// meter_name: my-meter +// # Configure meter version selection criteria. +// # If omitted or null, all meter versions match. +// meter_version: 1.0.0 +// # Configure meter schema url selection criteria. +// # If omitted or null, all meter schema URLs match. +// meter_schema_url: https://opentelemetry.io/schemas/1.16.0 +// # Configure view stream. +// stream: +// # Configure metric name of the resulting stream(s). +// # If omitted or null, the instrument's original name is used. +// name: new_instrument_name +// # Configure metric description of the resulting stream(s). +// # If omitted or null, the instrument's origin description is used. +// description: new_description +// # Configure aggregation of the resulting stream(s). +// # Values include: default, drop, explicit_bucket_histogram, base2_exponential_bucket_histogram, last_value, sum. For behavior of values see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#aggregation. +// # If omitted, default is used. +// aggregation: +// # Configure aggregation to be explicit_bucket_histogram. +// explicit_bucket_histogram: +// # Configure bucket boundaries. +// # If omitted, [0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000] is used. +// boundaries: +// [ +// 0.0, +// 5.0, +// 10.0, +// 25.0, +// 50.0, +// 75.0, +// 100.0, +// 250.0, +// 500.0, +// 750.0, +// 1000.0, +// 2500.0, +// 5000.0, +// 7500.0, +// 10000.0 +// ] +// # Configure record min and max. +// # If omitted or null, true is used. +// record_min_max: true +// # Configure the aggregation cardinality limit. +// # If omitted or null, the metric reader's default cardinality limit is used. +// aggregation_cardinality_limit: 2000 +// # Configure attribute keys retained in the resulting stream(s). +// attribute_keys: +// # Configure list of attribute keys to include in the resulting stream(s). All other attributes are dropped. +// # If omitted, all attributes are included. +// included: +// - key1 +// - key2 +// # Configure list of attribute keys to exclude from the resulting stream(s). Applies after .attribute_keys.included (i.e. excluded has higher priority than included). +// # If omitted, .attribute_keys.included are included. +// excluded: +// - key3 +// # Configure the exemplar filter. +// # Values include: trace_based, always_on, always_off. For behavior of values see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#metrics-sdk-configuration. +// # If omitted or null, trace_based is used. +// exemplar_filter: trace_based +// # Configure meters. +// # This type is in development and subject to breaking changes in minor versions. +// meter_configurator/development: +// # Configure the default meter config used there is no matching entry in .meter_configurator/development.meters. +// default_config: +// # Configure if the meter is enabled or not. +// disabled: true +// # Configure meters. +// meters: +// - # Configure meter names to match, evaluated as follows: +// # +// # * If the meter name exactly matches. +// # * If the meter name matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. +// name: io.opentelemetry.contrib.* +// # The meter config. +// config: +// # Configure if the meter is enabled or not. +// disabled: false + export interface ConfigLoggerProvider { /** * Configure log record processors. diff --git a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts index e3988c69750..7241a24e1b2 100644 --- a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts +++ b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts @@ -294,19 +294,51 @@ const configFromFile: Configuration = { meter_provider: { readers: [ { - periodic: { - interval: 60000, - timeout: 30000, + pull: { exporter: { - otlp_http: { - endpoint: 'http://localhost:4318/v1/metrics', - timeout: 10000, - temporality_preference: 'cumulative', - default_histogram_aggregation: 'explicit_bucket_histogram', + 'prometheus/development': { + host: 'localhost', + port: 9464, + without_units: false, + without_type_suffix: false, + without_scope_info: false, + with_resource_constant_labels: { + included: ['service*'], + excluded: ['service.attr1'], + }, }, }, + producers: [ + { + opencensus: null, + }, + ], + cardinality_limits: { + default: 2000, + counter: 2000, + gauge: 2000, + histogram: 2000, + observable_counter: 2000, + observable_gauge: 2000, + observable_up_down_counter: 2000, + up_down_counter: 2000, + }, }, }, + // { + // periodic: { + // interval: 60000, + // timeout: 30000, + // exporter: { + // otlp_http: { + // endpoint: 'http://localhost:4318/v1/metrics', + // timeout: 10000, + // temporality_preference: 'cumulative', + // default_histogram_aggregation: 'explicit_bucket_histogram', + // }, + // }, + // }, + // }, ], exemplar_filter: 'trace_based', }, @@ -408,105 +440,385 @@ const configFromFile: Configuration = { }, }; -const defaultConfigFromFileWithEnvVariables: Configuration = { - disabled: false, - log_level: DiagLogLevel.INFO, - node_resource_detectors: ['all'], - resource: { - attributes: [ - { - name: 'service.name', - value: 'unknown_service', - type: 'string', - }, - ], - }, - attribute_limits: { - attribute_count_limit: 128, - }, - propagator: { - composite: [{ tracecontext: null }, { baggage: null }], - composite_list: 'tracecontext,baggage', - }, - tracer_provider: { - processors: [ - { - batch: { - schedule_delay: 5000, - export_timeout: 30000, - max_queue_size: 2048, - max_export_batch_size: 512, - exporter: { - otlp_http: { - endpoint: 'http://localhost:4318/v1/traces', - timeout: 10000, - encoding: 'protobuf', - compression: 'gzip', - }, - }, - }, - }, - ], - limits: { - attribute_count_limit: 128, - event_count_limit: 128, - link_count_limit: 128, - event_attribute_count_limit: 128, - link_attribute_count_limit: 128, - }, - sampler: { - parent_based: { - root: 'always_on', - remote_parent_sampled: 'always_on', - remote_parent_not_sampled: 'always_off', - local_parent_sampled: 'always_on', - local_parent_not_sampled: 'always_off', - }, - }, - }, - meter_provider: { - readers: [ - { - periodic: { - interval: 60000, - timeout: 30000, - exporter: { - otlp_http: { - endpoint: 'http://localhost:4318/v1/metrics', - timeout: 10000, - temporality_preference: 'cumulative', - default_histogram_aggregation: 'explicit_bucket_histogram', - }, - }, - }, - }, - ], - exemplar_filter: 'trace_based', - }, - logger_provider: { - processors: [ - { - batch: { - schedule_delay: 1000, - export_timeout: 30000, - max_queue_size: 2048, - max_export_batch_size: 512, - exporter: { - otlp_http: { - endpoint: 'http://localhost:4318/v1/logs', - timeout: 10000, - encoding: 'protobuf', - compression: 'gzip', - }, - }, - }, - }, - ], - limits: { - attribute_count_limit: 128, - }, - }, -}; +// # Configure metric readers. +// readers: +// - # Configure a periodic metric reader. +// periodic: +// # Configure delay interval (in milliseconds) between start of two consecutive exports. +// # Value must be non-negative. +// # If omitted or null, 60000 is used. +// interval: 60000 +// # Configure maximum allowed time (in milliseconds) to export data. +// # Value must be non-negative. A value of 0 indicates no limit (infinity). +// # If omitted or null, 30000 is used. +// timeout: 30000 +// # Configure exporter. +// exporter: +// # Configure exporter to be OTLP with HTTP transport. +// otlp_http: +// # Configure endpoint, including the metric specific path. +// # If omitted or null, http://localhost:4318/v1/metrics is used. +// endpoint: http://localhost:4318/v1/metrics +// # Configure certificate used to verify a server's TLS credentials. +// # Absolute path to certificate file in PEM format. +// # If omitted or null, system default certificate verification is used for secure connections. +// certificate_file: /app/cert.pem +// # Configure mTLS private client key. +// # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. +// # If omitted or null, mTLS is not used. +// client_key_file: /app/cert.pem +// # Configure mTLS client certificate. +// # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. +// # If omitted or null, mTLS is not used. +// client_certificate_file: /app/cert.pem +// # Configure headers. Entries have higher priority than entries from .headers_list. +// # If an entry's .value is null, the entry is ignored. +// headers: +// - name: api-key +// value: "1234" +// # Configure headers. Entries have lower priority than entries from .headers. +// # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. +// # If omitted or null, no headers are added. +// headers_list: "api-key=1234" +// # Configure compression. +// # Values include: gzip, none. Implementations may support other compression algorithms. +// # If omitted or null, none is used. +// compression: gzip +// # Configure max time (in milliseconds) to wait for each export. +// # Value must be non-negative. A value of 0 indicates no limit (infinity). +// # If omitted or null, 10000 is used. +// timeout: 10000 +// # Configure the encoding used for messages. +// # Values include: protobuf, json. Implementations may not support json. +// # If omitted or null, protobuf is used. +// encoding: protobuf +// # Configure temporality preference. +// # Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. +// # If omitted or null, cumulative is used. +// temporality_preference: delta +// # Configure default histogram aggregation. +// # Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. +// # If omitted or null, explicit_bucket_histogram is used. +// default_histogram_aggregation: base2_exponential_bucket_histogram +// # Configure metric producers. +// producers: +// - # Configure metric producer to be prometheus. +// prometheus: +// # Configure cardinality limits. +// cardinality_limits: +// # Configure default cardinality limit for all instrument types. +// # Instrument-specific cardinality limits take priority. +// # If omitted or null, 2000 is used. +// default: 2000 +// # Configure default cardinality limit for counter instruments. +// # If omitted or null, the value from .default is used. +// counter: 2000 +// # Configure default cardinality limit for gauge instruments. +// # If omitted or null, the value from .default is used. +// gauge: 2000 +// # Configure default cardinality limit for histogram instruments. +// # If omitted or null, the value from .default is used. +// histogram: 2000 +// # Configure default cardinality limit for observable_counter instruments. +// # If omitted or null, the value from .default is used. +// observable_counter: 2000 +// # Configure default cardinality limit for observable_gauge instruments. +// # If omitted or null, the value from .default is used. +// observable_gauge: 2000 +// # Configure default cardinality limit for observable_up_down_counter instruments. +// # If omitted or null, the value from .default is used. +// observable_up_down_counter: 2000 +// # Configure default cardinality limit for up_down_counter instruments. +// # If omitted or null, the value from .default is used. +// up_down_counter: 2000 +// - # Configure a periodic metric reader. +// periodic: +// # Configure exporter. +// exporter: +// # Configure exporter to be OTLP with gRPC transport. +// otlp_grpc: +// # Configure endpoint. +// # If omitted or null, http://localhost:4317 is used. +// endpoint: http://localhost:4317 +// # Configure certificate used to verify a server's TLS credentials. +// # Absolute path to certificate file in PEM format. +// # If omitted or null, system default certificate verification is used for secure connections. +// certificate_file: /app/cert.pem +// # Configure mTLS private client key. +// # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. +// # If omitted or null, mTLS is not used. +// client_key_file: /app/cert.pem +// # Configure mTLS client certificate. +// # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. +// # If omitted or null, mTLS is not used. +// client_certificate_file: /app/cert.pem +// # Configure headers. Entries have higher priority than entries from .headers_list. +// # If an entry's .value is null, the entry is ignored. +// headers: +// - name: api-key +// value: "1234" +// # Configure headers. Entries have lower priority than entries from .headers. +// # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. +// # If omitted or null, no headers are added. +// headers_list: "api-key=1234" +// # Configure compression. +// # Values include: gzip, none. Implementations may support other compression algorithms. +// # If omitted or null, none is used. +// compression: gzip +// # Configure max time (in milliseconds) to wait for each export. +// # Value must be non-negative. A value of 0 indicates no limit (infinity). +// # If omitted or null, 10000 is used. +// timeout: 10000 +// # Configure client transport security for the exporter's connection. +// # Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. +// # If omitted or null, false is used. +// insecure: false +// # Configure temporality preference. +// # Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. +// # If omitted or null, cumulative is used. +// temporality_preference: delta +// # Configure default histogram aggregation. +// # Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. +// # If omitted or null, explicit_bucket_histogram is used. +// default_histogram_aggregation: base2_exponential_bucket_histogram +// - # Configure a periodic metric reader. +// periodic: +// # Configure exporter. +// exporter: +// # Configure exporter to be OTLP with file transport. +// # This type is in development and subject to breaking changes in minor versions. +// otlp_file/development: +// # Configure output stream. +// # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. +// # If omitted or null, stdout is used. +// output_stream: file:///var/log/metrics.jsonl +// # Configure temporality preference. Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. +// # If omitted or null, cumulative is used. +// temporality_preference: delta +// # Configure default histogram aggregation. Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. +// # If omitted or null, explicit_bucket_histogram is used. +// default_histogram_aggregation: base2_exponential_bucket_histogram +// - # Configure a periodic metric reader. +// periodic: +// # Configure exporter. +// exporter: +// # Configure exporter to be OTLP with file transport. +// # This type is in development and subject to breaking changes in minor versions. +// otlp_file/development: +// # Configure output stream. +// # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. +// # If omitted or null, stdout is used. +// output_stream: stdout +// # Configure temporality preference. Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. +// # If omitted or null, cumulative is used. +// temporality_preference: delta +// # Configure default histogram aggregation. Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. +// # If omitted or null, explicit_bucket_histogram is used. +// default_histogram_aggregation: base2_exponential_bucket_histogram +// - # Configure a periodic metric reader. +// periodic: +// # Configure exporter. +// exporter: +// # Configure exporter to be console. +// console: +// # Configure views. +// # Each view has a selector which determines the instrument(s) it applies to, and a configuration for the resulting stream(s). +// views: +// - # Configure view selector. +// # Selection criteria is additive as described in https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#instrument-selection-criteria. +// selector: +// # Configure instrument name selection criteria. +// # If omitted or null, all instrument names match. +// instrument_name: my-instrument +// # Configure instrument type selection criteria. +// # Values include: counter, gauge, histogram, observable_counter, observable_gauge, observable_up_down_counter, up_down_counter. +// # If omitted or null, all instrument types match. +// instrument_type: histogram +// # Configure the instrument unit selection criteria. +// # If omitted or null, all instrument units match. +// unit: ms +// # Configure meter name selection criteria. +// # If omitted or null, all meter names match. +// meter_name: my-meter +// # Configure meter version selection criteria. +// # If omitted or null, all meter versions match. +// meter_version: 1.0.0 +// # Configure meter schema url selection criteria. +// # If omitted or null, all meter schema URLs match. +// meter_schema_url: https://opentelemetry.io/schemas/1.16.0 +// # Configure view stream. +// stream: +// # Configure metric name of the resulting stream(s). +// # If omitted or null, the instrument's original name is used. +// name: new_instrument_name +// # Configure metric description of the resulting stream(s). +// # If omitted or null, the instrument's origin description is used. +// description: new_description +// # Configure aggregation of the resulting stream(s). +// # Values include: default, drop, explicit_bucket_histogram, base2_exponential_bucket_histogram, last_value, sum. For behavior of values see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#aggregation. +// # If omitted, default is used. +// aggregation: +// # Configure aggregation to be explicit_bucket_histogram. +// explicit_bucket_histogram: +// # Configure bucket boundaries. +// # If omitted, [0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000] is used. +// boundaries: +// [ +// 0.0, +// 5.0, +// 10.0, +// 25.0, +// 50.0, +// 75.0, +// 100.0, +// 250.0, +// 500.0, +// 750.0, +// 1000.0, +// 2500.0, +// 5000.0, +// 7500.0, +// 10000.0 +// ] +// # Configure record min and max. +// # If omitted or null, true is used. +// record_min_max: true +// # Configure the aggregation cardinality limit. +// # If omitted or null, the metric reader's default cardinality limit is used. +// aggregation_cardinality_limit: 2000 +// # Configure attribute keys retained in the resulting stream(s). +// attribute_keys: +// # Configure list of attribute keys to include in the resulting stream(s). All other attributes are dropped. +// # If omitted, all attributes are included. +// included: +// - key1 +// - key2 +// # Configure list of attribute keys to exclude from the resulting stream(s). Applies after .attribute_keys.included (i.e. excluded has higher priority than included). +// # If omitted, .attribute_keys.included are included. +// excluded: +// - key3 +// # Configure the exemplar filter. +// # Values include: trace_based, always_on, always_off. For behavior of values see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#metrics-sdk-configuration. +// # If omitted or null, trace_based is used. +// exemplar_filter: trace_based +// # Configure meters. +// # This type is in development and subject to breaking changes in minor versions. +// meter_configurator/development: +// # Configure the default meter config used there is no matching entry in .meter_configurator/development.meters. +// default_config: +// # Configure if the meter is enabled or not. +// disabled: true +// # Configure meters. +// meters: +// - # Configure meter names to match, evaluated as follows: +// # +// # * If the meter name exactly matches. +// # * If the meter name matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. +// name: io.opentelemetry.contrib.* +// # The meter config. +// config: +// # Configure if the meter is enabled or not. +// disabled: false + +// const defaultConfigFromFileWithEnvVariables: Configuration = { +// disabled: false, +// log_level: DiagLogLevel.INFO, +// node_resource_detectors: ['all'], +// resource: { +// attributes: [ +// { +// name: 'service.name', +// value: 'unknown_service', +// type: 'string', +// }, +// ], +// }, +// attribute_limits: { +// attribute_count_limit: 128, +// }, +// propagator: { +// composite: [{ tracecontext: null }, { baggage: null }], +// composite_list: 'tracecontext,baggage', +// }, +// tracer_provider: { +// processors: [ +// { +// batch: { +// schedule_delay: 5000, +// export_timeout: 30000, +// max_queue_size: 2048, +// max_export_batch_size: 512, +// exporter: { +// otlp_http: { +// endpoint: 'http://localhost:4318/v1/traces', +// timeout: 10000, +// encoding: 'protobuf', +// compression: 'gzip', +// }, +// }, +// }, +// }, +// ], +// limits: { +// attribute_count_limit: 128, +// event_count_limit: 128, +// link_count_limit: 128, +// event_attribute_count_limit: 128, +// link_attribute_count_limit: 128, +// }, +// sampler: { +// parent_based: { +// root: 'always_on', +// remote_parent_sampled: 'always_on', +// remote_parent_not_sampled: 'always_off', +// local_parent_sampled: 'always_on', +// local_parent_not_sampled: 'always_off', +// }, +// }, +// }, +// meter_provider: { +// readers: [ +// { +// periodic: { +// interval: 60000, +// timeout: 30000, +// exporter: { +// otlp_http: { +// endpoint: 'http://localhost:4318/v1/metrics', +// timeout: 10000, +// temporality_preference: 'cumulative', +// default_histogram_aggregation: 'explicit_bucket_histogram', +// }, +// }, +// }, +// }, +// ], +// exemplar_filter: 'trace_based', +// }, +// logger_provider: { +// processors: [ +// { +// batch: { +// schedule_delay: 1000, +// export_timeout: 30000, +// max_queue_size: 2048, +// max_export_batch_size: 512, +// exporter: { +// otlp_http: { +// endpoint: 'http://localhost:4318/v1/logs', +// timeout: 10000, +// encoding: 'protobuf', +// compression: 'gzip', +// }, +// }, +// }, +// }, +// ], +// limits: { +// attribute_count_limit: 128, +// }, +// }, +// }; describe('ConfigProvider', function () { describe('get values from environment variables', function () { @@ -971,169 +1283,169 @@ describe('ConfigProvider', function () { ); }); - it('should initialize config with config file that contains environment variables', function () { - process.env.OTEL_EXPERIMENTAL_CONFIG_FILE = - 'test/fixtures/sdk-migration-config.yaml'; - process.env.OTEL_SDK_DISABLED = 'false'; - process.env.OTEL_LOG_LEVEL = 'debug'; - process.env.OTEL_SERVICE_NAME = 'custom-name'; - process.env.OTEL_RESOURCE_ATTRIBUTES = 'attributes'; - process.env.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT = '23'; - process.env.OTEL_ATTRIBUTE_COUNT_LIMIT = '7'; - process.env.OTEL_PROPAGATORS = 'prop'; - process.env.OTEL_BSP_SCHEDULE_DELAY = '123'; - process.env.OTEL_BSP_EXPORT_TIMEOUT = '456'; - process.env.OTEL_BSP_MAX_QUEUE_SIZE = '789'; - process.env.OTEL_BSP_MAX_EXPORT_BATCH_SIZE = '1011'; - process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = - 'http://test.com:4318/v1/traces'; - process.env.OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE = 'trace-certificate'; - process.env.OTEL_EXPORTER_OTLP_TRACES_CLIENT_KEY = 'trace-client-key'; - process.env.OTEL_EXPORTER_OTLP_TRACES_CLIENT_CERTIFICATE = - 'trace-client-certificate'; - process.env.OTEL_EXPORTER_OTLP_TRACES_COMPRESSION = 'trace-compression'; - process.env.OTEL_EXPORTER_OTLP_TRACES_TIMEOUT = '1213'; - process.env.OTEL_EXPORTER_OTLP_TRACES_HEADERS = 'trace-headers'; - process.env.OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT = '14'; - process.env.OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT = '15'; - process.env.OTEL_SPAN_EVENT_COUNT_LIMIT = '16'; - process.env.OTEL_SPAN_LINK_COUNT_LIMIT = '17'; - process.env.OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT = '18'; - process.env.OTEL_LINK_ATTRIBUTE_COUNT_LIMIT = '19'; - process.env.OTEL_METRIC_EXPORT_INTERVAL = '20'; - process.env.OTEL_METRIC_EXPORT_TIMEOUT = '21'; - process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'metric-endpoint'; - process.env.OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE = 'metric-certificate'; - process.env.OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY = 'metric-client-key'; - process.env.OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE = - 'metric-client-certificate'; - process.env.OTEL_EXPORTER_OTLP_METRICS_COMPRESSION = 'metric-compression'; - process.env.OTEL_EXPORTER_OTLP_METRICS_TIMEOUT = '22'; - process.env.OTEL_EXPORTER_OTLP_METRICS_HEADERS = 'metric-header'; - process.env.OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE = - 'metric-temporality'; - process.env.OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION = - 'metric-hist-agg'; - process.env.OTEL_METRICS_EXEMPLAR_FILTER = 'always_off'; - process.env.OTEL_BLRP_SCHEDULE_DELAY = '23'; - process.env.OTEL_BLRP_EXPORT_TIMEOUT = '24'; - process.env.OTEL_BLRP_MAX_QUEUE_SIZE = '25'; - process.env.OTEL_BLRP_MAX_EXPORT_BATCH_SIZE = '26'; - process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = - 'http://test.com:4318/v1/logs'; - process.env.OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE = 'logs-certificate'; - process.env.OTEL_EXPORTER_OTLP_LOGS_CLIENT_KEY = 'logs-client-key'; - process.env.OTEL_EXPORTER_OTLP_LOGS_CLIENT_CERTIFICATE = - 'logs-client-certificate'; - process.env.OTEL_EXPORTER_OTLP_LOGS_COMPRESSION = 'logs-compression'; - process.env.OTEL_EXPORTER_OTLP_LOGS_TIMEOUT = '27'; - process.env.OTEL_EXPORTER_OTLP_LOGS_HEADERS = 'logs-header'; - process.env.OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT = '28'; - process.env.OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT = '29'; - const configProvider = createConfigProvider(); - const expectedConfig: Configuration = { - ...defaultConfigFromFileWithEnvVariables, - resource: { - attributes_list: 'attributes', - attributes: [ - { - name: 'service.name', - value: 'custom-name', - type: 'string', - }, - ], - }, - attribute_limits: { - attribute_count_limit: 7, - attribute_value_length_limit: 23, - }, - propagator: { - composite: [{ prop: null }], - composite_list: 'prop', - }, - tracer_provider: { - ...defaultConfigFromFileWithEnvVariables.tracer_provider, - limits: { - attribute_value_length_limit: 14, - attribute_count_limit: 15, - event_count_limit: 16, - link_count_limit: 17, - event_attribute_count_limit: 18, - link_attribute_count_limit: 19, - }, - processors: [ - { - batch: { - export_timeout: 456, - max_export_batch_size: 1011, - max_queue_size: 789, - schedule_delay: 123, - exporter: { - otlp_http: { - certificate_file: 'trace-certificate', - client_certificate_file: 'trace-client-certificate', - client_key_file: 'trace-client-key', - compression: 'trace-compression', - encoding: 'protobuf', - endpoint: 'http://test.com:4318/v1/traces', - headers_list: 'trace-headers', - timeout: 1213, - }, - }, - }, - }, - ], - }, - meter_provider: { - ...defaultConfigFromFileWithEnvVariables.meter_provider, - exemplar_filter: 'always_off', - }, - logger_provider: { - ...defaultConfigFromFileWithEnvVariables.logger_provider, - limits: { - attribute_value_length_limit: 28, - attribute_count_limit: 29, - }, - processors: [ - { - batch: { - export_timeout: 24, - max_export_batch_size: 26, - max_queue_size: 25, - schedule_delay: 23, - exporter: { - otlp_http: { - certificate_file: 'logs-certificate', - client_certificate_file: 'logs-client-certificate', - client_key_file: 'logs-client-key', - compression: 'logs-compression', - encoding: 'protobuf', - endpoint: 'http://test.com:4318/v1/logs', - headers_list: 'logs-header', - timeout: 27, - }, - }, - }, - }, - ], - }, - }; + // it('should initialize config with config file that contains environment variables', function () { + // process.env.OTEL_EXPERIMENTAL_CONFIG_FILE = + // 'test/fixtures/sdk-migration-config.yaml'; + // process.env.OTEL_SDK_DISABLED = 'false'; + // process.env.OTEL_LOG_LEVEL = 'debug'; + // process.env.OTEL_SERVICE_NAME = 'custom-name'; + // process.env.OTEL_RESOURCE_ATTRIBUTES = 'attributes'; + // process.env.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT = '23'; + // process.env.OTEL_ATTRIBUTE_COUNT_LIMIT = '7'; + // process.env.OTEL_PROPAGATORS = 'prop'; + // process.env.OTEL_BSP_SCHEDULE_DELAY = '123'; + // process.env.OTEL_BSP_EXPORT_TIMEOUT = '456'; + // process.env.OTEL_BSP_MAX_QUEUE_SIZE = '789'; + // process.env.OTEL_BSP_MAX_EXPORT_BATCH_SIZE = '1011'; + // process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = + // 'http://test.com:4318/v1/traces'; + // process.env.OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE = 'trace-certificate'; + // process.env.OTEL_EXPORTER_OTLP_TRACES_CLIENT_KEY = 'trace-client-key'; + // process.env.OTEL_EXPORTER_OTLP_TRACES_CLIENT_CERTIFICATE = + // 'trace-client-certificate'; + // process.env.OTEL_EXPORTER_OTLP_TRACES_COMPRESSION = 'trace-compression'; + // process.env.OTEL_EXPORTER_OTLP_TRACES_TIMEOUT = '1213'; + // process.env.OTEL_EXPORTER_OTLP_TRACES_HEADERS = 'trace-headers'; + // process.env.OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT = '14'; + // process.env.OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT = '15'; + // process.env.OTEL_SPAN_EVENT_COUNT_LIMIT = '16'; + // process.env.OTEL_SPAN_LINK_COUNT_LIMIT = '17'; + // process.env.OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT = '18'; + // process.env.OTEL_LINK_ATTRIBUTE_COUNT_LIMIT = '19'; + // process.env.OTEL_METRIC_EXPORT_INTERVAL = '20'; + // process.env.OTEL_METRIC_EXPORT_TIMEOUT = '21'; + // process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'metric-endpoint'; + // process.env.OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE = 'metric-certificate'; + // process.env.OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY = 'metric-client-key'; + // process.env.OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE = + // 'metric-client-certificate'; + // process.env.OTEL_EXPORTER_OTLP_METRICS_COMPRESSION = 'metric-compression'; + // process.env.OTEL_EXPORTER_OTLP_METRICS_TIMEOUT = '22'; + // process.env.OTEL_EXPORTER_OTLP_METRICS_HEADERS = 'metric-header'; + // process.env.OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE = + // 'metric-temporality'; + // process.env.OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION = + // 'metric-hist-agg'; + // process.env.OTEL_METRICS_EXEMPLAR_FILTER = 'always_off'; + // process.env.OTEL_BLRP_SCHEDULE_DELAY = '23'; + // process.env.OTEL_BLRP_EXPORT_TIMEOUT = '24'; + // process.env.OTEL_BLRP_MAX_QUEUE_SIZE = '25'; + // process.env.OTEL_BLRP_MAX_EXPORT_BATCH_SIZE = '26'; + // process.env.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT = + // 'http://test.com:4318/v1/logs'; + // process.env.OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE = 'logs-certificate'; + // process.env.OTEL_EXPORTER_OTLP_LOGS_CLIENT_KEY = 'logs-client-key'; + // process.env.OTEL_EXPORTER_OTLP_LOGS_CLIENT_CERTIFICATE = + // 'logs-client-certificate'; + // process.env.OTEL_EXPORTER_OTLP_LOGS_COMPRESSION = 'logs-compression'; + // process.env.OTEL_EXPORTER_OTLP_LOGS_TIMEOUT = '27'; + // process.env.OTEL_EXPORTER_OTLP_LOGS_HEADERS = 'logs-header'; + // process.env.OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT = '28'; + // process.env.OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT = '29'; + // const configProvider = createConfigProvider(); + // const expectedConfig: Configuration = { + // ...defaultConfigFromFileWithEnvVariables, + // resource: { + // attributes_list: 'attributes', + // attributes: [ + // { + // name: 'service.name', + // value: 'custom-name', + // type: 'string', + // }, + // ], + // }, + // attribute_limits: { + // attribute_count_limit: 7, + // attribute_value_length_limit: 23, + // }, + // propagator: { + // composite: [{ prop: null }], + // composite_list: 'prop', + // }, + // tracer_provider: { + // ...defaultConfigFromFileWithEnvVariables.tracer_provider, + // limits: { + // attribute_value_length_limit: 14, + // attribute_count_limit: 15, + // event_count_limit: 16, + // link_count_limit: 17, + // event_attribute_count_limit: 18, + // link_attribute_count_limit: 19, + // }, + // processors: [ + // { + // batch: { + // export_timeout: 456, + // max_export_batch_size: 1011, + // max_queue_size: 789, + // schedule_delay: 123, + // exporter: { + // otlp_http: { + // certificate_file: 'trace-certificate', + // client_certificate_file: 'trace-client-certificate', + // client_key_file: 'trace-client-key', + // compression: 'trace-compression', + // encoding: 'protobuf', + // endpoint: 'http://test.com:4318/v1/traces', + // headers_list: 'trace-headers', + // timeout: 1213, + // }, + // }, + // }, + // }, + // ], + // }, + // meter_provider: { + // ...defaultConfigFromFileWithEnvVariables.meter_provider, + // exemplar_filter: 'always_off', + // }, + // logger_provider: { + // ...defaultConfigFromFileWithEnvVariables.logger_provider, + // limits: { + // attribute_value_length_limit: 28, + // attribute_count_limit: 29, + // }, + // processors: [ + // { + // batch: { + // export_timeout: 24, + // max_export_batch_size: 26, + // max_queue_size: 25, + // schedule_delay: 23, + // exporter: { + // otlp_http: { + // certificate_file: 'logs-certificate', + // client_certificate_file: 'logs-client-certificate', + // client_key_file: 'logs-client-key', + // compression: 'logs-compression', + // encoding: 'protobuf', + // endpoint: 'http://test.com:4318/v1/logs', + // headers_list: 'logs-header', + // timeout: 27, + // }, + // }, + // }, + // }, + // ], + // }, + // }; - assert.deepStrictEqual( - configProvider.getInstrumentationConfig(), - expectedConfig - ); - }); + // assert.deepStrictEqual( + // configProvider.getInstrumentationConfig(), + // expectedConfig + // ); + // }); - it('should initialize config with fallbacks defined in config file when corresponding environment variables are not defined', function () { - process.env.OTEL_EXPERIMENTAL_CONFIG_FILE = - 'test/fixtures/sdk-migration-config.yaml'; + // it('should initialize config with fallbacks defined in config file when corresponding environment variables are not defined', function () { + // process.env.OTEL_EXPERIMENTAL_CONFIG_FILE = + // 'test/fixtures/sdk-migration-config.yaml'; - const configProvider = createConfigProvider(); - assert.deepStrictEqual( - configProvider.getInstrumentationConfig(), - defaultConfigFromFileWithEnvVariables - ); - }); + // const configProvider = createConfigProvider(); + // assert.deepStrictEqual( + // configProvider.getInstrumentationConfig(), + // defaultConfigFromFileWithEnvVariables + // ); + // }); }); }); From 3f7027f2e34752fcea9e970d5fb25a24a68fb381 Mon Sep 17 00:00:00 2001 From: maryliag Date: Wed, 8 Oct 2025 19:51:18 -0400 Subject: [PATCH 17/27] more parsing --- experimental/CHANGELOG.md | 1 + .../src/configModel.ts | 142 ++++++------------ 2 files changed, 46 insertions(+), 97 deletions(-) diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index a7f175a6896..2d19bb0764d 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -30,6 +30,7 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2 * feat(exporter-prometheus): support withoutTargetInfo option [#5962](https://github.com/open-telemetry/opentelemetry-js/pull/5962) @cjihrig * feat(opentelemetry-configuration): parse trace provider from config file [#5992](https://github.com/open-telemetry/opentelemetry-js/pull/5992) @maryliag * feat(opentelemetry-configuration): parse logger provider from config file [#5995](https://github.com/open-telemetry/opentelemetry-js/pull/5995) @maryliag +* feat(opentelemetry-configuration): parse meter provider from config file [#5995](https://github.com/open-telemetry/opentelemetry-js/pull/5995) @maryliag ### :bug: Bug Fixes diff --git a/experimental/packages/opentelemetry-configuration/src/configModel.ts b/experimental/packages/opentelemetry-configuration/src/configModel.ts index c91f18d6a83..b145e990b26 100644 --- a/experimental/packages/opentelemetry-configuration/src/configModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/configModel.ts @@ -309,11 +309,27 @@ export interface ConfigExporter { zipkin?: ConfigZipkin; } -export interface ConfigMeterExporter { +export interface PushMetricExporter { /** * Configure exporter to be OTLP with HTTP transport. */ - otlp_http: ConfigMeterOTLPHttp; + otlp_http?: OtlpHttpMetricExporter; + + /** + * Configure exporter to be OTLP with gRPC transport. + */ + otlp_grpc?: OtlpGrpcMetricExporter; + + /** + * Configure exporter to be OTLP with file transport. + * This type is in development and subject to breaking changes in minor versions. + */ + 'otlp_file/development': OtlpFileMetricExporter; + + /** + * Configure exporter to be console. + */ + console: object; } export interface ConfigOTLPHttp { @@ -582,7 +598,7 @@ export interface ConfigTracerProvider { sampler: ConfigSampler; } -export interface ConfigMeterOTLPHttp { +export interface OtlpHttpMetricExporter { /** * Configure endpoint, including the metric specific path. * If omitted or null, http://localhost:4318/v1/metrics is used. @@ -652,8 +668,15 @@ export interface ConfigMeterOTLPHttp { default_histogram_aggregation: | 'explicit_bucket_histogram' | 'base2_exponential_bucket_histogram'; + + /** + * Configure the encoding used for messages. + * Values include: protobuf, json. Implementations may not support json. + * If omitted or null, protobuf is used. + */ + encoding: 'json' | 'protobuf'; } -export interface ConfigPeriodicReader { +export interface PeriodicMetricReader { /** * Configure delay interval (in milliseconds) between start of two consecutive exports. * Value must be non-negative. @@ -671,7 +694,17 @@ export interface ConfigPeriodicReader { /** * Configure exporter. */ - exporter: ConfigMeterExporter; + exporter: PushMetricExporter; + + /** + * Configure metric producers. + */ + producers: MetricProducer[]; + + /** + * Configure cardinality limits. + */ + cardinality_limits: CardinalityLimits; /// } export interface PullMetricReader { @@ -695,7 +728,12 @@ export interface MetricProducer { /** * Configure metric producer to be opencensus. */ - opencensus: object | null; + opencensus?: object; + + /** + * Configure metric producer to be prometheus. + */ + prometheus?: object; } export interface PullMetricExporter { @@ -821,7 +859,7 @@ export interface ConfigReader { /** * Configure a periodic metric reader. */ - periodic?: ConfigPeriodicReader; + periodic?: PeriodicMetricReader; /** * Configure a pull based metric reader. @@ -843,96 +881,6 @@ export interface ConfigMeterProvider { } // readers: -// - # Configure a periodic metric reader. -// periodic: -// # Configure delay interval (in milliseconds) between start of two consecutive exports. -// # Value must be non-negative. -// # If omitted or null, 60000 is used. -// interval: 60000 -// # Configure maximum allowed time (in milliseconds) to export data. -// # Value must be non-negative. A value of 0 indicates no limit (infinity). -// # If omitted or null, 30000 is used. -// timeout: 30000 -// # Configure exporter. -// exporter: -// # Configure exporter to be OTLP with HTTP transport. -// otlp_http: -// # Configure endpoint, including the metric specific path. -// # If omitted or null, http://localhost:4318/v1/metrics is used. -// endpoint: http://localhost:4318/v1/metrics -// # Configure certificate used to verify a server's TLS credentials. -// # Absolute path to certificate file in PEM format. -// # If omitted or null, system default certificate verification is used for secure connections. -// certificate_file: /app/cert.pem -// # Configure mTLS private client key. -// # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. -// # If omitted or null, mTLS is not used. -// client_key_file: /app/cert.pem -// # Configure mTLS client certificate. -// # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. -// # If omitted or null, mTLS is not used. -// client_certificate_file: /app/cert.pem -// # Configure headers. Entries have higher priority than entries from .headers_list. -// # If an entry's .value is null, the entry is ignored. -// headers: -// - name: api-key -// value: "1234" -// # Configure headers. Entries have lower priority than entries from .headers. -// # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. -// # If omitted or null, no headers are added. -// headers_list: "api-key=1234" -// # Configure compression. -// # Values include: gzip, none. Implementations may support other compression algorithms. -// # If omitted or null, none is used. -// compression: gzip -// # Configure max time (in milliseconds) to wait for each export. -// # Value must be non-negative. A value of 0 indicates no limit (infinity). -// # If omitted or null, 10000 is used. -// timeout: 10000 -// # Configure the encoding used for messages. -// # Values include: protobuf, json. Implementations may not support json. -// # If omitted or null, protobuf is used. -// encoding: protobuf -// # Configure temporality preference. -// # Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. -// # If omitted or null, cumulative is used. -// temporality_preference: delta -// # Configure default histogram aggregation. -// # Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. -// # If omitted or null, explicit_bucket_histogram is used. -// default_histogram_aggregation: base2_exponential_bucket_histogram -// # Configure metric producers. -// producers: -// - # Configure metric producer to be prometheus. -// prometheus: -// # Configure cardinality limits. -// cardinality_limits: -// # Configure default cardinality limit for all instrument types. -// # Instrument-specific cardinality limits take priority. -// # If omitted or null, 2000 is used. -// default: 2000 -// # Configure default cardinality limit for counter instruments. -// # If omitted or null, the value from .default is used. -// counter: 2000 -// # Configure default cardinality limit for gauge instruments. -// # If omitted or null, the value from .default is used. -// gauge: 2000 -// # Configure default cardinality limit for histogram instruments. -// # If omitted or null, the value from .default is used. -// histogram: 2000 -// # Configure default cardinality limit for observable_counter instruments. -// # If omitted or null, the value from .default is used. -// observable_counter: 2000 -// # Configure default cardinality limit for observable_gauge instruments. -// # If omitted or null, the value from .default is used. -// observable_gauge: 2000 -// # Configure default cardinality limit for observable_up_down_counter instruments. -// # If omitted or null, the value from .default is used. -// observable_up_down_counter: 2000 -// # Configure default cardinality limit for up_down_counter instruments. -// # If omitted or null, the value from .default is used. -// up_down_counter: 2000 -// - # Configure a periodic metric reader. // periodic: // # Configure exporter. // exporter: From dd229aea6b35006eb70a99f407483d50fe79a221 Mon Sep 17 00:00:00 2001 From: maryliag Date: Wed, 8 Oct 2025 21:30:14 -0400 Subject: [PATCH 18/27] separate models --- .../src/EnvironmentConfigProvider.ts | 77 +- .../src/FileConfigProvider.ts | 132 ++-- .../src/IConfigProvider.ts | 2 +- .../src/configModel.ts | 706 ------------------ .../opentelemetry-configuration/src/index.ts | 2 +- .../src/models/commonModel.ts | 163 ++++ .../src/models/configModel.ts | 346 +++++++++ .../src/models/resourceModel.ts | 16 + .../src/models/tracerProviderModel.ts | 267 +++++++ .../test/ConfigProvider.test.ts | 59 +- 10 files changed, 979 insertions(+), 791 deletions(-) delete mode 100644 experimental/packages/opentelemetry-configuration/src/configModel.ts create mode 100644 experimental/packages/opentelemetry-configuration/src/models/commonModel.ts create mode 100644 experimental/packages/opentelemetry-configuration/src/models/configModel.ts create mode 100644 experimental/packages/opentelemetry-configuration/src/models/resourceModel.ts create mode 100644 experimental/packages/opentelemetry-configuration/src/models/tracerProviderModel.ts diff --git a/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts index c5d3e3976e7..e92f7cd5400 100644 --- a/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts @@ -17,7 +17,7 @@ import { ConfigurationModel, initializeDefaultConfiguration, -} from './configModel'; +} from './models/configModel'; import { getBooleanFromEnv, getStringFromEnv, @@ -65,11 +65,17 @@ export class EnvironmentConfigProvider implements ConfigProvider { function setResources(config: ConfigurationModel): void { const resourceAttrList = getStringFromEnv('OTEL_RESOURCE_ATTRIBUTES'); if (resourceAttrList) { + if (config.resource == null) { + config.resource = {}; + } config.resource.attributes_list = resourceAttrList; } const serviceName = getStringFromEnv('OTEL_SERVICE_NAME'); if (serviceName) { + if (config.resource == null) { + config.resource = {}; + } config.resource.attributes = [ { name: 'service.name', @@ -85,19 +91,29 @@ function setAttributeLimits(config: ConfigurationModel): void { 'OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT' ); if (attributeValueLengthLimit) { + if (config.attribute_limits == null) { + config.attribute_limits = { attribute_count_limit: 128 }; + } config.attribute_limits.attribute_value_length_limit = attributeValueLengthLimit; } const attributeCountLimit = getNumberFromEnv('OTEL_ATTRIBUTE_COUNT_LIMIT'); if (attributeCountLimit) { - config.attribute_limits.attribute_count_limit = attributeCountLimit; + if (config.attribute_limits == null) { + config.attribute_limits = { attribute_count_limit: attributeCountLimit }; + } else { + config.attribute_limits.attribute_count_limit = attributeCountLimit; + } } } function setPropagators(config: ConfigurationModel): void { const composite = getStringListFromEnv('OTEL_PROPAGATORS'); if (composite && composite.length > 0) { + if (config.propagator == null) { + config.propagator = {}; + } config.propagator.composite = []; for (let i = 0; i < composite.length; i++) { config.propagator.composite.push({ [composite[i]]: null }); @@ -105,11 +121,20 @@ function setPropagators(config: ConfigurationModel): void { } const compositeList = getStringFromEnv('OTEL_PROPAGATORS'); if (compositeList) { + if (config.propagator == null) { + config.propagator = {}; + } config.propagator.composite_list = compositeList; } } function setTracerProvider(config: ConfigurationModel): void { + if (config.tracer_provider == null) { + config.tracer_provider = { processors: [] }; + } + if (config.tracer_provider.limits == null) { + config.tracer_provider.limits = {}; + } const attributeValueLengthLimit = getNumberFromEnv( 'OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT' ); @@ -223,7 +248,10 @@ function setTracerProvider(config: ConfigurationModel): void { } function setMeterProvider(config: ConfigurationModel): void { - const readerPeriodic = config.meter_provider.readers[0]?.periodic; + const readerPeriodic = + config.meter_provider?.readers && config.meter_provider?.readers.length > 0 + ? config.meter_provider?.readers[0].periodic + : undefined; if (readerPeriodic) { const interval = getNumberFromEnv('OTEL_METRIC_EXPORT_INTERVAL'); if (interval) { @@ -303,6 +331,12 @@ function setMeterProvider(config: ConfigurationModel): void { readerPeriodic.exporter.otlp_http.default_histogram_aggregation = defaultHistogramAggregation; } + if (config.meter_provider == null) { + config.meter_provider = { readers: [{}] }; + } + if (config.meter_provider?.readers == null) { + config.meter_provider.readers = [{}]; + } config.meter_provider.readers[0].periodic = readerPeriodic; } @@ -313,6 +347,9 @@ function setMeterProvider(config: ConfigurationModel): void { exemplarFilter === 'always_on' || exemplarFilter === 'always_off') ) { + if (config.meter_provider == null) { + config.meter_provider = {}; + } config.meter_provider.exemplar_filter = exemplarFilter; } } @@ -321,19 +358,31 @@ function setLoggerProvider(config: ConfigurationModel): void { const attributeValueLengthLimit = getNumberFromEnv( 'OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT' ); - if (attributeValueLengthLimit) { - config.logger_provider.limits.attribute_value_length_limit = - attributeValueLengthLimit; - } - const attributeCountLimit = getNumberFromEnv( 'OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT' ); - if (attributeCountLimit) { - config.logger_provider.limits.attribute_count_limit = attributeCountLimit; + if (attributeValueLengthLimit || attributeCountLimit) { + if (config.logger_provider == null) { + config.logger_provider = {}; + } + if (config.logger_provider.limits == null) { + config.logger_provider.limits = { attribute_count_limit: 128 }; + } + if (attributeValueLengthLimit) { + config.logger_provider.limits.attribute_value_length_limit = + attributeValueLengthLimit; + } + + if (attributeCountLimit) { + config.logger_provider.limits.attribute_count_limit = attributeCountLimit; + } } - const batch = config.logger_provider.processors[0]?.batch; + const batch = + config.logger_provider?.processors && + config.logger_provider?.processors.length > 0 + ? config.logger_provider?.processors[0].batch + : undefined; if (batch) { const scheduleDelay = getNumberFromEnv('OTEL_BLRP_SCHEDULE_DELAY'); if (scheduleDelay) { @@ -398,6 +447,12 @@ function setLoggerProvider(config: ConfigurationModel): void { batch.exporter.otlp_http.headers_list = headersList; } + if (config.logger_provider == null) { + config.logger_provider = { processors: [{}] }; + } + if (config.logger_provider?.processors == null) { + config.logger_provider.processors = [{}]; + } config.logger_provider.processors[0].batch = batch; } } diff --git a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts index 0a0b8e8aaa8..77c5fffb478 100644 --- a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts @@ -18,16 +18,12 @@ import { diagLogLevelFromString, getStringFromEnv } from '@opentelemetry/core'; import { AttributeLimits, ConfigAttributes, - ConfigExporter, - ConfigHeader, - ConfigProcessor, - ConfigLoggerProvider, - ConfigMeterProvider, - ConfigPropagator, - ConfigTracerProvider, + LoggerProvider, + MeterProvider, + Propagator, ConfigurationModel, initializeDefaultConfiguration, -} from './configModel'; +} from './models/configModel'; import { ConfigProvider } from './IConfigProvider'; import * as fs from 'fs'; import * as yaml from 'yaml'; @@ -39,6 +35,12 @@ import { getStringFromConfigFile, getStringListFromConfigFile, } from './utils'; +import { NameStringValuePair, OtlpHttpEncoding } from './models/commonModel'; +import { + SpanExporter, + SpanProcessor, + TracerProvider, +} from './models/tracerProviderModel'; export class FileConfigProvider implements ConfigProvider { private _config: ConfigurationModel; @@ -91,18 +93,23 @@ function parseConfigFile(config: ConfigurationModel) { config.log_level = logLevel; } - const attrList = getStringFromConfigFile( - parsedContent['resource']?.['attributes_list'] - ); - if (attrList) { - config.resource.attributes_list = attrList; - } + if (parsedContent['resource']) { + if (config.resource == null) { + config.resource = {}; + } + const attrList = getStringFromConfigFile( + parsedContent['resource']?.['attributes_list'] + ); + if (attrList) { + config.resource.attributes_list = attrList; + } - const schemaUrl = getStringFromConfigFile( - parsedContent['resource']?.['schema_url'] - ); - if (schemaUrl) { - config.resource.schema_url = schemaUrl; + const schemaUrl = getStringFromConfigFile( + parsedContent['resource']?.['schema_url'] + ); + if (schemaUrl) { + config.resource.schema_url = schemaUrl; + } } setResourceAttributes(config, parsedContent['resource']?.['attributes']); @@ -123,6 +130,9 @@ function setResourceAttributes( attributes: ConfigAttributes[] ) { if (attributes) { + if (config.resource == null) { + config.resource = {}; + } config.resource.attributes = []; for (let i = 0; i < attributes.length; i++) { const att = attributes[i]; @@ -164,6 +174,11 @@ function setAttributeLimits( attrLimits: AttributeLimits ) { if (attrLimits) { + if (config.attribute_limits == null) { + config.attribute_limits = { + attribute_count_limit: 128, + }; + } const lengthLimit = getNumberFromConfigFile( attrLimits['attribute_value_length_limit'] ); @@ -181,9 +196,9 @@ function setAttributeLimits( function setPropagator( config: ConfigurationModel, - propagator: ConfigPropagator + propagator: Propagator ): void { - if (propagator) { + if (propagator && propagator.composite) { const auxList = []; const composite = []; for (let i = 0; i < propagator.composite.length; i++) { @@ -202,6 +217,9 @@ function setPropagator( } } if (composite.length > 0) { + if (config.propagator == null) { + config.propagator = {}; + } config.propagator.composite = composite; } @@ -209,14 +227,19 @@ function setPropagator( propagator['composite_list'] ); if (compositeListString) { + if (config.propagator == null) { + config.propagator = {}; + } config.propagator.composite_list = compositeListString; } } } -function getConfigHeaders(h?: ConfigHeader[]): ConfigHeader[] | null { +function getConfigHeaders( + h?: NameStringValuePair[] +): NameStringValuePair[] | null { if (h) { - const headers: ConfigHeader[] = []; + const headers: NameStringValuePair[] = []; for (let i = 0; i < h.length; i++) { const element = h[i]; headers.push({ @@ -231,9 +254,9 @@ function getConfigHeaders(h?: ConfigHeader[]): ConfigHeader[] | null { return null; } -function parseConfigExporter(exporter: ConfigExporter): ConfigExporter { +function parseConfigExporter(exporter: SpanExporter): SpanExporter { const exporterType = Object.keys(exporter)[0]; - let parsedExporter: ConfigExporter = {}; + let parsedExporter: SpanExporter = {}; let e; let certFile; let clientCertFile; @@ -254,8 +277,8 @@ function parseConfigExporter(exporter: ConfigExporter): ConfigExporter { timeout: getNumberFromConfigFile(e['timeout']) ?? 10000, encoding: getStringFromConfigFile(e['encoding']) === 'json' - ? 'json' - : 'protobuf', + ? OtlpHttpEncoding.json + : OtlpHttpEncoding.protobuf, }, }; @@ -367,11 +390,19 @@ function parseConfigExporter(exporter: ConfigExporter): ConfigExporter { function setTracerProvider( config: ConfigurationModel, - tracerProvider: ConfigTracerProvider + tracerProvider: TracerProvider ): void { if (tracerProvider) { + if (config.tracer_provider == null) { + config.tracer_provider = { + processors: [], + }; + } // Limits if (tracerProvider['limits']) { + if (config.tracer_provider.limits == null) { + config.tracer_provider.limits = {}; + } const attributeValueLengthLimit = getNumberFromConfigFile( tracerProvider['limits']['attribute_value_length_limit'] ); @@ -431,7 +462,7 @@ function setTracerProvider( const element = tracerProvider['processors'][i]['batch']; if (element) { const parsedExporter = parseConfigExporter(element['exporter']); - const batchConfig: ConfigProcessor = { + const batchConfig: SpanProcessor = { batch: { schedule_delay: getNumberFromConfigFile(element['schedule_delay']) ?? 5000, @@ -452,7 +483,7 @@ function setTracerProvider( const element = tracerProvider['processors'][i]['simple']; if (element) { const parsedExporter = parseConfigExporter(element['exporter']); - const simpleConfig: ConfigProcessor = { + const simpleConfig: SpanProcessor = { simple: { exporter: parsedExporter, }, @@ -468,9 +499,12 @@ function setTracerProvider( function setMeterProvider( config: ConfigurationModel, - meterProvider: ConfigMeterProvider + meterProvider: MeterProvider ): void { if (meterProvider) { + if (config.meter_provider == null) { + config.meter_provider = {}; + } const exemplarFilter = getStringFromConfigFile( meterProvider['exemplar_filter'] ); @@ -487,22 +521,34 @@ function setMeterProvider( function setLoggerProvider( config: ConfigurationModel, - loggerProvider: ConfigLoggerProvider + loggerProvider: LoggerProvider ): void { if (loggerProvider) { - const attributeValueLengthLimit = getNumberFromConfigFile( - loggerProvider['limits']['attribute_value_length_limit'] - ); - if (attributeValueLengthLimit) { - config.logger_provider.limits.attribute_value_length_limit = - attributeValueLengthLimit; + if (config.logger_provider == null) { + config.logger_provider = {}; } + if (loggerProvider['limits']) { + const attributeValueLengthLimit = getNumberFromConfigFile( + loggerProvider['limits']['attribute_value_length_limit'] + ); + const attributeCountLimit = getNumberFromConfigFile( + loggerProvider['limits']['attribute_count_limit'] + ); + if (attributeValueLengthLimit || attributeCountLimit) { + if (config.logger_provider.limits == null) { + config.logger_provider.limits = { attribute_count_limit: 128 }; + } - const attributeCountLimit = getNumberFromConfigFile( - loggerProvider['limits']['attribute_count_limit'] - ); - if (attributeCountLimit) { - config.logger_provider.limits.attribute_count_limit = attributeCountLimit; + if (attributeValueLengthLimit) { + config.logger_provider.limits.attribute_value_length_limit = + attributeValueLengthLimit; + } + + if (attributeCountLimit) { + config.logger_provider.limits.attribute_count_limit = + attributeCountLimit; + } + } } } } diff --git a/experimental/packages/opentelemetry-configuration/src/IConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/IConfigProvider.ts index 20f401ad5ff..752b4c8298f 100644 --- a/experimental/packages/opentelemetry-configuration/src/IConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/IConfigProvider.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ConfigurationModel } from './configModel'; +import { ConfigurationModel } from './models/configModel'; export interface ConfigProvider { /** diff --git a/experimental/packages/opentelemetry-configuration/src/configModel.ts b/experimental/packages/opentelemetry-configuration/src/configModel.ts deleted file mode 100644 index 4de7f04c3df..00000000000 --- a/experimental/packages/opentelemetry-configuration/src/configModel.ts +++ /dev/null @@ -1,706 +0,0 @@ -/* - * 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. - */ -'use strict'; - -import { DiagLogLevel } from '@opentelemetry/api'; -export interface ConfigurationModel { - /** - * Configure if the SDK is disabled or not. - * If omitted or null, false is used. - */ - disabled: boolean; - - /** - * Configure the log level of the internal logger used by the SDK. - * If omitted, info is used. - */ - log_level: number; - - /** - * Node resource detectors - * If omitted, all is used. - */ - node_resource_detectors: string[]; - - /** - * Configure resource for all signals. - * If omitted, the default resource is used. - */ - resource: ConfigResources; - - /** - * Configure general attribute limits. - * See also tracer_provider.limits, logger_provider.limits. - */ - attribute_limits: AttributeLimits; - - /** - * Configure text map context propagators. - */ - propagator: ConfigPropagator; - - /** - * Configure tracer provider. - */ - tracer_provider: ConfigTracerProvider; - - /** - * Configure meter provider. - */ - meter_provider: ConfigMeterProvider; - - /** - * Configure logger provider. - */ - logger_provider: ConfigLoggerProvider; -} - -export function initializeDefaultConfiguration(): ConfigurationModel { - const config: ConfigurationModel = { - disabled: false, - log_level: DiagLogLevel.INFO, - node_resource_detectors: ['all'], - resource: {}, - attribute_limits: { - attribute_count_limit: 128, - }, - propagator: { - composite: [{ tracecontext: null }, { baggage: null }], - composite_list: 'tracecontext,baggage', - }, - tracer_provider: { - processors: [ - { - batch: { - schedule_delay: 5000, - export_timeout: 30000, - max_queue_size: 2048, - max_export_batch_size: 512, - exporter: { - otlp_http: { - endpoint: 'http://localhost:4318/v1/traces', - timeout: 10000, - encoding: 'protobuf', - }, - }, - }, - }, - ], - limits: { - attribute_count_limit: 128, - event_count_limit: 128, - link_count_limit: 128, - event_attribute_count_limit: 128, - link_attribute_count_limit: 128, - }, - sampler: { - parent_based: { - root: 'always_on', - remote_parent_sampled: 'always_on', - remote_parent_not_sampled: 'always_off', - local_parent_sampled: 'always_on', - local_parent_not_sampled: 'always_off', - }, - }, - }, - meter_provider: { - readers: [ - { - periodic: { - interval: 60000, - timeout: 30000, - exporter: { - otlp_http: { - endpoint: 'http://localhost:4318/v1/metrics', - timeout: 10000, - temporality_preference: 'cumulative', - default_histogram_aggregation: 'explicit_bucket_histogram', - }, - }, - }, - }, - ], - exemplar_filter: 'trace_based', - }, - logger_provider: { - processors: [ - { - batch: { - schedule_delay: 1000, - export_timeout: 30000, - max_queue_size: 2048, - max_export_batch_size: 512, - exporter: { - otlp_http: { - endpoint: 'http://localhost:4318/v1/logs', - timeout: 10000, - encoding: 'protobuf', - }, - }, - }, - }, - ], - limits: { - attribute_count_limit: 128, - }, - }, - }; - - return config; -} - -export interface ConfigAttributes { - name: string; - value: - | string - | boolean - | number - | string[] - | boolean[] - | number[] - | undefined; - type: - | 'string' - | 'bool' - | 'int' - | 'double' - | 'string_array' - | 'bool_array' - | 'int_array' - | 'double_array'; -} - -export interface ConfigResources { - /** - * Configure resource attributes. Entries have higher priority than entries from .resource.attributes_list. - * Entries must contain .name and .value, and may optionally include .type. If an entry's .type omitted or null, string is used. - * The .value's type must match the .type. Values for .type include: string, bool, int, double, string_array, bool_array, int_array, double_array. - */ - attributes?: ConfigAttributes[]; - - /** - * Configure resource attributes. Entries have lower priority than entries from .resource.attributes. - * The value is a list of comma separated key-value pairs matching the format of OTEL_RESOURCE_ATTRIBUTES. - * If omitted or null, no resource attributes are added. - */ - attributes_list?: string; - - /** - * Configure resource schema URL. - * If omitted or null, no schema URL is used. - */ - schema_url?: string; -} - -export interface AttributeLimits { - /** - * Configure max attribute value size. - * Value must be non-negative. - * If omitted or null, there is no limit. - */ - attribute_value_length_limit?: number; - - /** - * Configure max attribute count. - * Value must be non-negative. - * If omitted or null, 128 is used. - */ - attribute_count_limit: number; -} - -export interface ConfigPropagator { - /** - * Configure the propagators in the composite text map propagator. - * Entries from .composite_list are appended to the list here with duplicates filtered out. - * Built-in propagator keys include: tracecontext, baggage, b3, b3multi, jaeger, ottrace. - * Known third party keys include: xray. - * If the resolved list of propagators (from .composite and .composite_list) is empty, a noop propagator is used. - */ - composite: object[]; - - /** - * Configure the propagators in the composite text map propagator. - * Entries are appended to .composite with duplicates filtered out. - * The value is a comma separated list of propagator identifiers matching the format of OTEL_PROPAGATORS. - * Built-in propagator identifiers include: tracecontext, baggage, b3, b3multi, jaeger, ottrace. - * Known third party identifiers include: xray. - * If the resolved list of propagators (from .composite and .composite_list) is empty, a noop propagator is used. - */ - composite_list: string; -} - -export interface ConfigSimpleProcessor { - /** - * Configure exporter. - */ - exporter: ConfigExporter; -} -export interface ConfigBatchProcessor { - /** - * Configure delay interval (in milliseconds) between two consecutive exports. - * Value must be non-negative. - * If omitted or null, 5000 is used for traces and 1000 for logs. - */ - schedule_delay: number; - - /** - * Configure maximum allowed time (in milliseconds) to export data. - * Value must be non-negative. A value of 0 indicates no limit (infinity). - * If omitted or null, 30000 is used. - */ - export_timeout: number; - - /** - * Configure maximum queue size. Value must be positive. - * If omitted or null, 2048 is used. - */ - max_queue_size: number; - - /** - * Configure maximum batch size. Value must be positive. - * If omitted or null, 512 is used. - */ - max_export_batch_size: number; - - /** - * Configure exporter. - */ - exporter: ConfigExporter; -} - -export interface ConfigExporter { - /** - * Configure exporter to be OTLP with HTTP transport. - */ - otlp_http?: ConfigOTLPHttp; - - /** - * Configure exporter to be OTLP with gRPC transport. - */ - otlp_grpc?: ConfigOTLPGRPC; - - /** - * Configure exporter to be OTLP with file transport. - * This type is in development and subject to breaking changes in minor versions. - */ - 'otlp_file/development'?: ConfigOTLPFile; - - /** - * Configure exporter to be console. - */ - console?: object; - - /** - * Configure exporter to be zipkin. - */ - zipkin?: ConfigZipkin; -} - -export interface ConfigMeterExporter { - /** - * Configure exporter to be OTLP with HTTP transport. - */ - otlp_http: ConfigMeterOTLPHttp; -} - -export interface ConfigOTLPHttp { - /** - * Configure endpoint, including the trace or log specific path. - * If omitted or null, http://localhost:4318/v1/traces is used for trace - * and http://localhost:4318/v1/logs is used for logs. - */ - endpoint: string; - - /** - * Configure certificate used to verify a server's TLS credentials. - * Absolute path to certificate file in PEM format. - * If omitted or null, system default certificate verification is used for secure connections. - */ - certificate_file?: string; - - /** - * Configure mTLS private client key. - * Absolute path to client key file in PEM format. If set, .client_certificate must also be set. - * If omitted or null, mTLS is not used. - */ - client_key_file?: string; - - /** - * Configure mTLS client certificate. - * Absolute path to client certificate file in PEM format. If set, .client_key must also be set. - * If omitted or null, mTLS is not used. - */ - client_certificate_file?: string; - - /** - * Configure compression. - * Values include: gzip, none. Implementations may support other compression algorithms. - * If omitted or null, none is used. - */ - compression?: string; - - /** - * Configure max time (in milliseconds) to wait for each export. - * Value must be non-negative. A value of 0 indicates no limit (infinity). - * If omitted or null, 10000 is used. - */ - timeout: number; - - /** - * Configure headers. Entries have higher priority than entries from .headers_list. - * If an entry's .value is null, the entry is ignored. - */ - headers?: ConfigHeader[]; - - /** - * Configure headers. Entries have lower priority than entries from .headers. - * The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. - * If omitted or null, no headers are added. - */ - headers_list?: string; - - /** - * Configure the encoding used for messages. - * Values include: protobuf, json. Implementations may not support json. - * If omitted or null, protobuf is used. - */ - encoding: 'protobuf' | 'json'; -} - -export interface ConfigOTLPGRPC { - /** - * Configure endpoint. - * If omitted or null, http://localhost:4317 is used. - */ - endpoint: string; - - /** - * Configure certificate used to verify a server's TLS credentials. - * Absolute path to certificate file in PEM format. - * If omitted or null, system default certificate verification is used for secure connections. - */ - certificate_file?: string; - - /** - * Configure mTLS private client key. - * Absolute path to client key file in PEM format. If set, .client_certificate must also be set. - * If omitted or null, mTLS is not used. - */ - client_key_file?: string; - - /** - * Configure mTLS client certificate. - * Absolute path to client certificate file in PEM format. If set, .client_key must also be set. - * If omitted or null, mTLS is not used. - */ - client_certificate_file?: string; - - /** - * Configure headers. Entries have higher priority than entries from .headers_list. - * If an entry's .value is null, the entry is ignored. - */ - headers?: ConfigHeader[]; - - /** - * Configure headers. Entries have lower priority than entries from .headers. - * The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. - * If omitted or null, no headers are added. - */ - headers_list?: string; - - /** - * Configure compression. - * Values include: gzip, none. Implementations may support other compression algorithms. - * If omitted or null, none is used. - */ - compression?: string; - - /** - * Configure max time (in milliseconds) to wait for each export. - * Value must be non-negative. A value of 0 indicates no limit (infinity). - * If omitted or null, 10000 is used. - */ - timeout: number; - - /** - * Configure client transport security for the exporter's connection. - * Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. - * If omitted or null, false is used. - */ - insecure?: boolean; -} -export interface ConfigOTLPFile { - /** - * Configure output stream. - * Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. - * If omitted or null, stdout is used. - */ - output_stream: string; -} - -export interface ConfigZipkin { - /** - * Configure endpoint. - * If omitted or null, http://localhost:9411/api/v2/spans is used. - */ - endpoint: string; - - /** - * Configure max time (in milliseconds) to wait for each export. - * Value must be non-negative. A value of 0 indicates indefinite. - * If omitted or null, 10000 is used. - */ - timeout: number; -} - -export interface ConfigProcessor { - /** - * Configure a batch span processor. - */ - batch?: ConfigBatchProcessor; - - /** - * Configure a simple span processor. - */ - simple?: ConfigSimpleProcessor; -} - -export interface ConfigHeader { - name: string; - value: string; -} - -export interface ConfigTracerLimits { - /** - * Configure max attribute value size. Overrides .attribute_limits.attribute_value_length_limit. - * Value must be non-negative. - * If omitted or null, there is no limit. - */ - attribute_value_length_limit?: number; - - /** - * Configure max attribute count. Overrides .attribute_limits.attribute_count_limit. - * Value must be non-negative. - * If omitted or null, 128 is used. - */ - attribute_count_limit: number; - - /** - * Configure max span event count. - * Value must be non-negative. - * If omitted or null, 128 is used. - */ - event_count_limit: number; - - /** - * Configure max span link count. - * Value must be non-negative. - * If omitted or null, 128 is used. - */ - link_count_limit: number; - - /** - * Configure max attributes per span event. - * Value must be non-negative. - * If omitted or null, 128 is used. - */ - event_attribute_count_limit: number; - - /** - * Configure max attributes per span link. - * Value must be non-negative. - * If omitted or null, 128 is used. - */ - link_attribute_count_limit: number; -} - -export interface ConfigParentBase { - /** - * Configure root sampler. - * If omitted or null, always_on is used. - */ - root: 'always_on' | 'always_off'; - - /** - * Configure remote_parent_sampled sampler. - * If omitted or null, always_on is used. - */ - remote_parent_sampled: 'always_on' | 'always_off'; - - /** - * Configure remote_parent_not_sampled sampler. - * If omitted or null, always_off is used. - */ - remote_parent_not_sampled: 'always_on' | 'always_off'; - - /** - * Configure local_parent_sampled sampler. - * If omitted or null, always_on is used. - */ - local_parent_sampled: 'always_on' | 'always_off'; - - /** - * Configure local_parent_not_sampled sampler. - * If omitted or null, always_off is used. - */ - local_parent_not_sampled: 'always_on' | 'always_off'; -} -export interface ConfigSampler { - /** - * Configure sampler to be parent_based. - */ - parent_based: ConfigParentBase; -} -export interface ConfigTracerProvider { - /** - * Configure span processors. - */ - processors: ConfigProcessor[]; - - /** - * Configure span limits. See also attribute_limits. - */ - limits: ConfigTracerLimits; - - /** - * Configure the sampler. - * If omitted, parent based sampler with a root of always_on is used. - */ - sampler: ConfigSampler; -} - -export interface ConfigMeterOTLPHttp { - /** - * Configure endpoint, including the metric specific path. - * If omitted or null, http://localhost:4318/v1/metrics is used. - */ - endpoint: string; - - /** - * Configure certificate used to verify a server's TLS credentials. - * Absolute path to certificate file in PEM format. - * If omitted or null, system default certificate verification is used for secure connections. - */ - certificate_file?: string; - - /** - * Configure mTLS private client key. - * Absolute path to client key file in PEM format. If set, .client_certificate must also be set. - * If omitted or null, mTLS is not used. - */ - client_key_file?: string; - - /** - * Configure mTLS client certificate. - * Absolute path to client certificate file in PEM format. If set, .client_key must also be set. - * If omitted or null, mTLS is not used. - */ - client_certificate_file?: string; - - /** - * Configure compression. - * Values include: gzip, none. Implementations may support other compression algorithms. - * If omitted or null, none is used. - */ - compression?: string; - - /** - * Configure max time (in milliseconds) to wait for each export. - * Value must be non-negative. A value of 0 indicates no limit (infinity). - * If omitted or null, 10000 is used. - */ - timeout: number; - - /** - * Configure headers. Entries have higher priority than entries from .headers_list. - * If an entry's .value is null, the entry is ignored. - */ - headers?: ConfigHeader[]; - - /** - * Configure headers. Entries have lower priority than entries from .headers. - * The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. - * If omitted or null, no headers are added. - */ - headers_list?: string; - - /** - * Configure temporality preference. - * Values include: cumulative, delta, low_memory. - * If omitted or null, cumulative is used. - */ - temporality_preference: 'cumulative' | 'delta' | 'low_memory'; - - /** - * Configure default histogram aggregation. - * Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. - * If omitted or null, explicit_bucket_histogram is used. - */ - default_histogram_aggregation: - | 'explicit_bucket_histogram' - | 'base2_exponential_bucket_histogram'; -} -export interface ConfigPeriodicReader { - /** - * Configure delay interval (in milliseconds) between start of two consecutive exports. - * Value must be non-negative. - * If omitted or null, 60000 is used. - */ - interval: number; - - /** - * Configure maximum allowed time (in milliseconds) to export data. - * Value must be non-negative. A value of 0 indicates no limit (infinity). - * If omitted or null, 30000 is used. - */ - timeout: number; - - /** - * Configure exporter. - */ - exporter: ConfigMeterExporter; -} -export interface ConfigReader { - /** - * Configure a periodic metric reader. - */ - periodic: ConfigPeriodicReader; -} -export interface ConfigMeterProvider { - /** - * Configure metric readers. - */ - readers: ConfigReader[]; - - /** - * Configure the exemplar filter. - * Values include: trace_based, always_on, always_off. - * If omitted or null, trace_based is used. - */ - exemplar_filter: 'trace_based' | 'always_on' | 'always_off'; -} - -export interface ConfigLoggerProvider { - /** - * Configure log record processors. - */ - processors: ConfigProcessor[]; - - /** - * Configure log record limits. See also attribute_limits. - */ - limits: AttributeLimits; -} diff --git a/experimental/packages/opentelemetry-configuration/src/index.ts b/experimental/packages/opentelemetry-configuration/src/index.ts index 8f3da25a946..c97ac1c4fad 100644 --- a/experimental/packages/opentelemetry-configuration/src/index.ts +++ b/experimental/packages/opentelemetry-configuration/src/index.ts @@ -16,4 +16,4 @@ export { EnvironmentConfigProvider } from './EnvironmentConfigProvider'; export type { ConfigProvider } from './IConfigProvider'; -export type { ConfigurationModel as Configuration } from './configModel'; +export type { ConfigurationModel as Configuration } from './models/configModel'; diff --git a/experimental/packages/opentelemetry-configuration/src/models/commonModel.ts b/experimental/packages/opentelemetry-configuration/src/models/commonModel.ts new file mode 100644 index 00000000000..d2a0addb3d2 --- /dev/null +++ b/experimental/packages/opentelemetry-configuration/src/models/commonModel.ts @@ -0,0 +1,163 @@ +/* + * 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. + */ +'use strict'; + +export interface NameStringValuePair { + name: string; + value: string; +} + +export interface OtlpHttpExporter { + /** + * Configure endpoint, including the trace, metric or log specific path. + * If omitted or null, http://localhost:4318/v1/traces is used for trace, + * http://localhost:4318/v1/metrics for metrics + * and http://localhost:4318/v1/logs is used for logs. + */ + endpoint?: string; + + /** + * Configure certificate used to verify a server's TLS credentials. + * Absolute path to certificate file in PEM format. + * If omitted or null, system default certificate verification is used for secure connections. + */ + certificate_file?: string; + + /** + * Configure mTLS private client key. + * Absolute path to client key file in PEM format. If set, .client_certificate must also be set. + * If omitted or null, mTLS is not used. + */ + client_key_file?: string; + + /** + * Configure mTLS client certificate. + * Absolute path to client certificate file in PEM format. If set, .client_key must also be set. + * If omitted or null, mTLS is not used. + */ + client_certificate_file?: string; + + /** + * Configure compression. + * Values include: gzip, none. Implementations may support other compression algorithms. + * If omitted or null, none is used. + */ + compression?: string; + + /** + * Configure max time (in milliseconds) to wait for each export. + * Value must be non-negative. A value of 0 indicates no limit (infinity). + * If omitted or null, 10000 is used. + */ + timeout?: number; + + /** + * Configure headers. Entries have higher priority than entries from .headers_list. + * If an entry's .value is null, the entry is ignored. + */ + headers?: NameStringValuePair[]; + + /** + * Configure headers. Entries have lower priority than entries from .headers. + * The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. + * If omitted or null, no headers are added. + */ + headers_list?: string; + + /** + * Configure the encoding used for messages. + * Values include: protobuf, json. Implementations may not support json. + * If omitted or null, protobuf is used. + */ + encoding?: OtlpHttpEncoding; +} + +export enum OtlpHttpEncoding { + protobuf, + json, +} + +export interface OtlpGrpcExporter { + /** + * Configure endpoint. + * If omitted or null, http://localhost:4317 is used. + */ + endpoint?: string; + + /** + * Configure certificate used to verify a server's TLS credentials. + * Absolute path to certificate file in PEM format. + * If omitted or null, system default certificate verification is used for secure connections. + */ + certificate_file?: string; + + /** + * Configure mTLS private client key. + * Absolute path to client key file in PEM format. If set, .client_certificate must also be set. + * If omitted or null, mTLS is not used. + */ + client_key_file?: string; + + /** + * Configure mTLS client certificate. + * Absolute path to client certificate file in PEM format. If set, .client_key must also be set. + * If omitted or null, mTLS is not used. + */ + client_certificate_file?: string; + + /** + * Configure headers. Entries have higher priority than entries from .headers_list. + * If an entry's .value is null, the entry is ignored. + */ + headers?: NameStringValuePair[]; + + /** + * Configure headers. Entries have lower priority than entries from .headers. + * The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. + * If omitted or null, no headers are added. + */ + headers_list?: string; + + /** + * Configure compression. + * Values include: gzip, none. Implementations may support other compression algorithms. + * If omitted or null, none is used. + */ + compression?: string; + + /** + * Configure max time (in milliseconds) to wait for each export. + * Value must be non-negative. A value of 0 indicates no limit (infinity). + * If omitted or null, 10000 is used. + */ + timeout?: number; + + /** + * Configure client transport security for the exporter's connection. + * Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. + * If omitted or null, false is used. + */ + insecure?: boolean; +} + +export interface OtlpFileExporter { + /** + * Configure output stream. + * Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. + * If omitted or null, stdout is used. + */ + output_stream?: string; +} diff --git a/experimental/packages/opentelemetry-configuration/src/models/configModel.ts b/experimental/packages/opentelemetry-configuration/src/models/configModel.ts new file mode 100644 index 00000000000..8efba5b1525 --- /dev/null +++ b/experimental/packages/opentelemetry-configuration/src/models/configModel.ts @@ -0,0 +1,346 @@ +/* + * 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. + */ +'use strict'; + +import { DiagLogLevel } from '@opentelemetry/api'; +import { NameStringValuePair, OtlpHttpEncoding } from './commonModel'; +import { + initializeDefaultTracerProviderConfiguration, + SpanProcessor, + TracerProvider, +} from './tracerProviderModel'; + +export interface ConfigurationModel { + /** + * Configure if the SDK is disabled or not. + * If omitted or null, false is used. + */ + disabled?: boolean; + + /** + * Configure the log level of the internal logger used by the SDK. + * If omitted, info is used. + */ + log_level?: number; + + /** + * Node resource detectors + * If omitted, all is used. + */ + node_resource_detectors?: string[]; + + /** + * Configure resource for all signals. + * If omitted, the default resource is used. + */ + resource?: Resource; + + /** + * Configure general attribute limits. + * See also tracer_provider.limits, logger_provider.limits. + */ + attribute_limits?: AttributeLimits; + + /** + * Configure text map context propagators. + */ + propagator?: Propagator; + + /** + * Configure tracer provider. + */ + tracer_provider?: TracerProvider; + + /** + * Configure meter provider. + */ + meter_provider?: MeterProvider; + + /** + * Configure logger provider. + */ + logger_provider?: LoggerProvider; +} + +export function initializeDefaultConfiguration(): ConfigurationModel { + const config: ConfigurationModel = { + disabled: false, + log_level: DiagLogLevel.INFO, + node_resource_detectors: ['all'], + resource: {}, + attribute_limits: { + attribute_count_limit: 128, + }, + propagator: { + composite: [{ tracecontext: null }, { baggage: null }], + composite_list: 'tracecontext,baggage', + }, + tracer_provider: initializeDefaultTracerProviderConfiguration(), + meter_provider: { + readers: [ + { + periodic: { + interval: 60000, + timeout: 30000, + exporter: { + otlp_http: { + endpoint: 'http://localhost:4318/v1/metrics', + timeout: 10000, + temporality_preference: 'cumulative', + default_histogram_aggregation: 'explicit_bucket_histogram', + }, + }, + }, + }, + ], + exemplar_filter: 'trace_based', + }, + logger_provider: { + processors: [ + { + batch: { + schedule_delay: 1000, + export_timeout: 30000, + max_queue_size: 2048, + max_export_batch_size: 512, + exporter: { + otlp_http: { + endpoint: 'http://localhost:4318/v1/logs', + timeout: 10000, + encoding: OtlpHttpEncoding.protobuf, + }, + }, + }, + }, + ], + limits: { + attribute_count_limit: 128, + }, + }, + }; + + return config; +} + +export interface ConfigAttributes { + name: string; + value: + | string + | boolean + | number + | string[] + | boolean[] + | number[] + | undefined; + type: + | 'string' + | 'bool' + | 'int' + | 'double' + | 'string_array' + | 'bool_array' + | 'int_array' + | 'double_array'; +} + +export interface Resource { + /** + * Configure resource attributes. Entries have higher priority than entries from .resource.attributes_list. + * Entries must contain .name and .value, and may optionally include .type. If an entry's .type omitted or null, string is used. + * The .value's type must match the .type. Values for .type include: string, bool, int, double, string_array, bool_array, int_array, double_array. + */ + attributes?: ConfigAttributes[]; + + /** + * Configure resource attributes. Entries have lower priority than entries from .resource.attributes. + * The value is a list of comma separated key-value pairs matching the format of OTEL_RESOURCE_ATTRIBUTES. + * If omitted or null, no resource attributes are added. + */ + attributes_list?: string; + + /** + * Configure resource schema URL. + * If omitted or null, no schema URL is used. + */ + schema_url?: string; +} + +export interface AttributeLimits { + /** + * Configure max attribute value size. + * Value must be non-negative. + * If omitted or null, there is no limit. + */ + attribute_value_length_limit?: number; + + /** + * Configure max attribute count. + * Value must be non-negative. + * If omitted or null, 128 is used. + */ + attribute_count_limit: number; +} + +export interface Propagator { + /** + * Configure the propagators in the composite text map propagator. + * Entries from .composite_list are appended to the list here with duplicates filtered out. + * Built-in propagator keys include: tracecontext, baggage, b3, b3multi, jaeger, ottrace. + * Known third party keys include: xray. + * If the resolved list of propagators (from .composite and .composite_list) is empty, a noop propagator is used. + */ + composite?: object[]; + + /** + * Configure the propagators in the composite text map propagator. + * Entries are appended to .composite with duplicates filtered out. + * The value is a comma separated list of propagator identifiers matching the format of OTEL_PROPAGATORS. + * Built-in propagator identifiers include: tracecontext, baggage, b3, b3multi, jaeger, ottrace. + * Known third party identifiers include: xray. + * If the resolved list of propagators (from .composite and .composite_list) is empty, a noop propagator is used. + */ + composite_list?: string; +} + +export interface ConfigMeterExporter { + /** + * Configure exporter to be OTLP with HTTP transport. + */ + otlp_http: ConfigMeterOTLPHttp; +} + +export interface ConfigMeterOTLPHttp { + /** + * Configure endpoint, including the metric specific path. + * If omitted or null, http://localhost:4318/v1/metrics is used. + */ + endpoint: string; + + /** + * Configure certificate used to verify a server's TLS credentials. + * Absolute path to certificate file in PEM format. + * If omitted or null, system default certificate verification is used for secure connections. + */ + certificate_file?: string; + + /** + * Configure mTLS private client key. + * Absolute path to client key file in PEM format. If set, .client_certificate must also be set. + * If omitted or null, mTLS is not used. + */ + client_key_file?: string; + + /** + * Configure mTLS client certificate. + * Absolute path to client certificate file in PEM format. If set, .client_key must also be set. + * If omitted or null, mTLS is not used. + */ + client_certificate_file?: string; + + /** + * Configure compression. + * Values include: gzip, none. Implementations may support other compression algorithms. + * If omitted or null, none is used. + */ + compression?: string; + + /** + * Configure max time (in milliseconds) to wait for each export. + * Value must be non-negative. A value of 0 indicates no limit (infinity). + * If omitted or null, 10000 is used. + */ + timeout: number; + + /** + * Configure headers. Entries have higher priority than entries from .headers_list. + * If an entry's .value is null, the entry is ignored. + */ + headers?: NameStringValuePair[]; + + /** + * Configure headers. Entries have lower priority than entries from .headers. + * The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. + * If omitted or null, no headers are added. + */ + headers_list?: string; + + /** + * Configure temporality preference. + * Values include: cumulative, delta, low_memory. + * If omitted or null, cumulative is used. + */ + temporality_preference: 'cumulative' | 'delta' | 'low_memory'; + + /** + * Configure default histogram aggregation. + * Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. + * If omitted or null, explicit_bucket_histogram is used. + */ + default_histogram_aggregation: + | 'explicit_bucket_histogram' + | 'base2_exponential_bucket_histogram'; +} +export interface ConfigPeriodicReader { + /** + * Configure delay interval (in milliseconds) between start of two consecutive exports. + * Value must be non-negative. + * If omitted or null, 60000 is used. + */ + interval: number; + + /** + * Configure maximum allowed time (in milliseconds) to export data. + * Value must be non-negative. A value of 0 indicates no limit (infinity). + * If omitted or null, 30000 is used. + */ + timeout: number; + + /** + * Configure exporter. + */ + exporter: ConfigMeterExporter; +} +export interface ConfigReader { + /** + * Configure a periodic metric reader. + */ + periodic?: ConfigPeriodicReader; +} +export interface MeterProvider { + /** + * Configure metric readers. + */ + readers?: ConfigReader[]; + + /** + * Configure the exemplar filter. + * Values include: trace_based, always_on, always_off. + * If omitted or null, trace_based is used. + */ + exemplar_filter?: 'trace_based' | 'always_on' | 'always_off'; +} + +export interface LoggerProvider { + /** + * Configure log record processors. + */ + processors?: SpanProcessor[]; + + /** + * Configure log record limits. See also attribute_limits. + */ + limits?: AttributeLimits; +} diff --git a/experimental/packages/opentelemetry-configuration/src/models/resourceModel.ts b/experimental/packages/opentelemetry-configuration/src/models/resourceModel.ts new file mode 100644 index 00000000000..911c0188266 --- /dev/null +++ b/experimental/packages/opentelemetry-configuration/src/models/resourceModel.ts @@ -0,0 +1,16 @@ +/* + * 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. + */ +'use strict'; diff --git a/experimental/packages/opentelemetry-configuration/src/models/tracerProviderModel.ts b/experimental/packages/opentelemetry-configuration/src/models/tracerProviderModel.ts new file mode 100644 index 00000000000..0b43f3fd371 --- /dev/null +++ b/experimental/packages/opentelemetry-configuration/src/models/tracerProviderModel.ts @@ -0,0 +1,267 @@ +/* + * 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. + */ +'use strict'; + +import { + OtlpFileExporter, + OtlpGrpcExporter, + OtlpHttpEncoding, + OtlpHttpExporter, +} from './commonModel'; + +export function initializeDefaultTracerProviderConfiguration(): TracerProvider { + return { + processors: [ + { + batch: { + schedule_delay: 5000, + export_timeout: 30000, + max_queue_size: 2048, + max_export_batch_size: 512, + exporter: { + otlp_http: { + endpoint: 'http://localhost:4318/v1/traces', + timeout: 10000, + encoding: OtlpHttpEncoding.protobuf, + }, + }, + }, + }, + ], + limits: { + attribute_count_limit: 128, + event_count_limit: 128, + link_count_limit: 128, + event_attribute_count_limit: 128, + link_attribute_count_limit: 128, + }, + sampler: { + parent_based: { + root: { always_on: undefined }, + remote_parent_sampled: { always_on: undefined }, + remote_parent_not_sampled: { always_off: undefined }, + local_parent_sampled: { always_on: undefined }, + local_parent_not_sampled: { always_off: undefined }, + }, + }, + }; +} + +export interface TracerProvider { + /** + * Configure span processors. + */ + processors: SpanProcessor[]; + + /** + * Configure span limits. See also attribute_limits. + */ + limits?: SpanLimits; + + /** + * Configure the sampler. + * If omitted, parent based sampler with a root of always_on is used. + */ + sampler?: Sampler; +} + +export interface SpanProcessor { + /** + * Configure a batch span processor. + */ + batch?: BatchSpanProcessor; + + /** + * Configure a simple span processor. + */ + simple?: SimpleSpanProcessor; +} + +export interface SpanLimits { + /** + * Configure max attribute value size. Overrides .attribute_limits.attribute_value_length_limit. + * Value must be non-negative. + * If omitted or null, there is no limit. + */ + attribute_value_length_limit?: number; + + /** + * Configure max attribute count. Overrides .attribute_limits.attribute_count_limit. + * Value must be non-negative. + * If omitted or null, 128 is used. + */ + attribute_count_limit?: number; + + /** + * Configure max span event count. + * Value must be non-negative. + * If omitted or null, 128 is used. + */ + event_count_limit?: number; + + /** + * Configure max span link count. + * Value must be non-negative. + * If omitted or null, 128 is used. + */ + link_count_limit?: number; + + /** + * Configure max attributes per span event. + * Value must be non-negative. + * If omitted or null, 128 is used. + */ + event_attribute_count_limit?: number; + + /** + * Configure max attributes per span link. + * Value must be non-negative. + * If omitted or null, 128 is used. + */ + link_attribute_count_limit?: number; +} + +export interface Sampler { + /** + * Configure sampler to be parent_based. + */ + parent_based?: ParentBasedSampler; + + /** + * Configure sampler to be always_off. + */ + always_off?: object; + + /** + * Configure sampler to be always_on. + */ + always_on?: object; +} + +export interface ParentBasedSampler { + /** + * Configure root sampler. + * If omitted or null, always_on is used. + */ + root: Sampler; + + /** + * Configure remote_parent_sampled sampler. + * If omitted or null, always_on is used. + */ + remote_parent_sampled: Sampler; + + /** + * Configure remote_parent_not_sampled sampler. + * If omitted or null, always_off is used. + */ + remote_parent_not_sampled: Sampler; + + /** + * Configure local_parent_sampled sampler. + * If omitted or null, always_on is used. + */ + local_parent_sampled: Sampler; + + /** + * Configure local_parent_not_sampled sampler. + * If omitted or null, always_off is used. + */ + local_parent_not_sampled: Sampler; +} + +export interface BatchSpanProcessor { + /** + * Configure delay interval (in milliseconds) between two consecutive exports. + * Value must be non-negative. + * If omitted or null, 5000 is used for traces and 1000 for logs. + */ + schedule_delay?: number; + + /** + * Configure maximum allowed time (in milliseconds) to export data. + * Value must be non-negative. A value of 0 indicates no limit (infinity). + * If omitted or null, 30000 is used. + */ + export_timeout?: number; + + /** + * Configure maximum queue size. Value must be positive. + * If omitted or null, 2048 is used. + */ + max_queue_size?: number; + + /** + * Configure maximum batch size. Value must be positive. + * If omitted or null, 512 is used. + */ + max_export_batch_size?: number; + + /** + * Configure exporter. + */ + exporter: SpanExporter; +} + +export interface SpanExporter { + /** + * Configure exporter to be OTLP with HTTP transport. + */ + otlp_http?: OtlpHttpExporter; + + /** + * Configure exporter to be OTLP with gRPC transport. + */ + otlp_grpc?: OtlpGrpcExporter; + + /** + * Configure exporter to be OTLP with file transport. + * This type is in development and subject to breaking changes in minor versions. + */ + 'otlp_file/development'?: OtlpFileExporter; + + /** + * Configure exporter to be console. + */ + console?: object; + + /** + * Configure exporter to be zipkin. + */ + zipkin?: ZipkinSpanExporter; +} + +export interface ZipkinSpanExporter { + /** + * Configure endpoint. + * If omitted or null, http://localhost:9411/api/v2/spans is used. + */ + endpoint?: string; + + /** + * Configure max time (in milliseconds) to wait for each export. + * Value must be non-negative. A value of 0 indicates indefinite. + * If omitted or null, 10000 is used. + */ + timeout?: number; +} + +export interface SimpleSpanProcessor { + /** + * Configure exporter. + */ + exporter: SpanExporter; +} diff --git a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts index 1466da06afb..30da7d7ec39 100644 --- a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts +++ b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts @@ -18,6 +18,7 @@ import * as assert from 'assert'; import { Configuration } from '../src'; import { DiagLogLevel } from '@opentelemetry/api'; import { createConfigProvider } from '../src/ConfigProvider'; +import { OtlpHttpEncoding } from '../src/models/commonModel'; const defaultConfig: Configuration = { disabled: false, @@ -43,7 +44,7 @@ const defaultConfig: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/traces', timeout: 10000, - encoding: 'protobuf', + encoding: OtlpHttpEncoding.protobuf, }, }, }, @@ -58,11 +59,11 @@ const defaultConfig: Configuration = { }, sampler: { parent_based: { - root: 'always_on', - remote_parent_sampled: 'always_on', - remote_parent_not_sampled: 'always_off', - local_parent_sampled: 'always_on', - local_parent_not_sampled: 'always_off', + root: { always_on: undefined }, + remote_parent_sampled: { always_on: undefined }, + remote_parent_not_sampled: { always_off: undefined }, + local_parent_sampled: { always_on: undefined }, + local_parent_not_sampled: { always_off: undefined }, }, }, }, @@ -97,7 +98,7 @@ const defaultConfig: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/logs', timeout: 10000, - encoding: 'protobuf', + encoding: OtlpHttpEncoding.protobuf, }, }, }, @@ -198,7 +199,7 @@ const configFromFile: Configuration = { headers: [{ name: 'api-key', value: '1234' }], headers_list: 'api-key=1234', compression: 'gzip', - encoding: 'protobuf', + encoding: OtlpHttpEncoding.protobuf, }, }, }, @@ -283,11 +284,11 @@ const configFromFile: Configuration = { }, sampler: { parent_based: { - root: 'always_on', - remote_parent_sampled: 'always_on', - remote_parent_not_sampled: 'always_off', - local_parent_sampled: 'always_on', - local_parent_not_sampled: 'always_off', + root: { always_on: undefined }, + remote_parent_sampled: { always_on: undefined }, + remote_parent_not_sampled: { always_off: undefined }, + local_parent_sampled: { always_on: undefined }, + local_parent_not_sampled: { always_off: undefined }, }, }, }, @@ -322,7 +323,7 @@ const configFromFile: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/logs', timeout: 10000, - encoding: 'protobuf', + encoding: OtlpHttpEncoding.protobuf, }, }, }, @@ -367,7 +368,7 @@ const defaultConfigFromFileWithEnvVariables: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/traces', timeout: 10000, - encoding: 'protobuf', + encoding: OtlpHttpEncoding.protobuf, compression: 'gzip', }, }, @@ -383,11 +384,11 @@ const defaultConfigFromFileWithEnvVariables: Configuration = { }, sampler: { parent_based: { - root: 'always_on', - remote_parent_sampled: 'always_on', - remote_parent_not_sampled: 'always_off', - local_parent_sampled: 'always_on', - local_parent_not_sampled: 'always_off', + root: { always_on: undefined }, + remote_parent_sampled: { always_on: undefined }, + remote_parent_not_sampled: { always_off: undefined }, + local_parent_sampled: { always_on: undefined }, + local_parent_not_sampled: { always_off: undefined }, }, }, }, @@ -422,7 +423,7 @@ const defaultConfigFromFileWithEnvVariables: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/logs', timeout: 10000, - encoding: 'protobuf', + encoding: OtlpHttpEncoding.protobuf, }, }, }, @@ -657,7 +658,7 @@ describe('ConfigProvider', function () { compression: 'gzip', timeout: 2000, headers_list: 'host=localhost', - encoding: 'protobuf', + encoding: OtlpHttpEncoding.protobuf, }, }, }, @@ -665,11 +666,11 @@ describe('ConfigProvider', function () { ], sampler: { parent_based: { - root: 'always_on', - remote_parent_sampled: 'always_on', - remote_parent_not_sampled: 'always_off', - local_parent_sampled: 'always_on', - local_parent_not_sampled: 'always_off', + root: { always_on: undefined }, + remote_parent_sampled: { always_on: undefined }, + remote_parent_not_sampled: { always_off: undefined }, + local_parent_sampled: { always_on: undefined }, + local_parent_not_sampled: { always_off: undefined }, }, }, }, @@ -773,7 +774,7 @@ describe('ConfigProvider', function () { compression: 'gzip', timeout: 700, headers_list: 'host=localhost', - encoding: 'protobuf', + encoding: OtlpHttpEncoding.protobuf, }, }, }, @@ -999,7 +1000,7 @@ describe('ConfigProvider', function () { client_certificate_file: 'trace-client-certificate', client_key_file: 'trace-client-key', compression: 'trace-compression', - encoding: 'protobuf', + encoding: OtlpHttpEncoding.protobuf, endpoint: 'http://test.com:4318/v1/traces', headers_list: 'trace-headers', timeout: 1213, From 79d6a61cc04d752f725e976dcec61d50402eb923 Mon Sep 17 00:00:00 2001 From: maryliag Date: Wed, 8 Oct 2025 23:17:23 -0400 Subject: [PATCH 19/27] updates to model --- .../src/EnvironmentConfigProvider.ts | 2 +- .../src/FileConfigProvider.ts | 31 ++- .../src/models/commonModel.ts | 20 ++ .../src/models/configModel.ts | 86 +------- .../src/models/loggerProviderModel.ts | 191 ++++++++++++++++++ .../src/models/resourceModel.ts | 89 ++++++++ 6 files changed, 331 insertions(+), 88 deletions(-) create mode 100644 experimental/packages/opentelemetry-configuration/src/models/loggerProviderModel.ts diff --git a/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts index e92f7cd5400..a2cee0213ad 100644 --- a/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts @@ -363,7 +363,7 @@ function setLoggerProvider(config: ConfigurationModel): void { ); if (attributeValueLengthLimit || attributeCountLimit) { if (config.logger_provider == null) { - config.logger_provider = {}; + config.logger_provider = { processors: [] }; } if (config.logger_provider.limits == null) { config.logger_provider.limits = { attribute_count_limit: 128 }; diff --git a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts index 7082ef11ab0..797dc6d312f 100644 --- a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts @@ -17,8 +17,6 @@ import { diagLogLevelFromString, getStringFromEnv } from '@opentelemetry/core'; import { AttributeLimits, - ConfigAttributes, - LoggerProvider, MeterProvider, Propagator, ConfigurationModel, @@ -41,6 +39,8 @@ import { SpanProcessor, TracerProvider, } from './models/tracerProviderModel'; +import { LoggerProvider } from './models/loggerProviderModel'; +import { AttributeNameValue } from './models/resourceModel'; export class FileConfigProvider implements ConfigProvider { private _config: ConfigurationModel; @@ -98,14 +98,14 @@ function parseConfigFile(config: ConfigurationModel) { config.resource = {}; } const attrList = getStringFromConfigFile( - parsedContent['resource']?.['attributes_list'] + parsedContent['resource']['attributes_list'] ); if (attrList) { config.resource.attributes_list = attrList; } const schemaUrl = getStringFromConfigFile( - parsedContent['resource']?.['schema_url'] + parsedContent['resource']['schema_url'] ); if (schemaUrl) { config.resource.schema_url = schemaUrl; @@ -127,7 +127,7 @@ function parseConfigFile(config: ConfigurationModel) { function setResourceAttributes( config: ConfigurationModel, - attributes: ConfigAttributes[] + attributes: AttributeNameValue[] ) { if (attributes) { if (config.resource == null) { @@ -551,7 +551,7 @@ function setLoggerProvider( ): void { if (loggerProvider) { if (config.logger_provider == null) { - config.logger_provider = {}; + config.logger_provider = { processors: [] }; } // Limits if (loggerProvider['limits']) { @@ -562,6 +562,9 @@ function setLoggerProvider( loggerProvider['limits']['attribute_count_limit'] ); if (attributeValueLengthLimit || attributeCountLimit) { + if (config.logger_provider == null) { + config.logger_provider = { processors: [] }; + } if (config.logger_provider.limits == null) { config.logger_provider.limits = { attribute_count_limit: 128 }; } @@ -579,6 +582,9 @@ function setLoggerProvider( // Processors if (loggerProvider['processors']) { if (loggerProvider['processors'].length > 0) { + if (config.logger_provider == null) { + config.logger_provider = { processors: [] }; + } config.logger_provider.processors = []; for (let i = 0; i < loggerProvider['processors'].length; i++) { const processorType = Object.keys(loggerProvider['processors'][i])[0]; @@ -634,6 +640,9 @@ function setLoggerProvider( ] ); if (defaultConfigDisabled || defaultConfigDisabled === false) { + if (config.logger_provider == null) { + config.logger_provider = { processors: [] }; + } config.logger_provider['logger_configurator/development'] = { default_config: { disabled: defaultConfigDisabled, @@ -653,8 +662,11 @@ function setLoggerProvider( ) { const logger = loggerProvider['logger_configurator/development'].loggers[i]; - const disabled = - getBooleanFromConfigFile(logger['config']['disabled']) ?? false; + let disabled = false; + if (logger['config']) { + disabled = + getBooleanFromConfigFile(logger['config']['disabled']) ?? false; + } const name = getStringFromConfigFile(logger['name']); if (name) { loggers.push({ @@ -665,6 +677,9 @@ function setLoggerProvider( }); } } + if (config.logger_provider == null) { + config.logger_provider = { processors: [] }; + } if (config.logger_provider['logger_configurator/development'] == null) { config.logger_provider['logger_configurator/development'] = {}; } diff --git a/experimental/packages/opentelemetry-configuration/src/models/commonModel.ts b/experimental/packages/opentelemetry-configuration/src/models/commonModel.ts index d2a0addb3d2..55a55535994 100644 --- a/experimental/packages/opentelemetry-configuration/src/models/commonModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/models/commonModel.ts @@ -15,6 +15,26 @@ */ 'use strict'; +export interface IncludeExclude { + /** + * Configure list of attribute key patterns to include from resource detectors. + * Attribute keys from resource detectors are evaluated to match as follows: + * * If the value of the attribute key exactly matches. + * * If the value of the attribute key matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. + * If omitted, all attributes are included. + */ + include: string[]; + + /** + * Configure list of attribute key patterns to exclude from resource detectors. Applies after .resource.detectors.attributes.included (i.e. excluded has higher priority than included). + * Attribute keys from resource detectors are evaluated to match as follows: + * * If the value of the attribute key exactly matches. + * * If the value of the attribute key matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. + * If omitted, .included attributes are included. + */ + exclude: string[]; +} + export interface NameStringValuePair { name: string; value: string; diff --git a/experimental/packages/opentelemetry-configuration/src/models/configModel.ts b/experimental/packages/opentelemetry-configuration/src/models/configModel.ts index 8efba5b1525..3d47266c135 100644 --- a/experimental/packages/opentelemetry-configuration/src/models/configModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/models/configModel.ts @@ -16,12 +16,16 @@ 'use strict'; import { DiagLogLevel } from '@opentelemetry/api'; -import { NameStringValuePair, OtlpHttpEncoding } from './commonModel'; +import { NameStringValuePair } from './commonModel'; import { initializeDefaultTracerProviderConfiguration, - SpanProcessor, TracerProvider, } from './tracerProviderModel'; +import { + initializeDefaultLoggerProviderConfiguration, + LoggerProvider, +} from './loggerProviderModel'; +import { Resource } from './resourceModel'; export interface ConfigurationModel { /** @@ -108,76 +112,12 @@ export function initializeDefaultConfiguration(): ConfigurationModel { ], exemplar_filter: 'trace_based', }, - logger_provider: { - processors: [ - { - batch: { - schedule_delay: 1000, - export_timeout: 30000, - max_queue_size: 2048, - max_export_batch_size: 512, - exporter: { - otlp_http: { - endpoint: 'http://localhost:4318/v1/logs', - timeout: 10000, - encoding: OtlpHttpEncoding.protobuf, - }, - }, - }, - }, - ], - limits: { - attribute_count_limit: 128, - }, - }, + logger_provider: initializeDefaultLoggerProviderConfiguration(), }; return config; } -export interface ConfigAttributes { - name: string; - value: - | string - | boolean - | number - | string[] - | boolean[] - | number[] - | undefined; - type: - | 'string' - | 'bool' - | 'int' - | 'double' - | 'string_array' - | 'bool_array' - | 'int_array' - | 'double_array'; -} - -export interface Resource { - /** - * Configure resource attributes. Entries have higher priority than entries from .resource.attributes_list. - * Entries must contain .name and .value, and may optionally include .type. If an entry's .type omitted or null, string is used. - * The .value's type must match the .type. Values for .type include: string, bool, int, double, string_array, bool_array, int_array, double_array. - */ - attributes?: ConfigAttributes[]; - - /** - * Configure resource attributes. Entries have lower priority than entries from .resource.attributes. - * The value is a list of comma separated key-value pairs matching the format of OTEL_RESOURCE_ATTRIBUTES. - * If omitted or null, no resource attributes are added. - */ - attributes_list?: string; - - /** - * Configure resource schema URL. - * If omitted or null, no schema URL is used. - */ - schema_url?: string; -} - export interface AttributeLimits { /** * Configure max attribute value size. @@ -332,15 +272,3 @@ export interface MeterProvider { */ exemplar_filter?: 'trace_based' | 'always_on' | 'always_off'; } - -export interface LoggerProvider { - /** - * Configure log record processors. - */ - processors?: SpanProcessor[]; - - /** - * Configure log record limits. See also attribute_limits. - */ - limits?: AttributeLimits; -} diff --git a/experimental/packages/opentelemetry-configuration/src/models/loggerProviderModel.ts b/experimental/packages/opentelemetry-configuration/src/models/loggerProviderModel.ts new file mode 100644 index 00000000000..cbb1bd2fe2c --- /dev/null +++ b/experimental/packages/opentelemetry-configuration/src/models/loggerProviderModel.ts @@ -0,0 +1,191 @@ +/* + * 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. + */ +'use strict'; + +import { + OtlpFileExporter, + OtlpGrpcExporter, + OtlpHttpEncoding, + OtlpHttpExporter, +} from './commonModel'; + +export function initializeDefaultLoggerProviderConfiguration(): LoggerProvider { + return { + processors: [ + { + batch: { + schedule_delay: 1000, + export_timeout: 30000, + max_queue_size: 2048, + max_export_batch_size: 512, + exporter: { + otlp_http: { + endpoint: 'http://localhost:4318/v1/logs', + timeout: 10000, + encoding: OtlpHttpEncoding.protobuf, + }, + }, + }, + }, + ], + limits: { + attribute_count_limit: 128, + }, + }; +} + +export interface LoggerProvider { + /** + * Configure log record processors. + */ + processors: LogRecordProcessor[]; + + /** + * Configure log record limits. See also attribute_limits. + */ + limits?: LogRecordLimits; + + /** + * Configure loggers. + * This type is in development and subject to breaking changes in minor versions. + */ + 'logger_configurator/development'?: LoggerConfigurator; +} + +export interface SimpleLogRecordProcessor { + /** + * Configure exporter. + */ + exporter: LogRecordExporter; +} + +export interface BatchLogRecordProcessor { + /** + * Configure delay interval (in milliseconds) between two consecutive exports. + * Value must be non-negative. + * If omitted or null, 1000 is used for traces and 1000 for logs. + */ + schedule_delay?: number; + + /** + * Configure maximum allowed time (in milliseconds) to export data. + * Value must be non-negative. A value of 0 indicates no limit (infinity). + * If omitted or null, 30000 is used. + */ + export_timeout?: number; + + /** + * Configure maximum queue size. Value must be positive. + * If omitted or null, 2048 is used. + */ + max_queue_size?: number; + + /** + * Configure maximum batch size. Value must be positive. + * If omitted or null, 512 is used. + */ + max_export_batch_size?: number; + + /** + * Configure exporter. + */ + exporter: LogRecordExporter; +} + +export interface LogRecordExporter { + /** + * Configure exporter to be OTLP with HTTP transport. + */ + otlp_http?: OtlpHttpExporter; + + /** + * Configure exporter to be OTLP with gRPC transport. + */ + otlp_grpc?: OtlpGrpcExporter; + + /** + * Configure exporter to be OTLP with file transport. + * This type is in development and subject to breaking changes in minor versions. + */ + 'otlp_file/development'?: OtlpFileExporter; + + /** + * Configure exporter to be console. + */ + console?: object; +} + +export interface LogRecordLimits { + /** + * Configure max attribute value size. Overrides .attribute_limits.attribute_value_length_limit. + * Value must be non-negative. + * If omitted or null, there is no limit. + */ + attribute_value_length_limit?: number; + + /** + * Configure max attribute count. Overrides .attribute_limits.attribute_count_limit. + * Value must be non-negative. + * If omitted or null, 128 is used. + */ + attribute_count_limit?: number; +} + +export interface LogRecordProcessor { + /** + * Configure a batch log record processor. + */ + batch?: BatchLogRecordProcessor; + + /** + * Configure a simple log record processor. + */ + simple?: SimpleLogRecordProcessor; +} + +export interface LoggerConfigurator { + /** + * Configure the default logger config used there is no matching entry in .logger_configurator/development.loggers. + */ + default_config?: LoggerConfig; + + /** + * Configure loggers. + */ + loggers?: LoggerMatcherAndConfig[]; +} + +export interface LoggerConfig { + /** + * Configure if the logger is enabled or not. + */ + disabled: boolean; +} + +export interface LoggerMatcherAndConfig { + /** + * Configure logger names to match, evaluated as follows: + * * If the logger name exactly matches. + * * If the logger name matches the wildcard pattern, where '?' matches any single character + * and '*' matches any number of characters including none. + */ + name?: string; + + /** + * The logger config. + */ + config?: LoggerConfig; +} diff --git a/experimental/packages/opentelemetry-configuration/src/models/resourceModel.ts b/experimental/packages/opentelemetry-configuration/src/models/resourceModel.ts index 911c0188266..6646766a50b 100644 --- a/experimental/packages/opentelemetry-configuration/src/models/resourceModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/models/resourceModel.ts @@ -14,3 +14,92 @@ * limitations under the License. */ 'use strict'; + +import { IncludeExclude } from './commonModel'; + +export interface Resource { + /** + * Configure resource attributes. Entries have higher priority than entries from .resource.attributes_list. + * Entries must contain .name and .value, and may optionally include .type. If an entry's .type omitted or null, string is used. + * The .value's type must match the .type. Values for .type include: string, bool, int, double, string_array, bool_array, int_array, double_array. + */ + attributes?: AttributeNameValue[]; + + /** + * Configure resource attributes. Entries have lower priority than entries from .resource.attributes. + * The value is a list of comma separated key-value pairs matching the format of OTEL_RESOURCE_ATTRIBUTES. + * If omitted or null, no resource attributes are added. + */ + attributes_list?: string; + + /** + * Configure resource schema URL. + * If omitted or null, no schema URL is used. + */ + schema_url?: string; + + /** + * Configure resource detection. + * This type is in development and subject to breaking changes in minor versions. + * If omitted or null, resource detection is disabled. + */ + 'detection/development'?: ResourceDetection; +} + +export interface AttributeNameValue { + name: string; + value: + | string + | boolean + | number + | string[] + | boolean[] + | number[] + | undefined; + type?: + | 'string' + | 'bool' + | 'int' + | 'double' + | 'string_array' + | 'bool_array' + | 'int_array' + | 'double_array'; +} + +export interface ResourceDetection { + /** + * Configure attributes provided by resource detectors. + */ + attributes?: IncludeExclude; + + /** + * Configure resource detectors. + * Resource detector names are dependent on the SDK language ecosystem. Please consult documentation for each respective language. + * If omitted or null, no resource detectors are enabled. + */ + detectors?: ResourceDetector; +} + +export interface ResourceDetector { + /** + * Enable the container resource detector, which populates container.* attributes. + */ + container?: object; + + /** + * Enable the host resource detector, which populates host.* and os.* attributes. + */ + host?: object; + + /** + * Enable the process resource detector, which populates process.* attributes. + */ + process?: object; + + /** + * Enable the service detector, which populates service.name based on the OTEL_SERVICE_NAME + * environment variable and service.instance.id. + */ + service?: object; +} From f473a6f3bd8b2bcde23aa26ecc6d13b17ded458c Mon Sep 17 00:00:00 2001 From: maryliag Date: Thu, 9 Oct 2025 14:52:38 -0400 Subject: [PATCH 20/27] parse attributes --- .../src/EnvironmentConfigProvider.ts | 81 ++- .../src/FileConfigProvider.ts | 527 ++++++++++++-- .../src/models/commonModel.ts | 4 +- .../src/models/configModel.ts | 25 +- .../src/models/meterProviderModel.ts | 438 +++++++++++- .../opentelemetry-configuration/src/utils.ts | 2 +- .../test/ConfigProvider.test.ts | 658 +++++++----------- 7 files changed, 1200 insertions(+), 535 deletions(-) diff --git a/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts index a2cee0213ad..10ba87bbaae 100644 --- a/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts @@ -26,6 +26,11 @@ import { getNumberFromEnv, } from '@opentelemetry/core'; import { ConfigProvider } from './IConfigProvider'; +import { + ExemplarFilter, + ExporterDefaultHistogramAggregation, + ExporterTemporalityPreference, +} from './models/meterProviderModel'; /** * EnvironmentConfigProvider provides a configuration based on environment variables. @@ -262,6 +267,9 @@ function setMeterProvider(config: ConfigurationModel): void { if (timeout) { readerPeriodic.timeout = timeout; } + if (readerPeriodic.exporter.otlp_http == null) { + readerPeriodic.exporter.otlp_http = {}; + } const endpoint = getStringFromEnv('OTEL_EXPORTER_OTLP_METRICS_ENDPOINT'); if (endpoint) { @@ -310,26 +318,45 @@ function setMeterProvider(config: ConfigurationModel): void { const temporalityPreference = getStringFromEnv( 'OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE' ); - if ( - temporalityPreference && - (temporalityPreference === 'cumulative' || - temporalityPreference === 'delta' || - temporalityPreference === 'low_memory') - ) { - readerPeriodic.exporter.otlp_http.temporality_preference = - temporalityPreference; + if (temporalityPreference) { + switch (temporalityPreference) { + case 'cumulative': + readerPeriodic.exporter.otlp_http.temporality_preference = + ExporterTemporalityPreference.cumulative; + break; + case 'delta': + readerPeriodic.exporter.otlp_http.temporality_preference = + ExporterTemporalityPreference.delta; + break; + case 'low_memory': + readerPeriodic.exporter.otlp_http.temporality_preference = + ExporterTemporalityPreference.low_memory; + break; + default: + readerPeriodic.exporter.otlp_http.temporality_preference = + ExporterTemporalityPreference.cumulative; + break; + } } const defaultHistogramAggregation = getStringFromEnv( 'OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION' ); - if ( - defaultHistogramAggregation && - (defaultHistogramAggregation === 'explicit_bucket_histogram' || - defaultHistogramAggregation === 'base2_exponential_bucket_histogram') - ) { - readerPeriodic.exporter.otlp_http.default_histogram_aggregation = - defaultHistogramAggregation; + if (defaultHistogramAggregation) { + switch (defaultHistogramAggregation) { + case 'explicit_bucket_histogram': + readerPeriodic.exporter.otlp_http.default_histogram_aggregation = + ExporterDefaultHistogramAggregation.explicit_bucket_histogram; + break; + case 'base2_exponential_bucket_histogram': + readerPeriodic.exporter.otlp_http.default_histogram_aggregation = + ExporterDefaultHistogramAggregation.base2_exponential_bucket_histogram; + break; + default: + readerPeriodic.exporter.otlp_http.default_histogram_aggregation = + ExporterDefaultHistogramAggregation.explicit_bucket_histogram; + break; + } } if (config.meter_provider == null) { config.meter_provider = { readers: [{}] }; @@ -341,16 +368,24 @@ function setMeterProvider(config: ConfigurationModel): void { config.meter_provider.readers[0].periodic = readerPeriodic; } const exemplarFilter = getStringFromEnv('OTEL_METRICS_EXEMPLAR_FILTER'); - if ( - exemplarFilter && - (exemplarFilter === 'trace_based' || - exemplarFilter === 'always_on' || - exemplarFilter === 'always_off') - ) { + if (exemplarFilter) { if (config.meter_provider == null) { - config.meter_provider = {}; + config.meter_provider = { readers: [] }; + } + switch (exemplarFilter) { + case 'trace_based': + config.meter_provider.exemplar_filter = ExemplarFilter.trace_based; + break; + case 'always_on': + config.meter_provider.exemplar_filter = ExemplarFilter.always_on; + break; + case 'always_off': + config.meter_provider.exemplar_filter = ExemplarFilter.always_off; + break; + default: + config.meter_provider.exemplar_filter = ExemplarFilter.trace_based; + break; } - config.meter_provider.exemplar_filter = exemplarFilter; } } diff --git a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts index 659bdf63db3..7e328ed5499 100644 --- a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts @@ -17,11 +17,9 @@ import { diagLogLevelFromString, getStringFromEnv } from '@opentelemetry/core'; import { AttributeLimits, - MeterProvider, Propagator, ConfigurationModel, initializeDefaultConfiguration, - ConfigReader, } from './models/configModel'; import { ConfigProvider } from './IConfigProvider'; import * as fs from 'fs'; @@ -42,7 +40,22 @@ import { } from './models/tracerProviderModel'; import { LoggerProvider } from './models/loggerProviderModel'; import { AttributeNameValue } from './models/resourceModel'; -import { CardinalityLimits, MetricProducer, PullMetricExporter } from './configModel'; +import { + Aggregation, + CardinalityLimits, + ExemplarFilter, + ExporterDefaultHistogramAggregation, + ExporterTemporalityPreference, + InstrumentType, + MeterProvider, + MetricProducer, + MetricReader, + PullMetricExporter, + PushMetricExporter, + View, + ViewSelector, + ViewStream, +} from './models/meterProviderModel'; export class FileConfigProvider implements ConfigProvider { private _config: ConfigurationModel; @@ -262,7 +275,7 @@ enum ProviderType { LOGGER = 2, } -function parseConfigExporter( +function parseConfigSpanExporter( exporter: SpanExporter, providerType: ProviderType ): SpanExporter { @@ -282,9 +295,6 @@ function parseConfigExporter( case ProviderType.TRACER: endpoint = 'http://localhost:4318/v1/traces'; break; - case ProviderType.METER: - endpoint = 'http://localhost:4318/v1/metrics'; - break; case ProviderType.LOGGER: endpoint = 'http://localhost:4318/v1/logs'; break; @@ -388,7 +398,7 @@ function parseConfigExporter( case 'console': parsedExporter = { - console: {}, + console: undefined, }; break; @@ -483,7 +493,7 @@ function setTracerProvider( if (processorType === 'batch') { const element = tracerProvider['processors'][i]['batch']; if (element) { - const parsedExporter = parseConfigExporter( + const parsedExporter = parseConfigSpanExporter( element['exporter'], ProviderType.TRACER ); @@ -507,7 +517,7 @@ function setTracerProvider( } else if (processorType === 'simple') { const element = tracerProvider['processors'][i]['simple']; if (element) { - const parsedExporter = parseConfigExporter( + const parsedExporter = parseConfigSpanExporter( element['exporter'], ProviderType.TRACER ); @@ -525,27 +535,247 @@ function setTracerProvider( } } +function getCardinalityLimits(limits?: CardinalityLimits): CardinalityLimits { + if (limits == null) { + limits = {}; + } + const defaultLimit = getNumberFromConfigFile(limits['default']) ?? 2000; + + return { + default: defaultLimit, + counter: getNumberFromConfigFile(limits['counter']) ?? defaultLimit, + gauge: getNumberFromConfigFile(limits['gauge']) ?? defaultLimit, + histogram: getNumberFromConfigFile(limits['histogram']) ?? defaultLimit, + observable_counter: + getNumberFromConfigFile(limits['observable_counter']) ?? defaultLimit, + observable_gauge: + getNumberFromConfigFile(limits['observable_gauge']) ?? defaultLimit, + observable_up_down_counter: + getNumberFromConfigFile(limits['observable_up_down_counter']) ?? + defaultLimit, + up_down_counter: + getNumberFromConfigFile(limits['up_down_counter']) ?? defaultLimit, + }; +} + +function getProducers(producers?: MetricProducer[]): MetricProducer[] { + const parsedProducers: MetricProducer[] = []; + if (producers) { + for (let j = 0; j < producers.length; j++) { + const producer = producers[j]; + if (Object.keys(producer)[0] === 'opencensus') { + parsedProducers.push({ opencensus: undefined }); + } + if (Object.keys(producer)[0] === 'prometheus') { + parsedProducers.push({ prometheus: undefined }); + } + } + } + + return parsedProducers; +} + +function getTemporalityPreference( + temporalityPreference?: ExporterTemporalityPreference +): ExporterTemporalityPreference { + const temporalityPreferenceType = getStringFromConfigFile( + temporalityPreference + ); + switch (temporalityPreferenceType) { + case 'cumulative': + return ExporterTemporalityPreference.cumulative; + case 'delta': + return ExporterTemporalityPreference.delta; + case 'low_memory': + return ExporterTemporalityPreference.low_memory; + default: + return ExporterTemporalityPreference.cumulative; + } +} + +function getDefaultHistogramAggregation( + defaultHistogramAggregation?: ExporterDefaultHistogramAggregation +): ExporterDefaultHistogramAggregation { + const defaultHistogramAggregationType = getStringFromConfigFile( + defaultHistogramAggregation + ); + switch (defaultHistogramAggregationType) { + case 'explicit_bucket_histogram': + return ExporterDefaultHistogramAggregation.explicit_bucket_histogram; + case 'base2_exponential_bucket_histogram': + return ExporterDefaultHistogramAggregation.base2_exponential_bucket_histogram; + default: + return ExporterDefaultHistogramAggregation.explicit_bucket_histogram; + } +} + +function parseMetricExporter(exporter: PushMetricExporter): PushMetricExporter { + const exporterType = Object.keys(exporter)[0]; + let parsedExporter: PushMetricExporter = {}; + let e; + let certFile; + let clientCertFile; + let clientKeyFile; + let compression; + let headers; + let headersList; + let insecure; + + switch (exporterType) { + case 'otlp_http': + e = exporter['otlp_http']; + if (e) { + parsedExporter = { + otlp_http: { + endpoint: + getStringFromConfigFile(e['endpoint']) ?? + 'http://localhost:4318/v1/metrics', + timeout: getNumberFromConfigFile(e['timeout']) ?? 10000, + encoding: + getStringFromConfigFile(e['encoding']) === 'json' + ? OtlpHttpEncoding.json + : OtlpHttpEncoding.protobuf, + temporality_preference: getTemporalityPreference( + e['temporality_preference'] + ), + default_histogram_aggregation: getDefaultHistogramAggregation( + e['default_histogram_aggregation'] + ), + }, + }; + + certFile = getStringFromConfigFile(e['certificate_file']); + if (certFile && parsedExporter.otlp_http) { + parsedExporter.otlp_http.certificate_file = certFile; + } + clientCertFile = getStringFromConfigFile(e['client_certificate_file']); + if (clientCertFile && parsedExporter.otlp_http) { + parsedExporter.otlp_http.client_certificate_file = clientCertFile; + } + clientKeyFile = getStringFromConfigFile(e['client_key_file']); + if (clientKeyFile && parsedExporter.otlp_http) { + parsedExporter.otlp_http.client_key_file = clientKeyFile; + } + compression = getStringFromConfigFile(e['compression']); + if (compression && parsedExporter.otlp_http) { + parsedExporter.otlp_http.compression = compression; + } + headersList = getStringFromConfigFile(e['headers_list']); + if (headersList && parsedExporter.otlp_http) { + parsedExporter.otlp_http.headers_list = headersList; + } + headers = getConfigHeaders(e['headers']); + if (headers && parsedExporter.otlp_http) { + parsedExporter.otlp_http.headers = headers; + } + } + break; + + case 'otlp_grpc': + e = exporter['otlp_grpc']; + if (e) { + parsedExporter = { + otlp_grpc: { + endpoint: + getStringFromConfigFile(e['endpoint']) ?? 'http://localhost:4317', + timeout: getNumberFromConfigFile(e['timeout']) ?? 10000, + temporality_preference: getTemporalityPreference( + e['temporality_preference'] + ), + default_histogram_aggregation: getDefaultHistogramAggregation( + e['default_histogram_aggregation'] + ), + }, + }; + + certFile = getStringFromConfigFile(e['certificate_file']); + if (certFile && parsedExporter.otlp_grpc) { + parsedExporter.otlp_grpc.certificate_file = certFile; + } + clientCertFile = getStringFromConfigFile(e['client_certificate_file']); + if (clientCertFile && parsedExporter.otlp_grpc) { + parsedExporter.otlp_grpc.client_certificate_file = clientCertFile; + } + clientKeyFile = getStringFromConfigFile(e['client_key_file']); + if (clientKeyFile && parsedExporter.otlp_grpc) { + parsedExporter.otlp_grpc.client_key_file = clientKeyFile; + } + compression = getStringFromConfigFile(e['compression']); + if (compression && parsedExporter.otlp_grpc) { + parsedExporter.otlp_grpc.compression = compression; + } + headersList = getStringFromConfigFile(e['headers_list']); + if (headersList && parsedExporter.otlp_grpc) { + parsedExporter.otlp_grpc.headers_list = headersList; + } + headers = getConfigHeaders(e['headers']); + if (headers && parsedExporter.otlp_grpc) { + parsedExporter.otlp_grpc.headers = headers; + } + insecure = getBooleanFromConfigFile(e['insecure']); + if ((insecure || insecure === false) && parsedExporter.otlp_grpc) { + parsedExporter.otlp_grpc.insecure = insecure; + } + } + break; + + case 'otlp_file/development': + e = exporter['otlp_file/development']; + if (e) { + parsedExporter = { + 'otlp_file/development': { + output_stream: + getStringFromConfigFile(e['output_stream']) ?? 'stdout', + temporality_preference: getTemporalityPreference( + e['temporality_preference'] + ), + default_histogram_aggregation: getDefaultHistogramAggregation( + e['default_histogram_aggregation'] + ), + }, + }; + } + break; + + case 'console': + parsedExporter = { + console: undefined, + }; + break; + } + + return parsedExporter; +} + function setMeterProvider( config: ConfigurationModel, meterProvider: MeterProvider ): void { if (meterProvider) { if (config.meter_provider == null) { - config.meter_provider = {}; + config.meter_provider = { readers: [] }; } const exemplarFilter = getStringFromConfigFile( meterProvider['exemplar_filter'] ); - if ( - exemplarFilter && - (exemplarFilter === 'trace_based' || - exemplarFilter === 'always_on' || - exemplarFilter === 'always_off') - ) { - config.meter_provider.exemplar_filter = exemplarFilter; + if (exemplarFilter) { + switch (exemplarFilter) { + case 'trace_based': + config.meter_provider.exemplar_filter = ExemplarFilter.trace_based; + break; + case 'always_on': + config.meter_provider.exemplar_filter = ExemplarFilter.always_on; + break; + case 'always_off': + config.meter_provider.exemplar_filter = ExemplarFilter.always_off; + break; + default: + config.meter_provider.exemplar_filter = ExemplarFilter.trace_based; + break; + } } - if (meterProvider['readers'] && meterProvider['readers']?.length > 0) { + if (meterProvider['readers'] && meterProvider['readers'].length > 0) { config.meter_provider.readers = []; for (let i = 0; i < meterProvider['readers'].length; i++) { @@ -563,24 +793,12 @@ function setMeterProvider( getNumberFromConfigFile( element['exporter']['prometheus/development']['port'] ) ?? 9464, - without_units: - getBooleanFromConfigFile( - element['exporter']['prometheus/development'][ - 'without_units' - ] - ) ?? false, without_scope_info: getBooleanFromConfigFile( element['exporter']['prometheus/development'][ 'without_scope_info' ] ) ?? false, - without_type_suffix: - getBooleanFromConfigFile( - element['exporter']['prometheus/development'][ - 'without_type_suffix' - ] - ) ?? false, with_resource_constant_labels: { included: getStringListFromConfigFile( @@ -597,53 +815,218 @@ function setMeterProvider( }, }, }; - const producers: MetricProducer[] = [{ opencensus: undefined }]; - const defaultLimit = - getNumberFromConfigFile( - element['cardinality_limits']['default'] - ) ?? 2000; - const cardinalityLimits: CardinalityLimits = { - default: defaultLimit, - counter: - getNumberFromConfigFile( - element['cardinality_limits']['counter'] - ) ?? defaultLimit, - gauge: - getNumberFromConfigFile( - element['cardinality_limits']['gauge'] - ) ?? defaultLimit, - histogram: - getNumberFromConfigFile( - element['cardinality_limits']['histogram'] - ) ?? defaultLimit, - observable_counter: - getNumberFromConfigFile( - element['cardinality_limits']['observable_counter'] - ) ?? defaultLimit, - observable_gauge: - getNumberFromConfigFile( - element['cardinality_limits']['observable_gauge'] - ) ?? defaultLimit, - observable_up_down_counter: - getNumberFromConfigFile( - element['cardinality_limits']['observable_up_down_counter'] - ) ?? defaultLimit, - up_down_counter: - getNumberFromConfigFile( - element['cardinality_limits']['up_down_counter'] - ) ?? defaultLimit, - }; - const pullReader: ConfigReader = { + const pullReader: MetricReader = { pull: { exporter: exporter, - producers: producers, - cardinality_limits: cardinalityLimits, + cardinality_limits: getCardinalityLimits( + element['cardinality_limits'] + ), }, }; + const p = getProducers(element['producers']); + if (p.length > 0 && pullReader.pull) { + pullReader.pull.producers = p; + } config.meter_provider.readers.push(pullReader); } + } else if (readerType === 'periodic') { + const element = meterProvider['readers'][i]['periodic']; + if (element) { + const parsedExporter = parseMetricExporter(element['exporter']); + + const periodicReader: MetricReader = { + periodic: { + exporter: parsedExporter, + cardinality_limits: getCardinalityLimits( + element['cardinality_limits'] + ), + interval: getNumberFromConfigFile(element['interval']) ?? 60000, + timeout: getNumberFromConfigFile(element['timeout']) ?? 30000, + }, + }; + const p = getProducers(element['producers']); + if (p.length > 0 && periodicReader.periodic) { + periodicReader.periodic.producers = p; + } + config.meter_provider.readers.push(periodicReader); + } + } + } + } + + if (meterProvider['views'] && meterProvider['views'].length > 0) { + config.meter_provider.views = []; + for (let j = 0; j < meterProvider['views'].length; j++) { + const element = meterProvider['views'][j]; + const view: View = {}; + if (element['selector']) { + const selector: ViewSelector = {}; + const instrumentName = getStringFromConfigFile( + element['selector']['instrument_name'] + ); + if (instrumentName) { + selector.instrument_name = instrumentName; + } + + const unit = getStringFromConfigFile(element['selector']['unit']); + if (unit) { + selector.unit = unit; + } + + const meterName = getStringFromConfigFile( + element['selector']['meter_name'] + ); + if (meterName) { + selector.meter_name = meterName; + } + + const meterVersion = getStringFromConfigFile( + element['selector']['meter_version'] + ); + if (meterVersion) { + selector.meter_version = meterVersion; + } + + const meterSchemaUrl = getStringFromConfigFile( + element['selector']['meter_schema_url'] + ); + if (meterSchemaUrl) { + selector.meter_schema_url = meterSchemaUrl; + } + + const instrumentType = getStringFromConfigFile( + element['selector']['instrument_type'] + ); + if (instrumentType) { + switch (instrumentType) { + case 'counter': + selector.instrument_type = InstrumentType.counter; + break; + case 'gauge': + selector.instrument_type = InstrumentType.gauge; + break; + case 'histogram': + selector.instrument_type = InstrumentType.histogram; + break; + case 'observable_counter': + selector.instrument_type = InstrumentType.observable_counter; + break; + case 'observable_gauge': + selector.instrument_type = InstrumentType.observable_gauge; + break; + case 'observable_up_down_counter': + selector.instrument_type = + InstrumentType.observable_up_down_counter; + break; + case 'up_down_counter': + selector.instrument_type = InstrumentType.up_down_counter; + break; + } + } + + if (Object.keys(selector).length > 0) { + view.selector = selector; + } + } + if (element['stream']) { + const stream: ViewStream = {}; + const name = getStringFromConfigFile(element['stream']['name']); + if (name) { + stream.name = name; + } + + const description = getStringFromConfigFile( + element['stream']['description'] + ); + if (description) { + stream.description = description; + } + + const aggregationCardinalityLimit = getNumberFromConfigFile( + element['stream']['aggregation_cardinality_limit'] + ); + if (aggregationCardinalityLimit) { + stream.aggregation_cardinality_limit = aggregationCardinalityLimit; + } + + if (element['stream']['attribute_keys']) { + stream.attribute_keys = { + included: + getStringListFromConfigFile( + element['stream']['attribute_keys']['included'] + ) ?? [], + excluded: + getStringListFromConfigFile( + element['stream']['attribute_keys']['excluded'] + ) ?? [], + }; + } + const rawAgg = element['stream']['aggregation']; + if (rawAgg) { + const aggregation: Aggregation = {}; + if (rawAgg['default']) { + aggregation.default = {}; + } + if (rawAgg['drop']) { + aggregation.drop = {}; + } + if (rawAgg['last_value']) { + aggregation.last_value = {}; + } + if (rawAgg['sum']) { + aggregation.sum = {}; + } + if (rawAgg['explicit_bucket_histogram']) { + aggregation.explicit_bucket_histogram = { + boundaries: getNumberListFromConfigFile( + rawAgg['explicit_bucket_histogram']['boundaries'] + ) ?? [ + 0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, + 7500, 10000, + ], + record_min_max: + getBooleanFromConfigFile( + rawAgg['explicit_bucket_histogram']['record_min_max'] + ) === false + ? false + : true, + }; + } + if (rawAgg['base2_exponential_bucket_histogram']) { + aggregation.base2_exponential_bucket_histogram = { + record_min_max: + getBooleanFromConfigFile( + rawAgg['base2_exponential_bucket_histogram'][ + 'record_min_max' + ] + ) === false + ? false + : true, + }; + const maxScale = getNumberFromConfigFile( + rawAgg['base2_exponential_bucket_histogram']['max_scale'] + ); + if (maxScale) { + aggregation.base2_exponential_bucket_histogram.max_scale = + maxScale; + } + + const maxSize = getNumberFromConfigFile( + rawAgg['base2_exponential_bucket_histogram']['max_size'] + ); + if (maxSize) { + aggregation.base2_exponential_bucket_histogram.max_size = + maxSize; + } + } + stream.aggregation = aggregation; + } + if (Object.keys(stream).length > 0) { + view.stream = stream; + } } + config.meter_provider.views.push(view); } } } @@ -695,7 +1078,7 @@ function setLoggerProvider( if (processorType === 'batch') { const element = loggerProvider['processors'][i]['batch']; if (element) { - const parsedExporter = parseConfigExporter( + const parsedExporter = parseConfigSpanExporter( element['exporter'], ProviderType.LOGGER ); @@ -719,7 +1102,7 @@ function setLoggerProvider( } else if (processorType === 'simple') { const element = loggerProvider['processors'][i]['simple']; if (element) { - const parsedExporter = parseConfigExporter( + const parsedExporter = parseConfigSpanExporter( element['exporter'], ProviderType.LOGGER ); diff --git a/experimental/packages/opentelemetry-configuration/src/models/commonModel.ts b/experimental/packages/opentelemetry-configuration/src/models/commonModel.ts index 55a55535994..e757570388f 100644 --- a/experimental/packages/opentelemetry-configuration/src/models/commonModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/models/commonModel.ts @@ -23,7 +23,7 @@ export interface IncludeExclude { * * If the value of the attribute key matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. * If omitted, all attributes are included. */ - include: string[]; + included?: string[]; /** * Configure list of attribute key patterns to exclude from resource detectors. Applies after .resource.detectors.attributes.included (i.e. excluded has higher priority than included). @@ -32,7 +32,7 @@ export interface IncludeExclude { * * If the value of the attribute key matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. * If omitted, .included attributes are included. */ - exclude: string[]; + excluded?: string[]; } export interface NameStringValuePair { diff --git a/experimental/packages/opentelemetry-configuration/src/models/configModel.ts b/experimental/packages/opentelemetry-configuration/src/models/configModel.ts index b713fd2b84a..d114d3d851f 100644 --- a/experimental/packages/opentelemetry-configuration/src/models/configModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/models/configModel.ts @@ -26,7 +26,10 @@ import { LoggerProvider, } from './loggerProviderModel'; import { Resource } from './resourceModel'; -import { ExemplarFilter, MeterProvider } from './meterProviderModel'; +import { + initializeDefaultMeterProviderConfiguration, + MeterProvider, +} from './meterProviderModel'; export interface ConfigurationModel { /** @@ -94,25 +97,7 @@ export function initializeDefaultConfiguration(): ConfigurationModel { composite_list: 'tracecontext,baggage', }, tracer_provider: initializeDefaultTracerProviderConfiguration(), - meter_provider: { - readers: [ - { - periodic: { - interval: 60000, - timeout: 30000, - exporter: { - otlp_http: { - endpoint: 'http://localhost:4318/v1/metrics', - timeout: 10000, - temporality_preference: 'cumulative', - default_histogram_aggregation: 'explicit_bucket_histogram', - }, - }, - }, - }, - ], - exemplar_filter: ExemplarFilter.trace_based, - }, + meter_provider: initializeDefaultMeterProviderConfiguration(), logger_provider: initializeDefaultLoggerProviderConfiguration(), }; diff --git a/experimental/packages/opentelemetry-configuration/src/models/meterProviderModel.ts b/experimental/packages/opentelemetry-configuration/src/models/meterProviderModel.ts index e9183b8490a..0bf80eb45e7 100644 --- a/experimental/packages/opentelemetry-configuration/src/models/meterProviderModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/models/meterProviderModel.ts @@ -15,6 +15,35 @@ */ 'use strict'; +import { + IncludeExclude, + NameStringValuePair, + OtlpHttpEncoding, +} from './commonModel'; + +export function initializeDefaultMeterProviderConfiguration(): MeterProvider { + return { + readers: [ + { + periodic: { + interval: 60000, + timeout: 30000, + exporter: { + otlp_http: { + endpoint: 'http://localhost:4318/v1/metrics', + timeout: 10000, + temporality_preference: ExporterTemporalityPreference.cumulative, + default_histogram_aggregation: + ExporterDefaultHistogramAggregation.explicit_bucket_histogram, + }, + }, + }, + }, + ], + exemplar_filter: ExemplarFilter.trace_based, + }; +} + export interface MeterProvider { /** * Configure metric readers. @@ -26,7 +55,7 @@ export interface MeterProvider { * Each view has a selector which determines the instrument(s) it applies to, * and a configuration for the resulting stream(s). */ - view?: View; + views?: View[]; /** * Configure the exemplar filter. @@ -82,12 +111,12 @@ export interface PullMetricReader { /** * Configure metric producers. */ - producers: MetricProducer[]; + producers?: MetricProducer[]; /** * Configure cardinality limits. */ - cardinality_limits: CardinalityLimits; + cardinality_limits?: CardinalityLimits; } export interface CardinalityLimits { @@ -156,14 +185,413 @@ export interface PushMetricExporter { * Configure exporter to be OTLP with file transport. * This type is in development and subject to breaking changes in minor versions. */ - 'otlp_file/development': OtlpFileMetricExporter; + 'otlp_file/development'?: OtlpFileMetricExporter; /** * Configure exporter to be console. */ - console: object; + console?: object; +} + +export interface PullMetricExporter { + /** + * Configure exporter to be prometheus. + * This type is in development and subject to breaking changes in minor versions. + */ + 'prometheus/development': PrometheusMetricExporter; +} + +export interface MetricProducer { + /** + * Configure metric producer to be opencensus. + */ + opencensus?: object; + + /** + * Configure metric producer to be prometheus. + */ + prometheus?: object; +} + +export interface PrometheusMetricExporter { + /** + * Configure host. + * If omitted or null, localhost is used. + */ + host?: string; + + /** + * Configure port. + * If omitted or null, 9464 is used. + */ + port?: number; + + /** + * Configure Prometheus Exporter to produce metrics without a scope info metric. + * If omitted or null, false is used. + */ + without_scope_info?: boolean; + + /** + * Configure Prometheus Exporter to add resource attributes as metrics attributes. + */ + with_resource_constant_labels: IncludeExclude; } export interface MetricReader { + /** + * Configure a periodic metric reader. + */ + periodic?: PeriodicMetricReader; + + /** + * Configure a pull based metric reader. + */ + pull?: PullMetricReader; +} + +export interface OtlpHttpMetricExporter { + /** + * Configure endpoint, including the metric specific path. + * If omitted or null, http://localhost:4318/v1/metrics is used. + */ + endpoint?: string; + + /** + * Configure certificate used to verify a server's TLS credentials. + * Absolute path to certificate file in PEM format. + * If omitted or null, system default certificate verification is used for secure connections. + */ + certificate_file?: string; + + /** + * Configure mTLS private client key. + * Absolute path to client key file in PEM format. If set, .client_certificate must also be set. + * If omitted or null, mTLS is not used. + */ + client_key_file?: string; + + /** + * Configure mTLS client certificate. + * Absolute path to client certificate file in PEM format. If set, .client_key must also be set. + * If omitted or null, mTLS is not used. + */ + client_certificate_file?: string; + + /** + * Configure headers. Entries have higher priority than entries from .headers_list. + * If an entry's .value is null, the entry is ignored. + */ + headers?: NameStringValuePair[]; + + /** + * Configure headers. Entries have lower priority than entries from .headers. + * The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. + * If omitted or null, no headers are added. + */ + headers_list?: string; + + /** + * Configure compression. + * Values include: gzip, none. Implementations may support other compression algorithms. + * If omitted or null, none is used. + */ + compression?: string; + + /** + * Configure max time (in milliseconds) to wait for each export. + * Value must be non-negative. A value of 0 indicates no limit (infinity). + * If omitted or null, 10000 is used. + */ + timeout?: number; + + /** + * Configure the encoding used for messages. + * Values include: protobuf, json. Implementations may not support json. + * If omitted or null, protobuf is used. + */ + encoding?: OtlpHttpEncoding; + + /** + * Configure temporality preference. + * Values include: cumulative, delta, low_memory. + * If omitted or null, cumulative is used. + */ + temporality_preference?: ExporterTemporalityPreference; + + /** + * Configure default histogram aggregation. + * Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. + * If omitted or null, explicit_bucket_histogram is used. + */ + default_histogram_aggregation?: ExporterDefaultHistogramAggregation; +} + +export interface OtlpGrpcMetricExporter { + /** + * Configure endpoint. + * If omitted or null, http://localhost:4317 is used. + */ + endpoint?: string; + + /** + * Configure certificate used to verify a server's TLS credentials. + * Absolute path to certificate file in PEM format. + * If omitted or null, system default certificate verification is used for secure connections. + */ + certificate_file?: string; + + /** + * Configure mTLS private client key. + * Absolute path to client key file in PEM format. If set, .client_certificate must also be set. + * If omitted or null, mTLS is not used. + */ + client_key_file?: string; + + /** + * Configure mTLS client certificate. + * Absolute path to client certificate file in PEM format. If set, .client_key must also be set. + * If omitted or null, mTLS is not used. + */ + client_certificate_file?: string; + + /** + * Configure headers. Entries have higher priority than entries from .headers_list. + * If an entry's .value is null, the entry is ignored. + */ + headers?: NameStringValuePair[]; + + /** + * Configure headers. Entries have lower priority than entries from .headers. + * The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. + * If omitted or null, no headers are added. + */ + headers_list?: string; + + /** + * Configure compression. + * Values include: gzip, none. Implementations may support other compression algorithms. + * If omitted or null, none is used. + */ + compression?: string; + + /** + * Configure max time (in milliseconds) to wait for each export. + * Value must be non-negative. A value of 0 indicates no limit (infinity). + * If omitted or null, 10000 is used. + */ + timeout?: number; + + /** + * Configure client transport security for the exporter's connection. + * Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. + * If omitted or null, false is used. + */ + insecure?: boolean; + + /** + * Configure temporality preference. + * Values include: cumulative, delta, low_memory. + * If omitted or null, cumulative is used. + */ + temporality_preference?: ExporterTemporalityPreference; + + /** + * Configure default histogram aggregation. + * Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. + * If omitted or null, explicit_bucket_histogram is used. + */ + default_histogram_aggregation?: ExporterDefaultHistogramAggregation; +} + +export interface OtlpFileMetricExporter { + /** + * Configure output stream. + * Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. + * If omitted or null, stdout is used. + */ + output_stream?: string; + + /** + * Configure temporality preference. + * Values include: cumulative, delta, low_memory. + * If omitted or null, cumulative is used. + */ + temporality_preference?: ExporterTemporalityPreference; + + /** + * Configure default histogram aggregation. + * Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. + * If omitted or null, explicit_bucket_histogram is used. + */ + default_histogram_aggregation?: ExporterDefaultHistogramAggregation; +} + +export enum ExporterTemporalityPreference { + cumulative, + delta, + low_memory, +} + +export enum ExporterDefaultHistogramAggregation { + explicit_bucket_histogram, + base2_exponential_bucket_histogram, +} + +export interface View { + /** + * Configure view selector. + */ + selector?: ViewSelector; + + /** + * Configure view stream. + */ + stream?: ViewStream; +} + +export interface ViewSelector { + /** + * Configure instrument name selection criteria. + * If omitted or null, all instrument names match. + */ + instrument_name?: string; + + /** + * Configure instrument type selection criteria. + * Values include: counter, gauge, histogram, observable_counter, observable_gauge, + * observable_up_down_counter, up_down_counter. + * If omitted or null, all instrument types match. + */ + instrument_type?: InstrumentType; + + /** + * Configure the instrument unit selection criteria. + * If omitted or null, all instrument units match. + */ + unit?: string; + + /** + * Configure meter name selection criteria. + * If omitted or null, all meter names match. + */ + meter_name?: string; + + /** + * Configure meter version selection criteria. + * If omitted or null, all meter versions match. + */ + meter_version?: string; + + /** + * Configure meter schema url selection criteria. + * If omitted or null, all meter schema URLs match. + */ + meter_schema_url?: string; +} + +export enum InstrumentType { + counter, + gauge, + histogram, + observable_counter, + observable_gauge, + observable_up_down_counter, + up_down_counter, +} +export interface ViewStream { + /** + * Configure metric name of the resulting stream(s). + * If omitted or null, the instrument's original name is used. + */ + name?: string; + + /** + * Configure metric description of the resulting stream(s). + * If omitted or null, the instrument's origin description is used. + */ + description?: string; + + /** + * Configure aggregation of the resulting stream(s). + * Values include: default, drop, explicit_bucket_histogram, base2_exponential_bucket_histogram, last_value, sum. + * If omitted, default is used. + */ + aggregation?: Aggregation; + + /** + * Configure the aggregation cardinality limit. + * If omitted or null, the metric reader's default cardinality limit is used. + */ + aggregation_cardinality_limit?: number; + + /** + * Configure attribute keys retained in the resulting stream(s). + */ + attribute_keys?: IncludeExclude; +} + +export interface Aggregation { + /** + * Configure aggregation to be default. + */ + default?: object; + + /** + * Configure aggregation to be drop. + */ + drop?: object; + + /** + * Configure aggregation to be explicit_bucket_histogram. + */ + explicit_bucket_histogram?: ExplicitBucketHistogramAggregation; + + /** + * Configure aggregation to be base2_exponential_bucket_histogram. + */ + base2_exponential_bucket_histogram?: Base2ExponentialBucketHistogramAggregation; + + /** + * Configure aggregation to be last_value. + */ + last_value?: object; + + /** + * Configure aggregation to be sum. + */ + sum?: object; +} + +export interface ExplicitBucketHistogramAggregation { + /** + * Configure bucket boundaries. + * If omitted, [0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000] is used. + */ + boundaries?: number[]; + + /** + * Configure record min and max. + * If omitted or null, true is used. + */ + record_min_max?: boolean; +} + +export interface Base2ExponentialBucketHistogramAggregation { + /** + * Configure max_scale. + */ + max_scale?: number; + + /** + * Configure max_size. + */ + max_size?: number; + + /** + * Configure record min and max. + * If omitted or null, true is used. + */ + record_min_max?: boolean; } diff --git a/experimental/packages/opentelemetry-configuration/src/utils.ts b/experimental/packages/opentelemetry-configuration/src/utils.ts index 5c3855d9546..211092d51ac 100644 --- a/experimental/packages/opentelemetry-configuration/src/utils.ts +++ b/experimental/packages/opentelemetry-configuration/src/utils.ts @@ -111,7 +111,7 @@ export function getNumberListFromConfigFile( const filteredList = []; for (let i = 0; i < list.length; i++) { const element = getNumberFromConfigFile(list[i]); - if (element) { + if (element || element === 0) { filteredList.push(element); } } diff --git a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts index 35e2716274b..c2d3b0de173 100644 --- a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts +++ b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts @@ -19,6 +19,12 @@ import { Configuration } from '../src'; import { DiagLogLevel } from '@opentelemetry/api'; import { createConfigProvider } from '../src/ConfigProvider'; import { OtlpHttpEncoding } from '../src/models/commonModel'; +import { + ExemplarFilter, + ExporterDefaultHistogramAggregation, + ExporterTemporalityPreference, + InstrumentType, +} from '../src/models/meterProviderModel'; const defaultConfig: Configuration = { disabled: false, @@ -77,14 +83,15 @@ const defaultConfig: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/metrics', timeout: 10000, - temporality_preference: 'cumulative', - default_histogram_aggregation: 'explicit_bucket_histogram', + temporality_preference: ExporterTemporalityPreference.cumulative, + default_histogram_aggregation: + ExporterDefaultHistogramAggregation.explicit_bucket_histogram, }, }, }, }, ], - exemplar_filter: 'trace_based', + exemplar_filter: ExemplarFilter.trace_based, }, logger_provider: { processors: [ @@ -268,7 +275,7 @@ const configFromFile: Configuration = { { simple: { exporter: { - console: {}, + console: undefined, }, }, }, @@ -300,8 +307,6 @@ const configFromFile: Configuration = { 'prometheus/development': { host: 'localhost', port: 9464, - without_units: false, - without_type_suffix: false, without_scope_info: false, with_resource_constant_labels: { included: ['service*'], @@ -311,7 +316,7 @@ const configFromFile: Configuration = { }, producers: [ { - opencensus: null, + opencensus: undefined, }, ], cardinality_limits: { @@ -326,22 +331,184 @@ const configFromFile: Configuration = { }, }, }, - // { - // periodic: { - // interval: 60000, - // timeout: 30000, - // exporter: { - // otlp_http: { - // endpoint: 'http://localhost:4318/v1/metrics', - // timeout: 10000, - // temporality_preference: 'cumulative', - // default_histogram_aggregation: 'explicit_bucket_histogram', - // }, - // }, - // }, - // }, + { + periodic: { + interval: 60000, + timeout: 30000, + exporter: { + otlp_http: { + endpoint: 'http://localhost:4318/v1/metrics', + certificate_file: '/app/cert.pem', + client_key_file: '/app/cert.pem', + client_certificate_file: '/app/cert.pem', + headers: [ + { + name: 'api-key', + value: '1234', + }, + ], + headers_list: 'api-key=1234', + compression: 'gzip', + timeout: 10000, + encoding: OtlpHttpEncoding.protobuf, + temporality_preference: ExporterTemporalityPreference.delta, + default_histogram_aggregation: + ExporterDefaultHistogramAggregation.base2_exponential_bucket_histogram, + }, + }, + producers: [ + { + prometheus: undefined, + }, + ], + cardinality_limits: { + default: 2000, + counter: 2000, + gauge: 2000, + histogram: 2000, + observable_counter: 2000, + observable_gauge: 2000, + observable_up_down_counter: 2000, + up_down_counter: 2000, + }, + }, + }, + { + periodic: { + interval: 60000, + timeout: 30000, + exporter: { + otlp_grpc: { + endpoint: 'http://localhost:4317', + certificate_file: '/app/cert.pem', + client_key_file: '/app/cert.pem', + client_certificate_file: '/app/cert.pem', + headers: [ + { + name: 'api-key', + value: '1234', + }, + ], + headers_list: 'api-key=1234', + compression: 'gzip', + timeout: 10000, + insecure: false, + temporality_preference: ExporterTemporalityPreference.delta, + default_histogram_aggregation: + ExporterDefaultHistogramAggregation.base2_exponential_bucket_histogram, + }, + }, + cardinality_limits: { + default: 2000, + counter: 2000, + gauge: 2000, + histogram: 2000, + observable_counter: 2000, + observable_gauge: 2000, + observable_up_down_counter: 2000, + up_down_counter: 2000, + }, + }, + }, + { + periodic: { + timeout: 30000, + interval: 60000, + exporter: { + 'otlp_file/development': { + output_stream: 'file:///var/log/metrics.jsonl', + temporality_preference: ExporterTemporalityPreference.delta, + default_histogram_aggregation: + ExporterDefaultHistogramAggregation.base2_exponential_bucket_histogram, + }, + }, + cardinality_limits: { + default: 2000, + counter: 2000, + gauge: 2000, + histogram: 2000, + observable_counter: 2000, + observable_gauge: 2000, + observable_up_down_counter: 2000, + up_down_counter: 2000, + }, + }, + }, + { + periodic: { + timeout: 30000, + interval: 60000, + exporter: { + 'otlp_file/development': { + output_stream: 'stdout', + temporality_preference: ExporterTemporalityPreference.delta, + default_histogram_aggregation: + ExporterDefaultHistogramAggregation.base2_exponential_bucket_histogram, + }, + }, + cardinality_limits: { + default: 2000, + counter: 2000, + gauge: 2000, + histogram: 2000, + observable_counter: 2000, + observable_gauge: 2000, + observable_up_down_counter: 2000, + up_down_counter: 2000, + }, + }, + }, + { + periodic: { + timeout: 30000, + interval: 60000, + exporter: { + console: undefined, + }, + cardinality_limits: { + default: 2000, + counter: 2000, + gauge: 2000, + histogram: 2000, + observable_counter: 2000, + observable_gauge: 2000, + observable_up_down_counter: 2000, + up_down_counter: 2000, + }, + }, + }, + ], + exemplar_filter: ExemplarFilter.trace_based, + views: [ + { + selector: { + instrument_name: 'my-instrument', + instrument_type: InstrumentType.histogram, + unit: 'ms', + meter_name: 'my-meter', + meter_version: '1.0.0', + meter_schema_url: 'https://opentelemetry.io/schemas/1.16.0', + }, + stream: { + name: 'new_instrument_name', + description: 'new_description', + aggregation: { + explicit_bucket_histogram: { + boundaries: [ + 0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, + 7500, 10000, + ], + record_min_max: true, + }, + }, + aggregation_cardinality_limit: 2000, + attribute_keys: { + included: ['key1', 'key2'], + excluded: ['key3'], + }, + }, + }, ], - exemplar_filter: 'trace_based', }, logger_provider: { processors: [ @@ -416,7 +583,7 @@ const configFromFile: Configuration = { { simple: { exporter: { - console: {}, + console: undefined, }, }, }, @@ -441,386 +608,6 @@ const configFromFile: Configuration = { }, }; -// # Configure metric readers. -// readers: -// - # Configure a periodic metric reader. -// periodic: -// # Configure delay interval (in milliseconds) between start of two consecutive exports. -// # Value must be non-negative. -// # If omitted or null, 60000 is used. -// interval: 60000 -// # Configure maximum allowed time (in milliseconds) to export data. -// # Value must be non-negative. A value of 0 indicates no limit (infinity). -// # If omitted or null, 30000 is used. -// timeout: 30000 -// # Configure exporter. -// exporter: -// # Configure exporter to be OTLP with HTTP transport. -// otlp_http: -// # Configure endpoint, including the metric specific path. -// # If omitted or null, http://localhost:4318/v1/metrics is used. -// endpoint: http://localhost:4318/v1/metrics -// # Configure certificate used to verify a server's TLS credentials. -// # Absolute path to certificate file in PEM format. -// # If omitted or null, system default certificate verification is used for secure connections. -// certificate_file: /app/cert.pem -// # Configure mTLS private client key. -// # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. -// # If omitted or null, mTLS is not used. -// client_key_file: /app/cert.pem -// # Configure mTLS client certificate. -// # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. -// # If omitted or null, mTLS is not used. -// client_certificate_file: /app/cert.pem -// # Configure headers. Entries have higher priority than entries from .headers_list. -// # If an entry's .value is null, the entry is ignored. -// headers: -// - name: api-key -// value: "1234" -// # Configure headers. Entries have lower priority than entries from .headers. -// # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. -// # If omitted or null, no headers are added. -// headers_list: "api-key=1234" -// # Configure compression. -// # Values include: gzip, none. Implementations may support other compression algorithms. -// # If omitted or null, none is used. -// compression: gzip -// # Configure max time (in milliseconds) to wait for each export. -// # Value must be non-negative. A value of 0 indicates no limit (infinity). -// # If omitted or null, 10000 is used. -// timeout: 10000 -// # Configure the encoding used for messages. -// # Values include: protobuf, json. Implementations may not support json. -// # If omitted or null, protobuf is used. -// encoding: protobuf -// # Configure temporality preference. -// # Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. -// # If omitted or null, cumulative is used. -// temporality_preference: delta -// # Configure default histogram aggregation. -// # Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. -// # If omitted or null, explicit_bucket_histogram is used. -// default_histogram_aggregation: base2_exponential_bucket_histogram -// # Configure metric producers. -// producers: -// - # Configure metric producer to be prometheus. -// prometheus: -// # Configure cardinality limits. -// cardinality_limits: -// # Configure default cardinality limit for all instrument types. -// # Instrument-specific cardinality limits take priority. -// # If omitted or null, 2000 is used. -// default: 2000 -// # Configure default cardinality limit for counter instruments. -// # If omitted or null, the value from .default is used. -// counter: 2000 -// # Configure default cardinality limit for gauge instruments. -// # If omitted or null, the value from .default is used. -// gauge: 2000 -// # Configure default cardinality limit for histogram instruments. -// # If omitted or null, the value from .default is used. -// histogram: 2000 -// # Configure default cardinality limit for observable_counter instruments. -// # If omitted or null, the value from .default is used. -// observable_counter: 2000 -// # Configure default cardinality limit for observable_gauge instruments. -// # If omitted or null, the value from .default is used. -// observable_gauge: 2000 -// # Configure default cardinality limit for observable_up_down_counter instruments. -// # If omitted or null, the value from .default is used. -// observable_up_down_counter: 2000 -// # Configure default cardinality limit for up_down_counter instruments. -// # If omitted or null, the value from .default is used. -// up_down_counter: 2000 -// - # Configure a periodic metric reader. -// periodic: -// # Configure exporter. -// exporter: -// # Configure exporter to be OTLP with gRPC transport. -// otlp_grpc: -// # Configure endpoint. -// # If omitted or null, http://localhost:4317 is used. -// endpoint: http://localhost:4317 -// # Configure certificate used to verify a server's TLS credentials. -// # Absolute path to certificate file in PEM format. -// # If omitted or null, system default certificate verification is used for secure connections. -// certificate_file: /app/cert.pem -// # Configure mTLS private client key. -// # Absolute path to client key file in PEM format. If set, .client_certificate must also be set. -// # If omitted or null, mTLS is not used. -// client_key_file: /app/cert.pem -// # Configure mTLS client certificate. -// # Absolute path to client certificate file in PEM format. If set, .client_key must also be set. -// # If omitted or null, mTLS is not used. -// client_certificate_file: /app/cert.pem -// # Configure headers. Entries have higher priority than entries from .headers_list. -// # If an entry's .value is null, the entry is ignored. -// headers: -// - name: api-key -// value: "1234" -// # Configure headers. Entries have lower priority than entries from .headers. -// # The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options for details. -// # If omitted or null, no headers are added. -// headers_list: "api-key=1234" -// # Configure compression. -// # Values include: gzip, none. Implementations may support other compression algorithms. -// # If omitted or null, none is used. -// compression: gzip -// # Configure max time (in milliseconds) to wait for each export. -// # Value must be non-negative. A value of 0 indicates no limit (infinity). -// # If omitted or null, 10000 is used. -// timeout: 10000 -// # Configure client transport security for the exporter's connection. -// # Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. -// # If omitted or null, false is used. -// insecure: false -// # Configure temporality preference. -// # Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. -// # If omitted or null, cumulative is used. -// temporality_preference: delta -// # Configure default histogram aggregation. -// # Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. -// # If omitted or null, explicit_bucket_histogram is used. -// default_histogram_aggregation: base2_exponential_bucket_histogram -// - # Configure a periodic metric reader. -// periodic: -// # Configure exporter. -// exporter: -// # Configure exporter to be OTLP with file transport. -// # This type is in development and subject to breaking changes in minor versions. -// otlp_file/development: -// # Configure output stream. -// # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. -// # If omitted or null, stdout is used. -// output_stream: file:///var/log/metrics.jsonl -// # Configure temporality preference. Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. -// # If omitted or null, cumulative is used. -// temporality_preference: delta -// # Configure default histogram aggregation. Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. -// # If omitted or null, explicit_bucket_histogram is used. -// default_histogram_aggregation: base2_exponential_bucket_histogram -// - # Configure a periodic metric reader. -// periodic: -// # Configure exporter. -// exporter: -// # Configure exporter to be OTLP with file transport. -// # This type is in development and subject to breaking changes in minor versions. -// otlp_file/development: -// # Configure output stream. -// # Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. -// # If omitted or null, stdout is used. -// output_stream: stdout -// # Configure temporality preference. Values include: cumulative, delta, low_memory. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. -// # If omitted or null, cumulative is used. -// temporality_preference: delta -// # Configure default histogram aggregation. Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. For behavior of values, see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk_exporters/otlp.md. -// # If omitted or null, explicit_bucket_histogram is used. -// default_histogram_aggregation: base2_exponential_bucket_histogram -// - # Configure a periodic metric reader. -// periodic: -// # Configure exporter. -// exporter: -// # Configure exporter to be console. -// console: -// # Configure views. -// # Each view has a selector which determines the instrument(s) it applies to, and a configuration for the resulting stream(s). -// views: -// - # Configure view selector. -// # Selection criteria is additive as described in https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#instrument-selection-criteria. -// selector: -// # Configure instrument name selection criteria. -// # If omitted or null, all instrument names match. -// instrument_name: my-instrument -// # Configure instrument type selection criteria. -// # Values include: counter, gauge, histogram, observable_counter, observable_gauge, observable_up_down_counter, up_down_counter. -// # If omitted or null, all instrument types match. -// instrument_type: histogram -// # Configure the instrument unit selection criteria. -// # If omitted or null, all instrument units match. -// unit: ms -// # Configure meter name selection criteria. -// # If omitted or null, all meter names match. -// meter_name: my-meter -// # Configure meter version selection criteria. -// # If omitted or null, all meter versions match. -// meter_version: 1.0.0 -// # Configure meter schema url selection criteria. -// # If omitted or null, all meter schema URLs match. -// meter_schema_url: https://opentelemetry.io/schemas/1.16.0 -// # Configure view stream. -// stream: -// # Configure metric name of the resulting stream(s). -// # If omitted or null, the instrument's original name is used. -// name: new_instrument_name -// # Configure metric description of the resulting stream(s). -// # If omitted or null, the instrument's origin description is used. -// description: new_description -// # Configure aggregation of the resulting stream(s). -// # Values include: default, drop, explicit_bucket_histogram, base2_exponential_bucket_histogram, last_value, sum. For behavior of values see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#aggregation. -// # If omitted, default is used. -// aggregation: -// # Configure aggregation to be explicit_bucket_histogram. -// explicit_bucket_histogram: -// # Configure bucket boundaries. -// # If omitted, [0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000] is used. -// boundaries: -// [ -// 0.0, -// 5.0, -// 10.0, -// 25.0, -// 50.0, -// 75.0, -// 100.0, -// 250.0, -// 500.0, -// 750.0, -// 1000.0, -// 2500.0, -// 5000.0, -// 7500.0, -// 10000.0 -// ] -// # Configure record min and max. -// # If omitted or null, true is used. -// record_min_max: true -// # Configure the aggregation cardinality limit. -// # If omitted or null, the metric reader's default cardinality limit is used. -// aggregation_cardinality_limit: 2000 -// # Configure attribute keys retained in the resulting stream(s). -// attribute_keys: -// # Configure list of attribute keys to include in the resulting stream(s). All other attributes are dropped. -// # If omitted, all attributes are included. -// included: -// - key1 -// - key2 -// # Configure list of attribute keys to exclude from the resulting stream(s). Applies after .attribute_keys.included (i.e. excluded has higher priority than included). -// # If omitted, .attribute_keys.included are included. -// excluded: -// - key3 -// # Configure the exemplar filter. -// # Values include: trace_based, always_on, always_off. For behavior of values see https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#metrics-sdk-configuration. -// # If omitted or null, trace_based is used. -// exemplar_filter: trace_based -// # Configure meters. -// # This type is in development and subject to breaking changes in minor versions. -// meter_configurator/development: -// # Configure the default meter config used there is no matching entry in .meter_configurator/development.meters. -// default_config: -// # Configure if the meter is enabled or not. -// disabled: true -// # Configure meters. -// meters: -// - # Configure meter names to match, evaluated as follows: -// # -// # * If the meter name exactly matches. -// # * If the meter name matches the wildcard pattern, where '?' matches any single character and '*' matches any number of characters including none. -// name: io.opentelemetry.contrib.* -// # The meter config. -// config: -// # Configure if the meter is enabled or not. -// disabled: false - -// const defaultConfigFromFileWithEnvVariables: Configuration = { -// disabled: false, -// log_level: DiagLogLevel.INFO, -// node_resource_detectors: ['all'], -// resource: { -// attributes: [ -// { -// name: 'service.name', -// value: 'unknown_service', -// type: 'string', -// }, -// ], -// }, -// attribute_limits: { -// attribute_count_limit: 128, -// }, -// propagator: { -// composite: [{ tracecontext: null }, { baggage: null }], -// composite_list: 'tracecontext,baggage', -// }, -// tracer_provider: { -// processors: [ -// { -// batch: { -// schedule_delay: 5000, -// export_timeout: 30000, -// max_queue_size: 2048, -// max_export_batch_size: 512, -// exporter: { -// otlp_http: { -// endpoint: 'http://localhost:4318/v1/traces', -// timeout: 10000, -// encoding: 'protobuf', -// compression: 'gzip', -// }, -// }, -// }, -// }, -// ], -// limits: { -// attribute_count_limit: 128, -// event_count_limit: 128, -// link_count_limit: 128, -// event_attribute_count_limit: 128, -// link_attribute_count_limit: 128, -// }, -// sampler: { -// parent_based: { -// root: 'always_on', -// remote_parent_sampled: 'always_on', -// remote_parent_not_sampled: 'always_off', -// local_parent_sampled: 'always_on', -// local_parent_not_sampled: 'always_off', -// }, -// }, -// }, -// meter_provider: { -// readers: [ -// { -// periodic: { -// interval: 60000, -// timeout: 30000, -// exporter: { -// otlp_http: { -// endpoint: 'http://localhost:4318/v1/metrics', -// timeout: 10000, -// temporality_preference: 'cumulative', -// default_histogram_aggregation: 'explicit_bucket_histogram', -// }, -// }, -// }, -// }, -// ], -// exemplar_filter: 'trace_based', -// }, -// logger_provider: { -// processors: [ -// { -// batch: { -// schedule_delay: 1000, -// export_timeout: 30000, -// max_queue_size: 2048, -// max_export_batch_size: 512, -// exporter: { -// otlp_http: { -// endpoint: 'http://localhost:4318/v1/logs', -// timeout: 10000, -// encoding: 'protobuf', -// compression: 'gzip', -// }, -// }, -// }, -// }, -// ], -// limits: { -// attribute_count_limit: 128, -// }, -// }, -// }; - const defaultConfigFromFileWithEnvVariables: Configuration = { disabled: false, log_level: DiagLogLevel.INFO, @@ -886,15 +673,28 @@ const defaultConfigFromFileWithEnvVariables: Configuration = { exporter: { otlp_http: { endpoint: 'http://localhost:4318/v1/metrics', + encoding: OtlpHttpEncoding.protobuf, + compression: 'gzip', timeout: 10000, - temporality_preference: 'cumulative', - default_histogram_aggregation: 'explicit_bucket_histogram', + temporality_preference: ExporterTemporalityPreference.cumulative, + default_histogram_aggregation: + ExporterDefaultHistogramAggregation.explicit_bucket_histogram, }, }, + cardinality_limits: { + default: 2000, + counter: 2000, + gauge: 2000, + histogram: 2000, + observable_counter: 2000, + observable_gauge: 2000, + observable_up_down_counter: 2000, + up_down_counter: 2000, + }, }, }, ], - exemplar_filter: 'trace_based', + exemplar_filter: ExemplarFilter.trace_based, }, logger_provider: { processors: [ @@ -1203,15 +1003,15 @@ describe('ConfigProvider', function () { compression: 'gzip', timeout: 300, headers_list: 'host=localhost', - temporality_preference: 'delta', + temporality_preference: ExporterTemporalityPreference.delta, default_histogram_aggregation: - 'base2_exponential_bucket_histogram', + ExporterDefaultHistogramAggregation.base2_exponential_bucket_histogram, }, }, }, }, ], - exemplar_filter: 'always_on', + exemplar_filter: ExemplarFilter.always_on, }, }; const configProvider = createConfigProvider(); @@ -1415,7 +1215,8 @@ describe('ConfigProvider', function () { process.env.OTEL_LINK_ATTRIBUTE_COUNT_LIMIT = '19'; process.env.OTEL_METRIC_EXPORT_INTERVAL = '20'; process.env.OTEL_METRIC_EXPORT_TIMEOUT = '21'; - process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'metric-endpoint'; + process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = + 'http://test:4318/v1/metrics'; process.env.OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE = 'metric-certificate'; process.env.OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY = 'metric-client-key'; process.env.OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE = @@ -1498,8 +1299,41 @@ describe('ConfigProvider', function () { ], }, meter_provider: { - ...defaultConfigFromFileWithEnvVariables.meter_provider, - exemplar_filter: 'always_off', + exemplar_filter: ExemplarFilter.always_off, + readers: [ + { + periodic: { + interval: 20, + timeout: 21, + exporter: { + otlp_http: { + endpoint: 'http://test:4318/v1/metrics', + timeout: 22, + temporality_preference: + ExporterTemporalityPreference.cumulative, + default_histogram_aggregation: + ExporterDefaultHistogramAggregation.explicit_bucket_histogram, + certificate_file: 'metric-certificate', + client_certificate_file: 'metric-client-certificate', + client_key_file: 'metric-client-key', + compression: 'metric-compression', + encoding: OtlpHttpEncoding.protobuf, + headers_list: 'metric-header', + }, + }, + cardinality_limits: { + default: 2000, + counter: 2000, + gauge: 2000, + histogram: 2000, + observable_counter: 2000, + observable_gauge: 2000, + observable_up_down_counter: 2000, + up_down_counter: 2000, + }, + }, + }, + ], }, logger_provider: { ...defaultConfigFromFileWithEnvVariables.logger_provider, From 3e8249da8b4c60784e48de69c44258c3f00cea7f Mon Sep 17 00:00:00 2001 From: maryliag Date: Thu, 9 Oct 2025 14:54:17 -0400 Subject: [PATCH 21/27] cleanup --- .../src/models/configModel.ts | 73 ------------------- 1 file changed, 73 deletions(-) diff --git a/experimental/packages/opentelemetry-configuration/src/models/configModel.ts b/experimental/packages/opentelemetry-configuration/src/models/configModel.ts index d114d3d851f..18f287de313 100644 --- a/experimental/packages/opentelemetry-configuration/src/models/configModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/models/configModel.ts @@ -16,7 +16,6 @@ 'use strict'; import { DiagLogLevel } from '@opentelemetry/api'; -import { NameStringValuePair } from './commonModel'; import { initializeDefaultTracerProviderConfiguration, TracerProvider, @@ -140,75 +139,3 @@ export interface Propagator { */ composite_list?: string; } - -export interface ConfigMeterOTLPHttp { - /** - * Configure endpoint, including the metric specific path. - * If omitted or null, http://localhost:4318/v1/metrics is used. - */ - endpoint: string; - - /** - * Configure certificate used to verify a server's TLS credentials. - * Absolute path to certificate file in PEM format. - * If omitted or null, system default certificate verification is used for secure connections. - */ - certificate_file?: string; - - /** - * Configure mTLS private client key. - * Absolute path to client key file in PEM format. If set, .client_certificate must also be set. - * If omitted or null, mTLS is not used. - */ - client_key_file?: string; - - /** - * Configure mTLS client certificate. - * Absolute path to client certificate file in PEM format. If set, .client_key must also be set. - * If omitted or null, mTLS is not used. - */ - client_certificate_file?: string; - - /** - * Configure compression. - * Values include: gzip, none. Implementations may support other compression algorithms. - * If omitted or null, none is used. - */ - compression?: string; - - /** - * Configure max time (in milliseconds) to wait for each export. - * Value must be non-negative. A value of 0 indicates no limit (infinity). - * If omitted or null, 10000 is used. - */ - timeout: number; - - /** - * Configure headers. Entries have higher priority than entries from .headers_list. - * If an entry's .value is null, the entry is ignored. - */ - headers?: NameStringValuePair[]; - - /** - * Configure headers. Entries have lower priority than entries from .headers. - * The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. - * If omitted or null, no headers are added. - */ - headers_list?: string; - - /** - * Configure temporality preference. - * Values include: cumulative, delta, low_memory. - * If omitted or null, cumulative is used. - */ - temporality_preference: 'cumulative' | 'delta' | 'low_memory'; - - /** - * Configure default histogram aggregation. - * Values include: explicit_bucket_histogram, base2_exponential_bucket_histogram. - * If omitted or null, explicit_bucket_histogram is used. - */ - default_histogram_aggregation: - | 'explicit_bucket_histogram' - | 'base2_exponential_bucket_histogram'; -} From 5d1e76a715b072801824d1ed0bc5f448314243ad Mon Sep 17 00:00:00 2001 From: maryliag Date: Thu, 9 Oct 2025 14:57:07 -0400 Subject: [PATCH 22/27] update changelog --- experimental/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index 7023e37d6e9..f52d6a4c232 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -37,7 +37,7 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2 * feat(exporter-prometheus): support withoutTargetInfo option [#5962](https://github.com/open-telemetry/opentelemetry-js/pull/5962) @cjihrig * feat(opentelemetry-configuration): parse trace provider from config file [#5992](https://github.com/open-telemetry/opentelemetry-js/pull/5992) @maryliag * feat(opentelemetry-configuration): parse logger provider from config file [#5995](https://github.com/open-telemetry/opentelemetry-js/pull/5995) @maryliag -* feat(opentelemetry-configuration): parse meter provider from config file [#5995](https://github.com/open-telemetry/opentelemetry-js/pull/5995) @maryliag +* feat(opentelemetry-configuration): parse meter provider from config file [#6000](https://github.com/open-telemetry/opentelemetry-js/pull/6000) @maryliag ### :bug: Bug Fixes From 08ec75b845701f0c85868fb3b22d8e1fb610df9d Mon Sep 17 00:00:00 2001 From: maryliag Date: Thu, 9 Oct 2025 15:02:26 -0400 Subject: [PATCH 23/27] add test --- .../packages/opentelemetry-configuration/test/utils.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/experimental/packages/opentelemetry-configuration/test/utils.test.ts b/experimental/packages/opentelemetry-configuration/test/utils.test.ts index 58eed2fcebd..5638e82ac4f 100644 --- a/experimental/packages/opentelemetry-configuration/test/utils.test.ts +++ b/experimental/packages/opentelemetry-configuration/test/utils.test.ts @@ -95,6 +95,7 @@ describe('config utils', function () { assert.deepStrictEqual(getNumberListFromConfigFile(null), undefined); assert.deepStrictEqual(getNumberListFromConfigFile(' '), undefined); assert.deepStrictEqual(getNumberListFromConfigFile(' , '), []); + assert.deepStrictEqual(getNumberListFromConfigFile('0'), [0]); assert.deepStrictEqual(getNumberListFromConfigFile(5), [5]); assert.deepStrictEqual(getNumberListFromConfigFile('7'), [7]); assert.deepStrictEqual( From 22d89f0b74a985e232f437cd972ae5c7c454bf7d Mon Sep 17 00:00:00 2001 From: maryliag Date: Thu, 9 Oct 2025 20:15:20 -0400 Subject: [PATCH 24/27] update enums --- .../src/EnvironmentConfigProvider.ts | 22 +++--- .../src/FileConfigProvider.ts | 44 ++++++------ .../src/models/commonModel.ts | 4 +- .../src/models/loggerProviderModel.ts | 2 +- .../src/models/meterProviderModel.ts | 36 +++++----- .../src/models/tracerProviderModel.ts | 2 +- .../test/ConfigProvider.test.ts | 70 +++++++++---------- 7 files changed, 90 insertions(+), 90 deletions(-) diff --git a/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts index 10ba87bbaae..9fcaccbcc82 100644 --- a/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts @@ -322,19 +322,19 @@ function setMeterProvider(config: ConfigurationModel): void { switch (temporalityPreference) { case 'cumulative': readerPeriodic.exporter.otlp_http.temporality_preference = - ExporterTemporalityPreference.cumulative; + ExporterTemporalityPreference.Cumulative; break; case 'delta': readerPeriodic.exporter.otlp_http.temporality_preference = - ExporterTemporalityPreference.delta; + ExporterTemporalityPreference.Delta; break; case 'low_memory': readerPeriodic.exporter.otlp_http.temporality_preference = - ExporterTemporalityPreference.low_memory; + ExporterTemporalityPreference.LowMemory; break; default: readerPeriodic.exporter.otlp_http.temporality_preference = - ExporterTemporalityPreference.cumulative; + ExporterTemporalityPreference.Cumulative; break; } } @@ -346,15 +346,15 @@ function setMeterProvider(config: ConfigurationModel): void { switch (defaultHistogramAggregation) { case 'explicit_bucket_histogram': readerPeriodic.exporter.otlp_http.default_histogram_aggregation = - ExporterDefaultHistogramAggregation.explicit_bucket_histogram; + ExporterDefaultHistogramAggregation.ExplicitBucketHistogram; break; case 'base2_exponential_bucket_histogram': readerPeriodic.exporter.otlp_http.default_histogram_aggregation = - ExporterDefaultHistogramAggregation.base2_exponential_bucket_histogram; + ExporterDefaultHistogramAggregation.Base2ExponentialBucketHistogram; break; default: readerPeriodic.exporter.otlp_http.default_histogram_aggregation = - ExporterDefaultHistogramAggregation.explicit_bucket_histogram; + ExporterDefaultHistogramAggregation.ExplicitBucketHistogram; break; } } @@ -374,16 +374,16 @@ function setMeterProvider(config: ConfigurationModel): void { } switch (exemplarFilter) { case 'trace_based': - config.meter_provider.exemplar_filter = ExemplarFilter.trace_based; + config.meter_provider.exemplar_filter = ExemplarFilter.TraceBased; break; case 'always_on': - config.meter_provider.exemplar_filter = ExemplarFilter.always_on; + config.meter_provider.exemplar_filter = ExemplarFilter.AlwaysOn; break; case 'always_off': - config.meter_provider.exemplar_filter = ExemplarFilter.always_off; + config.meter_provider.exemplar_filter = ExemplarFilter.AlwaysOff; break; default: - config.meter_provider.exemplar_filter = ExemplarFilter.trace_based; + config.meter_provider.exemplar_filter = ExemplarFilter.TraceBased; break; } } diff --git a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts index 7e328ed5499..33bded270dd 100644 --- a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts @@ -310,8 +310,8 @@ function parseConfigSpanExporter( timeout: getNumberFromConfigFile(e['timeout']) ?? 10000, encoding: getStringFromConfigFile(e['encoding']) === 'json' - ? OtlpHttpEncoding.json - : OtlpHttpEncoding.protobuf, + ? OtlpHttpEncoding.JSON + : OtlpHttpEncoding.Protobuf, }, }; @@ -583,13 +583,13 @@ function getTemporalityPreference( ); switch (temporalityPreferenceType) { case 'cumulative': - return ExporterTemporalityPreference.cumulative; + return ExporterTemporalityPreference.Cumulative; case 'delta': - return ExporterTemporalityPreference.delta; + return ExporterTemporalityPreference.Delta; case 'low_memory': - return ExporterTemporalityPreference.low_memory; + return ExporterTemporalityPreference.LowMemory; default: - return ExporterTemporalityPreference.cumulative; + return ExporterTemporalityPreference.Cumulative; } } @@ -601,11 +601,11 @@ function getDefaultHistogramAggregation( ); switch (defaultHistogramAggregationType) { case 'explicit_bucket_histogram': - return ExporterDefaultHistogramAggregation.explicit_bucket_histogram; + return ExporterDefaultHistogramAggregation.ExplicitBucketHistogram; case 'base2_exponential_bucket_histogram': - return ExporterDefaultHistogramAggregation.base2_exponential_bucket_histogram; + return ExporterDefaultHistogramAggregation.Base2ExponentialBucketHistogram; default: - return ExporterDefaultHistogramAggregation.explicit_bucket_histogram; + return ExporterDefaultHistogramAggregation.ExplicitBucketHistogram; } } @@ -633,8 +633,8 @@ function parseMetricExporter(exporter: PushMetricExporter): PushMetricExporter { timeout: getNumberFromConfigFile(e['timeout']) ?? 10000, encoding: getStringFromConfigFile(e['encoding']) === 'json' - ? OtlpHttpEncoding.json - : OtlpHttpEncoding.protobuf, + ? OtlpHttpEncoding.JSON + : OtlpHttpEncoding.Protobuf, temporality_preference: getTemporalityPreference( e['temporality_preference'] ), @@ -761,16 +761,16 @@ function setMeterProvider( if (exemplarFilter) { switch (exemplarFilter) { case 'trace_based': - config.meter_provider.exemplar_filter = ExemplarFilter.trace_based; + config.meter_provider.exemplar_filter = ExemplarFilter.TraceBased; break; case 'always_on': - config.meter_provider.exemplar_filter = ExemplarFilter.always_on; + config.meter_provider.exemplar_filter = ExemplarFilter.AlwaysOn; break; case 'always_off': - config.meter_provider.exemplar_filter = ExemplarFilter.always_off; + config.meter_provider.exemplar_filter = ExemplarFilter.AlwaysOff; break; default: - config.meter_provider.exemplar_filter = ExemplarFilter.trace_based; + config.meter_provider.exemplar_filter = ExemplarFilter.TraceBased; break; } } @@ -901,26 +901,26 @@ function setMeterProvider( if (instrumentType) { switch (instrumentType) { case 'counter': - selector.instrument_type = InstrumentType.counter; + selector.instrument_type = InstrumentType.Counter; break; case 'gauge': - selector.instrument_type = InstrumentType.gauge; + selector.instrument_type = InstrumentType.Gauge; break; case 'histogram': - selector.instrument_type = InstrumentType.histogram; + selector.instrument_type = InstrumentType.Histogram; break; case 'observable_counter': - selector.instrument_type = InstrumentType.observable_counter; + selector.instrument_type = InstrumentType.ObservableCounter; break; case 'observable_gauge': - selector.instrument_type = InstrumentType.observable_gauge; + selector.instrument_type = InstrumentType.ObservableGauge; break; case 'observable_up_down_counter': selector.instrument_type = - InstrumentType.observable_up_down_counter; + InstrumentType.ObservableUpDownCounter; break; case 'up_down_counter': - selector.instrument_type = InstrumentType.up_down_counter; + selector.instrument_type = InstrumentType.UpDownCounter; break; } } diff --git a/experimental/packages/opentelemetry-configuration/src/models/commonModel.ts b/experimental/packages/opentelemetry-configuration/src/models/commonModel.ts index e757570388f..1d8cbf626c8 100644 --- a/experimental/packages/opentelemetry-configuration/src/models/commonModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/models/commonModel.ts @@ -106,8 +106,8 @@ export interface OtlpHttpExporter { } export enum OtlpHttpEncoding { - protobuf, - json, + JSON = 'json', + Protobuf = 'protobuf', } export interface OtlpGrpcExporter { diff --git a/experimental/packages/opentelemetry-configuration/src/models/loggerProviderModel.ts b/experimental/packages/opentelemetry-configuration/src/models/loggerProviderModel.ts index cbb1bd2fe2c..1816a28d993 100644 --- a/experimental/packages/opentelemetry-configuration/src/models/loggerProviderModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/models/loggerProviderModel.ts @@ -35,7 +35,7 @@ export function initializeDefaultLoggerProviderConfiguration(): LoggerProvider { otlp_http: { endpoint: 'http://localhost:4318/v1/logs', timeout: 10000, - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, }, }, }, diff --git a/experimental/packages/opentelemetry-configuration/src/models/meterProviderModel.ts b/experimental/packages/opentelemetry-configuration/src/models/meterProviderModel.ts index 0bf80eb45e7..f6d38cdcdbc 100644 --- a/experimental/packages/opentelemetry-configuration/src/models/meterProviderModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/models/meterProviderModel.ts @@ -32,15 +32,15 @@ export function initializeDefaultMeterProviderConfiguration(): MeterProvider { otlp_http: { endpoint: 'http://localhost:4318/v1/metrics', timeout: 10000, - temporality_preference: ExporterTemporalityPreference.cumulative, + temporality_preference: ExporterTemporalityPreference.Cumulative, default_histogram_aggregation: - ExporterDefaultHistogramAggregation.explicit_bucket_histogram, + ExporterDefaultHistogramAggregation.ExplicitBucketHistogram, }, }, }, }, ], - exemplar_filter: ExemplarFilter.trace_based, + exemplar_filter: ExemplarFilter.TraceBased, }; } @@ -66,9 +66,9 @@ export interface MeterProvider { } export enum ExemplarFilter { - always_on, - always_off, - trace_based, + AlwaysOff = 'always_off', + AlwaysOn = 'always_on', + TraceBased = 'trace_based', } export interface PeriodicMetricReader { @@ -428,14 +428,14 @@ export interface OtlpFileMetricExporter { } export enum ExporterTemporalityPreference { - cumulative, - delta, - low_memory, + Cumulative = 'cumulative', + Delta = 'delta', + LowMemory = 'low_memory', } export enum ExporterDefaultHistogramAggregation { - explicit_bucket_histogram, - base2_exponential_bucket_histogram, + Base2ExponentialBucketHistogram = 'base2_exponential_bucket_histogram', + ExplicitBucketHistogram = 'explicit_bucket_histogram', } export interface View { @@ -491,13 +491,13 @@ export interface ViewSelector { } export enum InstrumentType { - counter, - gauge, - histogram, - observable_counter, - observable_gauge, - observable_up_down_counter, - up_down_counter, + Counter = 'counter', + Gauge = 'gauge', + Histogram = 'histogram', + ObservableCounter = 'observable_counter', + ObservableGauge = 'observable_gauge', + ObservableUpDownCounter = 'observable_up_down_counter', + UpDownCounter = 'up_down_counter', } export interface ViewStream { diff --git a/experimental/packages/opentelemetry-configuration/src/models/tracerProviderModel.ts b/experimental/packages/opentelemetry-configuration/src/models/tracerProviderModel.ts index 0b43f3fd371..5e337a66a1a 100644 --- a/experimental/packages/opentelemetry-configuration/src/models/tracerProviderModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/models/tracerProviderModel.ts @@ -35,7 +35,7 @@ export function initializeDefaultTracerProviderConfiguration(): TracerProvider { otlp_http: { endpoint: 'http://localhost:4318/v1/traces', timeout: 10000, - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, }, }, }, diff --git a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts index c2d3b0de173..6bfb274d2e2 100644 --- a/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts +++ b/experimental/packages/opentelemetry-configuration/test/ConfigProvider.test.ts @@ -50,7 +50,7 @@ const defaultConfig: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/traces', timeout: 10000, - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, }, }, }, @@ -83,15 +83,15 @@ const defaultConfig: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/metrics', timeout: 10000, - temporality_preference: ExporterTemporalityPreference.cumulative, + temporality_preference: ExporterTemporalityPreference.Cumulative, default_histogram_aggregation: - ExporterDefaultHistogramAggregation.explicit_bucket_histogram, + ExporterDefaultHistogramAggregation.ExplicitBucketHistogram, }, }, }, }, ], - exemplar_filter: ExemplarFilter.trace_based, + exemplar_filter: ExemplarFilter.TraceBased, }, logger_provider: { processors: [ @@ -105,7 +105,7 @@ const defaultConfig: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/logs', timeout: 10000, - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, }, }, }, @@ -206,7 +206,7 @@ const configFromFile: Configuration = { headers: [{ name: 'api-key', value: '1234' }], headers_list: 'api-key=1234', compression: 'gzip', - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, }, }, }, @@ -350,10 +350,10 @@ const configFromFile: Configuration = { headers_list: 'api-key=1234', compression: 'gzip', timeout: 10000, - encoding: OtlpHttpEncoding.protobuf, - temporality_preference: ExporterTemporalityPreference.delta, + encoding: OtlpHttpEncoding.Protobuf, + temporality_preference: ExporterTemporalityPreference.Delta, default_histogram_aggregation: - ExporterDefaultHistogramAggregation.base2_exponential_bucket_histogram, + ExporterDefaultHistogramAggregation.Base2ExponentialBucketHistogram, }, }, producers: [ @@ -393,9 +393,9 @@ const configFromFile: Configuration = { compression: 'gzip', timeout: 10000, insecure: false, - temporality_preference: ExporterTemporalityPreference.delta, + temporality_preference: ExporterTemporalityPreference.Delta, default_histogram_aggregation: - ExporterDefaultHistogramAggregation.base2_exponential_bucket_histogram, + ExporterDefaultHistogramAggregation.Base2ExponentialBucketHistogram, }, }, cardinality_limits: { @@ -417,9 +417,9 @@ const configFromFile: Configuration = { exporter: { 'otlp_file/development': { output_stream: 'file:///var/log/metrics.jsonl', - temporality_preference: ExporterTemporalityPreference.delta, + temporality_preference: ExporterTemporalityPreference.Delta, default_histogram_aggregation: - ExporterDefaultHistogramAggregation.base2_exponential_bucket_histogram, + ExporterDefaultHistogramAggregation.Base2ExponentialBucketHistogram, }, }, cardinality_limits: { @@ -441,9 +441,9 @@ const configFromFile: Configuration = { exporter: { 'otlp_file/development': { output_stream: 'stdout', - temporality_preference: ExporterTemporalityPreference.delta, + temporality_preference: ExporterTemporalityPreference.Delta, default_histogram_aggregation: - ExporterDefaultHistogramAggregation.base2_exponential_bucket_histogram, + ExporterDefaultHistogramAggregation.Base2ExponentialBucketHistogram, }, }, cardinality_limits: { @@ -478,12 +478,12 @@ const configFromFile: Configuration = { }, }, ], - exemplar_filter: ExemplarFilter.trace_based, + exemplar_filter: ExemplarFilter.TraceBased, views: [ { selector: { instrument_name: 'my-instrument', - instrument_type: InstrumentType.histogram, + instrument_type: InstrumentType.Histogram, unit: 'ms', meter_name: 'my-meter', meter_version: '1.0.0', @@ -522,7 +522,7 @@ const configFromFile: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/logs', timeout: 10000, - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, certificate_file: '/app/cert.pem', client_key_file: '/app/cert.pem', client_certificate_file: '/app/cert.pem', @@ -640,7 +640,7 @@ const defaultConfigFromFileWithEnvVariables: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/traces', timeout: 10000, - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, compression: 'gzip', }, }, @@ -673,12 +673,12 @@ const defaultConfigFromFileWithEnvVariables: Configuration = { exporter: { otlp_http: { endpoint: 'http://localhost:4318/v1/metrics', - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, compression: 'gzip', timeout: 10000, - temporality_preference: ExporterTemporalityPreference.cumulative, + temporality_preference: ExporterTemporalityPreference.Cumulative, default_histogram_aggregation: - ExporterDefaultHistogramAggregation.explicit_bucket_histogram, + ExporterDefaultHistogramAggregation.ExplicitBucketHistogram, }, }, cardinality_limits: { @@ -694,7 +694,7 @@ const defaultConfigFromFileWithEnvVariables: Configuration = { }, }, ], - exemplar_filter: ExemplarFilter.trace_based, + exemplar_filter: ExemplarFilter.TraceBased, }, logger_provider: { processors: [ @@ -708,7 +708,7 @@ const defaultConfigFromFileWithEnvVariables: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/logs', timeout: 10000, - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, compression: 'gzip', }, }, @@ -944,7 +944,7 @@ describe('ConfigProvider', function () { compression: 'gzip', timeout: 2000, headers_list: 'host=localhost', - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, }, }, }, @@ -1003,15 +1003,15 @@ describe('ConfigProvider', function () { compression: 'gzip', timeout: 300, headers_list: 'host=localhost', - temporality_preference: ExporterTemporalityPreference.delta, + temporality_preference: ExporterTemporalityPreference.Delta, default_histogram_aggregation: - ExporterDefaultHistogramAggregation.base2_exponential_bucket_histogram, + ExporterDefaultHistogramAggregation.Base2ExponentialBucketHistogram, }, }, }, }, ], - exemplar_filter: ExemplarFilter.always_on, + exemplar_filter: ExemplarFilter.AlwaysOn, }, }; const configProvider = createConfigProvider(); @@ -1060,7 +1060,7 @@ describe('ConfigProvider', function () { compression: 'gzip', timeout: 700, headers_list: 'host=localhost', - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, }, }, }, @@ -1288,7 +1288,7 @@ describe('ConfigProvider', function () { client_certificate_file: 'trace-client-certificate', client_key_file: 'trace-client-key', compression: 'trace-compression', - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, endpoint: 'http://test.com:4318/v1/traces', headers_list: 'trace-headers', timeout: 1213, @@ -1299,7 +1299,7 @@ describe('ConfigProvider', function () { ], }, meter_provider: { - exemplar_filter: ExemplarFilter.always_off, + exemplar_filter: ExemplarFilter.AlwaysOff, readers: [ { periodic: { @@ -1310,14 +1310,14 @@ describe('ConfigProvider', function () { endpoint: 'http://test:4318/v1/metrics', timeout: 22, temporality_preference: - ExporterTemporalityPreference.cumulative, + ExporterTemporalityPreference.Cumulative, default_histogram_aggregation: - ExporterDefaultHistogramAggregation.explicit_bucket_histogram, + ExporterDefaultHistogramAggregation.ExplicitBucketHistogram, certificate_file: 'metric-certificate', client_certificate_file: 'metric-client-certificate', client_key_file: 'metric-client-key', compression: 'metric-compression', - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, headers_list: 'metric-header', }, }, @@ -1354,7 +1354,7 @@ describe('ConfigProvider', function () { client_certificate_file: 'logs-client-certificate', client_key_file: 'logs-client-key', compression: 'logs-compression', - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, endpoint: 'http://test.com:4318/v1/logs', headers_list: 'logs-header', timeout: 27, From 6c7f7a9b3d72b25d8919da82cb1ece8633044876 Mon Sep 17 00:00:00 2001 From: maryliag Date: Thu, 9 Oct 2025 20:26:23 -0400 Subject: [PATCH 25/27] feedback from PR --- .../src/EnvironmentConfigProvider.ts | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts index e92f7cd5400..06ac35e55f1 100644 --- a/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts @@ -63,19 +63,17 @@ export class EnvironmentConfigProvider implements ConfigProvider { } function setResources(config: ConfigurationModel): void { + if (config.resource == null) { + config.resource = {}; + } + const resourceAttrList = getStringFromEnv('OTEL_RESOURCE_ATTRIBUTES'); if (resourceAttrList) { - if (config.resource == null) { - config.resource = {}; - } config.resource.attributes_list = resourceAttrList; } const serviceName = getStringFromEnv('OTEL_SERVICE_NAME'); if (serviceName) { - if (config.resource == null) { - config.resource = {}; - } config.resource.attributes = [ { name: 'service.name', @@ -90,7 +88,7 @@ function setAttributeLimits(config: ConfigurationModel): void { const attributeValueLengthLimit = getNumberFromEnv( 'OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT' ); - if (attributeValueLengthLimit) { + if (attributeValueLengthLimit && attributeValueLengthLimit > 0) { if (config.attribute_limits == null) { config.attribute_limits = { attribute_count_limit: 128 }; } @@ -109,11 +107,11 @@ function setAttributeLimits(config: ConfigurationModel): void { } function setPropagators(config: ConfigurationModel): void { + if (config.propagator == null) { + config.propagator = {}; + } const composite = getStringListFromEnv('OTEL_PROPAGATORS'); if (composite && composite.length > 0) { - if (config.propagator == null) { - config.propagator = {}; - } config.propagator.composite = []; for (let i = 0; i < composite.length; i++) { config.propagator.composite.push({ [composite[i]]: null }); @@ -121,9 +119,6 @@ function setPropagators(config: ConfigurationModel): void { } const compositeList = getStringFromEnv('OTEL_PROPAGATORS'); if (compositeList) { - if (config.propagator == null) { - config.propagator = {}; - } config.propagator.composite_list = compositeList; } } From 2b48da4b14fa619c6e14b1e4c6fab968bd5a5df5 Mon Sep 17 00:00:00 2001 From: maryliag Date: Thu, 9 Oct 2025 20:28:33 -0400 Subject: [PATCH 26/27] fix endpoint --- .../opentelemetry-configuration/src/FileConfigProvider.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts index 77c5fffb478..9b31cf2cebf 100644 --- a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts @@ -315,8 +315,7 @@ function parseConfigExporter(exporter: SpanExporter): SpanExporter { parsedExporter = { otlp_grpc: { endpoint: - getStringFromConfigFile(e['endpoint']) ?? - 'http://localhost:4318/v1/traces', + getStringFromConfigFile(e['endpoint']) ?? 'http://localhost:4317', timeout: getNumberFromConfigFile(e['timeout']) ?? 10000, }, }; From 2b8a2d23aa6fda89ad3b15a94c150261f5f8cb45 Mon Sep 17 00:00:00 2001 From: maryliag Date: Tue, 14 Oct 2025 23:00:42 +0200 Subject: [PATCH 27/27] fixes with messed merge --- .../src/FileConfigProvider.ts | 3 - .../src/models/configModel.ts | 155 ------------------ 2 files changed, 158 deletions(-) diff --git a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts index a0322af4a69..4de69d1a6b9 100644 --- a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts @@ -280,9 +280,6 @@ function parseConfigExporter( case ProviderType.TRACER: endpoint = 'http://localhost:4318/v1/traces'; break; - case ProviderType.METER: - endpoint = 'http://localhost:4318/v1/metrics'; - break; case ProviderType.LOGGER: endpoint = 'http://localhost:4318/v1/logs'; break; diff --git a/experimental/packages/opentelemetry-configuration/src/models/configModel.ts b/experimental/packages/opentelemetry-configuration/src/models/configModel.ts index 13d9a140b8f..8aa13872ab2 100644 --- a/experimental/packages/opentelemetry-configuration/src/models/configModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/models/configModel.ts @@ -161,161 +161,6 @@ export interface ConfigMeterExporter { otlp_http: ConfigMeterOTLPHttp; } -export interface ConfigOTLPHttp { - /** - * Configure endpoint, including the trace or log specific path. - * If omitted or null, http://localhost:4318/v1/traces is used for trace - * and http://localhost:4318/v1/logs is used for logs. - */ - endpoint: string; - - /** - * Configure certificate used to verify a server's TLS credentials. - * Absolute path to certificate file in PEM format. - * If omitted or null, system default certificate verification is used for secure connections. - */ - certificate_file?: string; - - /** - * Configure mTLS private client key. - * Absolute path to client key file in PEM format. If set, .client_certificate must also be set. - * If omitted or null, mTLS is not used. - */ - client_key_file?: string; - - /** - * Configure mTLS client certificate. - * Absolute path to client certificate file in PEM format. If set, .client_key must also be set. - * If omitted or null, mTLS is not used. - */ - client_certificate_file?: string; - - /** - * Configure compression. - * Values include: gzip, none. Implementations may support other compression algorithms. - * If omitted or null, none is used. - */ - compression?: string; - - /** - * Configure max time (in milliseconds) to wait for each export. - * Value must be non-negative. A value of 0 indicates no limit (infinity). - * If omitted or null, 10000 is used. - */ - timeout: number; - - /** - * Configure headers. Entries have higher priority than entries from .headers_list. - * If an entry's .value is null, the entry is ignored. - */ - headers?: ConfigHeader[]; - - /** - * Configure headers. Entries have lower priority than entries from .headers. - * The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. - * If omitted or null, no headers are added. - */ - headers_list?: string; - - /** - * Configure the encoding used for messages. - * Values include: protobuf, json. Implementations may not support json. - * If omitted or null, protobuf is used. - */ - encoding: 'protobuf' | 'json'; -} - -export interface ConfigOTLPGRPC { - /** - * Configure endpoint. - * If omitted or null, http://localhost:4317 is used. - */ - endpoint: string; - - /** - * Configure certificate used to verify a server's TLS credentials. - * Absolute path to certificate file in PEM format. - * If omitted or null, system default certificate verification is used for secure connections. - */ - certificate_file?: string; - - /** - * Configure mTLS private client key. - * Absolute path to client key file in PEM format. If set, .client_certificate must also be set. - * If omitted or null, mTLS is not used. - */ - client_key_file?: string; - - /** - * Configure mTLS client certificate. - * Absolute path to client certificate file in PEM format. If set, .client_key must also be set. - * If omitted or null, mTLS is not used. - */ - client_certificate_file?: string; - - /** - * Configure headers. Entries have higher priority than entries from .headers_list. - * If an entry's .value is null, the entry is ignored. - */ - headers?: ConfigHeader[]; - - /** - * Configure headers. Entries have lower priority than entries from .headers. - * The value is a list of comma separated key-value pairs matching the format of OTEL_EXPORTER_OTLP_HEADERS. - * If omitted or null, no headers are added. - */ - headers_list?: string; - - /** - * Configure compression. - * Values include: gzip, none. Implementations may support other compression algorithms. - * If omitted or null, none is used. - */ - compression?: string; - - /** - * Configure max time (in milliseconds) to wait for each export. - * Value must be non-negative. A value of 0 indicates no limit (infinity). - * If omitted or null, 10000 is used. - */ - timeout: number; - - /** - * Configure client transport security for the exporter's connection. - * Only applicable when .endpoint is provided without http or https scheme. Implementations may choose to ignore .insecure. - * If omitted or null, false is used. - */ - insecure?: boolean; -} -export interface ConfigOTLPFile { - /** - * Configure output stream. - * Values include stdout, or scheme+destination. For example: file:///path/to/file.jsonl. - * If omitted or null, stdout is used. - */ - output_stream: string; -} - -export interface ConfigZipkin { - /** - * Configure endpoint. - * If omitted or null, http://localhost:9411/api/v2/spans is used. - */ - endpoint: string; - - /** - * Configure max time (in milliseconds) to wait for each export. - * Value must be non-negative. A value of 0 indicates indefinite. - * If omitted or null, 10000 is used. - */ - timeout: number; -} - -export interface ConfigHeader { - name: string; - value: string; -} - export interface ConfigMeterOTLPHttp { /** * Configure endpoint, including the metric specific path.