From 2a32c935c408079db6f1bcb34ec6b00cf512792c Mon Sep 17 00:00:00 2001 From: Mike Goldsmith Date: Wed, 11 Feb 2026 14:53:32 +0000 Subject: [PATCH 1/3] feat(configuration): add prometheus exporter support - Add PullMetricReader import - Handle 'prometheus' exporter type with pull reader - Support OTEL_EXPORTER_PROMETHEUS_HOST and OTEL_EXPORTER_PROMETHEUS_PORT - Default to localhost:9464 - Added tests for default and custom config --- .../src/EnvironmentConfigFactory.ts | 19 +++++- .../configuration/test/ConfigFactory.test.ts | 58 +++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/experimental/packages/configuration/src/EnvironmentConfigFactory.ts b/experimental/packages/configuration/src/EnvironmentConfigFactory.ts index 4dfc3d29f4a..2cf1724dbc8 100644 --- a/experimental/packages/configuration/src/EnvironmentConfigFactory.ts +++ b/experimental/packages/configuration/src/EnvironmentConfigFactory.ts @@ -32,6 +32,7 @@ import { ExporterTemporalityPreference, initializeDefaultMeterProviderConfiguration, PeriodicMetricReader, + PullMetricReader, } from './models/meterProviderModel'; import { OtlpHttpEncoding } from './models/commonModel'; import { diag } from '@opentelemetry/api'; @@ -360,13 +361,29 @@ export function setMeterProvider(config: ConfigurationModel): void { } for (let i = 0; i < exportersType.length; i++) { const exporterType = exportersType[i]; + if (exporterType === 'prometheus') { + // Prometheus uses a pull reader + const pullReader: PullMetricReader = { + exporter: { + 'prometheus/development': { + host: + getStringFromEnv('OTEL_EXPORTER_PROMETHEUS_HOST') ?? 'localhost', + port: getNumberFromEnv('OTEL_EXPORTER_PROMETHEUS_PORT') ?? 9464, + without_scope_info: false, + without_target_info: false, + }, + }, + }; + config.meter_provider.readers.push({ pull: pullReader }); + continue; + } + const readerPeriodicInfo = { ...readerPeriodic }; const timeout = getNumberFromEnv('OTEL_METRIC_EXPORT_TIMEOUT') ?? 30000; if (timeout) { readerPeriodicInfo.timeout = timeout; } - // TODO: add prometheus exporter support if (exporterType === 'console') { readerPeriodicInfo.exporter = { console: {} }; } else { diff --git a/experimental/packages/configuration/test/ConfigFactory.test.ts b/experimental/packages/configuration/test/ConfigFactory.test.ts index 0bee4827169..9c122c95f42 100644 --- a/experimental/packages/configuration/test/ConfigFactory.test.ts +++ b/experimental/packages/configuration/test/ConfigFactory.test.ts @@ -1414,6 +1414,64 @@ describe('ConfigFactory', function () { assert.deepStrictEqual(configFactory.getConfigModel(), expectedConfig); }); + it('should return config with meter_provider with prometheus exporter', function () { + process.env.OTEL_METRICS_EXPORTER = 'prometheus'; + + const expectedConfig: ConfigurationModel = { + ...defaultConfig, + meter_provider: { + readers: [ + { + pull: { + exporter: { + 'prometheus/development': { + host: 'localhost', + port: 9464, + without_scope_info: false, + without_target_info: false, + }, + }, + }, + }, + ], + exemplar_filter: ExemplarFilter.TraceBased, + views: [], + }, + }; + const configFactory = createConfigFactory(); + assert.deepStrictEqual(configFactory.getConfigModel(), expectedConfig); + }); + + it('should return config with meter_provider with prometheus exporter and custom port', function () { + process.env.OTEL_METRICS_EXPORTER = 'prometheus'; + process.env.OTEL_EXPORTER_PROMETHEUS_HOST = '0.0.0.0'; + process.env.OTEL_EXPORTER_PROMETHEUS_PORT = '8080'; + + const expectedConfig: ConfigurationModel = { + ...defaultConfig, + meter_provider: { + readers: [ + { + pull: { + exporter: { + 'prometheus/development': { + host: '0.0.0.0', + port: 8080, + without_scope_info: false, + without_target_info: false, + }, + }, + }, + }, + ], + exemplar_filter: ExemplarFilter.TraceBased, + views: [], + }, + }; + const configFactory = createConfigFactory(); + assert.deepStrictEqual(configFactory.getConfigModel(), expectedConfig); + }); + it('should return config with meter_provider with no exporter', function () { process.env.OTEL_METRICS_EXPORTER = 'none,console'; const configFactory = createConfigFactory(); From 401289d439864f4e3d0e0abbff990eae246646ef Mon Sep 17 00:00:00 2001 From: Mike Goldsmith Date: Wed, 11 Feb 2026 19:31:02 +0000 Subject: [PATCH 2/3] add changelog entry --- experimental/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index 72c86519839..f49d6a19f20 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -15,6 +15,7 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2 ### :rocket: Features +* feat(configuration): add Prometheus exporter support * feat(sampler-composite): add ComposableAnnotatingSampler and ComposableRuleBasedSampler [#6305](https://github.com/open-telemetry/opentelemetry-js/pull/6305) @trentm * feat(configuration): parse config for rc 3 [#6304](https://github.com/open-telemetry/opentelemetry-js/pull/6304) @maryliag * feat(instrumentation): use the `internals: true` option with import-in-the-middle hook, allowing instrumentations to hook internal files in ES modules [#6344](https://github.com/open-telemetry/opentelemetry-js/pull/6344) @trentm From 889e2c9ab39cc0f3f303175ff139b51a948f87b8 Mon Sep 17 00:00:00 2001 From: Mike Goldsmith Date: Wed, 11 Feb 2026 19:59:27 +0000 Subject: [PATCH 3/3] Update experimental/CHANGELOG.md Co-authored-by: Marylia Gutierrez --- experimental/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index f49d6a19f20..116fc706156 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -15,7 +15,8 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2 ### :rocket: Features -* feat(configuration): add Prometheus exporter support +* feat(configuration): add Prometheus exporter support [#6400](https://github.com/open-telemetry/opentelemetry-js/pull/6400) @MikeGoldsmith + * feat(sampler-composite): add ComposableAnnotatingSampler and ComposableRuleBasedSampler [#6305](https://github.com/open-telemetry/opentelemetry-js/pull/6305) @trentm * feat(configuration): parse config for rc 3 [#6304](https://github.com/open-telemetry/opentelemetry-js/pull/6304) @maryliag * feat(instrumentation): use the `internals: true` option with import-in-the-middle hook, allowing instrumentations to hook internal files in ES modules [#6344](https://github.com/open-telemetry/opentelemetry-js/pull/6344) @trentm