applicationinsights
Version:
Microsoft Application Insights module for Node.js
208 lines • 10.2 kB
JavaScript
"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