Skip to content

Instantly share code, notes, and snippets.

@naholyr
Last active June 8, 2021 08:29
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save naholyr/5480807 to your computer and use it in GitHub Desktop.
Save naholyr/5480807 to your computer and use it in GitHub Desktop.
Make stack traces useful again
var fs = require('fs');
// Here is a simple function that reads a file and makes something with its content
function readLog1 (cb) {
// Notice how I even gave a name to my callback, this is useful for stack traces, everyone says…
fs.readFile('file-not-found.log', function onRead1 (err, content) {
// Usual error handling
if (err) return cb(err);
// deal with content… not the point here
});
}
// I run my function, and print the error
readLog1(function (err) { console.error('ERR 1', err.stack) });
// Here is the output:
/*
ERR 1 Error: ENOENT, open 'file-not-found.log'
*/
// Oh great, what am I supposed to do with that? No line number, nothing…
// What could I do in a real-life app to find *where* it failed?
// You faced even worse frustrating useless stack traces with DB modules
var fs = require('fs');
// Here is the same function
function readLog2 (cb) {
// that does the same thing
fs.readFile('file-not-found.log', function onRead2 (err, content) {
// except it wraps received error in a new Error(…)
if (err) return cb(new Error(err));
// deal with content… not the point here
});
}
// Run exactly the same way
readLog2(function (err) { console.error('ERR 2', err.stack) });
// But this time:
/*
ERR 2 Error: Error: ENOENT, open 'file-not-found.log'
at onRead2 (/home/nchambrier/Projects/LMTM/ooz/2-userful-stack.js:9:24)
at fs.js:207:20
at Object.oncomplete (fs.js:107:15)
*/
// some useful output, I know WHERE it happened exactly
// and THAT's a stack worth storing in my logs
var fs = require('fs');
// Here is the same function
function readLog3 (cb) {
// that does the same thing
fs.readFile('file-not-found.log', function onRead3 (err, content) {
// not wrapping error cause I forgot it
if (err) return cb(err);
// deal with content… not the point here
});
}
// This, let's use console.trace
readLog3(function (err) { console.trace('ERR 3', String(err)) });
// We get this:
/*
Trace: ERR 3 Error: ENOENT, open 'file-not-found.log'
at /home/nchambrier/Projects/Perso/5480807/3-console-trace.js:16:35
at onRead3 (/home/nchambrier/Projects/Perso/5480807/3-console-trace.js:9:21)
at fs.js:207:20
at Object.oncomplete (fs.js:107:15)
*/
// may be the best option, we don't rely on the called function to properly
// wrap error.
// Drawbacks:
// * It forces the way you should *log*, if you're writing a module which should
// definitely not log itself, then you can't use that to be sure to provide
// useful information to your user
// You can use Error.captureStackTrace for the same purpose:
readLog3(function (err) {
var o = {};
Error.captureStackTrace(o, handleError);
console.error('ERR 3 (bis)', String(err), o.stack);
});
// I'm afraid you may lose the track in case of multiple async calls nested
// this has to be tested
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment