lib/metrics/runtime.js (55 lines of code) (raw):

/* * Copyright Elasticsearch B.V. and other contributors where applicable. * Licensed under the BSD 2-Clause License; you may not use this file except in * compliance with the BSD 2-Clause License. */ 'use strict'; const eventLoopMonitor = require('monitor-event-loop-delay'); const activeHandles = typeof process._getActiveHandles === 'function' ? process._getActiveHandles.bind(process) : () => []; const activeRequests = typeof process._getActiveRequests === 'function' ? process._getActiveRequests.bind(process) : () => []; const eventLoopMonitorResolution = 10; class RuntimeCollector { constructor() { this.stats = { 'nodejs.handles.active': 0, 'nodejs.requests.active': 0, 'nodejs.eventloop.delay.avg.ms': 0, 'nodejs.memory.heap.allocated.bytes': 0, 'nodejs.memory.heap.used.bytes': 0, 'nodejs.memory.external.bytes': 0, 'nodejs.memory.arrayBuffers.bytes': 0, }; const monitor = eventLoopMonitor({ resolution: eventLoopMonitorResolution, }); monitor.enable(); this.loopMonitor = monitor; this.collect(); } collect(cb) { // Handles and Requests this.stats['nodejs.handles.active'] = activeHandles().length; this.stats['nodejs.requests.active'] = activeRequests().length; // Event loop const loopDelay = Math.max( 0, (this.loopMonitor.mean || 0) / 1e6 - eventLoopMonitorResolution, ); this.stats['nodejs.eventloop.delay.avg.ms'] = loopDelay; this.loopMonitor.reset(); // Memory / Heap const memoryUsage = process.memoryUsage(); this.stats['nodejs.memory.heap.allocated.bytes'] = memoryUsage.heapTotal; this.stats['nodejs.memory.heap.used.bytes'] = memoryUsage.heapUsed; this.stats['nodejs.memory.external.bytes'] = memoryUsage.external; this.stats['nodejs.memory.arrayBuffers.bytes'] = memoryUsage.arrayBuffers || 0; // Only available in NodeJS +13.0 if (cb) process.nextTick(cb); } } module.exports = function createRuntimeMetrics(registry) { const collector = new RuntimeCollector(); registry.registerCollector(collector); for (const metric of Object.keys(collector.stats)) { registry.getOrCreateGauge(metric, () => collector.stats[metric]); } };