Background

The node-report npm is useful for diagnosing many errors in Node.js applications. It generates a report telling you about the state of your Node.js process. It can do this automatically on fatal errors or when the Node.js process is sent a signal. Additionally it provides two useful functions, triggerReport() and getReport(), to allow you to integrate it into your own error handling. The first function creates a report and writes it to a file, the second creates a report and returns it as a String. These let you generate a report while handling errors in your Node.js applications.

Since node-report gives you lots of runtime information like the level of Node.js you are using, environment variables, the OS level you are running and more you can use it in production to give you a report about the Node.js state and the environment it was running in. Some of this information may seem a bit trivial in development but if you are seeing errors in production that you don’t see in development then using node-report can capture all that information for you without requiring you to gather it yourself.

Stack Traces in node-report

One of the key items of program state reported by node-report is the current JavaScript stack at the moment the report was generated. This gives you some context when you are looking at all the other details.

A simple callback (that uses node-report for error handling) might look something like this:

const nodereport = require('node-report');
...
(err, result) => {
  if(err) {
    nodereport.triggerReport();
    return;
  }
  useResult(result);
}

Node.js makes heavy use of callbacks to handle results and errors and if you have tried debugging errors handled by callbacks before you may notice a problem with the example. One of the consequences of the Node.js asynchronous programming model is that the location you handle an error is unlikely to be the location it was raised or even further up or down the stack from there. The current stack you get in the output of node-report is just the stack for your the callback handling the error. It is not the stack for the location which created the Error.

Passing node-report an Error

The stack trace for where you handled the error is useful but what you really want is the details from the object passed in via the err parameter. For that reason the 2.2.0 release of node-report lets you pass an error object to triggerReport() or getReport():

(err, result) => {
  if(err) {
    nodereport.triggerReport(err);
    return;
  }
  useResult(result);
}

This adds an additional “JavaScript Exception Details” section to the report containing the message and stack trace (if there was one) from err. The triggerReport() function can already take a filename as an argument so if you want to pass a filename String and an Error then the Error needs to be the second parameter but if the Error is the only parameter you want to pass then that’s all you need to do.

Examples

The output includes the message from the Error object and any stack trace it contained. Below is the output for a very simple example that uses process.chdir() to change to a non-existent directory:

================================================================================
==== JavaScript Exception Details ==============================================

Uncaught Error: ENOENT: no such file or directory, uv_chdir

./chdir_nodereport.js:6:11
Module._compile (module.js:571:32)
Module._extensions..js (module.js:580:10)
Module.load (module.js:488:32)
tryModuleLoad (module.js:447:12)
Module._load (module.js:439:3)
Module.runMain (module.js:605:10)
run (bootstrap_node.js:418:7)
startup (bootstrap_node.js:139:9)
bootstrap_node.js:533:3

There may be cases where there is an error but no stack trace. This can happen if an error occurs in native code, outside of JavaScript, before the callback is invoked. For example the fs.stat() function performs the actual stat call in native code before creating an Error or result object and invoking the JavaScript callback function. At the time stat is invoked, asynchronously, there is no JavaScript stack at all!

Example:

var fs = require('fs');
var nodereport = require('node-report/api');

fs.stat('/usr/local/fake/fake.txt', (err, stats) => {
  if(err) {
    console.log(nodereport.getReport(err));
  }
});

In this case the report will include a message indicating that no stack trace was available:

================================================================================
==== JavaScript Exception Details ==============================================

Uncaught Error: ENOENT: no such file or directory, stat '/usr/local/fake/fake.txt'

No stack trace available from Exception::GetStackTrace()

Join The Discussion

Your email address will not be published. Required fields are marked *