"use strict"; var __assign = (this && this.__assign) || Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; Object.defineProperty(exports, "__esModule", { value: true }); var Config = require("../Library/Config"); var Context = require("../Library/Context"); var Logging = require("../Library/Logging"); var AutoCollectNativePerformance = (function () { function AutoCollectNativePerformance(client) { this._disabledMetrics = {}; // Note: Only 1 instance of this can exist. So when we reconstruct this object, // just disable old native instance and reset JS member variables if (AutoCollectNativePerformance.INSTANCE) { AutoCollectNativePerformance.INSTANCE.dispose(); } AutoCollectNativePerformance.INSTANCE = this; this._client = client; } /** * Reports if NativePerformance is able to run in this environment */ AutoCollectNativePerformance.isNodeVersionCompatible = function () { var nodeVer = process.versions.node.split("."); return parseInt(nodeVer[0]) >= 6; }; /** * Start instance of native metrics agent. * * @param {boolean} isEnabled * @param {number} [collectionInterval=60000] * @memberof AutoCollectNativePerformance */ AutoCollectNativePerformance.prototype.enable = function (isEnabled, disabledMetrics, collectionInterval) { var _this = this; if (disabledMetrics === void 0) { disabledMetrics = {}; } if (collectionInterval === void 0) { collectionInterval = 60000; } if (!AutoCollectNativePerformance.isNodeVersionCompatible()) { return; } if (AutoCollectNativePerformance._metricsAvailable == undefined && isEnabled && !this._isInitialized) { // Try to require in the native-metrics library. If it's found initialize it, else do nothing and never try again. try { var NativeMetricsEmitters = require("applicationinsights-native-metrics"); AutoCollectNativePerformance._emitter = new NativeMetricsEmitters(); AutoCollectNativePerformance._metricsAvailable = true; Logging.info("Native metrics module successfully loaded!"); } catch (err) { // Package not available. Never try again AutoCollectNativePerformance._metricsAvailable = false; return; } } this._isEnabled = isEnabled; this._disabledMetrics = disabledMetrics; if (this._isEnabled && !this._isInitialized) { this._isInitialized = true; } // Enable the emitter if we were able to construct one if (this._isEnabled && AutoCollectNativePerformance._emitter) { // enable self AutoCollectNativePerformance._emitter.enable(true, collectionInterval); this._handle = setInterval(function () { return _this._trackNativeMetrics(); }, collectionInterval); this._handle.unref(); } else if (AutoCollectNativePerformance._emitter) { // disable self AutoCollectNativePerformance._emitter.enable(false); if (this._handle) { clearInterval(this._handle); this._handle = undefined; } } }; /** * Cleanup this instance of AutoCollectNativePerformance * * @memberof AutoCollectNativePerformance */ AutoCollectNativePerformance.prototype.dispose = function () { this.enable(false); }; /** * Parse environment variable and overwrite isEnabled based on respective fields being set * * @private * @static * @param {(boolean | IDisabledExtendedMetrics)} collectExtendedMetrics * @returns {(boolean | IDisabledExtendedMetrics)} * @memberof AutoCollectNativePerformance */ AutoCollectNativePerformance.parseEnabled = function (collectExtendedMetrics) { var disableAll = process.env[Config.ENV_nativeMetricsDisableAll]; var individualOptOuts = process.env[Config.ENV_nativeMetricsDisablers]; // case 1: disable all env var set, RETURN with isEnabled=false if (disableAll) { return { isEnabled: false, disabledMetrics: {} }; } // case 2: individual env vars set, RETURN with isEnabled=true, disabledMetrics={...} if (individualOptOuts) { var optOutsArr = individualOptOuts.split(","); var disabledMetrics = {}; if (optOutsArr.length > 0) { for (var _i = 0, optOutsArr_1 = optOutsArr; _i < optOutsArr_1.length; _i++) { var opt = optOutsArr_1[_i]; disabledMetrics[opt] = true; } } // case 2a: collectExtendedMetrics is an object, overwrite existing ones if they exist if (typeof collectExtendedMetrics === "object") { return { isEnabled: true, disabledMetrics: __assign({}, collectExtendedMetrics, disabledMetrics) }; } // case 2b: collectExtendedMetrics is a boolean, set disabledMetrics as is return { isEnabled: collectExtendedMetrics, disabledMetrics: disabledMetrics }; } // case 4: no env vars set, input arg is a boolean, RETURN with isEnabled=collectExtendedMetrics, disabledMetrics={} if (typeof collectExtendedMetrics === "boolean") { return { isEnabled: collectExtendedMetrics, disabledMetrics: {} }; } else { // case 5: no env vars set, input arg is object, RETURN with isEnabled=true, disabledMetrics=collectExtendedMetrics return { isEnabled: true, disabledMetrics: collectExtendedMetrics }; } }; /** * Trigger an iteration of native metrics collection * * @private * @memberof AutoCollectNativePerformance */ AutoCollectNativePerformance.prototype._trackNativeMetrics = function () { var shouldSendAll = true; if (typeof this._isEnabled !== "object") { shouldSendAll = this._isEnabled; } if (shouldSendAll) { this._trackGarbageCollection(); this._trackEventLoop(); this._trackHeapUsage(); } }; /** * Tracks garbage collection stats for this interval. One custom metric is sent per type of garbage * collection that occurred during this collection interval. * * @private * @memberof AutoCollectNativePerformance */ AutoCollectNativePerformance.prototype._trackGarbageCollection = function () { if (this._disabledMetrics.gc) { return; } var gcData = AutoCollectNativePerformance._emitter.getGCData(); for (var gc in gcData) { var metrics = gcData[gc].metrics; var name_1 = gc + " Garbage Collection Duration"; var stdDev = Math.sqrt(metrics.sumSquares / metrics.count - Math.pow(metrics.total / metrics.count, 2)) || 0; this._client.trackMetric({ name: name_1, value: metrics.total, count: metrics.count, max: metrics.max, min: metrics.min, stdDev: stdDev, tagOverrides: (_a = {}, _a[this._client.context.keys.internalSdkVersion] = "node-nativeperf:" + Context.sdkVersion, _a) }); } var _a; }; /** * Tracks event loop ticks per interval as a custom metric. Also included in the metric is min/max/avg * time spent in event loop for this interval. * * @private * @returns {void} * @memberof AutoCollectNativePerformance */ AutoCollectNativePerformance.prototype._trackEventLoop = function () { if (this._disabledMetrics.loop) { return; } var loopData = AutoCollectNativePerformance._emitter.getLoopData(); var metrics = loopData.loopUsage; if (metrics.count == 0) { return; } var name = "Event Loop CPU Time"; var stdDev = Math.sqrt(metrics.sumSquares / metrics.count - Math.pow(metrics.total / metrics.count, 2)) || 0; this._client.trackMetric({ name: name, value: metrics.total, count: metrics.count, min: metrics.min, max: metrics.max, stdDev: stdDev, tagOverrides: (_a = {}, _a[this._client.context.keys.internalSdkVersion] = "node-nativeperf:" + Context.sdkVersion, _a) }); var _a; }; /** * Track heap memory usage metrics as a custom metric. * * @private * @memberof AutoCollectNativePerformance */ AutoCollectNativePerformance.prototype._trackHeapUsage = function () { if (this._disabledMetrics.heap) { return; } var memoryUsage = process.memoryUsage(); var heapUsed = memoryUsage.heapUsed, heapTotal = memoryUsage.heapTotal, rss = memoryUsage.rss; this._client.trackMetric({ name: "Memory Usage (Heap)", value: heapUsed, count: 1, tagOverrides: (_a = {}, _a[this._client.context.keys.internalSdkVersion] = "node-nativeperf:" + Context.sdkVersion, _a) }); this._client.trackMetric({ name: "Memory Total (Heap)", value: heapTotal, count: 1, tagOverrides: (_b = {}, _b[this._client.context.keys.internalSdkVersion] = "node-nativeperf:" + Context.sdkVersion, _b) }); this._client.trackMetric({ name: "Memory Usage (Non-Heap)", value: rss - heapTotal, count: 1, tagOverrides: (_c = {}, _c[this._client.context.keys.internalSdkVersion] = "node-nativeperf:" + Context.sdkVersion, _c) }); var _a, _b, _c; }; return AutoCollectNativePerformance; }()); exports.AutoCollectNativePerformance = AutoCollectNativePerformance; //# sourceMappingURL=NativePerformance.js.map