You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nodebb/src/logger.js

223 lines
4.9 KiB
JavaScript

11 years ago
'use strict';
/*
* Logger module: ability to dynamically turn on/off logging for http requests & socket.io events
*/
var fs = require('fs'),
11 years ago
path = require('path'),
express = require('express'),
winston = require('winston'),
util = require('util'),
socketio = require('socket.io'),
11 years ago
meta = require('./meta');
var opts = {
/*
* state used by Logger
*/
express : {
app : {},
set : 0,
ofn : null,
},
streams : {
log : { f : process.stdout },
}
};
/* -- Logger -- */
(function(Logger) {
Logger.init = function(app) {
opts.express.app = app;
/* Open log file stream & initialize express logging if meta.config.logger* variables are set */
Logger.setup();
11 years ago
};
Logger.setup = function() {
Logger.setup_one('loggerPath', meta.config.loggerPath);
11 years ago
};
11 years ago
Logger.setup_one = function(key, value) {
/*
* 1. Open the logger stream: stdout or file
* 2. Re-initialize the express logger hijack
*/
11 years ago
if (key === 'loggerPath') {
Logger.setup_one_log(value);
Logger.express_open();
}
11 years ago
};
Logger.setup_one_log = function(value) {
/*
* If logging is currently enabled, create a stream.
* Otherwise, close the current stream
*/
if(meta.config.loggerStatus > 0 || meta.config.loggerIOStatus) {
var stream = Logger.open(value);
11 years ago
if(stream) {
opts.streams.log.f = stream;
} else {
opts.streams.log.f = process.stdout;
}
}
else {
Logger.close(opts.streams.log);
}
11 years ago
};
Logger.open = function(value) {
/* Open the streams to log to: either a path or stdout */
var stream;
11 years ago
if(value) {
if(fs.existsSync(value)) {
11 years ago
var stats = fs.statSync(value);
11 years ago
if(stats) {
if(stats.isDirectory()) {
stream = fs.createWriteStream(path.join(value, 'nodebb.log'), {flags: 'a'});
} else {
stream = fs.createWriteStream(value, {flags: 'a'});
}
11 years ago
}
11 years ago
} else {
stream = fs.createWriteStream(value, {flags: 'a'});
}
if(stream) {
11 years ago
stream.on('error', function(err) {
winston.error(err.message);
});
11 years ago
}
11 years ago
} else {
stream = process.stdout;
11 years ago
}
return stream;
11 years ago
};
Logger.close = function(stream) {
11 years ago
if(stream.f !== process.stdout && stream.f) {
stream.end();
}
stream.f = null;
11 years ago
};
Logger.monitorConfig = function(socket, data) {
/*
* This monitor's when a user clicks "save" in the Logger section of the admin panel
*/
Logger.setup_one(data.key,data.value);
Logger.io_close(socket);
Logger.io(socket);
11 years ago
};
Logger.express_open = function() {
11 years ago
if(opts.express.set !== 1) {
opts.express.set = 1;
opts.express.app.use(Logger.expressLogger);
}
/*
* Always initialize "ofn" (original function) with the original logger function
*/
opts.express.ofn = express.logger({stream : opts.streams.log.f});
11 years ago
};
Logger.expressLogger = function(req,res,next) {
/*
* The new express.logger
*
* This hijack allows us to turn logger on/off dynamically within express
*/
if(meta.config.loggerStatus > 0) {
return opts.express.ofn(req,res,next);
11 years ago
} else {
return next();
}
11 years ago
};
Logger.prepare_io_string = function(_type, _uid, _args) {
/*
* This prepares the output string for intercepted socket.io events
*
* The format is: io: <uid> <event> <args>
*/
try {
return 'io: '+_uid+' '+_type+' '+util.inspect(Array.prototype.slice.call(_args))+'\n';
} catch(err) {
11 years ago
winston.info("Logger.prepare_io_string: Failed", err);
return "error";
}
11 years ago
};
Logger.io_close = function(socket) {
/*
* Restore all hijacked sockets to their original emit/on functions
*/
var clients = socket.io.sockets.clients();
11 years ago
clients.forEach(function(client) {
if(client.oEmit && client.oEmit !== client.emit) {
client.emit = client.oEmit;
11 years ago
}
11 years ago
if(client.$oEmit && client.$oEmit !== client.$emit) {
client.$emit = client.$oEmit;
11 years ago
}
11 years ago
});
};
Logger.io = function(socket) {
/*
* Go through all of the currently established sockets & hook their .emit/.on
*/
11 years ago
if(!socket && !socket.io.sockets) {
return;
}
var clients = socket.io.sockets.clients();
11 years ago
clients.forEach(function(client) {
Logger.io_one(client, client.uid);
});
};
Logger.io_one = function(socket, uid) {
/*
* This function replaces a socket's .emit/.on functions in order to intercept events
*/
11 years ago
if(socket && meta.config.loggerIOStatus > 0) {
(function() {
11 years ago
function override(method, name, errorMsg) {
return function() {
if(opts.streams.log.f) {
opts.streams.log.f.write(Logger.prepare_io_string(name, uid, arguments));
}
try {
method.apply(socket, arguments);
} catch(err) {
winston.info(errorMsg, err);
}
};
}
// courtesy of: http://stackoverflow.com/a/9674248
socket.oEmit = socket.emit;
var emit = socket.emit;
11 years ago
socket.emit = override(emit, 'emit', 'Logger.io_one: emit.apply: Failed');
11 years ago
socket.$oEmit = socket.$emit;
var $emit = socket.$emit;
11 years ago
socket.$emit = override($emit, 'on', 'Logger.io_one: $emit.apply: Failed');
})();
}
11 years ago
};
}(exports));