UNPKG

faastjs

Version:

Serverless batch computing made simple.

138 lines 14.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.clearLeakDetector = exports.onAsyncHook = exports.stopAsyncTracing = exports.printHooks = exports.detectAsyncLeaks = exports.printAsyncStack = exports.trace = exports.startAsyncTracing = void 0; const asyncHooks = require("async_hooks"); const util_1 = require("util"); let hook; const asyncObjects = new Map(); const objectMapping = new Map(); function startAsyncTracing(stackTraces = false) { hook = onAsyncHook(stackTraces); } exports.startAsyncTracing = startAsyncTracing; function trace(obj) { let res = objectMapping.get(obj); if (!res) { // console.log(`trace: object not found: ${util.inspect(obj)}`); return; } let asyncTrace = `== Tracing leaked object ${res.asyncId} ==`; while (res) { const { stack, ...rest } = res; asyncTrace += `${(0, util_1.inspect)(rest)}\n${stack}`; res = asyncObjects.get(res.triggerId); } console.log(asyncTrace); return { obj, trace: asyncTrace }; } exports.trace = trace; function printAsyncStack() { console.log(`Async stack:`); let res = asyncObjects.get(asyncHooks.executionAsyncId()); while (res) { const { stack, ...rest } = res; console.log(`%O\n${stack}`, rest); res = asyncObjects.get(res.triggerId); } } exports.printAsyncStack = printAsyncStack; function detectAsyncLeaks() { const leaks = []; process._getActiveHandles().forEach((h) => { if (h !== process.stdout && h !== process.stderr) { const leak = trace(h); leak && leaks.push(leak); } }); process._getActiveRequests().forEach((h) => { const leak = trace(h); leak && leaks.push(leak); }); return leaks; } exports.detectAsyncLeaks = detectAsyncLeaks; function printHooks() { for (const obj of asyncObjects) { console.log(`%O`, obj); } } exports.printHooks = printHooks; function stopAsyncTracing() { hook?.(); } exports.stopAsyncTracing = stopAsyncTracing; function onAsyncHook(stackTraces) { const hooks = { init, before, after, destroy, promiseResolve }; const asyncHook = asyncHooks.createHook(hooks); asyncHook.enable(); return () => { asyncHook.disable(); }; function init(asyncId, type, triggerId, resource) { const obj = { asyncId, type, triggerId, resource, state: "init", startedCount: 0, finishedCount: 0, stack: stackTraces ? new Error("stack:").stack.replace(/Error:/, "") : undefined }; asyncObjects.set(asyncId, obj); objectMapping.set(resource, obj); } function destroy(asyncId) { const obj = asyncObjects.get(asyncId); if (obj) { obj.state = "destroyed"; } else { // console.log(`destroyed: No obj ${asyncId}`); } } function before(asyncId) { const obj = asyncObjects.get(asyncId); if (obj) { obj.state = "before"; obj.startedCount++; } else { // console.log(`before: No obj ${asyncId}`); } } function after(asyncId) { const obj = asyncObjects.get(asyncId); if (obj) { obj.state = "after"; obj.finishedCount++; } else { // console.log(`after: No obj ${asyncId}`); } } function promiseResolve(asyncId) { const obj = asyncObjects.get(asyncId); if (obj) { obj.state = "resolved"; } else { // console.log(`resolved: No obj ${asyncId}`); } } } exports.onAsyncHook = onAsyncHook; function clearLeakDetector() { asyncObjects.clear(); objectMapping.clear(); } exports.clearLeakDetector = clearLeakDetector; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHJhY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsMENBQTBDO0FBQzFDLCtCQUErQjtBQUUvQixJQUFJLElBQTRCLENBQUM7QUFlakMsTUFBTSxZQUFZLEdBQTZCLElBQUksR0FBRyxFQUFFLENBQUM7QUFDekQsTUFBTSxhQUFhLEdBQTZCLElBQUksR0FBRyxFQUFFLENBQUM7QUFFMUQsU0FBZ0IsaUJBQWlCLENBQUMsY0FBdUIsS0FBSztJQUMxRCxJQUFJLEdBQUcsV0FBVyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0FBQ3BDLENBQUM7QUFGRCw4Q0FFQztBQU9ELFNBQWdCLEtBQUssQ0FBQyxHQUFXO0lBQzdCLElBQUksR0FBRyxHQUFHLGFBQWEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDakMsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNOLGdFQUFnRTtRQUNoRSxPQUFPO0tBQ1Y7SUFDRCxJQUFJLFVBQVUsR0FBRyw0QkFBNEIsR0FBRyxDQUFDLE9BQU8sS0FBSyxDQUFDO0lBQzlELE9BQU8sR0FBRyxFQUFFO1FBQ1IsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLElBQUksRUFBRSxHQUFHLEdBQUcsQ0FBQztRQUMvQixVQUFVLElBQUksR0FBRyxJQUFBLGNBQU8sRUFBQyxJQUFJLENBQUMsS0FBSyxLQUFLLEVBQUUsQ0FBQztRQUMzQyxHQUFHLEdBQUcsWUFBWSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7S0FDekM7SUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3hCLE9BQU8sRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxDQUFDO0FBQ3RDLENBQUM7QUFkRCxzQkFjQztBQUVELFNBQWdCLGVBQWU7SUFDM0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FB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UUFDdEMsSUFBSSxHQUFHLEVBQUU7WUFDTCxHQUFHLENBQUMsS0FBSyxHQUFHLFdBQVcsQ0FBQztTQUMzQjthQUFNO1lBQ0gsK0NBQStDO1NBQ2xEO0lBQ0wsQ0FBQztJQUNELFNBQVMsTUFBTSxDQUFDLE9BQWU7UUFDM0IsTUFBTSxHQUFHLEdBQUcsWUFBWSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN0QyxJQUFJLEdBQUcsRUFBRTtZQUNMLEdBQUcsQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFDO1lBQ3JCLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztTQUN0QjthQUFNO1lBQ0gsNENBQTRDO1NBQy9DO0lBQ0wsQ0FBQztJQUNELFNBQVMsS0FBSyxDQUFDLE9BQWU7UUFDMUIsTUFBTSxHQUFHLEdBQUcsWUFBWSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN0QyxJQUFJLEdBQUcsRUFBRTtZQUNMLEdBQUcsQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDO1lBQ3BCLEdBQUcsQ0FBQyxhQUFhLEVBQUUsQ0FBQztTQUN2QjthQUFNO1lBQ0gsMkNBQTJDO1NBQzlDO0lBQ0wsQ0FBQztJQUNELFNBQVMsY0FBYyxDQUFDLE9BQWU7UUFDbkMsTUFBTSxHQUFHLEdBQUcsWUFBWSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN0QyxJQUFJLEdBQUcsRUFBRTtZQUNMLEdBQUcsQ0FBQyxLQUFLLEdBQUcsVUFBVSxDQUFDO1NBQzFCO2FBQU07WUFDSCw4Q0FBOEM7U0FDakQ7SUFDTCxDQUFDO0FBQ0wsQ0FBQztBQWxFRCxrQ0FrRUM7QUFFRCxTQUFnQixpQkFBaUI7SUFDN0IsWUFBWSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3JCLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztBQUMxQixDQUFDO0FBSEQsOENBR0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBhc3luY0hvb2tzIGZyb20gXCJhc3luY19ob29rc1wiO1xuaW1wb3J0IHsgaW5zcGVjdCB9IGZyb20gXCJ1dGlsXCI7XG5cbmxldCBob29rOiAoKSA9PiB2b2lkIHwgdW5kZWZpbmVkO1xuXG50eXBlIEFzeW5jU3RhdGUgPSBcImluaXRcIiB8IFwiYmVmb3JlXCIgfCBcImFmdGVyXCIgfCBcImRlc3Ryb3llZFwiIHwgXCJyZXNvbHZlZFwiO1xuXG5pbnRlcmZhY2UgQXN5bmNPYmplY3Qge1xuICAgIGFzeW5jSWQ6IG51bWJlcjtcbiAgICB0eXBlOiBzdHJpbmc7XG4gICAgdHJpZ2dlcklkOiBudW1iZXI7XG4gICAgcmVzb3VyY2U6IGFueTtcbiAgICBzdGF0ZTogQXN5bmNTdGF0ZTtcbiAgICBzdGFydGVkQ291bnQ6IG51bWJlcjtcbiAgICBmaW5pc2hlZENvdW50OiBudW1iZXI7XG4gICAgc3RhY2s/OiBzdHJpbmc7XG59XG5cbmNvbnN0IGFzeW5jT2JqZWN0czogTWFwPG51bWJlciwgQXN5bmNPYmplY3Q+ID0gbmV3IE1hcCgpO1xuY29uc3Qgb2JqZWN0TWFwcGluZzogTWFwPG9iamVjdCwgQXN5bmNPYmplY3Q+ID0gbmV3IE1hcCgpO1xuXG5leHBvcnQgZnVuY3Rpb24gc3RhcnRBc3luY1RyYWNpbmcoc3RhY2tUcmFjZXM6IGJvb2xlYW4gPSBmYWxzZSkge1xuICAgIGhvb2sgPSBvbkFzeW5jSG9vayhzdGFja1RyYWNlcyk7XG59XG5cbmludGVyZmFjZSBUcmFjZSB7XG4gICAgb2JqOiBvYmplY3Q7XG4gICAgdHJhY2U6IHN0cmluZztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYWNlKG9iajogb2JqZWN0KTogVHJhY2UgfCB2b2lkIHtcbiAgICBsZXQgcmVzID0gb2JqZWN0TWFwcGluZy5nZXQob2JqKTtcbiAgICBpZiAoIXJlcykge1xuICAgICAgICAvLyBjb25zb2xlLmxvZyhgdHJhY2U6IG9iamVjdCBub3QgZm91bmQ6ICR7dXRpbC5pbnNwZWN0KG9iail9YCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGV0IGFzeW5jVHJhY2UgPSBgPT0gVHJhY2luZyBsZWFrZWQgb2JqZWN0ICR7cmVzLmFzeW5jSWR9ID09YDtcbiAgICB3aGlsZSAocmVzKSB7XG4gICAgICAgIGNvbnN0IHsgc3RhY2ssIC4uLnJlc3QgfSA9IHJlcztcbiAgICAgICAgYXN5bmNUcmFjZSArPSBgJHtpbnNwZWN0KHJlc3QpfVxcbiR7c3RhY2t9YDtcbiAgICAgICAgcmVzID0gYXN5bmNPYmplY3RzLmdldChyZXMudHJpZ2dlcklkKTtcbiAgICB9XG4gICAgY29uc29sZS5sb2coYXN5bmNUcmFjZSk7XG4gICAgcmV0dXJuIHsgb2JqLCB0cmFjZTogYXN5bmNUcmFjZSB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJpbnRBc3luY1N0YWNrKCkge1xuICAgIGNvbnNvbGUubG9nKGBBc3luYyBzdGFjazpgKTtcbiAgICBsZXQgcmVzID0gYXN5bmNPYmplY3RzLmdldChhc3luY0hvb2tzLmV4ZWN1dGlvbkFzeW5jSWQoKSk7XG4gICAgd2hpbGUgKHJlcykge1xuICAgICAgICBjb25zdCB7IHN0YWNrLCAuLi5yZXN0IH0gPSByZXM7XG4gICAgICAgIGNvbnNvbGUubG9nKGAlT1xcbiR7c3RhY2t9YCwgcmVzdCk7XG4gICAgICAgIHJlcyA9IGFzeW5jT2JqZWN0cy5nZXQocmVzLnRyaWdnZXJJZCk7XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZGV0ZWN0QXN5bmNMZWFrcygpOiBvYmplY3RbXSB7XG4gICAgY29uc3QgbGVha3M6IFRyYWNlW10gPSBbXTtcbiAgICAocHJvY2VzcyBhcyBhbnkpLl9nZXRBY3RpdmVIYW5kbGVzKCkuZm9yRWFjaCgoaDogb2JqZWN0KSA9PiB7XG4gICAgICAgIGlmIChoICE9PSBwcm9jZXNzLnN0ZG91dCAmJiBoICE9PSBwcm9jZXNzLnN0ZGVycikge1xuICAgICAgICAgICAgY29uc3QgbGVhayA9IHRyYWNlKGgpO1xuICAgICAgICAgICAgbGVhayAmJiBsZWFrcy5wdXNoKGxlYWspO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgKHByb2Nlc3MgYXMgYW55KS5fZ2V0QWN0aXZlUmVxdWVzdHMoKS5mb3JFYWNoKChoOiBvYmplY3QpID0+IHtcbiAgICAgICAgY29uc3QgbGVhayA9IHRyYWNlKGgpO1xuICAgICAgICBsZWFrICYmIGxlYWtzLnB1c2gobGVhayk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGxlYWtzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJpbnRIb29rcygpIHtcbiAgICBmb3IgKGNvbnN0IG9iaiBvZiBhc3luY09iamVjdHMpIHtcbiAgICAgICAgY29uc29sZS5sb2coYCVPYCwgb2JqKTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdG9wQXN5bmNUcmFjaW5nKCkge1xuICAgIGhvb2s/LigpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gb25Bc3luY0hvb2soc3RhY2tUcmFjZXM6IGJvb2xlYW4pIHtcbiAgICBjb25zdCBob29rczogYXN5bmNIb29rcy5Ib29rQ2FsbGJhY2tzID0ge1xuICAgICAgICBpbml0LFxuICAgICAgICBiZWZvcmUsXG4gICAgICAgIGFmdGVyLFxuICAgICAgICBkZXN0cm95LFxuICAgICAgICBwcm9taXNlUmVzb2x2ZVxuICAgIH07XG5cbiAgICBjb25zdCBhc3luY0hvb2sgPSBhc3luY0hvb2tzLmNyZWF0ZUhvb2soaG9va3MpO1xuICAgIGFzeW5jSG9vay5lbmFibGUoKTtcblxuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgIGFzeW5jSG9vay5kaXNhYmxlKCk7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGluaXQoYXN5bmNJZDogbnVtYmVyLCB0eXBlOiBzdHJpbmcsIHRyaWdnZXJJZDogbnVtYmVyLCByZXNvdXJjZTogb2JqZWN0KSB7XG4gICAgICAgIGNvbnN0IG9iajogQXN5bmNPYmplY3QgPSB7XG4gICAgICAgICAgICBhc3luY0lkLFxuICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgIHRyaWdnZXJJZCxcbiAgICAgICAgICAgIHJlc291cmNlLFxuICAgICAgICAgICAgc3RhdGU6IFwiaW5pdFwiLFxuICAgICAgICAgICAgc3RhcnRlZENvdW50OiAwLFxuICAgICAgICAgICAgZmluaXNoZWRDb3VudDogMCxcbiAgICAgICAgICAgIHN0YWNrOiBzdGFja1RyYWNlc1xuICAgICAgICAgICAgICAgID8gbmV3IEVycm9yKFwic3RhY2s6XCIpLnN0YWNrIS5yZXBsYWNlKC9FcnJvcjovLCBcIlwiKVxuICAgICAgICAgICAgICAgIDogdW5kZWZpbmVkXG4gICAgICAgIH07XG4gICAgICAgIGFzeW5jT2JqZWN0cy5zZXQoYXN5bmNJZCwgb2JqKTtcbiAgICAgICAgb2JqZWN0TWFwcGluZy5zZXQocmVzb3VyY2UsIG9iaik7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGRlc3Ryb3koYXN5bmNJZDogbnVtYmVyKSB7XG4gICAgICAgIGNvbnN0IG9iaiA9IGFzeW5jT2JqZWN0cy5nZXQoYXN5bmNJZCk7XG4gICAgICAgIGlmIChvYmopIHtcbiAgICAgICAgICAgIG9iai5zdGF0ZSA9IFwiZGVzdHJveWVkXCI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhgZGVzdHJveWVkOiBObyBvYmogJHthc3luY0lkfWApO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIGJlZm9yZShhc3luY0lkOiBudW1iZXIpIHtcbiAgICAgICAgY29uc3Qgb2JqID0gYXN5bmNPYmplY3RzLmdldChhc3luY0lkKTtcbiAgICAgICAgaWYgKG9iaikge1xuICAgICAgICAgICAgb2JqLnN0YXRlID0gXCJiZWZvcmVcIjtcbiAgICAgICAgICAgIG9iai5zdGFydGVkQ291bnQrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKGBiZWZvcmU6IE5vIG9iaiAke2FzeW5jSWR9YCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gYWZ0ZXIoYXN5bmNJZDogbnVtYmVyKSB7XG4gICAgICAgIGNvbnN0IG9iaiA9IGFzeW5jT2JqZWN0cy5nZXQoYXN5bmNJZCk7XG4gICAgICAgIGlmIChvYmopIHtcbiAgICAgICAgICAgIG9iai5zdGF0ZSA9IFwiYWZ0ZXJcIjtcbiAgICAgICAgICAgIG9iai5maW5pc2hlZENvdW50Kys7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhgYWZ0ZXI6IE5vIG9iaiAke2FzeW5jSWR9YCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gcHJvbWlzZVJlc29sdmUoYXN5bmNJZDogbnVtYmVyKSB7XG4gICAgICAgIGNvbnN0IG9iaiA9IGFzeW5jT2JqZWN0cy5nZXQoYXN5bmNJZCk7XG4gICAgICAgIGlmIChvYmopIHtcbiAgICAgICAgICAgIG9iai5zdGF0ZSA9IFwicmVzb2x2ZWRcIjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKGByZXNvbHZlZDogTm8gb2JqICR7YXN5bmNJZH1gKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNsZWFyTGVha0RldGVjdG9yKCkge1xuICAgIGFzeW5jT2JqZWN0cy5jbGVhcigpO1xuICAgIG9iamVjdE1hcHBpbmcuY2xlYXIoKTtcbn1cbiJdfQ==