splog
Version:
A NodeJS library which provides a syslog-like remote logging interface
208 lines (190 loc) • 5.41 kB
JavaScript
var exec = require('child_process').exec;
var net = require('net');
var util = require('util');
var hostname = null;
function _hostname(error, stdout, stderr) {
if (stdout) {
hostname = stdout.trim();
} else {
hostname = 'localhost';
}
onHostnameReady();
}
exec('hostname', _hostname);
function _pad(what, howFar, withWhat) {
var padded = what.toString();
if (withWhat === undefined) {
if (typeof what === 'number') {
withWhat = '0';
} else {
withWhat = ' ';
}
}
for (var index = padded.length; index < howFar; index = index + 1) {
padded = withWhat + padded;
}
return padded;
}
function _timestamp() {
var now = new Date();
return [
[
[now.getFullYear(), _pad(now.getMonth() + 1, 2), _pad(now.getDate(), 2)].join('-'),
[_pad(now.getHours(), 2), _pad(now.getMinutes(), 2), _pad(now.getSeconds(), 2)].join(':'),
].join(' '), _pad(now.getMilliseconds(), 3)].join(',');
}
var FACILITIES = {
'user': 1,
};
var LEVELS = {
'debug': 7,
'info': 6,
'warning': 4,
'error': 3,
'critical': 2,
};
var configuration = {
'hostnameBacklog': [],
'socketBacklog': [],
'hostnameReady': false,
'socketReady': false,
};
function onSocketError(line) {
configuration['socketReady'] = false;
if (line) {
if(line instanceof Error){
log('warning',line.toString());
console.log(line);
} else {
configuration['socketBacklog'].push(line);
}
}
_reconnectSocket();
}
function onHostnameReady() {
configuration['hostnameReady'] = true;
var backlog = configuration['hostnameBacklog'];
configuration['hostnameBacklog'] = [];
for (var index in backlog) {
backlog[index]['hostname'] = hostname;
_format(backlog[index]);
}
}
function onSocketReady() {
configuration['socketReady'] = true;
var backlog = configuration['socketBacklog'];
configuration['socketBacklog'] = [];
if (backlog.length > 0) {
_send(backlog.join(''));
}
}
function _reconnectSocket() {
if (configuration['socket']) {
configuration['socket'].destroy();
}
var socket = new net.Socket({type: 'tcp'});
socket.setNoDelay(true);
socket.setKeepAlive(true);
socket.on('error', onSocketError);
socket.on('connect', onSocketReady);
configuration['socketReady'] = false;
configuration['socket'] = socket;
socket.connect(configuration['port'] || 514, configuration['host']);
}
function configure(settings) {
if (settings) {
if (settings['port']) {
configuration['port'] = settings['port'];
} else {
delete configuration['port'];
}
if (settings['host']) {
configuration['host'] = settings['host'];
} else {
delete configuration['host'];
}
if (settings['app']) {
configuration['app'] = settings['app'];
} else {
delete configuration['app'];
}
if (settings['instance']) {
configuration['instance'] = settings['instance'];
} else {
delete configuration['instance'];
}
if (settings['minLevel']) {
configuration['minLevel'] = parseInt(settings['minLevel']);
if(isNaN(configuration['minLevel'])){
configuration['minLevel'] = LEVELS[settings['minLevel'].trim().toLowerCase()];
}
}
}
if (configuration['host']) {
_reconnectSocket();
}
}
module.exports.configure = configure;
function _format(data) {
if (configuration['hostnameReady']) {
var message = (data['msg'] || '').toString();
if (message[message.length - 1] === '\n'){
message = message.slice(0, -1);
}
var lines = message.split('\n');
for (var index in lines) {
var line = data['hostname'] + ' ' + data['app'] + ' ' + data['timestamp']+ ' ' + data['instance'] + ' ' + data['level'].toUpperCase() + ' ' + lines[index];
if (configuration['host']) {
line = '<' + 8 * FACILITIES[data['facility']] + LEVELS[data['level'].toLowerCase()] + '>' + line;
if (line[line.length - 1] !== '\n') {
line += '\n';
}
} else {
// This is destined for console.log which will throw in a newline.
if (line[line.length - 1] === '\n') {
line = line.slice(0, -1);
}
}
_send(line);
}
} else {
configuration['hostnameBacklog'].push(data);
}
}
function _send(line) {
if (configuration['host']) {
if (configuration['socketReady']) {
configuration['socket'].write(line,function(err){
if(err){
onSocketError(line);
}
});
} else {
configuration['socketBacklog'].push(line);
}
} else {
console.log(line);
}
}
function log(level, msg) {
if(configuration.minLevel && LEVELS[level.trim().toLowerCase()] > configuration.minLevel){
return;
}
var data = {
'facility': configuration['facility'] || 'user',
'level': level,
'hostname': hostname,
'app': configuration['app'] || process.argv[0],
'timestamp': _timestamp(),
'instance': configuration['instance'] || process.pid,
'msg': msg,
};
_format(data);
}
module.exports.log = log
module.exports.debug = function(msg) { log('debug', msg); }
module.exports.info = function(msg) { log('info', msg); }
module.exports.warning = function(msg) { log('warning', msg); }
module.exports.error = function(msg) { log('error', msg); }
module.exports.critical = function(msg) { log('critical', msg); }
//module.exports.configure = configure