Skip to content

Commit

Permalink
Refactor Log, in a tiny and light way.
Browse files Browse the repository at this point in the history
  • Loading branch information
Tjatse committed Dec 4, 2014
1 parent 174ca28 commit 26aff8b
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 95 deletions.
9 changes: 7 additions & 2 deletions bin/pm2
Original file line number Diff line number Diff line change
Expand Up @@ -487,9 +487,14 @@ commander.command('reloadLogs')
// Log streaming
//
commander.command('logs [id|name]')
.option('--lines <N>', 'output the last N lines, instead of the last 20')
.description('stream logs file. Default stream all logs')
.action(function(id) {
CLI.streamLogs(id);
.action(function(id, cmd) {
var line = 20;
if(typeof cmd.lines == 'number'){
line = cmd.lines;
}
CLI.streamLogs(id, line);
});

commander.command('ilogs')
Expand Down
37 changes: 19 additions & 18 deletions lib/CLI.js
Original file line number Diff line number Diff line change
Expand Up @@ -1239,40 +1239,41 @@ CLI.monit = function(cb) {
* @param {} id
* @return
*/
function fallbackLogStream(id) {
function fallbackLogStream(id, lines) {
lines = lines || 20;
Satan.executeRemote('getMonitorData', {}, function(err, list) {
if (err) {
printError(err);
exitCli(cst.ERROR_EXIT);
}

Log.stream(cst.PM2_LOG_FILE_PATH, 'PM2');
Log.stream(cst.PM2_LOG_FILE_PATH, lines);

printOut('########### Starting streaming logs for [%s] process', id || 'all');
list.forEach(function(proc) {
if ((!id || (id && !isNaN(parseInt(id)) && proc.pm_id == id)) ||
(!id || (id && isNaN(parseInt(id)) && proc.pm2_env.name == id))) {
var app_name = proc.pm2_env.name || p.basename(proc.pm2_env.pm_exec_path);

if (proc.pm2_env.pm_log_path) {
Log.stream(proc.pm2_env.pm_log_path,
app_name + '-' + proc.pm_id + ' (entire)');
} else {
if (proc.pm2_env.pm_out_log_path)
Log.stream(proc.pm2_env.pm_out_log_path,
app_name + '-' + proc.pm_id + ' (out)');
if (proc.pm2_env.pm_err_log_path)
Log.stream(proc.pm2_env.pm_err_log_path,
app_name + '-' + proc.pm_id + ' (err)');
}
var app_name = (proc.pm2_env.name || p.basename(proc.pm2_env.pm_exec_path)) + '-' + proc.pm_id;

['', 'out', 'err'].some(function(n){
var pk = 'pm_' + (n ? n + '_':'') + 'log_path';
if(pk in proc.pm2_env){
Log.stream({
path: proc.pm2_env[pk],
type: n
}, app_name + '(' + (!n ? 'entire' : n) + ')', lines);
return !n;
}
return false;
});
}
});

});
}

CLI.streamLogs = function(id) {
fallbackLogStream(id);
CLI.streamLogs = function(id, lines) {
fallbackLogStream(id, lines);
};

CLI.ilogs = function() {
Expand Down Expand Up @@ -1474,7 +1475,7 @@ function speedList() {
if (Satan._noDaemonMode) {
printOut('--no-daemon option enabled = do not exit pm2 CLI');
printOut('PM2 dameon PID = %s', fs.readFileSync(cst.PM2_PID_FILE_PATH));
return Log.stream(cst.PM2_LOG_FILE_PATH, 'PM2', 0);
return Log.stream(cst.PM2_LOG_FILE_PATH);
}
else {
return exitCli(cst.SUCCESS_EXIT);
Expand Down
135 changes: 60 additions & 75 deletions lib/Log.js
Original file line number Diff line number Diff line change
@@ -1,93 +1,78 @@
//
// Display a file in streaming
//
var fs = require('fs');
var fs = require('fs'),
chalk = require('chalk'),
spawn = require('child_process').spawn;

var colors = [
'\x1B[34m', // blue
'\x1B[36m', // cyan
'\x1B[32m', // green
'\x1B[35m', // magenta
'\x1B[31m', // red
'\x1B[90m', // grey
'\x1B[33m' // yellow
];
var Log = module.exports = {};

var gl_idx = 0;
var db = [];
// Empty line.
var re_blank = /^[\s\r\t]*$/;

var Log = module.exports = {};
/**
* Styles of title and content.
* @type {{def: {title: string, content: string}, out: {title: string, content: string}, err: {title: string, content: string}}}
*/
Log.styles = {
def: {title: 'blue', content: 'grey'},
out: {title: 'green', content: 'black'},
err: {title: 'red', content: 'red'}
};

/**
* Description
* @method stream
* @param {} path
* @param {} title
* @return
* Tail logs from file stream.
* @param {String|Object} path
* @param {String} title
* @param {Number} lines
* @returns {*}
*/
Log.stream = function(path, title, read_bytes) {
if (title === undefined)
title = gl_idx;
Log.stream = function(path, title, lines){
var type = 'def';

try {
var currSize = fs.statSync(path).size - (typeof(read_bytes) === 'undefined' ? 1000 : read_bytes);
currSize = currSize > 0 ? currSize : 0;
} catch(e) {
if (e.code == 'ENOENT')
console.log('%s with %s file not found', title, path);
return false;
// Make options in the right position.
if (typeof path == 'object') {
type = !path.type ? 'def' : path.type;
path = path.path;
}
if (typeof title == 'number') {
lines = title;
title = null;
}
lines = lines || 20;

var odb = db[title] = {color : colors[gl_idx++ % colors.length], l : 0};
title = '[' + (title || 'PM2') + ']';

var _stream = function() {
fs.stat(path, function(err, stat) {
var prevSize = stat.size;
var style = Log.styles[type] || 'blue';

if (currSize > prevSize) return true;
// Check file exist or not.
if (!fs.existsSync(path)) {
return console.info(chalk.bold.red(title), chalk.red('Log file "' + path + '" does not exist.'));
}

var rstream = fs.createReadStream(path, {
encoding : 'utf8',
start : currSize,
end : prevSize
});
// Tail logs.
var tail = spawn('tail', ['-f', '-n', lines, path], {
// Kill the spawned process by `tail.kill('SIGTERM')`.
killSignal: 'SIGTERM',
stdio : [null, 'pipe', 'pipe']
});

rstream.on('data', function(data) {
print_data(odb, title, data);
});
// Use utf8 encoding.
tail.stdio.forEach(function(stdio){
stdio.setEncoding('utf8');
});

currSize = stat.size;
return true;
// stdout.
tail.stdout.on('data', function(data){
data.split(/\n/).forEach(function(line){
if (!re_blank.test(line)) {
console.info(chalk.bold[style.title](title), chalk[style.content](line));
}
});
};

_stream();

fs.watch(path, function(ev, filename) {
if (ev == 'rename')
return console.error('Renaming file ?');

_stream();
return true;
});
};

//
// Privates
//
/**
* Description
* @method print_data
* @param {} odb
* @param {} title
* @param {} data
* @return
*/
function print_data(odb, title, data) {
var lines = data.split('\n');

lines.forEach(function(l) {
if (l)
console.log(odb.color + '[%s]\x1B[39m %s', title, l);
// handle error.
tail.stderr.on('data', function(data){
tail.disconnect();
console.info(chalk.bold.red(title), chalk.red(data.toString().replace(/\n/, '')));
});
}

return tail;
};

0 comments on commit 26aff8b

Please sign in to comment.