Skip to content

Commit

Permalink
feat: OTEL_EXPORTER_OTLP_ENDPOINT append version and signal (#2438)
Browse files Browse the repository at this point in the history
* fix(@opentelemetry/exporter-collector): OTEL_EXPORTER_OTLP_ENDPOINT append version and signal

collector convention of appending the version and signal to the path
(e.g. v1/traces or v1/metrics), if not present already

* docs: update exporter collector readme

* docs: update exporter readme

* refactor: append util

* fix: lint on readme

Co-authored-by: Bartlomiej Obecny <bobecny@gmail.com>
  • Loading branch information
longility and obecny committed Aug 31, 2021
1 parent f0caa22 commit dc574f7
Show file tree
Hide file tree
Showing 16 changed files with 117 additions and 21 deletions.
Expand Up @@ -18,13 +18,15 @@ import {
collectorTypes,
toCollectorExportMetricServiceRequest,
CollectorExporterNodeConfigBase,
appendResourcePathToUrlIfNotPresent,
} from '@opentelemetry/exporter-collector';
import { MetricRecord, MetricExporter } from '@opentelemetry/sdk-metrics-base';
import { ServiceClientType } from './types';
import { CollectorExporterNodeBase } from './CollectorExporterNodeBase';
import { getEnv, baggageUtils } from '@opentelemetry/core';

const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/metrics';
const DEFAULT_COLLECTOR_RESOURCE_PATH = '/v1/metrics';
const DEFAULT_COLLECTOR_URL=`http://localhost:55681${DEFAULT_COLLECTOR_RESOURCE_PATH}`;

/**
* Collector Metric Exporter for Node with protobuf
Expand Down Expand Up @@ -64,7 +66,7 @@ export class CollectorMetricExporter
: 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
? appendResourcePathToUrlIfNotPresent(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH)
: DEFAULT_COLLECTOR_URL;
}

Expand Down
Expand Up @@ -20,11 +20,13 @@ import {
collectorTypes,
toCollectorExportTraceServiceRequest,
CollectorExporterNodeConfigBase,
appendResourcePathToUrlIfNotPresent,
} from '@opentelemetry/exporter-collector';
import { ServiceClientType } from './types';
import { getEnv, baggageUtils } from '@opentelemetry/core';

const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/traces';
const DEFAULT_COLLECTOR_RESOURCE_PATH = '/v1/traces';
const DEFAULT_COLLECTOR_URL=`http://localhost:55681${DEFAULT_COLLECTOR_RESOURCE_PATH}`;

/**
* Collector Trace Exporter for Node with protobuf
Expand Down Expand Up @@ -57,7 +59,7 @@ export class CollectorTraceExporter
: 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
? appendResourcePathToUrlIfNotPresent(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH)
: DEFAULT_COLLECTOR_URL;
}

Expand Down
Expand Up @@ -85,4 +85,4 @@ export function send<ExportItem, ServiceRequest>(
} else {
onError(new collectorTypes.CollectorExporterError('No proto'));
}
}
}
Expand Up @@ -56,14 +56,23 @@ describe('CollectorMetricExporter - node with proto 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';
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/v1/metrics';
const collectorExporter = new CollectorMetricExporter();
assert.strictEqual(
collectorExporter.url,
envSource.OTEL_EXPORTER_OTLP_ENDPOINT
);
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = '';
});
it('should use url defined in env and append version and signal when not present', () => {
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar';
const collectorExporter = new CollectorMetricExporter();
assert.strictEqual(
collectorExporter.url,
`${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/metrics`
);
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';
Expand Down
Expand Up @@ -50,14 +50,23 @@ describe('CollectorTraceExporter - node with proto 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';
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/v1/traces';
const collectorExporter = new CollectorTraceExporter();
assert.strictEqual(
collectorExporter.url,
envSource.OTEL_EXPORTER_OTLP_ENDPOINT
);
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = '';
});
it('should use url defined in env and append version and signal when not present', () => {
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar';
const collectorExporter = new CollectorTraceExporter();
assert.strictEqual(
collectorExporter.url,
`${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/traces`
);
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';
Expand Down
27 changes: 25 additions & 2 deletions packages/opentelemetry-exporter-collector/README.md
Expand Up @@ -28,7 +28,7 @@ import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
import { CollectorTraceExporter } from '@opentelemetry/exporter-collector';

const collectorOptions = {
url: '<opentelemetry-collector-url>', // url is optional and can be omitted - default is http://localhost:55681/v1/trace
url: '<opentelemetry-collector-url>', // url is optional and can be omitted - default is http://localhost:55681/v1/traces
headers: {}, // an optional object containing custom headers to be sent with each request
concurrencyLimit: 10, // an optional limit on pending requests
};
Expand Down Expand Up @@ -83,7 +83,7 @@ const { BasicTracerProvider, BatchSpanProcessor } = require('@opentelemetry/sdk-
const { CollectorTraceExporter } = require('@opentelemetry/exporter-collector');

const collectorOptions = {
url: '<opentelemetry-collector-url>', // url is optional and can be omitted - default is http://localhost:55681/v1/trace
url: '<opentelemetry-collector-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
Expand Down Expand Up @@ -134,6 +134,28 @@ For GRPC please check [npm-url-grpc]

For PROTOBUF please check [npm-url-proto]

## Configuration options as environment variables

Instead of providing options to `CollectorMetricExporter` and `CollectorTraceExporter` explicitly, environment variables may be provided instead.

```sh
OTEL_EXPORTER_OTLP_ENDPOINT=https://localhost:4317
# this will automatically append the version and signal path
# e.g. https://localhost:4317/v1/traces for `CollectorTraceExporter` and https://localhost:4317/v1/metrics for `CollectorMetricExporter`
```

If the trace and metric exporter endpoints have different providers, the env var for per-signal endpoints are available to use

```sh
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://trace-service:4317/v1/traces
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://metric-service:4317/v1/metrics
# version and signal needs to be explicit
```

> The per-signal endpoints take precedence and overrides `OTEL_EXPORTER_OTLP_ENDPOINT`
For more details, see [OpenTelemetry Specification on Protocol Exporter][opentelemetry-spec-protocol-exporter].

## Running opentelemetry-collector locally to see the traces

1. Go to examples/collector-exporter-node
Expand Down Expand Up @@ -162,4 +184,5 @@ Apache 2.0 - See [LICENSE][license-url] for more information.
[npm-url-proto]: https://www.npmjs.com/package/@opentelemetry/exporter-collector-proto
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fexporter-collector.svg
[opentelemetry-collector-url]: https://github.com/open-telemetry/opentelemetry-collector
[opentelemetry-spec-protocol-exporter]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options
[semconv-resource-service-name]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service
1 change: 1 addition & 0 deletions packages/opentelemetry-exporter-collector/src/index.ts
Expand Up @@ -19,3 +19,4 @@ export * from './platform';
export * as collectorTypes from './types';
export { toCollectorExportTraceServiceRequest } from './transform';
export { toCollectorExportMetricServiceRequest } from './transformMetrics';
export { appendResourcePathToUrlIfNotPresent } from './util';
Expand Up @@ -20,8 +20,10 @@ import * as collectorTypes from '../../types';
import { CollectorExporterBrowserBase } from './CollectorExporterBrowserBase';
import { toCollectorExportMetricServiceRequest } from '../../transformMetrics';
import { getEnv, baggageUtils } from '@opentelemetry/core';
import { appendResourcePathToUrlIfNotPresent } from '../../util';

const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/metrics';
const DEFAULT_COLLECTOR_RESOURCE_PATH = '/v1/metrics';
const DEFAULT_COLLECTOR_URL=`http://localhost:55681${DEFAULT_COLLECTOR_RESOURCE_PATH}`;

/**
* Collector Metric Exporter for Web
Expand Down Expand Up @@ -61,7 +63,7 @@ export class CollectorMetricExporter
: 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
? appendResourcePathToUrlIfNotPresent(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH)
: DEFAULT_COLLECTOR_URL;
}
}
Expand Up @@ -20,8 +20,10 @@ import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';
import { toCollectorExportTraceServiceRequest } from '../../transform';
import * as collectorTypes from '../../types';
import { getEnv, baggageUtils } from '@opentelemetry/core';
import { appendResourcePathToUrlIfNotPresent } from '../../util';

const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/traces';
const DEFAULT_COLLECTOR_RESOURCE_PATH = '/v1/traces';
const DEFAULT_COLLECTOR_URL=`http://localhost:55681${DEFAULT_COLLECTOR_RESOURCE_PATH}`;

/**
* Collector Trace Exporter for Web
Expand Down Expand Up @@ -53,7 +55,7 @@ export class CollectorTraceExporter
: 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
? appendResourcePathToUrlIfNotPresent(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH)
: DEFAULT_COLLECTOR_URL;
}
}
Expand Up @@ -20,8 +20,10 @@ import { CollectorExporterNodeConfigBase } from './types';
import { CollectorExporterNodeBase } from './CollectorExporterNodeBase';
import { toCollectorExportMetricServiceRequest } from '../../transformMetrics';
import { getEnv, baggageUtils } from '@opentelemetry/core';
import { appendResourcePathToUrlIfNotPresent } from '../../util';

const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/metrics';
const DEFAULT_COLLECTOR_RESOURCE_PATH = '/v1/metrics';
const DEFAULT_COLLECTOR_URL=`http://localhost:55681${DEFAULT_COLLECTOR_RESOURCE_PATH}`;

/**
* Collector Metric Exporter for Node
Expand Down Expand Up @@ -61,7 +63,7 @@ export class CollectorMetricExporter
: 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
? appendResourcePathToUrlIfNotPresent(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH)
: DEFAULT_COLLECTOR_URL;
}
}
Expand Up @@ -20,8 +20,10 @@ import { CollectorExporterNodeConfigBase } from './types';
import * as collectorTypes from '../../types';
import { toCollectorExportTraceServiceRequest } from '../../transform';
import { getEnv, baggageUtils } from '@opentelemetry/core';
import { appendResourcePathToUrlIfNotPresent } from '../../util';

const DEFAULT_COLLECTOR_URL = 'http://localhost:55681/v1/traces';
const DEFAULT_COLLECTOR_RESOURCE_PATH = '/v1/traces';
const DEFAULT_COLLECTOR_URL=`http://localhost:55681${DEFAULT_COLLECTOR_RESOURCE_PATH}`;

/**
* Collector Trace Exporter for Node
Expand Down Expand Up @@ -54,7 +56,7 @@ export class CollectorTraceExporter
: 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
? appendResourcePathToUrlIfNotPresent(getEnv().OTEL_EXPORTER_OTLP_ENDPOINT, DEFAULT_COLLECTOR_RESOURCE_PATH)
: DEFAULT_COLLECTOR_URL;
}
}
6 changes: 6 additions & 0 deletions packages/opentelemetry-exporter-collector/src/util.ts
Expand Up @@ -33,3 +33,9 @@ export function parseHeaders(
});
return headers;
}

export function appendResourcePathToUrlIfNotPresent(url: string, path: string): string {
if (url.match(/v\d\/(traces|metrics)$/)) return url;

return url + path;
}
Expand Up @@ -383,14 +383,23 @@ 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';
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/v1/metrics';
const collectorExporter = new CollectorMetricExporter();
assert.strictEqual(
collectorExporter.url,
envSource.OTEL_EXPORTER_OTLP_ENDPOINT
);
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = '';
});
it('should use url defined in env and append version and signal when not present', () => {
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar';
const collectorExporter = new CollectorMetricExporter();
assert.strictEqual(
collectorExporter.url,
`${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/metrics`
);
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';
Expand Down
Expand Up @@ -312,14 +312,23 @@ 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';
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/v1/traces';
const collectorExporter = new CollectorTraceExporter();
assert.strictEqual(
collectorExporter.url,
envSource.OTEL_EXPORTER_OTLP_ENDPOINT
);
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = '';
});
it('should use url defined in env and append version and signal when not present', () => {
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar';
const collectorExporter = new CollectorTraceExporter();
assert.strictEqual(
collectorExporter.url,
`${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/traces`
);
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';
Expand Down
Expand Up @@ -84,14 +84,23 @@ 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';
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/v1/metrics';
const collectorExporter = new CollectorMetricExporter();
assert.strictEqual(
collectorExporter.url,
envSource.OTEL_EXPORTER_OTLP_ENDPOINT
);
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = '';
});
it('should use url defined in env and append version and signal when not present', () => {
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar';
const collectorExporter = new CollectorMetricExporter();
assert.strictEqual(
collectorExporter.url,
`${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/metrics`
);
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';
Expand Down
Expand Up @@ -70,14 +70,23 @@ 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';
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar/v1/traces';
const collectorExporter = new CollectorTraceExporter();
assert.strictEqual(
collectorExporter.url,
envSource.OTEL_EXPORTER_OTLP_ENDPOINT
);
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = '';
});
it('should use url defined in env and append version and signal when not present', () => {
envSource.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://foo.bar';
const collectorExporter = new CollectorTraceExporter();
assert.strictEqual(
collectorExporter.url,
`${envSource.OTEL_EXPORTER_OTLP_ENDPOINT}/v1/traces`
);
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';
Expand Down

0 comments on commit dc574f7

Please sign in to comment.