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.

122 lines 5.31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SnapshotProfiler = void 0; exports.startSnapshotProfiling = startSnapshotProfiling; exports.stopSnapshotProfiling = stopSnapshotProfiling; exports.isSnapshotProfilingEnabled = isSnapshotProfilingEnabled; exports.snapshotSpanProcessor = snapshotSpanProcessor; exports.snapshotProfiler = snapshotProfiler; const profiling_1 = require("../../profiling"); const utils_1 = require("../../utils"); const SnapshotSpanProcessor_1 = require("./SnapshotSpanProcessor"); const OtlpHttpProfilingExporter_1 = require("../../profiling/OtlpHttpProfilingExporter"); const profiling_2 = require("../../profiling"); // After the last snapshot has ended, keep the profiler running to avoid cold starts. const LINGER_PERIOD_MS = 60000; class SnapshotProfiler { constructor(options) { var _a; this.extension = (0, profiling_2.loadExtension)() || (0, profiling_1.noopExtension)(); this.profilerHandle = -1; // The number traces currently being profiled. this.activeSnapshots = 0; (0, profiling_1.ensureProfilingContextManager)(); this.processor = new SnapshotSpanProcessor_1.SnapshotSpanProcessor({ traceSnapshotBegin: (traceId) => { this.extension.addTraceIdFilter(this.profilerHandle, traceId); this.extension.startCpuProfiler(this.profilerHandle); this.activeSnapshots += 1; }, traceSnapshotEnd: (traceId) => { this.activeSnapshots = Math.max(this.activeSnapshots - 1, 0); this.extension.removeTraceIdFilter(this.profilerHandle, traceId); if (this.stopTimeout !== undefined) { clearTimeout(this.stopTimeout); this.stopTimeout = undefined; } if (this.activeSnapshots === 0) { this.stopTimeout = setTimeout(async () => { const profile = this.extension.stop(this.profilerHandle); await this._export(profile); this.stopTimeout = undefined; }, LINGER_PERIOD_MS); this.stopTimeout.unref(); } }, }); const samplingIntervalMicroseconds = options.samplingIntervalMs * 1000; this.profilerHandle = (_a = this.extension.createCpuProfiler({ name: 'splunk-snapshot-profiler', samplingIntervalMicroseconds, maxSampleCutoffDelayMicroseconds: samplingIntervalMicroseconds / 2, recordDebugInfo: false, onlyFilteredStacktraces: true, })) !== null && _a !== void 0 ? _a : -1; this.collectionLoop = setInterval(async () => { const profile = this.extension.collect(this.profilerHandle); await this._export(profile); }, options.collectionIntervalMs); this.collectionLoop.unref(); process.on('exit', () => { this.extension.stop(this.profilerHandle); }); // Tracing needs to be started after profiling, setting up the profiling exporter // causes @grpc/grpc-js to be loaded, but to avoid any loads before tracing's setup // has finished, load it next event loop. setImmediate(() => { this.exporter = new OtlpHttpProfilingExporter_1.OtlpHttpProfilingExporter({ endpoint: options.endpoint, callstackInterval: options.samplingIntervalMs, resource: options.resource, instrumentationSource: 'snapshot', }); }); } async _export(profile) { if (!profile || !this.exporter) { return; } if (profile.stacktraces.length > 0) { await this.exporter.send(profile); } } async stop() { clearTimeout(this.stopTimeout); clearInterval(this.collectionLoop); const profile = this.extension.stop(this.profilerHandle); if (profile) { await this._export(profile); } } } exports.SnapshotProfiler = SnapshotProfiler; let profiler; function startSnapshotProfiling(options) { var _a, _b; const samplingIntervalMs = (_a = options.samplingIntervalMs) !== null && _a !== void 0 ? _a : (0, utils_1.getEnvNumber)('SPLUNK_SNAPSHOT_PROFILER_SAMPLING_INTERVAL', 1); const collectionIntervalMs = (_b = options.collectionIntervalMs) !== null && _b !== void 0 ? _b : (0, utils_1.getEnvNumber)('SPLUNK_CPU_PROFILER_COLLECTION_INTERVAL', 30000); profiler = new SnapshotProfiler({ serviceName: options.serviceName, endpoint: options.endpoint, resource: options.resource, samplingIntervalMs, collectionIntervalMs, }); } async function stopSnapshotProfiling() { if (!profiler) { return; } await profiler.stop(); } function isSnapshotProfilingEnabled() { return (0, utils_1.getEnvBoolean)('SPLUNK_SNAPSHOT_PROFILER_ENABLED', false); } function snapshotSpanProcessor() { return profiler === null || profiler === void 0 ? void 0 : profiler.processor; } function snapshotProfiler() { return profiler; } //# sourceMappingURL=Snapshots.js.map