-
Notifications
You must be signed in to change notification settings - Fork 1.1k
chore(sdk-node): migrate to the new sdk-trace package #6828
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
Changes from all commits
930abcf
0e58a94
22daaab
16f091a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| /** | ||
| * Create SDK components from parsed declarative config. | ||
| * https://opentelemetry.io/docs/specs/otel/configuration/sdk/#create | ||
| */ | ||
|
|
||
| import type { | ||
| AttributeLimitsConfigModel, | ||
| SpanLimitsConfigModel, | ||
| } from '@opentelemetry/configuration'; | ||
| import type { SpanLimits } from '@opentelemetry/sdk-trace'; | ||
|
|
||
| export function createSpanLimitsFromConfig( | ||
| limits?: SpanLimitsConfigModel, | ||
| attribute_limits?: AttributeLimitsConfigModel | ||
| ): SpanLimits | undefined { | ||
| if (!limits && !attribute_limits) { | ||
| return undefined; | ||
| } | ||
| return { | ||
| attributeValueLengthLimit: | ||
| limits?.attribute_value_length_limit ?? | ||
| attribute_limits?.attribute_value_length_limit ?? | ||
| undefined, | ||
| attributeCountLimit: | ||
| limits?.attribute_count_limit ?? | ||
| attribute_limits?.attribute_count_limit ?? | ||
| undefined, | ||
| eventCountLimit: limits?.event_count_limit ?? undefined, | ||
| linkCountLimit: limits?.link_count_limit ?? undefined, | ||
| attributePerEventCountLimit: | ||
| limits?.event_attribute_count_limit ?? undefined, | ||
| attributePerLinkCountLimit: limits?.link_attribute_count_limit ?? undefined, | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,113 @@ | ||||
| /* | ||||
| * Copyright The OpenTelemetry Authors | ||||
| * SPDX-License-Identifier: Apache-2.0 | ||||
| */ | ||||
|
|
||||
| /** | ||||
| * Create SDK components from environment variable settings. | ||||
| * https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/ | ||||
| */ | ||||
|
|
||||
| import { diag } from '@opentelemetry/api'; | ||||
| import { getNumberFromEnv, getStringFromEnv } from '@opentelemetry/core'; | ||||
| import type { | ||||
| Sampler, | ||||
| SpanExporter, | ||||
| SpanLimits, | ||||
| } from '@opentelemetry/sdk-trace'; | ||||
| import { BatchSpanProcessor } from '@opentelemetry/sdk-trace'; | ||||
| import { | ||||
| AlwaysOffSampler, | ||||
| AlwaysOnSampler, | ||||
| ParentBasedSampler, | ||||
| TraceIdRatioBasedSampler, | ||||
| } from '@opentelemetry/sdk-trace'; | ||||
| import { getNonNegativeNumberFromEnv } from './utils'; | ||||
|
|
||||
| const DEFAULT_RATIO = 1; | ||||
|
|
||||
| export function createSamplerFromEnv(): Sampler | undefined { | ||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: Adapted from buildSamplerFromEnv in sdk-trace-base:
|
||||
| const samplerName = getStringFromEnv('OTEL_TRACES_SAMPLER'); | ||||
| if (samplerName === undefined) { | ||||
| return undefined; | ||||
| } | ||||
| switch (samplerName) { | ||||
| case 'always_on': | ||||
| return new AlwaysOnSampler(); | ||||
| case 'always_off': | ||||
| return new AlwaysOffSampler(); | ||||
| case 'parentbased_always_on': | ||||
| return new ParentBasedSampler({ | ||||
| root: new AlwaysOnSampler(), | ||||
| }); | ||||
| case 'parentbased_always_off': | ||||
| return new ParentBasedSampler({ | ||||
| root: new AlwaysOffSampler(), | ||||
| }); | ||||
| case 'traceidratio': | ||||
| return new TraceIdRatioBasedSampler(getSamplerRatioFromEnv()); | ||||
| case 'parentbased_traceidratio': | ||||
| return new ParentBasedSampler({ | ||||
| root: new TraceIdRatioBasedSampler(getSamplerRatioFromEnv()), | ||||
| }); | ||||
| default: | ||||
| diag.error( | ||||
| `unknown OTEL_TRACES_SAMPLER value "${samplerName}", using default` | ||||
| ); | ||||
| return undefined; | ||||
| } | ||||
| } | ||||
|
|
||||
| function getSamplerRatioFromEnv(): number | undefined { | ||||
| const ratio = getNumberFromEnv('OTEL_TRACES_SAMPLER_ARG'); | ||||
| if (ratio == null) { | ||||
| diag.error( | ||||
| `OTEL_TRACES_SAMPLER_ARG is blank, defaulting to ${DEFAULT_RATIO}.` | ||||
| ); | ||||
| return DEFAULT_RATIO; | ||||
| } | ||||
|
|
||||
| if (ratio < 0 || ratio > 1) { | ||||
| diag.error( | ||||
| `OTEL_TRACES_SAMPLER_ARG=${ratio} was given, but it is out of range ([0..1]), defaulting to ${DEFAULT_RATIO}.` | ||||
| ); | ||||
| return DEFAULT_RATIO; | ||||
| } | ||||
|
|
||||
| return ratio; | ||||
| } | ||||
|
|
||||
| export function createSpanLimitsFromEnv(): SpanLimits | undefined { | ||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: Adapted from
|
||||
| return { | ||||
| attributeCountLimit: | ||||
| getNumberFromEnv('OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT') ?? | ||||
| getNumberFromEnv('OTEL_ATTRIBUTE_COUNT_LIMIT'), | ||||
| attributeValueLengthLimit: | ||||
| getNumberFromEnv('OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT') ?? | ||||
| getNumberFromEnv('OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT'), | ||||
| eventCountLimit: getNumberFromEnv('OTEL_SPAN_EVENT_COUNT_LIMIT'), | ||||
| linkCountLimit: getNumberFromEnv('OTEL_SPAN_LINK_COUNT_LIMIT'), | ||||
| attributePerEventCountLimit: getNumberFromEnv( | ||||
| 'OTEL_SPAN_ATTRIBUTE_PER_EVENT_COUNT_LIMIT' | ||||
| ), | ||||
| attributePerLinkCountLimit: getNumberFromEnv( | ||||
| 'OTEL_SPAN_ATTRIBUTE_PER_LINK_COUNT_LIMIT' | ||||
| ), | ||||
| }; | ||||
| } | ||||
|
|
||||
| export function createBatchSpanProcessorFromEnv( | ||||
| exporter: SpanExporter | ||||
| ): BatchSpanProcessor { | ||||
| return new BatchSpanProcessor({ | ||||
| exporter, | ||||
| maxQueueSize: getNonNegativeNumberFromEnv('OTEL_BSP_MAX_QUEUE_SIZE'), | ||||
| scheduledDelayMillis: getNonNegativeNumberFromEnv( | ||||
| 'OTEL_BSP_SCHEDULE_DELAY' | ||||
| ), | ||||
| exportTimeoutMillis: getNonNegativeNumberFromEnv('OTEL_BSP_EXPORT_TIMEOUT'), | ||||
| maxExportBatchSize: getNonNegativeNumberFromEnv( | ||||
| 'OTEL_BSP_MAX_EXPORT_BATCH_SIZE' | ||||
| ), | ||||
| }); | ||||
| } | ||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,8 +14,15 @@ 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'; | ||
|
|
||
| /** | ||
| * @deprecated Import directly from `@opentelemetry/sdk-trace` instead. | ||
| */ | ||
| export * as node from '@opentelemetry/sdk-trace-node'; | ||
| /** | ||
| * @deprecated Import directly from `@opentelemetry/sdk-trace` instead. | ||
| */ | ||
| export * as tracing from '@opentelemetry/sdk-trace-base'; | ||
|
Comment on lines
+22
to
26
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: These existing re-exports are the only reason sdk-node cannot yet drop its dep on sdk-trace-node and sdk-trace-base. We'll drop these with SDK 3.0.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see you opened #6824. If you're feeling adventurous, we could also try to remove it and see if anybody is unhappy with that. I'd be willing to bet that almost nobody is using these re-exports. We don't need to do it in this PR though, let's keep this low-friction for now. |
||
| /* eslint-enable no-restricted-syntax */ | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,10 +39,7 @@ import { | |
| ConsoleMetricExporter, | ||
| PeriodicExportingMetricReader, | ||
| } from '@opentelemetry/sdk-metrics'; | ||
| import type { SpanProcessor } from '@opentelemetry/sdk-trace-base'; | ||
| import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base'; | ||
| import type { NodeTracerConfig } from '@opentelemetry/sdk-trace-node'; | ||
| import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; | ||
| import { TracerProvider } from '@opentelemetry/sdk-trace'; | ||
| import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions'; | ||
| import type { NodeSDKConfiguration } from './types'; | ||
| import { | ||
|
|
@@ -62,11 +59,11 @@ import { | |
| getBatchLogRecordProcessorFromEnv, | ||
| getLoggerProviderConfigFromEnv, | ||
| } from './utils'; | ||
|
|
||
| type TracerProviderConfig = { | ||
| tracerConfig: NodeTracerConfig; | ||
| spanProcessors: SpanProcessor[]; | ||
| }; | ||
| import { | ||
| createBatchSpanProcessorFromEnv, | ||
| createSamplerFromEnv, | ||
| createSpanLimitsFromEnv, | ||
| } from './create-from-env'; | ||
|
|
||
| export type MeterProviderConfig = { | ||
| /** | ||
|
|
@@ -150,7 +147,6 @@ function getMetricReadersFromEnv(): IMetricReader[] { | |
| * nodeSdk.start(); // registers all configured SDK components | ||
| */ | ||
| export class NodeSDK { | ||
| private _tracerProviderConfig?: TracerProviderConfig; | ||
| private _loggerProviderConfig?: LoggerProviderConfig; | ||
| private _meterProviderConfig?: MeterProviderConfig; | ||
| private _instrumentations: Instrumentation[]; | ||
|
|
@@ -160,7 +156,7 @@ export class NodeSDK { | |
|
|
||
| private _autoDetectResources: boolean; | ||
|
|
||
| private _tracerProvider?: NodeTracerProvider; | ||
| private _tracerProvider?: TracerProvider; | ||
| private _loggerProvider?: LoggerProvider; | ||
| private _meterProvider?: MeterProvider; | ||
| private _serviceName?: string; | ||
|
|
@@ -201,40 +197,10 @@ export class NodeSDK { | |
|
|
||
| this._serviceName = configuration.serviceName; | ||
|
|
||
| // If a tracer provider can be created from manual configuration, create it | ||
| if ( | ||
| configuration.traceExporter || | ||
| configuration.spanProcessor || | ||
| configuration.spanProcessors | ||
| ) { | ||
| const tracerProviderConfig: NodeTracerConfig = {}; | ||
|
|
||
| if (configuration.sampler) { | ||
| tracerProviderConfig.sampler = configuration.sampler; | ||
| } | ||
| if (configuration.spanLimits) { | ||
| tracerProviderConfig.spanLimits = configuration.spanLimits; | ||
| } | ||
| if (configuration.idGenerator) { | ||
| tracerProviderConfig.idGenerator = configuration.idGenerator; | ||
| } | ||
|
Comment on lines
-212
to
-220
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: This |
||
|
|
||
| if (configuration.spanProcessor) { | ||
| diag.warn( | ||
| "The 'spanProcessor' option is deprecated. Please use 'spanProcessors' instead." | ||
| ); | ||
| } | ||
|
|
||
| const spanProcessor = | ||
| configuration.spanProcessor ?? | ||
| new BatchSpanProcessor(configuration.traceExporter!); | ||
|
|
||
| const spanProcessors = configuration.spanProcessors ?? [spanProcessor]; | ||
|
|
||
| this._tracerProviderConfig = { | ||
| tracerConfig: tracerProviderConfig, | ||
| spanProcessors, | ||
| }; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: All of this handling of input config options for span processors is moved (and cleaned up) to and if-block in |
||
| if (configuration.spanProcessor) { | ||
| diag.warn( | ||
| "The 'spanProcessor' option is deprecated. Please use 'spanProcessors' instead." | ||
| ); | ||
| } | ||
|
|
||
| if (configuration.logRecordProcessors) { | ||
|
|
@@ -340,16 +306,31 @@ export class NodeSDK { | |
| } | ||
| } | ||
|
|
||
| const spanProcessors = this._tracerProviderConfig | ||
| ? this._tracerProviderConfig.spanProcessors | ||
| : getSpanProcessorsFromEnv(); | ||
| // Determine `spanProcessors` from multiple possible options. | ||
| let spanProcessors; | ||
| if (this._configuration?.spanProcessors) { | ||
| spanProcessors = this._configuration.spanProcessors; | ||
| } else if (this._configuration?.spanProcessor) { | ||
| spanProcessors = [this._configuration.spanProcessor]; | ||
| } else if (this._configuration?.traceExporter) { | ||
| spanProcessors = [ | ||
| createBatchSpanProcessorFromEnv(this._configuration.traceExporter!), | ||
| ]; | ||
| } else { | ||
| spanProcessors = getSpanProcessorsFromEnv(); | ||
| } | ||
|
|
||
| // Only register if there is a span processor | ||
| if (spanProcessors.length > 0) { | ||
| this._tracerProvider = new NodeTracerProvider({ | ||
| ...this._configuration, | ||
| this._tracerProvider = new TracerProvider({ | ||
| sampler: this._configuration?.sampler ?? createSamplerFromEnv(), | ||
| spanLimits: { | ||
| ...createSpanLimitsFromEnv(), | ||
| ...this._configuration?.spanLimits, | ||
| }, | ||
| resource: this._resource, | ||
| meterProvider: sdkMetricsEnabled ? this._meterProvider : undefined, | ||
| idGenerator: this._configuration?.idGenerator, | ||
| spanProcessors, | ||
| }); | ||
| trace.setGlobalTracerProvider(this._tracerProvider); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: This continues the
create<SDK Thing>FromConfig()pattern started in #6785I've also started moving "FromConfig"-specific things to this file, from the overly large "utils.ts".
I think it'll be helpful for maint and testing to separate the "FromEnv" handling and the "FromConfig" handling. Over a number of PRs I'll move/re-implement things in utils.ts over to "create-from-config.ts" and "create-from-env.ts".