UNPKG

applicationinsights

Version:

Microsoft Application Insights module for Node.js

208 lines 10.2 kB
"use strict"; // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. Object.defineProperty(exports, "__esModule", { value: true }); exports.PerformanceCounterMetrics = void 0; const os = require("os"); const api_1 = require("@opentelemetry/api"); const monitor_opentelemetry_exporter_1 = require("@azure/monitor-opentelemetry-exporter"); const sdk_metrics_1 = require("@opentelemetry/sdk-metrics"); const types_1 = require("./types"); /** * Azure Monitor PerformanceCounter Metrics */ class PerformanceCounterMetrics { /** * Creates performance counter instruments. * @param options - Distro configuration. * @param config - Application Insights configuration. */ constructor(config, options) { this._collectionInterval = 60000; // 60 seconds this._totalCount = 0; this._intervalExecutionTime = 0; this._internalConfig = config; this._lastCpus = os.cpus(); this._lastCpusProcess = os.cpus(); this._lastAppCpuUsage = process.cpuUsage(); this._lastHrtime = process.hrtime(); this._lastRequestRate = { count: this._totalCount, time: +new Date(), executionInterval: this._intervalExecutionTime, }; const meterProviderConfig = { resource: this._internalConfig.resource, }; this._meterProvider = new sdk_metrics_1.MeterProvider(meterProviderConfig); this._azureExporter = new monitor_opentelemetry_exporter_1.AzureMonitorMetricExporter(this._internalConfig.azureMonitorExporterOptions); const metricReaderOptions = { exporter: this._azureExporter, exportIntervalMillis: (options === null || options === void 0 ? void 0 : options.collectionInterval) || this._collectionInterval, }; this._metricReader = new sdk_metrics_1.PeriodicExportingMetricReader(metricReaderOptions); this._meterProvider.addMetricReader(this._metricReader); this._meter = this._meterProvider.getMeter("AzureMonitorPerformanceCountersMeter"); this._lastRequestRate = { count: 0, time: 0, executionInterval: 0 }; // Create Instruments this._requestDurationHistogram = this._meter.createHistogram(types_1.PerformanceCounterMetricNames.REQUEST_DURATION, { valueType: api_1.ValueType.DOUBLE }); this._requestRateGauge = this._meter.createObservableGauge(types_1.PerformanceCounterMetricNames.REQUEST_RATE, { description: "Incoming Requests Average Execution Time", valueType: api_1.ValueType.DOUBLE, }); this._memoryPrivateBytesGauge = this._meter.createObservableGauge(types_1.PerformanceCounterMetricNames.PRIVATE_BYTES, { description: "Amount of memory process has used in bytes", valueType: api_1.ValueType.INT }); this._memoryAvailableBytesGauge = this._meter.createObservableGauge(types_1.PerformanceCounterMetricNames.AVAILABLE_BYTES, { description: "Amount of available memory in bytes", valueType: api_1.ValueType.INT }); this._processorTimeGauge = this._meter.createObservableGauge(types_1.PerformanceCounterMetricNames.PROCESSOR_TIME, { description: "Processor time as a percentage", valueType: api_1.ValueType.DOUBLE, }); this._processTimeGauge = this._meter.createObservableGauge(types_1.PerformanceCounterMetricNames.PROCESS_TIME, { description: "Process CPU usage as a percentage", valueType: api_1.ValueType.DOUBLE, }); // Add callbacks this._requestRateGaugeCallback = this._getRequestRate.bind(this); this._memoryPrivateBytesGaugeCallback = this._getPrivateMemory.bind(this); this._memoryAvailableBytesGaugeCallback = this._getAvailableMemory.bind(this); this._processorTimeGaugeCallback = this._getProcessorTime.bind(this); this._processTimeGaugeCallback = this._getProcessTime.bind(this); this._memoryPrivateBytesGauge.addCallback(this._memoryPrivateBytesGaugeCallback); this._memoryAvailableBytesGauge.addCallback(this._memoryAvailableBytesGaugeCallback); this._processTimeGauge.addCallback(this._processTimeGaugeCallback); this._processorTimeGauge.addCallback(this._processorTimeGaugeCallback); this._requestRateGauge.addCallback(this._requestRateGaugeCallback); } /** * Shutdown Meter Provider it will return no-op Meters after being called. */ async shutdown() { return this._meterProvider.shutdown(); } /** * Force flush Meter Provider. */ async flush() { return this._meterProvider.forceFlush(); } /** *Get OpenTelemetry MeterProvider */ getMeterProvider() { return this._meterProvider; } /** * Record Span metrics */ recordSpan(span) { if (span.kind !== api_1.SpanKind.SERVER) { return; } this._totalCount++; const durationMs = span.duration[0]; this._intervalExecutionTime += durationMs; this._requestDurationHistogram.record(durationMs); } _getRequestRate(observableResult) { const currentTime = +new Date(); const intervalRequests = this._totalCount - this._lastRequestRate.count || 0; const elapsedMs = currentTime - this._lastRequestRate.time; if (elapsedMs > 0) { const elapsedSeconds = elapsedMs / 1000; const requestsPerSec = intervalRequests / elapsedSeconds; observableResult.observe(requestsPerSec); } this._lastRequestRate = { count: this._totalCount, time: currentTime, executionInterval: this._lastRequestRate.executionInterval, }; } _getPrivateMemory(observableResult) { observableResult.observe(process.memoryUsage().rss); } _getAvailableMemory(observableResult) { observableResult.observe(os.freemem()); } _getTotalCombinedCpu(cpus, lastCpus) { let totalUser = 0; let totalSys = 0; let totalNice = 0; let totalIdle = 0; let totalIrq = 0; for (let i = 0; !!cpus && i < cpus.length; i++) { const cpu = cpus[i]; const lastCpu = lastCpus[i]; const times = cpu.times; const lastTimes = lastCpu.times; // user cpu time (or) % CPU time spent in user space let user = times.user - lastTimes.user; user = user > 0 ? user : 0; // Avoid negative values totalUser += user; // system cpu time (or) % CPU time spent in kernel space let sys = times.sys - lastTimes.sys; sys = sys > 0 ? sys : 0; // Avoid negative values totalSys += sys; // user nice cpu time (or) % CPU time spent on low priority processes let nice = times.nice - lastTimes.nice; nice = nice > 0 ? nice : 0; // Avoid negative values totalNice += nice; // idle cpu time (or) % CPU time spent idle let idle = times.idle - lastTimes.idle; idle = idle > 0 ? idle : 0; // Avoid negative values totalIdle += idle; // irq (or) % CPU time spent servicing/handling hardware interrupts let irq = times.irq - lastTimes.irq; irq = irq > 0 ? irq : 0; // Avoid negative values totalIrq += irq; } const combinedTotal = totalUser + totalSys + totalNice + totalIdle + totalIrq; return { combinedTotal: combinedTotal, totalUser: totalUser, totalIdle: totalIdle, }; } _getProcessorTime(observableResult) { // this reports total ms spent in each category since the OS was booted, to calculate percent it is necessary // to find the delta since the last measurement const cpus = os.cpus(); if (cpus && cpus.length && this._lastCpus && cpus.length === this._lastCpus.length) { const cpuTotals = this._getTotalCombinedCpu(cpus, this._lastCpus); const value = cpuTotals.combinedTotal > 0 ? ((cpuTotals.combinedTotal - cpuTotals.totalIdle) / cpuTotals.combinedTotal) * 100 : 0; observableResult.observe(value); } this._lastCpus = cpus; } _getProcessTime(observableResult) { // this reports total ms spent in each category since the OS was booted, to calculate percent it is necessary // to find the delta since the last measurement const cpus = os.cpus(); if (cpus && cpus.length && this._lastCpusProcess && cpus.length === this._lastCpusProcess.length) { // Calculate % of total cpu time (user + system) this App Process used (Only supported by node v6.1.0+) let appCpuPercent = undefined; const appCpuUsage = process.cpuUsage(); const hrtime = process.hrtime(); const totalApp = appCpuUsage.user - this._lastAppCpuUsage.user + (appCpuUsage.system - this._lastAppCpuUsage.system) || 0; if (typeof this._lastHrtime !== "undefined" && this._lastHrtime.length === 2) { const elapsedTime = (hrtime[0] - this._lastHrtime[0]) * 1e6 + (hrtime[1] - this._lastHrtime[1]) / 1e3 || 0; // convert to microseconds appCpuPercent = (100 * totalApp) / (elapsedTime * cpus.length); } // Set previous this._lastAppCpuUsage = appCpuUsage; this._lastHrtime = hrtime; const cpuTotals = this._getTotalCombinedCpu(cpus, this._lastCpusProcess); const value = appCpuPercent || (cpuTotals.totalUser / cpuTotals.combinedTotal) * 100; observableResult.observe(value); } this._lastCpusProcess = cpus; } } exports.PerformanceCounterMetrics = PerformanceCounterMetrics; //# sourceMappingURL=performanceCounters.js.map