From 69cced26a23d03ae04e5a4b66a75e7c3983c3cae Mon Sep 17 00:00:00 2001 From: Svetlana Brennan <50715937+svetlanabrennan@users.noreply.github.com> Date: Tue, 17 May 2022 02:18:38 -0500 Subject: [PATCH] fix(otlp-http-exporter): update endpoint to match spec (#2895) Co-authored-by: Daniel Dyla Co-authored-by: Chengzhong Wu --- experimental/CHANGELOG.md | 1 + .../src/platform/browser/OTLPTraceExporter.ts | 16 ++++-- .../src/platform/node/OTLPTraceExporter.ts | 11 ++-- .../browser/CollectorTraceExporter.test.ts | 55 ++++++++++++++++-- .../test/node/CollectorTraceExporter.test.ts | 55 ++++++++++++++++-- .../src/OTLPTraceExporter.ts | 14 +++-- .../test/OTLPTraceExporter.test.ts | 55 ++++++++++++++++-- .../platform/browser/OTLPMetricExporter.ts | 13 +++-- .../src/platform/node/OTLPMetricExporter.ts | 13 +++-- .../browser/CollectorMetricExporter.test.ts | 55 ++++++++++++++++-- .../test/node/CollectorMetricExporter.test.ts | 55 ++++++++++++++++-- .../src/OTLPMetricExporter.ts | 16 ++++-- .../test/OTLPMetricExporter.test.ts | 55 ++++++++++++++++-- .../packages/otlp-exporter-base/src/util.ts | 27 +++++++-- .../test/common/util.test.ts | 56 ++++++++++++++++++- 15 files changed, 428 insertions(+), 69 deletions(-) diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index 51ea849844..1aaa61599c 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -20,6 +20,7 @@ All notable changes to experimental packages in this project will be documented * fix(opentelemetry-instrumentation-http): use correct origin when port is `null` #2948 @danielgblanco * fix(otlp-exporter-base): include esm and esnext in package files #2952 @dyladan +* fix(otlp-http-exporter): update endpoint to match spec #2895 @svetlanabrennan ### :books: (Refine Doc) diff --git a/experimental/packages/exporter-trace-otlp-http/src/platform/browser/OTLPTraceExporter.ts b/experimental/packages/exporter-trace-otlp-http/src/platform/browser/OTLPTraceExporter.ts index 21c78e8368..ff478ead7c 100644 --- a/experimental/packages/exporter-trace-otlp-http/src/platform/browser/OTLPTraceExporter.ts +++ b/experimental/packages/exporter-trace-otlp-http/src/platform/browser/OTLPTraceExporter.ts @@ -14,14 +14,18 @@ * limitations under the License. */ -import { appendResourcePathToUrlIfNotPresent, OTLPExporterBrowserBase } from '@opentelemetry/otlp-exporter-base'; import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base'; import { getEnv, baggageUtils } from '@opentelemetry/core'; -import { OTLPExporterConfigBase } from '@opentelemetry/otlp-exporter-base'; +import { + OTLPExporterConfigBase, + appendResourcePathToUrl, + appendRootPathToUrlIfNeeded, + OTLPExporterBrowserBase +} from '@opentelemetry/otlp-exporter-base'; import { createExportTraceServiceRequest, IExportTraceServiceRequest } from '@opentelemetry/otlp-transformer'; -const DEFAULT_COLLECTOR_RESOURCE_PATH = '/v1/traces'; -const DEFAULT_COLLECTOR_URL=`http://localhost:4318${DEFAULT_COLLECTOR_RESOURCE_PATH}`; +const DEFAULT_COLLECTOR_RESOURCE_PATH = 'v1/traces'; +const DEFAULT_COLLECTOR_URL = `http://localhost:4318/${DEFAULT_COLLECTOR_RESOURCE_PATH}`; /** * Collector Trace Exporter for Web @@ -49,9 +53,9 @@ export class OTLPTraceExporter return typeof config.url === 'string' ? config.url : getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0 - ? getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT + ? appendRootPathToUrlIfNeeded(getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0 - ? appendResourcePathToUrlIfNotPresent(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) + ? appendResourcePathToUrl(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) : DEFAULT_COLLECTOR_URL; } } diff --git a/experimental/packages/exporter-trace-otlp-http/src/platform/node/OTLPTraceExporter.ts b/experimental/packages/exporter-trace-otlp-http/src/platform/node/OTLPTraceExporter.ts index 517148717d..aeec62259b 100644 --- a/experimental/packages/exporter-trace-otlp-http/src/platform/node/OTLPTraceExporter.ts +++ b/experimental/packages/exporter-trace-otlp-http/src/platform/node/OTLPTraceExporter.ts @@ -19,12 +19,13 @@ import { getEnv, baggageUtils } from '@opentelemetry/core'; import { OTLPExporterNodeBase } from '@opentelemetry/otlp-exporter-base'; import { OTLPExporterNodeConfigBase, - appendResourcePathToUrlIfNotPresent + appendResourcePathToUrl, + appendRootPathToUrlIfNeeded } from '@opentelemetry/otlp-exporter-base'; import { createExportTraceServiceRequest, IExportTraceServiceRequest } from '@opentelemetry/otlp-transformer'; -const DEFAULT_COLLECTOR_RESOURCE_PATH = '/v1/traces'; -const DEFAULT_COLLECTOR_URL = `http://localhost:4318${DEFAULT_COLLECTOR_RESOURCE_PATH}`; +const DEFAULT_COLLECTOR_RESOURCE_PATH = 'v1/traces'; +const DEFAULT_COLLECTOR_URL = `http://localhost:4318/${DEFAULT_COLLECTOR_RESOURCE_PATH}`; /** * Collector Trace Exporter for Node @@ -51,9 +52,9 @@ export class OTLPTraceExporter return typeof config.url === 'string' ? config.url : getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0 - ? getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT + ? appendRootPathToUrlIfNeeded(getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0 - ? appendResourcePathToUrlIfNotPresent(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) + ? appendResourcePathToUrl(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) : DEFAULT_COLLECTOR_URL; } } diff --git a/experimental/packages/exporter-trace-otlp-http/test/browser/CollectorTraceExporter.test.ts b/experimental/packages/exporter-trace-otlp-http/test/browser/CollectorTraceExporter.test.ts index 7970005c08..4e933cf6a5 100644 --- a/experimental/packages/exporter-trace-otlp-http/test/browser/CollectorTraceExporter.test.ts +++ b/experimental/packages/exporter-trace-otlp-http/test/browser/CollectorTraceExporter.test.ts @@ -508,16 +508,25 @@ describe('OTLPTraceExporter - browser (getDefaultUrl)', () => { describe('when configuring via environment', () => { const envSource = window as any; - it('should use url defined in env', () => { + it('should use url defined in env that ends with root path and append version and signal path', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/'; + const collectorExporter = new OTLPTraceExporter(); + assert.strictEqual( + collectorExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}v1/traces` + ); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + }); + it('should use url defined in env without checking if path is already present', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/v1/traces'; const collectorExporter = new OTLPTraceExporter(); assert.strictEqual( collectorExporter.url, - envSource.OTEL_EXPORTER_OTLP_ENDPOINT + `${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/traces` ); envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; }); - it('should use url defined in env and append version and signal when not present', () => { + it('should use url defined in env and append version and signal', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; const collectorExporter = new OTLPTraceExporter(); assert.strictEqual( @@ -527,8 +536,8 @@ describe('when configuring via environment', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; }); it('should override global exporter url with signal url defined in env', () => { - envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; - envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.traces'; + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/'; + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.traces/'; const collectorExporter = new OTLPTraceExporter(); assert.strictEqual( collectorExporter.url, @@ -537,6 +546,42 @@ describe('when configuring via environment', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; }); + it('should add root path when signal url defined in env contains no path and no root path', () => { + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.bar'; + const collectorExporter = new OTLPTraceExporter(); + assert.strictEqual( + collectorExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT}/` + ); + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains root path but no path', () => { + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.bar/'; + const collectorExporter = new OTLPTraceExporter(); + assert.strictEqual( + collectorExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains path', () => { + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.bar/v1/traces'; + const collectorExporter = new OTLPTraceExporter(); + assert.strictEqual( + collectorExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains path and ends in /', () => { + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.bar/v1/traces/'; + const collectorExporter = new OTLPTraceExporter(); + assert.strictEqual( + collectorExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; + }); it('should use headers defined via env', () => { envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar'; const collectorExporter = new OTLPTraceExporter({ headers: {} }); diff --git a/experimental/packages/exporter-trace-otlp-http/test/node/CollectorTraceExporter.test.ts b/experimental/packages/exporter-trace-otlp-http/test/node/CollectorTraceExporter.test.ts index 3e9da9370e..7ba730da61 100644 --- a/experimental/packages/exporter-trace-otlp-http/test/node/CollectorTraceExporter.test.ts +++ b/experimental/packages/exporter-trace-otlp-http/test/node/CollectorTraceExporter.test.ts @@ -82,16 +82,25 @@ describe('OTLPTraceExporter - node with json over http', () => { describe('when configuring via environment', () => { const envSource = process.env; - it('should use url defined in env', () => { + it('should use url defined in env that ends with root path and append version and signal path', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/'; + const collectorExporter = new OTLPTraceExporter(); + assert.strictEqual( + collectorExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}v1/traces` + ); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + }); + it('should use url defined in env without checking if path is already present', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/v1/traces'; const collectorExporter = new OTLPTraceExporter(); assert.strictEqual( collectorExporter.url, - envSource.OTEL_EXPORTER_OTLP_ENDPOINT + `${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/traces` ); envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; }); - it('should use url defined in env and append version and signal when not present', () => { + it('should use url defined in env and append version and signal', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; const collectorExporter = new OTLPTraceExporter(); assert.strictEqual( @@ -101,8 +110,8 @@ describe('OTLPTraceExporter - node with json over http', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; }); it('should override global exporter url with signal url defined in env', () => { - envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; - envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.traces'; + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/'; + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.traces/'; const collectorExporter = new OTLPTraceExporter(); assert.strictEqual( collectorExporter.url, @@ -111,6 +120,42 @@ describe('OTLPTraceExporter - node with json over http', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; }); + it('should add root path when signal url defined in env contains no path and no root path', () => { + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.bar'; + const collectorExporter = new OTLPTraceExporter(); + assert.strictEqual( + collectorExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT}/` + ); + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains root path but no path', () => { + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.bar/'; + const collectorExporter = new OTLPTraceExporter(); + assert.strictEqual( + collectorExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains path', () => { + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.bar/v1/traces'; + const collectorExporter = new OTLPTraceExporter(); + assert.strictEqual( + collectorExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains path and ends in /', () => { + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.bar/v1/traces/'; + const collectorExporter = new OTLPTraceExporter(); + assert.strictEqual( + collectorExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; + }); it('should use headers defined via env', () => { envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar'; const collectorExporter = new OTLPTraceExporter(); diff --git a/experimental/packages/exporter-trace-otlp-proto/src/OTLPTraceExporter.ts b/experimental/packages/exporter-trace-otlp-proto/src/OTLPTraceExporter.ts index 9fcc7f5a3f..f523110024 100644 --- a/experimental/packages/exporter-trace-otlp-proto/src/OTLPTraceExporter.ts +++ b/experimental/packages/exporter-trace-otlp-proto/src/OTLPTraceExporter.ts @@ -16,12 +16,16 @@ import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base'; import { getEnv, baggageUtils } from '@opentelemetry/core'; -import { appendResourcePathToUrlIfNotPresent, OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base'; +import { + OTLPExporterNodeConfigBase, + appendResourcePathToUrl, + appendRootPathToUrlIfNeeded +} from '@opentelemetry/otlp-exporter-base'; import { OTLPProtoExporterNodeBase, ServiceClientType } from '@opentelemetry/otlp-proto-exporter-base'; import { createExportTraceServiceRequest, IExportTraceServiceRequest } from '@opentelemetry/otlp-transformer'; -const DEFAULT_COLLECTOR_RESOURCE_PATH = '/v1/traces'; -const DEFAULT_COLLECTOR_URL=`http://localhost:4318${DEFAULT_COLLECTOR_RESOURCE_PATH}`; +const DEFAULT_COLLECTOR_RESOURCE_PATH = 'v1/traces'; +const DEFAULT_COLLECTOR_URL = `http://localhost:4318/${DEFAULT_COLLECTOR_RESOURCE_PATH}`; /** * Collector Trace Exporter for Node with protobuf @@ -50,9 +54,9 @@ export class OTLPTraceExporter return typeof config.url === 'string' ? config.url : getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0 - ? getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT + ? appendRootPathToUrlIfNeeded(getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0 - ? appendResourcePathToUrlIfNotPresent(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) + ? appendResourcePathToUrl(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) : DEFAULT_COLLECTOR_URL; } diff --git a/experimental/packages/exporter-trace-otlp-proto/test/OTLPTraceExporter.test.ts b/experimental/packages/exporter-trace-otlp-proto/test/OTLPTraceExporter.test.ts index e68a02e762..983f3d55df 100644 --- a/experimental/packages/exporter-trace-otlp-proto/test/OTLPTraceExporter.test.ts +++ b/experimental/packages/exporter-trace-otlp-proto/test/OTLPTraceExporter.test.ts @@ -47,16 +47,25 @@ describe('OTLPTraceExporter - node with proto over http', () => { describe('when configuring via environment', () => { const envSource = process.env; - it('should use url defined in env', () => { + it('should use url defined in env that ends with root path and append version and signal path', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/'; + const collectorExporter = new OTLPTraceExporter(); + assert.strictEqual( + collectorExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}v1/traces` + ); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + }); + it('should use url defined in env without checking if path is already present', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/v1/traces'; const collectorExporter = new OTLPTraceExporter(); assert.strictEqual( collectorExporter.url, - envSource.OTEL_EXPORTER_OTLP_ENDPOINT + `${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/traces` ); envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; }); - it('should use url defined in env and append version and signal when not present', () => { + it('should use url defined in env and append version and signal', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; const collectorExporter = new OTLPTraceExporter(); assert.strictEqual( @@ -66,8 +75,8 @@ describe('OTLPTraceExporter - node with proto over http', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; }); it('should override global exporter url with signal url defined in env', () => { - envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; - envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.traces'; + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/'; + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.traces/'; const collectorExporter = new OTLPTraceExporter(); assert.strictEqual( collectorExporter.url, @@ -76,6 +85,42 @@ describe('OTLPTraceExporter - node with proto over http', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; }); + it('should add root path when signal url defined in env contains no path and no root path', () => { + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.bar'; + const collectorExporter = new OTLPTraceExporter(); + assert.strictEqual( + collectorExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT}/` + ); + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains root path but no path', () => { + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.bar/'; + const collectorExporter = new OTLPTraceExporter(); + assert.strictEqual( + collectorExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains path', () => { + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.bar/v1/traces'; + const collectorExporter = new OTLPTraceExporter(); + assert.strictEqual( + collectorExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains path and ends in /', () => { + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = 'http://foo.bar/v1/traces/'; + const collectorExporter = new OTLPTraceExporter(); + assert.strictEqual( + collectorExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; + }); it('should use headers defined via env', () => { envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar'; const collectorExporter = new OTLPTraceExporter(); diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/browser/OTLPMetricExporter.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/browser/OTLPMetricExporter.ts index 16dfd998bf..e7aedd8d99 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/browser/OTLPMetricExporter.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/src/platform/browser/OTLPMetricExporter.ts @@ -19,14 +19,15 @@ import { baggageUtils, getEnv } from '@opentelemetry/core'; import { defaultOptions, OTLPMetricExporterOptions } from '../../OTLPMetricExporterOptions'; import { OTLPMetricExporterBase } from '../../OTLPMetricExporterBase'; import { - appendResourcePathToUrlIfNotPresent, OTLPExporterBrowserBase, - OTLPExporterConfigBase + OTLPExporterConfigBase, + appendResourcePathToUrl, + appendRootPathToUrlIfNeeded } from '@opentelemetry/otlp-exporter-base'; import { createExportMetricsServiceRequest, IExportMetricsServiceRequest } from '@opentelemetry/otlp-transformer'; -const DEFAULT_COLLECTOR_RESOURCE_PATH = '/v1/metrics'; -const DEFAULT_COLLECTOR_URL = `http://localhost:4318${DEFAULT_COLLECTOR_RESOURCE_PATH}`; +const DEFAULT_COLLECTOR_RESOURCE_PATH = 'v1/metrics'; +const DEFAULT_COLLECTOR_URL = `http://localhost:4318/${DEFAULT_COLLECTOR_RESOURCE_PATH}`; class OTLPExporterBrowserProxy extends OTLPExporterBrowserBase { @@ -44,9 +45,9 @@ class OTLPExporterBrowserProxy extends OTLPExporterBrowserBase 0 - ? getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT + ? appendRootPathToUrlIfNeeded(getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0 - ? appendResourcePathToUrlIfNotPresent(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) + ? appendResourcePathToUrl(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) : DEFAULT_COLLECTOR_URL; } 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 10de31aa53..4652764f7d 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 @@ -19,14 +19,15 @@ import { getEnv, baggageUtils} from '@opentelemetry/core'; import { defaultOptions, OTLPMetricExporterOptions } from '../../OTLPMetricExporterOptions'; import { OTLPMetricExporterBase } from '../../OTLPMetricExporterBase'; import { - appendResourcePathToUrlIfNotPresent, OTLPExporterNodeBase, - OTLPExporterNodeConfigBase + OTLPExporterNodeConfigBase, + appendResourcePathToUrl, + appendRootPathToUrlIfNeeded } from '@opentelemetry/otlp-exporter-base'; import { createExportMetricsServiceRequest, IExportMetricsServiceRequest } from '@opentelemetry/otlp-transformer'; -const DEFAULT_COLLECTOR_RESOURCE_PATH = '/v1/metrics'; -const DEFAULT_COLLECTOR_URL = `http://localhost:4318${DEFAULT_COLLECTOR_RESOURCE_PATH}`; +const DEFAULT_COLLECTOR_RESOURCE_PATH = 'v1/metrics'; +const DEFAULT_COLLECTOR_URL = `http://localhost:4318/${DEFAULT_COLLECTOR_RESOURCE_PATH}`; class OTLPExporterNodeProxy extends OTLPExporterNodeBase { @@ -48,9 +49,9 @@ class OTLPExporterNodeProxy extends OTLPExporterNodeBase 0 - ? getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT + ? appendRootPathToUrlIfNeeded(getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0 - ? appendResourcePathToUrlIfNotPresent(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) + ? appendResourcePathToUrl(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) : DEFAULT_COLLECTOR_URL; } } diff --git a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/CollectorMetricExporter.test.ts b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/CollectorMetricExporter.test.ts index 18deb1e16d..f1e00dce99 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/CollectorMetricExporter.test.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-http/test/browser/CollectorMetricExporter.test.ts @@ -377,16 +377,25 @@ describe('OTLPMetricExporter - web', () => { describe('when configuring via environment', () => { const envSource = window as any; - it('should use url defined in env', () => { + it('should use url defined in env that ends with root path and append version and signal path', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/'; + const collectorExporter = new OTLPMetricExporter(); + assert.strictEqual( + collectorExporter._otlpExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}v1/metrics` + ); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + }); + it('should use url defined in env without checking if path is already present', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/v1/metrics'; const collectorExporter = new OTLPMetricExporter(); assert.strictEqual( collectorExporter._otlpExporter.url, - envSource.OTEL_EXPORTER_OTLP_ENDPOINT + `${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/metrics` ); envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; }); - it('should use url defined in env and append version and signal when not present', () => { + it('should use url defined in env and append version and signal', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; const collectorExporter = new OTLPMetricExporter(); assert.strictEqual( @@ -396,8 +405,8 @@ describe('when configuring via environment', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; }); it('should override global exporter url with signal url defined in env', () => { - envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; - envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.metrics'; + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/'; + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.metrics/'; const collectorExporter = new OTLPMetricExporter(); assert.strictEqual( collectorExporter._otlpExporter.url, @@ -406,6 +415,42 @@ describe('when configuring via environment', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; }); + it('should add root path when signal url defined in env contains no path and no root path', () => { + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.bar'; + const collectorExporter = new OTLPMetricExporter(); + assert.strictEqual( + collectorExporter._otlpExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT}/` + ); + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains root path but no path', () => { + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.bar/'; + const collectorExporter = new OTLPMetricExporter(); + assert.strictEqual( + collectorExporter._otlpExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains path', () => { + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.bar/v1/metrics'; + const collectorExporter = new OTLPMetricExporter(); + assert.strictEqual( + collectorExporter._otlpExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains path and ends in /', () => { + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.bar/v1/metrics/'; + const collectorExporter = new OTLPMetricExporter(); + assert.strictEqual( + collectorExporter._otlpExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; + }); it('should use headers defined via env', () => { envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar'; const collectorExporter = new OTLPMetricExporter({ 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 a9076abafb..a34f1e4f67 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 @@ -98,16 +98,25 @@ describe('OTLPMetricExporter - node with json over http', () => { describe('when configuring via environment', () => { const envSource = process.env; - it('should use url defined in env', () => { + it('should use url defined in env that ends with root path and append version and signal path', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/'; + const collectorExporter = new OTLPMetricExporter(); + assert.strictEqual( + collectorExporter._otlpExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}v1/metrics` + ); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + }); + it('should use url defined in env without checking if path is already present', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/v1/metrics'; const collectorExporter = new OTLPMetricExporter(); assert.strictEqual( collectorExporter._otlpExporter.url, - envSource.OTEL_EXPORTER_OTLP_ENDPOINT + `${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/metrics` ); envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; }); - it('should use url defined in env and append version and signal when not present', () => { + it('should use url defined in env and append version and signal', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; const collectorExporter = new OTLPMetricExporter(); assert.strictEqual( @@ -117,8 +126,8 @@ describe('OTLPMetricExporter - node with json over http', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; }); it('should override global exporter url with signal url defined in env', () => { - envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; - envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.metrics'; + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/'; + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.metrics/'; const collectorExporter = new OTLPMetricExporter(); assert.strictEqual( collectorExporter._otlpExporter.url, @@ -127,6 +136,42 @@ describe('OTLPMetricExporter - node with json over http', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; }); + it('should add root path when signal url defined in env contains no path and no root path', () => { + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.bar'; + const collectorExporter = new OTLPMetricExporter(); + assert.strictEqual( + collectorExporter._otlpExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT}/` + ); + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains root path but no path', () => { + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.bar/'; + const collectorExporter = new OTLPMetricExporter(); + assert.strictEqual( + collectorExporter._otlpExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains path', () => { + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.bar/v1/metrics'; + const collectorExporter = new OTLPMetricExporter(); + assert.strictEqual( + collectorExporter._otlpExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains path and ends in /', () => { + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.bar/v1/metrics/'; + const collectorExporter = new OTLPMetricExporter(); + assert.strictEqual( + collectorExporter._otlpExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; + }); it('should use headers defined via env', () => { envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar'; const collectorExporter = new OTLPMetricExporter(); 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 ffcbede041..925be74611 100644 --- a/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/OTLPMetricExporter.ts +++ b/experimental/packages/opentelemetry-exporter-metrics-otlp-proto/src/OTLPMetricExporter.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { defaultOptions, OTLPMetricExporterOptions @@ -21,12 +22,15 @@ import { ServiceClientType, OTLPProtoExporterNodeBase } from '@opentelemetry/otl import { getEnv, baggageUtils} from '@opentelemetry/core'; import { ResourceMetrics} from '@opentelemetry/sdk-metrics-base'; import { OTLPMetricExporterBase } from '@opentelemetry/exporter-metrics-otlp-http'; -import { appendResourcePathToUrlIfNotPresent, OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base'; +import { + OTLPExporterNodeConfigBase, + appendResourcePathToUrl, + appendRootPathToUrlIfNeeded +} from '@opentelemetry/otlp-exporter-base'; import { createExportMetricsServiceRequest, IExportMetricsServiceRequest } from '@opentelemetry/otlp-transformer'; -const DEFAULT_COLLECTOR_RESOURCE_PATH = '/v1/metrics'; -const DEFAULT_COLLECTOR_URL = `http://localhost:4318${DEFAULT_COLLECTOR_RESOURCE_PATH}`; - +const DEFAULT_COLLECTOR_RESOURCE_PATH = 'v1/metrics'; +const DEFAULT_COLLECTOR_URL = `http://localhost:4318/${DEFAULT_COLLECTOR_RESOURCE_PATH}`; class OTLPMetricExporterNodeProxy extends OTLPProtoExporterNodeBase { @@ -48,9 +52,9 @@ class OTLPMetricExporterNodeProxy extends OTLPProtoExporterNodeBase 0 - ? getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT + ? appendRootPathToUrlIfNeeded(getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0 - ? appendResourcePathToUrlIfNotPresent(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) + ? appendResourcePathToUrl(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH) : DEFAULT_COLLECTOR_URL; } 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 086c829ae1..d0d41865fa 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 @@ -52,16 +52,25 @@ describe('OTLPMetricExporter - node with proto over http', () => { describe('when configuring via environment', () => { const envSource = process.env; - it('should use url defined in env', () => { + it('should use url defined in env that ends with root path and append version and signal path', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/'; + const collectorExporter = new OTLPMetricExporter(); + assert.strictEqual( + collectorExporter._otlpExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}v1/metrics` + ); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + }); + it('should use url defined in env without checking if path is already present', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/v1/metrics'; const collectorExporter = new OTLPMetricExporter(); assert.strictEqual( collectorExporter._otlpExporter.url, - envSource.OTEL_EXPORTER_OTLP_ENDPOINT + `${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/metrics` ); envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; }); - it('should use url defined in env and append version and signal when not present', () => { + it('should use url defined in env and append version and signal', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; const collectorExporter = new OTLPMetricExporter(); assert.strictEqual( @@ -71,8 +80,8 @@ describe('OTLPMetricExporter - node with proto over http', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; }); it('should override global exporter url with signal url defined in env', () => { - envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; - envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.metrics'; + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/'; + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.metrics/'; const collectorExporter = new OTLPMetricExporter(); assert.strictEqual( collectorExporter._otlpExporter.url, @@ -81,6 +90,42 @@ describe('OTLPMetricExporter - node with proto over http', () => { envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; }); + it('should add root path when signal url defined in env contains no path and no root path', () => { + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.bar'; + const collectorExporter = new OTLPMetricExporter(); + assert.strictEqual( + collectorExporter._otlpExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT}/` + ); + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains root path but no path', () => { + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.bar/'; + const collectorExporter = new OTLPMetricExporter(); + assert.strictEqual( + collectorExporter._otlpExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains path', () => { + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.bar/v1/metrics'; + const collectorExporter = new OTLPMetricExporter(); + assert.strictEqual( + collectorExporter._otlpExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; + }); + it('should not add root path when signal url defined in env contains path and ends in /', () => { + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = 'http://foo.bar/v1/metrics/'; + const collectorExporter = new OTLPMetricExporter(); + assert.strictEqual( + collectorExporter._otlpExporter.url, + `${envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT}` + ); + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; + }); it('should use headers defined via env', () => { envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar'; const collectorExporter = new OTLPMetricExporter(); diff --git a/experimental/packages/otlp-exporter-base/src/util.ts b/experimental/packages/otlp-exporter-base/src/util.ts index 47629d9a8e..bfe9209758 100644 --- a/experimental/packages/otlp-exporter-base/src/util.ts +++ b/experimental/packages/otlp-exporter-base/src/util.ts @@ -37,18 +37,37 @@ export function parseHeaders( return headers; } -export function appendResourcePathToUrlIfNotPresent(url: string, path: string): string { - if (url.match(/v\d\/(traces|metrics)$/)) return url; - +/** + * Adds path (version + signal) to a no per-signal endpoint + * @param url + * @param path + * @returns url + path + */ +export function appendResourcePathToUrl(url: string, path: string): string { + if (!url.endsWith('/')) { + url = url + '/'; + } return url + path; } +/** + * Adds root path to signal specific endpoint when endpoint contains no path part and no root path + * @param url + * @param path + * @returns url + */ +export function appendRootPathToUrlIfNeeded(url: string, path: string): string { + if (!url.includes(path) && !url.endsWith('/')) { + url = url + '/'; + } + return url; +} + /** * Configure exporter trace timeout value from passed in value or environment variables * @param timeoutMillis * @returns timeout value in milliseconds */ - export function configureExporterTimeout(timeoutMillis: number | undefined): number { if (typeof timeoutMillis === 'number') { if (timeoutMillis <= 0) { diff --git a/experimental/packages/otlp-exporter-base/test/common/util.test.ts b/experimental/packages/otlp-exporter-base/test/common/util.test.ts index e241495214..cc29de641d 100644 --- a/experimental/packages/otlp-exporter-base/test/common/util.test.ts +++ b/experimental/packages/otlp-exporter-base/test/common/util.test.ts @@ -17,7 +17,11 @@ import * as assert from 'assert'; import * as sinon from 'sinon'; import { diag } from '@opentelemetry/api'; -import { parseHeaders } from '../../src/util'; +import { + parseHeaders, + appendResourcePathToUrl, + appendRootPathToUrlIfNeeded +} from '../../src/util'; describe('utils', () => { afterEach(() => { @@ -50,4 +54,54 @@ describe('utils', () => { assert.deepStrictEqual(result, {}); }); }); + + // only invoked with general endpoint (not signal specific endpoint) + describe('appendResourcePathToUrl - general http endpoint', () => { + it('should append resource path when missing', () => { + const url = 'http://foo.bar/'; + const resourcePath = 'v1/traces'; + + const finalUrl = appendResourcePathToUrl(url, resourcePath); + assert.strictEqual(finalUrl, url + resourcePath); + }); + it('should append root path and resource path when missing', () => { + const url = 'http://foo.bar'; + const resourcePath = 'v1/traces'; + + const finalUrl = appendResourcePathToUrl(url, resourcePath); + assert.strictEqual(finalUrl, url + '/' + resourcePath); + }); + it('should append resourse path even when url already contains path ', () => { + const url = 'http://foo.bar/v1/traces'; + const resourcePath = 'v1/traces'; + + const finalUrl = appendResourcePathToUrl(url, resourcePath); + assert.strictEqual(finalUrl, url + '/' + resourcePath); + }); + }); + + // only invoked with signal specific endpoint + describe('appendRootPathToUrlIfNeeded - specifc signal http endpoint', () => { + it('should append root path when missing', () => { + const url = 'http://foo.bar'; + const resourcePath = 'v1/traces'; + + const finalUrl = appendRootPathToUrlIfNeeded(url, resourcePath); + assert.strictEqual(finalUrl, url + '/'); + }); + it('should not append root path and return same url', () => { + const url = 'http://foo.bar/'; + const resourcePath = 'v1/traces'; + + const finalUrl = appendRootPathToUrlIfNeeded(url, resourcePath); + assert.strictEqual(finalUrl, url); + }); + it('should append root path when url contains resource path', () => { + const url = 'http://foo.bar/v1/traces'; + const resourcePath = 'v1/traces'; + + const finalUrl = appendRootPathToUrlIfNeeded(url, resourcePath); + assert.strictEqual(finalUrl, url); + }); + }); });