Skip to content

Commit bc60b8d

Browse files
authored
feat(configuration): set tracer provider exporter type from env variable (#6106)
1 parent cc651d7 commit bc60b8d

File tree

3 files changed

+304
-46
lines changed

3 files changed

+304
-46
lines changed

experimental/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2
1414
* refactor(configuration): improvements on package [#6101](https://github.com/open-telemetry/opentelemetry-js/pull/6101) @maryliag
1515
* feat(configuration): set logger provider exporter type from env variable [#6104](https://github.com/open-telemetry/opentelemetry-js/pull/6104) @maryliag
1616
* feat(configuration): set meter provider exporter type from env variable [#6105](https://github.com/open-telemetry/opentelemetry-js/pull/6105) @maryliag
17+
* feat(configuration): set tracer provider exporter type from env variables [#6106](https://github.com/open-telemetry/opentelemetry-js/pull/6106) @maryliag
18+
* feat(configuration): set meter provider exporter type from env variable [#6105](https://github.com/open-telemetry/opentelemetry-js/pull/6105) @maryliag
1719

1820
### :bug: Bug Fixes
1921

experimental/packages/configuration/src/EnvironmentConfigFactory.ts

Lines changed: 116 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -212,58 +212,128 @@ export function setTracerProvider(config: ConfigurationModel): void {
212212
batch.max_export_batch_size = maxExportBatchSize;
213213
}
214214

215-
const endpoint =
216-
getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT') ??
217-
(getStringFromEnv('OTEL_EXPORTER_OTLP_ENDPOINT')
218-
? `${getStringFromEnv('OTEL_EXPORTER_OTLP_ENDPOINT')}/v1/traces`
219-
: null);
220-
if (endpoint && batch.exporter.otlp_http) {
221-
batch.exporter.otlp_http.endpoint = endpoint;
222-
}
223-
224-
const certificateFile =
225-
getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE') ??
226-
getStringFromEnv('OTEL_EXPORTER_OTLP_CERTIFICATE');
227-
if (certificateFile && batch.exporter.otlp_http) {
228-
batch.exporter.otlp_http.certificate_file = certificateFile;
229-
}
230-
231-
const clientKeyFile =
232-
getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_CLIENT_KEY') ??
233-
getStringFromEnv('OTEL_EXPORTER_OTLP_CLIENT_KEY');
234-
if (clientKeyFile && batch.exporter.otlp_http) {
235-
batch.exporter.otlp_http.client_key_file = clientKeyFile;
236-
}
237-
238-
const clientCertificateFile =
239-
getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_CLIENT_CERTIFICATE') ??
240-
getStringFromEnv('OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE');
241-
if (clientCertificateFile && batch.exporter.otlp_http) {
242-
batch.exporter.otlp_http.client_certificate_file = clientCertificateFile;
215+
const exportersType = Array.from(
216+
new Set(getStringListFromEnv('OTEL_TRACES_EXPORTER'))
217+
);
218+
if (exportersType.length === 0) {
219+
exportersType.push('otlp');
243220
}
244221

245-
const compression =
246-
getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_COMPRESSION') ??
247-
getStringFromEnv('OTEL_EXPORTER_OTLP_COMPRESSION');
248-
if (compression && batch.exporter.otlp_http) {
249-
batch.exporter.otlp_http.compression = compression;
222+
config.tracer_provider.processors = [];
223+
if (exportersType.includes('none')) {
224+
diag.info(
225+
`OTEL_TRACES_EXPORTER contains "none". Tracer provider will not be initialized.`
226+
);
227+
return;
250228
}
229+
for (let i = 0; i < exportersType.length; i++) {
230+
const exporterType = exportersType[i];
231+
const batchInfo = { ...batch };
232+
if (exporterType === 'console') {
233+
config.tracer_provider.processors.push({
234+
simple: { exporter: { console: {} } },
235+
});
236+
} else if (exporterType === 'zipkin') {
237+
batchInfo.exporter = {
238+
zipkin: {
239+
endpoint:
240+
getStringFromEnv('OTEL_EXPORTER_ZIPKIN_ENDPOINT') ??
241+
'http://localhost:9411/api/v2/spans',
242+
timeout: getNumberFromEnv('OTEL_EXPORTER_ZIPKIN_TIMEOUT') ?? 10000,
243+
},
244+
};
245+
config.tracer_provider.processors.push({ batch: batchInfo });
246+
} else {
247+
// 'otlp' and default
248+
const protocol =
249+
getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_PROTOCOL') ??
250+
getStringFromEnv('OTEL_EXPORTER_OTLP_PROTOCOL') ??
251+
'http/protobuf';
252+
const certificateFile =
253+
getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE') ??
254+
getStringFromEnv('OTEL_EXPORTER_OTLP_CERTIFICATE');
255+
const clientKeyFile =
256+
getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_CLIENT_KEY') ??
257+
getStringFromEnv('OTEL_EXPORTER_OTLP_CLIENT_KEY');
258+
const clientCertificateFile =
259+
getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_CLIENT_CERTIFICATE') ??
260+
getStringFromEnv('OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE');
261+
const compression =
262+
getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_COMPRESSION') ??
263+
getStringFromEnv('OTEL_EXPORTER_OTLP_COMPRESSION');
264+
const timeout =
265+
getNumberFromEnv('OTEL_EXPORTER_OTLP_TRACES_TIMEOUT') ??
266+
getNumberFromEnv('OTEL_EXPORTER_OTLP_TIMEOUT') ??
267+
10000;
268+
const headersList =
269+
getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_HEADERS') ??
270+
getStringFromEnv('OTEL_EXPORTER_OTLP_HEADERS');
251271

252-
const timeout =
253-
getNumberFromEnv('OTEL_EXPORTER_OTLP_TRACES_TIMEOUT') ??
254-
getNumberFromEnv('OTEL_EXPORTER_OTLP_TIMEOUT');
255-
if (timeout && batch.exporter.otlp_http) {
256-
batch.exporter.otlp_http.timeout = timeout;
257-
}
272+
if (protocol === 'grpc') {
273+
delete batchInfo.exporter.otlp_http;
274+
batchInfo.exporter.otlp_grpc = {};
275+
const endpoint =
276+
getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT') ??
277+
getStringFromEnv('OTEL_EXPORTER_OTLP_ENDPOINT') ??
278+
'http://localhost:4317';
279+
if (endpoint) {
280+
batchInfo.exporter.otlp_grpc.endpoint = endpoint;
281+
}
282+
if (certificateFile) {
283+
batchInfo.exporter.otlp_grpc.certificate_file = certificateFile;
284+
}
285+
if (clientKeyFile) {
286+
batchInfo.exporter.otlp_grpc.client_key_file = clientKeyFile;
287+
}
288+
if (clientCertificateFile) {
289+
batchInfo.exporter.otlp_grpc.client_certificate_file =
290+
clientCertificateFile;
291+
}
292+
if (compression) {
293+
batchInfo.exporter.otlp_grpc.compression = compression;
294+
}
295+
if (timeout) {
296+
batchInfo.exporter.otlp_grpc.timeout = timeout;
297+
}
298+
if (headersList) {
299+
batchInfo.exporter.otlp_grpc.headers_list = headersList;
300+
}
301+
} else {
302+
if (batchInfo.exporter.otlp_http == null) {
303+
batchInfo.exporter.otlp_http = {};
304+
}
305+
const endpoint =
306+
getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT') ??
307+
(getStringFromEnv('OTEL_EXPORTER_OTLP_ENDPOINT')
308+
? `${getStringFromEnv('OTEL_EXPORTER_OTLP_ENDPOINT')}/v1/traces`
309+
: null);
310+
if (endpoint) {
311+
batchInfo.exporter.otlp_http.endpoint = endpoint;
312+
}
313+
if (certificateFile) {
314+
batchInfo.exporter.otlp_http.certificate_file = certificateFile;
315+
}
316+
if (clientKeyFile) {
317+
batchInfo.exporter.otlp_http.client_key_file = clientKeyFile;
318+
}
319+
if (clientCertificateFile) {
320+
batchInfo.exporter.otlp_http.client_certificate_file =
321+
clientCertificateFile;
322+
}
323+
if (compression) {
324+
batchInfo.exporter.otlp_http.compression = compression;
325+
}
326+
if (timeout) {
327+
batchInfo.exporter.otlp_http.timeout = timeout;
328+
}
329+
if (headersList) {
330+
batchInfo.exporter.otlp_http.headers_list = headersList;
331+
}
332+
}
258333

259-
const headersList =
260-
getStringFromEnv('OTEL_EXPORTER_OTLP_TRACES_HEADERS') ??
261-
getStringFromEnv('OTEL_EXPORTER_OTLP_HEADERS');
262-
if (headersList && batch.exporter.otlp_http) {
263-
batch.exporter.otlp_http.headers_list = headersList;
334+
config.tracer_provider.processors.push({ batch: batchInfo });
335+
}
264336
}
265-
266-
config.tracer_provider.processors[0].batch = batch;
267337
}
268338
}
269339

experimental/packages/configuration/test/ConfigFactory.test.ts

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,192 @@ describe('ConfigFactory', function () {
930930
assert.deepStrictEqual(configFactory.getConfigModel(), expectedConfig);
931931
});
932932

933+
it('should return config with tracer_provider with console exporter', function () {
934+
process.env.OTEL_TRACES_EXPORTER = 'console';
935+
const expectedConfig: ConfigurationModel = {
936+
...defaultConfig,
937+
tracer_provider: {
938+
...defaultConfig.tracer_provider,
939+
processors: [
940+
{
941+
simple: {
942+
exporter: {
943+
console: {},
944+
},
945+
},
946+
},
947+
],
948+
},
949+
};
950+
const configProvider = createConfigFactory();
951+
assert.deepStrictEqual(configProvider.getConfigModel(), expectedConfig);
952+
});
953+
954+
it('should return config with tracer_provider with default zipkin exporter', function () {
955+
process.env.OTEL_TRACES_EXPORTER = 'zipkin';
956+
const expectedConfig: ConfigurationModel = {
957+
...defaultConfig,
958+
tracer_provider: {
959+
...defaultConfig.tracer_provider,
960+
processors: [
961+
{
962+
batch: {
963+
schedule_delay: 5000,
964+
export_timeout: 30000,
965+
max_queue_size: 2048,
966+
max_export_batch_size: 512,
967+
exporter: {
968+
zipkin: {
969+
endpoint: 'http://localhost:9411/api/v2/spans',
970+
timeout: 10000,
971+
},
972+
},
973+
},
974+
},
975+
],
976+
},
977+
};
978+
const configProvider = createConfigFactory();
979+
assert.deepStrictEqual(configProvider.getConfigModel(), expectedConfig);
980+
});
981+
982+
it('should return config with tracer_provider with default zipkin exporter', function () {
983+
process.env.OTEL_TRACES_EXPORTER = 'zipkin';
984+
process.env.OTEL_EXPORTER_ZIPKIN_ENDPOINT =
985+
'http://custom:9411/api/v2/spans';
986+
process.env.OTEL_EXPORTER_ZIPKIN_TIMEOUT = '15000';
987+
const expectedConfig: ConfigurationModel = {
988+
...defaultConfig,
989+
tracer_provider: {
990+
...defaultConfig.tracer_provider,
991+
processors: [
992+
{
993+
batch: {
994+
schedule_delay: 5000,
995+
export_timeout: 30000,
996+
max_queue_size: 2048,
997+
max_export_batch_size: 512,
998+
exporter: {
999+
zipkin: {
1000+
endpoint: 'http://custom:9411/api/v2/spans',
1001+
timeout: 15000,
1002+
},
1003+
},
1004+
},
1005+
},
1006+
],
1007+
},
1008+
};
1009+
const configProvider = createConfigFactory();
1010+
assert.deepStrictEqual(configProvider.getConfigModel(), expectedConfig);
1011+
});
1012+
1013+
it('should return config with tracer_provider with exporter list', function () {
1014+
process.env.OTEL_TRACES_EXPORTER = 'otlp,console,zipkin';
1015+
process.env.OTEL_EXPORTER_ZIPKIN_ENDPOINT =
1016+
'http://custom:9411/api/v2/spans';
1017+
process.env.OTEL_EXPORTER_ZIPKIN_TIMEOUT = '15000';
1018+
const expectedConfig: ConfigurationModel = {
1019+
...defaultConfig,
1020+
tracer_provider: {
1021+
...defaultConfig.tracer_provider,
1022+
processors: [
1023+
{
1024+
batch: {
1025+
schedule_delay: 5000,
1026+
export_timeout: 30000,
1027+
max_queue_size: 2048,
1028+
max_export_batch_size: 512,
1029+
exporter: {
1030+
otlp_http: {
1031+
endpoint: 'http://localhost:4318/v1/traces',
1032+
timeout: 10000,
1033+
encoding: OtlpHttpEncoding.Protobuf,
1034+
},
1035+
},
1036+
},
1037+
},
1038+
{
1039+
simple: {
1040+
exporter: {
1041+
console: {},
1042+
},
1043+
},
1044+
},
1045+
{
1046+
batch: {
1047+
schedule_delay: 5000,
1048+
export_timeout: 30000,
1049+
max_queue_size: 2048,
1050+
max_export_batch_size: 512,
1051+
exporter: {
1052+
zipkin: {
1053+
endpoint: 'http://custom:9411/api/v2/spans',
1054+
timeout: 15000,
1055+
},
1056+
},
1057+
},
1058+
},
1059+
],
1060+
},
1061+
};
1062+
const configProvider = createConfigFactory();
1063+
assert.deepStrictEqual(configProvider.getConfigModel(), expectedConfig);
1064+
});
1065+
1066+
it('should return config with tracer_provider with no exporter', function () {
1067+
process.env.OTEL_TRACES_EXPORTER = 'none,console';
1068+
const expectedConfig: ConfigurationModel = {
1069+
...defaultConfig,
1070+
tracer_provider: {
1071+
...defaultConfig.tracer_provider,
1072+
processors: [],
1073+
},
1074+
};
1075+
const configProvider = createConfigFactory();
1076+
assert.deepStrictEqual(configProvider.getConfigModel(), expectedConfig);
1077+
});
1078+
1079+
it('should return config with tracer_provider with otlp grpc exporter', function () {
1080+
process.env.OTEL_TRACES_EXPORTER = 'otlp';
1081+
process.env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL = 'grpc';
1082+
process.env.OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE = 'traces-cert.pem';
1083+
process.env.OTEL_EXPORTER_OTLP_TRACES_CLIENT_KEY = 'traces-key.pem';
1084+
process.env.OTEL_EXPORTER_OTLP_TRACES_CLIENT_CERTIFICATE =
1085+
'traces-client-cert.pem';
1086+
process.env.OTEL_EXPORTER_OTLP_TRACES_COMPRESSION = 'gzip';
1087+
process.env.OTEL_EXPORTER_OTLP_TRACES_HEADERS = 'host=localhost';
1088+
const expectedConfig: ConfigurationModel = {
1089+
...defaultConfig,
1090+
tracer_provider: {
1091+
...defaultConfig.tracer_provider,
1092+
processors: [
1093+
{
1094+
batch: {
1095+
schedule_delay: 5000,
1096+
export_timeout: 30000,
1097+
max_queue_size: 2048,
1098+
max_export_batch_size: 512,
1099+
exporter: {
1100+
otlp_grpc: {
1101+
endpoint: 'http://localhost:4317',
1102+
timeout: 10000,
1103+
certificate_file: 'traces-cert.pem',
1104+
client_key_file: 'traces-key.pem',
1105+
client_certificate_file: 'traces-client-cert.pem',
1106+
compression: 'gzip',
1107+
headers_list: 'host=localhost',
1108+
},
1109+
},
1110+
},
1111+
},
1112+
],
1113+
},
1114+
};
1115+
const configProvider = createConfigFactory();
1116+
assert.deepStrictEqual(configProvider.getConfigModel(), expectedConfig);
1117+
});
1118+
9331119
it('should return config with custom meter_provider', function () {
9341120
process.env.OTEL_METRIC_EXPORT_INTERVAL = '100';
9351121
process.env.OTEL_METRIC_EXPORT_TIMEOUT = '200';

0 commit comments

Comments
 (0)