/*! * Cluster - logger * Copyright (c) 2011 LearnBoost * MIT Licensed */ /** * Module dependencies. */ var fs = require('fs') , Log = require('log') , mkdir = require('mkdirp').mkdirp; /** * Enable stdout / stderr logs for both the master * process, as well as workers. * * These output to the given `dir`, or `./logs` * relative to the server's file. * * Examples: * * // log to ./logs * engine(server) * .use(engine.logger()) * .listen(3000); * * // log to ./app/logs * engine(server) * .use(engine.logger('./app/logs')) * .listen(3000); * * // log to /var/log/node * engine(server) * .use(engine.logger('/var/log/node')) * .listen(3000); * * @param {String} dir * @param {Number} level * @return {Function} * @api public */ module.exports = function(dir, level){ return function(master){ dir = master.resolve(dir || 'logs'); mkdir(dir, 0755, function(err){ if (err) throw err; // master log var stream = fs.createWriteStream(dir + '/master.log', { flags: 'a' }); var log = master.log = new Log(level || Log.INFO, stream); // master events master.on('start', function(){ log.info('master started'); }); // master is shutting down master.on('closing', function(){ log.warning('shutting down master'); }); // master has closed and performed cleanup master.on('close', function(){ log.info('shutdown complete'); }); // sending signal to all workers master.on('kill', function(sig){ log.warning('sent kill(%s) to all workers', sig); }); // worker was killed master.on('worker killed', function(worker){ if ('restarting' == master.state) return; log.error('worker %s died', worker.id); }); // worker exception master.on('worker exception', function(worker, err){ log.error('worker %s uncaught exception %s', worker.id, err.message); }); // worker is waiting on connections to be closed master.on('worker waiting', function(worker, connections){ log.info('worker %s waiting on %s connections', worker.id, connections); }); // worker has timed out master.on('worker timeout', function(worker, timeout){ log.warning('worker %s timed out after %sms', worker.id, timeout); }); // worker connected to master master.on('worker connected', function(worker){ log.debug('worker %s connected', worker.id); }); // cyclic or immediate restart master.on('cyclic restart', function(){ log.warning('cyclic restart detected, restarting in %sms' , master.options['restart timeout']); }); // restart requested master.on('restarting', function(){ log.info('restart requested'); }); // restart complete master.on('restart', function(){ log.info('restart complete'); }); // repl socket connection established master.on('repl socket', function(sock){ var from = sock.remoteAddress ? 'from ' + sock.remoteAddress : ''; sock.on('connect', function(){ log.info('repl connection %s', from); }); sock.on('close', function(){ log.info('repl disconnect %s', from); }); }); // override fds master.customFds = [-1, -1]; // children master.on('worker', function(worker){ var proc = worker.proc; log.info('spawned worker ' + worker.id); // worker log streams var access = fs.createWriteStream(dir + '/workers.access.log', { flags: 'a' }) , error = fs.createWriteStream(dir + '/workers.error.log', { flags: 'a' }); // redirect stdout / stderr proc.stdout.pipe(access); proc.stderr.pipe(error); }); }); } };