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
3 changes: 3 additions & 0 deletions experimental/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2

### :rocket: Features

* feat(sdk-node): always set up propagtion and context manager [#5930](https://github.com/open-telemetry/opentelemetry-js/pull/5930)
* using `(new NodeSDK).start()` will now automatically set up a context management and propagation, even if no Trace SDK
is initialized.
* feat(otlp-exporter-base, otlp-grpc-exporter-base): add an option to let an SDK distribution prepend their own user-agent string in HTTP & GRPC exporters [#5928](https://github.com/open-telemetry/opentelemetry-js/pull/5928) @david-luna

### :bug: Bug Fixes
Expand Down
70 changes: 40 additions & 30 deletions experimental/packages/opentelemetry-sdk-node/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,7 @@
* limitations under the License.
*/

import {
ContextManager,
TextMapPropagator,
metrics,
diag,
DiagConsoleLogger,
} from '@opentelemetry/api';
import { metrics, trace, diag, DiagConsoleLogger } from '@opentelemetry/api';
import { logs } from '@opentelemetry/api-logs';
import {
Instrumentation,
Expand Down Expand Up @@ -79,9 +73,14 @@ import {
getResourceDetectorsFromEnv,
getSpanProcessorsFromEnv,
getPropagatorFromEnv,
setupPropagator,
setupContextManager,
} from './utils';

/** This class represents everything needed to register a fully configured OpenTelemetry Node.js SDK */
type TracerProviderConfig = {
tracerConfig: NodeTracerConfig;
spanProcessors: SpanProcessor[];
};

export type MeterProviderConfig = {
/**
Expand Down Expand Up @@ -129,6 +128,7 @@ function configureMetricProviderFromEnv(): IMetricReader[] {
);
return metricReaders;
}

enabledExporters.forEach(exporter => {
if (exporter === 'otlp') {
const protocol =
Expand Down Expand Up @@ -201,13 +201,27 @@ function configureMetricProviderFromEnv(): IMetricReader[] {

return metricReaders;
}

/**
* A setup helper for the OpenTelemetry SDKs (logs, metrics, traces).
* <p> After successful setup using {@link NodeSDK#start()}, use `@opentelemetry/api` to obtain the registered components.
* <p> Use the shutdown handler {@link NodeSDK#shutdown()} to ensure your telemetry is exported before the process exits.
*
* @example <caption> Register SDK by using environment variables </caption>
* const nodeSdk = new NodeSDK(); // providing no options uses OTEL_* environment variables for SDK setup.
* nodeSdk.start(); // registers all configured SDK components
* @example <caption> Override environment variable config with your own components </caption>
* const nodeSdk = new NodeSDK({
* // override the list of metric reader with your own options and ignore environment variable config
* // explore the docs of other options to learn more!
* metricReaders: [ new PeriodicExportingMetricReader({
* exporter: new OTLPMetricsExporter()
* })]
* });
* nodeSdk.start(); // registers all configured SDK components
*/
export class NodeSDK {
private _tracerProviderConfig?: {
tracerConfig: NodeTracerConfig;
spanProcessors: SpanProcessor[];
contextManager?: ContextManager;
textMapPropagator?: TextMapPropagator;
};
private _tracerProviderConfig?: TracerProviderConfig;
private _loggerProviderConfig?: LoggerProviderConfig;
private _meterProviderConfig?: MeterProviderConfig;
private _instrumentations: Instrumentation[];
Expand Down Expand Up @@ -292,8 +306,6 @@ export class NodeSDK {
this._tracerProviderConfig = {
tracerConfig: tracerProviderConfig,
spanProcessors,
contextManager: configuration.contextManager,
textMapPropagator: configuration.textMapPropagator,
};
}

Expand Down Expand Up @@ -350,6 +362,13 @@ export class NodeSDK {
instrumentations: this._instrumentations,
});

setupContextManager(this._configuration?.contextManager);
setupPropagator(
this._configuration?.textMapPropagator === null
? null // null means don't set, so we cannot fall back to env config.
: (this._configuration?.textMapPropagator ?? getPropagatorFromEnv())
);

if (this._autoDetectResources) {
const internalConfig: ResourceDetectionConfig = {
detectors: this._resourceDetectors,
Expand All @@ -371,23 +390,14 @@ export class NodeSDK {
? this._tracerProviderConfig.spanProcessors
: getSpanProcessorsFromEnv();

this._tracerProvider = new NodeTracerProvider({
...this._configuration,
resource: this._resource,
spanProcessors,
});

// Only register if there is a span processor
if (spanProcessors.length > 0) {
this._tracerProvider.register({
contextManager:
this._tracerProviderConfig?.contextManager ??
// _tracerProviderConfig may be undefined if trace-specific settings are not provided - fall back to raw config
this._configuration?.contextManager,
propagator:
this._tracerProviderConfig?.textMapPropagator ??
getPropagatorFromEnv(),
this._tracerProvider = new NodeTracerProvider({
...this._configuration,
resource: this._resource,
spanProcessors,
});
trace.setGlobalTracerProvider(this._tracerProvider);
}

if (this._loggerProviderConfig) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {
export interface NodeSDKConfiguration {
autoDetectResources: boolean;
contextManager: ContextManager;
textMapPropagator: TextMapPropagator;
textMapPropagator: TextMapPropagator | null;
/** @deprecated use logRecordProcessors instead*/
logRecordProcessor: LogRecordProcessor;
logRecordProcessors?: LogRecordProcessor[];
Expand Down
57 changes: 56 additions & 1 deletion experimental/packages/opentelemetry-sdk-node/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@
* limitations under the License.
*/

import { diag, TextMapPropagator } from '@opentelemetry/api';
import {
context,
ContextManager,
diag,
propagation,
TextMapPropagator,
} from '@opentelemetry/api';
import {
CompositePropagator,
getStringFromEnv,
Expand Down Expand Up @@ -43,6 +49,7 @@ import {
} from '@opentelemetry/sdk-trace-base';
import { B3InjectEncoding, B3Propagator } from '@opentelemetry/propagator-b3';
import { JaegerPropagator } from '@opentelemetry/propagator-jaeger';
import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-hooks';

const RESOURCE_DETECTOR_ENVIRONMENT = 'env';
const RESOURCE_DETECTOR_HOST = 'host';
Expand Down Expand Up @@ -198,6 +205,10 @@ export function getPropagatorFromEnv(): TextMapPropagator | null | undefined {
return undefined;
}

if (propagatorsEnvVarValue.includes('none')) {
return null;
}

// Implementation note: this only contains specification required propagators that are actually hosted in this repo.
// Any other propagators (like aws, aws-lambda, should go into `@opentelemetry/auto-configuration-propagators` instead).
const propagatorsFactory = new Map<string, () => TextMapPropagator>([
Expand Down Expand Up @@ -247,3 +258,47 @@ export function getPropagatorFromEnv(): TextMapPropagator | null | undefined {
});
}
}

export function setupContextManager(
contextManager: ContextManager | null | undefined
) {
// null means 'do not register'
if (contextManager === null) {
return;
}

// undefined means 'register default'
if (contextManager === undefined) {
const defaultContextManager = new AsyncLocalStorageContextManager();
defaultContextManager.enable();
context.setGlobalContextManager(defaultContextManager);
return;
}

contextManager.enable();
context.setGlobalContextManager(contextManager);
}

export function setupPropagator(
propagator: TextMapPropagator | null | undefined
) {
// null means 'do not register'
if (propagator === null) {
return;
}

// undefined means 'register default'
if (propagator === undefined) {
propagation.setGlobalPropagator(
new CompositePropagator({
propagators: [
new W3CTraceContextPropagator(),
new W3CBaggagePropagator(),
],
})
);
return;
}

propagation.setGlobalPropagator(propagator);
}
Loading