Skip to content
Permalink
Browse files

[api] logs: new logging.

  • Loading branch information...
chjj committed Nov 9, 2012
1 parent 796b75d commit 0d69cc51fee4530fdef099443fb1fd40148e085e
Showing with 277 additions and 17 deletions.
  1. +76 −4 node.js/lib/client/client.js
  2. +152 −0 node.js/lib/client/logs-winston.js
  3. +49 −13 node.js/lib/client/logs.js
@@ -44,15 +44,22 @@ util.inherits(Client, EventEmitter);
//
Client.prototype.request = function (method, uri /* variable arguments */) {
var options, args = Array.prototype.slice.call(arguments),
logServer = args[args.length - 1] === 'log' && args.pop(),
success = args.pop(),
callback = args.pop(),
body = typeof args[args.length - 1] === 'object' && !Array.isArray(args[args.length - 1]) && args.pop(),
encoded = new Buffer(this.options.get('username') + ':' + this.options.get('password')).toString('base64'),
proxy = this.options.get('proxy');

var server = logServer
? this.options.get('logServer') || 'https://logs.nodejitsu.com'
: this.options.get('remoteUri');

server = server.replace(/\/+$/g, '');

options = {
method: method || 'GET',
uri: this.options.get('remoteUri') + '/' + uri.join('/'),
uri: server + '/' + uri.join('/'),
headers: {
'Authorization': 'Basic ' + encoded,
'Content-Type': 'application/json'
@@ -107,10 +114,75 @@ Client.prototype.request = function (method, uri /* variable arguments */) {
return callback(error);
}


success(response, result);
});
};

//
// ### function stream (method, uri, options)
// #### @method {string} HTTP Method
// #### @uri {Array} Locator for the Remote Resource
// #### @options {object} Request body.
// Stream a request from log server.
//
Client.prototype.stream = function (method, uri, options) {
var options, args = Array.prototype.slice.call(arguments),
body = options,
encoded,
proxy = this.options.get('proxy'),
logServer = this.options.get('logServer');

encoded = new Buffer(this.options.get('username')
+ ':' + this.options.get('password')).toString('base64');

logServer = logServer || 'https://logs.nodejitsu.com';
logServer = logServer.replace(/\/+$/g, '');

options = {
method: method || 'GET',
uri: logServer + '/' + uri.join('/'),
headers: {
'Authorization': 'Basic ' + encoded,
'Content-Type': 'application/json'
},
timeout: this.options.get('timeout') || 8 * 60 * 1000
};

if (body) {
options.body = JSON.stringify(body);
} else if (method !== 'GET') {
options.body = '{}';
}

if (proxy) {
options.proxy = proxy;
}

this.emit('debug::request', options);

var req = this._request(options),
buff = '';

req.on('data', function (data) {
var data = (buff + data).split(/\n+/),
l = data.length - 1,
i = 0;

for (; i < l; i++) {
try {
req.emit('log', JSON.parse(data[i]));
} catch (e) {
req.emit('error', e);
}
}

buff = data[l];
});

return req;
};

//
// ### function upload (uri, contentType, file, callback, success)
// #### @uri {Array} Locator for the Remote Resource
@@ -176,18 +248,18 @@ Client.prototype.upload = function (uri, contentType, file, callback, success) {

success(response, result);
});

out.on('request', function(request) {
var buffer = 0;
request.on('socket', function(socket) {
request.on('socket', function(socket) {
var id = setInterval(function() {
var data = socket._bytesDispatched || (socket.socket && socket.socket._bytesDispatched);
emitter.emit('data', data - buffer);
buffer = data;
if(buffer >= stat.size) {
clearInterval(id);
emitter.emit('end');
}
}
},100);
});
});
@@ -0,0 +1,152 @@
/*
* logs.js: Client for the Nodejitsu logs API.
*
* (C) 2010, Nodejitsu Inc.
*
*/

var util = require('util'),
Client = require('./client').Client,
defaultUser = require('./helpers').defaultUser;

//
// ### function Logs (options)
// #### @options {Object} Options for this instance
// Constructor function for the Logs resource
// with Nodejitsu's Logs API
//
var Logs = exports.Logs = function (options) {
Client.call(this, options);
};

// Inherit from Client base object
util.inherits(Logs, Client);

//
// ### function _logger (appName, amount, callback)
// Lazily load winston logger.
//
Logs.prototype._logger = function () {
if (this.__logger) return this.__logger;

var winston = require('winston'),
url = require('url');

var logger = new winston.Logger;
var uri = url.parse(this.options.get('logServer'));

logger.add(winston.transports.Http, {
ssl: uri.protocol === 'https:',
host: uri.host,
port: uri.port
});

return this.__logger = logger;
};

//
// ### function byApp (appName, amount, callback)
// #### @appName {string} Name of the application to retrieve
// #### @amount {number} the number of lines to retrieve
// #### @callback {function} Continuation to pass control to when complete.
// It retrieves the specified amount of logs for the application
//
Logs.prototype.byApp = function (appName, amount, callback) {
var appName = defaultUser.call(this, appName),
argv = ['query'].concat(appName.split('/')),
options = {
from: Date.now() - 24 * 60 * 60 * 1000,
until: Date.now(),
rows: amount,
path: argv.join('/')
};

return this._logger().query(options, function (err, results) {
if (err) return callback(err);
return callback(null, results.http.redis);
});
};

//
// ### function byUser (amount, callback)
// #### @username {string} Name of user whose logs we wish to retrieve
// #### @amount {number} the number of lines to retrieve
// #### @callback {function} Continuation to pass control to when complete.
// It retrieves the specified amount of logs for all the applications for the user
//
Logs.prototype.byUser = function (username, amount, callback) {
var options;

if (arguments.length == 2) {
callback = amount;
amount = username;
username = this.options.get('username');
}

if (username == null) {
username = this.options.get('username');
}

options = {
from: Date.now() - 24 * 60 * 60 * 1000,
until: Date.now(),
rows: amount,
path: ['query', username].join('/')
};

return this._logger().query(options, function (err, results) {
if (err) return callback(err);
return callback(null, results.http.redis);
});
};

//
// ### function streamByUser (amount, callback)
// #### @username {string} Name of user whose logs we wish to retrieve
// #### @amount {number} the number of lines to retrieve
// #### @callback {function} Continuation to pass control to when complete.
// Retrieves logs for all the applications for the user.
//
Logs.prototype.streamByUser = function (username, options, callback) {
if (!callback) {
callback = options;
options = null;
}

if (!callback) {
callback = username;
username = null;
}

if (username == null) {
username = this.options.get('username');
}

options = options || { start: -1 };

options.path = ['stream', username].join('/');

return this._logger().stream(options);
};

//
// ### function streamByApp (amount, callback)
// #### @username {string} Name of user whose logs we wish to retrieve
// #### @amount {number} the number of lines to retrieve
// #### @callback {function} Continuation to pass control to when complete.
// Retrieves streaming logs for a user's application.
//
Logs.prototype.streamByApp = function (appName, options, callback) {
if (!callback) {
callback = options;
options = null;
}

var appName = defaultUser.call(this, appName),
argv = ['stream'].concat(appName.split('/'));

options = options || { start: -1 };
options.path = argv.join('/');

return this._logger().stream(options);
};
@@ -31,16 +31,16 @@ util.inherits(Logs, Client);
//
Logs.prototype.byApp = function (appName, amount, callback) {
var appName = defaultUser.call(this, appName),
argv = ['logs'].concat(appName.split('/')),
argv = ['query'].concat(appName.split('/')),
options = {
from: 'NOW-1DAY',
until: 'NOW',
from: Date.now() - 24 * 60 * 60 * 1000,
until: Date.now(),
rows: amount
};

this.request('POST', argv, options, callback, function (res, result) {
callback(null, result);
});
callback(null, result.redis || result);
}, 'log');
};

//
@@ -53,25 +53,61 @@ Logs.prototype.byApp = function (appName, amount, callback) {
Logs.prototype.byUser = function (username, amount, callback) {
var options;


if (arguments.length == 2) {
callback = amount;
amount = username;
username = this.options.get('username');

}

if (typeof username === undefined || username === null) {
if (username == null) {
username = this.options.get('username');
}

options = {
from: 'NOW-1DAY',
until: 'NOW',
from: Date.now() - 24 * 60 * 60 * 1000,
until: Date.now(),
rows: amount
};

this.request('POST', ['logs', username], options, callback, function (res, result) {
callback(null, result);
});
this.request('POST', ['query', username], options, callback, function (res, result) {
callback(null, result.redis || result);
}, 'log');
};

//
// ### function streamByUser (amount, callback)
// #### @username {string} Name of user whose logs we wish to retrieve
// #### @amount {number} the number of lines to retrieve
// #### @callback {function} Continuation to pass control to when complete.
// Retrieves logs for all the applications for the user.
//
Logs.prototype.streamByUser = function (username, options) {
if (username && typeof username === 'object') {
options = username;
username = null;
}

if (username == null) {
username = this.options.get('username');
}

options = options || { start: -1 };

return this.stream('POST', ['stream', username], options);
};

//
// ### function streamByApp (amount, callback)
// #### @username {string} Name of user whose logs we wish to retrieve
// #### @amount {number} the number of lines to retrieve
// #### @callback {function} Continuation to pass control to when complete.
// Retrieves streaming logs for a user's application.
//
Logs.prototype.streamByApp = function (appName, options) {
var appName = defaultUser.call(this, appName),
argv = ['stream'].concat(appName.split('/'));

options = options || { start: -1 };

return this.stream('POST', argv, options);
};

0 comments on commit 0d69cc5

Please sign in to comment.
You can’t perform that action at this time.