summaryrefslogtreecommitdiff
path: root/node_modules/winston/lib
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/winston/lib')
-rw-r--r--node_modules/winston/lib/winston.js165
-rw-r--r--node_modules/winston/lib/winston/common.js483
-rw-r--r--node_modules/winston/lib/winston/config.js68
-rw-r--r--node_modules/winston/lib/winston/config/cli-config.js35
-rw-r--r--node_modules/winston/lib/winston/config/npm-config.js27
-rw-r--r--node_modules/winston/lib/winston/config/syslog-config.js31
-rw-r--r--node_modules/winston/lib/winston/container.js127
-rw-r--r--node_modules/winston/lib/winston/exception.js56
-rw-r--r--node_modules/winston/lib/winston/logger.js723
-rw-r--r--node_modules/winston/lib/winston/transports.js29
-rw-r--r--node_modules/winston/lib/winston/transports/console.js130
-rw-r--r--node_modules/winston/lib/winston/transports/file.js678
-rw-r--r--node_modules/winston/lib/winston/transports/http.js232
-rw-r--r--node_modules/winston/lib/winston/transports/memory.js89
-rw-r--r--node_modules/winston/lib/winston/transports/transport.js135
15 files changed, 3008 insertions, 0 deletions
diff --git a/node_modules/winston/lib/winston.js b/node_modules/winston/lib/winston.js
new file mode 100644
index 0000000..43aa6d1
--- /dev/null
+++ b/node_modules/winston/lib/winston.js
@@ -0,0 +1,165 @@
+/*
+ * winston.js: Top-level include defining Winston.
+ *
+ * (C) 2010 Charlie Robbins
+ * MIT LICENCE
+ *
+ */
+
+var winston = exports;
+
+//
+// Expose version using `pkginfo`
+//
+require('pkginfo')(module, 'version');
+
+//
+// Include transports defined by default by winston
+//
+winston.transports = require('./winston/transports');
+
+//
+// Expose utility methods
+//
+var common = require('./winston/common');
+winston.hash = common.hash;
+winston.clone = common.clone;
+winston.longestElement = common.longestElement;
+winston.exception = require('./winston/exception');
+winston.config = require('./winston/config');
+winston.addColors = winston.config.addColors;
+
+//
+// Expose core Logging-related prototypes.
+//
+winston.Container = require('./winston/container').Container;
+winston.Logger = require('./winston/logger').Logger;
+winston.Transport = require('./winston/transports/transport').Transport;
+
+//
+// We create and expose a default `Container` to `winston.loggers` so that the
+// programmer may manage multiple `winston.Logger` instances without any additional overhead.
+//
+// ### some-file1.js
+//
+// var logger = require('winston').loggers.get('something');
+//
+// ### some-file2.js
+//
+// var logger = require('winston').loggers.get('something');
+//
+winston.loggers = new winston.Container();
+
+//
+// We create and expose a 'defaultLogger' so that the programmer may do the
+// following without the need to create an instance of winston.Logger directly:
+//
+// var winston = require('winston');
+// winston.log('info', 'some message');
+// winston.error('some error');
+//
+var defaultLogger = new winston.Logger({
+ transports: [new winston.transports.Console()]
+});
+
+//
+// Pass through the target methods onto `winston.
+//
+var methods = [
+ 'log',
+ 'query',
+ 'stream',
+ 'add',
+ 'remove',
+ 'clear',
+ 'profile',
+ 'startTimer',
+ 'extend',
+ 'cli',
+ 'handleExceptions',
+ 'unhandleExceptions',
+ 'addRewriter',
+ 'addFilter'
+];
+common.setLevels(winston, null, defaultLogger.levels);
+methods.forEach(function (method) {
+ winston[method] = function () {
+ return defaultLogger[method].apply(defaultLogger, arguments);
+ };
+});
+
+//
+// ### function cli ()
+// Configures the default winston logger to have the
+// settings for command-line interfaces: no timestamp,
+// colors enabled, padded output, and additional levels.
+//
+winston.cli = function () {
+ winston.padLevels = true;
+ common.setLevels(winston, defaultLogger.levels, winston.config.cli.levels);
+ defaultLogger.setLevels(winston.config.cli.levels);
+ winston.config.addColors(winston.config.cli.colors);
+
+ if (defaultLogger.transports.console) {
+ defaultLogger.transports.console.colorize = true;
+ defaultLogger.transports.console.timestamp = false;
+ }
+
+ return winston;
+};
+
+//
+// ### function setLevels (target)
+// #### @target {Object} Target levels to use
+// Sets the `target` levels specified on the default winston logger.
+//
+winston.setLevels = function (target) {
+ common.setLevels(winston, defaultLogger.levels, target);
+ defaultLogger.setLevels(target);
+};
+
+//
+// Define getter / setter for the default logger level
+// which need to be exposed by winston.
+//
+Object.defineProperty(winston, 'level', {
+ get: function () {
+ return defaultLogger.level;
+ },
+ set: function (val) {
+ defaultLogger.level = val;
+
+ Object.keys(defaultLogger.transports).forEach(function(key) {
+ defaultLogger.transports[key].level = val;
+ });
+ }
+});
+
+//
+// Define getters / setters for appropriate properties of the
+// default logger which need to be exposed by winston.
+//
+['emitErrs', 'exitOnError', 'padLevels', 'levelLength', 'stripColors'].forEach(function (prop) {
+ Object.defineProperty(winston, prop, {
+ get: function () {
+ return defaultLogger[prop];
+ },
+ set: function (val) {
+ defaultLogger[prop] = val;
+ }
+ });
+});
+
+//
+// @default {Object}
+// The default transports and exceptionHandlers for
+// the default winston logger.
+//
+Object.defineProperty(winston, 'default', {
+ get: function () {
+ return {
+ transports: defaultLogger.transports,
+ exceptionHandlers: defaultLogger.exceptionHandlers
+ };
+ }
+});
diff --git a/node_modules/winston/lib/winston/common.js b/node_modules/winston/lib/winston/common.js
new file mode 100644
index 0000000..29dfec0
--- /dev/null
+++ b/node_modules/winston/lib/winston/common.js
@@ -0,0 +1,483 @@
+/*
+ * common.js: Internal helper and utility functions for winston
+ *
+ * (C) 2010 Charlie Robbins
+ * MIT LICENCE
+ *
+ */
+
+var util = require('util'),
+ crypto = require('crypto'),
+ cycle = require('cycle'),
+ fs = require('fs'),
+ StringDecoder = require('string_decoder').StringDecoder,
+ Stream = require('stream').Stream,
+ config = require('./config');
+
+//
+// ### function setLevels (target, past, current)
+// #### @target {Object} Object on which to set levels.
+// #### @past {Object} Previous levels set on target.
+// #### @current {Object} Current levels to set on target.
+// Create functions on the target objects for each level
+// in current.levels. If past is defined, remove functions
+// for each of those levels.
+//
+exports.setLevels = function (target, past, current, isDefault) {
+ var self = this;
+ if (past) {
+ Object.keys(past).forEach(function (level) {
+ delete target[level];
+ });
+ }
+
+ target.levels = current || config.npm.levels;
+ if (target.padLevels) {
+ target.levelLength = exports.longestElement(Object.keys(target.levels));
+ }
+
+ //
+ // Define prototype methods for each log level
+ // e.g. target.log('info', msg) <=> target.info(msg)
+ //
+ Object.keys(target.levels).forEach(function (level) {
+
+ // TODO Refactor logging methods into a different object to avoid name clashes
+ if (level === 'log') {
+ console.warn('Log level named "log" will clash with the method "log". Consider using a different name.');
+ return;
+ }
+
+ target[level] = function (msg) {
+ // build argument list (level, msg, ... [string interpolate], [{metadata}], [callback])
+ var args = [level].concat(Array.prototype.slice.call(arguments));
+ target.log.apply(target, args);
+ };
+ });
+
+ return target;
+};
+
+//
+// ### function longestElement
+// #### @xs {Array} Array to calculate against
+// Returns the longest element in the `xs` array.
+//
+exports.longestElement = function (xs) {
+ return Math.max.apply(
+ null,
+ xs.map(function (x) { return x.length; })
+ );
+};
+
+//
+// ### function clone (obj)
+// #### @obj {Object} Object to clone.
+// Helper method for deep cloning pure JSON objects
+// i.e. JSON objects that are either literals or objects (no Arrays, etc)
+//
+exports.clone = function (obj) {
+ //
+ // We only need to clone reference types (Object)
+ //
+ var copy = {};
+
+ if (obj instanceof Error) {
+ // With potential custom Error objects, this might not be exactly correct,
+ // but probably close-enough for purposes of this lib.
+ copy = new Error(obj.message);
+ Object.getOwnPropertyNames(obj).forEach(function (key) {
+ copy[key] = obj[key];
+ });
+
+ return copy;
+ }
+ else if (!(obj instanceof Object)) {
+ return obj;
+ }
+ else if (obj instanceof Date) {
+ return new Date(obj.getTime());
+ }
+
+ for (var i in obj) {
+ if (Array.isArray(obj[i])) {
+ copy[i] = obj[i].slice(0);
+ }
+ else if (obj[i] instanceof Buffer) {
+ copy[i] = obj[i].slice(0);
+ }
+ else if (typeof obj[i] != 'function') {
+ copy[i] = obj[i] instanceof Object ? exports.clone(obj[i]) : obj[i];
+ }
+ else if (typeof obj[i] === 'function') {
+ copy[i] = obj[i];
+ }
+ }
+
+ return copy;
+};
+
+//
+// ### function log (options)
+// #### @options {Object} All information about the log serialization.
+// Generic logging function for returning timestamped strings
+// with the following options:
+//
+// {
+// level: 'level to add to serialized message',
+// message: 'message to serialize',
+// meta: 'additional logging metadata to serialize',
+// colorize: false, // Colorizes output (only if `.json` is false)
+// align: false // Align message level.
+// timestamp: true // Adds a timestamp to the serialized message
+// label: 'label to prepend the message'
+// }
+//
+exports.log = function (options) {
+ var timestampFn = typeof options.timestamp === 'function'
+ ? options.timestamp
+ : exports.timestamp,
+ timestamp = options.timestamp ? timestampFn() : null,
+ showLevel = options.showLevel === undefined ? true : options.showLevel,
+ meta = options.meta !== null && options.meta !== undefined && !(options.meta instanceof Error)
+ ? exports.clone(cycle.decycle(options.meta))
+ : options.meta || null,
+ output;
+
+ //
+ // raw mode is intended for outputing winston as streaming JSON to STDOUT
+ //
+ if (options.raw) {
+ if (typeof meta !== 'object' && meta != null) {
+ meta = { meta: meta };
+ }
+ output = exports.clone(meta) || {};
+ output.level = options.level;
+ //
+ // Remark (jcrugzz): This used to be output.message = options.message.stripColors.
+ // I do not know why this is, it does not make sense but im handling that
+ // case here as well as handling the case that does make sense which is to
+ // make the `output.message = options.message`
+ //
+ output.message = options.message.stripColors
+ ? options.message.stripColors
+ : options.message;
+
+ return JSON.stringify(output);
+ }
+
+ //
+ // json mode is intended for pretty printing multi-line json to the terminal
+ //
+ if (options.json || true === options.logstash) {
+ if (typeof meta !== 'object' && meta != null) {
+ meta = { meta: meta };
+ }
+
+ output = exports.clone(meta) || {};
+ output.level = options.level;
+ output.message = output.message || '';
+
+ if (options.label) { output.label = options.label; }
+ if (options.message) { output.message = options.message; }
+ if (timestamp) { output.timestamp = timestamp; }
+
+ if (options.logstash === true) {
+ // use logstash format
+ var logstashOutput = {};
+ if (output.message !== undefined) {
+ logstashOutput['@message'] = output.message;
+ delete output.message;
+ }
+
+ if (output.timestamp !== undefined) {
+ logstashOutput['@timestamp'] = output.timestamp;
+ delete output.timestamp;
+ }
+
+ logstashOutput['@fields'] = exports.clone(output);
+ output = logstashOutput;
+ }
+
+ if (typeof options.stringify === 'function') {
+ return options.stringify(output);
+ }
+
+ return JSON.stringify(output, function (key, value) {
+ return value instanceof Buffer
+ ? value.toString('base64')
+ : value;
+ });
+ }
+
+ //
+ // Remark: this should really be a call to `util.format`.
+ //
+ if (typeof options.formatter == 'function') {
+ return String(options.formatter(exports.clone(options)));
+ }
+
+ output = timestamp ? timestamp + ' - ' : '';
+ if (showLevel) {
+ output += options.colorize === 'all' || options.colorize === 'level' || options.colorize === true
+ ? config.colorize(options.level)
+ : options.level;
+ }
+
+ output += (options.align) ? '\t' : '';
+ output += (timestamp || showLevel) ? ': ' : '';
+ output += options.label ? ('[' + options.label + '] ') : '';
+ output += options.colorize === 'all' || options.colorize === 'message'
+ ? config.colorize(options.level, options.message)
+ : options.message;
+
+ if (meta !== null && meta !== undefined) {
+ if (meta && meta instanceof Error && meta.stack) {
+ meta = meta.stack;
+ }
+
+ if (typeof meta !== 'object') {
+ output += ' ' + meta;
+ }
+ else if (Object.keys(meta).length > 0) {
+ if (typeof options.prettyPrint === 'function') {
+ output += ' ' + options.prettyPrint(meta);
+ } else if (options.prettyPrint) {
+ output += ' ' + '\n' + util.inspect(meta, false, options.depth || null, options.colorize);
+ } else if (
+ options.humanReadableUnhandledException
+ && Object.keys(meta).length === 5
+ && meta.hasOwnProperty('date')
+ && meta.hasOwnProperty('process')
+ && meta.hasOwnProperty('os')
+ && meta.hasOwnProperty('trace')
+ && meta.hasOwnProperty('stack')) {
+
+ //
+ // If meta carries unhandled exception data serialize the stack nicely
+ //
+ var stack = meta.stack;
+ delete meta.stack;
+ delete meta.trace;
+ output += ' ' + exports.serialize(meta);
+ output += '\n' + stack.join('\n');
+ } else {
+ output += ' ' + exports.serialize(meta);
+ }
+ }
+ }
+
+ return output;
+};
+
+exports.capitalize = function (str) {
+ return str && str[0].toUpperCase() + str.slice(1);
+};
+
+//
+// ### function hash (str)
+// #### @str {string} String to hash.
+// Utility function for creating unique ids
+// e.g. Profiling incoming HTTP requests on the same tick
+//
+exports.hash = function (str) {
+ return crypto.createHash('sha1').update(str).digest('hex');
+};
+
+//
+// ### function pad (n)
+// Returns a padded string if `n < 10`.
+//
+exports.pad = function (n) {
+ return n < 10 ? '0' + n.toString(10) : n.toString(10);
+};
+
+//
+// ### function timestamp ()
+// Returns a timestamp string for the current time.
+//
+exports.timestamp = function () {
+ return new Date().toISOString();
+};
+
+//
+// ### function serialize (obj, key)
+// #### @obj {Object|literal} Object to serialize
+// #### @key {string} **Optional** Optional key represented by obj in a larger object
+// Performs simple comma-separated, `key=value` serialization for Loggly when
+// logging to non-JSON inputs.
+//
+exports.serialize = function (obj, key) {
+ if (obj === null) {
+ obj = 'null';
+ }
+ else if (obj === undefined) {
+ obj = 'undefined';
+ }
+ else if (obj === false) {
+ obj = 'false';
+ }
+
+ if (typeof obj !== 'object') {
+ return key ? key + '=' + obj : obj;
+ }
+
+ if (obj instanceof Buffer) {
+ return key ? key + '=' + obj.toString('base64') : obj.toString('base64');
+ }
+
+ var msg = '',
+ keys = Object.keys(obj),
+ length = keys.length;
+
+ for (var i = 0; i < length; i++) {
+ if (Array.isArray(obj[keys[i]])) {
+ msg += keys[i] + '=[';
+
+ for (var j = 0, l = obj[keys[i]].length; j < l; j++) {
+ msg += exports.serialize(obj[keys[i]][j]);
+ if (j < l - 1) {
+ msg += ', ';
+ }
+ }
+
+ msg += ']';
+ }
+ else if (obj[keys[i]] instanceof Date) {
+ msg += keys[i] + '=' + obj[keys[i]];
+ }
+ else {
+ msg += exports.serialize(obj[keys[i]], keys[i]);
+ }
+
+ if (i < length - 1) {
+ msg += ', ';
+ }
+ }
+
+ return msg;
+};
+
+//
+// ### function tailFile (options, callback)
+// #### @options {Object} Options for tail.
+// #### @callback {function} Callback to execute on every line.
+// `tail -f` a file. Options must include file.
+//
+exports.tailFile = function(options, callback) {
+ var buffer = new Buffer(64 * 1024)
+ , decode = new StringDecoder('utf8')
+ , stream = new Stream
+ , buff = ''
+ , pos = 0
+ , row = 0;
+
+ if (options.start === -1) {
+ delete options.start;
+ }
+
+ stream.readable = true;
+ stream.destroy = function() {
+ stream.destroyed = true;
+ stream.emit('end');
+ stream.emit('close');
+ };
+
+ fs.open(options.file, 'a+', '0644', function(err, fd) {
+ if (err) {
+ if (!callback) {
+ stream.emit('error', err);
+ } else {
+ callback(err);
+ }
+ stream.destroy();
+ return;
+ }
+
+ (function read() {
+ if (stream.destroyed) {
+ fs.close(fd);
+ return;
+ }
+
+ return fs.read(fd, buffer, 0, buffer.length, pos, function(err, bytes) {
+ if (err) {
+ if (!callback) {
+ stream.emit('error', err);
+ } else {
+ callback(err);
+ }
+ stream.destroy();
+ return;
+ }
+
+ if (!bytes) {
+ if (buff) {
+ if (options.start == null || row > options.start) {
+ if (!callback) {
+ stream.emit('line', buff);
+ } else {
+ callback(null, buff);
+ }
+ }
+ row++;
+ buff = '';
+ }
+ return setTimeout(read, 1000);
+ }
+
+ var data = decode.write(buffer.slice(0, bytes));
+
+ if (!callback) {
+ stream.emit('data', data);
+ }
+
+ var data = (buff + data).split(/\n+/)
+ , l = data.length - 1
+ , i = 0;
+
+ for (; i < l; i++) {
+ if (options.start == null || row > options.start) {
+ if (!callback) {
+ stream.emit('line', data[i]);
+ } else {
+ callback(null, data[i]);
+ }
+ }
+ row++;
+ }
+
+ buff = data[l];
+
+ pos += bytes;
+
+ return read();
+ });
+ })();
+ });
+
+ if (!callback) {
+ return stream;
+ }
+
+ return stream.destroy;
+};
+
+//
+// ### function stringArrayToSet (array)
+// #### @strArray {Array} Array of Set-elements as strings.
+// #### @errMsg {string} **Optional** Custom error message thrown on invalid input.
+// Returns a Set-like object with strArray's elements as keys (each with the value true).
+//
+exports.stringArrayToSet = function (strArray, errMsg) {
+ if (typeof errMsg === 'undefined') {
+ errMsg = 'Cannot make set from Array with non-string elements';
+ }
+ return strArray.reduce(function (set, el) {
+ if (!(typeof el === 'string' || el instanceof String)) {
+ throw new Error(errMsg);
+ }
+ set[el] = true;
+ return set;
+ }, Object.create(null));
+};
diff --git a/node_modules/winston/lib/winston/config.js b/node_modules/winston/lib/winston/config.js
new file mode 100644
index 0000000..1bb52fd
--- /dev/null
+++ b/node_modules/winston/lib/winston/config.js
@@ -0,0 +1,68 @@
+/*
+ * config.js: Default settings for all levels that winston knows about
+ *
+ * (C) 2010 Charlie Robbins
+ * MIT LICENCE
+ *
+ */
+
+var colors = require('colors/safe');
+
+// Fix colors not appearing in non-tty environments
+colors.enabled = true;
+
+var config = exports,
+ allColors = exports.allColors = {};
+
+config.addColors = function (colors) {
+ mixin(allColors, colors);
+};
+
+config.colorize = function (level, message) {
+ if (typeof message === 'undefined') message = level;
+
+ var colorized = message;
+ if (allColors[level] instanceof Array) {
+ for (var i = 0, l = allColors[level].length; i < l; ++i) {
+ colorized = colors[allColors[level][i]](colorized);
+ }
+ }
+ else if (allColors[level].match(/\s/)) {
+ var colorArr = allColors[level].split(/\s+/);
+ for (var i = 0; i < colorArr.length; ++i) {
+ colorized = colors[colorArr[i]](colorized);
+ }
+ allColors[level] = colorArr;
+ }
+ else {
+ colorized = colors[allColors[level]](colorized);
+ }
+
+ return colorized;
+};
+
+//
+// Export config sets
+//
+config.cli = require('./config/cli-config');
+config.npm = require('./config/npm-config');
+config.syslog = require('./config/syslog-config');
+
+//
+// Add colors for pre-defined config sets
+//
+config.addColors(config.cli.colors);
+config.addColors(config.npm.colors);
+config.addColors(config.syslog.colors);
+
+function mixin (target) {
+ var args = Array.prototype.slice.call(arguments, 1);
+
+ args.forEach(function (a) {
+ var keys = Object.keys(a);
+ for (var i = 0; i < keys.length; i++) {
+ target[keys[i]] = a[keys[i]];
+ }
+ });
+ return target;
+};
diff --git a/node_modules/winston/lib/winston/config/cli-config.js b/node_modules/winston/lib/winston/config/cli-config.js
new file mode 100644
index 0000000..764d2a8
--- /dev/null
+++ b/node_modules/winston/lib/winston/config/cli-config.js
@@ -0,0 +1,35 @@
+/*
+ * cli-config.js: Config that conform to commonly used CLI logging levels.
+ *
+ * (C) 2010 Charlie Robbins
+ * MIT LICENCE
+ *
+ */
+
+var cliConfig = exports;
+
+cliConfig.levels = {
+ error: 0,
+ warn: 1,
+ help: 2,
+ data: 3,
+ info: 4,
+ debug: 5,
+ prompt: 6,
+ verbose: 7,
+ input: 8,
+ silly: 9,
+};
+
+cliConfig.colors = {
+ error: 'red',
+ warn: 'yellow',
+ help: 'cyan',
+ data: 'grey',
+ info: 'green',
+ debug: 'blue',
+ prompt: 'grey',
+ verbose: 'cyan',
+ input: 'grey',
+ silly: 'magenta'
+};
diff --git a/node_modules/winston/lib/winston/config/npm-config.js b/node_modules/winston/lib/winston/config/npm-config.js
new file mode 100644
index 0000000..6402ab3
--- /dev/null
+++ b/node_modules/winston/lib/winston/config/npm-config.js
@@ -0,0 +1,27 @@
+/*
+ * npm-config.js: Config that conform to npm logging levels.
+ *
+ * (C) 2010 Charlie Robbins
+ * MIT LICENCE
+ *
+ */
+
+var npmConfig = exports;
+
+npmConfig.levels = {
+ error: 0,
+ warn: 1,
+ info: 2,
+ verbose: 3,
+ debug: 4,
+ silly: 5
+};
+
+npmConfig.colors = {
+ error: 'red',
+ warn: 'yellow',
+ info: 'green',
+ verbose: 'cyan',
+ debug: 'blue',
+ silly: 'magenta'
+};
diff --git a/node_modules/winston/lib/winston/config/syslog-config.js b/node_modules/winston/lib/winston/config/syslog-config.js
new file mode 100644
index 0000000..67c6a09
--- /dev/null
+++ b/node_modules/winston/lib/winston/config/syslog-config.js
@@ -0,0 +1,31 @@
+/*
+ * syslog-config.js: Config that conform to syslog logging levels.
+ *
+ * (C) 2010 Charlie Robbins
+ * MIT LICENCE
+ *
+ */
+
+var syslogConfig = exports;
+
+syslogConfig.levels = {
+ emerg: 0,
+ alert: 1,
+ crit: 2,
+ error: 3,
+ warning: 4,
+ notice: 5,
+ info: 6,
+ debug: 7
+};
+
+syslogConfig.colors = {
+ emerg: 'red',
+ alert: 'yellow',
+ crit: 'red',
+ error: 'red',
+ warning: 'red',
+ notice: 'yellow',
+ info: 'green',
+ debug: 'blue'
+};
diff --git a/node_modules/winston/lib/winston/container.js b/node_modules/winston/lib/winston/container.js
new file mode 100644
index 0000000..f5faaa7
--- /dev/null
+++ b/node_modules/winston/lib/winston/container.js
@@ -0,0 +1,127 @@
+/*
+ * container.js: Inversion of control container for winston logger instances
+ *
+ * (C) 2010 Charlie Robbins
+ * MIT LICENCE
+ *
+ */
+
+var common = require('./common'),
+ winston = require('../winston'),
+ extend = require('util')._extend;
+
+//
+// ### function Container (options)
+// #### @options {Object} Default pass-thru options for Loggers
+// Constructor function for the Container object responsible for managing
+// a set of `winston.Logger` instances based on string ids.
+//
+var Container = exports.Container = function (options) {
+ this.loggers = {};
+ this.options = options || {};
+ this.default = {
+ transports: [
+ new winston.transports.Console({
+ level: 'silly',
+ colorize: false
+ })
+ ]
+ }
+};
+
+//
+// ### function get / add (id, options)
+// #### @id {string} Id of the Logger to get
+// #### @options {Object} **Optional** Options for the Logger instance
+// Retreives a `winston.Logger` instance for the specified `id`. If
+// an instance does not exist, one is created.
+//
+Container.prototype.get = Container.prototype.add = function (id, options) {
+ var self = this,
+ existing;
+
+ if (!this.loggers[id]) {
+ //
+ // Remark: Simple shallow clone for configuration options in case we pass in
+ // instantiated protoypal objects
+ //
+ options = extend({}, options || this.options || this.default);
+ existing = options.transports || this.options.transports;
+ //
+ // Remark: Make sure if we have an array of transports we slice it to make copies
+ // of those references.
+ //
+ options.transports = existing ? existing.slice() : [];
+
+ if (options.transports.length === 0 && (!options || !options['console'])) {
+ options.transports.push(this.default.transports[0]);
+ }
+
+ Object.keys(options).forEach(function (key) {
+ if (key === 'transports') {
+ return;
+ }
+
+ var name = common.capitalize(key);
+
+ if (!winston.transports[name]) {
+ throw new Error('Cannot add unknown transport: ' + name);
+ }
+
+ var namedOptions = options[key];
+ namedOptions.id = id;
+ options.transports.push(new (winston.transports[name])(namedOptions));
+ });
+
+ this.loggers[id] = new winston.Logger(options);
+
+ this.loggers[id].on('close', function () {
+ self._delete(id);
+ });
+ }
+
+ return this.loggers[id];
+};
+
+//
+// ### function close (id)
+// #### @id {string} **Optional** Id of the Logger instance to find
+// Returns a boolean value indicating if this instance
+// has a logger with the specified `id`.
+//
+Container.prototype.has = function (id) {
+ return !!this.loggers[id];
+};
+
+//
+// ### function close (id)
+// #### @id {string} **Optional** Id of the Logger instance to close
+// Closes a `Logger` instance with the specified `id` if it exists.
+// If no `id` is supplied then all Loggers are closed.
+//
+Container.prototype.close = function (id) {
+ var self = this;
+
+ function _close (id) {
+ if (!self.loggers[id]) {
+ return;
+ }
+
+ self.loggers[id].close();
+ self._delete(id);
+ }
+
+ return id ? _close(id) : Object.keys(this.loggers).forEach(function (id) {
+ _close(id);
+ });
+};
+
+//
+// ### @private function _delete (id)
+// #### @id {string} Id of the Logger instance to delete from container
+// Deletes a `Logger` instance with the specified `id`.
+//
+Container.prototype._delete = function (id) {
+ delete this.loggers[id];
+}
+
diff --git a/node_modules/winston/lib/winston/exception.js b/node_modules/winston/lib/winston/exception.js
new file mode 100644
index 0000000..22717dd
--- /dev/null
+++ b/node_modules/winston/lib/winston/exception.js
@@ -0,0 +1,56 @@
+/*
+ * exception.js: Utility methods for gathing information about uncaughtExceptions.
+ *
+ * (C) 2010 Charlie Robbins
+ * MIT LICENCE
+ *
+ */
+
+var os = require('os'),
+ stackTrace = require('stack-trace');
+
+var exception = exports;
+
+exception.getAllInfo = function (err) {
+ return {
+ date: new Date().toString(),
+ process: exception.getProcessInfo(),
+ os: exception.getOsInfo(),
+ trace: exception.getTrace(err),
+ stack: err.stack && err.stack.split('\n')
+ };
+};
+
+exception.getProcessInfo = function () {
+ return {
+ pid: process.pid,
+ uid: process.getuid ? process.getuid() : null,
+ gid: process.getgid ? process.getgid() : null,
+ cwd: process.cwd(),
+ execPath: process.execPath,
+ version: process.version,
+ argv: process.argv,
+ memoryUsage: process.memoryUsage()
+ };
+};
+
+exception.getOsInfo = function () {
+ return {
+ loadavg: os.loadavg(),
+ uptime: os.uptime()
+ };
+};
+
+exception.getTrace = function (err) {
+ var trace = err ? stackTrace.parse(err) : stackTrace.get();
+ return trace.map(function (site) {
+ return {
+ column: site.getColumnNumber(),
+ file: site.getFileName(),
+ function: site.getFunctionName(),
+ line: site.getLineNumber(),
+ method: site.getMethodName(),
+ native: site.isNative(),
+ }
+ });
+};
diff --git a/node_modules/winston/lib/winston/logger.js b/node_modules/winston/lib/winston/logger.js
new file mode 100644
index 0000000..97fba64
--- /dev/null
+++ b/node_modules/winston/lib/winston/logger.js
@@ -0,0 +1,723 @@
+/*
+ * logger.js: Core logger object used by winston.
+ *
+ * (C) 2010 Charlie Robbins
+ * MIT LICENCE
+ *
+ */
+
+var events = require('events'),
+ util = require('util'),
+ async = require('async'),
+ config = require('./config'),
+ common = require('./common'),
+ exception = require('./exception'),
+ Stream = require('stream').Stream;
+
+const formatRegExp = /%[sdj%]/g;
+
+//
+// ### function Logger (options)
+// #### @options {Object} Options for this instance.
+// Constructor function for the Logger object responsible
+// for persisting log messages and metadata to one or more transports.
+//
+var Logger = exports.Logger = function (options) {
+ events.EventEmitter.call(this);
+ this.configure(options);
+};
+
+//
+// Inherit from `events.EventEmitter`.
+//
+util.inherits(Logger, events.EventEmitter);
+
+//
+// ### function configure (options)
+// This will wholesale reconfigure this instance by:
+// 1. Resetting all transports. Older transports will be removed implicitly.
+// 2. Set all other options including levels, colors, rewriters, filters,
+// exceptionHandlers, etc.
+//
+Logger.prototype.configure = function (options) {
+ var self = this;
+
+ //
+ // If we have already been setup with transports
+ // then remove them before proceeding.
+ //
+ if (Array.isArray(this._names) && this._names.length) {
+ this.clear();
+ }
+
+ options = options || {};
+ this.transports = {};
+ this._names = [];
+
+ if (options.transports) {
+ options.transports.forEach(function (transport) {
+ self.add(transport, null, true);
+ });
+ }
+
+ //
+ // Set Levels and default logging level
+ //
+ this.padLevels = options.padLevels || false;
+ this.setLevels(options.levels);
+ if (options.colors) {
+ config.addColors(options.colors);
+ }
+
+ //
+ // Hoist other options onto this instance.
+ //
+ this.level = options.level || 'info';
+ this.emitErrs = options.emitErrs || false;
+ this.stripColors = options.stripColors || false;
+ this.exitOnError = typeof options.exitOnError !== 'undefined'
+ ? options.exitOnError
+ : true;
+
+ //
+ // Setup internal state as empty Objects even though it is
+ // defined lazily later to ensure a strong existential API contract.
+ //
+ this.exceptionHandlers = {};
+ this.profilers = {};
+
+ ['rewriters', 'filters'].forEach(function (kind) {
+ self[kind] = Array.isArray(options[kind])
+ ? options[kind]
+ : [];
+ });
+
+ if (options.exceptionHandlers) {
+ this.handleExceptions(options.exceptionHandlers);
+ }
+};
+
+//
+// ### 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.
+//
+Logger.prototype.log = function (level) {
+ var args = Array.prototype.slice.call(arguments, 1),
+ self = this,
+ transports;
+
+ while (args[args.length - 1] === null) {
+ args.pop();
+ }
+
+ //
+ // Determining what is `meta` and what are arguments for string interpolation
+ // turns out to be VERY tricky. e.g. in the cases like this:
+ //
+ // logger.info('No interpolation symbols', 'ok', 'why', { meta: 'is-this' });
+ //
+ var callback = typeof args[args.length - 1] === 'function'
+ ? args.pop()
+ : null;
+
+ //
+ // Handle errors appropriately.
+ //
+ function onError(err) {
+ if (callback) {
+ callback(err);
+ }
+ else if (self.emitErrs) {
+ self.emit('error', err);
+ }
+ }
+
+ if (this._names.length === 0) {
+ return onError(new Error('Cannot log with no transports.'));
+ }
+ else if (typeof self.levels[level] === 'undefined') {
+ return onError(new Error('Unknown log level: ' + level));
+ }
+
+ //
+ // If there are no transports that match the level
+ // then be eager and return. This could potentially be calculated
+ // during `setLevels` for more performance gains.
+ //
+ var targets = this._names.filter(function (name) {
+ var transport = self.transports[name];
+ return (transport.level && self.levels[transport.level] >= self.levels[level])
+ || (!transport.level && self.levels[self.level] >= self.levels[level]);
+ });
+
+ if (!targets.length) {
+ if (callback) { callback(); }
+ return;
+ }
+
+ //
+ // Determining what is `meta` and what are arguments for string interpolation
+ // turns out to be VERY tricky. e.g. in the cases like this:
+ //
+ // logger.info('No interpolation symbols', 'ok', 'why', { meta: 'is-this' });
+ //
+ var metaType = Object.prototype.toString.call(args[args.length - 1]),
+ fmtMatch = args[0] && args[0].match && args[0].match(formatRegExp),
+ isFormat = fmtMatch && fmtMatch.length,
+ validMeta = !isFormat
+ ? metaType === '[object Object]' || metaType === '[object Error]' || metaType === '[object Array]'
+ : metaType === '[object Object]',
+ meta = validMeta ? args.pop() : {},
+ msg = util.format.apply(null, args);
+
+ //
+ // Respond to the callback.
+ //
+ function finish(err) {
+ if (callback) {
+ if (err) return callback(err);
+ callback(null, level, msg, meta);
+ }
+
+ callback = null;
+ if (!err) {
+ self.emit('logged', level, msg, meta);
+ }
+ }
+
+ // If we should pad for levels, do so
+ if (this.padLevels) {
+ msg = new Array(this.levelLength - level.length + 1).join(' ') + msg;
+ }
+
+ this.rewriters.forEach(function (rewriter) {
+ meta = rewriter(level, msg, meta, self);
+ });
+
+ this.filters.forEach(function(filter) {
+ var filtered = filter(level, msg, meta, self);
+ if (typeof filtered === 'string')
+ msg = filtered;
+ else {
+ msg = filtered.msg;
+ meta = filtered.meta;
+ }
+ });
+
+ //
+ // For consideration of terminal 'color" programs like colors.js,
+ // which can add ANSI escape color codes to strings, we destyle the
+ // ANSI color escape codes when `this.stripColors` is set.
+ //
+ // see: http://en.wikipedia.org/wiki/ANSI_escape_code
+ //
+ if (this.stripColors) {
+ var code = /\u001b\[(\d+(;\d+)*)?m/g;
+ msg = ('' + msg).replace(code, '');
+ }
+
+ //
+ // Log for each transport and emit 'logging' event
+ //
+ function transportLog(name, next) {
+ var transport = self.transports[name];
+ transport.log(level, msg, meta, function (err) {
+ if (err) {
+ err.transport = transport;
+ finish(err);
+ return next();
+ }
+
+ self.emit('logging', transport, level, msg, meta);
+ next();
+ });
+ }
+
+ async.forEach(targets, transportLog, finish);
+ return this;
+};
+
+//
+// ### function query (options, callback)
+// #### @options {Object} Query options for this instance.
+// #### @callback {function} Continuation to respond to when complete.
+// Queries the all transports for this instance with the specified `options`.
+// This will aggregate each transport's results into one object containing
+// a property per transport.
+//
+Logger.prototype.query = function (options, callback) {
+ if (typeof options === 'function') {
+ callback = options;
+ options = {};
+ }
+
+ var self = this,
+ options = options || {},
+ results = {},
+ query = common.clone(options.query) || {},
+ transports;
+
+ //
+ // Helper function to query a single transport
+ //
+ function queryTransport(transport, next) {
+ if (options.query) {
+ options.query = transport.formatQuery(query);
+ }
+
+ transport.query(options, function (err, results) {
+ if (err) {
+ return next(err);
+ }
+
+ next(null, transport.formatResults(results, options.format));
+ });
+ }
+
+ //
+ // Helper function to accumulate the results from
+ // `queryTransport` into the `results`.
+ //
+ function addResults(transport, next) {
+ queryTransport(transport, function (err, result) {
+ //
+ // queryTransport could potentially invoke the callback
+ // multiple times since Transport code can be unpredictable.
+ //
+ if (next) {
+ result = err || result;
+ if (result) {
+ results[transport.name] = result;
+ }
+
+ next();
+ }
+
+ next = null;
+ });
+ }
+
+ //
+ // If an explicit transport is being queried then
+ // respond with the results from only that transport
+ //
+ if (options.transport) {
+ options.transport = options.transport.toLowerCase();
+ return queryTransport(this.transports[options.transport], callback);
+ }
+
+ //
+ // Create a list of all transports for this instance.
+ //
+ transports = this._names.map(function (name) {
+ return self.transports[name];
+ }).filter(function (transport) {
+ return !!transport.query;
+ });
+
+ //
+ // Iterate over the transports in parallel setting the
+ // appropriate key in the `results`
+ //
+ async.forEach(transports, addResults, function () {
+ callback(null, results);
+ });
+};
+
+//
+// ### function stream (options)
+// #### @options {Object} Stream options for this instance.
+// Returns a log stream for all transports. Options object is optional.
+//
+Logger.prototype.stream = function (options) {
+ var self = this,
+ options = options || {},
+ out = new Stream,
+ streams = [],
+ transports;
+
+ if (options.transport) {
+ var transport = this.transports[options.transport];
+ delete options.transport;
+ if (transport && transport.stream) {
+ return transport.stream(options);
+ }
+ }
+
+ out._streams = streams;
+ out.destroy = function () {
+ var i = streams.length;
+ while (i--) streams[i].destroy();
+ };
+
+ //
+ // Create a list of all transports for this instance.
+ //
+ transports = this._names.map(function (name) {
+ return self.transports[name];
+ }).filter(function (transport) {
+ return !!transport.stream;
+ });
+
+ transports.forEach(function (transport) {
+ var stream = transport.stream(options);
+ if (!stream) return;
+
+ streams.push(stream);
+
+ stream.on('log', function (log) {
+ log.transport = log.transport || [];
+ log.transport.push(transport.name);
+ out.emit('log', log);
+ });
+
+ stream.on('error', function (err) {
+ err.transport = err.transport || [];
+ err.transport.push(transport.name);
+ out.emit('error', err);
+ });
+ });
+
+ return out;
+};
+
+//
+// ### function close ()
+// Cleans up resources (streams, event listeners) for all
+// transports associated with this instance (if necessary).
+//
+Logger.prototype.close = function () {
+ var self = this;
+
+ this._names.forEach(function (name) {
+ var transport = self.transports[name];
+ if (transport && transport.close) {
+ transport.close();
+ }
+ });
+
+ this.emit('close');
+};
+
+//
+// ### function handleExceptions ([tr0, tr1...] || tr0, tr1, ...)
+// Handles `uncaughtException` events for the current process by
+// ADDING any handlers passed in.
+//
+Logger.prototype.handleExceptions = function () {
+ var args = Array.prototype.slice.call(arguments),
+ handlers = [],
+ self = this;
+
+ args.forEach(function (a) {
+ if (Array.isArray(a)) {
+ handlers = handlers.concat(a);
+ }
+ else {
+ handlers.push(a);
+ }
+ });
+
+ this.exceptionHandlers = this.exceptionHandlers || {};
+ handlers.forEach(function (handler) {
+ self.exceptionHandlers[handler.name] = handler;
+ });
+
+ this._hnames = Object.keys(self.exceptionHandlers);
+
+ if (!this.catchExceptions) {
+ this.catchExceptions = this._uncaughtException.bind(this);
+ process.on('uncaughtException', this.catchExceptions);
+ }
+};
+
+//
+// ### function unhandleExceptions ()
+// Removes any handlers to `uncaughtException` events
+// for the current process
+//
+Logger.prototype.unhandleExceptions = function () {
+ var self = this;
+
+ if (this.catchExceptions) {
+ Object.keys(this.exceptionHandlers).forEach(function (name) {
+ var handler = self.exceptionHandlers[name];
+ if (handler.close) {
+ handler.close();
+ }
+ });
+
+ this.exceptionHandlers = {};
+ Object.keys(this.transports).forEach(function (name) {
+ var transport = self.transports[name];
+ if (transport.handleExceptions) {
+ transport.handleExceptions = false;
+ }
+ })
+
+ process.removeListener('uncaughtException', this.catchExceptions);
+ this.catchExceptions = false;
+ }
+};
+
+//
+// ### function add (transport, [options])
+// #### @transport {Transport} Prototype of the Transport object to add.
+// #### @options {Object} **Optional** Options for the Transport to add.
+// #### @instance {Boolean} **Optional** Value indicating if `transport` is already instantiated.
+// Adds a transport of the specified type to this instance.
+//
+Logger.prototype.add = function (transport, options, created) {
+ var instance = created ? transport : (new (transport)(options));
+
+ if (!instance.name && !instance.log) {
+ throw new Error('Unknown transport with no log() method');
+ }
+ else if (this.transports[instance.name]) {
+ throw new Error('Transport already attached: ' + instance.name);
+ }
+
+ this.transports[instance.name] = instance;
+ this._names = Object.keys(this.transports);
+
+ //
+ // Listen for the `error` event on the new Transport
+ //
+ instance._onError = this._onError.bind(this, instance)
+ if (!created) {
+ instance.on('error', instance._onError);
+ }
+
+ //
+ // If this transport has `handleExceptions` set to `true`
+ // and we are not already handling exceptions, do so.
+ //
+ if (instance.handleExceptions && !this.catchExceptions) {
+ this.handleExceptions();
+ }
+
+ return this;
+};
+
+//
+// ### function clear ()
+// Remove all transports from this instance
+//
+Logger.prototype.clear = function () {
+ Object.keys(this.transports).forEach(function (name) {
+ this.remove({ name: name });
+ }, this);
+};
+
+//
+// ### function remove (transport)
+// #### @transport {Transport|String} Transport or Name to remove.
+// Removes a transport of the specified type from this instance.
+//
+Logger.prototype.remove = function (transport) {
+ var name = typeof transport !== 'string'
+ ? transport.name || transport.prototype.name
+ : transport;
+
+ if (!this.transports[name]) {
+ throw new Error('Transport ' + name + ' not attached to this instance');
+ }
+
+ var instance = this.transports[name];
+ delete this.transports[name];
+ this._names = Object.keys(this.transports);
+
+ if (instance.close) {
+ instance.close();
+ }
+
+ if (instance._onError) {
+ instance.removeListener('error', instance._onError);
+ }
+ return this;
+};
+
+//
+// ### function startTimer ()
+// Returns an object corresponding to a specific timing. When done
+// is called the timer will finish and log the duration. e.g.:
+//
+// timer = winston.startTimer()
+// setTimeout(function(){
+// timer.done("Logging message");
+// }, 1000);
+//
+Logger.prototype.startTimer = function () {
+ return new ProfileHandler(this);
+};
+
+//
+// ### function profile (id, [msg, meta, callback])
+// #### @id {string} Unique id of the profiler
+// #### @msg {string} **Optional** Message to log
+// #### @meta {Object} **Optional** Additional metadata to attach
+// #### @callback {function} **Optional** Continuation to respond to when complete.
+// Tracks the time inbetween subsequent calls to this method
+// with the same `id` parameter. The second call to this method
+// will log the difference in milliseconds along with the message.
+//
+Logger.prototype.profile = function (id) {
+ var now = Date.now(), then, args,
+ msg, meta, callback;
+
+ if (this.profilers[id]) {
+ then = this.profilers[id];
+ delete this.profilers[id];
+
+ // Support variable arguments: msg, meta, callback
+ args = Array.prototype.slice.call(arguments);
+ callback = typeof args[args.length - 1] === 'function' ? args.pop() : null;
+ meta = typeof args[args.length - 1] === 'object' ? args.pop() : {};
+ msg = args.length === 2 ? args[1] : id;
+
+ // Set the duration property of the metadata
+ meta.durationMs = now - then;
+ return this.info(msg, meta, callback);
+ }
+ else {
+ this.profilers[id] = now;
+ }
+
+ return this;
+};
+
+//
+// ### function setLevels (target)
+// #### @target {Object} Target levels to use on this instance
+// Sets the `target` levels specified on this instance.
+//
+Logger.prototype.setLevels = function (target) {
+ return common.setLevels(this, this.levels, target);
+};
+
+//
+// ### function cli ()
+// Configures this instance to have the default
+// settings for command-line interfaces: no timestamp,
+// colors enabled, padded output, and additional levels.
+//
+Logger.prototype.cli = function () {
+ this.padLevels = true;
+ this.setLevels(config.cli.levels);
+ config.addColors(config.cli.colors);
+
+ if (this.transports.console) {
+ this.transports.console.colorize = this.transports.console.colorize || true;
+ this.transports.console.timestamp = this.transports.console.timestamp || false;
+ }
+
+ return this;
+};
+
+//
+// ### @private function _uncaughtException (err)
+// #### @err {Error} Error to handle
+// Logs all relevant information around the `err` and
+// exits the current process.
+//
+Logger.prototype._uncaughtException = function (err) {
+ var self = this,
+ responded = false,
+ info = exception.getAllInfo(err),
+ handlers = this._getExceptionHandlers(),
+ timeout,
+ doExit;
+
+ //
+ // Calculate if we should exit on this error
+ //
+ doExit = typeof this.exitOnError === 'function'
+ ? this.exitOnError(err)
+ : this.exitOnError;
+
+ function logAndWait(transport, next) {
+ transport.logException('uncaughtException: ' + (err.message || err), info, next, err);
+ }
+
+ function gracefulExit() {
+ if (doExit && !responded) {
+ //
+ // Remark: Currently ignoring any exceptions from transports
+ // when catching uncaught exceptions.
+ //
+ clearTimeout(timeout);
+ responded = true;
+ process.exit(1);
+ }
+ }
+
+ if (!handlers || handlers.length === 0) {
+ return gracefulExit();
+ }
+
+ //
+ // Log to all transports and allow the operation to take
+ // only up to `3000ms`.
+ //
+ async.forEach(handlers, logAndWait, gracefulExit);
+ if (doExit) {
+ timeout = setTimeout(gracefulExit, 3000);
+ }
+};
+
+//
+// ### @private function _getExceptionHandlers ()
+// Returns the list of transports and exceptionHandlers
+// for this instance.
+//
+Logger.prototype._getExceptionHandlers = function () {
+ var self = this;
+
+ return this._hnames.map(function (name) {
+ return self.exceptionHandlers[name];
+ }).concat(this._names.map(function (name) {
+ return self.transports[name].handleExceptions && self.transports[name];
+ })).filter(Boolean);
+};
+
+//
+// ### @private function _onError (transport, err)
+// #### @transport {Object} Transport on which the error occured
+// #### @err {Error} Error that occurred on the transport
+// Bubbles the error, `err`, that occured on the specified `transport`
+// up from this instance if `emitErrs` has been set.
+//
+Logger.prototype._onError = function (transport, err) {
+ if (this.emitErrs) {
+ this.emit('error', err, transport);
+ }
+};
+
+//
+// ### @private ProfileHandler
+// Constructor function for the ProfileHandler instance used by
+// `Logger.prototype.startTimer`. When done is called the timer
+// will finish and log the duration.
+//
+function ProfileHandler(logger) {
+ this.logger = logger;
+ this.start = Date.now();
+}
+
+//
+// ### function done (msg)
+// Ends the current timer (i.e. ProfileHandler) instance and
+// logs the `msg` along with the duration since creation.
+//
+ProfileHandler.prototype.done = function (msg) {
+ var args = Array.prototype.slice.call(arguments),
+ callback = typeof args[args.length - 1] === 'function' ? args.pop() : null,
+ meta = typeof args[args.length - 1] === 'object' ? args.pop() : {};
+
+ meta.duration = (Date.now()) - this.start + 'ms';
+ return this.logger.info(msg, meta, callback);
+};
diff --git a/node_modules/winston/lib/winston/transports.js b/node_modules/winston/lib/winston/transports.js
new file mode 100644
index 0000000..34f800e
--- /dev/null
+++ b/node_modules/winston/lib/winston/transports.js
@@ -0,0 +1,29 @@
+/*
+ * transports.js: Set of all transports Winston knows about
+ *
+ * (C) 2010 Charlie Robbins
+ * MIT LICENCE
+ *
+ */
+
+var path = require('path');
+
+//
+// Setup all transports as lazy-loaded getters.
+//
+Object.defineProperties(
+ exports,
+ ['Console', 'File', 'Http', 'Memory']
+ .reduce(function (acc, name) {
+ acc[name] = {
+ configurable: true,
+ enumerable: true,
+ get: function () {
+ var fullpath = path.join(__dirname, 'transports', name.toLowerCase());
+ return exports[name] = require(fullpath)[name];
+ }
+ };
+
+ return acc;
+ }, {})
+);
diff --git a/node_modules/winston/lib/winston/transports/console.js b/node_modules/winston/lib/winston/transports/console.js
new file mode 100644
index 0000000..f573e17
--- /dev/null
+++ b/node_modules/winston/lib/winston/transports/console.js
@@ -0,0 +1,130 @@
+/*
+ * console.js: Transport for outputting to the console
+ *
+ * (C) 2010 Charlie Robbins
+ * MIT LICENCE
+ *
+ */
+
+var events = require('events'),
+ os = require('os'),
+ util = require('util'),
+ common = require('../common'),
+ Transport = require('./transport').Transport;
+
+//
+// ### function Console (options)
+// #### @options {Object} Options for this instance.
+// Constructor function for the Console transport object responsible
+// for persisting log messages and metadata to a terminal or TTY.
+//
+var Console = exports.Console = function (options) {
+ Transport.call(this, options);
+ options = options || {};
+
+ this.json = options.json || false;
+ this.colorize = options.colorize || false;
+ this.prettyPrint = options.prettyPrint || false;
+ this.timestamp = typeof options.timestamp !== 'undefined' ? options.timestamp : false;
+ this.showLevel = options.showLevel === undefined ? true : options.showLevel;
+ this.label = options.label || null;
+ this.logstash = options.logstash || false;
+ this.depth = options.depth || null;
+ this.align = options.align || false;
+ this.stderrLevels = setStderrLevels(options.stderrLevels, options.debugStdout);
+ this.eol = options.eol || os.EOL;
+
+ if (this.json) {
+ this.stringify = options.stringify || function (obj) {
+ return JSON.stringify(obj, null, 2);
+ };
+ }
+
+ //
+ // Convert stderrLevels into an Object for faster key-lookup times than an Array.
+ //
+ // For backwards compatibility, stderrLevels defaults to ['error', 'debug']
+ // or ['error'] depending on whether options.debugStdout is true.
+ //
+ function setStderrLevels (levels, debugStdout) {
+ var defaultMsg = 'Cannot have non-string elements in stderrLevels Array';
+ if (debugStdout) {
+ if (levels) {
+ //
+ // Don't allow setting both debugStdout and stderrLevels together,
+ // since this could cause behaviour a programmer might not expect.
+ //
+ throw new Error('Cannot set debugStdout and stderrLevels together');
+ }
+
+ return common.stringArrayToSet(['error'], defaultMsg);
+ }
+
+ if (!levels) {
+ return common.stringArrayToSet(['error', 'debug'], defaultMsg);
+ } else if (!(Array.isArray(levels))) {
+ throw new Error('Cannot set stderrLevels to type other than Array');
+ }
+
+ return common.stringArrayToSet(levels, defaultMsg);
+ };
+};
+
+//
+// Inherit from `winston.Transport`.
+//
+util.inherits(Console, Transport);
+
+//
+// Expose the name of this Transport on the prototype
+//
+Console.prototype.name = 'console';
+
+//
+// ### 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.
+//
+Console.prototype.log = function (level, msg, meta, callback) {
+ if (this.silent) {
+ return callback(null, true);
+ }
+
+ var self = this,
+ output;
+
+ output = common.log({
+ colorize: this.colorize,
+ json: this.json,
+ level: level,
+ message: msg,
+ meta: meta,
+ stringify: this.stringify,
+ timestamp: this.timestamp,
+ showLevel: this.showLevel,
+ prettyPrint: this.prettyPrint,
+ raw: this.raw,
+ label: this.label,
+ logstash: this.logstash,
+ depth: this.depth,
+ formatter: this.formatter,
+ align: this.align,
+ humanReadableUnhandledException: this.humanReadableUnhandledException
+ });
+
+ if (this.stderrLevels[level]) {
+ process.stderr.write(output + '\n');
+ } else {
+ process.stdout.write(output + this.eol);
+ }
+
+ //
+ // Emit the `logged` event immediately because the event loop
+ // will not exit until `process.stdout` has drained anyway.
+ //
+ self.emit('logged');
+ callback(null, true);
+};
diff --git a/node_modules/winston/lib/winston/transports/file.js b/node_modules/winston/lib/winston/transports/file.js
new file mode 100644
index 0000000..b3df4b5
--- /dev/null
+++ b/node_modules/winston/lib/winston/transports/file.js
@@ -0,0 +1,678 @@
+/*
+ * file.js: Transport for outputting to a local log file
+ *
+ * (C) 2010 Charlie Robbins
+ * MIT LICENCE
+ *
+ */
+
+var events = require('events'),
+ fs = require('fs'),
+ path = require('path'),
+ util = require('util'),
+ async = require('async'),
+ zlib = require('zlib'),
+ common = require('../common'),
+ Transport = require('./transport').Transport,
+ isWritable = require('isstream').isWritable,
+ Stream = require('stream').Stream,
+ os = require('os');
+
+//
+// ### function File (options)
+// #### @options {Object} Options for this instance.
+// Constructor function for the File transport object responsible
+// for persisting log messages and metadata to one or more files.
+//
+var File = exports.File = function (options) {
+ var self = this;
+ Transport.call(this, options);
+
+ //
+ // Helper function which throws an `Error` in the event
+ // that any of the rest of the arguments is present in `options`.
+ //
+ function throwIf (target /*, illegal... */) {
+ Array.prototype.slice.call(arguments, 1).forEach(function (name) {
+ if (options[name]) {
+ throw new Error('Cannot set ' + name + ' and ' + target + 'together');
+ }
+ });
+ }
+
+ if (options.filename || options.dirname) {
+ throwIf('filename or dirname', 'stream');
+ this._basename = this.filename = options.filename
+ ? path.basename(options.filename)
+ : 'winston.log';
+
+ this.dirname = options.dirname || path.dirname(options.filename);
+ this.options = options.options || { flags: 'a' };
+
+ //
+ // "24 bytes" is maybe a good value for logging lines.
+ //
+ this.options.highWaterMark = this.options.highWaterMark || 24;
+ }
+ else if (options.stream) {
+ throwIf('stream', 'filename', 'maxsize');
+ this._stream = options.stream;
+ this._isStreams2 = isWritable(this._stream);
+ this._stream.on('error', function(error){
+ self.emit('error', error);
+ });
+ //
+ // We need to listen for drain events when
+ // write() returns false. This can make node
+ // mad at times.
+ //
+ this._stream.setMaxListeners(Infinity);
+ }
+ else {
+ throw new Error('Cannot log to file without filename or stream.');
+ }
+
+ this.json = options.json !== false;
+ this.logstash = options.logstash || false;
+ this.colorize = options.colorize || false;
+ this.maxsize = options.maxsize || null;
+ this.rotationFormat = options.rotationFormat || false;
+ this.zippedArchive = options.zippedArchive || false;
+ this.maxFiles = options.maxFiles || null;
+ this.prettyPrint = options.prettyPrint || false;
+ this.label = options.label || null;
+ this.timestamp = options.timestamp != null ? options.timestamp : true;
+ this.eol = options.eol || os.EOL;
+ this.tailable = options.tailable || false;
+ this.depth = options.depth || null;
+ this.showLevel = options.showLevel === undefined ? true : options.showLevel;
+ this.maxRetries = options.maxRetries || 2;
+
+ if (this.json) {
+ this.stringify = options.stringify;
+ }
+
+ //
+ // Internal state variables representing the number
+ // of files this instance has created and the current
+ // size (in bytes) of the current logfile.
+ //
+ this._size = 0;
+ this._created = 0;
+ this._buffer = [];
+ this._draining = false;
+ this._opening = false;
+ this._failures = 0;
+ this._archive = null;
+};
+
+//
+// Inherit from `winston.Transport`.
+//
+util.inherits(File, Transport);
+
+//
+// Expose the name of this Transport on the prototype
+//
+File.prototype.name = 'file';
+
+//
+// ### 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.
+//
+File.prototype.log = function (level, msg, meta, callback) {
+ if (this.silent) {
+ return callback(null, true);
+ }
+
+ //
+ // If failures exceeds maxRetries then we can't access the
+ // stream. In this case we need to perform a noop and return
+ // an error.
+ //
+ if (this._failures >= this.maxRetries) {
+ return callback(new Error('Transport is in a failed state.'));
+ }
+
+ var self = this;
+
+ if (typeof msg !== 'string') {
+ msg = '' + msg;
+ }
+
+ var output = common.log({
+ level: level,
+ message: msg,
+ meta: meta,
+ json: this.json,
+ logstash: this.logstash,
+ colorize: this.colorize,
+ prettyPrint: this.prettyPrint,
+ timestamp: this.timestamp,
+ showLevel: this.showLevel,
+ stringify: this.stringify,
+ label: this.label,
+ depth: this.depth,
+ formatter: this.formatter,
+ humanReadableUnhandledException: this.humanReadableUnhandledException
+ });
+
+ if (typeof output === 'string') {
+ output += this.eol;
+ }
+
+ if (!this.filename) {
+ //
+ // If there is no `filename` on this instance then it was configured
+ // with a raw `WriteableStream` instance and we should not perform any
+ // size restrictions.
+ //
+ this._write(output, callback);
+ this._size += output.length;
+ this._lazyDrain();
+ }
+ else {
+ this.open(function (err) {
+ if (err) {
+ //
+ // If there was an error enqueue the message
+ //
+ return self._buffer.push([output, callback]);
+ }
+
+ self._write(output, callback);
+ self._size += output.length;
+ self._lazyDrain();
+ });
+ }
+};
+
+//
+// ### function _write (data, cb)
+// #### @data {String|Buffer} Data to write to the instance's stream.
+// #### @cb {function} Continuation to respond to when complete.
+// Write to the stream, ensure execution of a callback on completion.
+//
+File.prototype._write = function(data, callback) {
+ if (this._isStreams2) {
+ this._stream.write(data);
+ return callback && process.nextTick(function () {
+ callback(null, true);
+ });
+ }
+
+ // If this is a file write stream, we could use the builtin
+ // callback functionality, however, the stream is not guaranteed
+ // to be an fs.WriteStream.
+ var ret = this._stream.write(data);
+ if (!callback) return;
+ if (ret === false) {
+ return this._stream.once('drain', function() {
+ callback(null, true);
+ });
+ }
+ process.nextTick(function () {
+ 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.
+//
+File.prototype.query = function (options, callback) {
+ if (typeof options === 'function') {
+ callback = options;
+ options = {};
+ }
+
+ var file = path.join(this.dirname, this.filename),
+ options = this.normalizeQuery(options),
+ buff = '',
+ results = [],
+ row = 0;
+
+ var stream = fs.createReadStream(file, {
+ encoding: 'utf8'
+ });
+
+ stream.on('error', function (err) {
+ if (stream.readable) {
+ stream.destroy();
+ }
+ if (!callback) return;
+ return err.code !== 'ENOENT'
+ ? callback(err)
+ : callback(null, results);
+ });
+
+ stream.on('data', function (data) {
+ var data = (buff + data).split(/\n+/),
+ l = data.length - 1,
+ i = 0;
+
+ for (; i < l; i++) {
+ if (!options.start || row >= options.start) {
+ add(data[i]);
+ }
+ row++;
+ }
+
+ buff = data[l];
+ });
+
+ stream.on('close', function () {
+ if (buff) add(buff, true);
+ if (options.order === 'desc') {
+ results = results.reverse();
+ }
+ if (callback) callback(null, results);
+ });
+
+ function add(buff, attempt) {
+ try {
+ var log = JSON.parse(buff);
+ if (check(log)) push(log);
+ } catch (e) {
+ if (!attempt) {
+ stream.emit('error', e);
+ }
+ }
+ }
+
+ function push(log) {
+ if (options.rows && results.length >= options.rows) {
+ if (stream.readable) {
+ stream.destroy();
+ }
+ return;
+ }
+
+ if (options.fields) {
+ var obj = {};
+ options.fields.forEach(function (key) {
+ obj[key] = log[key];
+ });
+ log = obj;
+ }
+
+ results.push(log);
+ }
+
+ function check(log) {
+ if (!log) return;
+
+ if (typeof log !== 'object') return;
+
+ var time = new Date(log.timestamp);
+ if ((options.from && time < options.from)
+ || (options.until && time > options.until)) {
+ return;
+ }
+
+ return true;
+ }
+};
+
+//
+// ### function stream (options)
+// #### @options {Object} Stream options for this instance.
+// Returns a log stream for this transport. Options object is optional.
+//
+File.prototype.stream = function (options) {
+ var file = path.join(this.dirname, this.filename),
+ options = options || {},
+ stream = new Stream;
+
+ var tail = {
+ file: file,
+ start: options.start
+ };
+
+ stream.destroy = common.tailFile(tail, function (err, line) {
+
+ if(err){
+ return stream.emit('error',err);
+ }
+
+ try {
+ stream.emit('data', line);
+ line = JSON.parse(line);
+ stream.emit('log', line);
+ } catch (e) {
+ stream.emit('error', e);
+ }
+ });
+
+ return stream;
+};
+
+//
+// ### function open (callback)
+// #### @callback {function} Continuation to respond to when complete
+// Checks to see if a new file needs to be created based on the `maxsize`
+// (if any) and the current size of the file used.
+//
+File.prototype.open = function (callback) {
+ if (this.opening) {
+ //
+ // If we are already attempting to open the next
+ // available file then respond with a value indicating
+ // that the message should be buffered.
+ //
+ return callback(true);
+ }
+ else if (!this._stream || (this.maxsize && this._size >= this.maxsize)) {
+ //
+ // If we dont have a stream or have exceeded our size, then create
+ // the next stream and respond with a value indicating that
+ // the message should be buffered.
+ //
+ callback(true);
+ return this._createStream();
+ }
+
+ this._archive = this.zippedArchive ? this._stream.path : null;
+
+ //
+ // Otherwise we have a valid (and ready) stream.
+ //
+ callback();
+};
+
+//
+// ### function close ()
+// Closes the stream associated with this instance.
+//
+File.prototype.close = function () {
+ var self = this;
+
+ if (this._stream) {
+ this._stream.end();
+ this._stream.destroySoon();
+
+ this._stream.once('finish', function () {
+ self.emit('flush');
+ self.emit('closed');
+ });
+ }
+};
+
+//
+// ### function flush ()
+// Flushes any buffered messages to the current `stream`
+// used by this instance.
+//
+File.prototype.flush = function () {
+ var self = this;
+
+ // If nothing to flush, there will be no "flush" event from native stream
+ // Thus, the "open" event will never be fired (see _createStream.createAndFlush function)
+ // That means, self.opening will never set to false and no logs will be written to disk
+ if (!this._buffer.length) {
+ return self.emit('flush');
+ }
+
+ //
+ // Iterate over the `_buffer` of enqueued messaged
+ // and then write them to the newly created stream.
+ //
+ this._buffer.forEach(function (item) {
+ var str = item[0],
+ callback = item[1];
+
+ process.nextTick(function () {
+ self._write(str, callback);
+ self._size += str.length;
+ });
+ });
+
+ //
+ // Quickly truncate the `_buffer` once the write operations
+ // have been started
+ //
+ self._buffer.length = 0;
+
+ //
+ // When the stream has drained we have flushed
+ // our buffer.
+ //
+ self._stream.once('drain', function () {
+ self.emit('flush');
+ self.emit('logged');
+ });
+};
+
+//
+// ### @private function _createStream ()
+// Attempts to open the next appropriate file for this instance
+// based on the common state (such as `maxsize` and `_basename`).
+//
+File.prototype._createStream = function () {
+ var self = this;
+ this.opening = true;
+
+ (function checkFile (target) {
+ var fullname = path.join(self.dirname, target);
+
+ //
+ // Creates the `WriteStream` and then flushes any
+ // buffered messages.
+ //
+ function createAndFlush (size) {
+ if (self._stream) {
+ self._stream.end();
+ self._stream.destroySoon();
+ }
+
+ self._size = size;
+ self.filename = target;
+ self._stream = fs.createWriteStream(fullname, self.options);
+ self._isStreams2 = isWritable(self._stream);
+ self._stream.on('error', function(error){
+ if (self._failures < self.maxRetries) {
+ self._createStream();
+ self._failures++;
+ }
+ else {
+ self.emit('error', error);
+ }
+ });
+ //
+ // We need to listen for drain events when
+ // write() returns false. This can make node
+ // mad at times.
+ //
+ self._stream.setMaxListeners(Infinity);
+
+ //
+ // When the current stream has finished flushing
+ // then we can be sure we have finished opening
+ // and thus can emit the `open` event.
+ //
+ self.once('flush', function () {
+ // Because "flush" event is based on native stream "drain" event,
+ // logs could be written inbetween "self.flush()" and here
+ // Therefore, we need to flush again to make sure everything is flushed
+ self.flush();
+
+ self.opening = false;
+ self.emit('open', fullname);
+ });
+ //
+ // Remark: It is possible that in the time it has taken to find the
+ // next logfile to be written more data than `maxsize` has been buffered,
+ // but for sensible limits (10s - 100s of MB) this seems unlikely in less
+ // than one second.
+ //
+ self.flush();
+ compressFile();
+ }
+
+ function compressFile() {
+ if (self._archive) {
+ var gzip = zlib.createGzip();
+
+ var inp = fs.createReadStream(String(self._archive));
+ var out = fs.createWriteStream(self._archive + '.gz');
+
+ inp.pipe(gzip).pipe(out);
+
+ fs.unlink(String(self._archive));
+ self._archive = '';
+ }
+ }
+
+ fs.stat(fullname, function (err, stats) {
+ if (err) {
+ if (err.code !== 'ENOENT') {
+ return self.emit('error', err);
+ }
+ return createAndFlush(0);
+ }
+
+ if (!stats || (self.maxsize && stats.size >= self.maxsize)) {
+ //
+ // If `stats.size` is greater than the `maxsize` for
+ // this instance then try again
+ //
+ return self._incFile(function() {
+ checkFile(self._getFile());
+ });
+ }
+
+ createAndFlush(stats.size);
+ });
+ })(this._getFile());
+};
+
+
+File.prototype._incFile = function (callback) {
+ var ext = path.extname(this._basename),
+ basename = path.basename(this._basename, ext),
+ oldest,
+ target;
+
+ if (!this.tailable) {
+ this._created += 1;
+ this._checkMaxFilesIncrementing(ext, basename, callback);
+ }
+ else {
+ this._checkMaxFilesTailable(ext, basename, callback);
+ }
+};
+
+//
+// ### @private function _getFile ()
+// Gets the next filename to use for this instance
+// in the case that log filesizes are being capped.
+//
+File.prototype._getFile = function () {
+ var ext = path.extname(this._basename),
+ basename = path.basename(this._basename, ext);
+
+ //
+ // Caveat emptor (indexzero): rotationFormat() was broken by design
+ // when combined with max files because the set of files to unlink
+ // is never stored.
+ //
+ return !this.tailable && this._created
+ ? basename + (this.rotationFormat ? this.rotationFormat() : this._created) + ext
+ : basename + ext;
+};
+
+//
+// ### @private function _checkMaxFilesIncrementing ()
+// Increment the number of files created or
+// checked by this instance.
+//
+File.prototype._checkMaxFilesIncrementing = function (ext, basename, callback) {
+ var oldest, target,
+ self = this;
+
+ if (self.zippedArchive) {
+ self._archive = path.join(self.dirname, basename +
+ ((self._created === 1) ? '' : self._created-1) +
+ ext);
+ }
+
+
+ // Check for maxFiles option and delete file
+ if (!self.maxFiles || self._created < self.maxFiles) {
+ return callback();
+ }
+
+ oldest = self._created - self.maxFiles;
+ target = path.join(self.dirname, basename + (oldest !== 0 ? oldest : '') + ext +
+ (self.zippedArchive ? '.gz' : ''));
+ fs.unlink(target, callback);
+};
+
+//
+// ### @private function _checkMaxFilesTailable ()
+//
+// Roll files forward based on integer, up to maxFiles.
+// e.g. if base if file.log and it becomes oversized, roll
+// to file1.log, and allow file.log to be re-used. If
+// file is oversized again, roll file1.log to file2.log,
+// roll file.log to file1.log, and so on.
+File.prototype._checkMaxFilesTailable = function (ext, basename, callback) {
+ var tasks = [],
+ self = this;
+
+ if (!this.maxFiles)
+ return;
+
+ for (var x = this.maxFiles - 1; x > 0; x--) {
+ tasks.push(function (i) {
+ return function (cb) {
+ var tmppath = path.join(self.dirname, basename + (i - 1) + ext +
+ (self.zippedArchive ? '.gz' : ''));
+ fs.exists(tmppath, function (exists) {
+ if (!exists) {
+ return cb(null);
+ }
+
+ fs.rename(tmppath, path.join(self.dirname, basename + i + ext +
+ (self.zippedArchive ? '.gz' : '')), cb);
+ });
+ };
+ }(x));
+ }
+
+ if (self.zippedArchive) {
+ self._archive = path.join(self.dirname, basename + 1 + ext);
+ }
+ async.series(tasks, function (err) {
+ fs.rename(
+ path.join(self.dirname, basename + ext),
+ path.join(self.dirname, basename + 1 + ext),
+ callback
+ );
+ });
+};
+
+//
+// ### @private function _lazyDrain ()
+// Lazily attempts to emit the `logged` event when `this.stream` has
+// drained. This is really just a simple mutex that only works because
+// Node.js is single-threaded.
+//
+File.prototype._lazyDrain = function () {
+ var self = this;
+
+ if (!this._draining && this._stream) {
+ this._draining = true;
+
+ this._stream.once('drain', function () {
+ this._draining = false;
+ self.emit('logged');
+ });
+ }
+};
diff --git a/node_modules/winston/lib/winston/transports/http.js b/node_modules/winston/lib/winston/transports/http.js
new file mode 100644
index 0000000..f7e1af6
--- /dev/null
+++ b/node_modules/winston/lib/winston/transports/http.js
@@ -0,0 +1,232 @@
+var util = require('util'),
+ winston = require('../../winston'),
+ http = require('http'),
+ https = require('https'),
+ Stream = require('stream').Stream,
+ Transport = require('./transport').Transport;
+
+//
+// ### 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) {
+ Transport.call(this, 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) {
+ options = options || {};
+
+ var auth = options.auth || this.auth,
+ path = options.path || this.path || '',
+ req;
+
+ delete options.auth;
+ delete options.path;
+
+ // Prepare options for outgoing HTTP request
+ req = (this.ssl ? https : http).request({
+ host: this.host,
+ port: this.port,
+ path: '/' + path.replace(/^\//, ''),
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ auth: (auth) ? auth.username + ':' + auth.password : ''
+ });
+
+ req.on('error', callback);
+ req.on('response', function (res) {
+ res.on('end', function () {
+ callback(null, res);
+ });
+
+ res.resume();
+ });
+
+ req.end(new Buffer(JSON.stringify(options), 'utf8'));
+};
+
+//
+// ### 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
+ }
+ };
+
+ if (meta) {
+ if (meta.path) {
+ options.path = meta.path;
+ delete meta.path;
+ }
+
+ if (meta.auth) {
+ options.auth = meta.auth;
+ delete meta.auth;
+ }
+ }
+
+ this._request(options, function (err, res) {
+ 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
+ };
+
+ if (options.params.path) {
+ options.path = options.params.path;
+ delete options.params.path;
+ }
+
+ if (options.params.auth) {
+ options.auth = options.params.auth;
+ delete options.params.auth;
+ }
+
+ 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) {
+ options = options || {};
+
+ var self = this,
+ stream = new Stream,
+ req,
+ buff;
+
+ stream.destroy = function () {
+ req.destroy();
+ };
+
+ options = {
+ method: 'stream',
+ params: options
+ };
+
+ if (options.params.path) {
+ options.path = options.params.path;
+ delete options.params.path;
+ }
+
+ if (options.params.auth) {
+ options.auth = options.params.auth;
+ delete options.params.auth;
+ }
+
+ 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;
+};
diff --git a/node_modules/winston/lib/winston/transports/memory.js b/node_modules/winston/lib/winston/transports/memory.js
new file mode 100644
index 0000000..e4f562e
--- /dev/null
+++ b/node_modules/winston/lib/winston/transports/memory.js
@@ -0,0 +1,89 @@
+var events = require('events'),
+ util = require('util'),
+ common = require('../common'),
+ Transport = require('./transport').Transport;
+
+//
+// ### function Memory (options)
+// #### @options {Object} Options for this instance.
+// Constructor function for the Memory transport object responsible
+// for persisting log messages and metadata to a memory array of messages.
+//
+var Memory = exports.Memory = function (options) {
+ Transport.call(this, options);
+ options = options || {};
+
+ this.errorOutput = [];
+ this.writeOutput = [];
+
+ this.json = options.json || false;
+ this.colorize = options.colorize || false;
+ this.prettyPrint = options.prettyPrint || false;
+ this.timestamp = typeof options.timestamp !== 'undefined' ? options.timestamp : false;
+ this.showLevel = options.showLevel === undefined ? true : options.showLevel;
+ this.label = options.label || null;
+ this.depth = options.depth || null;
+
+ if (this.json) {
+ this.stringify = options.stringify || function (obj) {
+ return JSON.stringify(obj, null, 2);
+ };
+ }
+};
+
+//
+// Inherit from `winston.Transport`.
+//
+util.inherits(Memory, Transport);
+
+//
+// Expose the name of this Transport on the prototype
+//
+Memory.prototype.name = 'memory';
+
+//
+// ### 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.
+//
+Memory.prototype.log = function (level, msg, meta, callback) {
+ if (this.silent) {
+ return callback(null, true);
+ }
+
+ var self = this,
+ output;
+
+ output = common.log({
+ colorize: this.colorize,
+ json: this.json,
+ level: level,
+ message: msg,
+ meta: meta,
+ stringify: this.stringify,
+ timestamp: this.timestamp,
+ prettyPrint: this.prettyPrint,
+ raw: this.raw,
+ label: this.label,
+ depth: this.depth,
+ formatter: this.formatter,
+ humanReadableUnhandledException: this.humanReadableUnhandledException
+ });
+
+ if (level === 'error' || level === 'debug') {
+ this.errorOutput.push(output);
+ } else {
+ this.writeOutput.push(output);
+ }
+
+ self.emit('logged');
+ callback(null, true);
+};
+
+Memory.prototype.clearLogs = function () {
+ this.errorOutput = [];
+ this.writeOutput = [];
+};
diff --git a/node_modules/winston/lib/winston/transports/transport.js b/node_modules/winston/lib/winston/transports/transport.js
new file mode 100644
index 0000000..d279d00
--- /dev/null
+++ b/node_modules/winston/lib/winston/transports/transport.js
@@ -0,0 +1,135 @@
+/*
+ * transport.js: Base Transport object for all Winston transports.
+ *
+ * (C) 2010 Charlie Robbins
+ * MIT LICENCE
+ *
+ */
+
+var events = require('events'),
+ util = require('util');
+
+//
+// ### function Transport (options)
+// #### @options {Object} Options for this instance.
+// Constructor function for the Tranport object responsible
+// base functionality for all winston transports.
+//
+var Transport = exports.Transport = function (options) {
+ events.EventEmitter.call(this);
+
+ options = options || {};
+ this.silent = options.silent || false;
+ this.raw = options.raw || false;
+ this.name = options.name || this.name;
+ this.formatter = options.formatter;
+
+ //
+ // Do not set a default level. When `level` is falsey on any
+ // `Transport` instance, any `Logger` instance uses the
+ // configured level (instead of the Transport level)
+ //
+ this.level = options.level;
+
+ this.handleExceptions = options.handleExceptions || false;
+ this.exceptionsLevel = options.exceptionsLevel || 'error';
+ this.humanReadableUnhandledException = options.humanReadableUnhandledException || false;
+};
+
+//
+// Inherit from `events.EventEmitter`.
+//
+util.inherits(Transport, events.EventEmitter);
+
+//
+// ### function formatQuery (query)
+// #### @query {string|Object} Query to format
+// Formats the specified `query` Object (or string) to conform
+// with the underlying implementation of this transport.
+//
+Transport.prototype.formatQuery = function (query) {
+ return query;
+};
+
+//
+// ### function normalizeQuery (query)
+// #### @options {string|Object} Query to normalize
+// Normalize options for query
+//
+Transport.prototype.normalizeQuery = function (options) {
+ //
+ // Use options similar to loggly.
+ // [See Loggly Search API](http://wiki.loggly.com/retrieve_events#optional)
+ //
+
+ options = options || {};
+
+ // limit
+ options.rows = options.rows || options.limit || 10;
+
+ // starting row offset
+ options.start = options.start || 0;
+
+ // now
+ options.until = options.until || new Date;
+ if (typeof options.until !== 'object') {
+ options.until = new Date(options.until);
+ }
+
+ // now - 24
+ options.from = options.from || (options.until - (24 * 60 * 60 * 1000));
+ if (typeof options.from !== 'object') {
+ options.from = new Date(options.from);
+ }
+
+
+ // 'asc' or 'desc'
+ options.order = options.order || 'desc';
+
+ // which fields to select
+ options.fields = options.fields;
+
+ return options;
+};
+
+//
+// ### function formatResults (results, options)
+// #### @results {Object|Array} Results returned from `.query`.
+// #### @options {Object} **Optional** Formatting options
+// Formats the specified `results` with the given `options` accordinging
+// to the implementation of this transport.
+//
+Transport.prototype.formatResults = function (results, options) {
+ return results;
+};
+
+//
+// ### function logException (msg, meta, callback)
+// #### @msg {string} Message to log
+// #### @meta {Object} **Optional** Additional metadata to attach
+// #### @callback {function} Continuation to respond to when complete.
+// Logs the specified `msg`, `meta` and responds to the callback once the log
+// operation is complete to ensure that the event loop will not exit before
+// all logging has completed.
+//
+Transport.prototype.logException = function (msg, meta, callback) {
+ var self = this,
+ called;
+
+ if (this.silent) {
+ return callback();
+ }
+
+ function onComplete () {
+ if (!called) {
+ called = true;
+ self.removeListener('logged', onComplete);
+ self.removeListener('error', onComplete);
+ callback();
+ }
+ }
+
+ this.once('logged', onComplete);
+ this.once('error', onComplete);
+ this.log(self.exceptionsLevel, msg, meta, function () { });
+};