diff --git a/README.md b/README.md index f1680c6541..0b5a554a92 100644 --- a/README.md +++ b/README.md @@ -757,6 +757,35 @@ clients: 1, NodeJS: 6.2.0, Redis: 3.2.0, parser: javascript, connected by: tcp To get debug output run your `node_redis` application with `NODE_DEBUG=redis`. +This is also going to result in good stack traces opposed to useless ones otherwise for any async operation. +If you only want to have good stack traces but not the debug output run your application in development mode instead (`NODE_ENV=development`). + +Good stack traces are only activated in development and debug mode as this results in a significant performance penalty. + +___Comparison___: +Useless stack trace: +``` +ReplyError: ERR wrong number of arguments for 'set' command + at parseError (/home/ruben/repos/redis/node_modules/redis-parser/lib/parser.js:158:12) + at parseType (/home/ruben/repos/redis/node_modules/redis-parser/lib/parser.js:219:14) +``` +Good stack trace: +``` +ReplyError: ERR wrong number of arguments for 'set' command + at new Command (/home/ruben/repos/redis/lib/command.js:9:902) + at RedisClient.set (/home/ruben/repos/redis/lib/commands.js:9:3238) + at Context. (/home/ruben/repos/redis/test/good_stacks.spec.js:20:20) + at callFnAsync (/home/ruben/repos/redis/node_modules/mocha/lib/runnable.js:349:8) + at Test.Runnable.run (/home/ruben/repos/redis/node_modules/mocha/lib/runnable.js:301:7) + at Runner.runTest (/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:422:10) + at /home/ruben/repos/redis/node_modules/mocha/lib/runner.js:528:12 + at next (/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:342:14) + at /home/ruben/repos/redis/node_modules/mocha/lib/runner.js:352:7 + at next (/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:284:14) + at Immediate._onImmediate (/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:320:5) + at processImmediate [as _immediateCallback] (timers.js:383:17) +``` + ## How to Contribute - Open a pull request or an issue about what you want to implement / change. We're glad for any help! - Please be aware that we'll only accept fully tested code. diff --git a/changelog.md b/changelog.md index a416a04aa9..a8fdd30fda 100644 --- a/changelog.md +++ b/changelog.md @@ -11,6 +11,7 @@ Features - The JS parser is from now on the new default as it is a lot faster than the hiredis parser - This is no BC as there is no changed behavior for the user at all but just a performance improvement. Explicitly requireing the Hiredis parser is still possible. - Added name property to all Redis functions (Node.js >= 4.0) +- Improved stack traces in development and debug mode Bugfixes diff --git a/index.js b/index.js index 84c9b64427..cd4edb1a5d 100644 --- a/index.js +++ b/index.js @@ -348,6 +348,9 @@ RedisClient.prototype.flush_and_error = function (error_attributes, options) { // Don't flush everything from the queue for (var command_obj = this[queue_names[i]].shift(); command_obj; command_obj = this[queue_names[i]].shift()) { var err = new errorClasses.AbortError(error_attributes); + if (command_obj.error) { + err.stack = err.stack + command_obj.error.stack.replace(/^Error.*?\n/, '\n'); + } err.command = command_obj.command.toUpperCase(); if (command_obj.args && command_obj.args.length) { err.args = command_obj.args; @@ -675,6 +678,9 @@ RedisClient.prototype.connection_gone = function (why, error) { RedisClient.prototype.return_error = function (err) { var command_obj = this.command_queue.shift(); + if (command_obj.error) { + err.stack = command_obj.error.stack.replace(/^Error.*?\n/, 'ReplyError: ' + err.message + '\n'); + } err.command = command_obj.command.toUpperCase(); if (command_obj.args && command_obj.args.length) { err.args = command_obj.args; diff --git a/lib/command.js b/lib/command.js index 6414d4d6fc..1c14b2d41f 100644 --- a/lib/command.js +++ b/lib/command.js @@ -1,5 +1,7 @@ 'use strict'; +var debug_mode = require('../').debug_mode; +var betterStackTraces = process.env.NODE_ENV && process.env.NODE_ENV.toUpperCase() === 'DEVELOPMENT' || debug_mode; function Command (command, args, callback, call_on_write) { this.command = command; @@ -7,6 +9,9 @@ function Command (command, args, callback, call_on_write) { this.buffer_args = false; this.callback = callback; this.call_on_write = call_on_write; + if (betterStackTraces) { + this.error = new Error(); + } } module.exports = Command;