lib/instrumentation/modules/@opentelemetry/api.js (53 lines of code) (raw):

/* * Copyright Elasticsearch B.V. and other contributors where applicable. * Licensed under the BSD 2-Clause License; you may not use this file except in * compliance with the BSD 2-Clause License. */ 'use strict'; // Instrument `.metrics.getMeterProvider()` from `@opentelemetry/api` to // provide an Elastic APM provider if user code hasn't registered one itself. // // This covers use case 2 in the OTel metrics spec: // https://github.com/elastic/apm/blob/main/specs/agents/metrics-otel.md#exporter-installation const semver = require('semver'); const { isOTelMetricsFeatSupported, } = require('../../../opentelemetry-metrics'); const shimmer = require('../../shimmer'); /** * `otel.metrics.getMeterProvider()` returns a singleton instance of the * internal `NoopMeterProvider` class if no global meter provider has been * set. There isn't an explicitly API to determine if a provider is a noop * one. This function attempts to sniff that out. * * We cannot rely on comparing to the `NOOP_METER_PROVIDER` exported by * "src/metrics/NoopMeterProvider.ts" because there might be multiple * "@opentelemetry/api" packages in play. * * @param {import('@opentelemetry/api').MeterProvider} * @returns {boolean} */ function isNoopMeterProvider(provider) { return !!( provider && provider.constructor && provider.constructor.name === 'NoopMeterProvider' ); } module.exports = function (mod, agent, { version, enabled }) { const log = agent.logger; if (!enabled) { return mod; } if (!agent._isMetricsEnabled()) { log.trace( 'metrics are not enabled, skipping @opentelemetry/api instrumentation', version, ); return mod; } if (!semver.satisfies(version, '>=1.3.0 <2', { includePrerelease: true })) { log.debug( '@opentelemetry/api version %s not supported, skipping @opentelemetry/api instrumentation', version, ); return mod; } if (!isOTelMetricsFeatSupported) { log.debug( 'elastic-apm-node OTel Metrics support does not support node %s, skipping @opentelemetry/api instrumentation', process.version, ); return mod; } log.debug('shimming @opentelemetry/api .metrics.getMeterProvider()'); shimmer.wrap(mod.metrics, 'getMeterProvider', wrapGetMeterProvider); return mod; function wrapGetMeterProvider(orig) { return function wrappedGetMeterProvider() { const provider = orig.apply(this, arguments); if (!isNoopMeterProvider(provider)) { return provider; } const elMeterProvider = agent._getOrCreateOTelMeterProvider(); return elMeterProvider || provider; }; } };