UNPKG

@atomist/automation-client

Version:

Atomist API for software low-level client

126 lines 4.32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const appRoot = require("app-root-path"); const fs = require("fs"); const os = require("os"); const logger_1 = require("../../util/logger"); const messages_1 = require("../transport/cluster/messages"); let DataDirectory = `${appRoot.path}/heap`; /** * Initialise memory monitoring. This is will set the data directory for heap dumps and * print the head usage to the console every 60 seconds. * @param {string} dataDirectory */ function initMemoryMonitoring(dataDirectory = `${appRoot.path}/heap`, log = true) { logger_1.logger.debug("Initialising memory monitoring"); DataDirectory = dataDirectory; if (log) { setInterval(() => { logger_1.logger.debug("Memory statistics '%j'", memoryUsage()); }, 60000); } } exports.initMemoryMonitoring = initMemoryMonitoring; /** * Create a head dump that can be downloaded and used to profile head usage. * @returns {string} */ function mtrace() { try { logger_1.logger.debug("Memory statistics '%j'", memoryUsage()); const mtrace = require("mtrace"); gc(); const filename = mtrace.mtrace(); if (!!filename) { logger_1.logger.debug("mtrace dump written to '%s'", filename); } else { logger_1.logger.warn("mtrace not supported"); } messages_1.broadcast({ type: "atomist:gc" }); messages_1.broadcast({ type: "atomist:mtrace" }); return name; } catch (err) { logger_1.logger.error("Failed to initialise mtrace. Required 'mtrace' module is missing or can't be" + " loaded. Please install with 'npm install --save mtrace'"); } } exports.mtrace = mtrace; /** * Create a head dump that can be downloaded and used to profile head usage. * @returns {string} */ function heapDump() { try { logger_1.logger.debug("Memory statistics '%j'", memoryUsage()); // tslint:disable-next-line:no-implicit-dependencies const heapdump = require("heapdump"); const name = `heapdump-${process.pid}-${Date.now()}.heapsnapshot`; if (!fs.existsSync(DataDirectory)) { fs.mkdirSync(DataDirectory); } gc(); heapdump.writeSnapshot(`${DataDirectory}/${name}`, (err, filename) => { logger_1.logger.debug("Heap dump written to '%s'", filename); }); messages_1.broadcast({ type: "atomist:gc" }); messages_1.broadcast({ type: "atomist:heapdump" }); return name; } catch (err) { logger_1.logger.error("Failed to initialise memory monitoring. Required 'heapdump' module is missing or can't be" + " loaded. Please install with 'npm install --save heapdump'"); } } exports.heapDump = heapDump; /** * Get some memory statistics. * @returns {{heap: {rss: string; total: string; used: string}; memory: {free: string; total: string}; up_time: string}} */ function memoryUsage() { const mem = process.memoryUsage(); const usage = { heap: { rss: (mem.rss / 1024 / 1024).toFixed(2), total: (mem.heapTotal / 1024 / 1024).toFixed(2), used: (mem.heapUsed / 1024 / 1024).toFixed(2), }, memory: { free: (os.freemem() / 1024 / 1024).toFixed(2), total: (os.totalmem() / 1024 / 1024).toFixed(2), }, up_time: formatMillis(process.uptime() * 1000), }; return usage; } exports.memoryUsage = memoryUsage; /** * Trigger gargabe collect. * This required the process to run with --expose_gc. */ function gc() { if (global.gc) { logger_1.logger.debug("Triggering GC"); global.gc(); logger_1.logger.debug("Memory statistics: %j", memoryUsage()); messages_1.broadcast({ type: "atomist:gc" }); } } exports.gc = gc; function formatMillis(millis) { const date = new Date(millis); let str = ""; if (date.getUTCDate() > 1) { str += date.getUTCDate() - 1 + " d, "; } if (date.getUTCHours() > 0) { str += date.getUTCHours() + " hr, "; } if (date.getUTCMinutes() > 0) { str += date.getUTCMinutes() + " min, "; } str += date.getUTCSeconds() + " s"; return str; } //# sourceMappingURL=memory.js.map