Skip to content

Commit 596bf78

Browse files
committed
Add an event loop monitor
1 parent 6ca66b7 commit 596bf78

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

apps/webapp/app/entry.server.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,4 @@ export { apiRateLimiter } from "./services/apiRateLimit.server";
186186
export { socketIo } from "./v3/handleSocketIo.server";
187187
export { wss } from "./v3/handleWebsockets.server";
188188
export { registryProxy } from "./v3/registryProxy.server";
189+
export { eventLoopMonitor } from "./eventLoopMonitor.server";
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { createHook } from "node:async_hooks";
2+
import { logger } from "./services/logger.server";
3+
import { singleton } from "./utils/singleton";
4+
5+
const THRESHOLD_NS = 1e8; // 100ms
6+
7+
const cache = new Map<number, [number, number]>();
8+
9+
function before(asyncId: number) {
10+
cache.set(asyncId, process.hrtime());
11+
}
12+
13+
function after(asyncId: number) {
14+
const cached = cache.get(asyncId);
15+
if (cached == null) {
16+
return;
17+
}
18+
cache.delete(asyncId);
19+
20+
const diff = process.hrtime(cached);
21+
const diffNs = diff[0] * 1e9 + diff[1];
22+
if (diffNs > THRESHOLD_NS) {
23+
const time = diffNs / 1e6; // in ms
24+
25+
logger.error(`Event loop was blocked for ${time}ms`, {
26+
label: "EventLoopMonitor",
27+
startTime: new Date(new Date().getTime() - time),
28+
durationMs: time,
29+
});
30+
}
31+
}
32+
33+
export const eventLoopMonitor = singleton("eventLoopMonitor", () => {
34+
console.log("🥸 Initializing event loop monitor");
35+
36+
const asyncHook = createHook({ before, after });
37+
asyncHook.enable();
38+
return asyncHook;
39+
});

0 commit comments

Comments
 (0)