Skip to content

Commit 126ae93

Browse files
fix(sdk-node): fix exporter to be read only OTEL_TRACES_EXPORTER is set to a valid exporter (#3492)
* fix(sdk-node): refactor to use otlp as default exporter when env is empty Signed-off-by: Svetlana Brennan <[email protected]> * fix(sdk-node): add changelog Signed-off-by: Svetlana Brennan <[email protected]> * (sdk-node): using existing env source Signed-off-by: Svetlana Brennan <[email protected]> Signed-off-by: Svetlana Brennan <[email protected]>
1 parent c93ab9e commit 126ae93

File tree

7 files changed

+92
-26
lines changed

7 files changed

+92
-26
lines changed

experimental/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ All notable changes to experimental packages in this project will be documented
2323
* fix(prometheus-sanitization): replace repeated `_` with a single `_` [3470](https://github.com/open-telemetry/opentelemetry-js/pull/3470) @samimusallam
2424
* fix(prometheus-serializer): correct string used for NaN [#3477](https://github.com/open-telemetry/opentelemetry-js/pull/3477) @JacksonWeber
2525
* fix(instrumentation-http): close server span when response finishes [#3407](https://github.com/open-telemetry/opentelemetry-js/pull/3407) @legendecas
26+
* fix(sdk-node): fix exporter to be read only OTEL_TRACES_EXPORTER is set to a valid exporter [3492] @svetlanabrennan
2627

2728
### :books: (Refine Doc)
2829

experimental/packages/opentelemetry-sdk-node/src/TracerProviderWithEnvExporter.ts

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,22 @@ export class TracerProviderWithEnvExporters extends NodeTracerProvider {
8484
Array.from(new Set(getEnv().OTEL_TRACES_EXPORTER.split(',')))
8585
);
8686

87-
if (traceExportersList.length === 0 || traceExportersList[0] === 'none') {
87+
if (traceExportersList[0] === 'none') {
8888
diag.warn(
89-
'OTEL_TRACES_EXPORTER contains "none" or is empty. SDK will not be initialized.'
89+
'OTEL_TRACES_EXPORTER contains "none". SDK will not be initialized.'
9090
);
91+
} else if (traceExportersList.length === 0) {
92+
diag.warn('OTEL_TRACES_EXPORTER is empty. Using default otlp exporter.');
93+
94+
traceExportersList = ['otlp'];
95+
this.createExportersFromList(traceExportersList);
96+
97+
this._spanProcessors = this.configureSpanProcessors(
98+
this._configuredExporters
99+
);
100+
this._spanProcessors.forEach(processor => {
101+
this.addSpanProcessor(processor);
102+
});
91103
} else {
92104
if (
93105
traceExportersList.length > 1 &&
@@ -99,16 +111,7 @@ export class TracerProviderWithEnvExporters extends NodeTracerProvider {
99111
traceExportersList = ['otlp'];
100112
}
101113

102-
traceExportersList.forEach(exporterName => {
103-
const exporter = this._getSpanExporter(exporterName);
104-
if (exporter) {
105-
this._configuredExporters.push(exporter);
106-
} else {
107-
diag.warn(
108-
`Unrecognized OTEL_TRACES_EXPORTER value: ${exporterName}.`
109-
);
110-
}
111-
});
114+
this.createExportersFromList(traceExportersList);
112115

113116
if (this._configuredExporters.length > 0) {
114117
this._spanProcessors = this.configureSpanProcessors(
@@ -136,6 +139,17 @@ export class TracerProviderWithEnvExporters extends NodeTracerProvider {
136139
}
137140
}
138141

142+
private createExportersFromList(exporterList: string[]) {
143+
exporterList.forEach(exporterName => {
144+
const exporter = this._getSpanExporter(exporterName);
145+
if (exporter) {
146+
this._configuredExporters.push(exporter);
147+
} else {
148+
diag.warn(`Unrecognized OTEL_TRACES_EXPORTER value: ${exporterName}.`);
149+
}
150+
});
151+
}
152+
139153
private configureSpanProcessors(
140154
exporters: SpanExporter[]
141155
): (BatchSpanProcessor | SimpleSpanProcessor)[] {

experimental/packages/opentelemetry-sdk-node/test/TracerProviderWithEnvExporter.test.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,29 @@ describe('set up trace exporter with env exporters', () => {
9696
delete env.OTEL_EXPORTER_OTLP_PROTOCOL;
9797
delete env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL;
9898
});
99-
it('do not use any exporters when empty value is provided for exporter', async () => {
99+
it('use default otlp exporter when user does not set exporter via env or config', async () => {
100+
const sdk = new TracerProviderWithEnvExporters();
101+
const listOfProcessors = sdk['_spanProcessors']!;
102+
const listOfExporters = sdk['_configuredExporters'];
103+
104+
assert(listOfExporters[0] instanceof OTLPProtoTraceExporter);
105+
assert(listOfExporters.length === 1);
106+
107+
assert(listOfProcessors.length === 1);
108+
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
109+
});
110+
it('use default otlp exporter when empty value is provided for exporter via env', async () => {
100111
env.OTEL_TRACES_EXPORTER = '';
101112
const sdk = new TracerProviderWithEnvExporters();
102-
const listOfProcessors = sdk['_spanProcessors'];
113+
const listOfProcessors = sdk['_spanProcessors']!;
103114
const listOfExporters = sdk['_configuredExporters'];
104115

105-
assert(spyGetOtlpProtocol.notCalled);
106-
assert(listOfExporters.length === 0);
107-
assert(listOfProcessors === undefined);
116+
assert(listOfExporters[0] instanceof OTLPProtoTraceExporter);
117+
assert(listOfExporters.length === 1);
118+
119+
assert(listOfProcessors.length === 1);
120+
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
121+
108122
env.OTEL_TRACES_EXPORTER = '';
109123
});
110124
it('do not use any exporters when none value is only provided', async () => {
@@ -124,7 +138,7 @@ describe('set up trace exporter with env exporters', () => {
124138

125139
assert.strictEqual(
126140
stubLoggerError.args[0][0],
127-
'OTEL_TRACES_EXPORTER contains "none" or is empty. SDK will not be initialized.'
141+
'OTEL_TRACES_EXPORTER contains "none". SDK will not be initialized.'
128142
);
129143
delete env.OTEL_TRACES_EXPORTER;
130144
});
@@ -174,6 +188,11 @@ describe('set up trace exporter with env exporters', () => {
174188

175189
assert.strictEqual(
176190
stubLoggerError.args[0][0],
191+
'OTEL_TRACES_EXPORTER is empty. Using default otlp exporter.'
192+
);
193+
194+
assert.strictEqual(
195+
stubLoggerError.args[1][0],
177196
'Unsupported OTLP traces protocol: invalid. Using http/protobuf.'
178197
);
179198
delete env.OTEL_EXPORTER_OTLP_PROTOCOL;

experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -769,21 +769,30 @@ describe('setup exporter from env', () => {
769769

770770
assert.strictEqual(
771771
stubLoggerError.args[0][0],
772-
'OTEL_TRACES_EXPORTER contains "none" or is empty. SDK will not be initialized.'
772+
'OTEL_TRACES_EXPORTER contains "none". SDK will not be initialized.'
773773
);
774774
delete env.OTEL_TRACES_EXPORTER;
775775
});
776-
it('do not use any exporters when empty value is provided for exporter', async () => {
777-
env.OTEL_TRACES_EXPORTER = '';
776+
it('use default otlp exporter when user does not set exporter via env or config', async () => {
778777
const sdk = new NodeSDK();
779778
await sdk.start();
780779

781780
const listOfProcessors =
782781
sdk['_tracerProvider']!['_registeredSpanProcessors']!;
783-
const activeProcessor = sdk['_tracerProvider']?.getActiveSpanProcessor();
782+
assert(sdk['_tracerProvider'] instanceof TracerProviderWithEnvExporters);
783+
assert(listOfProcessors.length === 1);
784+
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
785+
});
786+
it('use default otlp exporter when empty value is provided for exporter via env', async () => {
787+
env.OTEL_TRACES_EXPORTER = '';
788+
const sdk = new NodeSDK();
789+
await sdk.start();
784790

785-
assert(listOfProcessors.length === 0);
786-
assert(activeProcessor instanceof NoopSpanProcessor);
791+
const listOfProcessors =
792+
sdk['_tracerProvider']!['_registeredSpanProcessors']!;
793+
assert(sdk['_tracerProvider'] instanceof TracerProviderWithEnvExporters);
794+
assert(listOfProcessors.length === 1);
795+
assert(listOfProcessors[0] instanceof BatchSpanProcessor);
787796
env.OTEL_TRACES_EXPORTER = '';
788797
});
789798

packages/opentelemetry-core/src/utils/environment.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ export const DEFAULT_ENVIRONMENT: Required<ENVIRONMENT> = {
172172
OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT: DEFAULT_ATTRIBUTE_COUNT_LIMIT,
173173
OTEL_SPAN_EVENT_COUNT_LIMIT: 128,
174174
OTEL_SPAN_LINK_COUNT_LIMIT: 128,
175-
OTEL_TRACES_EXPORTER: 'otlp',
175+
OTEL_TRACES_EXPORTER: '',
176176
OTEL_TRACES_SAMPLER: TracesSamplerValues.ParentBasedAlwaysOn,
177177
OTEL_TRACES_SAMPLER_ARG: '',
178178
OTEL_EXPORTER_OTLP_INSECURE: '',

packages/opentelemetry-sdk-trace-base/src/BasicTracerProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ export class BasicTracerProvider implements TracerProvider {
275275

276276
protected _buildExporterFromEnv(): SpanExporter | undefined {
277277
const exporterName = getEnv().OTEL_TRACES_EXPORTER;
278-
if (exporterName === 'none') return;
278+
if (exporterName === 'none' || exporterName === '') return;
279279
const exporter = this._getSpanExporter(exporterName);
280280
if (!exporter) {
281281
diag.error(

packages/opentelemetry-sdk-trace-base/test/common/BasicTracerProvider.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,29 @@ describe('BasicTracerProvider', () => {
9090
const tracer = new BasicTracerProvider();
9191
assert.ok(tracer.activeSpanProcessor instanceof NoopSpanProcessor);
9292
});
93+
it('should use noop span processor by default and no diag error', () => {
94+
const errorStub = sinon.spy(diag, 'error');
95+
const tracer = new BasicTracerProvider();
96+
assert.ok(tracer.activeSpanProcessor instanceof NoopSpanProcessor);
97+
98+
sinon.assert.notCalled(errorStub);
99+
});
100+
});
101+
102+
describe('when user sets unavailable exporter', () => {
103+
it('should use noop span processor by default and show diag error', () => {
104+
const errorStub = sinon.spy(diag, 'error');
105+
envSource.OTEL_TRACES_EXPORTER = 'someExporter';
106+
107+
const tracer = new BasicTracerProvider();
108+
assert.ok(tracer.activeSpanProcessor instanceof NoopSpanProcessor);
109+
110+
sinon.assert.calledWith(
111+
errorStub,
112+
'Exporter "someExporter" requested through environment variable is unavailable.'
113+
);
114+
delete envSource.OTEL_TRACES_EXPORTER;
115+
});
93116
});
94117

95118
describe('when "sampler" option defined', () => {

0 commit comments

Comments
 (0)