diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index f3b556773e..dc40e891f6 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -10,6 +10,8 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2 ### :rocket: Features +* feat(sdk-node): wire up metric producers from declarative config [#6712](https://github.com/open-telemetry/opentelemetry-js/pull/6712) @MikeGoldsmith + ### :bug: Bug Fixes * fix(sdk-node): warn and ignore zero exporter timeout in declarative config [#6711](https://github.com/open-telemetry/opentelemetry-js/pull/6711) @MikeGoldsmith diff --git a/experimental/packages/configuration/src/index.ts b/experimental/packages/configuration/src/index.ts index 0ddde3c3bf..e0a7735303 100644 --- a/experimental/packages/configuration/src/index.ts +++ b/experimental/packages/configuration/src/index.ts @@ -14,6 +14,7 @@ export type { Sampler as SamplerConfigModel, SpanExporter as SpanExporterConfigModel, SpanProcessor as SpanProcessorConfigModel, + MetricProducer as MetricProducerConfigModel, NameStringValuePair as NameStringValuePairConfigModel, HttpTls as HttpTlsConfigModel, SeverityNumber as SeverityNumberConfigModel, diff --git a/experimental/packages/opentelemetry-sdk-node/src/utils.ts b/experimental/packages/opentelemetry-sdk-node/src/utils.ts index 5c3c28cbb4..d80eb9a36f 100644 --- a/experimental/packages/opentelemetry-sdk-node/src/utils.ts +++ b/experimental/packages/opentelemetry-sdk-node/src/utils.ts @@ -62,6 +62,7 @@ import type { LogRecordExporterConfigModel, InstrumentTypeConfigModel, AggregationConfigModel, + MetricProducerConfigModel, PeriodicMetricReaderConfigModel, SpanExporterConfigModel, SamplerConfigModel, @@ -92,6 +93,7 @@ import type { LoggerProviderOptions, LogRecordProcessor, } from '@opentelemetry/sdk-logs'; +import type { MetricProducer } from '@opentelemetry/sdk-metrics'; import { BatchLogRecordProcessor, ConsoleLogRecordExporter, @@ -514,6 +516,33 @@ export function getOtlpMetricExporterFromEnv(): PushMetricExporter { return new OTLPProtoMetricExporter(); } +function getMetricProducersFromConfiguration( + producers: MetricProducerConfigModel[] | undefined +): MetricProducer[] | undefined { + if (!producers || producers.length === 0) { + return undefined; + } + const result: MetricProducer[] = []; + for (const producer of producers) { + if (producer.opencensus) { + try { + const { + OpenCensusMetricProducer, + // eslint-disable-next-line @typescript-eslint/no-require-imports + } = require('@opentelemetry/shim-opencensus'); + result.push(new OpenCensusMetricProducer()); + } catch { + diag.warn( + 'OpenCensus metric producer configured but @opentelemetry/shim-opencensus is not installed.' + ); + } + } else { + diag.warn('Unsupported metric producer configured.'); + } + } + return result.length > 0 ? result : undefined; +} + export function getPeriodicMetricReaderFromConfiguration( periodic: PeriodicMetricReaderConfigModel ): IMetricReader | undefined { @@ -548,17 +577,23 @@ export function getPeriodicMetricReaderFromConfiguration( }); } + const metricProducers = getMetricProducersFromConfiguration( + periodic.producers + ); + if (exporter) { // TODO(6425): add cardinality_limits return new PeriodicExportingMetricReader({ exportIntervalMillis: periodic.interval ?? 60_000, exportTimeoutMillis: periodic.timeout ?? 30_000, exporter, + metricProducers, }); } if (periodic.exporter.console) { return new PeriodicExportingMetricReader({ exporter: new ConsoleMetricExporter(), + metricProducers, }); } } diff --git a/experimental/packages/opentelemetry-sdk-node/test/start.test.ts b/experimental/packages/opentelemetry-sdk-node/test/start.test.ts index d23729a6a7..8f6021b068 100644 --- a/experimental/packages/opentelemetry-sdk-node/test/start.test.ts +++ b/experimental/packages/opentelemetry-sdk-node/test/start.test.ts @@ -57,6 +57,7 @@ import { import { ATTR_OS_TYPE } from '@opentelemetry/resources/src/semconv'; import { getLogRecordExporter, + getPeriodicMetricReaderFromConfiguration, getSpanExporter, setupContextManager, } from '../src/utils'; @@ -963,6 +964,30 @@ describe('startNodeSDK', function () { assert.equal(getLogRecordExporter(exporter), undefined); }); + it('should create metric reader with opencensus producer when shim is available', async () => { + const reader = getPeriodicMetricReaderFromConfiguration({ + exporter: { console: {} }, + producers: [{ opencensus: {} }], + }); + assert.ok(reader !== undefined); + await (reader as PeriodicExportingMetricReader).shutdown(); + }); + + it('should warn for unsupported metric producer', async () => { + const warnSpy = Sinon.spy(diag, 'warn'); + const reader = getPeriodicMetricReaderFromConfiguration({ + exporter: { console: {} }, + producers: [{ 'unknown/producer': {} }], + }); + assert.ok(reader !== undefined); + assert.ok( + warnSpy.args.some(args => + String(args[0]).includes('Unsupported metric producer') + ) + ); + await (reader as PeriodicExportingMetricReader).shutdown(); + }); + it('should warn when exporter timeout is 0', async () => { const warnSpy = Sinon.spy(diag, 'warn'); const exporter = getSpanExporter({