Monitoring Node.js applications
A Node.js application is recognised by its process and monitored as a service from the first minute: is it up, has it been restarting, what does it log. Request rates on the wire and the runtime metrics that tell you the event loop is falling behind come next, and traces arrive once you apply one staged change. The agent never restarts your application on its own.
How Node.js is recognised
The node definition matches a process whose executable is node, judged by the binary
rather than the process title, so an application pm2 has renamed still matches. The pm2
daemon itself and Node processes running inside containers are skipped; up to five
distinct applications per host are fingerprinted. For each one the agent records the
binary, the script it runs, the Node version (node --version, cached per binary) and how
it is launched: a systemd unit, pm2, or a bare process no supervisor owns.
The runtime probe runs every 5 minutes, the request-rate probe and the log probes every 30 seconds, the flame graph every 5 minutes where it is enabled.
What is collected
Service state. For a systemd unit, whether it is active and how many times systemd has restarted it after a crash. For every launch mode, including pm2, the agent also counts restarts it detects itself from the process identity changing between two looks, so a pm2 restart loop shows up too.
Request rates on the wire. Where the kernel allows eBPF (virtual machines, bare metal, privileged containers), the agent watches the ports the Node process itself listens on and reports requests, 4xx, 5xx and latency percentiles per port, plus the client-side round trip to the database (3306, 5432), the cache (6379, 11211) and external HTTPS (443). No code change, no restart.
Runtime metrics, once the application is instrumented: event loop delay, event loop utilization, GC pause time and heap in use, per service.
Facts shown on the host page: binary, script, Node version, launch mode, whether the runtime is new enough for spans, and the activation state per service.
| Signal | Metric |
|---|---|
| Node applications found | svc.node.masters |
| Service active (systemd unit) | svc.node.up tagged unit |
| Crash restarts counted by the supervisor | svc.node.crash_restarts tagged unit |
| Restarts detected by process identity | svc.node.restarts_seen tagged unit |
| Share of the service running the instrumentation | svc.node.instrumented tagged unit |
| Event loop delay, mean and p99 | svc.node.nodejs_eventloop_delay_mean_ms, svc.node.nodejs_eventloop_delay_p99_ms |
| Event loop utilization, GC pause, heap | svc.node.nodejs_eventloop_utilization, svc.node.v8js_gc_duration, svc.node.v8js_memory_heap_used |
| Requests, errors and latency per listening port | apm.http.* tagged port |
| Round trip to db, cache, ext | apm.backend.* tagged component |
Names, tags and units are in the metrics reference.
Logs. The journal entries of the node and pm2 identifiers ship by default at notice
level and above; a JSON level field in the line is honoured, so a structured logger's
warnings and errors are classified as such. pm2 error logs (the *-error.log files under the pm2 home the
daemon reports) ship the same way; pm2 out logs are collected only when you switch the
service to full depth in the console.
Alerts out of the box
| Rule | Fires when | Severity | Ships |
|---|---|---|---|
| Node event loop lag high | the mean event loop delay of a service stays at 100 ms or more for 5 minutes | warning | auto |
| Service floods error logs | 50 or more error lines in 15 minutes | warning | auto |
The event loop is where every request of a Node process waits its turn; a delay that stays at 100 ms means each callback runs a tenth of a second late before any real work starts, which is what "the app feels sluggish" looks like from the inside. Five minutes rides out a GC storm or a deploy, and the incident closes only when the mean falls back under 50 ms. The rule arms itself the moment the runtime metrics start flowing, so it needs the instrumentation applied first. Thresholds and hysteresis are in the rules catalog.
Going deeper
- Traces and runtime metrics come from the OpenTelemetry Node.js auto-instrumentation,
provisioned by the agent and activated through
NODE_OPTIONS. The change is staged: a unit drop-in for systemd services, an environment file plus thepm2commands for pm2 apps, and the exact apply command is shown as an "action required". A human runs it when it suits them; the apply carries a backup and reverts itself if the service does not come back. A bare launch gets a ready-to-paste recipe instead. Node 18.19 is the floor; an older runtime is reported as blocked and nothing is staged. See APM: how it works. - CPU flame graph. Sampled with
perffrom outside the process (99 Hz, 10-second windows, up to 12 processes). It needs one launch flag in the stagedNODE_OPTIONS, so it is a separate grant, off by default: enabling it means a restart. - Logs at full depth include pm2 out logs, see Logs.
When a path is not where pm2 says it is
pm2 log paths come from the daemon's environment. If pm2 writes elsewhere:
sudo wakora --set node.pm2-logs-err=/home/app/.pm2/logs/api-error.log
Keys (pm2-logs-err, pm2-logs-out) are listed in Agent configuration.
Limitations
- Node applications inside Docker or Kubernetes are not matched by this definition (containers are excluded from host discovery); see Docker and Kubernetes for those.
- At most five applications per host are fingerprinted.
- Request rates on the wire need eBPF. Without it (an unprivileged container) there is no
access log to fall back on for Node, so
apm.http.*is absent there. - The
upandcrash_restartsmetrics exist for systemd units (and Windows services); pm2 apps getrestarts_seenonly. - Runtime metrics and the event loop rule appear only after the staged instrumentation has been applied, which is a restart of the service.
- The flame graph needs
perfinstalled, root, the launch flag, and Linux. On Windows there is no eBPF and noperf: Node there gets service state, spans, runtime metrics and logs. - Spans need Node 18.19 or newer.
Related
- Monitoring nginx and Monitoring HAProxy for the proxy in front of the application
- Monitoring PHP-FPM, the other provisioned runtime
- Features on the main site