Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions experimental/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2
### :bug: Bug Fixes

* fix(instrumentation-grpc): attach correct name to diag message [#6097](https://github.com/open-telemetry/opentelemetry-js/pull/6043) @pichlermarc
* fix(opentelemetry-sdk-node): default to otlp if OTEL_METRICS_EXPORTER is empty [#6092](https://github.com/open-telemetry/opentelemetry-js/pull/6092) @jeengbe

### :books: Documentation

Expand Down
2 changes: 1 addition & 1 deletion experimental/packages/opentelemetry-sdk-node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ This is an alternative to programmatically configuring an exporter or span proce
| 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`. |
| OTEL_EXPORTER_OTLP_LOGS_PROTOCOL | The transport protocol to use on OTLP log requests. Options include `grpc`, `http/protobuf`, and `http/json`. Default is `http/protobuf`. |
| OTEL_METRICS_EXPORTER | Metrics exporter to be used. options are `otlp`, `prometheus`, `console` or `none`. |
| OTEL_METRICS_EXPORTER | Metrics exporter to be used. options are `otlp`, `prometheus`, `console` or `none`. Default is `otlp`. |
| OTEL_METRIC_EXPORT_INTERVAL | The export interval when using a push Metric Reader. Default is `60000`. |
| OTEL_METRIC_EXPORT_TIMEOUT | The export timeout when using a push Metric Reader. Default is `30000`. |

Expand Down
31 changes: 16 additions & 15 deletions experimental/packages/opentelemetry-sdk-node/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,13 @@ function getValueInMillis(envName: string, defaultValue: number): number {
*/
function configureMetricProviderFromEnv(): IMetricReader[] {
const metricReaders: IMetricReader[] = [];
const enabledExporters = getStringListFromEnv('OTEL_METRICS_EXPORTER');
if (!enabledExporters) {
return metricReaders;
}
const enabledExporters = Array.from(
new Set(getStringListFromEnv('OTEL_METRICS_EXPORTER') ?? [])
);

if (enabledExporters.length === 0) {
diag.debug('OTEL_METRICS_EXPORTER is empty. Using default otlp exporter.');
enabledExporters.push('otlp');
}

if (enabledExporters.includes('none')) {
Expand All @@ -132,8 +132,10 @@ function configureMetricProviderFromEnv(): IMetricReader[] {
enabledExporters.forEach(exporter => {
if (exporter === 'otlp') {
const protocol =
process.env.OTEL_EXPORTER_OTLP_METRICS_PROTOCOL?.trim() ||
process.env.OTEL_EXPORTER_OTLP_PROTOCOL?.trim();
(
getStringFromEnv('OTEL_EXPORTER_OTLP_METRICS_PROTOCOL') ??
getStringFromEnv('OTEL_EXPORTER_OTLP_PROTOCOL')
)?.trim() || 'http/protobuf'; // Using || to also fall back on empty string

const exportIntervalMillis = getValueInMillis(
'OTEL_METRIC_EXPORT_INTERVAL',
Expand Down Expand Up @@ -461,7 +463,9 @@ export class NodeSDK {
}

private configureLoggerProviderFromEnv(): void {
const enabledExporters = getStringListFromEnv('OTEL_LOGS_EXPORTER') ?? [];
const enabledExporters = Array.from(
new Set(getStringListFromEnv('OTEL_LOGS_EXPORTER') ?? [])
);

if (enabledExporters.length === 0) {
diag.debug('OTEL_LOGS_EXPORTER is empty. Using default otlp exporter.');
Expand All @@ -479,10 +483,11 @@ export class NodeSDK {

enabledExporters.forEach(exporter => {
if (exporter === 'otlp') {
const protocol = (
getStringFromEnv('OTEL_EXPORTER_OTLP_LOGS_PROTOCOL') ??
getStringFromEnv('OTEL_EXPORTER_OTLP_PROTOCOL')
)?.trim();
const protocol =
(
getStringFromEnv('OTEL_EXPORTER_OTLP_LOGS_PROTOCOL') ??
getStringFromEnv('OTEL_EXPORTER_OTLP_PROTOCOL')
)?.trim() || 'http/protobuf'; // Using || to also fall back on empty string

switch (protocol) {
case 'grpc':
Expand All @@ -494,10 +499,6 @@ export class NodeSDK {
case 'http/protobuf':
exporters.push(new OTLPProtoLogExporter());
break;
case undefined:
case '':
exporters.push(new OTLPProtoLogExporter());
break;
default:
diag.warn(
`Unsupported OTLP logs protocol: "${protocol}". Using http/protobuf.`
Expand Down
77 changes: 60 additions & 17 deletions experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,10 @@ describe('Node SDK', () => {
});

it('should not register more than the minimal SDK components', async () => {
// need to set these to none, since the deafult value is 'otlp'
// need to set these to none, since the default value is 'otlp'
process.env.OTEL_TRACES_EXPORTER = 'none';
process.env.OTEL_LOGS_EXPORTER = 'none';
process.env.OTEL_METRIC_EXPORTER = 'none';
process.env.OTEL_METRICS_EXPORTER = 'none';
const sdk = new NodeSDK({
autoDetectResources: false,
});
Expand All @@ -156,6 +156,7 @@ describe('Node SDK', () => {
logsDelegate,
'logger provider should not have changed'
);

await sdk.shutdown();
});

Expand Down Expand Up @@ -200,8 +201,6 @@ describe('Node SDK', () => {

sdk.start();

assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider));

assertDefaultContextManagerRegistered();
assertDefaultPropagatorRegistered();

Expand All @@ -219,8 +218,6 @@ describe('Node SDK', () => {

sdk.start();

assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider));

assertDefaultContextManagerRegistered();
assertDefaultPropagatorRegistered();

Expand All @@ -244,8 +241,6 @@ describe('Node SDK', () => {

sdk.start();

assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider));

assertDefaultContextManagerRegistered();
assertDefaultPropagatorRegistered();

Expand Down Expand Up @@ -1245,13 +1240,6 @@ describe('Node SDK', () => {
delete process.env.OTEL_EXPORTER_METRICS_PROTOCOL;
});

it('should not register the provider if OTEL_METRICS_EXPORTER is not set', async () => {
const sdk = new NodeSDK();
sdk.start();
assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider));
await sdk.shutdown();
});

it('should not register the provider if OTEL_METRICS_EXPORTER contains none', async () => {
process.env.OTEL_METRICS_EXPORTER = 'console,none';
const sdk = new NodeSDK();
Expand Down Expand Up @@ -1441,7 +1429,7 @@ describe('Node SDK', () => {
await sdk.shutdown();
});

it('should use prometheus if that is set ', async () => {
it('should use prometheus if that is set', async () => {
process.env.OTEL_METRICS_EXPORTER = 'prometheus';
delete process.env.OTEL_EXPORTER_OTLP_METRICS_PROTOCOL;
const sdk = new NodeSDK();
Expand All @@ -1454,9 +1442,44 @@ describe('Node SDK', () => {
);
await sdk.shutdown();
});

it('should use default grpc otlp exporter when empty value is provided for exporter via env', async () => {
process.env.OTEL_METRICS_EXPORTER = '';
const sdk = new NodeSDK();
sdk.start();

const meterProvider = metrics.getMeterProvider();
const sharedState = (meterProvider as any)['_sharedState'];
assert.ok(
sharedState.metricCollectors[0]._metricReader._exporter instanceof
OTLPProtoMetricExporter
);
await sdk.shutdown();
});

it('should not register the same exporter twice', async () => {
process.env.OTEL_METRICS_EXPORTER = 'console,otlp,console';
const sdk = new NodeSDK();
sdk.start();

const meterProvider = metrics.getMeterProvider();
const sharedState = (meterProvider as any)['_sharedState'];

assert.ok(sharedState.metricCollectors.length === 2);
assert.ok(
sharedState.metricCollectors[0]._metricReader._exporter instanceof
ConsoleMetricExporter
);
assert.ok(
sharedState.metricCollectors[1]._metricReader._exporter instanceof
OTLPProtoMetricExporter
);

await sdk.shutdown();
});
});

describe('setup exporter from env', () => {
describe('setup trace exporter from env', () => {
let stubLoggerError: Sinon.SinonStub;

const getSdkSpanProcessors = (sdk: NodeSDK) => {
Expand All @@ -1474,6 +1497,7 @@ describe('Node SDK', () => {
beforeEach(() => {
stubLoggerError = Sinon.stub(diag, 'warn');
});

afterEach(() => {
delete process.env.OTEL_EXPORTER_OTLP_PROTOCOL;
delete process.env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL;
Expand Down Expand Up @@ -1751,5 +1775,24 @@ describe('Node SDK', () => {
);
await sdk.shutdown();
});

it('should not register the same exporter twice', async () => {
process.env.OTEL_TRACES_EXPORTER = 'console,otlp,console';
const sdk = new NodeSDK();
sdk.start();

const listOfProcessors = getSdkSpanProcessors(sdk);

assert.ok(listOfProcessors.length === 2);
assert.ok(listOfProcessors[0] instanceof SimpleSpanProcessor);
assert.ok(
listOfProcessors[0]['_exporter'] instanceof ConsoleSpanExporter
);
assert.ok(listOfProcessors[1] instanceof BatchSpanProcessor);
assert.ok(
listOfProcessors[1]['_exporter'] instanceof OTLPProtoTraceExporter
);
await sdk.shutdown();
});
});
});