import { monitorEventLoopDelay } from "node:perf_hooks"; import { logger, serializeError } from "../logger.js"; export const installProcessObservability = (options: { workers: () => Promise; }): void => { process.on("uncaughtException", (err) => { logger.fatal({ err: serializeError(err) }, "uncaught exception"); setTimeout(() => process.exit(1), 1_000); }); process.on("unhandledRejection", (reason) => { logger.fatal({ err: serializeError(reason) }, "unhandled rejection"); }); const eventLoopDelay = monitorEventLoopDelay({ resolution: 20 }); eventLoopDelay.enable(); const heartbeat = async (): Promise => { const memory = process.memoryUsage(); logger.info( { operation: "heartbeat", uptimeSeconds: Math.round(process.uptime()), workers: await options.workers().catch(() => -1), rssBytes: memory.rss, heapUsedBytes: memory.heapUsed, eventLoopLagMs: eventLoopDelay.mean / 1e6, }, "pinboard heartbeat", ); eventLoopDelay.reset(); }; setInterval(() => { heartbeat().catch((error) => { logger.error( { source: "heartbeat", err: serializeError(error) }, "background loop error", ); }); }, 60_000).unref(); };