function getInstrumentations()

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;
}