nodejs/node
Diagnostics
Purpose
Give operators and APM authors observability into a running Node process: async-resource lifecycle (async_hooks, AsyncLocalStorage), library-level events (diagnostics_channel), V8/system performance counters (perf_hooks), categorical traces (trace_events), JSON crash dumps (process.report), and the V8 Inspector (--inspect).
Surfaces
| API | JS | C++ |
|---|---|---|
async_hooks |
lib/async_hooks.js, lib/internal/async_hooks.js |
src/async_wrap.cc |
AsyncLocalStorage |
lib/internal/async_local_storage/ |
src/async_context_frame.{cc,h} |
diagnostics_channel |
lib/diagnostics_channel.js |
src/node_diagnostics_channel.{cc,h} |
perf_hooks |
lib/perf_hooks.js, lib/internal/perf/ |
src/node_perf.{cc,h} |
trace_events |
lib/trace_events.js |
src/tracing/, src/node_trace_events.cc |
process.report |
exposed via lib/internal/process/report.js |
src/node_report.cc, src/node_report_module.cc |
inspector module |
lib/inspector.js, lib/internal/inspector/ |
src/inspector/, src/inspector_*.{cc,h} |
| histograms | lib/internal/histogram.js |
src/histogram.{cc,h} |
v8.startupSnapshot.* |
lib/v8.js |
src/node_snapshotable.cc |
async_hooks and AsyncWrap
Every async resource in Node — sockets, FS requests, timers, fs watchers, HTTP parsers — descends from AsyncWrap in C++. AsyncWrap assigns each resource an asyncId and a triggerAsyncId, and threads them through MakeCallback so JS callbacks always run with the correct context.
sequenceDiagram
participant Wrap as AsyncWrap (e.g. TCPWrap)
participant Hooks as async_hooks dispatch
participant Listener as user hook (init/before/after/destroy)
Wrap-->>Hooks: emitInit(asyncId, type, triggerAsyncId, resource)
Hooks->>Listener: init(asyncId, type, ...)
Wrap->>Wrap: produces I/O event
Wrap-->>Hooks: emitBefore(asyncId)
Hooks->>Listener: before(asyncId)
Wrap-->>Hooks: run JS callback
Wrap-->>Hooks: emitAfter(asyncId)
Hooks->>Listener: after(asyncId)
Wrap-->>Hooks: emitDestroy(asyncId) at GC or close
Hooks->>Listener: destroy(asyncId)User-facing API: async_hooks.createHook({ init, before, after, destroy, promiseResolve }). Hooks installed at startup are essentially free; hooks that run init on every async resource have measurable cost, so most APMs only enable a subset.
AsyncLocalStorage is the modern public API and prefers the V8 AsyncContextFrame mechanism (src/async_context_frame.cc) when available; the legacy implementation falls back to async_hooks. Implementation detail: --no-async-context-frame toggles between them.
diagnostics_channel
diagnostics_channel (lib/diagnostics_channel.js) is a publish/subscribe API tailored for "library events". A channel name is a string; the 'tracing' subscriber pattern lets subscribers see five lifecycle events (start/end/asyncStart/asyncEnd/error) for an operation.
Built-in channels published by core (see doc/api/diagnostics_channel.md for the full list):
dgram.socketnet.client.socket/net.server.socketudp.socket.bindchild_processlifecyclehttp.client.request.*,http.server.request.*,http.server.response.*node:worker_threads:create,:exittracing:net.client.connect,tracing:net.server.listen
undici publishes undici:* channels (request created, headers, error, completion), and the SQLite binding publishes node:sqlite.*.
perf_hooks
lib/perf_hooks.js exposes the WHATWG Performance API plus Node-specific marks (gc, dns, http, function, eventloop). The C++ side (src/node_perf.cc) collects the data; the histograms (src/histogram.cc) back the eventloop-delay and request-rate measurements.
Highlights:
performance.eventLoopUtilization()(aliasloopUtilization) — measured by sampling the libuv loop.monitorEventLoopDelay({ resolution })— a sliding histogram backed bynode::Histogram.PerformanceObserver— observes entries by type.
trace_events
trace_events (lib/trace_events.js) emits structured trace events in the Chrome trace format. When NODE_USE_V8_PLATFORM is on, the implementation uses the V8 TracingController and writes through src/tracing/ (which is built on perfetto when enabled). Categories include node, v8, node.fs.sync, node.http, node.console, node.async_hooks. Output goes to a JSON file (set via --trace-event-file-pattern).
process.report
--report-on-fatalerror, --report-on-signal, --report-uncaught-exception, and process.report.writeReport() all funnel through src/node_report.cc. The report is a single JSON document with: header (timestamp, pid, command line, OS, node version), JS stack, native stack, libuv handles, environment, resource usage, OS open handles, system errors, user-provided context. Use it as the post-mortem trail when crashes don't reproduce locally.
Inspector
lib/inspector.js exposes Session — a programmatic V8 inspector channel — and open, close, url, waitForDebugger. The C++ side is in src/inspector/:
inspector_agent.cc— owns the V8 inspector channel and lifecycle.inspector_io.cc,inspector_socket.cc,inspector_socket_server.cc— WebSocket/TCP transport.inspector_profiler.cc— CPU + heap profiler integration.inspector_js_api.cc— bindings for the JSinspector.Session.inspector_protocol/— generated protocol stubs (tools/inspector_protocol/runs the codegen).
Workers share the inspector router (worker_inspector.h) so DevTools can attach to a worker via the same root WebSocket URL.
Integration points
- Streams publish
tracing:channels for connect/data/error events. fshas atracing:fschannel and trace-events category.- HTTP publishes the most channels; both
httpandundiciare well covered. - AsyncLocalStorage combines with
diagnostics_channel.tracingChannel(...).traceCallbackto build per-operation context propagation that survives acrossawaits.
Entry points for modification
- New
diagnostics_channel? Pick a stable channel name, publish events, document atdoc/api/diagnostics_channel.md. - New
process.reportfield? Editsrc/node_report.cc(the writer is hand-rolled JSON) anddoc/api/report.md. - Async-hook integration for a new C++ resource? Make sure it inherits from
AsyncWrapand callsMakeCallback(src/async_wrap.cc).
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.