From 5bb70fbe5824642cbe85b7f4156f3259db37be4e Mon Sep 17 00:00:00 2001 From: Spencer Alger Date: Fri, 15 Nov 2013 19:10:45 -0700 Subject: [PATCH] Moved the curl formatting into the log and changed the arguments for the log event listeneres to receive both the "message" and the "curlCommand". Added a "tracer" logger which allows you to create log files that a executable scripts. Those scripts will write all of the log messages as script comments, and not comment out the curlCommands, so that they can trace their application and use the generated script to recreate the issue. Most changes are simply cased by adding the "unused" rule to jshint. --- .jshintrc | 1 + Gruntfile.js | 2 - scripts/clean.js | 2 +- scripts/generate/js_api/actions.js | 2 +- scripts/generate/js_api/index.js | 7 --- .../generate/js_api/templates/api_file.tmpl | 2 - scripts/generate/js_api/templates/index.js | 42 ------------- scripts/generate/logs/index.js | 1 - scripts/generate/logs/samples/index.js | 13 ++-- scripts/generate/logs/samples/random_list.js | 2 - scripts/generate/yaml_tests/index.js | 1 - scripts/server.js | 3 +- scripts/stupid-benchmark.js | 62 +++++++++++++------ src/lib/api.js | 2 - src/lib/client.js | 2 +- src/lib/client_action.js | 9 +-- src/lib/client_config.js | 13 ++-- src/lib/connection_pool.js | 36 ++++++----- src/lib/connectors/angular.js | 5 -- src/lib/connectors/http.js | 14 ++--- src/lib/connectors/jquery.js | 2 +- src/lib/connectors/xhr.js | 3 +- src/lib/log.js | 24 ++++++- src/lib/logger.js | 10 +-- src/lib/loggers/console.js | 18 +++--- src/lib/loggers/file.js | 15 ++--- src/lib/loggers/stdio.js | 19 ++---- src/lib/loggers/stream.js | 10 ++- src/lib/loggers/tracer.js | 40 ++++++++++++ src/lib/transport.js | 5 +- src/lib/utils.js | 7 +-- test/serializers/json.test.js! | 40 ------------ 32 files changed, 185 insertions(+), 229 deletions(-) create mode 100755 src/lib/loggers/tracer.js delete mode 100755 test/serializers/json.test.js! diff --git a/.jshintrc b/.jshintrc index b93ee9388..d6a7bd3b3 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,4 +1,5 @@ { + "unused": true, "node": true, "white": true, "bitwise": false, diff --git a/Gruntfile.js b/Gruntfile.js index 2021cb6ba..fc077079f 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -4,7 +4,6 @@ module.exports = function (grunt) { var _ = require('lodash'); - var child_process = require('child_process'); var sharedBrowserfyExclusions = [ 'when', @@ -43,7 +42,6 @@ module.exports = function (grunt) { options: { require: 'should', reporter: 'dot', - bail: true, timeout: 11e3 } }, diff --git a/scripts/clean.js b/scripts/clean.js index 356c8d1e4..1c9187d7d 100644 --- a/scripts/clean.js +++ b/scripts/clean.js @@ -23,7 +23,7 @@ module.exports = function (path) { function rmDirRecursive(path) { - fs.readdirSync(path).forEach(function (file, index) { + fs.readdirSync(path).forEach(function (file) { var curPath = path + '/' + file; if (fs.statSync(curPath).isDirectory()) { // recurse rmDirRecursive(curPath); diff --git a/scripts/generate/js_api/actions.js b/scripts/generate/js_api/actions.js index 1037d0f51..606227b4f 100644 --- a/scripts/generate/js_api/actions.js +++ b/scripts/generate/js_api/actions.js @@ -64,7 +64,7 @@ function transformFile(entry) { } var urls = _.difference(def.url.paths, aliases[name]); - urls = _.map(urls, function (url, i) { + urls = _.map(urls, function (url) { var optionalVars = {}; var requiredVars = {}; var param; diff --git a/scripts/generate/js_api/index.js b/scripts/generate/js_api/index.js index bf87df017..95790a535 100644 --- a/scripts/generate/js_api/index.js +++ b/scripts/generate/js_api/index.js @@ -1,21 +1,14 @@ var _ = require('../../../src/lib/utils'); -var asset = require('assert'); -var path = require('path'); var fs = require('fs'); -var mkdirp = require('mkdirp'); var templates = require('./templates'); var clean = require('../../clean'); var restSpecUpdated = require('../../rest_spec_updated'); -var urlParamRE = /\{(\w+)\}/g; var outputPath = _.joinPath(__dirname, '../../../src/lib/api.js'); var docOutputPath = _.joinPath(__dirname, '../../../docs/api.md'); -var lastFetchTmp = path.join(__dirname, './last_fetch.tmp'); function download() { require('./actions').on('ready', function (actions) { - var defs = []; - var namespaces = _.filter(_.map(actions, function (action) { if (~action.location.indexOf('.')) { var path = action.location.split('.').slice(0, -1); diff --git a/scripts/generate/js_api/templates/api_file.tmpl b/scripts/generate/js_api/templates/api_file.tmpl index 50ffb5124..25d1efde9 100644 --- a/scripts/generate/js_api/templates/api_file.tmpl +++ b/scripts/generate/js_api/templates/api_file.tmpl @@ -1,8 +1,6 @@ /* jshint maxlen: false */ var ca = require('./client_action'); -var errors = require('./errors'); - var api = module.exports = {}; api._namespaces = <%= stringify(namespaces) %>;<% diff --git a/scripts/generate/js_api/templates/index.js b/scripts/generate/js_api/templates/index.js index bbb3ed2fc..2f2f91573 100644 --- a/scripts/generate/js_api/templates/index.js +++ b/scripts/generate/js_api/templates/index.js @@ -4,48 +4,6 @@ var fs = require('fs'); var path = require('path'); -/** - * Simple manager to take care of indentation - * @param {number} i - Width of the indentation - * @return {function} - Call this to add a new line to the output - */ -function lines(i) { - - function l(line) { - if (line === '') { - // no indent on empty lines - l.lines.push(''); - } else if (line === void 0) { - l.lines.push(_.repeat(' ', l.indent) + line); - } - return l; - } - - l.lines = []; - l.indent = i || 0; - - l.split = function (toSplit) { - _.each(toSplit.split(/\r?\n/), l); - return l; - }; - - l.in = function (line) { - l.indent += 2; - return l(line); - }; - - l.out = function (line) { - l.indent -= 2; - return l(line); - }; - - l.toString = function () { - return l.lines.join('\n'); - }; - - return l; -} - /** * we want strings in code to use single-quotes, so this will JSON encode vars, but then * modify them to follow our code standards. diff --git a/scripts/generate/logs/index.js b/scripts/generate/logs/index.js index 5a1f33589..0f14f14ae 100644 --- a/scripts/generate/logs/index.js +++ b/scripts/generate/logs/index.js @@ -45,7 +45,6 @@ if (argv.host) { } var client = new es.Client(clientConfig); -var log = client.config.log; console.log('Generating', count, 'events across ±', days, 'days'); diff --git a/scripts/generate/logs/samples/index.js b/scripts/generate/logs/samples/index.js index a8410ff4f..8253132e3 100644 --- a/scripts/generate/logs/samples/index.js +++ b/scripts/generate/logs/samples/index.js @@ -1,10 +1,9 @@ -var _ = require('../../../../src/lib/utils'), - WeightedList = require('./weighted_list'), - RandomList = require('./random_list'), - IpGenerator = require('./ip_generator'), - Stochator = require('./stochator'), - moment = require('moment'), - dayMs = 86400000; +var _ = require('../../../../src/lib/utils'); +var WeightedList = require('./weighted_list'); +var RandomList = require('./random_list'); +var IpGenerator = require('./ip_generator'); +var Stochator = require('./stochator'); +var dayMs = 86400000; exports.make = function (startingMoment, endingMoment) { diff --git a/scripts/generate/logs/samples/random_list.js b/scripts/generate/logs/samples/random_list.js index 0f298c9dc..ff7462cc2 100644 --- a/scripts/generate/logs/samples/random_list.js +++ b/scripts/generate/logs/samples/random_list.js @@ -4,8 +4,6 @@ module.exports = RandomList; -var _ = require('../../../../src/lib/utils'); - function RandomList(list) { this.get = function () { return list[Math.round(Math.random() * list.length)]; diff --git a/scripts/generate/yaml_tests/index.js b/scripts/generate/yaml_tests/index.js index 96ed52ed2..5828f2020 100644 --- a/scripts/generate/yaml_tests/index.js +++ b/scripts/generate/yaml_tests/index.js @@ -7,7 +7,6 @@ var path = require('path'); var jsYaml = require('js-yaml'); var spec = require('../../get_spec'); var clean = require('../../clean'); -var _ = require('../../../src/lib/utils'); var restSpecUpdated = require('../../rest_spec_updated'); var testFile = path.resolve(__dirname, '../../../test/integration/yaml_suite/yaml_tests.json'); diff --git a/scripts/server.js b/scripts/server.js index 7d87bf89c..5ae66c3c4 100644 --- a/scripts/server.js +++ b/scripts/server.js @@ -1,5 +1,4 @@ -var http = require('http'), - async = require('async'); +var http = require('http'); var server = http.createServer(function (req, resp) { var closed, count = 0; diff --git a/scripts/stupid-benchmark.js b/scripts/stupid-benchmark.js index 110550854..950cdb1e6 100644 --- a/scripts/stupid-benchmark.js +++ b/scripts/stupid-benchmark.js @@ -1,46 +1,70 @@ var es = require('../src/elasticsearch'); var async = require('async'); +var argv = require('optimist').default({ + indx: 'test-docs', + type: 'test-doc', + warm: 10000, + docs: 100000, + sync: false, + sock: 100 + }) + .boolean('sync') + .argv; -function getMs() { - var hr = process.hrtime(); - return (hr[0] * 1e9 + hr[1]) / 1e6; +function hrtime(start) { + var hr = start ? process.hrtime(start) : process.hrtime(); + return start ? Math.round(((hr[0] * 1e9 + hr[1]) / 1e6) * 100) / 100 : hr; } var client = new es.Client({ hosts: 'localhost:9200', log: null, - maxSockets: 100 + maxSockets: argv.sock }); async.series([ function (done) { - console.log('clearing existing "test-docs" indices'); + console.log('removing existing "%s" index', argv.indx); client.indices.delete({ - index: 'test-docs', + index: argv.indx, ignore: 404 }, done); }, function (done) { - console.log('waiting for cluster'); - client.cluster.health({ - wait_for_status: 'yellow' + console.log('creating new "%s" index', argv.indx); + client.indices.create({ + index: argv.indx, + body: {} }, done); }, function (done) { - var times = 1e4; - console.log('creating %d docs', times); - var start = getMs(); - async.times(times, function (i, done) { + console.log('warnming up index with %d docs', argv.warm); + async.times(argv.warm, function (i, done) { client.index({ - index: 'test-docs', - type: 'test-doc', + index: argv.indx, + type: argv.type, + body: {} + }, done); + }, done); + }, + function (done) { + console.log('waiting for cluster to go yellow'); + client.cluster.health({ + waitForStatus: 'yellow' + }, done); + }, + function (done) { + console.log('creating %d docs ' + (async.sync ? 'in series' : argv.sock + ' requests at a time'), argv.docs); + var start = hrtime(); + async[argv.sync ? 'timesSeries' : 'times'](argv.docs, function (i, done) { + client.index({ + index: argv.indx, + type: argv.type, body: {} }, done); }, function (err) { - console.log('complete in', Math.round((getMs() - start) * 100) / 100, 'ms'); - if (err) { - client.config.log.error(err); - } + console.log('complete in', hrtime(start), 'ms'); + done(err); }); } ], function (err) { diff --git a/src/lib/api.js b/src/lib/api.js index 1e5f7756e..d641c067e 100644 --- a/src/lib/api.js +++ b/src/lib/api.js @@ -1,8 +1,6 @@ /* jshint maxlen: false */ var ca = require('./client_action'); -var errors = require('./errors'); - var api = module.exports = {}; api._namespaces = ['cluster', 'indices']; diff --git a/src/lib/client.js b/src/lib/client.js index e445fc0c7..71655f7a5 100755 --- a/src/lib/client.js +++ b/src/lib/client.js @@ -52,7 +52,7 @@ function Client(config) { } } -Client.prototype = _.clone(api); +Client.prototype = api; /** * Ping some node to ensure that the cluster is available in some respect diff --git a/src/lib/client_action.js b/src/lib/client_action.js index e0975bfc3..395ff6059 100644 --- a/src/lib/client_action.js +++ b/src/lib/client_action.js @@ -8,9 +8,7 @@ module.exports = function ClientAction(spec, client) { }; }; -var errors = require('./errors'); var _ = require('./utils'); -var urlParamRE = /\{(\w+)\}/g; var castType = { enum: function (param, val, name) { @@ -45,7 +43,7 @@ var castType = { return !!val; } }, - boolean: function (param, val, name) { + boolean: function (param, val) { val = _.isString(val) ? val.toLowerCase() : val; return (val === 'no' || val === 'off') ? false : !!val; }, @@ -139,7 +137,6 @@ function exec(transport, spec, params, cb) { } var request = {}; - var parts = {}; var query = {}; var i; @@ -147,8 +144,6 @@ function exec(transport, spec, params, cb) { return _.nextTick(cb, new TypeError('A request body is required.')); } - params.body && (request.body = params.body); - params.ignore && (request.ignore = _.isArray(params.ignore) ? params.ignore : [params.ignore]); if (params.timeout === void 0) { request.timeout = 10000; } else { @@ -156,6 +151,8 @@ function exec(transport, spec, params, cb) { } // copy over some properties from the spec + params.body && (request.body = params.body); + params.ignore && (request.ignore = _.isArray(params.ignore) ? params.ignore : [params.ignore]); spec.bulkBody && (request.bulkBody = true); spec.castExists && (request.castExists = true); diff --git a/src/lib/client_config.js b/src/lib/client_config.js index f43aa57bc..0e843661b 100644 --- a/src/lib/client_config.js +++ b/src/lib/client_config.js @@ -6,7 +6,6 @@ */ module.exports = ClientConfig; -var url = require('url'); var _ = require('./utils'); var Host = require('./host'); var selectors = require('./selectors'); @@ -20,6 +19,7 @@ if (process.browser) { connectors.Http = require('./connectors/http'); } +// remove connectors that have been excluded in the build _.each(connectors, function (conn, name) { if (typeof conn !== 'function') { delete connectors[name]; @@ -30,8 +30,7 @@ var serializers = { Json: require('./serializers/json') }; -var extractHostPartsRE = /\[([^:]+):(\d+)]/; -var hostProtocolRE = /^([a-z]+:)?\/\//; +var extractHostPartsRE = /\[([^:]+):(\d+)\]/; var defaultClasses = { log: require('./log'), @@ -62,17 +61,18 @@ var defaultConfig = { timeout: 10000, deadTimeout: 60000, maxSockets: 10, + // transforms the response from /_cluster/nodes nodesToHostCallback: function (nodes) { var hosts = []; _.each(nodes, function (node, id) { - var hostnameMatches = extractHostPartsRE.exec(node.host); + var hostnameMatches = extractHostPartsRE.exec(node.http_address); hosts.push({ host: hostnameMatches[1], port: hostnameMatches[2], _meta: { id: id, name: node.name, - servername: node.host, + hostname: node.hostname, version: node.version } }); @@ -128,9 +128,6 @@ function ClientConfig(config) { } ClientConfig.prototype.prepareHosts = function (hosts) { - var host; - var i; - if (!_.isArray(hosts)) { hosts = [hosts]; } diff --git a/src/lib/connection_pool.js b/src/lib/connection_pool.js index 557d99de5..bc8c41000 100644 --- a/src/lib/connection_pool.js +++ b/src/lib/connection_pool.js @@ -9,9 +9,6 @@ module.exports = ConnectionPool; var _ = require('./utils'); -var selectors = require('./selectors'); -var EventEmitter = require('events').EventEmitter; -var errors = require('./errors'); var Host = require('./host'); function ConnectionPool(config) { @@ -37,7 +34,7 @@ ConnectionPool.prototype.select = function (cb) { } } } else { - cb(); + _.nextTick(cb, null, this.connections.dead[0]); } }; @@ -45,9 +42,14 @@ ConnectionPool.prototype.onStatusChanged = _.handler(function (status, oldStatus var from, to, index; if (oldStatus === status) { - return true; + if (status === 'dead') { + // we want to remove the connection from it's current possition and move it to the end + status = 'redead'; + } else { + return true; + } } else { - this.config.log.info('connection id:', connection.__id, 'is', status); + this.config.log.info('connection id:', connection.id, 'is', status); } switch (status) { @@ -59,6 +61,10 @@ ConnectionPool.prototype.onStatusChanged = _.handler(function (status, oldStatus from = this.connections.alive; to = this.connections.dead; break; + case 'redead': + from = this.connections.dead; + to = this.connections.dead; + break; case 'closed': from = this.connections[oldStatus]; break; @@ -79,17 +85,17 @@ ConnectionPool.prototype.onStatusChanged = _.handler(function (status, oldStatus } }); -ConnectionPool.prototype._add = function (connection) { - if (!this.index[connection.__id]) { - this.index[connection.__id] = connection; +ConnectionPool.prototype.addConnection = function (connection) { + if (!this.index[connection.id]) { + this.index[connection.id] = connection; connection.on('status changed', this.bound.onStatusChanged); connection.setStatus('alive'); } }; -ConnectionPool.prototype._remove = function (connection) { - if (this.index[connection.__id]) { - delete this.index[connection.__id]; +ConnectionPool.prototype.removeConnection = function (connection) { + if (this.index[connection.id]) { + delete this.index[connection.id]; connection.setStatus('closed'); connection.removeListener('status changed', this.bound.onStatusChanged); } @@ -110,13 +116,13 @@ ConnectionPool.prototype.setNodes = function (nodeConfigs) { delete toRemove[id]; } else { connection = new this.config.connectionClass(node, this.config); - connection.__id = id; - this._add(connection); + connection.id = id; + this.addConnection(connection); } } } - _.each(toRemove, this._remove, this); + _.each(toRemove, this.removeConnection, this); }; ConnectionPool.prototype.close = function () { diff --git a/src/lib/connectors/angular.js b/src/lib/connectors/angular.js index 8d7b7bc23..c30993a78 100644 --- a/src/lib/connectors/angular.js +++ b/src/lib/connectors/angular.js @@ -10,16 +10,12 @@ var _ = require('../utils'); var ConnectionAbstract = require('../connection'); var ConnectionFault = require('../errors').ConnectionFault; -/* global angular */ - function AngularConnector(host, config) { ConnectionAbstract.call(this, host, config); } _.inherits(AngularConnector, ConnectionAbstract); AngularConnector.prototype.request = function (params, cb) { - var timeoutId; - this.$http({ method: params.method, url: this.host.makeUrl(params), @@ -31,7 +27,6 @@ AngularConnector.prototype.request = function (params, cb) { }, function (err) { cb(new ConnectionFault(err.message)); }); - }; // must be overwritten before this connection can be used diff --git a/src/lib/connectors/http.js b/src/lib/connectors/http.js index bce4d80f9..d9a1adeaa 100644 --- a/src/lib/connectors/http.js +++ b/src/lib/connectors/http.js @@ -8,22 +8,21 @@ */ module.exports = HttpConnector; -var http = require('http'); -var https = require('https'); +var handles = { + http: require('http'), + https: require('https') +}; var _ = require('../utils'); var errors = require('../errors'); var qs = require('querystring'); var KeepAliveAgent = require('agentkeepalive/lib/agent'); var ConnectionAbstract = require('../connection'); -var defaultHeaders = { - 'connection': 'keep-alive' -}; function HttpConnector(host, config) { ConnectionAbstract.call(this, host, config); - this.hand = require(this.host.protocol); + this.hand = handles[this.host.protocol]; this.agent = new KeepAliveAgent({ maxSockets: 1, maxKeepAliveRequests: 0, // max requests per keepalive socket, default is 0, no limit. @@ -58,7 +57,6 @@ HttpConnector.prototype.makeReqParams = function (params) { }; var query = this.host.query ? this.host.query : null; - var queryStr; if (typeof query === 'string') { query = qs.parse(query); @@ -85,9 +83,7 @@ HttpConnector.prototype.request = function (params, cb) { var incoming; var timeoutId; var request; - var requestId = this.requestCount; var response; - var responseStarted = false; var status = 0; var timeout = params.timeout || this.config.timeout; var log = this.config.log; diff --git a/src/lib/connectors/jquery.js b/src/lib/connectors/jquery.js index 10e58af45..95ceebaf1 100644 --- a/src/lib/connectors/jquery.js +++ b/src/lib/connectors/jquery.js @@ -10,7 +10,7 @@ module.exports = JqueryConnector; function JqueryConnector() {} JqueryConnector.prototype.request = function (params, cb) { - var $xhr = jQuery.ajax(params).done(cb); + jQuery.ajax(params).done(cb); }; diff --git a/src/lib/connectors/xhr.js b/src/lib/connectors/xhr.js index 618686e03..13c178dac 100644 --- a/src/lib/connectors/xhr.js +++ b/src/lib/connectors/xhr.js @@ -32,6 +32,7 @@ if (typeof XMLHttpRequest !== 'undefined') { } else { // find the first MS implementation available getXhr = _.first(['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], function (appName) { + /* jshint unused: false */ try { var test = new window.ActiveXObject(appName); return function () { @@ -61,7 +62,7 @@ XhrConnector.prototype.request = function (params, cb) { xhr.open(params.method, url, async); } - xhr.onreadystatechange = function (e) { + xhr.onreadystatechange = function () { if (xhr.readyState === 4) { clearTimeout(timeoutId); log.trace(params.method, url, params.body, xhr.responseText, xhr.status); diff --git a/src/lib/log.js b/src/lib/log.js index 468609701..cafbb2d3b 100755 --- a/src/lib/log.js +++ b/src/lib/log.js @@ -9,7 +9,8 @@ if (process.browser) { var loggers = { File: require('./loggers/file'), Stream: require('./loggers/file'), - Stdio: require('./loggers/stdio') + Stdio: require('./loggers/stdio'), + Tracer: require('./loggers/tracer') }; } @@ -290,8 +291,27 @@ Log.prototype.trace = function (method, requestUrl, body, responseBody, response requestUrl.pathname = requestUrl.path.split('?').shift(); } - return this.emit('trace', method, url.format(requestUrl), body, responseBody, responseStatus); + requestUrl = url.format(requestUrl); + + var message = '<- ' + responseStatus + '\n' + prettyJSON(responseBody); + + /* jshint quotmark: double */ + var curlCall = "curl '" + requestUrl.replace(/'/g, "\\'") + "' -X" + method.toUpperCase(); + if (body) { + curlCall += " -d '" + prettyJSON(body) + "'"; + } + /* jshint quotmark: single */ + + return this.emit('trace', message, curlCall); } }; +function prettyJSON(body) { + try { + return JSON.stringify(JSON.parse(body), null, ' ').replace(/'/g, '\\\''); + } catch (e) { + return body || ''; + } +} + module.exports = Log; diff --git a/src/lib/logger.js b/src/lib/logger.js index 673b31327..49939ae07 100644 --- a/src/lib/logger.js +++ b/src/lib/logger.js @@ -1,5 +1,4 @@ -var Log = require('./log'), - _ = require('./utils'); +var _ = require('./utils'); /** * Abstract class providing common functionality to loggers @@ -145,12 +144,7 @@ LoggerAbstract.prototype.onDebug = _.handler(function (msg) { * @param {String} msg - The message to be logged * @return {undefined} */ -LoggerAbstract.prototype.onTrace = _.handler(function (method, url, body, responseBody, responseStatus) { - var message = 'curl "' + url.replace(/"/g, '\\"') + '" -X' + method.toUpperCase(); - if (body) { - message += ' -d "' + body.replace(/"/g, '\\"') + '"'; - } - message += '\n<- ' + responseStatus + '\n' + responseBody; +LoggerAbstract.prototype.onTrace = _.handler(function (message) { this.write('TRACE', message); }); diff --git a/src/lib/loggers/console.js b/src/lib/loggers/console.js index 9bc93a884..1d9a567d2 100644 --- a/src/lib/loggers/console.js +++ b/src/lib/loggers/console.js @@ -16,6 +16,7 @@ var LoggerAbstract = require('../logger'); var _ = require('../utils'); function Console(config, bridge) { + // call my super LoggerAbstract.call(this, config, bridge); // config/state @@ -31,9 +32,11 @@ _.inherits(Console, LoggerAbstract); Console.prototype.setupListeners = function (levels) { // since some of our functions are bound a bit differently (to the console) // create some of the bound properties manually + this.bound.onError = this.onError; this.bound.onWarning = this.onWarning; this.bound.onInfo = this.onInfo; this.bound.onDebug = this.onDebug; + this.bound.onTrace = this.onTrace; // call the super method LoggerAbstract.prototype.setupListeners.call(this, levels); @@ -47,13 +50,13 @@ Console.prototype.setupListeners = function (levels) { * @param {Error} e - The Error object to log * @return {undefined} */ -Console.prototype.onError = _.handler(function (e) { +Console.prototype.onError = function (e) { if (console.error && console.trace) { console.error(e.name === 'Error' ? 'ERROR' : e.name, e.stack || e.message); } else { console.log(e.name === 'Error' ? 'ERROR' : e.name, e.stack || e.message); } -}); +}; /** * Handler for the bridges "warning" event @@ -97,11 +100,6 @@ Console.prototype.onDebug = function (msg) { * @private * @return {undefined} */ -Console.prototype.onTrace = _.handler(function (method, url, body, responseBody, responseStatus) { - var message = 'curl "' + url.replace(/"/g, '\\"') + '" -X' + method.toUpperCase(); - if (body) { - message += ' -d "' + body.replace(/"/g, '\\"') + '"'; - } - message += '\n<- ' + responseStatus + '\n' + responseBody; - console.log('TRACE:\n' + message + '\n'); -}); +Console.prototype.onTrace = function (message, curlCall) { + console.log('TRACE:\n' + curlCall + '\n' + message); +}; diff --git a/src/lib/loggers/file.js b/src/lib/loggers/file.js index 6601a3fdc..ec32e2e87 100755 --- a/src/lib/loggers/file.js +++ b/src/lib/loggers/file.js @@ -11,19 +11,20 @@ module.exports = File; -var StreamLogger = require('./stream'), - _ = require('../utils'), - fs = require('fs'); +var StreamLogger = require('./stream'); +var _ = require('../utils'); +var fs = require('fs'); function File(config, bridge) { - this.path = config.path; - - config.stream = fs.createWriteStream(config.path, { + // setup the stream before calling the super + this.path = config.path || 'elasticsearch.log'; + config.stream = fs.createWriteStream(this.path, { flags: 'a', encoding: 'utf8' }); - File.callSuper(this, arguments); + // call my super + StreamLogger.call(this, config, bridge); } _.inherits(File, StreamLogger); diff --git a/src/lib/loggers/stdio.js b/src/lib/loggers/stdio.js index 58a3ab90a..54f00b0bc 100755 --- a/src/lib/loggers/stdio.js +++ b/src/lib/loggers/stdio.js @@ -41,7 +41,8 @@ var defaultColors = { }; function Stdio(config, bridge) { - Stdio.callSuper(this, arguments); + // call my super + LoggerAbstract.call(this, config, bridge); // config/state this.color = Boolean(_.has(config, 'color') ? config.color : chalk.supportsColor); @@ -124,18 +125,6 @@ Stdio.prototype.onDebug = _.handler(function (msg) { * @private * @return {undefined} */ -Stdio.prototype.onTrace = _.handler(function (method, url, body, resp, status) { - var message = 'curl "' + url.replace(/"/g, '\\"') + '" -X' + method.toUpperCase(); - if (body) { - message += ' -d "' + body.replace(/"/g, '\\"') + '"'; - } - message += '\n<- '; - if (this.color) { - message += this.colors.traceStatus(status); - } else { - message += status; - } - message += '\n' + resp; - - this.write(process.stdout, 'TRACE', this.colors.trace, message); +Stdio.prototype.onTrace = _.handler(function (message, curlCall) { + this.write(process.stdout, 'TRACE', this.colors.trace, curlCall + '\n' + message); }); diff --git a/src/lib/loggers/stream.js b/src/lib/loggers/stream.js index 809c11e2d..8e4ec8794 100755 --- a/src/lib/loggers/stream.js +++ b/src/lib/loggers/stream.js @@ -12,14 +12,12 @@ module.exports = Stream; -var LoggerAbstract = require('../logger'), - nodeStreams = require('stream'), - _ = require('../utils'), - fs = require('fs'); +var LoggerAbstract = require('../logger'); +var _ = require('../utils'); function Stream(config, bridge) { - Stream.callSuper(this, arguments); - _.makeBoundMethods(this); + // call my super + LoggerAbstract.call(this, config, bridge); if (config.stream.write && config.stream.end) { this.stream = config.stream; diff --git a/src/lib/loggers/tracer.js b/src/lib/loggers/tracer.js new file mode 100755 index 000000000..248fbede4 --- /dev/null +++ b/src/lib/loggers/tracer.js @@ -0,0 +1,40 @@ +/** + * Logger that writes to a file, but the file can be executed as a shell script, + * meaning everything but the curl commands are commented out + * + * @class Loggers.Tracer + * @extends StreamLogger + * @constructor + * @param {Object} config - The configuration for the Logger (See LoggerAbstract for generic options) + * @param {String} config.path - The location to write + * @param {Log} bridge - The object that triggers logging events, which we will record + */ + +module.exports = Tracer; + +var FileLogger = require('./file'); +var _ = require('../utils'); + +function Tracer(config, bridge) { + // call my super + FileLogger.call(this, config, bridge); +} +_.inherits(Tracer, FileLogger); + +Tracer.prototype.onTrace = _.handler(function (message, curlCall) { + this.write('TRACE', message, curlCall); +}); + +function comment(str) { + return _.map(str.split(/\r?\n/g), function (line) { + return '# ' + line; + }).join('\n'); +} + +Tracer.prototype.write = function (label, message, curlCall) { + this.stream.write( + comment(label + ': ' + this.timestamp()) + '\n' + (curlCall ? curlCall + '\n' : '') + + comment(message) + '\n\n', + 'utf8' + ); +}; diff --git a/src/lib/transport.js b/src/lib/transport.js index 76b2ce202..f7519356b 100644 --- a/src/lib/transport.js +++ b/src/lib/transport.js @@ -140,8 +140,9 @@ Transport.prototype.request = function (params, cb) { abort: abortRequest }; } else { - request = when.defer(); - request.abort = abortRequest; + var defer = when.defer(); + defer.promise.abort = abortRequest; + request = defer.promise; } return request; diff --git a/src/lib/utils.js b/src/lib/utils.js index 22b2df88e..162d006e2 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -1,6 +1,6 @@ -var path = require('path'), - _ = require('lodash'), - nodeUtils = require('util'); +var path = require('path'); +var _ = require('lodash'); +var nodeUtils = require('util'); /** * Custom utils library, basically a modified version of [lodash](http://lodash.com/docs) + @@ -120,7 +120,6 @@ utils.ucfirst = function (word) { */ function adjustWordCase(firstWordCap, otherWordsCap, sep) { return function (string) { - var inWord = false; var i = 0; var words = []; var word = ''; diff --git a/test/serializers/json.test.js! b/test/serializers/json.test.js! deleted file mode 100755 index 0261b1c69..000000000 --- a/test/serializers/json.test.js! +++ /dev/null @@ -1,40 +0,0 @@ -/* JSON Serializer tests */ - -var JsonSerializer = require('../../src/lib/serializers/Json'); - -describe('json serializer', function () { - - var json; - - beforeEach(function () { - json = new JsonSerializer(); - }); - - it('creates simple json strings', function () { - json.serialize({foo: true}).should.eql('{"foo":true}'); - }); - - it('creates pretty json strings', function () { - json.serialize({foo: true, bake: 'cake', 'with': ['bacon']}, null, ' ') - .should.eql(['{', - ' "foo": true,', - ' "bake": "cake",', - ' "with": [', - ' "bacon"', - ' ]', - '}'].join('\n')); - }); - - it('reads simple json strings', function () { - json.unserialize('{"foo":true}').should.eql({ foo: true }); - }); - - it('does not create date objects', function () { - json - .unserialize('{"date":"2012-04-23T18:25:43.511Z"}') - .should.eql({ - date: '2012-04-23T18:25:43.511Z' - }); - }); - -}); \ No newline at end of file