Adam
Adam

Reputation: 5233

Node.js: log ignored errors

Is there any way in node.js to log all exceptions?

process.on('uncaughtException') is not enough for me, because I need to log all caught and uncaught exceptions, even if there was a catch somewhere in the code which just ignored/swallowed the error.

Do you guys think, it is possible in node.js?

Upvotes: 3

Views: 1576

Answers (3)

vkurchatkin
vkurchatkin

Reputation: 13570

One hacky way to do this is using debug context:

const vm = require('vm');

const Debug = vm.runInDebugContext('Debug'); // Obtain Debug object

Debug.setListener((type, _, e) => { // listen for all debug events
  if (type == Debug.DebugEvent.Exception) {
    console.log(e.exception().stack) // e is an event object
  }
});

Debug.setBreakOnException(); // this is required for Exception event to fire

try {
  throw new Error('bla');
} catch(e) {
  // ha
}

Warning: don't leave this code in production, use for debugging only.

Obviously, it won't call asynchronous errors, because they are not actually thrown, they are just created to passed to a callback.

Another way is to replace possible error constructors:

const OldError = Error;
const MyError = function(message) {
  const err = new OldError(message);
  OldError.captureStackTrace(err, MyError); // remove top frame from stack trace

  console.log(err.stack);

  return err;
}

MyError.prototype = Error.prototype; // Fix instanceof
global.Error = MyError;

try {
  throw new Error('bla');
} catch(e) {
}


new Error('blabla');

This way you can also handle asynchronous error, but won't see if something other than instance Error is thrown.

If you are interested only in promises and you are using native v8 promises, then you can try this:

const vm = require('vm');

const Debug = vm.runInDebugContext('Debug');

Debug.setListener((type, _, e) => {
  if (type == Debug.DebugEvent.PromiseEvent) {
    if (e.status() === -1) { // 0=pending, 1=resolved, -1=rejected
      console.log(e.value().value().stack);
    }
  }
});



Promise.reject(new Error('test'))
  .catch(() => {});

It will likely generate some duplicates, since it catches child promise rejection as well as original promise rejection.

Upvotes: 6

saintedlama
saintedlama

Reputation: 6898

You could attach a debugger like node-inspector and active the option Pause on caught Exceptions in node-inspector. This does not log exceptions but pause execution which should be enough to find the quirks in the 3rd party module.

If you're using WebStorm you can log uncaught exceptions to the console or to a file. After starting the WebStorm debugger open the breakpoints dialog and activate the "Any exception" setting for "JavaScript Exception Breakpoints" and breakpoint actions according to this dialog

Upvotes: 1

Enrichman
Enrichman

Reputation: 11337

If you are swallowing the exceptions you cannot track them. If you think that a module that you're using is ignoring the exceptions you are using a bad module or you are not using it correctly.

If you are using Express the correct approach will be to redirect all the exception and errors with next(err).

The exceptions will be passed to the error handler (note the four parameters in the function) and there you can log them:

router.get('/', function (req, res, next) {
    // your logic

    if(err) {
        return next(err);
    }


    return next();
});


// Error handler
app.use(function(err, req, res, next) {

    console.log(err.stack);

    res.status(err.status || 500).json({
        error: {
            code: err.code,
            message: err.message
        }
    });

    next(err);
});

Upvotes: 0

Related Questions