Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Tests
  • Loading branch information
mhennoch committed May 28, 2024
commit b68b9d8fc95604921e8424815dc5ffcdcfcae52a
48 changes: 31 additions & 17 deletions experimental/packages/opentelemetry-sdk-node/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import {
ConsoleLogRecordExporter,
LogRecordExporter,
} from '@opentelemetry/sdk-logs';
import { OTLPLogExporter as OTLPHttpLogExporter} from '@opentelemetry/exporter-logs-otlp-http';
import { OTLPLogExporter as OTLPHttpLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
import { OTLPLogExporter as OTLPGrpcLogExporter } from '@opentelemetry/exporter-logs-otlp-grpc';
import { OTLPLogExporter as OTLPProtoLogExporter } from '@opentelemetry/exporter-logs-otlp-proto';
import { MeterProvider, MetricReader, View } from '@opentelemetry/sdk-metrics';
Expand All @@ -59,7 +59,11 @@ import {
import { SEMRESATTRS_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
import { NodeSDKConfiguration } from './types';
import { TracerProviderWithEnvExporters } from './TracerProviderWithEnvExporter';
import { ENVIRONMENT, getEnv, getEnvWithoutDefaults } from '@opentelemetry/core';
import {
ENVIRONMENT,
getEnv,
getEnvWithoutDefaults,
} from '@opentelemetry/core';
import {
getResourceDetectorsFromEnv,
parseInstrumentationOptions,
Expand Down Expand Up @@ -189,7 +193,9 @@ export class NodeSDK {

if (configuration.logRecordProcessor || configuration.logRecordProcessors) {
this._loggerProviderConfig = {
logRecordProcessors: configuration.logRecordProcessors ? configuration.logRecordProcessors : [configuration.logRecordProcessor!]
logRecordProcessors: configuration.logRecordProcessors
? configuration.logRecordProcessors
: [configuration.logRecordProcessor!],
};
} else {
this.configureLoggerProviderFromEnv(envWithoutDefaults);
Expand Down Expand Up @@ -275,7 +281,8 @@ export class NodeSDK {
resource: this._resource,
});

for (const logRecordProcessor of this._loggerProviderConfig.logRecordProcessors) {
for (const logRecordProcessor of this._loggerProviderConfig
.logRecordProcessors) {
loggerProvider.addLogRecordProcessor(logRecordProcessor);
}

Expand Down Expand Up @@ -329,23 +336,30 @@ export class NodeSDK {
);
}

private configureLoggerProviderFromEnv(envWithoutDefaults: ENVIRONMENT): void {
const logsExporter = envWithoutDefaults.OTEL_LOGS_EXPORTER;
if (logsExporter) {
private configureLoggerProviderFromEnv(
envWithoutDefaults: ENVIRONMENT
): void {
const logExportersList = envWithoutDefaults.OTEL_LOGS_EXPORTER;
if (logExportersList) {
const exporters: LogRecordExporter[] = [];
const enabledLogExporters = filterBlanksAndNulls(logsExporter.split(','));
const enabledExporters = filterBlanksAndNulls(
logExportersList.split(',')
);

if (enabledLogExporters.includes('none')) {
if (enabledExporters.includes('none')) {
diag.warn(
`Logs will not be exported.`
`OTEL_LOGS_EXPORTER contains "none". Logger provider will not be initialized.`
);
return;
}

enabledLogExporters.forEach((exporter) => {
enabledExporters.forEach(exporter => {
if (exporter === 'otlp') {
const protocol = envWithoutDefaults.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL ?? envWithoutDefaults.OTEL_EXPORTER_OTLP_PROTOCOL;
switch (protocol?.trim()) { //FIXME trim?
const protocol = (
envWithoutDefaults.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL ??
envWithoutDefaults.OTEL_EXPORTER_OTLP_PROTOCOL
)?.trim();
switch (protocol) {
case 'grpc':
exporters.push(new OTLPGrpcLogExporter());
break;
Expand All @@ -372,13 +386,13 @@ export class NodeSDK {

if (exporters.length > 0) {
this._loggerProviderConfig = {
logRecordProcessors: exporters.map((exporter) => new BatchLogRecordProcessor(exporter))
logRecordProcessors: exporters.map(
exporter => new BatchLogRecordProcessor(exporter)
),
};
}
} else {
diag.warn(
`No log exporter specified. Logs will not be exported.`
);
diag.warn(`No log exporters specified. Logs will not be exported.`);
}
}
}
114 changes: 101 additions & 13 deletions experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,16 @@ import {
serviceInstanceIdDetectorSync,
} from '@opentelemetry/resources';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { logs } from '@opentelemetry/api-logs';
import { logs, NoopLoggerProvider } from '@opentelemetry/api-logs';
import {
SimpleLogRecordProcessor,
InMemoryLogRecordExporter,
LoggerProvider,
ConsoleLogRecordExporter,
BatchLogRecordProcessor,
} from '@opentelemetry/sdk-logs';
import { OTLPLogExporter as OTLPProtoLogExporter } from '@opentelemetry/exporter-logs-otlp-proto';
import { OTLPLogExporter as OTLPHttpLogExporter} from '@opentelemetry/exporter-logs-otlp-http';
import { OTLPLogExporter as OTLPHttpLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
import { OTLPLogExporter as OTLPGrpcLogExporter } from '@opentelemetry/exporter-logs-otlp-grpc';
import {
SEMRESATTRS_HOST_NAME,
Expand Down Expand Up @@ -332,8 +333,41 @@ describe('Node SDK', () => {
});

it('should register a logger provider if multiple log record processors are provided', async () => {
//FIXME
assert.ok(false);
const logRecordExporter = new InMemoryLogRecordExporter();
const simpleLogRecordProcessor = new SimpleLogRecordProcessor(
logRecordExporter
);
const batchLogRecordProcessor = new BatchLogRecordProcessor(
logRecordExporter
);
const sdk = new NodeSDK({
logRecordProcessors: [
simpleLogRecordProcessor,
batchLogRecordProcessor,
],
});

sdk.start();

const loggerProvider = logs.getLoggerProvider();
const sharedState = (loggerProvider as any)['_sharedState'];
assert(sharedState.registeredLogRecordProcessors.length === 2);
assert(
sharedState.registeredLogRecordProcessors[0]._exporter instanceof
InMemoryLogRecordExporter
);
assert(
sharedState.registeredLogRecordProcessors[0] instanceof
SimpleLogRecordProcessor
);
assert(
sharedState.registeredLogRecordProcessors[1]._exporter instanceof
InMemoryLogRecordExporter
);
assert(
sharedState.registeredLogRecordProcessors[1] instanceof
BatchLogRecordProcessor
);
});
});

Expand Down Expand Up @@ -846,7 +880,11 @@ describe('Node SDK', () => {
});

describe('configuring logger provider from env', () => {
let stubLogger = Sinon.stub(diag, 'warn');
let stubLogger: Sinon.SinonStub;

beforeEach(() => {
stubLogger = Sinon.stub(diag, 'warn');
});

afterEach(() => {
stubLogger.reset();
Expand All @@ -858,14 +896,23 @@ describe('Node SDK', () => {

assert.strictEqual(
stubLogger.args[0][0],
'No log exporter specified. Logs will not be exported.'
'No log exporters specified. Logs will not be exported.'
);

await sdk.shutdown();
});

it('should not register the provider if OTEL_LOGS_EXPORTER contains none', async () => {
assert(true);
env.OTEL_LOGS_EXPORTER = 'console,none';
const sdk = new NodeSDK();
sdk.start();
assert.strictEqual(
stubLogger.args[0][0],
'OTEL_LOGS_EXPORTER contains "none". Logger provider will not be initialized.'
);

assert(logs.getLoggerProvider() instanceof NoopLoggerProvider);
await sdk.shutdown();
});

it('should set up all allowed exporters', async () => {
Expand All @@ -877,10 +924,23 @@ describe('Node SDK', () => {
const loggerProvider = logs.getLoggerProvider();
const sharedState = (loggerProvider as any)['_sharedState'];
assert(sharedState.registeredLogRecordProcessors.length === 2);
assert(sharedState.registeredLogRecordProcessors[0]._exporter instanceof ConsoleLogRecordExporter);
assert(
sharedState.registeredLogRecordProcessors[0]._exporter instanceof
ConsoleLogRecordExporter
);
assert(
sharedState.registeredLogRecordProcessors[0] instanceof
BatchLogRecordProcessor
);
// defaults to http/protobuf
assert(sharedState.registeredLogRecordProcessors[1]._exporter instanceof OTLPProtoLogExporter);
// FIXME check that BatchLogProcessor is used
assert(
sharedState.registeredLogRecordProcessors[1]._exporter instanceof
OTLPProtoLogExporter
);
assert(
sharedState.registeredLogRecordProcessors[1] instanceof
BatchLogRecordProcessor
);
delete env.OTEL_LOGS_EXPORTER;
await sdk.shutdown();
});
Expand All @@ -895,7 +955,29 @@ describe('Node SDK', () => {
const loggerProvider = logs.getLoggerProvider();
const sharedState = (loggerProvider as any)['_sharedState'];
assert(sharedState.registeredLogRecordProcessors.length === 1);
assert(sharedState.registeredLogRecordProcessors[0]._exporter instanceof OTLPGrpcLogExporter);
assert(
sharedState.registeredLogRecordProcessors[0]._exporter instanceof
OTLPGrpcLogExporter
);
delete env.OTEL_LOGS_EXPORTER;
delete env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL;
await sdk.shutdown();
});

it('should use OTLPHttpLogExporter when http/json is set', async () => {
env.OTEL_LOGS_EXPORTER = 'otlp';
env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL = 'http/json';
const sdk = new NodeSDK();

sdk.start();

const loggerProvider = logs.getLoggerProvider();
const sharedState = (loggerProvider as any)['_sharedState'];
assert(sharedState.registeredLogRecordProcessors.length === 1);
assert(
sharedState.registeredLogRecordProcessors[0]._exporter instanceof
OTLPHttpLogExporter
);
delete env.OTEL_LOGS_EXPORTER;
delete env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL;
await sdk.shutdown();
Expand All @@ -911,7 +993,10 @@ describe('Node SDK', () => {
const loggerProvider = logs.getLoggerProvider();
const sharedState = (loggerProvider as any)['_sharedState'];
assert(sharedState.registeredLogRecordProcessors.length === 1);
assert(sharedState.registeredLogRecordProcessors[0]._exporter instanceof OTLPGrpcLogExporter);
assert(
sharedState.registeredLogRecordProcessors[0]._exporter instanceof
OTLPGrpcLogExporter
);

delete env.OTEL_LOGS_EXPORTER;
delete env.OTEL_EXPORTER_OTLP_PROTOCOL;
Expand All @@ -928,7 +1013,10 @@ describe('Node SDK', () => {
const loggerProvider = logs.getLoggerProvider();
const sharedState = (loggerProvider as any)['_sharedState'];
assert(sharedState.registeredLogRecordProcessors.length === 1);
assert(sharedState.registeredLogRecordProcessors[0]._exporter instanceof OTLPProtoLogExporter);
assert(
sharedState.registeredLogRecordProcessors[0]._exporter instanceof
OTLPProtoLogExporter
);

delete env.OTEL_LOGS_EXPORTER;
delete env.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL;
Expand Down