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): logs support added #3969

Merged
merged 7 commits into from
Jul 10, 2023
Merged
Changes from 3 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
3 changes: 3 additions & 0 deletions experimental/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -2,6 +2,9 @@

All notable changes to experimental packages in this project will be documented in this file.

## New Feature
logs feature added in SDK-NODE

psk001 marked this conversation as resolved.
Show resolved Hide resolved
## Unreleased

### :boom: Breaking Change
2 changes: 2 additions & 0 deletions experimental/packages/opentelemetry-sdk-node/package.json
Original file line number Diff line number Diff line change
@@ -44,6 +44,7 @@
"access": "public"
},
"dependencies": {
"@opentelemetry/api-logs":"0.41.0",
"@opentelemetry/core": "1.15.0",
"@opentelemetry/exporter-jaeger": "1.15.0",
"@opentelemetry/exporter-trace-otlp-grpc": "0.41.0",
@@ -52,6 +53,7 @@
"@opentelemetry/exporter-zipkin": "1.15.0",
"@opentelemetry/instrumentation": "0.41.0",
"@opentelemetry/resources": "1.15.0",
"@opentelemetry/sdk-logs":"0.41.0",
"@opentelemetry/sdk-metrics": "1.15.0",
"@opentelemetry/sdk-trace-base": "1.15.0",
"@opentelemetry/sdk-trace-node": "1.15.0",
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
export * as api from '@opentelemetry/api';
export * as contextBase from '@opentelemetry/api';
export * as core from '@opentelemetry/core';
export * as logs from '@opentelemetry/sdk-logs';
export * as metrics from '@opentelemetry/sdk-metrics';
export * as node from '@opentelemetry/sdk-trace-node';
export * as resources from '@opentelemetry/resources';
58 changes: 58 additions & 0 deletions experimental/packages/opentelemetry-sdk-node/src/sdk.ts
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ import {
diag,
DiagConsoleLogger,
} from '@opentelemetry/api';
import { logs } from '@opentelemetry/api-logs';
import {
InstrumentationOption,
registerInstrumentations,
@@ -35,6 +36,7 @@ import {
Resource,
ResourceDetectionConfig,
} from '@opentelemetry/resources';
import { LogRecordProcessor, LoggerProvider } from '@opentelemetry/sdk-logs';
import { MeterProvider, MetricReader, View } from '@opentelemetry/sdk-metrics';
import {
BatchSpanProcessor,
@@ -63,13 +65,21 @@ export type MeterProviderConfig = {
views?: View[];
};

export type LoggerProviderConfig = {
/**
* Reference to the Logger instance by the NodeSDK
psk001 marked this conversation as resolved.
Show resolved Hide resolved
*/
logRecordProcessor: LogRecordProcessor;
};

export class NodeSDK {
private _tracerProviderConfig?: {
tracerConfig: NodeTracerConfig;
spanProcessor: SpanProcessor;
contextManager?: ContextManager;
textMapPropagator?: TextMapPropagator;
};
private _loggerProviderConfig?: LoggerProviderConfig;
private _meterProviderConfig?: MeterProviderConfig;
private _instrumentations: InstrumentationOption[];

@@ -79,6 +89,7 @@ export class NodeSDK {
private _autoDetectResources: boolean;

private _tracerProvider?: NodeTracerProvider | TracerProviderWithEnvExporters;
private _loggerProvider?: LoggerProvider;
private _meterProvider?: MeterProvider;
private _serviceName?: string;

@@ -140,6 +151,13 @@ export class NodeSDK {
);
}

if (configuration.logRecordProcessor) {
const loggerProviderConfig: LoggerProviderConfig = {
logRecordProcessor: configuration.logRecordProcessor,
};
this.configureLoggerProvider(loggerProviderConfig);
}

if (configuration.metricReader || configuration.views) {
const meterProviderConfig: MeterProviderConfig = {};
if (configuration.metricReader) {
@@ -175,6 +193,30 @@ export class NodeSDK {
};
}

/**Set configurations neeeded to register a LoggerProvider */
psk001 marked this conversation as resolved.
Show resolved Hide resolved
public configureLoggerProvider(config: LoggerProviderConfig): void {
// nothing is set yet, we can set config and then return
if (this._loggerProviderConfig == null) {
this._loggerProviderConfig = config;
return;
}

// make sure we do not override existing logRecordProcessor with other logRecordProcessors.
if (
this._loggerProviderConfig.logRecordProcessor != null &&
config.logRecordProcessor != null
) {
throw new Error(
'LogRecordProvider passed but LogRecordProcessor has already been configured.'
psk001 marked this conversation as resolved.
Show resolved Hide resolved
);
}

// set logRecordProcessor, but make sure we do not override existing logRecordProcessors with null/undefined.
if (config.logRecordProcessor != null) {
this._loggerProviderConfig.logRecordProcessor = config.logRecordProcessor;
}
}

/** Set configurations needed to register a MeterProvider */
public configureMeterProvider(config: MeterProviderConfig): void {
// nothing is set yet, we can set config and return.
@@ -269,6 +311,19 @@ export class NodeSDK {
propagator: this._tracerProviderConfig?.textMapPropagator,
});

if (this._loggerProviderConfig) {
const loggerProvider = new LoggerProvider({
resource: this._resource,
});
loggerProvider.addLogRecordProcessor(
this._loggerProviderConfig.logRecordProcessor
);

this._loggerProvider = loggerProvider;

logs.setGlobalLoggerProvider(loggerProvider);
}

if (this._meterProviderConfig) {
const meterProvider = new MeterProvider({
resource: this._resource,
@@ -299,6 +354,9 @@ export class NodeSDK {
if (this._tracerProvider) {
promises.push(this._tracerProvider.shutdown());
}
if (this._loggerProvider) {
promises.push(this._loggerProvider.shutdown());
}
if (this._meterProvider) {
promises.push(this._meterProvider.shutdown());
}
2 changes: 2 additions & 0 deletions experimental/packages/opentelemetry-sdk-node/src/types.ts
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@ import type { ContextManager } from '@opentelemetry/api';
import { TextMapPropagator } from '@opentelemetry/api';
import { InstrumentationOption } from '@opentelemetry/instrumentation';
import { Detector, DetectorSync, IResource } from '@opentelemetry/resources';
import { LogRecordProcessor } from '@opentelemetry/sdk-logs';
import { MetricReader, View } from '@opentelemetry/sdk-metrics';
import {
Sampler,
@@ -31,6 +32,7 @@ export interface NodeSDKConfiguration {
autoDetectResources: boolean;
contextManager: ContextManager;
textMapPropagator: TextMapPropagator;
logRecordProcessor: LogRecordProcessor;
metricReader: MetricReader;
views: View[];
instrumentations: InstrumentationOption[];
63 changes: 63 additions & 0 deletions experimental/packages/opentelemetry-sdk-node/test/sdk.test.ts
Original file line number Diff line number Diff line change
@@ -59,6 +59,12 @@ import {
Resource,
} from '@opentelemetry/resources';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { logs } from '@opentelemetry/api-logs';
import {
SimpleLogRecordProcessor,
InMemoryLogRecordExporter,
LoggerProvider,
} from '@opentelemetry/sdk-logs';

const DefaultContextManager = semver.gte(process.version, '14.8.0')
? AsyncLocalStorageContextManager
@@ -112,6 +118,7 @@ describe('Node SDK', () => {
'tracer provider should not have changed'
);
assert.ok(!(metrics.getMeterProvider() instanceof MeterProvider));
assert.ok(!(logs.getLoggerProvider() instanceof LoggerProvider));
delete env.OTEL_TRACES_EXPORTER;
});

@@ -233,6 +240,40 @@ describe('Node SDK', () => {
await sdk.shutdown();
delete env.OTEL_TRACES_EXPORTER;
});

it('should register a logger provider if a log record processor is provided', async () => {
env.OTEL_TRACES_EXPORTER = 'none';
const logRecordExporter = new InMemoryLogRecordExporter();
const logRecordProcessor = new SimpleLogRecordProcessor(
logRecordExporter
);
const sdk = new NodeSDK({
logRecordProcessor: logRecordProcessor,
autoDetectResources: false,
});

sdk.start();

assert.strictEqual(
context['_getContextManager'](),
ctxManager,
'context manager should not change'
);
assert.strictEqual(
propagation['_getGlobalPropagator'](),
propagator,
'propagator should not change'
);
assert.strictEqual(
(trace.getTracerProvider() as ProxyTracerProvider).getDelegate(),
delegate,
'tracer provider should not have changed'
);

assert.ok(logs.getLoggerProvider() instanceof LoggerProvider);
await sdk.shutdown();
delete env.OTEL_TRACES_EXPORTER;
});
});

async function waitForNumberOfMetrics(
@@ -406,6 +447,28 @@ describe('Node SDK', () => {
);
});

it('should throw error when calling configureLoggerProvider when logRecordProcessor is already configured', () => {
const logRecordExporter = new InMemoryLogRecordExporter();
const logRecordProcessor = new SimpleLogRecordProcessor(logRecordExporter);
const sdk = new NodeSDK({
logRecordProcessor: logRecordProcessor,
autoDetectResources: false,
});

assert.throws(
() => {
sdk.configureLoggerProvider({
logRecordProcessor: logRecordProcessor,
});
},
(error: Error) => {
return error.message.includes(
'LogRecordProvider passed but LogRecordProcessor has already been configured.'
);
}
);
});

describe('detectResources', async () => {
beforeEach(() => {
process.env.OTEL_RESOURCE_ATTRIBUTES =
6 changes: 6 additions & 0 deletions experimental/packages/opentelemetry-sdk-node/tsconfig.json
Original file line number Diff line number Diff line change
@@ -12,6 +12,9 @@
{
"path": "../../../api"
},
{
"path": "../../packages/api-logs"
},
{
"path": "../../../packages/opentelemetry-context-async-hooks"
},
@@ -36,6 +39,9 @@
{
"path": "../../../packages/opentelemetry-semantic-conventions"
},
{
"path": "../../packages/sdk-logs"
},
{
"path": "../../../packages/sdk-metrics"
},