| var util = require('util'), |
| winston = require('../../winston'), |
| request = require('request'), |
| Stream = require('stream').Stream; |
| |
| // |
| // ### function Http (options) |
| // #### @options {Object} Options for this instance. |
| // Constructor function for the Http transport object responsible |
| // for persisting log messages and metadata to a terminal or TTY. |
| // |
| var Http = exports.Http = function (options) { |
| options = options || {}; |
| |
| this.name = 'http'; |
| this.ssl = !!options.ssl; |
| this.host = options.host || 'localhost'; |
| this.port = options.port; |
| this.auth = options.auth; |
| this.path = options.path || ''; |
| |
| if (!this.port) { |
| this.port = this.ssl ? 443 : 80; |
| } |
| }; |
| |
| util.inherits(Http, winston.Transport); |
| |
| // |
| // Expose the name of this Transport on the prototype |
| // |
| Http.prototype.name = 'http'; |
| |
| // |
| // ### function _request (options, callback) |
| // #### @callback {function} Continuation to respond to when complete. |
| // Make a request to a winstond server or any http server which can |
| // handle json-rpc. |
| // |
| Http.prototype._request = function (options, callback) { |
| var options = options || {}, |
| auth = options.auth || this.auth, |
| path = options.path || this.path || ''; |
| |
| delete options.auth; |
| delete options.path; |
| |
| options = { json: options }; |
| options.method = 'POST'; |
| options.url = 'http' |
| + (this.ssl ? 's' : '') |
| + '://' |
| + (auth ? auth.username + ':' : '') |
| + (auth ? auth.password + '@' : '') |
| + this.host |
| + ':' |
| + this.port |
| + '/' |
| + path; |
| |
| return request(options, callback); |
| }; |
| |
| // |
| // ### function log (level, msg, [meta], callback) |
| // #### @level {string} Level at which to log the message. |
| // #### @msg {string} Message to log |
| // #### @meta {Object} **Optional** Additional metadata to attach |
| // #### @callback {function} Continuation to respond to when complete. |
| // Core logging method exposed to Winston. Metadata is optional. |
| // |
| Http.prototype.log = function (level, msg, meta, callback) { |
| var self = this; |
| |
| if (typeof meta === 'function') { |
| callback = meta; |
| meta = {}; |
| } |
| |
| var options = { |
| method: 'collect', |
| params: { |
| level: level, |
| message: msg, |
| meta: meta |
| } |
| }; |
| |
| // hack |
| if (meta.auth) { |
| options.auth = meta.auth; |
| delete meta.auth; |
| } |
| |
| // hack |
| if (meta.path) { |
| options.path = meta.path; |
| delete meta.path; |
| } |
| |
| this._request(options, function (err, res, body) { |
| if (res && res.statusCode !== 200) { |
| err = new Error('HTTP Status Code: ' + res.statusCode); |
| } |
| |
| if (err) return callback(err); |
| |
| // TODO: emit 'logged' correctly, |
| // keep track of pending logs. |
| self.emit('logged'); |
| |
| if (callback) callback(null, true); |
| }); |
| }; |
| |
| // |
| // ### function query (options, callback) |
| // #### @options {Object} Loggly-like query options for this instance. |
| // #### @callback {function} Continuation to respond to when complete. |
| // Query the transport. Options object is optional. |
| // |
| Http.prototype.query = function (options, callback) { |
| if (typeof options === 'function') { |
| callback = options; |
| options = {}; |
| } |
| |
| var self = this, |
| options = this.normalizeQuery(options); |
| |
| options = { |
| method: 'query', |
| params: options |
| }; |
| |
| this._request(options, function (err, res, body) { |
| if (res && res.statusCode !== 200) { |
| err = new Error('HTTP Status Code: ' + res.statusCode); |
| } |
| |
| if (err) return callback(err); |
| |
| if (typeof body === 'string') { |
| try { |
| body = JSON.parse(body); |
| } catch (e) { |
| return callback(e); |
| } |
| } |
| |
| callback(null, body); |
| }); |
| }; |
| |
| // |
| // ### function stream (options) |
| // #### @options {Object} Stream options for this instance. |
| // Returns a log stream for this transport. Options object is optional. |
| // |
| Http.prototype.stream = function (options) { |
| var self = this, |
| options = options || {}, |
| stream = new Stream, |
| req, |
| buff; |
| |
| stream.destroy = function () { |
| req.destroy(); |
| }; |
| |
| options = { |
| method: 'stream', |
| params: options |
| }; |
| |
| 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 { |
| stream.emit('log', JSON.parse(data[i])); |
| } catch (e) { |
| stream.emit('error', e); |
| } |
| } |
| |
| buff = data[l]; |
| }); |
| |
| req.on('error', function (err) { |
| stream.emit('error', err); |
| }); |
| |
| return stream; |
| }; |