Chỉ số cần theo dõi là event loop delay (lag): khoảng chênh giữa thời điểm một timer đáng lẽ chạy và thời điểm nó thực sự chạy. Lag cao nghĩa là có việc đồng bộ đang giữ thread — và nó tương quan trực tiếp với đuôi latency p99 của API.
Node có API sẵn trong perf_hooks:
import { monitorEventLoopDelay } from 'node:perf_hooks'
const histogram = monitorEventLoopDelay({ resolution: 20 })
histogram.enable()
setInterval(() => {
metrics.gauge('event_loop_delay_p99_ms', histogram.percentile(99) / 1e6)
metrics.gauge('event_loop_delay_max_ms', histogram.max / 1e6)
histogram.reset()
}, 10_000).unref()Giá trị trả về tính bằng nanosecond, nên phải chia 1e6 để ra millisecond.
Đọc số thế nào: lag ở mức vài millisecond là bình thường. p99 vượt khoảng 100ms nghĩa là có handler đồng bộ đủ nặng để ảnh hưởng người dùng. Nên báo động theo p99 và max, không phải mean — trung bình che mất đúng các đợt nghẽn cần tìm.
Hạn chế cần biết: trong lúc event loop bị chặn thì không có mẫu nào được lấy, nên histogram bị lệch về phía các giá trị nhỏ và có thể báo nhẹ hơn thực tế. Vì vậy nên kết hợp thêm:
- Thời gian xử lý theo route (server-timing hoặc middleware đo thủ công) để khoanh vùng handler.
- Khi đã khoanh được, chạy CPU profile (node --cpu-prof, clinic flame hoặc Chrome DevTools Profiler) để tìm hàm đồng bộ tốn thời gian nhất.
Các nguồn chặn hay gặp: JSON.parse/JSON.stringify payload lớn, regex bị catastrophic backtracking, hash mật khẩu chạy đồng bộ, fs.*Sync trong đường xử lý request, và render template cho danh sách lớn.