3

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?

10
  • Create a new console and direct the two output streams to files. If you are handling the errors then just add console.error( // your error... and you will then be logging all errors. See Node.js documents Console. Commented Jan 26, 2016 at 11:38
  • I know I can log all exceptions from node.js code, but now I'm looking for a solution to catch all exceptions without touching the part of the code where it was thrown. Commented Jan 26, 2016 at 11:40
  • 4
    If you are catching the errors and ignoring them you can not trace them. Commented Jan 26, 2016 at 11:43
  • Is modyfying node.js source an option? Commented Jan 26, 2016 at 12:07
  • 2
    If the app is catching exceptions and throwing them away (the thought of which makes me nauseous) and this is a 3rd party app which you have no control over then, unless Harry Potter wrote the compiler, it's going to take a bit of wizardry to get those errors logged - way beyond my muggle capabilities. Commented Jan 26, 2016 at 12:39

3 Answers 3

6

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

0

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);
});

10 Comments

It won't log any error that was caught and ignored.
Of course, if you are ignoring it how can you log it?
You can't. If the exception is ignored it's just discarded. That's why is bad to ignore or swallow the exceptions. I cannot understand why you cannot just avoid to ignore the exception.
@zangw I guess because it's not a specific answer to the question, but the question itself is impossible to answer. Anyway, you can still debug the module and see where it swallows the exception (it seems strange to me, maybe you're using a bad module or incorrectly. Which module is it? Can you post some code?).
In my experience these kind of errors are almost never due to a bug in the modules or libraries but to a "bad" use of them. Maybe you should add the code where you have the problem and ask "this promise is not being resolved, why?"
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.