TritonDataCenter / node-verror

Rich JavaScript errors
MIT License
1.18k stars 61 forks source link

Feature request: option to have fullStack be the default stack property #69

Open magicmark opened 5 years ago

magicmark commented 5 years ago

Thanks for this awesome library, excited to use it!

Motivation:

Let's say I want to catch something and rethrow it with my own error message and context. Something like this:

try {
    await execa('ls');
} catch (e) {
    throw new VError(
        { name: 'MyCustomError', cause: err },
        `Error doing stuff.`,
    );
}

We lose the full context of the error in the default output when throwing. My motivation in using this library is to preserve the previous errors in the stack.

I can can use VError.fullStack, but it's not clear how to throw an error that prints the full stack trace.

tl;dr

cat test.js
const VError = require('verror')
var err1 = new VError('something bad happened');
var err2 = new VError(err1, 'something really bad happened here');

console.log('========= The output I want when doing `throw new VError(...)` =========');
console.log(VError.fullStack(err2));

console.log('========= The output I get... =========');
throw err2;

Output:

node test.js
========= The output I want when doing `throw new VError(...)` =========
VError: something really bad happened here: something bad happened
    at Object.<anonymous> (/nail/home/markl/pg/yelp-graphql-extract/test.js:3:12)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Function.Module.runMain (module.js:694:10)
    at startup (bootstrap_node.js:204:16)
    at bootstrap_node.js:625:3
caused by: VError: something bad happened
    at Object.<anonymous> (/nail/home/markl/pg/yelp-graphql-extract/test.js:2:12)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Function.Module.runMain (module.js:694:10)
    at startup (bootstrap_node.js:204:16)
    at bootstrap_node.js:625:3
========= The output I get... =========

/nail/home/markl/pg/yelp-graphql-extract/test.js:9
throw err2;
^
VError: something really bad happened here: something bad happened
    at Object.<anonymous> (/nail/home/markl/pg/yelp-graphql-extract/test.js:3:12)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Function.Module.runMain (module.js:694:10)
    at startup (bootstrap_node.js:204:16)
    at bootstrap_node.js:625:3

Prior Art

Looks like others are experimenting with this too? https://github.com/duccio/winston-verror-format/blob/f7adb35552a4de7b092540b683d0ec5a08ea5c28/src/index.ts#L22

Suggestion

Would you be open to a PR that provides a new option - useFullStack that kinda does the above? So I could do something like this:

throw new VError(
    { name: 'MyCustomError', cause: err, useFullStack: true },
    `Error doing stuff.`,
);

Thanks!

richardscarrott commented 5 years ago

This would be super useful as we've found tools like stackdriver / new relic group errors based on the stacktrace meaning it incorrectly groups different errors which happen to be caught, wrapped and rethrown at the same place.

davepacheco commented 5 years ago

I think as long as that's an option that's off by default and any potential downsides are documented clearly, that seems reasonable! As I recall, V8 avoids formatting stack traces until they're explicitly requested via an access to the stack property because it's fairly expensive and many errors never wind up having their stack formatted. Is it possible to implement what you suggested and preserve that behavior?