diff --git a/experimental/CHANGELOG.md b/experimental/CHANGELOG.md index a8140469bf..d025c4d4b7 100644 --- a/experimental/CHANGELOG.md +++ b/experimental/CHANGELOG.md @@ -19,6 +19,7 @@ All notable changes to experimental packages in this project will be documented ### :bug: (Bug Fix) * fix(prometheus-exporter): add possibility to respond to errors returned by `server.listen()` [#3552](https://github.com/open-telemetry/opentelemetry-js/pull/3402) @pichlermarc + fix(sdk-node): update instrumentations once MeterProvider is initialized [#3624](https://github.com/open-telemetry/opentelemetry-js/pull/3624) @pichlermarc ### :books: (Refine Doc) diff --git a/experimental/packages/opentelemetry-sdk-node/src/sdk.ts b/experimental/packages/opentelemetry-sdk-node/src/sdk.ts index 8b0e539eeb..dc9244f3e4 100644 --- a/experimental/packages/opentelemetry-sdk-node/src/sdk.ts +++ b/experimental/packages/opentelemetry-sdk-node/src/sdk.ts @@ -48,6 +48,7 @@ import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions' import { NodeSDKConfiguration } from './types'; import { TracerProviderWithEnvExporters } from './TracerProviderWithEnvExporter'; import { getEnv } from '@opentelemetry/core'; +import { parseInstrumentationOptions } from './utils'; /** This class represents everything needed to register a fully configured OpenTelemetry Node.js SDK */ @@ -61,6 +62,7 @@ export type MeterProviderConfig = { */ views?: View[]; }; + export class NodeSDK { private _tracerProviderConfig?: { tracerConfig: NodeTracerConfig; @@ -275,6 +277,15 @@ export class NodeSDK { this._meterProvider = meterProvider; metrics.setGlobalMeterProvider(meterProvider); + + // TODO: This is a workaround to fix https://github.com/open-telemetry/opentelemetry-js/issues/3609 + // If the MeterProvider is not yet registered when instrumentations are registered, all metrics are dropped. + // This code is obsolete once https://github.com/open-telemetry/opentelemetry-js/issues/3622 is implemented. + for (const instrumentation of parseInstrumentationOptions( + this._instrumentations + )) { + instrumentation.setMeterProvider(metrics.getMeterProvider()); + } } } diff --git a/experimental/packages/opentelemetry-sdk-node/src/utils.ts b/experimental/packages/opentelemetry-sdk-node/src/utils.ts new file mode 100644 index 0000000000..a3d8314747 --- /dev/null +++ b/experimental/packages/opentelemetry-sdk-node/src/utils.ts @@ -0,0 +1,43 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + Instrumentation, + InstrumentationOption, +} from '@opentelemetry/instrumentation'; + +// TODO: This part of a workaround to fix https://github.com/open-telemetry/opentelemetry-js/issues/3609 +// If the MeterProvider is not yet registered when instrumentations are registered, all metrics are dropped. +// This code is obsolete once https://github.com/open-telemetry/opentelemetry-js/issues/3622 is implemented. +export function parseInstrumentationOptions( + options: InstrumentationOption[] = [] +): Instrumentation[] { + let instrumentations: Instrumentation[] = []; + for (let i = 0, j = options.length; i < j; i++) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const option = options[i] as any; + if (Array.isArray(option)) { + const results = parseInstrumentationOptions(option); + instrumentations = instrumentations.concat(results); + } else if (typeof option === 'function') { + instrumentations.push(new option()); + } else if ((option as Instrumentation).instrumentationName) { + instrumentations.push(option); + } + } + + return instrumentations; +}