diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index 1bcefed6d3c..ea641d52542 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -6,6 +6,10 @@ All notable changes to experimental packages in this project will be documented ### :boom: Breaking Change +* fix(exporter-metrics-otlp-grpc): programatic headers take precedence over environment variables [#2370](https://github.com/open-telemetry/opentelemetry-js/pull/4334) @Vunovati +* fix(exporter-metrics-otlp-http): programatic headers take precedence over environment variables [#2370](https://github.com/open-telemetry/opentelemetry-js/pull/4334) @Vunovati +* fix(exporter-metrics-otlp-proto): programatic headers take precedence over environment variables [#2370](https://github.com/open-telemetry/opentelemetry-js/pull/4334) @Vunovati + ### :rocket: (Enhancement) * feat(sdk-logs): add droppedAttributesCount field to ReadableLogRecord diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts index 0ada75d4375..b1b12272750 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/src/OTLPMetricExporter.ts @@ -49,6 +49,7 @@ class OTLPMetricExporterProxy extends OTLPGRPCExporterNodeBase< ...baggageUtils.parseKeyPairsIntoRecord( getEnv().OTEL_EXPORTER_OTLP_METRICS_HEADERS ), + ...config?.headers, }; this.metadata ||= new Metadata(); diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/OTLPMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/OTLPMetricExporter.test.ts index 1df8e0cc128..79a6125a095 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/OTLPMetricExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-grpc/test/OTLPMetricExporter.test.ts @@ -322,6 +322,15 @@ describe('when configuring via environment', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; }); + it('should use override url defined in env with url defined in constructor', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/v1/metrics'; + const constructorDefinedEndpoint = 'http://constructor/v1/metrics'; + const collectorExporter = new OTLPMetricExporter({ + url: constructorDefinedEndpoint, + }); + assert.strictEqual(collectorExporter._otlpExporter.url, 'constructor'); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + }); it('should use headers defined via env', () => { envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar'; const collectorExporter = new OTLPMetricExporter(); @@ -363,6 +372,23 @@ describe('when configuring via environment', () => { envSource.OTEL_EXPORTER_OTLP_METRICS_HEADERS = ''; envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; }); + it('should override headers defined via env with headers defined in constructor', () => { + envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo'; + const collectorExporter = new OTLPMetricExporter({ + headers: { + foo: 'constructor', + }, + }); + assert.deepStrictEqual( + collectorExporter._otlpExporter.metadata?.get('foo'), + ['constructor'] + ); + assert.deepStrictEqual( + collectorExporter._otlpExporter.metadata?.get('bar'), + ['foo'] + ); + envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; + }); }); testOTLPMetricExporter({ useTLS: true }); diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/OTLPMetricExporter.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/OTLPMetricExporter.ts index d051b7be9b3..cd648ce8753 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/OTLPMetricExporter.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/node/OTLPMetricExporter.ts @@ -48,6 +48,7 @@ class OTLPExporterNodeProxy extends OTLPExporterNodeBase< ...baggageUtils.parseKeyPairsIntoRecord( getEnv().OTEL_EXPORTER_OTLP_METRICS_HEADERS ), + ...config?.headers, }; } diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/CollectorMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/CollectorMetricExporter.test.ts index 2f809e62517..66f6af3006e 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/CollectorMetricExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/node/CollectorMetricExporter.test.ts @@ -296,6 +296,18 @@ describe('OTLPMetricExporter - node with json over http', () => { ); envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; }); + it('should use override url defined in env with url defined in constructor', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/v1/metrics'; + const constructorDefinedEndpoint = 'http://constructor/v1/metrics'; + const collectorExporter = new OTLPMetricExporter({ + url: constructorDefinedEndpoint, + }); + assert.strictEqual( + collectorExporter._otlpExporter.url, + constructorDefinedEndpoint + ); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + }); it('should use headers defined via env', () => { envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar'; const collectorExporter = new OTLPMetricExporter(); @@ -318,6 +330,20 @@ describe('OTLPMetricExporter - node with json over http', () => { envSource.OTEL_EXPORTER_OTLP_METRICS_HEADERS = ''; envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; }); + it('should override headers defined via env with headers defined in constructor', () => { + envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo'; + const collectorExporter = new OTLPMetricExporter({ + headers: { + foo: 'constructor', + }, + }); + assert.strictEqual( + collectorExporter._otlpExporter.headers.foo, + 'constructor' + ); + assert.strictEqual(collectorExporter._otlpExporter.headers.bar, 'foo'); + envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; + }); it('should use delta temporality defined via env', () => { for (const envValue of ['delta', 'DELTA', 'DeLTa', 'delta ']) { envSource.OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE = envValue; diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/OTLPMetricExporter.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/OTLPMetricExporter.ts index 8d1fb114b3f..52c9991e30a 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/OTLPMetricExporter.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/OTLPMetricExporter.ts @@ -51,6 +51,7 @@ class OTLPMetricExporterNodeProxy extends OTLPProtoExporterNodeBase< ...baggageUtils.parseKeyPairsIntoRecord( getEnv().OTEL_EXPORTER_OTLP_METRICS_HEADERS ), + ...config?.headers, }; } diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/OTLPMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/OTLPMetricExporter.test.ts index 80902daeaa2..51c175f8e6c 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/OTLPMetricExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/test/OTLPMetricExporter.test.ts @@ -148,6 +148,18 @@ describe('OTLPMetricExporter - node with proto over http', () => { ); envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; }); + it('should use override url defined in env with url defined in constructor', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/v1/metrics'; + const constructorDefinedEndpoint = 'http://constructor/v1/metrics'; + const collectorExporter = new OTLPMetricExporter({ + url: constructorDefinedEndpoint, + }); + assert.strictEqual( + collectorExporter._otlpExporter.url, + constructorDefinedEndpoint + ); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + }); it('should use headers defined via env', () => { envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar'; const collectorExporter = new OTLPMetricExporter(); @@ -163,6 +175,20 @@ describe('OTLPMetricExporter - node with proto over http', () => { envSource.OTEL_EXPORTER_OTLP_METRICS_HEADERS = ''; envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; }); + it('should override headers defined via env with headers defined in constructor', () => { + envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo'; + const collectorExporter = new OTLPMetricExporter({ + headers: { + foo: 'constructor', + }, + }); + assert.strictEqual( + collectorExporter._otlpExporter.headers.foo, + 'constructor' + ); + assert.strictEqual(collectorExporter._otlpExporter.headers.bar, 'foo'); + envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; + }); }); describe('export', () => {