UNPKG

@splunk/otel

Version:

The Splunk distribution of OpenTelemetry Node Instrumentation provides a Node agent that automatically instruments your Node application to capture and report distributed traces to Splunk APM.

155 lines 6.86 kB
"use strict"; /* * Copyright Splunk Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.isTracingContextManagerEnabled = isTracingContextManagerEnabled; exports.getLoadedInstrumentations = getLoadedInstrumentations; exports.startTracing = startTracing; exports.stopTracing = stopTracing; const assert_1 = require("assert"); const api_1 = require("@opentelemetry/api"); const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node"); const instrumentation_1 = require("@opentelemetry/instrumentation"); const context_async_hooks_1 = require("@opentelemetry/context-async-hooks"); const profiling_1 = require("../profiling"); const utils_1 = require("../utils"); const Snapshots_1 = require("./snapshots/Snapshots"); const snapshots_1 = require("./snapshots"); const core_1 = require("@opentelemetry/core"); /** * We disallow calling `startTracing` twice because: * 1. This is very rarely the user intention; * 2. Causes unexpected applied configuration to OTel libs; * 3. There's no way to reliably clean up before applying new configuration. */ let isStarted = false; let tracingContextManagerEnabled = false; let _instrumentations = []; let unregisterInstrumentations = null; function isTracingContextManagerEnabled() { return tracingContextManagerEnabled; } function getLoadedInstrumentations() { return _instrumentations; } function setLoadedInstrumentations(instrumentations) { _instrumentations = []; // eslint-disable-next-line @typescript-eslint/no-explicit-any function storeInstrumentation(instrumentation) { if (typeof instrumentation['setMeterProvider'] === 'function') { _instrumentations.push(instrumentation); } } for (const option of instrumentations) { if (Array.isArray(option)) { for (const instrumentation of option) { storeInstrumentation(instrumentation); } } else { storeInstrumentation(option); } } } function startTracing(options) { (0, assert_1.strict)(!isStarted, 'Splunk APM already started'); isStarted = true; let propagator = options.propagatorFactory(options); if ((0, Snapshots_1.isSnapshotProfilingEnabled)()) { propagator = new core_1.CompositePropagator({ propagators: [ propagator, new snapshots_1.SnapshotPropagator((0, utils_1.getEnvNumber)('SPLUNK_SNAPSHOT_SELECTION_RATE', 0.01)), ], }); } api_1.propagation.setGlobalPropagator(propagator); // OpenTelemetry would log an error diagnostic when attempting to overwrite a global. // Once profiling has set its context manager, we should not attempt to overwrite it. if (!(0, profiling_1.isProfilingContextManagerSet)()) { const contextManager = new context_async_hooks_1.AsyncLocalStorageContextManager(); contextManager.enable(); api_1.context.setGlobalContextManager(contextManager); tracingContextManagerEnabled = true; } // Workaround for https://github.com/open-telemetry/opentelemetry-js/issues/3422 const envTracesExporter = process.env.OTEL_TRACES_EXPORTER; if (envTracesExporter !== undefined) { process.env.OTEL_TRACES_EXPORTER = ''; } let spanProcessors = options.spanProcessorFactory(options); if (!Array.isArray(spanProcessors)) { spanProcessors = [spanProcessors]; } if ((0, Snapshots_1.isSnapshotProfilingEnabled)()) { const processor = (0, Snapshots_1.snapshotSpanProcessor)(); if (processor !== undefined) { spanProcessors.push(processor); } } const tracerConfig = Object.assign({ spanProcessors }, options.tracerConfig); const provider = new sdk_trace_node_1.NodeTracerProvider(tracerConfig); if (envTracesExporter !== undefined) { process.env.OTEL_TRACES_EXPORTER = envTracesExporter; } // instrumentations unregisterInstrumentations = (0, instrumentation_1.registerInstrumentations)({ tracerProvider: provider, instrumentations: options.instrumentations, }); setLoadedInstrumentations(options.instrumentations); // register global provider api_1.trace.setGlobalTracerProvider(provider); return true; } async function stopTracing() { // in reality unregistering is not reliable because of the function pointers // floating around everywhere in the user code already and will lead to // unexpected consequences should it be done more than once. We enable it // mostly for tests. unregisterInstrumentations === null || unregisterInstrumentations === void 0 ? void 0 : unregisterInstrumentations(); unregisterInstrumentations = null; const shutdownPromise = shutdownGlobalTracerProvider(); api_1.propagation.disable(); if (tracingContextManagerEnabled) { api_1.context.disable(); tracingContextManagerEnabled = false; } api_1.trace.disable(); return shutdownPromise; } function isShutDownable(tracerProvider) { // eslint-disable-next-line @typescript-eslint/no-explicit-any return typeof tracerProvider.shutdown === 'function'; } async function shutdownGlobalTracerProvider() { var _a; // `shutdown` is not in the interface of TracerProvider - not always implemented // Global TracerProvider isn't actually the set TracerProvider, but a proxy const globalProvider = api_1.trace.getTracerProvider(); let reportedConstructor = globalProvider === null || globalProvider === void 0 ? void 0 : globalProvider.constructor; if (globalProvider instanceof api_1.ProxyTracerProvider) { const delegate = globalProvider.getDelegate(); reportedConstructor = delegate === null || delegate === void 0 ? void 0 : delegate.constructor; if (isShutDownable(delegate)) { return delegate.shutdown().catch((e) => { api_1.diag.warn('OpenTelemetry: error shutting down tracer provider', e); }); } } api_1.diag.warn(`Enabled TracerProvider(${(_a = reportedConstructor === null || reportedConstructor === void 0 ? void 0 : reportedConstructor.name) !== null && _a !== void 0 ? _a : reportedConstructor}) does not implement shutdown()`); } //# sourceMappingURL=index.js.map