Files
triggerdotdev--trigger.dev/apps/webapp/app/eventLoopMonitor.server.ts
2024-06-21 12:46:46 +01:00

78 lines
1.5 KiB
TypeScript

import { createHook } from "node:async_hooks";
import { singleton } from "./utils/singleton";
import { tracer } from "./v3/tracer.server";
const THRESHOLD_NS = 1e8; // 100ms
const cache = new Map<number, { type: string; start?: [number, number] }>();
function init(asyncId: number, type: string, triggerAsyncId: number, resource: any) {
cache.set(asyncId, {
type,
});
}
function destroy(asyncId: number) {
cache.delete(asyncId);
}
function before(asyncId: number) {
const cached = cache.get(asyncId);
if (!cached) {
return;
}
cache.set(asyncId, {
...cached,
start: process.hrtime(),
});
}
function after(asyncId: number) {
const cached = cache.get(asyncId);
if (!cached) {
return;
}
cache.delete(asyncId);
if (!cached.start) {
return;
}
const diff = process.hrtime(cached.start);
const diffNs = diff[0] * 1e9 + diff[1];
if (diffNs > THRESHOLD_NS) {
const time = diffNs / 1e6; // in ms
const newSpan = tracer.startSpan("event-loop-blocked", {
startTime: new Date(new Date().getTime() - time),
attributes: {
asyncType: cached.type,
label: "EventLoopMonitor",
},
});
newSpan.end();
}
}
export const eventLoopMonitor = singleton("eventLoopMonitor", () => {
const hook = createHook({ init, before, after, destroy });
return {
enable: () => {
console.log("🥸 Initializing event loop monitor");
hook.enable();
},
disable: () => {
console.log("🥸 Disabling event loop monitor");
hook.disable();
},
};
});