diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index 022fed4887..3091d530d5 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -43,6 +43,8 @@ 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 +* feat(opentelemetry-configuration): parse meter provider from config file [#6000](https://github.com/open-telemetry/opentelemetry-js/pull/6000) @maryliag ### :bug: Bug Fixes diff --git a/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts b/experimental/packages/opentelemetry-configuration/src/EnvironmentConfigProvider.ts index 06ac35e55f..779889a22d 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. @@ -257,6 +262,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) { @@ -305,26 +313,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.LowMemory; + 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.ExplicitBucketHistogram; + break; + case 'base2_exponential_bucket_histogram': + readerPeriodic.exporter.otlp_http.default_histogram_aggregation = + ExporterDefaultHistogramAggregation.Base2ExponentialBucketHistogram; + break; + default: + readerPeriodic.exporter.otlp_http.default_histogram_aggregation = + ExporterDefaultHistogramAggregation.ExplicitBucketHistogram; + break; + } } if (config.meter_provider == null) { config.meter_provider = { readers: [{}] }; @@ -336,16 +363,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.TraceBased; + break; + case 'always_on': + config.meter_provider.exemplar_filter = ExemplarFilter.AlwaysOn; + break; + case 'always_off': + config.meter_provider.exemplar_filter = ExemplarFilter.AlwaysOff; + break; + default: + config.meter_provider.exemplar_filter = ExemplarFilter.TraceBased; + break; } - config.meter_provider.exemplar_filter = exemplarFilter; } } @@ -358,7 +393,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 9b31cf2ceb..cba939a07c 100644 --- a/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts +++ b/experimental/packages/opentelemetry-configuration/src/FileConfigProvider.ts @@ -17,9 +17,6 @@ import { diagLogLevelFromString, getStringFromEnv } from '@opentelemetry/core'; import { AttributeLimits, - ConfigAttributes, - LoggerProvider, - MeterProvider, Propagator, ConfigurationModel, initializeDefaultConfiguration, @@ -41,6 +38,24 @@ import { SpanProcessor, TracerProvider, } from './models/tracerProviderModel'; +import { LoggerProvider } from './models/loggerProviderModel'; +import { AttributeNameValue } from './models/resourceModel'; +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; @@ -98,14 +113,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 +142,7 @@ function parseConfigFile(config: ConfigurationModel) { function setResourceAttributes( config: ConfigurationModel, - attributes: ConfigAttributes[] + attributes: AttributeNameValue[] ) { if (attributes) { if (config.resource == null) { @@ -254,7 +269,16 @@ function getConfigHeaders( return null; } -function parseConfigExporter(exporter: SpanExporter): SpanExporter { +enum ProviderType { + TRACER = 0, + METER = 1, + LOGGER = 2, +} + +function parseConfigSpanExporter( + exporter: SpanExporter, + providerType: ProviderType +): SpanExporter { const exporterType = Object.keys(exporter)[0]; let parsedExporter: SpanExporter = {}; let e; @@ -265,20 +289,29 @@ function parseConfigExporter(exporter: SpanExporter): SpanExporter { let headers; let headersList; let insecure; + let endpoint; + + switch (providerType) { + case ProviderType.TRACER: + endpoint = 'http://localhost:4318/v1/traces'; + 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' - ? OtlpHttpEncoding.json - : OtlpHttpEncoding.protobuf, + ? OtlpHttpEncoding.JSON + : OtlpHttpEncoding.Protobuf, }, }; @@ -365,7 +398,7 @@ function parseConfigExporter(exporter: SpanExporter): SpanExporter { case 'console': parsedExporter = { - console: {}, + console: undefined, }; break; @@ -460,7 +493,10 @@ function setTracerProvider( if (processorType === 'batch') { const element = tracerProvider['processors'][i]['batch']; if (element) { - const parsedExporter = parseConfigExporter(element['exporter']); + const parsedExporter = parseConfigSpanExporter( + element['exporter'], + ProviderType.TRACER + ); const batchConfig: SpanProcessor = { batch: { schedule_delay: @@ -481,7 +517,10 @@ function setTracerProvider( } else if (processorType === 'simple') { const element = tracerProvider['processors'][i]['simple']; if (element) { - const parsedExporter = parseConfigExporter(element['exporter']); + const parsedExporter = parseConfigSpanExporter( + element['exporter'], + ProviderType.TRACER + ); const simpleConfig: SpanProcessor = { simple: { exporter: parsedExporter, @@ -496,24 +535,499 @@ 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.LowMemory; + default: + return ExporterTemporalityPreference.Cumulative; + } +} + +function getDefaultHistogramAggregation( + defaultHistogramAggregation?: ExporterDefaultHistogramAggregation +): ExporterDefaultHistogramAggregation { + const defaultHistogramAggregationType = getStringFromConfigFile( + defaultHistogramAggregation + ); + switch (defaultHistogramAggregationType) { + case 'explicit_bucket_histogram': + return ExporterDefaultHistogramAggregation.ExplicitBucketHistogram; + case 'base2_exponential_bucket_histogram': + return ExporterDefaultHistogramAggregation.Base2ExponentialBucketHistogram; + default: + return ExporterDefaultHistogramAggregation.ExplicitBucketHistogram; + } +} + +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.TraceBased; + break; + case 'always_on': + config.meter_provider.exemplar_filter = ExemplarFilter.AlwaysOn; + break; + case 'always_off': + config.meter_provider.exemplar_filter = ExemplarFilter.AlwaysOff; + break; + default: + config.meter_provider.exemplar_filter = ExemplarFilter.TraceBased; + break; + } + } + + if (meterProvider['readers'] && 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_scope_info: + getBooleanFromConfigFile( + element['exporter']['prometheus/development'][ + 'without_scope_info' + ] + ) ?? 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 pullReader: MetricReader = { + pull: { + exporter: exporter, + 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.ObservableCounter; + break; + case 'observable_gauge': + selector.instrument_type = InstrumentType.ObservableGauge; + break; + case 'observable_up_down_counter': + selector.instrument_type = + InstrumentType.ObservableUpDownCounter; + break; + case 'up_down_counter': + selector.instrument_type = InstrumentType.UpDownCounter; + 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); + } } } } @@ -524,8 +1038,9 @@ function setLoggerProvider( ): void { if (loggerProvider) { if (config.logger_provider == null) { - config.logger_provider = {}; + config.logger_provider = { processors: [] }; } + // Limits if (loggerProvider['limits']) { const attributeValueLengthLimit = getNumberFromConfigFile( loggerProvider['limits']['attribute_value_length_limit'] @@ -549,5 +1064,114 @@ 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]; + if (processorType === 'batch') { + const element = loggerProvider['processors'][i]['batch']; + if (element) { + const parsedExporter = parseConfigSpanExporter( + element['exporter'], + ProviderType.LOGGER + ); + const batchConfig: SpanProcessor = { + 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 = parseConfigSpanExporter( + element['exporter'], + ProviderType.LOGGER + ); + const simpleConfig: SpanProcessor = { + 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) { + if (config.logger_provider == null) { + config.logger_provider = { processors: [] }; + } + 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]; + let disabled = false; + if (logger['config']) { + disabled = + getBooleanFromConfigFile(logger['config']['disabled']) ?? false; + } + const name = getStringFromConfigFile(logger['name']); + if (name) { + loggers.push({ + name: name, + config: { + disabled: disabled, + }, + }); + } + } + if (config.logger_provider == null) { + config.logger_provider = { processors: [] }; + } + 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/models/commonModel.ts b/experimental/packages/opentelemetry-configuration/src/models/commonModel.ts index d2a0addb3d..1d8cbf626c 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. + */ + 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). + * 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. + */ + excluded?: string[]; +} + export interface NameStringValuePair { name: string; value: string; @@ -86,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/configModel.ts b/experimental/packages/opentelemetry-configuration/src/models/configModel.ts index 8efba5b152..63450cf8d1 100644 --- a/experimental/packages/opentelemetry-configuration/src/models/configModel.ts +++ b/experimental/packages/opentelemetry-configuration/src/models/configModel.ts @@ -16,12 +16,19 @@ 'use strict'; import { DiagLogLevel } from '@opentelemetry/api'; -import { NameStringValuePair, OtlpHttpEncoding } from './commonModel'; import { initializeDefaultTracerProviderConfiguration, - SpanProcessor, TracerProvider, } from './tracerProviderModel'; +import { + initializeDefaultLoggerProviderConfiguration, + LoggerProvider, +} from './loggerProviderModel'; +import { Resource } from './resourceModel'; +import { + initializeDefaultMeterProviderConfiguration, + MeterProvider, +} from './meterProviderModel'; export interface ConfigurationModel { /** @@ -89,95 +96,12 @@ 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: '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, - }, - }, + meter_provider: initializeDefaultMeterProviderConfiguration(), + 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. @@ -214,133 +138,3 @@ export interface Propagator { */ 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/loggerProviderModel.ts b/experimental/packages/opentelemetry-configuration/src/models/loggerProviderModel.ts new file mode 100644 index 0000000000..1816a28d99 --- /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/meterProviderModel.ts b/experimental/packages/opentelemetry-configuration/src/models/meterProviderModel.ts new file mode 100644 index 0000000000..f6d38cdcdb --- /dev/null +++ b/experimental/packages/opentelemetry-configuration/src/models/meterProviderModel.ts @@ -0,0 +1,597 @@ +/* + * 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 { + 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.ExplicitBucketHistogram, + }, + }, + }, + }, + ], + exemplar_filter: ExemplarFilter.TraceBased, + }; +} + +export interface MeterProvider { + /** + * Configure metric readers. + */ + readers: MetricReader[]; + + /** + * Configure views. + * Each view has a selector which determines the instrument(s) it applies to, + * and a configuration for the resulting stream(s). + */ + views?: View[]; + + /** + * Configure the exemplar filter. + * Values include: trace_based, always_on, always_off. + * If omitted or null, trace_based is used. + */ + exemplar_filter?: ExemplarFilter; +} + +export enum ExemplarFilter { + AlwaysOff = 'always_off', + AlwaysOn = 'always_on', + TraceBased = 'trace_based', +} + +export interface PeriodicMetricReader { + /** + * 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: PushMetricExporter; + + /** + * Configure metric producers. + */ + producers?: MetricProducer[]; + + /** + * Configure cardinality limits. + */ + cardinality_limits?: CardinalityLimits; +} + +export interface PullMetricReader { + /** + * Configure exporter. + */ + exporter: PullMetricExporter; + + /** + * Configure metric producers. + */ + producers?: MetricProducer[]; + + /** + * Configure cardinality limits. + */ + cardinality_limits?: CardinalityLimits; +} + +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 PushMetricExporter { + /** + * Configure exporter to be OTLP with HTTP transport. + */ + 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 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 = 'cumulative', + Delta = 'delta', + LowMemory = 'low_memory', +} + +export enum ExporterDefaultHistogramAggregation { + Base2ExponentialBucketHistogram = 'base2_exponential_bucket_histogram', + ExplicitBucketHistogram = 'explicit_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 = 'counter', + Gauge = 'gauge', + Histogram = 'histogram', + ObservableCounter = 'observable_counter', + ObservableGauge = 'observable_gauge', + ObservableUpDownCounter = 'observable_up_down_counter', + UpDownCounter = '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/models/resourceModel.ts b/experimental/packages/opentelemetry-configuration/src/models/resourceModel.ts index 911c018826..6646766a50 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; +} diff --git a/experimental/packages/opentelemetry-configuration/src/models/tracerProviderModel.ts b/experimental/packages/opentelemetry-configuration/src/models/tracerProviderModel.ts index 0b43f3fd37..5e337a66a1 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/src/utils.ts b/experimental/packages/opentelemetry-configuration/src/utils.ts index 5c3855d954..211092d51a 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 5ad5e2a392..0bb3850c13 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, @@ -44,7 +50,7 @@ const defaultConfig: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/traces', timeout: 10000, - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, }, }, }, @@ -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.ExplicitBucketHistogram, }, }, }, }, ], - exemplar_filter: 'trace_based', + exemplar_filter: ExemplarFilter.TraceBased, }, logger_provider: { processors: [ @@ -98,7 +105,7 @@ const defaultConfig: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/logs', timeout: 10000, - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, }, }, }, @@ -199,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, }, }, }, @@ -268,7 +275,7 @@ const configFromFile: Configuration = { { simple: { exporter: { - console: {}, + console: undefined, }, }, }, @@ -294,6 +301,36 @@ const configFromFile: Configuration = { }, meter_provider: { readers: [ + { + pull: { + exporter: { + 'prometheus/development': { + host: 'localhost', + port: 9464, + without_scope_info: false, + with_resource_constant_labels: { + included: ['service*'], + excluded: ['service.attr1'], + }, + }, + }, + producers: [ + { + opencensus: 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, @@ -301,21 +338,183 @@ const configFromFile: Configuration = { 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.Base2ExponentialBucketHistogram, + }, + }, + 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, - temporality_preference: 'cumulative', - default_histogram_aggregation: 'explicit_bucket_histogram', + insecure: false, + temporality_preference: ExporterTemporalityPreference.Delta, + default_histogram_aggregation: + ExporterDefaultHistogramAggregation.Base2ExponentialBucketHistogram, + }, + }, + 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.Base2ExponentialBucketHistogram, + }, + }, + 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.Base2ExponentialBucketHistogram, + }, + }, + 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.TraceBased, + 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: [ { batch: { - schedule_delay: 1000, + schedule_delay: 5000, export_timeout: 30000, max_queue_size: 2048, max_export_batch_size: 512, @@ -323,16 +522,89 @@ 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', + 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: undefined, + }, + }, + }, ], 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, + }, + }, + ], + }, }, }; @@ -368,7 +640,7 @@ const defaultConfigFromFileWithEnvVariables: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/traces', timeout: 10000, - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, compression: 'gzip', }, }, @@ -401,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.ExplicitBucketHistogram, }, }, + 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.TraceBased, }, logger_provider: { processors: [ @@ -423,7 +708,8 @@ const defaultConfigFromFileWithEnvVariables: Configuration = { otlp_http: { endpoint: 'http://localhost:4318/v1/logs', timeout: 10000, - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, + compression: 'gzip', }, }, }, @@ -610,7 +896,7 @@ describe('ConfigProvider', function () { compression: 'gzip', timeout: 2000, headers_list: 'host=localhost', - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, }, }, }, @@ -669,15 +955,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.Base2ExponentialBucketHistogram, }, }, }, }, ], - exemplar_filter: 'always_on', + exemplar_filter: ExemplarFilter.AlwaysOn, }, }; const configProvider = createConfigProvider(); @@ -726,7 +1012,7 @@ describe('ConfigProvider', function () { compression: 'gzip', timeout: 700, headers_list: 'host=localhost', - encoding: OtlpHttpEncoding.protobuf, + encoding: OtlpHttpEncoding.Protobuf, }, }, }, @@ -826,7 +1112,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 = @@ -843,7 +1130,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 = @@ -897,7 +1185,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, @@ -908,8 +1196,41 @@ describe('ConfigProvider', function () { ], }, meter_provider: { - ...defaultConfigFromFileWithEnvVariables.meter_provider, - exemplar_filter: 'always_off', + exemplar_filter: ExemplarFilter.AlwaysOff, + 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.ExplicitBucketHistogram, + 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, @@ -917,6 +1238,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: OtlpHttpEncoding.Protobuf, + endpoint: 'http://test.com:4318/v1/logs', + headers_list: 'logs-header', + timeout: 27, + }, + }, + }, + }, + ], }, }; diff --git a/experimental/packages/opentelemetry-configuration/test/utils.test.ts b/experimental/packages/opentelemetry-configuration/test/utils.test.ts index 58eed2fceb..5638e82ac4 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(