UNPKG

@ledgerhq/coin-modules-monitoring

Version:
150 lines 5.08 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.measureCalls = measureCalls; /* eslint-disable @typescript-eslint/consistent-type-assertions */ const node_http_1 = __importDefault(require("node:http")); const node_https_1 = __importDefault(require("node:https")); function average(values) { return values.reduce((previous, current) => previous + current) / values.length; } function computeStats(values) { if (values.length === 0) { return { min: 0, average: 0, max: 0, p90: 0, p99: 0, p50: 0, p95: 0 }; } const sortedValues = values.slice().sort((a, b) => a - b); const valuesCount = sortedValues.length; const quantile = (p) => { const rank = Math.ceil((p / 100) * valuesCount); const index = Math.min(Math.max(rank - 1, 0), valuesCount - 1); return sortedValues[index]; }; return { min: sortedValues[0], average: average(values), max: sortedValues[valuesCount - 1], p50: quantile(50), p90: quantile(90), p95: quantile(95), p99: quantile(99), }; } function cpuPercentDelta(diffUserUs, diffSysUs, elapsedMs) { const totalMs = (diffUserUs + diffSysUs) / 1000; return elapsedMs > 0 ? (totalMs / elapsedMs) * 100 : 0; } function bytesToMB(bytes) { return bytes / (1024 * 1024); } function setImmediateInterval(fn, ms) { return setInterval((() => { fn(); return fn; })(), ms); } async function measureDuring(fn) { const cpuSamples = []; const memSamples = []; let prevCpu = process.cpuUsage(); let prevTs = Date.now(); const { rss: previousMemory } = process.memoryUsage(); const tick = () => { const now = Date.now(); const elapsed = now - prevTs; const curCpu = process.cpuUsage(); const diffUser = curCpu.user - prevCpu.user; const diffSys = curCpu.system - prevCpu.system; const cpu = cpuPercentDelta(diffUser, diffSys, elapsed); cpuSamples.push(cpu); const { rss } = process.memoryUsage(); memSamples.push(bytesToMB(Math.max(rss - previousMemory, 0))); prevCpu = curCpu; prevTs = now; }; const timer = setImmediateInterval(tick, 30); try { const result = await fn(); clearInterval(timer); return { result, cpuSamples, memSamples }; } catch (err) { clearInterval(timer); throw err; } } function createCallCounter() { const counters = {}; let started = false; const originalHttpRequest = node_http_1.default.request; const originalHttpsRequest = node_https_1.default.request; const originalFetch = globalThis.fetch; function start() { if (started) return; node_http_1.default.request = patchedRequestOnHttp; node_https_1.default.request = patchedRequestOnHttps; globalThis.fetch = patchedFetch; started = true; } function bump(url) { const key = new URL(url).hostname; counters[key] = (counters[key] ?? 0) + 1; } const patchedRequestOnHttp = (...args) => { const request = originalHttpRequest.apply(node_http_1.default, args); bump(request.protocol + "//" + request.host + request.path); return request; }; const patchedRequestOnHttps = (...args) => { const request = originalHttpsRequest.apply(node_https_1.default, args); bump(request.protocol + "//" + request.host + request.path); return request; }; const patchedFetch = (input, init) => { const url = typeof input === "string" ? input : input instanceof Request ? input.url : input.href; bump(url); return originalFetch(input, init); }; function stop() { if (!started) return; node_http_1.default.request = originalHttpRequest; node_https_1.default.request = originalHttpsRequest; globalThis.fetch = originalFetch; started = false; } function reset() { for (const k in counters) delete counters[k]; } function snapshot() { return { ...counters }; } function total() { return Object.values(counters).reduce((sum, v) => sum + v, 0); } return { start, stop, reset, snapshot, total }; } async function measureCalls(phase) { const localCounter = createCallCounter(); localCounter.reset(); localCounter.start(); try { const { result, cpuSamples, memSamples } = await measureDuring(() => phase()); localCounter.stop(); return { result, totalCalls: localCounter.total(), callsByDomain: localCounter.snapshot(), cpu: computeStats(cpuSamples), memory: computeStats(memSamples), }; } catch (err) { localCounter.stop(); throw err; } } //# sourceMappingURL=measure.js.map