UNPKG

faastjs

Version:

Serverless batch computing made simple.

139 lines 14.6 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 tslib_1 = require("tslib"); const async_hooks_1 = tslib_1.__importDefault(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(async_hooks_1.default.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 = async_hooks_1.default.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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHJhY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLHNFQUFxQztBQUNyQywrQkFBK0I7QUFFL0IsSUFBSSxJQUE0QixDQUFDO0FBZWpDLE1BQU0sWUFBWSxHQUE2QixJQUFJLEdBQUcsRUFBRSxDQUFDO0FBQ3pELE1BQU0sYUFBYSxHQUE2QixJQUFJLEdBQUcsRUFBRSxDQUFDO0FBRTFELFNBQWdCLGlCQUFpQixDQUFDLGNBQXVCLEtBQUs7SUFDMUQsSUFBSSxHQUFHLFdBQVcsQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUNwQyxDQUFDO0FBRkQsOENBRUM7QUFPRCxTQUFnQixLQUFLLENBQUMsR0FBVztJQUM3QixJQUFJLEdBQUcsR0FBRyxhQUFhLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ2pDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNQLGdFQUFnRTtRQUNoRSxPQUFPO0lBQ1gsQ0FBQztJQUNELElBQUksVUFBVSxHQUFHLDRCQUE0QixHQUFHLENBQUMsT0FBTyxLQUFLLENBQUM7SUFDOUQsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNULE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxJQUFJLEVBQUUsR0FBRyxHQUFHLENBQUM7UUFDL0IsVUFBVSxJQUFJLEdBQUcsSUFBQSxjQUFPLEVBQUMsSUFBSSxDQUFDLEtBQUssS0FBSyxFQUFFLENBQUM7UUFDM0MsR0FBRyxHQUFHLFlBQVksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3hCLE9BQU8sRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxDQUFDO0FBQ3RDLENBQUM7QUFkRCxzQkFjQztBQUVELFNBQWdCLGVBQWU7SUFDM0IsT0FBTyxDQUFDLEdB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LENBQUMsS0FBSyxFQUFFLENBQUM7QUFDMUIsQ0FBQztBQUhELDhDQUdDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGFzeW5jSG9va3MgZnJvbSBcImFzeW5jX2hvb2tzXCI7XG5pbXBvcnQgeyBpbnNwZWN0IH0gZnJvbSBcInV0aWxcIjtcblxubGV0IGhvb2s6ICgpID0+IHZvaWQgfCB1bmRlZmluZWQ7XG5cbnR5cGUgQXN5bmNTdGF0ZSA9IFwiaW5pdFwiIHwgXCJiZWZvcmVcIiB8IFwiYWZ0ZXJcIiB8IFwiZGVzdHJveWVkXCIgfCBcInJlc29sdmVkXCI7XG5cbmludGVyZmFjZSBBc3luY09iamVjdCB7XG4gICAgYXN5bmNJZDogbnVtYmVyO1xuICAgIHR5cGU6IHN0cmluZztcbiAgICB0cmlnZ2VySWQ6IG51bWJlcjtcbiAgICByZXNvdXJjZTogYW55O1xuICAgIHN0YXRlOiBBc3luY1N0YXRlO1xuICAgIHN0YXJ0ZWRDb3VudDogbnVtYmVyO1xuICAgIGZpbmlzaGVkQ291bnQ6IG51bWJlcjtcbiAgICBzdGFjaz86IHN0cmluZztcbn1cblxuY29uc3QgYXN5bmNPYmplY3RzOiBNYXA8bnVtYmVyLCBBc3luY09iamVjdD4gPSBuZXcgTWFwKCk7XG5jb25zdCBvYmplY3RNYXBwaW5nOiBNYXA8b2JqZWN0LCBBc3luY09iamVjdD4gPSBuZXcgTWFwKCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFydEFzeW5jVHJhY2luZyhzdGFja1RyYWNlczogYm9vbGVhbiA9IGZhbHNlKSB7XG4gICAgaG9vayA9IG9uQXN5bmNIb29rKHN0YWNrVHJhY2VzKTtcbn1cblxuaW50ZXJmYWNlIFRyYWNlIHtcbiAgICBvYmo6IG9iamVjdDtcbiAgICB0cmFjZTogc3RyaW5nO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHJhY2Uob2JqOiBvYmplY3QpOiBUcmFjZSB8IHZvaWQge1xuICAgIGxldCByZXMgPSBvYmplY3RNYXBwaW5nLmdldChvYmopO1xuICAgIGlmICghcmVzKSB7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKGB0cmFjZTogb2JqZWN0IG5vdCBmb3VuZDogJHt1dGlsLmluc3BlY3Qob2JqKX1gKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgYXN5bmNUcmFjZSA9IGA9PSBUcmFjaW5nIGxlYWtlZCBvYmplY3QgJHtyZXMuYXN5bmNJZH0gPT1gO1xuICAgIHdoaWxlIChyZXMpIHtcbiAgICAgICAgY29uc3QgeyBzdGFjaywgLi4ucmVzdCB9ID0gcmVzO1xuICAgICAgICBhc3luY1RyYWNlICs9IGAke2luc3BlY3QocmVzdCl9XFxuJHtzdGFja31gO1xuICAgICAgICByZXMgPSBhc3luY09iamVjdHMuZ2V0KHJlcy50cmlnZ2VySWQpO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZyhhc3luY1RyYWNlKTtcbiAgICByZXR1cm4geyBvYmosIHRyYWNlOiBhc3luY1RyYWNlIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcmludEFzeW5jU3RhY2soKSB7XG4gICAgY29uc29sZS5sb2coYEFzeW5jIHN0YWNrOmApO1xuICAgIGxldCByZXMgPSBhc3luY09iamVjdHMuZ2V0KGFzeW5jSG9va3MuZXhlY3V0aW9uQXN5bmNJZCgpKTtcbiAgICB3aGlsZSAocmVzKSB7XG4gICAgICAgIGNvbnN0IHsgc3RhY2ssIC4uLnJlc3QgfSA9IHJlcztcbiAgICAgICAgY29uc29sZS5sb2coYCVPXFxuJHtzdGFja31gLCByZXN0KTtcbiAgICAgICAgcmVzID0gYXN5bmNPYmplY3RzLmdldChyZXMudHJpZ2dlcklkKTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZXRlY3RBc3luY0xlYWtzKCk6IG9iamVjdFtdIHtcbiAgICBjb25zdCBsZWFrczogVHJhY2VbXSA9IFtdO1xuICAgIChwcm9jZXNzIGFzIGFueSkuX2dldEFjdGl2ZUhhbmRsZXMoKS5mb3JFYWNoKChoOiBvYmplY3QpID0+IHtcbiAgICAgICAgaWYgKGggIT09IHByb2Nlc3Muc3Rkb3V0ICYmIGggIT09IHByb2Nlc3Muc3RkZXJyKSB7XG4gICAgICAgICAgICBjb25zdCBsZWFrID0gdHJhY2UoaCk7XG4gICAgICAgICAgICBsZWFrICYmIGxlYWtzLnB1c2gobGVhayk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICAocHJvY2VzcyBhcyBhbnkpLl9nZXRBY3RpdmVSZXF1ZXN0cygpLmZvckVhY2goKGg6IG9iamVjdCkgPT4ge1xuICAgICAgICBjb25zdCBsZWFrID0gdHJhY2UoaCk7XG4gICAgICAgIGxlYWsgJiYgbGVha3MucHVzaChsZWFrKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbGVha3M7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcmludEhvb2tzKCkge1xuICAgIGZvciAoY29uc3Qgb2JqIG9mIGFzeW5jT2JqZWN0cykge1xuICAgICAgICBjb25zb2xlLmxvZyhgJU9gLCBvYmopO1xuICAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0b3BBc3luY1RyYWNpbmcoKSB7XG4gICAgaG9vaz8uKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvbkFzeW5jSG9vayhzdGFja1RyYWNlczogYm9vbGVhbikge1xuICAgIGNvbnN0IGhvb2tzOiBhc3luY0hvb2tzLkhvb2tDYWxsYmFja3MgPSB7XG4gICAgICAgIGluaXQsXG4gICAgICAgIGJlZm9yZSxcbiAgICAgICAgYWZ0ZXIsXG4gICAgICAgIGRlc3Ryb3ksXG4gICAgICAgIHByb21pc2VSZXNvbHZlXG4gICAgfTtcblxuICAgIGNvbnN0IGFzeW5jSG9vayA9IGFzeW5jSG9va3MuY3JlYXRlSG9vayhob29rcyk7XG4gICAgYXN5bmNIb29rLmVuYWJsZSgpO1xuXG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgYXN5bmNIb29rLmRpc2FibGUoKTtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gaW5pdChhc3luY0lkOiBudW1iZXIsIHR5cGU6IHN0cmluZywgdHJpZ2dlcklkOiBudW1iZXIsIHJlc291cmNlOiBvYmplY3QpIHtcbiAgICAgICAgY29uc3Qgb2JqOiBBc3luY09iamVjdCA9IHtcbiAgICAgICAgICAgIGFzeW5jSWQsXG4gICAgICAgICAgICB0eXBlLFxuICAgICAgICAgICAgdHJpZ2dlcklkLFxuICAgICAgICAgICAgcmVzb3VyY2UsXG4gICAgICAgICAgICBzdGF0ZTogXCJpbml0XCIsXG4gICAgICAgICAgICBzdGFydGVkQ291bnQ6IDAsXG4gICAgICAgICAgICBmaW5pc2hlZENvdW50OiAwLFxuICAgICAgICAgICAgc3RhY2s6IHN0YWNrVHJhY2VzXG4gICAgICAgICAgICAgICAgPyBuZXcgRXJyb3IoXCJzdGFjazpcIikuc3RhY2shLnJlcGxhY2UoL0Vycm9yOi8sIFwiXCIpXG4gICAgICAgICAgICAgICAgOiB1bmRlZmluZWRcbiAgICAgICAgfTtcbiAgICAgICAgYXN5bmNPYmplY3RzLnNldChhc3luY0lkLCBvYmopO1xuICAgICAgICBvYmplY3RNYXBwaW5nLnNldChyZXNvdXJjZSwgb2JqKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZGVzdHJveShhc3luY0lkOiBudW1iZXIpIHtcbiAgICAgICAgY29uc3Qgb2JqID0gYXN5bmNPYmplY3RzLmdldChhc3luY0lkKTtcbiAgICAgICAgaWYgKG9iaikge1xuICAgICAgICAgICAgb2JqLnN0YXRlID0gXCJkZXN0cm95ZWRcIjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKGBkZXN0cm95ZWQ6IE5vIG9iaiAke2FzeW5jSWR9YCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gYmVmb3JlKGFzeW5jSWQ6IG51bWJlcikge1xuICAgICAgICBjb25zdCBvYmogPSBhc3luY09iamVjdHMuZ2V0KGFzeW5jSWQpO1xuICAgICAgICBpZiAob2JqKSB7XG4gICAgICAgICAgICBvYmouc3RhdGUgPSBcImJlZm9yZVwiO1xuICAgICAgICAgICAgb2JqLnN0YXJ0ZWRDb3VudCsrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coYGJlZm9yZTogTm8gb2JqICR7YXN5bmNJZH1gKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBhZnRlcihhc3luY0lkOiBudW1iZXIpIHtcbiAgICAgICAgY29uc3Qgb2JqID0gYXN5bmNPYmplY3RzLmdldChhc3luY0lkKTtcbiAgICAgICAgaWYgKG9iaikge1xuICAgICAgICAgICAgb2JqLnN0YXRlID0gXCJhZnRlclwiO1xuICAgICAgICAgICAgb2JqLmZpbmlzaGVkQ291bnQrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKGBhZnRlcjogTm8gb2JqICR7YXN5bmNJZH1gKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBwcm9taXNlUmVzb2x2ZShhc3luY0lkOiBudW1iZXIpIHtcbiAgICAgICAgY29uc3Qgb2JqID0gYXN5bmNPYmplY3RzLmdldChhc3luY0lkKTtcbiAgICAgICAgaWYgKG9iaikge1xuICAgICAgICAgICAgb2JqLnN0YXRlID0gXCJyZXNvbHZlZFwiO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coYHJlc29sdmVkOiBObyBvYmogJHthc3luY0lkfWApO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY2xlYXJMZWFrRGV0ZWN0b3IoKSB7XG4gICAgYXN5bmNPYmplY3RzLmNsZWFyKCk7XG4gICAgb2JqZWN0TWFwcGluZy5jbGVhcigpO1xufVxuIl19