# Node.js Diagnostic Capture

yCrash extends its diagnostic capture capabilities to Node.js applications, bringing the same troubleshooting workflow yCrash already provides for Java and .NET. Once configured, yCrash can capture a detailed snapshot of a running Node.js process: memory and resource usage, event loop health, unhandled promise rejections, loaded npm packages, garbage collection activity, and more. This data appears alongside your existing yCrash report, in a dedicated Node.js Internals section, so your team can triage Node.js incidents with the same tools it already uses for Java and .NET.

No changes to your application's source code are required. Node.js diagnostics are captured using the yc-360 script, the same lightweight executable already used for Java and .NET monitoring.

# How Node.js Diagnostics Are Captured

yCrash supports two independent ways of capturing diagnostics from a Node.js process. They differ in how much data they can capture and in what they require from your application's deployment configuration.

  • Hook Mode (recommended): a small script loaded directly into your Node.js process at startup. It captures the full diagnostic set and requires a one time startup configuration change.
  • Signal Mode (fallback): relies only on Node.js's own built in diagnostic flags, with no hook file involved. It captures a reduced set of artifacts and exists for environments where changing startup configuration isn't an option.

Choose Hook Mode unless you have a specific reason to fall back to Signal Mode.

Hook Mode (Recommended)

Hook Mode loads a small, dependency free file (the yCrash Node.js hook, yc360-node-hook.js) into your application process at startup, using Node's native --require mechanism. Because it runs inside your process, it can reach data that's only available to in process instrumentation: the event loop, the module registry, V8's CPU profiler, and more. It communicates with the yc-360 script over a local, access controlled channel (a Unix domain socket on Linux and macOS, a named pipe on Windows) and never opens a network port.

Configuring Hook Mode

  1. Get the hook file. It ships as part of the yc-360 package, inside a nodejs folder alongside the Linux, macOS, and Windows script folders.
  2. Enable the hook by adding one environment variable to your application's startup configuration, then restart the application once:
# Linux / macOS
export NODE_OPTIONS="--require=/path/to/nodejs/yc360-node-hook.js"
1
2
REM Windows
set NODE_OPTIONS=--require=C:\path\to\nodejs\yc360-node-hook.js
1
2

This is the same integration pattern used by most Node.js monitoring and APM agents: a single environment variable, set once at deployment time. No code changes and no npm dependency are required.

  1. Optional: use a dedicated runtime directory. By default, the hook stores a small amount of local state (a registration file and an access token) in your system's temp directory. In production, especially if the yc-360 script runs as a different system user than your application, point both sides at a dedicated directory instead:
    • On your application, set YC360_NODE_RUNTIME_DIR as an environment variable, the same way you set NODE_OPTIONS above.
    • On the yc-360 script, set the identical value, either as the same YC360_NODE_RUNTIME_DIR environment variable or via the nodejsRuntimeDir argument.

Both sides must resolve to the exact same directory for the script to find the hook's registration files.

What Hook Mode captures

  • Process Overview: environment variables (sensitive values masked), CPU and memory usage, Node.js version and runtime configuration, and active libuv handles.
  • Call Stack: a snapshot of what your application's main thread was executing at capture time.
  • Event Loop Lag: second by second event loop responsiveness over the capture window, with automatic spike detection.
  • Unhandled Promise Rejections: every unhandled rejection observed during the capture window, with its reason and stack trace.
  • Module Inventory: every distinct npm package loaded, with version, file count, and install path.
  • Active Handles and Requests Growth: a time series of open sockets, timers, and other active resources, often the earliest visible signal of a resource leak.
  • Heap Summary: a lightweight, near instant snapshot of V8 heap statistics. This is not a full heap dump.
  • CPU Profile: a V8 sampling CPU profile for deep performance investigation.
  • GC Log: garbage collection activity, either continuously (when the application is started with --trace-gc) or captured on demand for a bounded window. See Configuring Continuous GC Log Capture below.

Every section above is captured automatically. There's nothing additional to enable on the yc-360 script side beyond the modes covered in Capturing Node.js Diagnostics.

Data privacy and security

  • Command line arguments are never captured. Applications sometimes receive credentials as command line arguments, so the hook excludes process.argv entirely from every artifact it produces.
  • Secret looking environment variables are fully masked before anything touches disk. Any environment variable whose name suggests a password, token, API key, credential, or certificate is completely masked. The unmasked value never leaves your application's memory.
  • Only engine level flags are captured for tuning context, such as --max-old-space-size, never application specific arguments.
  • Communication is entirely local. The hook never opens a network port. It talks to the yc-360 script over a local socket, protected by a locally generated access token that only your yc-360 script can read.
Signal Mode (Fallback)

Signal Mode uses only Node.js's own built in diagnostic flags, with no hook file and no NODE_OPTIONS change. It exists for environments where you can't modify your application's startup configuration to add the hook. It's available on Linux and macOS only. Node.js has no equivalent signal delivery mechanism on Windows.

Configuring Signal Mode

Start your application with Node's built in report and GC trace flags:

node --report-on-signal --trace-gc app.js
1

Then tell the yc-360 script to use Signal Mode instead of the default Hook Mode, using nodejsCaptureMode:

./yc -onlyCapture -p {PID} -appRuntime=nodejs -nodejsCaptureMode=signal
1

Node.js defaults --report-on-signal to SIGUSR2, and the yc-360 script defaults to that same signal, so in the common case no further configuration is needed. If your deployment already reserves SIGUSR2 for something else, change both sides together using a matching --report-on-signal=<SIGNAL> on the application and nodejsReportSignal on the script.

Note

Avoid SIGUSR1. Node.js treats it as an inspector activation signal, and the yc-360 script refuses it for that reason.

What Signal Mode captures

  • Process Overview: environment variables (masked), CPU and memory usage, Node.js version and configuration, and active libuv handles, all from Node's built in diagnostic report.
  • Call Stack: a snapshot of the main thread's execution at capture time, also from the built in diagnostic report.
  • GC Log: garbage collection activity, provided the application was started with --trace-gc and its output is available to the yc-360 script. See Configuring Continuous GC Log Capture below.

What Signal Mode doesn't capture, and why

Event Loop Lag, Unhandled Promise Rejections, Module Inventory, Active Handles and Requests Growth, Heap Summary, and CPU Profile aren't available in Signal Mode. This isn't a configuration gap you can work around. Signal Mode triggers Node's built in --report-on-signal diagnostic report, a fixed snapshot defined by Node.js itself, and there's no channel to ask the running process for anything beyond what that report already contains. Each of the six sections above requires live, in process instrumentation, which only Hook Mode has access to. If you need the full report, switch to Hook Mode.

Data privacy and security

  • Environment variables are excluded entirely, not partially shown, as a conservative default.
  • Command line arguments are never captured, for the same reason as Hook Mode.
  • No additional listening channel is created. Signal Mode adds nothing beyond Node's own built in flags. There's no new socket, port, or process to secure.

# Capturing Node.js Diagnostics

Once your Node.js application is configured with Hook Mode or Signal Mode, the yc-360 script captures its diagnostics the same way it does for Java and .NET, using -appRuntime=nodejs to tell the script which capture path to use.

The commands themselves depend on how you want to trigger a capture. Rather than repeating them here, see:

  • On-Demand Mode to trigger a single capture manually against a running process.
  • Only Capture Mode to save a capture locally as a zip file instead of uploading it.
  • M3 Mode to continuously monitor a Node.js process and capture automatically when early signs of trouble appear.

Each of those pages includes a Node.js specific example for every supported platform.

# Configuring Continuous GC Log Capture

GC Log works differently from every other artifact on this page, because Node.js has no direct equivalent of Java's -Xlog:gc:file=... or .NET's GC trace to file option. There's no V8 or Node.js flag that writes garbage collection activity to a file of your choosing. --trace-gc always writes to the process's standard output, interleaved with whatever your application logs to the console.

The yc-360 script works around that interleaving differently depending on the platform:

  • Linux and macOS: the script discovers the target process's standard output on its own and reads GC lines directly from it. No extra configuration is required beyond starting the application with --trace-gc.
  • Windows: there's no equivalent OS level mechanism for one process to discover where another process's output is pointing, so auto discovery isn't possible without cooperation from the application itself.

The workaround is the same on any platform, and required on Windows: redirect your application's own output to a file at startup. That file will contain your application's regular console output with GC trace lines interleaved throughout. Point the yc-360 script at that same file using nodejsGCLogPath, and it will read GC data from there instead of trying to discover it automatically:

node --trace-gc app.js > app-output.log 2>&1
1
./yc -onlyCapture -p {PID} -appRuntime=nodejs -nodejsGCLogPath=/path/to/app-output.log
1

# Supported Versions and Platforms

Node.js 14.x and later. Hook Mode runs on Linux, macOS, and Windows. Signal Mode runs on Linux and macOS only.

# Frequently Asked Questions