A simple Node.js log server using ZeroMQ
This post walks through building a simple Node.js log server that uses ZeroMQ to accept messages. Such a server could then be shared by multiple applications (or modules within a single application).
In this example the log server is launched as a stand alone process, but in practice you could launch it as a thread from a parent application using require('child_process').fork()
.
Installing ZeroMQ
Before you can use ZeroMQ with node you need to install its C header files and Node.js bindings.
If you are running Debian Wheezy (the stable release at the time of writing) then you will need to add the wheezy-backports repository first:
echo 'deb http://http.debian.net/debian wheezy-backports main' > /etc/apt/sources.list.d/wheezy-backports.list
aptitude -q update
Assuming that you run Debian, libzmq3-dev is the package you are looking for:
aptitude -q install libzmq3-dev
Now you can install the bindings:
npm install zmq
The Logger
This is the code for logger.js
. The logger accepts messages into its own internal queue and then a worker periodically goes through the queue and gets the messages out.
/*jshint node:true*/
'use strict';
var zmq = require('zmq');
var socket = zmq.socket('pull');
// Instead of a Unix socket you can use 'tcp://...' etc.
var socketAddress = 'ipc://' + __dirname + '/logger.socket';
// internal message queue
var messages = [];
// function to log the message
function log (message) {
// in practice this can be much more fancy
console.log(message);
}
// message queue worker loop
(function loop() {
setTimeout(function () {
while (messages.length) {
log(messages.shift());
}
loop();
}, 1000);
})();
// multi-part message parts go in separate arguments
socket.on('message', function (level, data) {
level = level.toString();
data = data.toString();
messages.push({
level: level,
data: data,
time: new Date().getTime()
});
});
// Once everything is ready start listening for messages
socket.bind(socketAddress);
console.log('Logger is ready');
The App
This is the code for app.js – nothing fancy here.
/*jshint node:true*/
'use strict';
var zmq = require('zmq');
var socket = zmq.socket('push');
// Instead of a Unix socket you can use 'tcp://...' etc.
var socketAddress = 'ipc://' + __dirname + '/logger.socket';
socket.connect(socketAddress);
console.log('App is ready');
// send some multi-part messages
socket.send(['info', 'Message #1']);
socket.send(['info', 'Message #2']);
socket.send(['info', 'Message #3']);
Testing
Launch the two scripts in separate terminals:
$ node app.js
App is ready
$ node logger.js
Logger is ready
{ level: 'info', data: 'Message #1', time: 1424348906861 }
{ level: 'info', data: 'Message #2', time: 1424348906861 }
{ level: 'info', data: 'Message #3', time: 1424348906861 }
Looks good. :)
Further reading
- Examples from the Node.js bindings package
- A very nice series on Node.js + ZeroMQ: Part 1, Part 2, Part 3 and Part 4
- The excellent ZeroMQ documentation
Disclaimer
The information above is accurate to my knowledge, however I provide no guarantees to this effect and consequently accept no liability whatsoever for any bad things that may happen as a result of the reader using this information in practice. Use at your own risk. Oh, and backup your data while you’re at it.