function startNodeSDK()

in packages/opentelemetry-node/lib/sdk.js [80:215]


function startNodeSDK(cfg = {}) {
    log.trace('startNodeSDK cfg:', cfg);

    // TODO: test behaviour with OTEL_SDK_DISABLED.
    //      Do we still log preamble? See NodeSDK _disabled handling.
    //      Do we still attempt to enableHostMetrics()?
    if (getBooleanFromEnv('OTEL_SDK_DISABLED')) {
        // Note: This differs slightly from current NodeSDK, which does *some*
        // processing, even if disabled.
        log.trace('startNodeSDK: disabled');
        return {
            shutdown() {
                return Promise.resolve();
            },
        };
    }

    registerOTelDiagLogger(api);

    /** @type {Partial<NodeSDKConfiguration>} */
    const defaultConfig = {
        resourceDetectors: resolveDetectors(cfg.resourceDetectors),
        instrumentations: cfg.instrumentations || getInstrumentations(),
        // Avoid setting `spanProcessor` or `traceExporter` to have NodeSDK
        // use its `TracerProviderWithEnvExporters` for tracing setup.
    };

    const exporterPkgNameFromEnvVar = {
        grpc: 'grpc',
        'http/json': 'http',
        'http/protobuf': 'proto', // default
    };

    // Logs config.
    const logsExportProtocol =
        getStringFromEnv('OTEL_EXPORTER_OTLP_LOGS_PROTOCOL') ||
        getStringFromEnv('OTEL_EXPORTER_OTLP_PROTOCOL') ||
        'http/protobuf';
    let logExporterType = exporterPkgNameFromEnvVar[logsExportProtocol];
    if (!logExporterType) {
        log.warn(
            `Logs exporter protocol "${logsExportProtocol}" unknown. Using default "http/protobuf" protocol`
        );
        logExporterType = 'proto';
    }
    log.trace(`Logs exporter protocol set to ${logsExportProtocol}`);
    const {OTLPLogExporter} = require(
        `@opentelemetry/exporter-logs-otlp-${logExporterType}`
    );
    defaultConfig.logRecordProcessors = [
        new BatchLogRecordProcessor(new OTLPLogExporter()),
    ];

    // Metrics config.
    // TODO: support `OTEL_METRICS_EXPORTER`, including being a list of exporters (e.g. console, debug)
    // TODO: metrics exporter should do for metrics what `TracerProviderWithEnvExporters` does for traces, does that include `url` export endpoint?

    // Setting default temporality to delta to avoid histogram storing issues in ES.
    // Or log if there is a different value set by the user
    // Ref: https://github.com/elastic/opentelemetry/pull/63
    const temporalityPreference = getStringFromEnv(
        'OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE'
    );
    if (typeof temporalityPreference === 'undefined') {
        process.env.OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE = 'delta';
    } else if (temporalityPreference !== 'delta') {
        const docsUrl =
            'https://elastic.github.io/opentelemetry/compatibility/limitations.html#ingestion-of-metrics-data';
        log.info(
            `Metrics temporality preference set to "${temporalityPreference}". Use "delta" temporality if you want to store Histogram metrics in Elasticsearch. See ${docsUrl}`
        );
    }

    // The implementation in SDK does treats the undefined and 'none' value
    // as same. https://github.com/open-telemetry/opentelemetry-js/blob/dac72912b3a895c91ee95cfa39a22a916411ba4c/experimental/packages/opentelemetry-sdk-node/src/sdk.ts#L117
    // According to https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#exporter-selection
    // the default should be 'otlp' so IMHO the implementation is wrong

    // We need to set the default value if env var is not defined until it's fixed in
    // upstream SDK
    // TODO: remove this when https://github.com/open-telemetry/opentelemetry-js/issues/5612 is closed
    if (!process.env.OTEL_METRICS_EXPORTER?.trim()) {
        process.env.OTEL_METRICS_EXPORTER = 'otlp';
    }
    const metricsExporters = getStringListFromEnv('OTEL_METRICS_EXPORTER');
    const metricsEnabled = metricsExporters.every((e) => e !== 'none');
    if (metricsEnabled) {
        defaultConfig.views = [
            // Add views for `host-metrics` to avoid excess of data being sent
            // to the server.
            ...HOST_METRICS_VIEWS,
        ];
    }

    const config = Object.assign(defaultConfig, cfg);

    setupEnvironment();
    const sdk = new NodeSDK(config);

    if (config.elasticSetupShutdownHandlers ?? true) {
        setupShutdownHandlers(sdk);
    }

    log.info(
        {
            preamble: true,
            distroVersion: DISTRO_VERSION,
            env: {
                // For darwin: https://en.wikipedia.org/wiki/Darwin_%28operating_system%29#Release_history
                os: `${os.platform()} ${os.release()}`,
                arch: os.arch(),
                runtime: `Node.js ${process.version}`,
            },
            // The "config" object structure is not stable.
            config: {
                logLevel: luggite.nameFromLevel[log.level()] ?? log.level(),
            },
        },
        'start EDOT Node.js'
    );
    sdk.start(); // .start() *does* use `process.env` though I think it should not.
    restoreEnvironment();

    if (metricsEnabled) {
        // TODO: make this configurable, user might collect host metrics with a separate utility. Perhaps use 'host-metrics' in DISABLED_INSTRs existing env var.
        enableHostMetrics();
    }

    // Return an object that is a subset of the upstream NodeSDK interface,
    // just enough to shutdown.
    return {
        shutdown() {
            return sdk.shutdown();
        },
    };
}