Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sdk-node): configure trace exporter with environment variables #3143

Merged
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
cf64bff
feat(sdk-node): wip add functionality to retrieve list of exporters
svetlanabrennan Jul 27, 2022
f6ff700
feat(sdk-node): wip add functionality to configure otlp
svetlanabrennan Jul 28, 2022
2259761
feat(sdk-node): wip add otlp protocol retrieval
svetlanabrennan Jul 28, 2022
651b5c7
feat(sdk-node): wip configure span processor
svetlanabrennan Jul 28, 2022
053175c
feat(sdk-node): wip create node tracer providers
svetlanabrennan Jul 28, 2022
a792d5d
feat(sdk-node): add otlp exporter tests
svetlanabrennan Jul 28, 2022
d2d54f1
Merge branch 'main' into add-trace-exporter-from-env
svetlanabrennan Jul 28, 2022
d852a9d
feat(sdk-node): refactor otlp protocol logic
svetlanabrennan Jul 28, 2022
b2eee41
feat(sdk-node): refactor configure exporter function
svetlanabrennan Jul 29, 2022
0d3b819
feat(sdk-node): add zipkin and jaeger exporters and tests
svetlanabrennan Jul 29, 2022
0ea7a6a
feat(sdk-node): add console exporter and tests
svetlanabrennan Jul 29, 2022
51c3203
feat(sdk-node): add console exporter and tests
svetlanabrennan Jul 29, 2022
4c50c25
feat(sdk-node): handle invalid exporters case
svetlanabrennan Jul 29, 2022
07f5df3
Merge branch 'main' into add-trace-exporter-from-env
svetlanabrennan Aug 2, 2022
663483c
feat(sdk-node): fix tests failing due to newly added feature
svetlanabrennan Aug 2, 2022
697e614
Merge branch 'main' into add-trace-exporter-from-env
svetlanabrennan Aug 3, 2022
de026d6
feat(sdk-node): add more unit tests
svetlanabrennan Aug 3, 2022
d579063
feat(sdk-node): add changelog
svetlanabrennan Aug 3, 2022
26ebf54
feat(sdk-node): add documentation to readme
svetlanabrennan Aug 3, 2022
3c35019
feat(sdk-node): add comments to public methods
svetlanabrennan Aug 3, 2022
0b2a104
feat(sdk-node): add integration tests
svetlanabrennan Aug 3, 2022
a9497c5
feat(sdk-node): fix lint
svetlanabrennan Aug 3, 2022
b718812
feat(sdk-node): fix lint in readme
svetlanabrennan Aug 3, 2022
9f94d56
feat(sdk-node): fix lint in readme
svetlanabrennan Aug 3, 2022
75c1404
feat(sdk-node): refactor to use class for tracer with env exporters
svetlanabrennan Aug 17, 2022
e7543b4
feat(sdk-node): fix lint
svetlanabrennan Aug 22, 2022
d807632
feat(sdk-node): refactor sdk class and tests
svetlanabrennan Aug 26, 2022
a979922
Merge branch 'main' into add-trace-exporter-from-env
svetlanabrennan Aug 26, 2022
405609d
feat(sdk-node): fix typo
svetlanabrennan Aug 26, 2022
d73b932
feat(sdk-node): fix typo
svetlanabrennan Aug 26, 2022
aed97d1
Merge branch 'add-trace-exporter-from-env' of github.com:svetlanabren…
svetlanabrennan Aug 26, 2022
0c634a0
feat(sdk-node): fix metric test
svetlanabrennan Aug 26, 2022
ec26779
feat(sdk-node): fix lint and refactor
svetlanabrennan Aug 29, 2022
fe888b9
feat(sdk-node): fix lint
svetlanabrennan Aug 29, 2022
c76d9d3
Rename tracerProviderWithEnvExporter.ts to TracerProviderWithEnvExpor…
svetlanabrennan Aug 29, 2022
c6e0a19
Merge branch 'main' into add-trace-exporter-from-env
svetlanabrennan Aug 29, 2022
e02d739
Merge branch 'main' into add-trace-exporter-from-env
svetlanabrennan Sep 1, 2022
0630bce
feat(sdk-node): move adding span processors to different class
svetlanabrennan Sep 7, 2022
c318a87
feat(sdk-node): add more tests and reconfigure some tests
svetlanabrennan Sep 19, 2022
f6d3ad7
Merge branch 'main' into add-trace-exporter-from-env
svetlanabrennan Sep 19, 2022
93f6367
feat(sdk-node): add missing env value deletion after test
svetlanabrennan Sep 19, 2022
e8a548c
Merge branch 'add-trace-exporter-from-env' of github.com:svetlanabren…
svetlanabrennan Sep 19, 2022
a42710e
feat(sdk-node): fix lint
svetlanabrennan Sep 19, 2022
83febe8
feat(sdk-node): override register method and upate logic and tests
svetlanabrennan Sep 23, 2022
6933ee4
Merge branch 'main' into add-trace-exporter-from-env
vmarchaud Sep 24, 2022
a5c2d93
feat(sdk-node): add override for addspanprocessor method
svetlanabrennan Sep 27, 2022
c2122f6
Merge branch 'add-trace-exporter-from-env' of github.com:svetlanabren…
svetlanabrennan Sep 27, 2022
6bc218e
feat(sdk-node): undo accidental changelog removal
svetlanabrennan Sep 27, 2022
7db936e
Undo accidental empty change heading
svetlanabrennan Sep 27, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions experimental/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ All notable changes to experimental packages in this project will be documented

### :rocket: (Enhancement)

* feat(sdk-node): configure trace exporter with environment variables [#3143](https://github.com/open-telemetry/opentelemetry-js/pull/3143) @svetlanabrennan
svetlanabrennan marked this conversation as resolved.
Show resolved Hide resolved

### :bug: (Bug Fix)

### :books: (Refine Doc)
Expand Down
26 changes: 25 additions & 1 deletion experimental/packages/opentelemetry-sdk-node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ Configure a custom sampler. By default all traces will be sampled.

### traceExporter

Configure a trace exporter. If an exporter OR span processor is not configured, the tracing SDK will not be initialized and registered. If an exporter is configured, it will be used with a [BatchSpanProcessor](../../../packages/opentelemetry-sdk-trace-base/src/platform/node/export/BatchSpanProcessor.ts).
Configure a trace exporter. If an exporter is configured, it will be used with a [BatchSpanProcessor](../../../packages/opentelemetry-sdk-trace-base/src/platform/node/export/BatchSpanProcessor.ts). If an exporter OR span processor is not configured programatically, this package will auto setup the default `otlp` exporter with `http/protobuf` protocol with a `BatchSpanProcessor`.

### spanLimits

Expand All @@ -136,6 +136,30 @@ Configure views of your instruments and accepts an array of [View](../openteleme

Configure the [service name](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#service).

## Configure Trace Exporter from Environment

This is an alternative to programmatically configuring an exporter or span processor. This package will auto setup the default `otlp` exporter with `http/protobuf` protocol if `traceExporter` or `spanProcessor` hasn't been passed into the `NodeSDK` constructor.

### Exporters

| Environment variable | Description |
|----------------------|-------------|
| OTEL_TRACES_EXPORTER | List of exporters to be used for tracing, separated by commas. Options include `otlp`, `jaeger`, `zipkin`, and `none`. Default is `otlp`. `none` means no autoconfigured exporter.

### OTLP Exporter

| Environment variable | Description |
|----------------------|-------------|
| OTEL_EXPORTER_OTLP_PROTOCOL | The transport protocol to use on OTLP trace, metric, and log requests. Options include `grpc`, `http/protobuf`, and `http/json`. Default is `http/protobuf`. |
| OTEL_EXPORTER_OTLP_TRACES_PROTOCOL | The transport protocol to use on OTLP trace requests. Options include `grpc`, `http/protobuf`, and `http/json`. Default is `http/protobuf`. |
| OTEL_EXPORTER_OTLP_METRICS_PROTOCOL | The transport protocol to use on OTLP metric requests. Options include `grpc`, `http/protobuf`, and `http/json`. Default is `http/protobuf`. |

Additionally, you can specify other applicable environment variables that apply to each exporter such as the following:

- [OTLP exporter environment configuration](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options)
- [Zipkin exporter environment configuration](https://github.com/open-telemetry/opentelemetry-specification/blob/6ce62202e5407518e19c56c445c13682ef51a51d/specification/sdk-environment-variables.md#zipkin-exporter)
- [Jaeger exporter environment configuration](https://github.com/open-telemetry/opentelemetry-specification/blob/6ce62202e5407518e19c56c445c13682ef51a51d/specification/sdk-environment-variables.md#jaeger-exporter)

## Useful links

- For more information on OpenTelemetry, visit: <https://opentelemetry.io/>
Expand Down
5 changes: 5 additions & 0 deletions experimental/packages/opentelemetry-sdk-node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@
"access": "public"
},
"dependencies": {
"@opentelemetry/exporter-jaeger": "^1.5.0",
"@opentelemetry/exporter-trace-otlp-grpc": "^0.31.0",
svetlanabrennan marked this conversation as resolved.
Show resolved Hide resolved
"@opentelemetry/exporter-trace-otlp-http": "^0.31.0",
"@opentelemetry/exporter-trace-otlp-proto": "^0.31.0",
"@opentelemetry/exporter-zipkin": "^1.5.0",
"@opentelemetry/api-metrics": "0.32.0",
"@opentelemetry/core": "1.6.0",
"@opentelemetry/instrumentation": "0.32.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* 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 { diag } from '@opentelemetry/api';
import { getEnv, getEnvWithoutDefaults } from '@opentelemetry/core';
import { ConsoleSpanExporter, SpanExporter, BatchSpanProcessor, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { NodeTracerConfig, NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { OTLPTraceExporter as OTLPProtoTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
import { OTLPTraceExporter as OTLPHttpTraceExporter} from '@opentelemetry/exporter-trace-otlp-http';
import { OTLPTraceExporter as OTLPGrpcTraceExporter} from '@opentelemetry/exporter-trace-otlp-grpc';
import { ZipkinExporter } from '@opentelemetry/exporter-zipkin';
import { JaegerExporter } from '@opentelemetry/exporter-jaeger';

export class TracerProviderWithEnvExporters extends NodeTracerProvider {
svetlanabrennan marked this conversation as resolved.
Show resolved Hide resolved
public configuredExporters: SpanExporter[] = [];
svetlanabrennan marked this conversation as resolved.
Show resolved Hide resolved
public spanProcessors: (BatchSpanProcessor | SimpleSpanProcessor)[] | undefined;
svetlanabrennan marked this conversation as resolved.
Show resolved Hide resolved

static configureOtlp(): SpanExporter {
const protocol = this.getOtlpProtocol();

switch (protocol) {
case 'grpc':
return new OTLPGrpcTraceExporter;
case 'http/json':
return new OTLPHttpTraceExporter;
case 'http/protobuf':
return new OTLPProtoTraceExporter;
default:
diag.warn(`Unsupported OTLP traces protocol: ${protocol}. Using http/protobuf.`);
return new OTLPProtoTraceExporter;
}
}

static getOtlpProtocol(): string {
const parsedEnvValues = getEnvWithoutDefaults();

return parsedEnvValues.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL ??
parsedEnvValues.OTEL_EXPORTER_OTLP_PROTOCOL ??
getEnv().OTEL_EXPORTER_OTLP_TRACES_PROTOCOL ??
getEnv().OTEL_EXPORTER_OTLP_PROTOCOL;
}

protected static override _registeredExporters = new Map<
string,
() => SpanExporter
>([
['otlp', () => this.configureOtlp()],
['zipkin', () => new ZipkinExporter],
['jaeger', () => new JaegerExporter],
['console', () => new ConsoleSpanExporter]
]);

public constructor(config: NodeTracerConfig = {}) {
super(config);
let traceExportersList = this.filterBlanksAndNulls(Array.from(new Set(getEnv().OTEL_TRACES_EXPORTER.split(','))));

if (traceExportersList.length === 0 || traceExportersList[0] === 'none') {
diag.warn('OTEL_TRACES_EXPORTER contains "none" or is empty. SDK will not be initialized.');
} else {
if (traceExportersList.length > 1 && traceExportersList.includes('none')) {
diag.warn('OTEL_TRACES_EXPORTER contains "none" along with other exporters. Using default otlp exporter.');
traceExportersList = ['otlp'];
}

traceExportersList.forEach(exporterName => {
const exporter = this._getSpanExporter(exporterName);
if (exporter) {
this.configuredExporters.push(exporter);
} else {
diag.warn(`Unrecognized OTEL_TRACES_EXPORTER value: ${exporterName}.`);
}
});

if (this.configuredExporters.length > 0) {
this.spanProcessors = this.configureSpanProcessors(this.configuredExporters);
} else {
diag.warn('Unable to set up trace exporter(s) due to invalid exporter and/or protocol values.');
}
}
}

public configureSpanProcessors(exporters: SpanExporter[]): (BatchSpanProcessor | SimpleSpanProcessor)[] {
svetlanabrennan marked this conversation as resolved.
Show resolved Hide resolved
return exporters.map(exporter => {
if (exporter instanceof ConsoleSpanExporter) {
return new SimpleSpanProcessor(exporter);
} else {
return new BatchSpanProcessor(exporter);
}
});
}

public filterBlanksAndNulls(list: string[]): string[] {
return list.map(item => item.trim())
.filter(s => s !== 'null' && s !== '');
}
}
49 changes: 36 additions & 13 deletions experimental/packages/opentelemetry-sdk-node/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ import {
import { MeterProvider, MetricReader, View } from '@opentelemetry/sdk-metrics';
import {
BatchSpanProcessor,
SpanProcessor
SpanProcessor,
} from '@opentelemetry/sdk-trace-base';
import { NodeTracerConfig, NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
import { NodeSDKConfiguration } from './types';
import { TracerProviderWithEnvExporters } from './TracerProviderWithEnvExporter';

/** This class represents everything needed to register a fully configured OpenTelemetry Node.js SDK */

Expand All @@ -60,14 +61,12 @@ export class NodeSDK {
};
private _meterProviderConfig?: MeterProviderConfig;
private _instrumentations: InstrumentationOption[];

private _resource: Resource;

private _autoDetectResources: boolean;

private _tracerProvider?: NodeTracerProvider;
private _tracerProvider?: NodeTracerProvider | TracerProviderWithEnvExporters;
private _meterProvider?: MeterProvider;
private _serviceName?: string;
private _useEnvExporters = false;

/**
* Create a new NodeJS SDK instance
Expand Down Expand Up @@ -99,6 +98,8 @@ export class NodeSDK {
configuration.contextManager,
configuration.textMapPropagator
);
} else {
this._useEnvExporters = true;
}

if (configuration.metricReader || configuration.views) {
Expand Down Expand Up @@ -196,19 +197,29 @@ export class NodeSDK {
{ [SemanticResourceAttributes.SERVICE_NAME]: this._serviceName }
));

if (this._tracerProviderConfig) {
const tracerProvider = new NodeTracerProvider({
...this._tracerProviderConfig.tracerConfig,
if (this._tracerProviderConfig || this._useEnvExporters) {
pichlermarc marked this conversation as resolved.
Show resolved Hide resolved
const Provider =
this._tracerProviderConfig ? NodeTracerProvider : TracerProviderWithEnvExporters;

const tracerProvider = new Provider ({
...this._tracerProviderConfig?.tracerConfig,
resource: this._resource,
});

this._tracerProvider = tracerProvider;

tracerProvider.addSpanProcessor(this._tracerProviderConfig.spanProcessor);
tracerProvider.register({
contextManager: this._tracerProviderConfig.contextManager,
propagator: this._tracerProviderConfig.textMapPropagator,
});
const processors = this.retrieveSpanProcessors(tracerProvider);

if (processors) {
processors.forEach((processor: SpanProcessor) => {
tracerProvider.addSpanProcessor(processor);
});

tracerProvider.register({
svetlanabrennan marked this conversation as resolved.
Show resolved Hide resolved
contextManager: this._tracerProviderConfig?.contextManager,
propagator: this._tracerProviderConfig?.textMapPropagator,
});
}
}

if (this._meterProviderConfig) {
Expand Down Expand Up @@ -247,4 +258,16 @@ export class NodeSDK {
})
);
}

private retrieveSpanProcessors(provider: NodeTracerProvider): SpanProcessor[] | undefined {
svetlanabrennan marked this conversation as resolved.
Show resolved Hide resolved
if (this._tracerProviderConfig) {
return [this._tracerProviderConfig.spanProcessor];
}

if (provider instanceof TracerProviderWithEnvExporters) {
return provider.spanProcessors;
}

return undefined;
}
}
Loading