162 lines
3.7 KiB
JavaScript
162 lines
3.7 KiB
JavaScript
/*
|
|
* search.js: chainable search functions for Loggly
|
|
*
|
|
* (C) 2010 Charlie Robbins
|
|
* MIT LICENSE
|
|
*
|
|
*/
|
|
|
|
var events = require('events'),
|
|
util = require('util'),
|
|
qs = require('querystring'),
|
|
moment = require('moment'),
|
|
common = require('./common');
|
|
|
|
//
|
|
// ### function Search (options, client, callback)
|
|
// #### @options {Object} Options for the search instance
|
|
// #### @client {Loggly} Loggly API client
|
|
// Chainable search object for Loggly API
|
|
//
|
|
var Search = exports.Search = function (options, client) {
|
|
if (!options || (!options.query && !options.q)) {
|
|
throw new Error('options.query is required to execute a Loggly search.');
|
|
}
|
|
|
|
events.EventEmitter.call(this);
|
|
|
|
if (options.query) {
|
|
options.q = options.query;
|
|
delete options.query;
|
|
}
|
|
|
|
this.options = options;
|
|
this.client = client;
|
|
|
|
//
|
|
// If we're passed a callback, run immediately.
|
|
//
|
|
if (options.callback) {
|
|
this.callback = options.callback;
|
|
delete options.callback;
|
|
this.run();
|
|
}
|
|
};
|
|
|
|
//
|
|
// Inherit from events.EventEmitter
|
|
//
|
|
util.inherits(Search, events.EventEmitter);
|
|
|
|
//
|
|
// ### function run (callback)
|
|
// #### @callback {function} Continuation to respond to when complete
|
|
// Runs the search query for for this instance with the query, and
|
|
// other parameters that have been configured on it.
|
|
//
|
|
Search.prototype.run = function (callback) {
|
|
var self = this,
|
|
responded;
|
|
|
|
//
|
|
// Trim the search query
|
|
//
|
|
this.options.q.trim();
|
|
|
|
//
|
|
// Update the callback for this instance if it's passed
|
|
//
|
|
this.callback = callback || this.callback;
|
|
if (!this.callback) {
|
|
throw new Error('Cannot run search without a callback function.');
|
|
}
|
|
|
|
//
|
|
// ### function respond (arguments...)
|
|
// Responds only once.
|
|
//
|
|
function respond() {
|
|
if (!responded) {
|
|
responded = true;
|
|
self.callback.apply(null, arguments);
|
|
}
|
|
}
|
|
|
|
//
|
|
// ### function awaitResults (rsid)
|
|
// Checks the Loggly API on an interval for the
|
|
// results from the specified `rsid`.
|
|
//
|
|
function awaitResults(rsid) {
|
|
if (!rsid || !rsid.id) {
|
|
return respond(rsid);
|
|
}
|
|
|
|
common.loggly({
|
|
uri: self.client.logglyUrl('events?' + qs.stringify({ rsid: rsid.id })),
|
|
auth: self.client.auth,
|
|
json: true
|
|
}, respond, function (res, body) {
|
|
var results;
|
|
try { results = JSON.parse(body) }
|
|
catch (ex) { return respond(ex) }
|
|
respond(null, results);
|
|
});
|
|
}
|
|
|
|
//
|
|
// Check any time ranges (if supplied) to ensure
|
|
// they are valid.
|
|
//
|
|
this._checkRange();
|
|
|
|
common.loggly({
|
|
uri: this.client.logglyUrl('search?' + qs.stringify(this.options)),
|
|
auth: this.client.auth,
|
|
json: true
|
|
}, this.callback, function (res, body) {
|
|
var rsid;
|
|
try { rsid = JSON.parse(body).rsid }
|
|
catch (ex) { rsid = ex }
|
|
|
|
self.emit('rsid', rsid);
|
|
awaitResults(rsid);
|
|
});
|
|
|
|
return this;
|
|
};
|
|
|
|
//
|
|
// ### function _checkRange ()
|
|
// Checks if the range that has been configured for this
|
|
// instance is valid and updates if it is not.
|
|
//
|
|
Search.prototype._checkRange = function () {
|
|
if (!this.options.until && !this.options.from) {
|
|
return;
|
|
}
|
|
|
|
this.options.until = this.options.until || 'now';
|
|
this.options.from = this.options.from || '-24h';
|
|
|
|
if (!moment.parseDate(this.options.until)) {
|
|
this.options.until = 'now';
|
|
}
|
|
|
|
if (!moment.parseDate(this.options.from)) {
|
|
this.options.from = '-24h';
|
|
}
|
|
|
|
if (moment.fromDates(this.options.from, this.options.until) < 0
|
|
|| this.options.until === this.options.from) {
|
|
//
|
|
// If the length of the moment for this Search instance is
|
|
// negative then set it to default values
|
|
//
|
|
this.options.until = 'now';
|
|
this.options.from = '-24h';
|
|
}
|
|
|
|
return this;
|
|
};
|