diff --git a/examples/collector-exporter-node/docker/collector-config.yaml b/examples/collector-exporter-node/docker/collector-config.yaml index e9a909d78fa..04d65a6ba2f 100644 --- a/examples/collector-exporter-node/docker/collector-config.yaml +++ b/examples/collector-exporter-node/docker/collector-config.yaml @@ -15,15 +15,14 @@ exporters: processors: batch: - queued_retry: service: pipelines: traces: receivers: [otlp] exporters: [zipkin] - processors: [batch, queued_retry] + processors: [batch] metrics: receivers: [otlp] exporters: [prometheus] - processors: [batch, queued_retry] + processors: [batch] diff --git a/examples/collector-exporter-node/docker/docker-compose.yaml b/examples/collector-exporter-node/docker/docker-compose.yaml index 97423dfa95b..1324c33f009 100644 --- a/examples/collector-exporter-node/docker/docker-compose.yaml +++ b/examples/collector-exporter-node/docker/docker-compose.yaml @@ -2,7 +2,7 @@ version: "3" services: # Collector collector: - image: otel/opentelemetry-collector:0.16.0 + image: otel/opentelemetry-collector:0.25.0 # image: otel/opentelemetry-collector:latest command: ["--config=/conf/collector-config.yaml", "--log-level=DEBUG"] volumes: diff --git a/packages/opentelemetry-core/src/baggage/constants.ts b/packages/opentelemetry-core/src/baggage/constants.ts new file mode 100644 index 00000000000..b043c2c5da6 --- /dev/null +++ b/packages/opentelemetry-core/src/baggage/constants.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +export const BAGGAGE_KEY_PAIR_SEPARATOR = '='; +export const BAGGAGE_PROPERTIES_SEPARATOR = ';'; +export const BAGGAGE_ITEMS_SEPARATOR = ','; + +// Name of the http header used to propagate the baggage +export const BAGGAGE_HEADER = 'baggage'; +// Maximum number of name-value pairs allowed by w3c spec +export const BAGGAGE_MAX_NAME_VALUE_PAIRS = 180; +// Maximum number of bytes per a single name-value pair allowed by w3c spec +export const BAGGAGE_MAX_PER_NAME_VALUE_PAIRS = 4096; +// Maximum total length of all name-value pairs allowed by w3c spec +export const BAGGAGE_MAX_TOTAL_LENGTH = 8192; diff --git a/packages/opentelemetry-core/src/baggage/propagation/HttpBaggagePropagator.ts b/packages/opentelemetry-core/src/baggage/propagation/HttpBaggagePropagator.ts index 33f636dfdc4..fb678a5e05a 100644 --- a/packages/opentelemetry-core/src/baggage/propagation/HttpBaggagePropagator.ts +++ b/packages/opentelemetry-core/src/baggage/propagation/HttpBaggagePropagator.ts @@ -15,7 +15,6 @@ */ import { - Baggage, Context, BaggageEntry, getBaggage, @@ -24,22 +23,15 @@ import { TextMapPropagator, TextMapSetter, createBaggage, - baggageEntryMetadataFromString, isInstrumentationSuppressed, } from '@opentelemetry/api'; - -const KEY_PAIR_SEPARATOR = '='; -const PROPERTIES_SEPARATOR = ';'; -const ITEMS_SEPARATOR = ','; - -// Name of the http header used to propagate the baggage -export const BAGGAGE_HEADER = 'baggage'; -// Maximum number of name-value pairs allowed by w3c spec -export const MAX_NAME_VALUE_PAIRS = 180; -// Maximum number of bytes per a single name-value pair allowed by w3c spec -export const MAX_PER_NAME_VALUE_PAIRS = 4096; -// Maximum total length of all name-value pairs allowed by w3c spec -export const MAX_TOTAL_LENGTH = 8192; +import { getKeyPairs, serializeKeyPairs, parsePairKeyValue } from '../utils'; +import { + BAGGAGE_MAX_NAME_VALUE_PAIRS, + BAGGAGE_ITEMS_SEPARATOR, + BAGGAGE_HEADER, + BAGGAGE_MAX_PER_NAME_VALUE_PAIRS, +} from '../constants'; /** * Propagates {@link Baggage} through Context format propagation. @@ -51,35 +43,17 @@ export class HttpBaggagePropagator implements TextMapPropagator { inject(context: Context, carrier: unknown, setter: TextMapSetter) { const baggage = getBaggage(context); if (!baggage || isInstrumentationSuppressed(context)) return; - const keyPairs = this._getKeyPairs(baggage) + const keyPairs = getKeyPairs(baggage) .filter((pair: string) => { - return pair.length <= MAX_PER_NAME_VALUE_PAIRS; + return pair.length <= BAGGAGE_MAX_PER_NAME_VALUE_PAIRS; }) - .slice(0, MAX_NAME_VALUE_PAIRS); - const headerValue = this._serializeKeyPairs(keyPairs); + .slice(0, BAGGAGE_MAX_NAME_VALUE_PAIRS); + const headerValue = serializeKeyPairs(keyPairs); if (headerValue.length > 0) { setter.set(carrier, BAGGAGE_HEADER, headerValue); } } - private _serializeKeyPairs(keyPairs: string[]) { - return keyPairs.reduce((hValue: string, current: string) => { - const value = `${hValue}${ - hValue !== '' ? ITEMS_SEPARATOR : '' - }${current}`; - return value.length > MAX_TOTAL_LENGTH ? hValue : value; - }, ''); - } - - private _getKeyPairs(baggage: Baggage): string[] { - return baggage - .getAllEntries() - .map( - ([key, value]) => - `${encodeURIComponent(key)}=${encodeURIComponent(value.value)}` - ); - } - extract(context: Context, carrier: unknown, getter: TextMapGetter): Context { const headerValue: string = getter.get(carrier, BAGGAGE_HEADER) as string; if (!headerValue) return context; @@ -87,9 +61,9 @@ export class HttpBaggagePropagator implements TextMapPropagator { if (headerValue.length === 0) { return context; } - const pairs = headerValue.split(ITEMS_SEPARATOR); + const pairs = headerValue.split(BAGGAGE_ITEMS_SEPARATOR); pairs.forEach(entry => { - const keyPair = this._parsePairKeyValue(entry); + const keyPair = parsePairKeyValue(entry); if (keyPair) { const baggageEntry: BaggageEntry = { value: keyPair.value }; if (keyPair.metadata) { @@ -104,24 +78,6 @@ export class HttpBaggagePropagator implements TextMapPropagator { return setBaggage(context, createBaggage(baggage)); } - private _parsePairKeyValue(entry: string) { - const valueProps = entry.split(PROPERTIES_SEPARATOR); - if (valueProps.length <= 0) return; - const keyPairPart = valueProps.shift(); - if (!keyPairPart) return; - const keyPair = keyPairPart.split(KEY_PAIR_SEPARATOR); - if (keyPair.length !== 2) return; - const key = decodeURIComponent(keyPair[0].trim()); - const value = decodeURIComponent(keyPair[1].trim()); - let metadata; - if (valueProps.length > 0) { - metadata = baggageEntryMetadataFromString( - valueProps.join(PROPERTIES_SEPARATOR) - ); - } - return { key, value, metadata }; - } - fields(): string[] { return [BAGGAGE_HEADER]; } diff --git a/packages/opentelemetry-core/src/baggage/utils.ts b/packages/opentelemetry-core/src/baggage/utils.ts new file mode 100644 index 00000000000..25935cf8f6a --- /dev/null +++ b/packages/opentelemetry-core/src/baggage/utils.ts @@ -0,0 +1,76 @@ +/* + * 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. + */ +import { Baggage, baggageEntryMetadataFromString } from '@opentelemetry/api'; +import { + BAGGAGE_ITEMS_SEPARATOR, + BAGGAGE_PROPERTIES_SEPARATOR, + BAGGAGE_KEY_PAIR_SEPARATOR, + BAGGAGE_MAX_TOTAL_LENGTH, +} from './constants'; + +export const serializeKeyPairs = (keyPairs: string[]) => { + return keyPairs.reduce((hValue: string, current: string) => { + const value = `${hValue}${ + hValue !== '' ? BAGGAGE_ITEMS_SEPARATOR : '' + }${current}`; + return value.length > BAGGAGE_MAX_TOTAL_LENGTH ? hValue : value; + }, ''); +}; + +export const getKeyPairs = (baggage: Baggage): string[] => { + return baggage + .getAllEntries() + .map( + ([key, value]) => + `${encodeURIComponent(key)}=${encodeURIComponent(value.value)}` + ); +}; + +export const parsePairKeyValue = (entry: string) => { + const valueProps = entry.split(BAGGAGE_PROPERTIES_SEPARATOR); + if (valueProps.length <= 0) return; + const keyPairPart = valueProps.shift(); + if (!keyPairPart) return; + const keyPair = keyPairPart.split(BAGGAGE_KEY_PAIR_SEPARATOR); + if (keyPair.length !== 2) return; + const key = decodeURIComponent(keyPair[0].trim()); + const value = decodeURIComponent(keyPair[1].trim()); + let metadata; + if (valueProps.length > 0) { + metadata = baggageEntryMetadataFromString( + valueProps.join(BAGGAGE_PROPERTIES_SEPARATOR) + ); + } + return { key, value, metadata }; +}; + +/** + * Parse a string serialized in the baggage HTTP Format (without metadata): + * https://github.com/w3c/baggage/blob/master/baggage/HTTP_HEADER_FORMAT.md + */ +export const parseKeyPairsIntoRecord = (value?: string) => { + if (typeof value !== 'string' || value.length === 0) return {}; + return value + .split(BAGGAGE_ITEMS_SEPARATOR) + .map(entry => { + return parsePairKeyValue(entry); + }) + .filter(keyPair => keyPair !== undefined && keyPair.value.length > 0) + .reduce>((headers, keyPair) => { + headers[keyPair!.key] = keyPair!.value; + return headers; + }, {}); +}; diff --git a/packages/opentelemetry-core/src/index.ts b/packages/opentelemetry-core/src/index.ts index 9cbf3642763..139263bc2f1 100644 --- a/packages/opentelemetry-core/src/index.ts +++ b/packages/opentelemetry-core/src/index.ts @@ -21,6 +21,8 @@ export * from './common/logging-error-handler'; export * from './common/time'; export * from './common/types'; export * from './ExportResult'; +export * from './version'; +export * as baggageUtils from './baggage/utils'; export * from './platform'; export * from './propagation/composite'; export * from './trace/HttpTraceContextPropagator'; diff --git a/packages/opentelemetry-core/src/utils/environment.ts b/packages/opentelemetry-core/src/utils/environment.ts index 9554fe64a57..61021a01ea3 100644 --- a/packages/opentelemetry-core/src/utils/environment.ts +++ b/packages/opentelemetry-core/src/utils/environment.ts @@ -67,6 +67,12 @@ export type ENVIRONMENT = { OTEL_EXPORTER_JAEGER_ENDPOINT?: string; OTEL_EXPORTER_JAEGER_PASSWORD?: string; OTEL_EXPORTER_JAEGER_USER?: string; + OTEL_EXPORTER_OTLP_ENDPOINT?: string; + OTEL_EXPORTER_OTLP_TRACES_ENDPOINT?: string; + OTEL_EXPORTER_OTLP_METRICS_ENDPOINT?: string; + OTEL_EXPORTER_OTLP_HEADERS?: string; + OTEL_EXPORTER_OTLP_TRACES_HEADERS?: string; + OTEL_EXPORTER_OTLP_METRICS_HEADERS?: string; OTEL_EXPORTER_ZIPKIN_ENDPOINT?: string; OTEL_LOG_LEVEL?: DiagLogLevel; OTEL_RESOURCE_ATTRIBUTES?: string; @@ -97,6 +103,12 @@ export const DEFAULT_ENVIRONMENT: Required = { OTEL_EXPORTER_JAEGER_ENDPOINT: '', OTEL_EXPORTER_JAEGER_PASSWORD: '', OTEL_EXPORTER_JAEGER_USER: '', + OTEL_EXPORTER_OTLP_ENDPOINT: '', + OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: '', + OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: '', + OTEL_EXPORTER_OTLP_HEADERS: '', + OTEL_EXPORTER_OTLP_TRACES_HEADERS: '', + OTEL_EXPORTER_OTLP_METRICS_HEADERS: '', OTEL_EXPORTER_ZIPKIN_ENDPOINT: 'http://localhost:9411/api/v2/spans', OTEL_LOG_LEVEL: DiagLogLevel.INFO, OTEL_NO_PATCH_MODULES: [], diff --git a/packages/opentelemetry-core/test/baggage/HttpBaggagePropagator.test.ts b/packages/opentelemetry-core/test/baggage/HttpBaggagePropagator.test.ts index f081693b45d..04aace011a4 100644 --- a/packages/opentelemetry-core/test/baggage/HttpBaggagePropagator.test.ts +++ b/packages/opentelemetry-core/test/baggage/HttpBaggagePropagator.test.ts @@ -25,10 +25,8 @@ import { } from '@opentelemetry/api'; import { ROOT_CONTEXT } from '@opentelemetry/api'; import * as assert from 'assert'; -import { - BAGGAGE_HEADER, - HttpBaggagePropagator, -} from '../../src/baggage/propagation/HttpBaggagePropagator'; +import { HttpBaggagePropagator } from '../../src/baggage/propagation/HttpBaggagePropagator'; +import { BAGGAGE_HEADER } from '../../src/baggage/constants'; describe('HttpBaggagePropagator', () => { const httpBaggagePropagator = new HttpBaggagePropagator(); diff --git a/packages/opentelemetry-exporter-collector-grpc/README.md b/packages/opentelemetry-exporter-collector-grpc/README.md index 93b01689a21..840afb71042 100644 --- a/packages/opentelemetry-exporter-collector-grpc/README.md +++ b/packages/opentelemetry-exporter-collector-grpc/README.md @@ -5,7 +5,7 @@ [![devDependencies][devDependencies-image]][devDependencies-url] [![Apache License][license-image]][license-image] -This module provides exporter for web and node to be used with [opentelemetry-collector][opentelemetry-collector-url] - last tested with version **0.16.0**. +This module provides exporter for web and node to be used with [opentelemetry-collector][opentelemetry-collector-url] - last tested with version **0.25.0**. ## Installation @@ -15,7 +15,7 @@ npm install --save @opentelemetry/exporter-collector-grpc ## Traces in Node - GRPC -The CollectorTraceExporter in Node expects the URL to only be the hostname. It will not work with `/v1/trace`. +The CollectorTraceExporter in Node expects the URL to only be the hostname. It will not work with `/v1/traces`. ```js const { BasicTracerProvider, SimpleSpanProcessor } = require('@opentelemetry/tracing'); diff --git a/packages/opentelemetry-exporter-collector-grpc/src/CollectorMetricExporter.ts b/packages/opentelemetry-exporter-collector-grpc/src/CollectorMetricExporter.ts index 9e2417805ec..8f5b79f45b6 100644 --- a/packages/opentelemetry-exporter-collector-grpc/src/CollectorMetricExporter.ts +++ b/packages/opentelemetry-exporter-collector-grpc/src/CollectorMetricExporter.ts @@ -21,6 +21,7 @@ import { import { MetricRecord, MetricExporter } from '@opentelemetry/metrics'; import { CollectorExporterConfigNode, ServiceClientType } from './types'; import { CollectorExporterNodeBase } from './CollectorExporterNodeBase'; +import { getEnv } from '@opentelemetry/core'; const DEFAULT_SERVICE_NAME = 'collector-metric-exporter'; const DEFAULT_COLLECTOR_URL = 'localhost:4317'; @@ -47,11 +48,14 @@ export class CollectorMetricExporter ); } - getDefaultUrl(config: CollectorExporterConfigNode): string { - if (!config.url) { - return DEFAULT_COLLECTOR_URL; - } - return config.url; + getDefaultUrl(config: CollectorExporterConfigNode) { + return typeof config.url === 'string' + ? config.url + : getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT.length > 0 + ? getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT + : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0 + ? getEnv().OTEL_EXPORTER_OTLP_ENDPOINT + : DEFAULT_COLLECTOR_URL; } getDefaultServiceName(config: CollectorExporterConfigNode): string { diff --git a/packages/opentelemetry-exporter-collector-grpc/src/CollectorTraceExporter.ts b/packages/opentelemetry-exporter-collector-grpc/src/CollectorTraceExporter.ts index da36d28c807..5166cccb921 100644 --- a/packages/opentelemetry-exporter-collector-grpc/src/CollectorTraceExporter.ts +++ b/packages/opentelemetry-exporter-collector-grpc/src/CollectorTraceExporter.ts @@ -21,6 +21,7 @@ import { toCollectorExportTraceServiceRequest, } from '@opentelemetry/exporter-collector'; import { CollectorExporterConfigNode, ServiceClientType } from './types'; +import { getEnv } from '@opentelemetry/core'; const DEFAULT_SERVICE_NAME = 'collector-trace-exporter'; const DEFAULT_COLLECTOR_URL = 'localhost:4317'; @@ -40,11 +41,14 @@ export class CollectorTraceExporter return toCollectorExportTraceServiceRequest(spans, this); } - getDefaultUrl(config: CollectorExporterConfigNode): string { - if (!config.url) { - return DEFAULT_COLLECTOR_URL; - } - return config.url; + getDefaultUrl(config: CollectorExporterConfigNode) { + return typeof config.url === 'string' + ? config.url + : getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0 + ? getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT + : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0 + ? getEnv().OTEL_EXPORTER_OTLP_ENDPOINT + : DEFAULT_COLLECTOR_URL; } getDefaultServiceName(config: CollectorExporterConfigNode): string { diff --git a/packages/opentelemetry-exporter-collector-grpc/test/CollectorMetricExporter.test.ts b/packages/opentelemetry-exporter-collector-grpc/test/CollectorMetricExporter.test.ts index 1426a30df90..c7b807d77ea 100644 --- a/packages/opentelemetry-exporter-collector-grpc/test/CollectorMetricExporter.test.ts +++ b/packages/opentelemetry-exporter-collector-grpc/test/CollectorMetricExporter.test.ts @@ -259,6 +259,30 @@ describe('CollectorMetricExporter - node (getDefaultUrl)', () => { }); }); +describe('when configuring via environment', () => { + const envSource = process.env; + it('should use url defined in env', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; + const collectorExporter = new CollectorMetricExporter(); + assert.strictEqual( + collectorExporter.url, + envSource.OTEL_EXPORTER_OTLP_ENDPOINT + ); + 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'; + const collectorExporter = new CollectorMetricExporter(); + assert.strictEqual( + collectorExporter.url, + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT + ); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; + }); +}); + testCollectorMetricExporter({ useTLS: true }); testCollectorMetricExporter({ useTLS: false }); testCollectorMetricExporter({ metadata }); diff --git a/packages/opentelemetry-exporter-collector-grpc/test/CollectorTraceExporter.test.ts b/packages/opentelemetry-exporter-collector-grpc/test/CollectorTraceExporter.test.ts index ce0163219dc..e090c05471e 100644 --- a/packages/opentelemetry-exporter-collector-grpc/test/CollectorTraceExporter.test.ts +++ b/packages/opentelemetry-exporter-collector-grpc/test/CollectorTraceExporter.test.ts @@ -221,6 +221,30 @@ describe('CollectorTraceExporter - node (getDefaultUrl)', () => { }); }); +describe('when configuring via environment', () => { + const envSource = process.env; + it('should use url defined in env', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; + const collectorExporter = new CollectorTraceExporter(); + assert.strictEqual( + collectorExporter.url, + envSource.OTEL_EXPORTER_OTLP_ENDPOINT + ); + 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'; + const collectorExporter = new CollectorTraceExporter(); + assert.strictEqual( + collectorExporter.url, + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT + ); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; + }); +}); + testCollectorExporter({ useTLS: true }); testCollectorExporter({ useTLS: false }); testCollectorExporter({ metadata }); diff --git a/packages/opentelemetry-exporter-collector-proto/README.md b/packages/opentelemetry-exporter-collector-proto/README.md index 29dcd11d35a..4d8bee9f08e 100644 --- a/packages/opentelemetry-exporter-collector-proto/README.md +++ b/packages/opentelemetry-exporter-collector-proto/README.md @@ -5,7 +5,7 @@ [![devDependencies][devDependencies-image]][devDependencies-url] [![Apache License][license-image]][license-image] -This module provides exporter for node to be used with [opentelemetry-collector][opentelemetry-collector-url] - last tested with version **0.16.0**. +This module provides exporter for node to be used with [opentelemetry-collector][opentelemetry-collector-url] - last tested with version **0.25.0**. ## Installation @@ -21,7 +21,7 @@ const { CollectorTraceExporter } = require('@opentelemetry/exporter-collector-p const collectorOptions = { serviceName: 'basic-service', - url: '', // url is optional and can be omitted - default is http://localhost:55681/v1/trace + url: '', // url is optional and can be omitted - default is http://localhost:55681/v1/traces headers: { foo: 'bar' }, //an optional object containing custom headers to be sent with each request will only work with http diff --git a/packages/opentelemetry-exporter-collector-proto/src/CollectorMetricExporter.ts b/packages/opentelemetry-exporter-collector-proto/src/CollectorMetricExporter.ts index 43618f5c068..73c4156d3b4 100644 --- a/packages/opentelemetry-exporter-collector-proto/src/CollectorMetricExporter.ts +++ b/packages/opentelemetry-exporter-collector-proto/src/CollectorMetricExporter.ts @@ -22,9 +22,10 @@ import { import { MetricRecord, MetricExporter } from '@opentelemetry/metrics'; import { ServiceClientType } from './types'; import { CollectorExporterNodeBase } from './CollectorExporterNodeBase'; +import { getEnv, baggageUtils } from '@opentelemetry/core'; const DEFAULT_SERVICE_NAME = 'collector-metric-exporter'; -const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/metrics'; +const DEFAULT_COLLECTOR_URL = 'http://localhost:4317/v1/metrics'; /** * Collector Metric Exporter for Node with protobuf @@ -38,6 +39,16 @@ export class CollectorMetricExporter // Converts time to nanoseconds protected readonly _startTime = new Date().getTime() * 1000000; + constructor(config: CollectorExporterNodeConfigBase = {}) { + super(config); + this.headers = Object.assign( + this.headers, + baggageUtils.parseKeyPairsIntoRecord( + getEnv().OTEL_EXPORTER_OTLP_METRICS_HEADERS + ) + ); + } + convert( metrics: MetricRecord[] ): collectorTypes.opentelemetryProto.collector.metrics.v1.ExportMetricsServiceRequest { @@ -48,11 +59,14 @@ export class CollectorMetricExporter ); } - getDefaultUrl(config: CollectorExporterNodeConfigBase): string { - if (!config.url) { - return DEFAULT_COLLECTOR_URL; - } - return config.url; + getDefaultUrl(config: CollectorExporterNodeConfigBase) { + return typeof config.url === 'string' + ? config.url + : getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT.length > 0 + ? getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT + : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0 + ? getEnv().OTEL_EXPORTER_OTLP_ENDPOINT + : DEFAULT_COLLECTOR_URL; } getDefaultServiceName(config: CollectorExporterNodeConfigBase): string { diff --git a/packages/opentelemetry-exporter-collector-proto/src/CollectorTraceExporter.ts b/packages/opentelemetry-exporter-collector-proto/src/CollectorTraceExporter.ts index 49d29c5d60d..4c08ddb6681 100644 --- a/packages/opentelemetry-exporter-collector-proto/src/CollectorTraceExporter.ts +++ b/packages/opentelemetry-exporter-collector-proto/src/CollectorTraceExporter.ts @@ -22,9 +22,10 @@ import { CollectorExporterNodeConfigBase, } from '@opentelemetry/exporter-collector'; import { ServiceClientType } from './types'; +import { getEnv, baggageUtils } from '@opentelemetry/core'; const DEFAULT_SERVICE_NAME = 'collector-trace-exporter'; -const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/trace'; +const DEFAULT_COLLECTOR_URL = 'http://localhost:4317/v1/traces'; /** * Collector Trace Exporter for Node with protobuf @@ -35,17 +36,30 @@ export class CollectorTraceExporter collectorTypes.opentelemetryProto.collector.trace.v1.ExportTraceServiceRequest > implements SpanExporter { + constructor(config: CollectorExporterNodeConfigBase = {}) { + super(config); + this.headers = Object.assign( + this.headers, + baggageUtils.parseKeyPairsIntoRecord( + getEnv().OTEL_EXPORTER_OTLP_TRACES_HEADERS + ) + ); + } + convert( spans: ReadableSpan[] ): collectorTypes.opentelemetryProto.collector.trace.v1.ExportTraceServiceRequest { return toCollectorExportTraceServiceRequest(spans, this); } - getDefaultUrl(config: CollectorExporterNodeConfigBase): string { - if (!config.url) { - return DEFAULT_COLLECTOR_URL; - } - return config.url; + getDefaultUrl(config: CollectorExporterNodeConfigBase) { + return typeof config.url === 'string' + ? config.url + : getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0 + ? getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT + : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0 + ? getEnv().OTEL_EXPORTER_OTLP_ENDPOINT + : DEFAULT_COLLECTOR_URL; } getDefaultServiceName(config: CollectorExporterNodeConfigBase): string { diff --git a/packages/opentelemetry-exporter-collector-proto/test/CollectorMetricExporter.test.ts b/packages/opentelemetry-exporter-collector-proto/test/CollectorMetricExporter.test.ts index 13fede22c51..5f4c4447a5e 100644 --- a/packages/opentelemetry-exporter-collector-proto/test/CollectorMetricExporter.test.ts +++ b/packages/opentelemetry-exporter-collector-proto/test/CollectorMetricExporter.test.ts @@ -53,6 +53,45 @@ describe('CollectorMetricExporter - node with proto over http', () => { let collectorExporterConfig: CollectorExporterNodeConfigBase; let metrics: metrics.MetricRecord[]; + describe('when configuring via environment', () => { + const envSource = process.env; + it('should use url defined in env', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; + const collectorExporter = new CollectorMetricExporter(); + assert.strictEqual( + collectorExporter.url, + envSource.OTEL_EXPORTER_OTLP_ENDPOINT + ); + 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'; + const collectorExporter = new CollectorMetricExporter(); + assert.strictEqual( + collectorExporter.url, + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT + ); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; + }); + it('should use headers defined via env', () => { + envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar'; + const collectorExporter = new CollectorMetricExporter(); + assert.strictEqual(collectorExporter.headers.foo, 'bar'); + envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; + }); + it('should override global headers config with signal headers defined via env', () => { + envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo'; + envSource.OTEL_EXPORTER_OTLP_METRICS_HEADERS = 'foo=boo'; + const collectorExporter = new CollectorMetricExporter(); + assert.strictEqual(collectorExporter.headers.foo, 'boo'); + assert.strictEqual(collectorExporter.headers.bar, 'foo'); + envSource.OTEL_EXPORTER_OTLP_METRICS_HEADERS = ''; + envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; + }); + }); + describe('export', () => { beforeEach(async () => { collectorExporterConfig = { diff --git a/packages/opentelemetry-exporter-collector-proto/test/CollectorTraceExporter.test.ts b/packages/opentelemetry-exporter-collector-proto/test/CollectorTraceExporter.test.ts index a826fa6ddfd..fd812f7a4ad 100644 --- a/packages/opentelemetry-exporter-collector-proto/test/CollectorTraceExporter.test.ts +++ b/packages/opentelemetry-exporter-collector-proto/test/CollectorTraceExporter.test.ts @@ -44,6 +44,45 @@ describe('CollectorTraceExporter - node with proto over http', () => { let collectorExporterConfig: CollectorExporterNodeConfigBase; let spans: ReadableSpan[]; + describe('when configuring via environment', () => { + const envSource = process.env; + it('should use url defined in env', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; + const collectorExporter = new CollectorTraceExporter(); + assert.strictEqual( + collectorExporter.url, + envSource.OTEL_EXPORTER_OTLP_ENDPOINT + ); + 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'; + const collectorExporter = new CollectorTraceExporter(); + assert.strictEqual( + collectorExporter.url, + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT + ); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; + }); + it('should use headers defined via env', () => { + envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar'; + const collectorExporter = new CollectorTraceExporter(); + assert.strictEqual(collectorExporter.headers.foo, 'bar'); + envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; + }); + it('should override global headers config with signal headers defined via env', () => { + envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo'; + envSource.OTEL_EXPORTER_OTLP_TRACES_HEADERS = 'foo=boo'; + const collectorExporter = new CollectorTraceExporter(); + assert.strictEqual(collectorExporter.headers.foo, 'boo'); + assert.strictEqual(collectorExporter.headers.bar, 'foo'); + envSource.OTEL_EXPORTER_OTLP_TRACES_HEADERS = ''; + envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; + }); + }); + describe('export', () => { beforeEach(() => { collectorExporterConfig = { diff --git a/packages/opentelemetry-exporter-collector/README.md b/packages/opentelemetry-exporter-collector/README.md index 4b60a4d4ea0..33934ed95e1 100644 --- a/packages/opentelemetry-exporter-collector/README.md +++ b/packages/opentelemetry-exporter-collector/README.md @@ -5,7 +5,7 @@ [![devDependencies][devDependencies-image]][devDependencies-url] [![Apache License][license-image]][license-image] -This module provides exporter for web and node to be used with [opentelemetry-collector][opentelemetry-collector-url] - last tested with version **0.16.0**. +This module provides exporter for web and node to be used with [opentelemetry-collector][opentelemetry-collector-url] - last tested with version **0.25.0**. ## Installation @@ -15,7 +15,7 @@ npm install --save @opentelemetry/exporter-collector ## Traces in Web -The CollectorTraceExporter in Web expects the endpoint to end in `/v1/trace`. +The CollectorTraceExporter in Web expects the endpoint to end in `/v1/traces`. ```js import { BatchSpanProcessor } from '@opentelemetry/tracing'; diff --git a/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorExporterBrowserBase.ts b/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorExporterBrowserBase.ts index 00a43641276..3c5ed1fbf1f 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorExporterBrowserBase.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorExporterBrowserBase.ts @@ -20,6 +20,7 @@ import * as collectorTypes from '../../types'; import { parseHeaders } from '../../util'; import { sendWithBeacon, sendWithXhr } from './util'; import { diag } from '@opentelemetry/api'; +import { getEnv, baggageUtils } from '@opentelemetry/core'; /** * Collector Metric Exporter abstract base class @@ -32,7 +33,7 @@ export abstract class CollectorExporterBrowserBase< ExportItem, ServiceRequest > { - private _headers: Record; + protected _headers: Record; private _useXHR: boolean = false; /** @@ -43,7 +44,13 @@ export abstract class CollectorExporterBrowserBase< this._useXHR = !!config.headers || typeof navigator.sendBeacon !== 'function'; if (this._useXHR) { - this._headers = parseHeaders(config.headers); + this._headers = Object.assign( + {}, + parseHeaders(config.headers), + baggageUtils.parseKeyPairsIntoRecord( + getEnv().OTEL_EXPORTER_OTLP_HEADERS + ) + ); } else { this._headers = {}; } diff --git a/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorMetricExporter.ts b/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorMetricExporter.ts index 09224a90aa0..4b8ce05b410 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorMetricExporter.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorMetricExporter.ts @@ -19,6 +19,7 @@ import { CollectorExporterConfigBase } from '../../types'; import * as collectorTypes from '../../types'; import { CollectorExporterBrowserBase } from './CollectorExporterBrowserBase'; import { toCollectorExportMetricServiceRequest } from '../../transformMetrics'; +import { getEnv, baggageUtils } from '@opentelemetry/core'; const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/metrics'; const DEFAULT_SERVICE_NAME = 'collector-metric-exporter'; @@ -35,6 +36,16 @@ export class CollectorMetricExporter // Converts time to nanoseconds private readonly _startTime = new Date().getTime() * 1000000; + constructor(config: CollectorExporterConfigBase = {}) { + super(config); + this._headers = Object.assign( + this._headers, + baggageUtils.parseKeyPairsIntoRecord( + getEnv().OTEL_EXPORTER_OTLP_METRICS_HEADERS + ) + ); + } + convert( metrics: MetricRecord[] ): collectorTypes.opentelemetryProto.collector.metrics.v1.ExportMetricsServiceRequest { @@ -45,8 +56,14 @@ export class CollectorMetricExporter ); } - getDefaultUrl(config: CollectorExporterConfigBase): string { - return config.url || DEFAULT_COLLECTOR_URL; + getDefaultUrl(config: CollectorExporterConfigBase) { + return typeof config.url === 'string' + ? config.url + : getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT.length > 0 + ? getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT + : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0 + ? getEnv().OTEL_EXPORTER_OTLP_ENDPOINT + : DEFAULT_COLLECTOR_URL; } getDefaultServiceName(config: CollectorExporterConfigBase): string { diff --git a/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts b/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts index e5826de390f..8115e3a5469 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/browser/CollectorTraceExporter.ts @@ -19,9 +19,10 @@ import { CollectorExporterBrowserBase } from './CollectorExporterBrowserBase'; import { ReadableSpan, SpanExporter } from '@opentelemetry/tracing'; import { toCollectorExportTraceServiceRequest } from '../../transform'; import * as collectorTypes from '../../types'; +import { getEnv, baggageUtils } from '@opentelemetry/core'; const DEFAULT_SERVICE_NAME = 'collector-trace-exporter'; -const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/trace'; +const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/traces'; /** * Collector Trace Exporter for Web @@ -32,6 +33,15 @@ export class CollectorTraceExporter collectorTypes.opentelemetryProto.collector.trace.v1.ExportTraceServiceRequest > implements SpanExporter { + constructor(config: CollectorExporterConfigBase = {}) { + super(config); + this._headers = Object.assign( + this._headers, + baggageUtils.parseKeyPairsIntoRecord( + getEnv().OTEL_EXPORTER_OTLP_TRACES_HEADERS + ) + ); + } convert( spans: ReadableSpan[] ): collectorTypes.opentelemetryProto.collector.trace.v1.ExportTraceServiceRequest { @@ -39,10 +49,16 @@ export class CollectorTraceExporter } getDefaultUrl(config: CollectorExporterConfigBase) { - return config.url || DEFAULT_COLLECTOR_URL; + return typeof config.url === 'string' + ? config.url + : getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0 + ? getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT + : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0 + ? getEnv().OTEL_EXPORTER_OTLP_ENDPOINT + : DEFAULT_COLLECTOR_URL; } getDefaultServiceName(config: CollectorExporterConfigBase): string { - return config.serviceName || DEFAULT_SERVICE_NAME; + return config.serviceName ?? DEFAULT_SERVICE_NAME; } } diff --git a/packages/opentelemetry-exporter-collector/src/platform/browser/util.ts b/packages/opentelemetry-exporter-collector/src/platform/browser/util.ts index 9e267fb6cb4..a695ee6944d 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/browser/util.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/browser/util.ts @@ -49,7 +49,7 @@ export function sendWithBeacon( export function sendWithXhr( body: string, url: string, - headers: { [key: string]: string }, + headers: Record, onSuccess: () => void, onError: (error: collectorTypes.CollectorExporterError) => void ) { diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/CollectorExporterNodeBase.ts b/packages/opentelemetry-exporter-collector/src/platform/node/CollectorExporterNodeBase.ts index a57e362d0d7..7b5dc98446d 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/CollectorExporterNodeBase.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/CollectorExporterNodeBase.ts @@ -23,6 +23,7 @@ import * as collectorTypes from '../../types'; import { parseHeaders } from '../../util'; import { createHttpAgent, sendWithHttp } from './util'; import { diag } from '@opentelemetry/api'; +import { getEnv, baggageUtils } from '@opentelemetry/core'; /** * Collector Metric Exporter abstract base class @@ -38,12 +39,17 @@ export abstract class CollectorExporterNodeBase< DEFAULT_HEADERS: Record = {}; headers: Record; agent: http.Agent | https.Agent | undefined; + constructor(config: CollectorExporterNodeConfigBase = {}) { super(config); if ((config as any).metadata) { diag.warn('Metadata cannot be set when using http'); } - this.headers = parseHeaders(config.headers) || this.DEFAULT_HEADERS; + this.headers = Object.assign( + this.DEFAULT_HEADERS, + parseHeaders(config.headers), + baggageUtils.parseKeyPairsIntoRecord(getEnv().OTEL_EXPORTER_OTLP_HEADERS) + ); this.agent = createHttpAgent(config); } diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/CollectorMetricExporter.ts b/packages/opentelemetry-exporter-collector/src/platform/node/CollectorMetricExporter.ts index 30c70e9e07a..90800cc250c 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/CollectorMetricExporter.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/CollectorMetricExporter.ts @@ -19,6 +19,7 @@ import * as collectorTypes from '../../types'; import { CollectorExporterNodeConfigBase } from './types'; import { CollectorExporterNodeBase } from './CollectorExporterNodeBase'; import { toCollectorExportMetricServiceRequest } from '../../transformMetrics'; +import { getEnv, baggageUtils } from '@opentelemetry/core'; const DEFAULT_SERVICE_NAME = 'collector-metric-exporter'; const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/metrics'; @@ -35,6 +36,16 @@ export class CollectorMetricExporter // Converts time to nanoseconds protected readonly _startTime = new Date().getTime() * 1000000; + constructor(config: CollectorExporterNodeConfigBase = {}) { + super(config); + this.headers = Object.assign( + this.headers, + baggageUtils.parseKeyPairsIntoRecord( + getEnv().OTEL_EXPORTER_OTLP_METRICS_HEADERS + ) + ); + } + convert( metrics: MetricRecord[] ): collectorTypes.opentelemetryProto.collector.metrics.v1.ExportMetricsServiceRequest { @@ -45,11 +56,14 @@ export class CollectorMetricExporter ); } - getDefaultUrl(config: CollectorExporterNodeConfigBase): string { - if (!config.url) { - return DEFAULT_COLLECTOR_URL; - } - return config.url; + getDefaultUrl(config: CollectorExporterNodeConfigBase) { + return typeof config.url === 'string' + ? config.url + : getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT.length > 0 + ? getEnv().OTEL_EXPORTER_OTLP_METRICS_ENDPOINT + : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0 + ? getEnv().OTEL_EXPORTER_OTLP_ENDPOINT + : DEFAULT_COLLECTOR_URL; } getDefaultServiceName(config: CollectorExporterNodeConfigBase): string { diff --git a/packages/opentelemetry-exporter-collector/src/platform/node/CollectorTraceExporter.ts b/packages/opentelemetry-exporter-collector/src/platform/node/CollectorTraceExporter.ts index 4d6e4c03ffa..f33d90400df 100644 --- a/packages/opentelemetry-exporter-collector/src/platform/node/CollectorTraceExporter.ts +++ b/packages/opentelemetry-exporter-collector/src/platform/node/CollectorTraceExporter.ts @@ -19,9 +19,10 @@ import { CollectorExporterNodeBase } from './CollectorExporterNodeBase'; import { CollectorExporterNodeConfigBase } from './types'; import * as collectorTypes from '../../types'; import { toCollectorExportTraceServiceRequest } from '../../transform'; +import { getEnv, baggageUtils } from '@opentelemetry/core'; const DEFAULT_SERVICE_NAME = 'collector-trace-exporter'; -const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/trace'; +const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/traces'; /** * Collector Trace Exporter for Node @@ -32,17 +33,30 @@ export class CollectorTraceExporter collectorTypes.opentelemetryProto.collector.trace.v1.ExportTraceServiceRequest > implements SpanExporter { + constructor(config: CollectorExporterNodeConfigBase = {}) { + super(config); + this.headers = Object.assign( + this.headers, + baggageUtils.parseKeyPairsIntoRecord( + getEnv().OTEL_EXPORTER_OTLP_TRACES_HEADERS + ) + ); + } + convert( spans: ReadableSpan[] ): collectorTypes.opentelemetryProto.collector.trace.v1.ExportTraceServiceRequest { return toCollectorExportTraceServiceRequest(spans, this, true); } - getDefaultUrl(config: CollectorExporterNodeConfigBase): string { - if (!config.url) { - return DEFAULT_COLLECTOR_URL; - } - return config.url; + getDefaultUrl(config: CollectorExporterNodeConfigBase) { + return typeof config.url === 'string' + ? config.url + : getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.length > 0 + ? getEnv().OTEL_EXPORTER_OTLP_TRACES_ENDPOINT + : getEnv().OTEL_EXPORTER_OTLP_ENDPOINT.length > 0 + ? getEnv().OTEL_EXPORTER_OTLP_ENDPOINT + : DEFAULT_COLLECTOR_URL; } getDefaultServiceName(config: CollectorExporterNodeConfigBase): string { diff --git a/packages/opentelemetry-exporter-collector/test/browser/CollectorMetricExporter.test.ts b/packages/opentelemetry-exporter-collector/test/browser/CollectorMetricExporter.test.ts index 2213028b9d9..5f40d55c2ef 100644 --- a/packages/opentelemetry-exporter-collector/test/browser/CollectorMetricExporter.test.ts +++ b/packages/opentelemetry-exporter-collector/test/browser/CollectorMetricExporter.test.ts @@ -380,3 +380,45 @@ describe('CollectorMetricExporter - web', () => { }); }); }); + +describe('when configuring via environment', () => { + const envSource = window as any; + it('should use url defined in env', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; + const collectorExporter = new CollectorMetricExporter(); + assert.strictEqual( + collectorExporter.url, + envSource.OTEL_EXPORTER_OTLP_ENDPOINT + ); + 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'; + const collectorExporter = new CollectorMetricExporter(); + assert.strictEqual( + collectorExporter.url, + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT + ); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; + }); + it('should use headers defined via env', () => { + envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar'; + const collectorExporter = new CollectorMetricExporter({ headers: {} }); + // @ts-expect-error access internal property for testing + assert.strictEqual(collectorExporter._headers.foo, 'bar'); + envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; + }); + it('should override global headers config with signal headers defined via env', () => { + envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo'; + envSource.OTEL_EXPORTER_OTLP_METRICS_HEADERS = 'foo=boo'; + const collectorExporter = new CollectorMetricExporter({ headers: {} }); + // @ts-expect-error access internal property for testing + assert.strictEqual(collectorExporter._headers.foo, 'boo'); + // @ts-expect-error access internal property for testing + assert.strictEqual(collectorExporter._headers.bar, 'foo'); + envSource.OTEL_EXPORTER_OTLP_METRICS_HEADERS = ''; + envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; + }); +}); diff --git a/packages/opentelemetry-exporter-collector/test/browser/CollectorTraceExporter.test.ts b/packages/opentelemetry-exporter-collector/test/browser/CollectorTraceExporter.test.ts index 2c02f751cb8..f0950cb3f27 100644 --- a/packages/opentelemetry-exporter-collector/test/browser/CollectorTraceExporter.test.ts +++ b/packages/opentelemetry-exporter-collector/test/browser/CollectorTraceExporter.test.ts @@ -294,7 +294,7 @@ describe('CollectorTraceExporter - browser (getDefaultUrl)', () => { setTimeout(() => { assert.strictEqual( collectorExporter['url'], - 'http://localhost:55681/v1/trace' + 'http://localhost:55681/v1/traces' ); done(); }); @@ -308,3 +308,45 @@ describe('CollectorTraceExporter - browser (getDefaultUrl)', () => { }); }); }); + +describe('when configuring via environment', () => { + const envSource = window as any; + it('should use url defined in env', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; + const collectorExporter = new CollectorTraceExporter(); + assert.strictEqual( + collectorExporter.url, + envSource.OTEL_EXPORTER_OTLP_ENDPOINT + ); + 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'; + const collectorExporter = new CollectorTraceExporter(); + assert.strictEqual( + collectorExporter.url, + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT + ); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; + }); + it('should use headers defined via env', () => { + envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar'; + const collectorExporter = new CollectorTraceExporter({ headers: {} }); + // @ts-expect-error access internal property for testing + assert.strictEqual(collectorExporter._headers.foo, 'bar'); + envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; + }); + it('should override global headers config with signal headers defined via env', () => { + envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo'; + envSource.OTEL_EXPORTER_OTLP_TRACES_HEADERS = 'foo=boo'; + const collectorExporter = new CollectorTraceExporter({ headers: {} }); + // @ts-expect-error access internal property for testing + assert.strictEqual(collectorExporter._headers.foo, 'boo'); + // @ts-expect-error access internal property for testing + assert.strictEqual(collectorExporter._headers.bar, 'foo'); + envSource.OTEL_EXPORTER_OTLP_TRACES_HEADERS = ''; + envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; + }); +}); diff --git a/packages/opentelemetry-exporter-collector/test/node/CollectorMetricExporter.test.ts b/packages/opentelemetry-exporter-collector/test/node/CollectorMetricExporter.test.ts index 765b603077d..dc3c0a98ff8 100644 --- a/packages/opentelemetry-exporter-collector/test/node/CollectorMetricExporter.test.ts +++ b/packages/opentelemetry-exporter-collector/test/node/CollectorMetricExporter.test.ts @@ -81,6 +81,45 @@ describe('CollectorMetricExporter - node with json over http', () => { }); }); + describe('when configuring via environment', () => { + const envSource = process.env; + it('should use url defined in env', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; + const collectorExporter = new CollectorMetricExporter(); + assert.strictEqual( + collectorExporter.url, + envSource.OTEL_EXPORTER_OTLP_ENDPOINT + ); + 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'; + const collectorExporter = new CollectorMetricExporter(); + assert.strictEqual( + collectorExporter.url, + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT + ); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + envSource.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT = ''; + }); + it('should use headers defined via env', () => { + envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar'; + const collectorExporter = new CollectorMetricExporter(); + assert.strictEqual(collectorExporter.headers.foo, 'bar'); + envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; + }); + it('should override global headers config with signal headers defined via env', () => { + envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo'; + envSource.OTEL_EXPORTER_OTLP_METRICS_HEADERS = 'foo=boo'; + const collectorExporter = new CollectorMetricExporter(); + assert.strictEqual(collectorExporter.headers.foo, 'boo'); + assert.strictEqual(collectorExporter.headers.bar, 'foo'); + envSource.OTEL_EXPORTER_OTLP_METRICS_HEADERS = ''; + envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; + }); + }); + describe('export', () => { beforeEach(async () => { stubRequest = sinon.stub(http, 'request').returns(fakeRequest as any); diff --git a/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporter.test.ts b/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporter.test.ts index 129e8b9ba6d..ec9fac3653e 100644 --- a/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporter.test.ts +++ b/packages/opentelemetry-exporter-collector/test/node/CollectorTraceExporter.test.ts @@ -67,6 +67,45 @@ describe('CollectorTraceExporter - node with json over http', () => { }); }); + describe('when configuring via environment', () => { + const envSource = process.env; + it('should use url defined in env', () => { + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar'; + const collectorExporter = new CollectorTraceExporter(); + assert.strictEqual( + collectorExporter.url, + envSource.OTEL_EXPORTER_OTLP_ENDPOINT + ); + 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'; + const collectorExporter = new CollectorTraceExporter(); + assert.strictEqual( + collectorExporter.url, + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT + ); + envSource.OTEL_EXPORTER_OTLP_ENDPOINT = ''; + envSource.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = ''; + }); + it('should use headers defined via env', () => { + envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar'; + const collectorExporter = new CollectorTraceExporter(); + assert.strictEqual(collectorExporter.headers.foo, 'bar'); + envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; + }); + it('should override global headers config with signal headers defined via env', () => { + envSource.OTEL_EXPORTER_OTLP_HEADERS = 'foo=bar,bar=foo'; + envSource.OTEL_EXPORTER_OTLP_TRACES_HEADERS = 'foo=boo'; + const collectorExporter = new CollectorTraceExporter(); + assert.strictEqual(collectorExporter.headers.foo, 'boo'); + assert.strictEqual(collectorExporter.headers.bar, 'foo'); + envSource.OTEL_EXPORTER_OTLP_TRACES_HEADERS = ''; + envSource.OTEL_EXPORTER_OTLP_HEADERS = ''; + }); + }); + describe('export', () => { beforeEach(() => { stubRequest = sinon.stub(http, 'request').returns(fakeRequest as any); @@ -210,7 +249,7 @@ describe('CollectorTraceExporter - node with json over http', () => { setTimeout(() => { assert.strictEqual( collectorExporter['url'], - 'http://localhost:55681/v1/trace' + 'http://localhost:55681/v1/traces' ); done(); });