lib/instrumentation/modules/@opentelemetry/sdk-metrics.js (50 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';
// This instruments '@opentelemetry/sdk-metrics' to automatically add a metric
// reader to any `MeterProvider` created by user code. The added metric
// reader will export metrics to the configured APM server.
//
// This covers use case 1 in the OTel metrics spec:
// https://github.com/elastic/apm/blob/main/specs/agents/metrics-otel.md#exporter-installation
//
// Dev Note: This avoids instrumenting the `MeterProvider` used *internally*
// by the APM agent itself (see "lib/opentelemetry-metrics/index.js") because
// that file imports `MeterProvider` before the APM agent is started.
const semver = require('semver');
const {
isOTelMetricsFeatSupported,
createOTelMetricReader,
} = require('../../../opentelemetry-metrics');
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/sdk-metrics instrumentation',
version,
);
return mod;
}
// Minimum supported version is 1.11.0 because that version included the fix
// for side-effects from having two MetricReaders.
// https://github.com/open-telemetry/opentelemetry-js/issues/3664
if (!semver.satisfies(version, '>=1.11.0 <2', { includePrerelease: true })) {
log.debug(
'@opentelemetry/sdk-metrics@%s is not supported, skipping @opentelemetry/sdk-metrics instrumentation',
version,
);
return mod;
}
if (!isOTelMetricsFeatSupported) {
log.debug(
'elastic-apm-node OTel Metrics feature does not support node %s, skipping @opentelemetry/sdk-metrics instrumentation',
process.version,
);
return mod;
}
class ApmMeterProvider extends mod.MeterProvider {
constructor(...args) {
super(...args);
// We create a new metric reader for each new MeterProvider instance,
// because they shutdown independently -- they cannot be shared between
// multiple MeterProviders.
log.trace(
'@opentelemetry/sdk-metrics ins: create Elastic APM MetricReader',
);
this.addMetricReader(createOTelMetricReader(agent));
}
}
Object.defineProperty(mod, 'MeterProvider', {
configurable: true,
enumerable: true,
get: function () {
return ApmMeterProvider;
},
});
return mod;
};