UNPKG

@opentelemetry/sdk-node

Version:
315 lines 14.8 kB
"use strict"; /* * Copyright The OpenTelemetry Authors * SPDX-License-Identifier: Apache-2.0 */ Object.defineProperty(exports, "__esModule", { value: true }); exports.NodeSDK = void 0; const api_1 = require("@opentelemetry/api"); const api_logs_1 = require("@opentelemetry/api-logs"); const instrumentation_1 = require("@opentelemetry/instrumentation"); const resources_1 = require("@opentelemetry/resources"); const sdk_logs_1 = require("@opentelemetry/sdk-logs"); const exporter_logs_otlp_http_1 = require("@opentelemetry/exporter-logs-otlp-http"); const exporter_logs_otlp_grpc_1 = require("@opentelemetry/exporter-logs-otlp-grpc"); const exporter_logs_otlp_proto_1 = require("@opentelemetry/exporter-logs-otlp-proto"); const exporter_prometheus_1 = require("@opentelemetry/exporter-prometheus"); const sdk_metrics_1 = require("@opentelemetry/sdk-metrics"); const sdk_trace_1 = require("@opentelemetry/sdk-trace"); const semantic_conventions_1 = require("@opentelemetry/semantic-conventions"); const core_1 = require("@opentelemetry/core"); const utils_1 = require("./utils"); const create_from_env_1 = require("./create-from-env"); /** * * @returns MetricReader[] if appropriate environment variables are configured */ function getMetricReadersFromEnv() { const metricReaders = []; const enabledExporters = Array.from(new Set((0, core_1.getStringListFromEnv)('OTEL_METRICS_EXPORTER') ?? [])); if (enabledExporters.length === 0) { api_1.diag.debug('OTEL_METRICS_EXPORTER is empty. Using default otlp exporter.'); enabledExporters.push('otlp'); } if (enabledExporters.includes('none')) { api_1.diag.info('OTEL_METRICS_EXPORTER contains "none". Metric provider will not be initialized.'); return metricReaders; } enabledExporters.forEach(exporter => { if (exporter === 'otlp') { metricReaders.push((0, utils_1.getPeriodicExportingMetricReaderFromEnv)((0, utils_1.getOtlpMetricExporterFromEnv)())); } else if (exporter === 'console') { metricReaders.push(new sdk_metrics_1.PeriodicExportingMetricReader({ exporter: new sdk_metrics_1.ConsoleMetricExporter(), })); } else if (exporter === 'prometheus') { metricReaders.push(new exporter_prometheus_1.PrometheusExporter()); } else { api_1.diag.warn(`Unsupported OTEL_METRICS_EXPORTER value: "${exporter}". Supported values are: otlp, console, prometheus, none.`); } }); return metricReaders; } /** * A setup helper for the OpenTelemetry SDKs (logs, metrics, traces). * <p> After successful setup using {@link NodeSDK#start()}, use `@opentelemetry/api` to obtain the registered components. * <p> Use the shutdown handler {@link NodeSDK#shutdown()} to ensure your telemetry is exported before the process exits. * * @example <caption> Register SDK by using environment variables </caption> * const nodeSdk = new NodeSDK(); // providing no options uses OTEL_* environment variables for SDK setup. * nodeSdk.start(); // registers all configured SDK components * @example <caption> Override environment variable config with your own components </caption> * const nodeSdk = new NodeSDK({ * // override the list of metric reader with your own options and ignore environment variable config * // explore the docs of other options to learn more! * metricReaders: [ new PeriodicExportingMetricReader({ * exporter: new OTLPMetricsExporter() * })] * }); * nodeSdk.start(); // registers all configured SDK components */ class NodeSDK { _loggerProviderConfig; _meterProviderConfig; _instrumentations; _resource; _resourceDetectors; _autoDetectResources; _tracerProvider; _loggerProvider; _meterProvider; _serviceName; _configuration; _disabled; /** * Create a new NodeJS SDK instance */ constructor(configuration = {}) { if ((0, core_1.getBooleanFromEnv)('OTEL_SDK_DISABLED')) { this._disabled = true; // Functions with possible side-effects are set // to no-op via the _disabled flag } const logLevel = (0, core_1.getStringFromEnv)('OTEL_LOG_LEVEL'); if (logLevel != null) { api_1.diag.setLogger(new api_1.DiagConsoleLogger(), { logLevel: (0, core_1.diagLogLevelFromString)(logLevel), }); } this._configuration = configuration; this._resource = configuration.resource ?? (0, resources_1.defaultResource)(); this._autoDetectResources = configuration.autoDetectResources ?? true; if (!this._autoDetectResources) { this._resourceDetectors = []; } else if (configuration.resourceDetectors != null) { this._resourceDetectors = configuration.resourceDetectors; } else if ((0, core_1.getStringFromEnv)('OTEL_NODE_RESOURCE_DETECTORS')) { this._resourceDetectors = (0, utils_1.getResourceDetectorsFromEnv)(); } else { this._resourceDetectors = [resources_1.envDetector, resources_1.processDetector, resources_1.hostDetector]; } this._serviceName = configuration.serviceName; if (configuration.spanProcessor) { api_1.diag.warn("The 'spanProcessor' option is deprecated. Please use 'spanProcessors' instead."); } if (configuration.logRecordProcessors) { this._loggerProviderConfig = { logRecordProcessors: configuration.logRecordProcessors, }; } else if (configuration.logRecordProcessor) { this._loggerProviderConfig = { logRecordProcessors: [configuration.logRecordProcessor], }; api_1.diag.warn("The 'logRecordProcessor' option is deprecated. Please use 'logRecordProcessors' instead."); } if (configuration.metricReaders) { this._meterProviderConfig = { readers: configuration.metricReaders, views: configuration.views, }; } else if (configuration.metricReader) { this._meterProviderConfig = { readers: [configuration.metricReader], views: configuration.views, }; api_1.diag.warn("The 'metricReader' option is deprecated. Please use 'metricReaders' instead."); } else { this._meterProviderConfig = { readers: getMetricReadersFromEnv(), views: configuration.views, }; } this._instrumentations = configuration.instrumentations?.flat() ?? []; } /** * Call this method to construct SDK components and register them with the OpenTelemetry API. */ start() { if (this._disabled) { return; } (0, instrumentation_1.registerInstrumentations)({ instrumentations: this._instrumentations, }); (0, utils_1.setupContextManager)(this._configuration?.contextManager); (0, utils_1.setupPropagator)(this._configuration?.textMapPropagator === null ? null // null means don't set, so we cannot fall back to env config. : (this._configuration?.textMapPropagator ?? (0, utils_1.getPropagatorFromEnv)())); if (this._autoDetectResources) { const internalConfig = { detectors: this._resourceDetectors, }; this._resource = this._resource.merge((0, resources_1.detectResources)(internalConfig)); } this._resource = this._serviceName === undefined ? this._resource : this._resource.merge((0, resources_1.resourceFromAttributes)({ [semantic_conventions_1.ATTR_SERVICE_NAME]: this._serviceName, })); // While SDK metrics are unstable, we require an opt-in. // https://opentelemetry.io/docs/specs/semconv/otel/sdk-metrics/ const sdkMetricsEnabled = (0, core_1.getBooleanFromEnv)('OTEL_NODE_EXPERIMENTAL_SDK_METRICS'); if (this._meterProviderConfig?.readers && // only register if there is a reader, otherwise we waste compute/memory. this._meterProviderConfig.readers.length > 0) { const meterProvider = new sdk_metrics_1.MeterProvider({ resource: this._resource, views: this._meterProviderConfig?.views ?? [], readers: this._meterProviderConfig.readers, sdkMetricsEnabled, }); this._meterProvider = meterProvider; api_1.metrics.setGlobalMeterProvider(meterProvider); // TODO: This is a workaround to fix https://github.com/open-telemetry/opentelemetry-js/issues/3609 // If the MeterProvider is not yet registered when instrumentations are registered, all metrics are dropped. // This code is obsolete once https://github.com/open-telemetry/opentelemetry-js/issues/3622 is implemented. for (const instrumentation of this._instrumentations) { instrumentation.setMeterProvider(api_1.metrics.getMeterProvider()); } } // Determine `spanProcessors` from multiple possible options. let spanProcessors; if (this._configuration?.spanProcessors) { spanProcessors = this._configuration.spanProcessors; } else if (this._configuration?.spanProcessor) { spanProcessors = [this._configuration.spanProcessor]; } else if (this._configuration?.traceExporter) { spanProcessors = [ (0, create_from_env_1.createBatchSpanProcessorFromEnv)(this._configuration.traceExporter, sdkMetricsEnabled ? this._meterProvider : undefined), ]; } else { spanProcessors = (0, utils_1.getSpanProcessorsFromEnv)(sdkMetricsEnabled ? this._meterProvider : undefined); } // Only register if there is a span processor if (spanProcessors.length > 0) { this._tracerProvider = new sdk_trace_1.TracerProvider({ sampler: this._configuration?.sampler ?? (0, create_from_env_1.createSamplerFromEnv)(), spanLimits: { ...(0, create_from_env_1.createSpanLimitsFromEnv)(), ...this._configuration?.spanLimits, }, resource: this._resource, meterProvider: sdkMetricsEnabled ? this._meterProvider : undefined, idGenerator: this._configuration?.idGenerator, spanProcessors, }); api_1.trace.setGlobalTracerProvider(this._tracerProvider); } if (!this._loggerProviderConfig) { this.configureLoggerProviderFromEnv(sdkMetricsEnabled ? this._meterProvider : undefined); } if (this._loggerProviderConfig) { const loggerProvider = new sdk_logs_1.LoggerProvider({ ...(0, utils_1.getLoggerProviderConfigFromEnv)(), resource: this._resource, processors: this._loggerProviderConfig.logRecordProcessors, meterProvider: sdkMetricsEnabled ? this._meterProvider : undefined, }); this._loggerProvider = loggerProvider; api_logs_1.logs.setGlobalLoggerProvider(loggerProvider); } } shutdown() { const promises = []; if (this._tracerProvider) { promises.push(this._tracerProvider.shutdown()); } if (this._loggerProvider) { promises.push(this._loggerProvider.shutdown()); } if (this._meterProvider) { promises.push(this._meterProvider.shutdown()); } return (Promise.all(promises) // return void instead of the array from Promise.all .then(() => { })); } configureLoggerProviderFromEnv(meterProvider) { const enabledExporters = Array.from(new Set((0, core_1.getStringListFromEnv)('OTEL_LOGS_EXPORTER') ?? [])); if (enabledExporters.length === 0) { api_1.diag.debug('OTEL_LOGS_EXPORTER is empty. Using default otlp exporter.'); enabledExporters.push('otlp'); } if (enabledExporters.includes('none')) { api_1.diag.info('OTEL_LOGS_EXPORTER contains "none". Logger provider will not be initialized.'); return; } const exporters = []; enabledExporters.forEach(exporter => { if (exporter === 'otlp') { const protocol = ((0, core_1.getStringFromEnv)('OTEL_EXPORTER_OTLP_LOGS_PROTOCOL') ?? (0, core_1.getStringFromEnv)('OTEL_EXPORTER_OTLP_PROTOCOL'))?.trim() || 'http/protobuf'; // Using || to also fall back on empty string switch (protocol) { case 'grpc': exporters.push(new exporter_logs_otlp_grpc_1.OTLPLogExporter()); break; case 'http/json': exporters.push(new exporter_logs_otlp_http_1.OTLPLogExporter()); break; case 'http/protobuf': exporters.push(new exporter_logs_otlp_proto_1.OTLPLogExporter()); break; default: api_1.diag.warn(`Unsupported OTLP logs protocol: "${protocol}". Using http/protobuf.`); exporters.push(new exporter_logs_otlp_proto_1.OTLPLogExporter()); } } else if (exporter === 'console') { exporters.push(new sdk_logs_1.ConsoleLogRecordExporter()); } else { api_1.diag.warn(`Unsupported OTEL_LOGS_EXPORTER value: "${exporter}". Supported values are: otlp, console, none.`); } }); if (exporters.length > 0) { this._loggerProviderConfig = { logRecordProcessors: exporters.map(exporter => { if (exporter instanceof sdk_logs_1.ConsoleLogRecordExporter) { return new sdk_logs_1.SimpleLogRecordProcessor({ exporter, selfObsMeterProvider: meterProvider, }); } else { return (0, utils_1.getBatchLogRecordProcessorFromEnv)(exporter, meterProvider); } }), }; } } } exports.NodeSDK = NodeSDK; //# sourceMappingURL=sdk.js.map