@@ -6,6 +6,7 @@
*/

var jitsu = require('../../jitsu'),
util = require('util'),
dateformat = require('dateformat'),
logs = exports,
utile = jitsu.common;
@@ -15,69 +16,102 @@ logs.usage = [
'The default number of lines to show is 10',
'',
'Example usages:',
'jitsu logs all',
'jitsu logs all <number of lines to show>',
'jitsu logs tail',
'jitsu logs app <app name>',
'jitsu logs app <app name> <number of lines to show>'
];

//
// ### function all (callback)
// #### @callback {function} Continuation to pass control to when complete.
// Queries the log API and retrieves the logs for all of the user's apps
// ### function tail (appName, callback)
// #### @appName {string} the application to get the logs for
// #### @callback {function} Continuation to pass control when complete.
// Queries the log API using live streaming
//
logs.all = function (amount, callback) {
logs.tail = function (appName, callback) {
//
// This is defined so that it can get called once all the arguments are
// sorted out.
//

//
// Allows arbitrary amount of arguments
//
if (arguments.length) {
var args = utile.args(arguments);
callback = args.callback;
amount = args[0] || null;
appName = args[0] || null;
}

if (!amount) {
amount = 10;
}
function tail(appName, callback) {
jitsu.apps.view(appName, function (err) {
if (err) {
return err.statusCode === 404
? callback(new Error('Application not found.'), true)
: callback(err);
}

jitsu.logs.byUser(jitsu.config.get('username'), amount, function (err, apps) {
if (err) {
return callback(err);
}
var amount = 10;
jitsu.logs.byApp(appName, amount, function (err, results) {
if (err) {
return callback(err);
}

if (apps.length === 0) {
jitsu.log.warn('No logs for ' + jitsu.config.get('username').magenta + ' from timespan');
return callback();
}
jitsu.log.info('Listing logs for ' + appName.magenta);

function sortLength (lname, rname) {
var llength = apps[lname].data.length,
rlength = apps[rname].data.length;
putLogs(results, appName, amount);

if (llength === rlength) {
return 0;
}
jitsu.logs.live(appName, function (err, socket) {
if (err) return callback(err);

return llength > rlength ? 1 : -1;
}
socket.on('data', printLog);
socket.on('error', function (err) {
return callback(err);
});
});
});
});
}

Object.keys(apps).sort(sortLength).forEach(function (app) {
console.log('App: '.grey + app.magenta);
putLogs(apps[app], app, amount, true);
function getAppName(callback) {
jitsu.package.read(process.cwd(), function (err, pkg) {
if (!err) {
jitsu.log.info('Attempting to load logs for ' + (process.cwd()+ '/package.json').grey);
return callback(null, pkg.name);
}
callback(err);
});
}

callback();
});
if (!appName) {
getAppName(function (err, name) {
if (err) {
jitsu.commands.list(function () {
jitsu.log.info('Which application to view ' + 'logs'.magenta + ' for?');
jitsu.prompt.get(["app name"], function (err, result) {
if (err) {
jitsu.log.error('Prompt error:');
return callback(err);
}
appName = result["app name"];
tail(appName, callback);
});
})
} else {
tail(name, callback);
}
});
} else {
tail(appName, callback);
}
};

logs.all.usage = [
'Print the logs from all applications. The default number of',
'lines to show is 10.',
'jits logs all <number of lines to show>',
logs.tail.usage = [
'The `jitsu logs tail` command will display logs in a live mode',
'jitsu logs tail <app name>',
'',
'Example usage:',
'jitsu logs all',
'jitsu logs all 5'
'Example usages:',
'jitsu logs tail',
'jitsu logs tail app'
];

//
@@ -116,6 +150,7 @@ logs.app = function (appName, amount, callback) {
}

jitsu.log.info('Listing logs for ' + appName.magenta);

putLogs(results, appName, amount);
callback();
});
@@ -132,7 +167,7 @@ logs.app = function (appName, amount, callback) {
});
}

amount = amount || 100;
amount = amount || 10;

if (!appName) {
getAppName(function (err, name) {
@@ -175,7 +210,7 @@ logs.app.usage = [
// #### @showApp {boolean} Value indicating if the app name should be output.
// Parses, formats, and outputs the specified `results` to the user.
//
function putLogs (results, appName, amount, showApp) { //TODO: utilize amount and showApp
function putLogs (results, appName) {
//
// Allows arbitrary amount of arguments
//
@@ -192,31 +227,32 @@ function putLogs (results, appName, amount, showApp) { //TODO: utilize amount an
appName = appName.split('/')[1];
}

results.data = results.data.filter(function (item) {
return item.json && item.json.hasOwnProperty('message');
});

if (results.data.length === 0) {
if (!results || results.length === 0) {
return jitsu.log.warn('No logs for ' + appName.magenta + ' in specified timespan');
}

var logLength = jitsu.config.get('loglength'),
logged = 0;

function sort(first, second) {
return new Date(first.timestamp) - new Date(second.timestamp);
}
results.reverse().forEach(printLog);
}

results.data.sort(sort).forEach(function (datum) {
if (datum.json && datum.json.message !== null && datum.json.app !== null && RegExp('^' + appName + '$').test(datum.json.app)) {
// '[' + datum.json.app.magenta + ']
datum.json.message.split('\n').forEach(function (line) {
var now = new Date(datum.timestamp);
now = dateformat(now, "mm/dd HH:MM:ss Z");
if (line.length) {
console.log('[' + now.toString().yellow + '] ' + line);
}
});
function printLog(datum) {
if (datum.description && datum.description !== null) {

if (jitsu.argv.raw) {
return console.log(datum);
}
});

datum.description.split('\n').forEach(function (line) {
var now = new Date(datum.time * 1000);
now = dateformat(now, "mm/dd HH:MM:ss Z");

var type = (datum.service === 'logs/stderr') ? "err".red : "out".green;

if (line.length) {
console.log(util.format('[%s][%s] %s', now.toString().yellow, type, line));
}
});
}
}
@@ -6,7 +6,6 @@
*/

var path = require('path'),
fs = require('fs'),
jitsu = require('../jitsu');

//
@@ -60,7 +59,12 @@ var defaults = {
root: process.env.HOME,
timeout: 4 * 60 * 1000,
tmproot: path.join(process.env.HOME, '.jitsu/tmp'),
userconfig: '.jitsuconf'
userconfig: '.jitsuconf',
logs: {
host: "logs.nodejitsu.com",
port: 443,
protocol: "https"
}
};

Object.defineProperty(defaults, 'remoteUri', {
@@ -272,6 +272,23 @@ package.validate = function (pkg, dir, options, callback) {
// create operation in the specified `dir`.
//
package.write = function (pkg, dir, create, callback) {
function doWrite(err, result) {
if (err) {
return cb(err);
}
if (!result) {
return create ? package.create(dir, callback) : callback(new Error('Save package.json cancelled.'));
}

fs.readFile(path.resolve(path.join(dir, 'package.json')), function (e, data) {
var offset = data ? ladder(data.toString()) : 2;

fs.writeFile(path.join(dir, 'package.json'), JSON.stringify(pkg, null, offset) + '\n', function (err) {
return err ? callback(err) : callback(null, pkg, dir);
});
});
}

if (!callback) {
callback = create;
create = null;
@@ -288,23 +305,9 @@ package.write = function (pkg, dir, create, callback) {

jitsu.inspect.putObject(pkg, 2);

jitsu.prompt.confirm('Is this ' + 'ok?'.green.bold, { default: 'yes'}, function (err, result) {
if (err) {
return cb(err);
}
if (!result) {
return create ? package.create(dir, callback) : callback(new Error('Save package.json cancelled.'));
}

fs.readFile(path.resolve(path.join(dir, 'package.json')), function (e, data) {
var offset = data ? ladder(data.toString()) : 2;

fs.writeFile(path.join(dir, 'package.json'), JSON.stringify(pkg, null, offset) + '\n', function (err) {
return err ? callback(err) : callback(null, pkg, dir);
});
});

});
return jitsu.argv.release
? doWrite(null, true)
: jitsu.prompt.confirm('Is this ' + 'ok?'.green.bold, { default: 'yes'}, doWrite);
};

//
@@ -371,7 +374,10 @@ package.createTarball = function (dir, version, callback) {
var name = [jitsu.config.get('username'), pkg.name, version || pkg.version].join('-') + '.tgz',
tarball = path.join(jitsu.config.get('tmproot'), name);

fstreamNpm({ path: dir })
fstreamNpm({
path: dir,
ignoreFiles: ['.jitsuignore', '.npmignore', '.gitignore', 'package.json']
})
.on('error', callback)
.pipe(tar.Pack())
.on('error', callback)
@@ -613,7 +619,7 @@ package.properties = function (dir) {
unique: false,
message: 'engines',
conform: semver.validRange,
default: '0.8.x'
default: '0.10.x'
}
];
};
@@ -8,7 +8,7 @@
"platform-as-a-service",
"deployment"
],
"version": "0.12.10-3",
"version": "0.13.3",
"author": "Nodejitsu Inc. <info@nodejitsu.com>",
"maintainers": [
"AvianFlu <avianflu@nodejitsu.com>",
@@ -29,8 +29,8 @@
"fstream": "0.1.22",
"fstream-npm": "0.1.4",
"ladder": "0.0.0",
"npm": "1.2.15",
"nodejitsu-api": "0.4.6",
"npm": "1.3.4",
"nodejitsu-api": "0.5.3",
"opener": "1.3.x",
"pkginfo": "0.3.0",
"progress": "0.1.0",
@@ -54,6 +54,7 @@
},
"engines": {
"node": ">= 0.6.0"
}
},
"license": "MIT"
}

Large diffs are not rendered by default.