in packages/opentelemetry-node/lib/instrumentations.js [245:353]
function getInstrumentations(opts = {}) {
/** @type {Array<Instrumentation>} */
const instrumentations = [];
const enabledFromEnv = getInstrumentationsFromEnv(
'OTEL_NODE_ENABLED_INSTRUMENTATIONS'
);
const disabledFromEnv = getInstrumentationsFromEnv(
'OTEL_NODE_DISABLED_INSTRUMENTATIONS'
);
// `@opentelemetry/instrumentation-http` defaults to emit old semconv attributes.
// Set the default to stable HTTP semconv if not defined by the user (http, http/dup)
// TODO: remove this once https://github.com/open-telemetry/opentelemetry-js/pull/5552
// is merged and published.
const semconvOptIn =
getStringListFromEnv('OTEL_SEMCONV_STABILITY_OPT_IN') || [];
if (!semconvOptIn.includes('http') && !semconvOptIn.includes('http/dup')) {
semconvOptIn.push('http');
process.env.OTEL_SEMCONV_STABILITY_OPT_IN = semconvOptIn.join(',');
}
const defaultInstrConfigFromName = {};
// Handle `ELASTIC_OTEL_NODE_ENABLE_LOG_SENDING`. The user must opt-in to
// the "log sending" feature of the OTel log framework instrumentations
// (pino, bunyan, winston). This *differs* from OTel JS, but matches
// OTel Java Agent behaviour.
//
// This sets a default `{disableLogSending: true}` default config for
// `instrumentation-{bunyan,pino,winston}`.
//
// See: https://github.com/elastic/elastic-otel-node/issues/680
// TODO: link instead to configuration doc for this when have it.
const enableLogSending = getBooleanFromEnv(
'ELASTIC_OTEL_NODE_ENABLE_LOG_SENDING'
);
if (!enableLogSending) {
const logInstrNames = ['bunyan', 'pino', 'winston'];
logInstrNames.forEach((name) => {
defaultInstrConfigFromName[
`@opentelemetry/instrumentation-${name}`
] = {disableLogSending: true};
});
}
// TODO: check `opts` and warn if it includes entries for unknown instrumentations (this is what `checkManuallyProvidedInstrumentationNames` does in auto-instrumentations-node).
Object.keys(instrumentationsMap).forEach((name) => {
// Skip if env has an `enabled` list and does not include this one
if (enabledFromEnv && !enabledFromEnv.includes(name)) {
return;
}
// Skip if env has an `disabled` list and it's present (overriding enabled list)
if (disabledFromEnv && disabledFromEnv.includes(name)) {
return;
}
// Skip if metrics are disabled by env var
const isMetricsDisabled =
getBooleanFromEnv('ELASTIC_OTEL_METRICS_DISABLED') ?? false;
if (
isMetricsDisabled &&
name === '@opentelemetry/instrumentation-runtime-node'
) {
return;
}
const isObject = typeof opts[name] === 'object';
if (!(opts[name] == null || isObject)) {
log.warn(
{instrConfig: opts[name]},
`invalid value for getInstrumentations() '${name}' option: must be object, got ${typeof opts[
name
]}`
);
}
let instrConfig = isObject ? opts[name] : undefined;
instrConfig = {...defaultInstrConfigFromName[name], ...instrConfig};
// We should instantiate a instrumentation:
// - if set via OTEL_NODE_ENABLED_INSTRUMENTATIONS
// - overriding any config that might be passed
// NOTE: factories are not overwritten
// - otherwise
// - if there is no config passed (elastic SDK will use its defaults)
// - if the configuration passed is not disabling it
let instr;
if (enabledFromEnv) {
instrConfig = {...instrConfig, enabled: true};
} else if (excludedInstrumentations.has(name)) {
// if excluded instrumentations not present in envvar the instrumentation
// is disabled unless an explicit config says the opposite
// ref: https://github.com/open-telemetry/opentelemetry-js-contrib/pull/2467
instrConfig = {enabled: false, ...instrConfig};
}
if (!instrConfig || instrConfig.enabled !== false) {
instr = instrumentationsMap[name](instrConfig);
}
if (instr) {
// Note that this doesn't log *functions* in instrConfig.
log.debug({instrConfig}, `Enabling instrumentation "${name}"`);
instrumentations.push(instr);
}
});
return instrumentations;
}