From 2fcc947f1114b7e4e463a8fb4fd9196ee3fa50a7 Mon Sep 17 00:00:00 2001 From: Matt Ranney Date: Mon, 14 Mar 2011 15:50:47 -1000 Subject: [PATCH] Add `MONITOR` command and special monitor command reply parsing. --- README.md | 23 +++++++++++++++++++++++ changelog.md | 4 ++++ index.js | 23 ++++++++++++++++------- package.json | 2 +- test.js | 5 +++-- 5 files changed, 47 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 2e2ce392fe..f448d0e8ef 100644 --- a/README.md +++ b/README.md @@ -394,6 +394,29 @@ of commands and arguments to the constructor: }); +## Monitor mode + +Redis supports the `MONITOR` command, which lets you see all commands received by the Redis server +across all client connections, including from other client libraries and other computers. + +After you send the `MONITOR` command, no other commands are valid on that connection. `node_redis` +will emit a `monitor` event for every new monitor message that comes across. The callback for the +`monitor` event takes a timestamp from the Redis server and an array of command arguments. + +Here is a simple example: + + var client = require("redis").createClient(), + util = require("util"); + + client.monitor(function (err, res) { + console.log("Entering monitoring mode."); + }); + + client.on("monitor", function (time, args) { + console.log(time + ": " + util.inspect(args)); + }); + + # Extras Some other things you might like to know about. diff --git a/changelog.md b/changelog.md index b3d7da387a..d6f9583efa 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,10 @@ Changelog ========= +## v0.5.8 - March 14, 2011 + +Add `MONITOR` command and special monitor command reply parsing. + ## v0.5.7 - February 27, 2011 Add magical auth command. diff --git a/index.js b/index.js index bbb19a618b..77695ba391 100644 --- a/index.js +++ b/index.js @@ -48,6 +48,7 @@ function RedisClient(stream, options) { this.retry_delay = 250; this.retry_backoff = 1.7; this.subscriptions = false; + this.monitoring = false; this.closing = false; this.server_info = {}; this.auth_pass = null; @@ -279,6 +280,7 @@ RedisClient.prototype.connection_gone = function (why) { self.connected = false; self.ready = false; self.subscriptions = false; + self.monitoring = false; // since we are collapsing end and close, users don't expect to be called twice if (! self.emitted_end) { @@ -361,7 +363,7 @@ RedisClient.prototype.return_error = function (err) { RedisClient.prototype.return_reply = function (reply) { var command_obj = this.command_queue.shift(), - obj, i, len, key, val, type; + obj, i, len, key, val, type, timestamp, args; if (this.subscriptions === false && this.command_queue.length === 0) { this.emit("idle"); @@ -414,6 +416,13 @@ RedisClient.prototype.return_reply = function (reply) { } else { throw new Error("subscriptions are active but got an invalid reply: " + reply); } + } else if (this.monitoring) { + len = reply.indexOf(" "); + timestamp = reply.slice(0, len); + args = reply.slice(len + 1).match(/"[^"]+"/g).map(function (elem) { + return elem.replace(/"/g, ""); + }); + this.emit("monitor", timestamp, args); } else { throw new Error("node_redis command queue state error. If you can reproduce this, please report it."); } @@ -469,12 +478,12 @@ RedisClient.prototype.send_command = function () { } command_obj.sub_command = true; this.subscriptions = true; - } else { - if (command === "quit") { - this.closing = true; - } else if (this.subscriptions === true) { - throw new Error("Connection in pub/sub mode, only pub/sub commands may be used"); - } + } else if (command === "monitor") { + this.monitoring = true; + } else if (command === "quit") { + this.closing = true; + } else if (this.subscriptions === true) { + throw new Error("Connection in pub/sub mode, only pub/sub commands may be used"); } this.command_queue.push(command_obj); this.commands_sent += 1; diff --git a/package.json b/package.json index 4d74363903..380aa8f662 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { "name" : "redis", - "version" : "0.5.7", + "version" : "0.5.8", "description" : "Redis client library", "author": "Matt Ranney ", "contributors": [ diff --git a/test.js b/test.js index 7147f0f807..70dec37a06 100644 --- a/test.js +++ b/test.js @@ -1068,7 +1068,8 @@ client.on('end', function () { ended = true; }); -// TODO - need a better way to test auth, maybe auto-config a local Redis server? +// TODO - need a better way to test auth, maybe auto-config a local Redis server? Sounds hard. +// Yes, this is the real password. Please be nice, thanks. client4.auth("664b1b6aaf134e1ec281945a8de702a9", function (err, res) { if (err) { assert.fail(err, name); @@ -1091,7 +1092,7 @@ client3.on("error", function (err) { }); client.on("reconnecting", function (params) { - console.log("reconnecting: " + util.inspect(params)); +// console.log("reconnecting: " + util.inspect(params)); }); process.on('uncaughtException', function (err) {