This commit is contained in:
Dobie Wollert
2015-12-16 09:12:35 -08:00
parent f9c9672818
commit f94ca33b9e
805 changed files with 67409 additions and 24609 deletions

165
node_modules/winston/lib/winston.js generated vendored Normal file
View File

@ -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
};
}
});

483
node_modules/winston/lib/winston/common.js generated vendored Normal file
View File

@ -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));
};

68
node_modules/winston/lib/winston/config.js generated vendored Normal file
View File

@ -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;
};

35
node_modules/winston/lib/winston/config/cli-config.js generated vendored Normal file
View File

@ -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'
};

27
node_modules/winston/lib/winston/config/npm-config.js generated vendored Normal file
View File

@ -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'
};

View File

@ -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'
};

127
node_modules/winston/lib/winston/container.js generated vendored Normal file
View File

@ -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];
}

56
node_modules/winston/lib/winston/exception.js generated vendored Normal file
View File

@ -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(),
}
});
};

723
node_modules/winston/lib/winston/logger.js generated vendored Executable file
View File

@ -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);
};

29
node_modules/winston/lib/winston/transports.js generated vendored Normal file
View File

@ -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;
}, {})
);

130
node_modules/winston/lib/winston/transports/console.js generated vendored Normal file
View File

@ -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);
};

678
node_modules/winston/lib/winston/transports/file.js generated vendored Normal file
View File

@ -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');
});
}
};

232
node_modules/winston/lib/winston/transports/http.js generated vendored Normal file
View File

@ -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;
};

89
node_modules/winston/lib/winston/transports/memory.js generated vendored Normal file
View File

@ -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 = [];
};

View File

@ -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 () { });
};