mirror of
https://github.com/mgerb/mywebsite
synced 2026-01-12 02:42:48 +00:00
updated package.json
This commit is contained in:
6
node_modules/winston/.npmignore
generated
vendored
Normal file
6
node_modules/winston/.npmignore
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
test/*.log
|
||||
test/fixtures/*.json
|
||||
test/fixtures/logs/*.log*
|
||||
node_modules/
|
||||
node_modules/*
|
||||
npm-debug.log
|
||||
10
node_modules/winston/.travis.yml
generated
vendored
Normal file
10
node_modules/winston/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "0.8"
|
||||
- "0.10"
|
||||
|
||||
notifications:
|
||||
email:
|
||||
- travis@nodejitsu.com
|
||||
irc: "irc.freenode.org#nodejitsu"
|
||||
|
||||
9
node_modules/winston/CHANGELOG.md
generated
vendored
Normal file
9
node_modules/winston/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
0.6.2 / 2012-07-08
|
||||
==================
|
||||
|
||||
* Added prettyPrint option for console logging
|
||||
* Multi-line values for conditional returns are not allowed
|
||||
* Added acceptance of `stringify` option
|
||||
* Fixed padding for log levels
|
||||
|
||||
19
node_modules/winston/LICENSE
generated
vendored
Normal file
19
node_modules/winston/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2010 Charlie Robbins
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
911
node_modules/winston/README.md
generated
vendored
Normal file
911
node_modules/winston/README.md
generated
vendored
Normal file
@@ -0,0 +1,911 @@
|
||||
# winston [](http://travis-ci.org/flatiron/winston)
|
||||
|
||||
A multi-transport async logging library for node.js. <span style="font-size:28px; font-weight:bold;">"CHILL WINSTON! ... I put it in the logs."</span>
|
||||
|
||||
## Motivation
|
||||
Winston is designed to be a simple and universal logging library with support for multiple transports. A transport is essentially a storage device for your logs. Each instance of a winston logger can have multiple transports configured at different levels. For example, one may want error logs to be stored in a persistent remote location (like a database), but all logs output to the console or a local file.
|
||||
|
||||
There also seemed to be a lot of logging libraries out there that coupled their implementation of logging (i.e. how the logs are stored / indexed) to the API that they exposed to the programmer. This library aims to decouple those parts of the process to make it more flexible and extensible.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install winston
|
||||
```
|
||||
|
||||
## Usage
|
||||
There are two different ways to use winston: directly via the default logger, or by instantiating your own Logger. The former is merely intended to be a convenient shared logger to use throughout your application if you so choose.
|
||||
|
||||
* [Logging](#logging)
|
||||
* [Using the Default Logger](#using-the-default-logger)
|
||||
* [Instantiating your own Logger](#instantiating-your-own-logger)
|
||||
* [Logging with Metadata](#logging-with-metadata)
|
||||
* [String interpolation ](#string-interpolation)
|
||||
* [Transports](https://github.com/flatiron/winston/blob/master/docs/transports.md)
|
||||
* [Profiling](#profiling)
|
||||
* [Streaming Logs](#streaming-logs)
|
||||
* [Querying Logs](#querying-logs)
|
||||
* [Exceptions](#exceptions)
|
||||
* [Handling Uncaught Exceptions with winston](#handling-uncaught-exceptions-with-winston)
|
||||
* [To Exit or Not to Exit](#to-exit-or-not-to-exit)
|
||||
* [Logging Levels](#logging-levels)
|
||||
* [Using Logging Levels](#using-logging-levels)
|
||||
* [Using Custom Logging Levels](#using-custom-logging-levels)
|
||||
* [Further Reading](#further-reading)
|
||||
* [Events and Callbacks in Winston](#events-and-callbacks-in-winston)
|
||||
* [Working with multiple Loggers in winston](#working-with-multiple-loggers-in-winston)
|
||||
* [Using winston in a CLI tool](#using-winston-in-a-cli-tool)
|
||||
* [Extending another object with Logging](#extending-another-object-with-logging)
|
||||
* [Working with transports](#working-with-transports)
|
||||
* [Adding Custom Transports](#adding-custom-transports)
|
||||
* [Installation](#installation)
|
||||
* [Run Tests](#run-tests)
|
||||
|
||||
|
||||
## Logging
|
||||
|
||||
### Using the Default Logger
|
||||
The default logger is accessible through the winston module directly. Any method that you could call on an instance of a logger is available on the default logger:
|
||||
|
||||
``` js
|
||||
var winston = require('winston');
|
||||
|
||||
winston.log('info', 'Hello distributed log files!');
|
||||
winston.info('Hello again distributed logs');
|
||||
```
|
||||
|
||||
By default, only the Console transport is set on the default logger. You can add or remove transports via the add() and remove() methods:
|
||||
|
||||
``` js
|
||||
winston.add(winston.transports.File, { filename: 'somefile.log' });
|
||||
winston.remove(winston.transports.Console);
|
||||
```
|
||||
|
||||
For more documentation about working with each individual transport supported by Winston see the [Working with transports](#working-with-transports) section below.
|
||||
|
||||
### Instantiating your own Logger
|
||||
If you would prefer to manage the object lifetime of loggers you are free to instantiate them yourself:
|
||||
|
||||
``` js
|
||||
var logger = new (winston.Logger)({
|
||||
transports: [
|
||||
new (winston.transports.Console)(),
|
||||
new (winston.transports.File)({ filename: 'somefile.log' })
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
You can work with this logger in the same way that you work with the default logger:
|
||||
|
||||
``` js
|
||||
//
|
||||
// Logging
|
||||
//
|
||||
logger.log('info', 'Hello distributed log files!');
|
||||
logger.info('Hello again distributed logs');
|
||||
|
||||
//
|
||||
// Adding / Removing Transports
|
||||
// (Yes It's chainable)
|
||||
//
|
||||
logger.add(winston.transports.File)
|
||||
.remove(winston.transports.Console);
|
||||
```
|
||||
|
||||
### Logging with Metadata
|
||||
In addition to logging string messages, winston will also optionally log additional JSON metadata objects. Adding metadata is simple:
|
||||
|
||||
``` js
|
||||
winston.log('info', 'Test Log Message', { anything: 'This is metadata' });
|
||||
```
|
||||
|
||||
The way these objects are stored varies from transport to transport (to best support the storage mechanisms offered). Here's a quick summary of how each transports handles metadata:
|
||||
|
||||
1. __Console:__ Logged via util.inspect(meta)
|
||||
2. __File:__ Logged via util.inspect(meta)
|
||||
|
||||
## Profiling
|
||||
In addition to logging messages and metadata, winston also has a simple profiling mechanism implemented for any logger:
|
||||
|
||||
``` js
|
||||
//
|
||||
// Start profile of 'test'
|
||||
// Remark: Consider using Date.now() with async operations
|
||||
//
|
||||
winston.profile('test');
|
||||
|
||||
setTimeout(function () {
|
||||
//
|
||||
// Stop profile of 'test'. Logging will now take place:
|
||||
// "17 Jan 21:00:00 - info: test duration=1000ms"
|
||||
//
|
||||
winston.profile('test');
|
||||
}, 1000);
|
||||
```
|
||||
|
||||
All profile messages are set to the 'info' by default and both message and metadata are optional There are no plans in the Roadmap to make this configurable, but I'm open to suggestions / issues.
|
||||
|
||||
### String interpolation
|
||||
The `log` method provides the same string interpolation methods like [`util.format`][10].
|
||||
|
||||
This allows for the following log messages.
|
||||
``` js
|
||||
logger.log('info', 'test message %s', 'my string');
|
||||
// info: test message my string
|
||||
|
||||
logger.log('info', 'test message %d', 123);
|
||||
// info: test message 123
|
||||
|
||||
logger.log('info', 'test message %j', {number: 123}, {});
|
||||
// info: test message {"number":123}
|
||||
// meta = {}
|
||||
|
||||
logger.log('info', 'test message %s, %s', 'first', 'second', {number: 123});
|
||||
// info: test message first, second
|
||||
// meta = {number: 123}
|
||||
|
||||
logger.log('info', 'test message', 'first', 'second', {number: 123});
|
||||
// info: test message first second
|
||||
// meta = {number: 123}
|
||||
|
||||
logger.log('info', 'test message %s, %s', 'first', 'second', {number: 123}, function(){});
|
||||
// info: test message first, second
|
||||
// meta = {numer: 123}
|
||||
// callback = function(){}
|
||||
|
||||
logger.log('info', 'test message', 'first', 'second', {number: 123}, function(){});
|
||||
// info: test message first second
|
||||
// meta = {numer: 123}
|
||||
// callback = function(){}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Querying Logs
|
||||
Winston supports querying of logs with Loggly-like options. [See Loggly Search API](http://wiki.loggly.com/retrieve_events#optional).
|
||||
Specifically: `File`, `Couchdb`, `Redis`, `Loggly`, `Nssocket`, and `Http`.
|
||||
|
||||
``` js
|
||||
var options = {
|
||||
from: new Date - 24 * 60 * 60 * 1000,
|
||||
until: new Date,
|
||||
limit: 10,
|
||||
start: 0,
|
||||
order: 'desc',
|
||||
fields: ['message']
|
||||
};
|
||||
|
||||
//
|
||||
// Find items logged between today and yesterday.
|
||||
//
|
||||
winston.query(options, function (err, results) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
console.log(results);
|
||||
});
|
||||
```
|
||||
|
||||
## Streaming Logs
|
||||
Streaming allows you to stream your logs back from your chosen transport.
|
||||
|
||||
``` js
|
||||
//
|
||||
// Start at the end.
|
||||
//
|
||||
winston.stream({ start: -1 }).on('log', function(log) {
|
||||
console.log(log);
|
||||
});
|
||||
```
|
||||
|
||||
## Exceptions
|
||||
|
||||
### Handling Uncaught Exceptions with winston
|
||||
|
||||
With `winston`, it is possible to catch and log `uncaughtException` events from your process. There are two distinct ways of enabling this functionality either through the default winston logger or your own logger instance.
|
||||
|
||||
If you want to use this feature with the default logger simply call `.handleExceptions()` with a transport instance.
|
||||
|
||||
``` js
|
||||
//
|
||||
// You can add a separate exception logger by passing it to `.handleExceptions`
|
||||
//
|
||||
winston.handleExceptions(new winston.transports.File({ filename: 'path/to/exceptions.log' }))
|
||||
|
||||
//
|
||||
// Alternatively you can set `.handleExceptions` to true when adding transports to winston
|
||||
//
|
||||
winston.add(winston.transports.File, {
|
||||
filename: 'path/to/all-logs.log',
|
||||
handleExceptions: true
|
||||
});
|
||||
```
|
||||
|
||||
### To Exit or Not to Exit
|
||||
|
||||
By default, winston will exit after logging an uncaughtException. if this is not the behavior you want,
|
||||
set `exitOnError = false`
|
||||
|
||||
``` js
|
||||
var logger = new (winston.Logger)({ exitOnError: false });
|
||||
|
||||
//
|
||||
// or, like this:
|
||||
//
|
||||
logger.exitOnError = false;
|
||||
```
|
||||
|
||||
When working with custom logger instances, you can pass in separate transports to the `exceptionHandlers` property or set `.handleExceptions` on any transport.
|
||||
|
||||
Example 1
|
||||
|
||||
``` js
|
||||
var logger = new (winston.Logger)({
|
||||
transports: [
|
||||
new winston.transports.File({ filename: 'path/to/all-logs.log' })
|
||||
]
|
||||
exceptionHandlers: [
|
||||
new winston.transports.File({ filename: 'path/to/exceptions.log' })
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
Example 2
|
||||
|
||||
```
|
||||
var logger = new winston.Logger({
|
||||
transports: [
|
||||
new winston.transports.Console({
|
||||
handleExceptions: true,
|
||||
json: true
|
||||
})
|
||||
],
|
||||
exitOnError: false
|
||||
});
|
||||
```
|
||||
|
||||
The `exitOnError` option can also be a function to prevent exit on only certain types of errors:
|
||||
|
||||
``` js
|
||||
function ignoreEpipe(err) {
|
||||
return err.code !== 'EPIPE';
|
||||
}
|
||||
|
||||
var logger = new (winston.Logger)({ exitOnError: ignoreEpipe });
|
||||
|
||||
//
|
||||
// or, like this:
|
||||
//
|
||||
logger.exitOnError = ignoreEpipe;
|
||||
```
|
||||
|
||||
## Logging Levels
|
||||
|
||||
### Using Logging Levels
|
||||
Setting the level for your logging message can be accomplished in one of two ways. You can pass a string representing the logging level to the log() method or use the level specified methods defined on every winston Logger.
|
||||
|
||||
``` js
|
||||
//
|
||||
// Any logger instance
|
||||
//
|
||||
logger.log('silly', "127.0.0.1 - there's no place like home");
|
||||
logger.log('debug', "127.0.0.1 - there's no place like home");
|
||||
logger.log('verbose', "127.0.0.1 - there's no place like home");
|
||||
logger.log('info', "127.0.0.1 - there's no place like home");
|
||||
logger.log('warn', "127.0.0.1 - there's no place like home");
|
||||
logger.log('error', "127.0.0.1 - there's no place like home");
|
||||
logger.info("127.0.0.1 - there's no place like home");
|
||||
logger.warn("127.0.0.1 - there's no place like home");
|
||||
logger.error("127.0.0.1 - there's no place like home");
|
||||
|
||||
//
|
||||
// Default logger
|
||||
//
|
||||
winston.log('info', "127.0.0.1 - there's no place like home");
|
||||
winston.info("127.0.0.1 - there's no place like home");
|
||||
```
|
||||
|
||||
Winston allows you to set a `level` on each transport that specifies the level of messages this transport should log. For example, you could log only errors to the console, with the full logs in a file (note that the default level of a transport is `info`):
|
||||
|
||||
``` js
|
||||
var logger = new (winston.Logger)({
|
||||
transports: [
|
||||
new (winston.transports.Console)({ level: 'error' }),
|
||||
new (winston.transports.File)({ filename: 'somefile.log' })
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
You may also dynamically change the log level of a transport:
|
||||
|
||||
``` js
|
||||
var logger = new (winston.Logger)({
|
||||
transports: [
|
||||
new (winston.transports.Console)({ level: 'warn' }),
|
||||
new (winston.transports.File)({ filename: 'somefile.log', level: 'error' })
|
||||
]
|
||||
});
|
||||
logger.debug("Will not be logged in either transport!");
|
||||
logger.transports.console.level = 'debug';
|
||||
logger.transports.file.level = 'verbose';
|
||||
logger.verbose("Will be logged in both transports!");
|
||||
```
|
||||
|
||||
As of 0.2.0, winston supports customizable logging levels, defaulting to [npm][0] style logging levels. Changing logging levels is easy:
|
||||
|
||||
``` js
|
||||
//
|
||||
// Change levels on the default winston logger
|
||||
//
|
||||
winston.setLevels(winston.config.syslog.levels);
|
||||
|
||||
//
|
||||
// Change levels on an instance of a logger
|
||||
//
|
||||
logger.setLevels(winston.config.syslog.levels);
|
||||
```
|
||||
|
||||
Calling `.setLevels` on a logger will remove all of the previous helper methods for the old levels and define helper methods for the new levels. Thus, you should be careful about the logging statements you use when changing levels. For example, if you ran this code after changing to the syslog levels:
|
||||
|
||||
``` js
|
||||
//
|
||||
// Logger does not have 'silly' defined since that level is not in the syslog levels
|
||||
//
|
||||
logger.silly('some silly message');
|
||||
```
|
||||
|
||||
### Using Custom Logging Levels
|
||||
In addition to the predefined `npm` and `syslog` levels available in Winston, you can also choose to define your own:
|
||||
|
||||
``` js
|
||||
var myCustomLevels = {
|
||||
levels: {
|
||||
foo: 0,
|
||||
bar: 1,
|
||||
baz: 2,
|
||||
foobar: 3
|
||||
},
|
||||
colors: {
|
||||
foo: 'blue',
|
||||
bar: 'green',
|
||||
baz: 'yellow',
|
||||
foobar: 'red'
|
||||
}
|
||||
};
|
||||
|
||||
var customLevelLogger = new (winston.Logger)({ levels: myCustomLevels.levels });
|
||||
customLevelLogger.foobar('some foobar level-ed message');
|
||||
```
|
||||
|
||||
Although there is slight repetition in this data structure, it enables simple encapsulation if you not to have colors. If you do wish to have colors, in addition to passing the levels to the Logger itself, you must make winston aware of them:
|
||||
|
||||
``` js
|
||||
//
|
||||
// Make winston aware of these colors
|
||||
//
|
||||
winston.addColors(myCustomLevels.colors);
|
||||
```
|
||||
|
||||
This enables transports with the 'colorize' option set to appropriately color the output of custom levels.
|
||||
|
||||
## Further Reading
|
||||
|
||||
### Events and Callbacks in Winston
|
||||
Each instance of winston.Logger is also an instance of an [EventEmitter][1]. A log event will be raised each time a transport successfully logs a message:
|
||||
|
||||
``` js
|
||||
logger.on('logging', function (transport, level, msg, meta) {
|
||||
// [msg] and [meta] have now been logged at [level] to [transport]
|
||||
});
|
||||
|
||||
logger.info('CHILL WINSTON!', { seriously: true });
|
||||
```
|
||||
|
||||
It is also worth mentioning that the logger also emits an 'error' event which you should handle or suppress if you don't want unhandled exceptions:
|
||||
|
||||
``` js
|
||||
//
|
||||
// Handle errors
|
||||
//
|
||||
logger.on('error', function (err) { /* Do Something */ });
|
||||
|
||||
//
|
||||
// Or just suppress them.
|
||||
//
|
||||
logger.emitErrs = false;
|
||||
```
|
||||
|
||||
Every logging method described in the previous section also takes an optional callback which will be called only when all of the transports have logged the specified message.
|
||||
|
||||
``` js
|
||||
logger.info('CHILL WINSTON!', { seriously: true }, function (err, level, msg, meta) {
|
||||
// [msg] and [meta] have now been logged at [level] to **every** transport.
|
||||
});
|
||||
```
|
||||
|
||||
### Working with multiple Loggers in winston
|
||||
|
||||
Often in larger, more complex applications it is necessary to have multiple logger instances with different settings. Each logger is responsible for a different feature area (or category). This is exposed in `winston` in two ways: through `winston.loggers` and instances of `winston.Container`. In fact, `winston.loggers` is just a predefined instance of `winston.Container`:
|
||||
|
||||
``` js
|
||||
var winston = require('winston');
|
||||
|
||||
//
|
||||
// Configure the logger for `category1`
|
||||
//
|
||||
winston.loggers.add('category1', {
|
||||
console: {
|
||||
level: 'silly',
|
||||
colorize: 'true',
|
||||
label: 'category one'
|
||||
},
|
||||
file: {
|
||||
filename: '/path/to/some/file'
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
// Configure the logger for `category2`
|
||||
//
|
||||
winston.loggers.add('category2', {
|
||||
couchdb: {
|
||||
host: '127.0.0.1',
|
||||
port: 5984
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Now that your loggers are setup you can require winston _in any file in your application_ and access these pre-configured loggers:
|
||||
|
||||
``` js
|
||||
var winston = require('winston');
|
||||
|
||||
//
|
||||
// Grab your preconfigured logger
|
||||
//
|
||||
var category1 = winston.loggers.get('category1');
|
||||
|
||||
category1.info('logging from your IoC container-based logger');
|
||||
```
|
||||
|
||||
If you prefer to manage the `Container` yourself you can simply instantiate one:
|
||||
|
||||
``` js
|
||||
var winston = require('winston'),
|
||||
container = new winston.Container();
|
||||
|
||||
container.add('category1', {
|
||||
console: {
|
||||
level: 'silly',
|
||||
colorize: 'true'
|
||||
},
|
||||
file: {
|
||||
filename: '/path/to/some/file'
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Sharing transports between Loggers in winston
|
||||
|
||||
``` js
|
||||
var winston = require('winston');
|
||||
|
||||
//
|
||||
// Setup transports to be shared across all loggers
|
||||
// in three ways:
|
||||
//
|
||||
// 1. By setting it on the default Container
|
||||
// 2. By passing `transports` into the constructor function of winston.Container
|
||||
// 3. By passing `transports` into the `.get()` or `.add()` methods
|
||||
//
|
||||
|
||||
//
|
||||
// 1. By setting it on the default Container
|
||||
//
|
||||
winston.loggers.options.transports = [
|
||||
// Setup your shared transports here
|
||||
];
|
||||
|
||||
//
|
||||
// 2. By passing `transports` into the constructor function of winston.Container
|
||||
//
|
||||
var container = new winston.Container({
|
||||
transports: [
|
||||
// Setup your shared transports here
|
||||
]
|
||||
});
|
||||
|
||||
//
|
||||
// 3. By passing `transports` into the `.get()` or `.add()` methods
|
||||
//
|
||||
winston.loggers.add('some-category', {
|
||||
transports: [
|
||||
// Setup your shared transports here
|
||||
]
|
||||
});
|
||||
|
||||
container.add('some-category', {
|
||||
transports: [
|
||||
// Setup your shared transports here
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
### Using winston in a CLI tool
|
||||
A common use-case for logging is output to a CLI tool. Winston has a special helper method which will pretty print output from your CLI tool. Here's an example from the [require-analyzer][2] written by [Nodejitsu][3]:
|
||||
|
||||
```
|
||||
info: require-analyzer starting in /Users/Charlie/Nodejitsu/require-analyzer
|
||||
info: Found existing dependencies
|
||||
data: {
|
||||
data: colors: '0.x.x',
|
||||
data: eyes: '0.1.x',
|
||||
data: findit: '0.0.x',
|
||||
data: npm: '1.0.x',
|
||||
data: optimist: '0.2.x',
|
||||
data: semver: '1.0.x',
|
||||
data: winston: '0.2.x'
|
||||
data: }
|
||||
info: Analyzing dependencies...
|
||||
info: Done analyzing raw dependencies
|
||||
info: Retrieved packages from npm
|
||||
warn: No additional dependencies found
|
||||
```
|
||||
|
||||
Configuring output for this style is easy, just use the `.cli()` method on `winston` or an instance of `winston.Logger`:
|
||||
|
||||
``` js
|
||||
var winston = require('winston');
|
||||
|
||||
//
|
||||
// Configure CLI output on the default logger
|
||||
//
|
||||
winston.cli();
|
||||
|
||||
//
|
||||
// Configure CLI on an instance of winston.Logger
|
||||
//
|
||||
var logger = new winston.Logger({
|
||||
transports: [
|
||||
new (winston.transports.Console)()
|
||||
]
|
||||
});
|
||||
|
||||
logger.cli();
|
||||
```
|
||||
|
||||
### Extending another object with Logging
|
||||
Often in a given code base with lots of Loggers it is useful to add logging methods to a different object so that these methods can be called with less syntax. Winston exposes this functionality via the 'extend' method:
|
||||
|
||||
``` js
|
||||
var myObject = {};
|
||||
|
||||
logger.extend(myObject);
|
||||
|
||||
//
|
||||
// You can now call logger methods on 'myObject'
|
||||
//
|
||||
myObject.info("127.0.0.1 - there's no place like home");
|
||||
```
|
||||
|
||||
## Working with Transports
|
||||
There are many transports supported by winston core. If you have a transport you would like to add either open an issue or fork and submit a pull request. Commits are welcome, but I'll give you extra street cred if you __add tests too :D__
|
||||
|
||||
|
||||
### Console Transport
|
||||
``` js
|
||||
winston.add(winston.transports.Console, options)
|
||||
```
|
||||
|
||||
The Console transport takes a few simple options:
|
||||
|
||||
* __level:__ Level of messages that this transport should log (default 'info').
|
||||
* __silent:__ Boolean flag indicating whether to suppress output (default false).
|
||||
* __colorize:__ Boolean flag indicating if we should colorize output (default false).
|
||||
* __timestamp:__ Boolean flag indicating if we should prepend output with timestamps (default false). If function is specified, its return value will be used instead of timestamps.
|
||||
|
||||
*Metadata:* Logged via util.inspect(meta);
|
||||
|
||||
### File Transport
|
||||
``` js
|
||||
winston.add(winston.transports.File, options)
|
||||
```
|
||||
|
||||
The File transport should really be the 'Stream' transport since it will accept any [WritableStream][14]. It is named such because it will also accept filenames via the 'filename' option:
|
||||
|
||||
* __level:__ Level of messages that this transport should log.
|
||||
* __silent:__ Boolean flag indicating whether to suppress output.
|
||||
* __colorize:__ Boolean flag indicating if we should colorize output.
|
||||
* __timestamp:__ Boolean flag indicating if we should prepend output with timestamps (default true). If function is specified, its return value will be used instead of timestamps.
|
||||
* __filename:__ The filename of the logfile to write output to.
|
||||
* __maxsize:__ Max size in bytes of the logfile, if the size is exceeded then a new file is created.
|
||||
* __maxFiles:__ Limit the number of files created when the size of the logfile is exceeded.
|
||||
* __stream:__ The WriteableStream to write output to.
|
||||
* __json:__ If true, messages will be logged as JSON (default true).
|
||||
* __logstash:__ If true, messages will be logged using the logstash JSON format.
|
||||
|
||||
*Metadata:* Logged via util.inspect(meta);
|
||||
|
||||
### Loggly Transport
|
||||
``` js
|
||||
var Loggly = require('winston-loggly').Loggly
|
||||
winston.add(Loggly, options);
|
||||
```
|
||||
|
||||
The Loggly transport is based on [Nodejitsu's][3] [node-loggly][6] implementation of the [Loggly][7] API. If you haven't heard of Loggly before, you should probably read their [value proposition][8]. The Loggly transport takes the following options. Either 'inputToken' or 'inputName' is required:
|
||||
|
||||
* __level:__ Level of messages that this transport should log.
|
||||
* __subdomain:__ The subdomain of your Loggly account. *[required]*
|
||||
* __auth__: The authentication information for your Loggly account. *[required with inputName]*
|
||||
* __inputName:__ The name of the input this instance should log to.
|
||||
* __inputToken:__ The input token of the input this instance should log to.
|
||||
* __json:__ If true, messages will be sent to Loggly as JSON.
|
||||
|
||||
*Metadata:* Logged in suggested [Loggly format][2]
|
||||
|
||||
### Riak Transport
|
||||
As of `0.3.0` the Riak transport has been broken out into a new module: [winston-riak][17]. Using it is just as easy:
|
||||
|
||||
``` js
|
||||
var Riak = require('winston-riak').Riak;
|
||||
winston.add(Riak, options);
|
||||
```
|
||||
|
||||
In addition to the options accepted by the [riak-js][3] [client][4], the Riak transport also accepts the following options. It is worth noting that the riak-js debug option is set to *false* by default:
|
||||
|
||||
* __level:__ Level of messages that this transport should log.
|
||||
* __bucket:__ The name of the Riak bucket you wish your logs to be in or a function to generate bucket names dynamically.
|
||||
|
||||
``` js
|
||||
// Use a single bucket for all your logs
|
||||
var singleBucketTransport = new (Riak)({ bucket: 'some-logs-go-here' });
|
||||
|
||||
// Generate a dynamic bucket based on the date and level
|
||||
var dynamicBucketTransport = new (Riak)({
|
||||
bucket: function (level, msg, meta, now) {
|
||||
var d = new Date(now);
|
||||
return level + [d.getDate(), d.getMonth(), d.getFullYear()].join('-');
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
*Metadata:* Logged as JSON literal in Riak
|
||||
|
||||
### MongoDB Transport
|
||||
As of `0.3.0` the MongoDB transport has been broken out into a new module: [winston-mongodb][16]. Using it is just as easy:
|
||||
|
||||
``` js
|
||||
var MongoDB = require('winston-mongodb').MongoDB;
|
||||
winston.add(MongoDB, options);
|
||||
```
|
||||
|
||||
The MongoDB transport takes the following options. 'db' is required:
|
||||
|
||||
* __level:__ Level of messages that this transport should log.
|
||||
* __silent:__ Boolean flag indicating whether to suppress output.
|
||||
* __db:__ The name of the database you want to log to. *[required]*
|
||||
* __collection__: The name of the collection you want to store log messages in, defaults to 'log'.
|
||||
* __safe:__ Boolean indicating if you want eventual consistency on your log messages, if set to true it requires an extra round trip to the server to ensure the write was committed, defaults to true.
|
||||
* __host:__ The host running MongoDB, defaults to localhost.
|
||||
* __port:__ The port on the host that MongoDB is running on, defaults to MongoDB's default port.
|
||||
|
||||
*Metadata:* Logged as a native JSON object.
|
||||
|
||||
### SimpleDB Transport
|
||||
|
||||
The [winston-simpledb][18] transport is just as easy:
|
||||
|
||||
``` js
|
||||
var SimpleDB = require('winston-simpledb').SimpleDB;
|
||||
winston.add(SimpleDB, options);
|
||||
```
|
||||
|
||||
The SimpleDB transport takes the following options. All items marked with an asterisk are required:
|
||||
|
||||
* __awsAccessKey__:* your AWS Access Key
|
||||
* __secretAccessKey__:* your AWS Secret Access Key
|
||||
* __awsAccountId__:* your AWS Account Id
|
||||
* __domainName__:* a string or function that returns the domain name to log to
|
||||
* __region__:* the region your domain resides in
|
||||
* __itemName__: a string ('uuid', 'epoch', 'timestamp') or function that returns the item name to log
|
||||
|
||||
*Metadata:* Logged as a native JSON object to the 'meta' attribute of the item.
|
||||
|
||||
### Mail Transport
|
||||
|
||||
The [winston-mail][19] is an email transport:
|
||||
|
||||
``` js
|
||||
var Mail = require('winston-mail').Mail;
|
||||
winston.add(Mail, options);
|
||||
```
|
||||
|
||||
The Mail transport uses [emailjs](https://github.com/eleith/emailjs) behind the scenes. Options are the following:
|
||||
|
||||
* __to:__ The address(es) you want to send to. *[required]*
|
||||
* __from:__ The address you want to send from. (default: `winston@[server-host-name]`)
|
||||
* __host:__ SMTP server hostname (default: localhost)
|
||||
* __port:__ SMTP port (default: 587 or 25)
|
||||
* __username__ User for server auth
|
||||
* __password__ Password for server auth
|
||||
* __ssl:__ Use SSL (boolean or object { key, ca, cert })
|
||||
* __tls:__ Boolean (if true, use starttls)
|
||||
* __level:__ Level of messages that this transport should log.
|
||||
* __silent:__ Boolean flag indicating whether to suppress output.
|
||||
|
||||
*Metadata:* Stringified as JSON in email.
|
||||
|
||||
### Amazon SNS (Simple Notification System) Transport
|
||||
|
||||
The [winston-sns][21] transport uses amazon SNS to send emails, texts, or a bunch of other notifications.
|
||||
|
||||
``` js
|
||||
require('winston-sns').SNS;
|
||||
winston.add(winston.transports.SNS, options);
|
||||
```
|
||||
|
||||
Options:
|
||||
|
||||
* __aws_key:__ Your Amazon Web Services Key. *[required]*
|
||||
* __aws_secret:__ Your Amazon Web Services Secret. *[required]*
|
||||
* __subscriber:__ Subscriber number - found in your SNS AWS Console, after clicking on a topic. Same as AWS Account ID. *[required]*
|
||||
* __topic_arn:__ Also found in SNS AWS Console - listed under a topic as Topic ARN. *[required]*
|
||||
* __region:__ AWS Region to use. Can be one of: `us-east-1`,`us-west-1`,`eu-west-1`,`ap-southeast-1`,`ap-northeast-1`,`us-gov-west-1`,`sa-east-1`. (default: `us-east-1`)
|
||||
* __subject:__ Subject for notifications. (default: "Winston Error Report")
|
||||
* __message:__ Message of notifications. Uses placeholders for level (%l), error message (%e), and metadata (%m). (default: "Level '%l' Error:\n%e\n\nMetadata:\n%m")
|
||||
* __level:__ lowest level this transport will log. (default: `info`)
|
||||
|
||||
### Graylog2 Transport
|
||||
|
||||
[winston-graylog2][22] is a Graylog2 transport:
|
||||
|
||||
``` js
|
||||
var Graylog2 = require('winston-graylog2').Graylog2;
|
||||
winston.add(Graylog2, options);
|
||||
```
|
||||
|
||||
The Graylog2 transport connects to a Graylog2 server over UDP using the following options:
|
||||
|
||||
* __level:__ Level of messages this transport should log. (default: info)
|
||||
* __silent:__ Boolean flag indicating whether to suppress output. (default: false)
|
||||
|
||||
* __graylogHost:__ IP address or hostname of the graylog2 server. (default: localhost)
|
||||
* __graylogPort:__ Port to send messages to on the graylog2 server. (default: 12201)
|
||||
* __graylogHostname:__ The hostname associated with graylog2 messages. (default: require('os').hostname())
|
||||
* __graylogFacility:__ The graylog2 facility to send log messages.. (default: nodejs)
|
||||
|
||||
*Metadata:* Stringified as JSON in the full message GELF field.
|
||||
|
||||
### Papertrail Transport
|
||||
|
||||
[winston-papertrail][23] is a Papertrail transport:
|
||||
|
||||
``` js
|
||||
var Papertrail = require('winston-papertrail').Papertrail;
|
||||
winston.add(Papertrail, options);
|
||||
```
|
||||
|
||||
The Papertrail transport connects to a [PapertrailApp log destination](https://papertrailapp.com) over TCP (TLS) using the following options:
|
||||
|
||||
* __level:__ Level of messages this transport should log. (default: info)
|
||||
* __host:__ FQDN or IP address of the Papertrail endpoint.
|
||||
* __port:__ Port for the Papertrail log destination.
|
||||
* __hostname:__ The hostname associated with messages. (default: require('os').hostname())
|
||||
* __program:__ The facility to send log messages.. (default: default)
|
||||
* __logFormat:__ a log formatting function with the signature `function(level, message)`, which allows custom formatting of the level or message prior to delivery
|
||||
|
||||
*Metadata:* Logged as a native JSON object to the 'meta' attribute of the item.
|
||||
|
||||
### Cassandra Transport
|
||||
|
||||
[winston-cassandra][24] is a Cassandra transport:
|
||||
|
||||
``` js
|
||||
var Cassandra = require('winston-cassandra').Cassandra;
|
||||
winston.add(Cassandra, options);
|
||||
```
|
||||
|
||||
The Cassandra transport connects to a cluster using the native protocol with the following options:
|
||||
|
||||
* __level:__ Level of messages that this transport should log (default: `'info'`).
|
||||
* __table:__ The name of the Cassandra column family you want to store log messages in (default: `'logs'`).
|
||||
* __partitionBy:__ How you want the logs to be partitioned. Possible values `'hour'` and `'day'`(Default).
|
||||
* __consistency:__ The consistency of the insert query (default: `quorum`).
|
||||
|
||||
In addition to the options accepted by the [Node.js Cassandra driver](https://github.com/jorgebay/node-cassandra-cql) Client.
|
||||
|
||||
* __hosts:__ Cluster nodes that will handle the write requests:
|
||||
Array of strings containing the hosts, for example `['host1', 'host2']` (required).
|
||||
* __keyspace:__ The name of the keyspace that will contain the logs table (required). The keyspace should be already created in the cluster.
|
||||
|
||||
### Adding Custom Transports
|
||||
Adding a custom transport (say for one of the datastore on the Roadmap) is actually pretty easy. All you need to do is accept a couple of options, set a name, implement a log() method, and add it to the set of transports exposed by winston.
|
||||
|
||||
``` js
|
||||
var util = require('util'),
|
||||
winston = require('winston');
|
||||
|
||||
var CustomLogger = winston.transports.CustomerLogger = function (options) {
|
||||
//
|
||||
// Name this logger
|
||||
//
|
||||
this.name = 'customLogger';
|
||||
|
||||
//
|
||||
// Set the level from your options
|
||||
//
|
||||
this.level = options.level || 'info';
|
||||
|
||||
//
|
||||
// Configure your storage backing as you see fit
|
||||
//
|
||||
};
|
||||
|
||||
//
|
||||
// Inherit from `winston.Transport` so you can take advantage
|
||||
// of the base functionality and `.handleExceptions()`.
|
||||
//
|
||||
util.inherits(CustomLogger, winston.Transport);
|
||||
|
||||
CustomLogger.prototype.log = function (level, msg, meta, callback) {
|
||||
//
|
||||
// Store this message and metadata, maybe use some custom logic
|
||||
// then callback indicating success.
|
||||
//
|
||||
callback(null, true);
|
||||
};
|
||||
```
|
||||
|
||||
### Inspirations
|
||||
1. [npm][0]
|
||||
2. [log.js][4]
|
||||
3. [socket.io][5]
|
||||
4. [node-rlog][6]
|
||||
5. [BigBrother][7]
|
||||
6. [Loggly][8]
|
||||
|
||||
## Installation
|
||||
|
||||
### Installing npm (node package manager)
|
||||
```
|
||||
curl http://npmjs.org/install.sh | sh
|
||||
```
|
||||
|
||||
### Installing winston
|
||||
```
|
||||
[sudo] npm install winston
|
||||
```
|
||||
|
||||
## Run Tests
|
||||
All of the winston tests are written in [vows][9], and designed to be run with npm.
|
||||
|
||||
``` bash
|
||||
$ npm test
|
||||
```
|
||||
|
||||
#### Author: [Charlie Robbins](http://twitter.com/indexzero)
|
||||
#### Contributors: [Matthew Bergman](http://github.com/fotoverite), [Marak Squires](http://github.com/marak)
|
||||
|
||||
[0]: https://github.com/npm/npmlog/blob/master/log.js
|
||||
[1]: http://nodejs.org/docs/v0.3.5/api/events.html#events.EventEmitter
|
||||
[2]: http://github.com/nodejitsu/require-analyzer
|
||||
[3]: http://nodejitsu.com
|
||||
[4]: https://github.com/visionmedia/log.js
|
||||
[5]: http://socket.io
|
||||
[6]: https://github.com/jbrisbin/node-rlog
|
||||
[7]: https://github.com/feisty/BigBrother
|
||||
[8]: http://loggly.com
|
||||
[9]: http://vowsjs.org
|
||||
[10]: http://nodejs.org/api/util.html#util_util_format_format
|
||||
[14]: http://nodejs.org/api/stream.html#stream_class_stream_writable
|
||||
[16]: https://github.com/indexzero/winston-mongodb
|
||||
[17]: https://github.com/indexzero/winston-riak
|
||||
[18]: https://github.com/appsattic/winston-simpledb
|
||||
[19]: https://github.com/wavded/winston-mail
|
||||
[21]: https://github.com/jesseditson/winston-sns
|
||||
[22]: https://github.com/flite/winston-graylog2
|
||||
[23]: https://github.com/kenperkins/winston-papertrail
|
||||
[24]: https://github.com/jorgebay/winston-cassandra
|
||||
369
node_modules/winston/docs/transports.md
generated
vendored
Normal file
369
node_modules/winston/docs/transports.md
generated
vendored
Normal file
@@ -0,0 +1,369 @@
|
||||
# Winston Transports
|
||||
|
||||
In `winston` a transport is essentially a storage device for your logs. Each instance of a winston logger can have multiple transports configured at different levels. For example, one may want error logs to be stored in a persistent remote location (like a database), but all logs output to the console or a local file.
|
||||
|
||||
There are several [core transports](#winston-core) included in `winston`, which leverage the built-in networking and file I/O offered by node.js core. In addition, there are [third-party transports which are supported by the winston core team](#winston-more). And last (but not least) there are [additional transports written by members of the community](#additional-transports).
|
||||
|
||||
* **[Winston Core](#winston-core)**
|
||||
* [Console](#console-transport)
|
||||
* [File](#file-transport)
|
||||
* [Http](#http-transport)
|
||||
* [Webhook](#webhook-transport)
|
||||
|
||||
* **[Winston More](#winston-more)**
|
||||
* [CouchDB](#couchdb-transport)
|
||||
* [Loggly](#loggly-transport)
|
||||
* [MongoDB](#mongodb-transport)
|
||||
* [Redis](#redis-transport)
|
||||
* [Riak](#riak-transport)
|
||||
|
||||
* **[Additional Transports](#additional-transports)**
|
||||
* [SimpleDB](#simpledb-transport)
|
||||
* [Mail](#mail-transport)
|
||||
* [Amazon SNS](#amazon-sns-simple-notification-system-transport)
|
||||
* [Graylog2](#graylog2-transport)
|
||||
|
||||
## Winston Core
|
||||
|
||||
There are several core transports included in `winston`, which leverage the built-in networking and file I/O offered by node.js core.
|
||||
|
||||
* [Console](#console-transport)
|
||||
* [File](#file-transport)
|
||||
* [Http](#http-transport)
|
||||
* [Webhook](#webhook-transport)
|
||||
|
||||
### Console Transport
|
||||
|
||||
``` js
|
||||
winston.add(winston.transports.Console, options)
|
||||
```
|
||||
|
||||
The Console transport takes two simple options:
|
||||
|
||||
* __level:__ Level of messages that this transport should log (default 'debug').
|
||||
* __silent:__ Boolean flag indicating whether to suppress output (default false).
|
||||
* __colorize:__ Boolean flag indicating if we should colorize output (default false).
|
||||
* __timestamp:__ Boolean flag indicating if we should prepend output with timestamps (default false). If function is specified, its return value will be used instead of timestamps.
|
||||
|
||||
*Metadata:* Logged via util.inspect(meta);
|
||||
|
||||
### File Transport
|
||||
|
||||
``` js
|
||||
winston.add(winston.transports.File, options)
|
||||
```
|
||||
|
||||
The File transport should really be the 'Stream' transport since it will accept any [WritableStream][0]. It is named such because it will also accept filenames via the 'filename' option:
|
||||
|
||||
* __level:__ Level of messages that this transport should log.
|
||||
* __silent:__ Boolean flag indicating whether to suppress output.
|
||||
* __colorize:__ Boolean flag indicating if we should colorize output.
|
||||
* __timestamp:__ Boolean flag indicating if we should prepend output with timestamps (default false). If function is specified, its return value will be used instead of timestamps.
|
||||
* __filename:__ The filename of the logfile to write output to.
|
||||
* __maxsize:__ Max size in bytes of the logfile, if the size is exceeded then a new file is created.
|
||||
* __maxFiles:__ Limit the number of files created when the size of the logfile is exceeded.
|
||||
* __stream:__ The WriteableStream to write output to.
|
||||
* __json:__ If true, messages will be logged as JSON (default true).
|
||||
|
||||
*Metadata:* Logged via util.inspect(meta);
|
||||
|
||||
### Http Transport
|
||||
|
||||
``` js
|
||||
winston.add(winston.transports.Http, options)
|
||||
```
|
||||
|
||||
The `Http` transport is a generic way to log, query, and stream logs from an arbitrary Http endpoint, preferably [winstond][1]. It takes options that are passed to the node.js `http` or `https` request:
|
||||
|
||||
* __host:__ (Default: **localhost**) Remote host of the HTTP logging endpoint
|
||||
* __port:__ (Default: **80 or 443**) Remote port of the HTTP logging endpoint
|
||||
* __path:__ (Default: **/**) Remote URI of the HTTP logging endpoint
|
||||
* __auth:__ (Default: **None**) An object representing the `username` and `password` for HTTP Basic Auth
|
||||
* __ssl:__ (Default: **false**) Value indicating if we should us HTTPS
|
||||
|
||||
## Winston More
|
||||
|
||||
Starting with `winston@0.3.0` an effort was made to remove any transport which added additional dependencies to `winston`. At the time there were several transports already in `winston` which will **always be supported by the winston core team.**
|
||||
|
||||
* [CouchDB](#couchdb-transport)
|
||||
* [Redis](#redis-transport)
|
||||
* [MongoDB](#mongodb-transport)
|
||||
* [Riak](#riak-transport)
|
||||
* [Loggly](#loggly-transport)
|
||||
|
||||
### CouchDB Transport
|
||||
|
||||
_As of `winston@0.6.0` the CouchDB transport has been broken out into a new module: [winston-couchdb][2]._
|
||||
|
||||
``` js
|
||||
winston.add(winston.transports.Couchdb, options)
|
||||
```
|
||||
|
||||
The `Couchdb` will place your logs in a remote CouchDB database. It will also create a [Design Document][3], `_design/Logs` for later querying and streaming your logs from CouchDB. The transport takes the following options:
|
||||
|
||||
* __host:__ (Default: **localhost**) Remote host of the HTTP logging endpoint
|
||||
* __port:__ (Default: **5984**) Remote port of the HTTP logging endpoint
|
||||
* __db:__ (Default: **winston**) Remote URI of the HTTP logging endpoint
|
||||
* __auth:__ (Default: **None**) An object representing the `username` and `password` for HTTP Basic Auth
|
||||
* __ssl:__ (Default: **false**) Value indicating if we should us HTTPS
|
||||
|
||||
### Redis Transport
|
||||
|
||||
``` js
|
||||
winston.add(winston.transports.Redis, options)
|
||||
```
|
||||
|
||||
This transport accepts the options accepted by the [node-redis][4] client:
|
||||
|
||||
* __host:__ (Default **localhost**) Remote host of the Redis server
|
||||
* __port:__ (Default **6379**) Port the Redis server is running on.
|
||||
* __auth:__ (Default **None**) Password set on the Redis server
|
||||
|
||||
In addition to these, the Redis transport also accepts the following options.
|
||||
|
||||
* __length:__ (Default **200**) Number of log messages to store.
|
||||
* __container:__ (Default **winston**) Name of the Redis container you wish your logs to be in.
|
||||
* __channel:__ (Default **None**) Name of the Redis channel to stream logs from.
|
||||
|
||||
*Metadata:* Logged as JSON literal in Redis
|
||||
|
||||
### Loggly Transport
|
||||
|
||||
_As of `winston@0.6.0` the Loggly transport has been broken out into a new module: [winston-loggly][5]._
|
||||
|
||||
``` js
|
||||
winston.add(winston.transports.Loggly, options);
|
||||
```
|
||||
|
||||
The Loggly transport is based on [Nodejitsu's][6] [node-loggly][7] implementation of the [Loggly][8] API. If you haven't heard of Loggly before, you should probably read their [value proposition][9]. The Loggly transport takes the following options. Either 'inputToken' or 'inputName' is required:
|
||||
|
||||
* __level:__ Level of messages that this transport should log.
|
||||
* __subdomain:__ The subdomain of your Loggly account. *[required]*
|
||||
* __auth__: The authentication information for your Loggly account. *[required with inputName]*
|
||||
* __inputName:__ The name of the input this instance should log to.
|
||||
* __inputToken:__ The input token of the input this instance should log to.
|
||||
* __json:__ If true, messages will be sent to Loggly as JSON.
|
||||
|
||||
*Metadata:* Logged in suggested [Loggly format][10]
|
||||
|
||||
### Riak Transport
|
||||
|
||||
_As of `winston@0.3.0` the Riak transport has been broken out into a new module: [winston-riak][11]._ Using it is just as easy:
|
||||
|
||||
``` js
|
||||
var Riak = require('winston-riak').Riak;
|
||||
winston.add(Riak, options);
|
||||
```
|
||||
|
||||
In addition to the options accepted by the [riak-js][12] [client][13], the Riak transport also accepts the following options. It is worth noting that the riak-js debug option is set to *false* by default:
|
||||
|
||||
* __level:__ Level of messages that this transport should log.
|
||||
* __bucket:__ The name of the Riak bucket you wish your logs to be in or a function to generate bucket names dynamically.
|
||||
|
||||
``` js
|
||||
// Use a single bucket for all your logs
|
||||
var singleBucketTransport = new (Riak)({ bucket: 'some-logs-go-here' });
|
||||
|
||||
// Generate a dynamic bucket based on the date and level
|
||||
var dynamicBucketTransport = new (Riak)({
|
||||
bucket: function (level, msg, meta, now) {
|
||||
var d = new Date(now);
|
||||
return level + [d.getDate(), d.getMonth(), d.getFullYear()].join('-');
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
*Metadata:* Logged as JSON literal in Riak
|
||||
|
||||
### MongoDB Transport
|
||||
|
||||
As of `winston@0.3.0` the MongoDB transport has been broken out into a new module: [winston-mongodb][14]. Using it is just as easy:
|
||||
|
||||
``` js
|
||||
var MongoDB = require('winston-mongodb').MongoDB;
|
||||
winston.add(MongoDB, options);
|
||||
```
|
||||
|
||||
The MongoDB transport takes the following options. 'db' is required:
|
||||
|
||||
* __level:__ Level of messages that this transport should log.
|
||||
* __silent:__ Boolean flag indicating whether to suppress output.
|
||||
* __db:__ The name of the database you want to log to. *[required]*
|
||||
* __collection__: The name of the collection you want to store log messages in, defaults to 'log'.
|
||||
* __safe:__ Boolean indicating if you want eventual consistency on your log messages, if set to true it requires an extra round trip to the server to ensure the write was committed, defaults to true.
|
||||
* __host:__ The host running MongoDB, defaults to localhost.
|
||||
* __port:__ The port on the host that MongoDB is running on, defaults to MongoDB's default port.
|
||||
|
||||
*Metadata:* Logged as a native JSON object.
|
||||
|
||||
## Additional Transports
|
||||
|
||||
The community has truly embraced `winston`; there are over **23** winston transports and over half of them are maintained by authors external to the winston core team. If you want to check them all out, just search `npm`:
|
||||
|
||||
``` bash
|
||||
$ npm search winston
|
||||
```
|
||||
|
||||
**If you have an issue using one of these modules you should contact the module author directly**
|
||||
|
||||
### SimpleDB Transport
|
||||
|
||||
The [winston-simpledb][15] transport is just as easy:
|
||||
|
||||
``` js
|
||||
var SimpleDB = require('winston-simpledb').SimpleDB;
|
||||
winston.add(SimpleDB, options);
|
||||
```
|
||||
|
||||
The SimpleDB transport takes the following options. All items marked with an asterisk are required:
|
||||
|
||||
* __awsAccessKey__:* your AWS Access Key
|
||||
* __secretAccessKey__:* your AWS Secret Access Key
|
||||
* __awsAccountId__:* your AWS Account Id
|
||||
* __domainName__:* a string or function that returns the domain name to log to
|
||||
* __region__:* the region your domain resides in
|
||||
* __itemName__: a string ('uuid', 'epoch', 'timestamp') or function that returns the item name to log
|
||||
|
||||
*Metadata:* Logged as a native JSON object to the 'meta' attribute of the item.
|
||||
|
||||
### Mail Transport
|
||||
|
||||
The [winston-mail][16] is an email transport:
|
||||
|
||||
``` js
|
||||
var Mail = require('winston-mail').Mail;
|
||||
winston.add(Mail, options);
|
||||
```
|
||||
|
||||
The Mail transport uses [node-mail][17] behind the scenes. Options are the following, `to` and `host` are required:
|
||||
|
||||
* __to:__ The address(es) you want to send to. *[required]*
|
||||
* __from:__ The address you want to send from. (default: `winston@[server-host-name]`)
|
||||
* __host:__ SMTP server hostname
|
||||
* __port:__ SMTP port (default: 587 or 25)
|
||||
* __secure:__ Use secure
|
||||
* __username__ User for server auth
|
||||
* __password__ Password for server auth
|
||||
* __level:__ Level of messages that this transport should log.
|
||||
* __silent:__ Boolean flag indicating whether to suppress output.
|
||||
|
||||
*Metadata:* Stringified as JSON in email.
|
||||
|
||||
### Amazon SNS (Simple Notification System) Transport
|
||||
|
||||
The [winston-sns][18] transport uses amazon SNS to send emails, texts, or a bunch of other notifications.
|
||||
|
||||
``` js
|
||||
require('winston-sns').SNS;
|
||||
winston.add(winston.transports.SNS, options);
|
||||
```
|
||||
|
||||
Options:
|
||||
|
||||
* __aws_key:__ Your Amazon Web Services Key. *[required]*
|
||||
* __aws_secret:__ Your Amazon Web Services Secret. *[required]*
|
||||
* __subscriber:__ Subscriber number - found in your SNS AWS Console, after clicking on a topic. Same as AWS Account ID. *[required]*
|
||||
* __topic_arn:__ Also found in SNS AWS Console - listed under a topic as Topic ARN. *[required]*
|
||||
* __region:__ AWS Region to use. Can be one of: `us-east-1`,`us-west-1`,`eu-west-1`,`ap-southeast-1`,`ap-northeast-1`,`us-gov-west-1`,`sa-east-1`. (default: `us-east-1`)
|
||||
* __subject:__ Subject for notifications. (default: "Winston Error Report")
|
||||
* __message:__ Message of notifications. Uses placeholders for level (%l), error message (%e), and metadata (%m). (default: "Level '%l' Error:\n%e\n\nMetadata:\n%m")
|
||||
* __level:__ lowest level this transport will log. (default: `info`)
|
||||
|
||||
### Graylog2 Transport
|
||||
|
||||
[winston-graylog2][19] is a Graylog2 transport:
|
||||
|
||||
``` js
|
||||
var Graylog2 = require('winston-graylog2').Graylog2;
|
||||
winston.add(Graylog2, options);
|
||||
```
|
||||
|
||||
The Graylog2 transport connects to a Graylog2 server over UDP using the following options:
|
||||
|
||||
* __level:__ Level of messages this transport should log. (default: info)
|
||||
* __silent:__ Boolean flag indicating whether to suppress output. (default: false)
|
||||
|
||||
* __graylogHost:__ IP address or hostname of the graylog2 server. (default: localhost)
|
||||
* __graylogPort:__ Port to send messages to on the graylog2 server. (default: 12201)
|
||||
* __graylogHostname:__ The hostname associated with graylog2 messages. (default: require('os').hostname())
|
||||
* __graylogFacility:__ The graylog2 facility to send log messages.. (default: nodejs)
|
||||
|
||||
*Metadata:* Stringified as JSON in the full message GELF field.
|
||||
|
||||
### Cassandra Transport
|
||||
|
||||
[winston-cassandra][20] is a Cassandra transport:
|
||||
|
||||
``` js
|
||||
var Cassandra = require('winston-cassandra').Cassandra;
|
||||
winston.add(Cassandra, options);
|
||||
```
|
||||
|
||||
The Cassandra transport connects to a cluster using the native protocol with the following options:
|
||||
|
||||
* __level:__ Level of messages that this transport should log (default: `'info'`).
|
||||
* __table:__ The name of the Cassandra column family you want to store log messages in (default: `'logs'`).
|
||||
* __partitionBy:__ How you want the logs to be partitioned. Possible values `'hour'` and `'day'`(Default).
|
||||
* __consistency:__ The consistency of the insert query (default: `quorum`).
|
||||
|
||||
In addition to the options accepted by the [Node.js Cassandra driver](https://github.com/jorgebay/node-cassandra-cql) Client.
|
||||
|
||||
* __hosts:__ Cluster nodes that will handle the write requests:
|
||||
Array of strings containing the hosts, for example `['host1', 'host2']` (required).
|
||||
* __keyspace:__ The name of the keyspace that will contain the logs table (required). The keyspace should be already created in the cluster.
|
||||
|
||||
|
||||
## Find more Transports
|
||||
|
||||
``` bash
|
||||
$ npm search winston
|
||||
(...)
|
||||
winston-amon Winston transport for Amon logging =zoramite
|
||||
winston-amqp An AMQP transport for winston =kr1sp1n
|
||||
winston-cassandra A Cassandra transport for winston =jorgebay
|
||||
winston-couchdb a couchdb transport for winston =alz
|
||||
winston-express Express middleware to let you use winston from the browser. =regality
|
||||
winston-graylog2 A graylog2 transport for winston =smithclay
|
||||
winston-hbase A HBase transport for winston =ddude
|
||||
winston-loggly A Loggly transport for winston =indexzero
|
||||
winston-mail A mail transport for winston =wavded
|
||||
winston-mail2 A mail transport for winston =ivolo
|
||||
winston-mongodb A MongoDB transport for winston =indexzero
|
||||
winston-nodemail A mail transport for winston =reinpk
|
||||
winston-nssocket nssocket transport for winston =mmalecki
|
||||
winston-papertrail A Papertrail transport for winston =kenperkins
|
||||
winston-redis A fixed-length Redis transport for winston =indexzero
|
||||
winston-riak A Riak transport for winston =indexzero
|
||||
winston-scribe A scribe transport for winston =wnoronha
|
||||
winston-simpledb A Winston transport for Amazon SimpleDB =chilts
|
||||
winston-skywriter A Windows Azure table storage transport for winston =pofallon
|
||||
winston-sns A Simple Notification System Transport for winston =jesseditson
|
||||
winston-syslog A syslog transport for winston =indexzero
|
||||
winston-syslog-ain2 An ain2 based syslog transport for winston =lamtha
|
||||
winston-winlog Windows Event Log logger for Winston =jfromaniello
|
||||
winston-zmq A 0MQ transport for winston =dhendo
|
||||
winston-growl A growl transport for winston =pgherveou
|
||||
|
||||
```
|
||||
|
||||
[0]: http://nodejs.org/docs/v0.3.5/api/streams.html#writable_Stream
|
||||
[1]: https://github.com/flatiron/winstond
|
||||
[2]: https://github.com/indexzero/winston-couchdb
|
||||
[3]: http://guide.couchdb.org/draft/design.html
|
||||
[4]: https://github.com/mranney/node_redis
|
||||
[5]: https://github.com/indexzero/winston-loggly
|
||||
[6]: http://nodejitsu.com
|
||||
[7]: https://github.com/nodejitsu/node-loggly
|
||||
[8]: http://loggly.com
|
||||
[9]: http://www.loggly.com/product/
|
||||
[10]: http://wiki.loggly.com/loggingfromcode
|
||||
[11]: https://github.com/indexzero/winston-riak
|
||||
[12]: http://riakjs.org
|
||||
[13]: https://github.com/frank06/riak-js/blob/master/src/http_client.coffee#L10
|
||||
[14]: http://github.com/indexzero/winston-mongodb
|
||||
[15]: http://github.com/appsattic/winston-simpledb
|
||||
[16]: http://github.com/wavded/winston-mail
|
||||
[17]: https://github.com/weaver/node-mail
|
||||
[18]: https://github.com/jesseditson/winston-sns
|
||||
[19]: https://github.com/flite/winston-graylog2
|
||||
[20]: https://github.com/jorgebay/winston-cassandra
|
||||
18
node_modules/winston/examples/couchdb.js
generated
vendored
Normal file
18
node_modules/winston/examples/couchdb.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
var winston = require('../lib/winston');
|
||||
|
||||
//
|
||||
// Create a new winston logger instance with two tranports: Console, and Couchdb
|
||||
//
|
||||
//
|
||||
// The Console transport will simply output to the console screen
|
||||
// The Couchdb tranport will perform an HTTP POST request to the specified CouchDB instance
|
||||
//
|
||||
var logger = new (winston.Logger)({
|
||||
transports: [
|
||||
new (winston.transports.Console)(),
|
||||
new (winston.transports.Couchdb)({ 'host': 'localhost', 'db': 'logs' })
|
||||
// if you need auth do this: new (winston.transports.Couchdb)({ 'user': 'admin', 'pass': 'admin', 'host': 'localhost', 'db': 'logs' })
|
||||
]
|
||||
});
|
||||
|
||||
logger.log('info', 'Hello webhook log files!', { 'foo': 'bar' });
|
||||
44
node_modules/winston/examples/custom-levels.js
generated
vendored
Normal file
44
node_modules/winston/examples/custom-levels.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* custom-levels.js: Custom logger and color levels in winston
|
||||
*
|
||||
* (C) 2012, Nodejitsu Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
var winston = require('../lib/winston');
|
||||
|
||||
//
|
||||
// Logging levels
|
||||
//
|
||||
var config = {
|
||||
levels: {
|
||||
silly: 0,
|
||||
verbose: 1,
|
||||
info: 2,
|
||||
data: 3,
|
||||
warn: 4,
|
||||
debug: 5,
|
||||
error: 6
|
||||
},
|
||||
colors: {
|
||||
silly: 'magenta',
|
||||
verbose: 'cyan',
|
||||
info: 'green',
|
||||
data: 'grey',
|
||||
warn: 'yellow',
|
||||
debug: 'blue',
|
||||
error: 'red'
|
||||
}
|
||||
};
|
||||
|
||||
var logger = module.exports = new (winston.Logger)({
|
||||
transports: [
|
||||
new (winston.transports.Console)({
|
||||
colorize: true
|
||||
})
|
||||
],
|
||||
levels: config.levels,
|
||||
colors: config.colors
|
||||
});
|
||||
|
||||
logger.data('hello')
|
||||
4
node_modules/winston/examples/exception.js
generated
vendored
Normal file
4
node_modules/winston/examples/exception.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
var winston = require('../');
|
||||
winston.handleExceptions(new winston.transports.Console({ colorize: true, json: true }));
|
||||
|
||||
throw new Error('Hello, winston!');
|
||||
10
node_modules/winston/examples/raw-mode.js
generated
vendored
Normal file
10
node_modules/winston/examples/raw-mode.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
var winston = require('../lib/winston');
|
||||
|
||||
var logger = new (winston.Logger)({
|
||||
transports: [
|
||||
new (winston.transports.Console)({ raw: true }),
|
||||
]
|
||||
});
|
||||
|
||||
logger.log('info', 'Hello, this is a raw logging event', { 'foo': 'bar' });
|
||||
logger.log('info', 'Hello, this is a raw logging event 2', { 'foo': 'bar' });
|
||||
17
node_modules/winston/examples/webhook-post.js
generated
vendored
Normal file
17
node_modules/winston/examples/webhook-post.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
var winston = require('../lib/winston');
|
||||
|
||||
//
|
||||
// Create a new winston logger instance with two tranports: Console, and Webhook
|
||||
//
|
||||
//
|
||||
// The Console transport will simply output to the console screen
|
||||
// The Webhook tranports will perform an HTTP POST request to an abritrary end-point ( for post/recieve webhooks )
|
||||
//
|
||||
var logger = new (winston.Logger)({
|
||||
transports: [
|
||||
new (winston.transports.Console)(),
|
||||
new (winston.transports.Webhook)({ 'host': 'localhost', 'port': 8080, 'path': '/collectdata' })
|
||||
]
|
||||
});
|
||||
|
||||
logger.log('info', 'Hello webhook log files!', { 'foo': 'bar' });
|
||||
163
node_modules/winston/lib/winston.js
generated
vendored
Normal file
163
node_modules/winston/lib/winston.js
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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'
|
||||
];
|
||||
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
|
||||
};
|
||||
}
|
||||
});
|
||||
347
node_modules/winston/lib/winston/common.js
generated
vendored
Normal file
347
node_modules/winston/lib/winston/common.js
generated
vendored
Normal file
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* 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'),
|
||||
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) {
|
||||
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) {
|
||||
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 refrence types (Object)
|
||||
if (!(obj instanceof Object)) {
|
||||
return obj;
|
||||
}
|
||||
else if (obj instanceof Date) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
var copy = {};
|
||||
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)
|
||||
// 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,
|
||||
meta = options.meta !== undefined || options.meta !== null ? exports.clone(cycle.decycle(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;
|
||||
output.message = options.message.stripColors;
|
||||
return JSON.stringify(output);
|
||||
}
|
||||
|
||||
//
|
||||
// json mode is intended for pretty printing multi-line json to the terminal
|
||||
//
|
||||
if (options.json) {
|
||||
if (typeof meta !== 'object' && meta != null) {
|
||||
meta = { meta: meta };
|
||||
}
|
||||
|
||||
output = exports.clone(meta) || {};
|
||||
output.level = options.level;
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
output = timestamp ? timestamp + ' - ' : '';
|
||||
output += options.colorize ? config.colorize(options.level) : options.level;
|
||||
output += ': ';
|
||||
output += options.label ? ('[' + options.label + '] ') : '';
|
||||
output += 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) {
|
||||
output += ' ' + (
|
||||
options.prettyPrint
|
||||
? ('\n' + util.inspect(meta, false, null, options.colorize))
|
||||
: 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 tail(options, callback) {
|
||||
var stream = fs.createReadStream(options.file, { encoding: 'utf8' }),
|
||||
buff = '',
|
||||
destroy,
|
||||
row = 0;
|
||||
|
||||
destroy = stream.destroy.bind(stream);
|
||||
stream.destroy = function () {};
|
||||
|
||||
if (options.start === -1) {
|
||||
delete options.start;
|
||||
}
|
||||
|
||||
stream.on('data', function (data) {
|
||||
var data = (buff + data).split(/\n+/),
|
||||
l = data.length - 1,
|
||||
i = 0;
|
||||
|
||||
for (; i < l; i++) {
|
||||
if (options.start == null || row > options.start) {
|
||||
callback(null, data[i]);
|
||||
}
|
||||
row++;
|
||||
}
|
||||
|
||||
buff = data[l];
|
||||
});
|
||||
|
||||
stream.on('error', function (err) {
|
||||
callback(err);
|
||||
destroy();
|
||||
});
|
||||
|
||||
stream.on('end', function () {
|
||||
if (buff) {
|
||||
stream.emit('line', buff);
|
||||
buff = '';
|
||||
}
|
||||
|
||||
resume();
|
||||
});
|
||||
|
||||
function resume() {
|
||||
setTimeout(function () {
|
||||
stream.resume();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
return destroy;
|
||||
};
|
||||
59
node_modules/winston/lib/winston/config.js
generated
vendored
Normal file
59
node_modules/winston/lib/winston/config.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* config.js: Default settings for all levels that winston knows about
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var colors = require('colors');
|
||||
|
||||
var config = exports,
|
||||
allColors = exports.allColors = {};
|
||||
|
||||
config.addColors = function (colors) {
|
||||
mixin(allColors, colors);
|
||||
};
|
||||
|
||||
config.colorize = function (level) {
|
||||
var colorized = level;
|
||||
if (allColors[level] instanceof Array) {
|
||||
for (var i = 0, l = allColors[level].length; i < l; ++i) {
|
||||
colorized = colorized[allColors[level][i]];
|
||||
}
|
||||
} else if (allColors[level].match(/\s/)) {
|
||||
var colorArr = allColors[level].split(/\s+/);
|
||||
for (var i = 0; i < colorArr.length; ++i) {
|
||||
colorized = colorized[colorArr[i]];
|
||||
}
|
||||
allColors[level] = colorArr;
|
||||
} else {
|
||||
colorized = colorized[allColors[level]];
|
||||
}
|
||||
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.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
35
node_modules/winston/lib/winston/config/cli-config.js
generated
vendored
Normal 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 = {
|
||||
silly: 0,
|
||||
input: 1,
|
||||
verbose: 2,
|
||||
prompt: 3,
|
||||
debug: 4,
|
||||
info: 5,
|
||||
data: 6,
|
||||
help: 7,
|
||||
warn: 8,
|
||||
error: 9
|
||||
};
|
||||
|
||||
cliConfig.colors = {
|
||||
silly: 'magenta',
|
||||
input: 'grey',
|
||||
verbose: 'cyan',
|
||||
prompt: 'grey',
|
||||
debug: 'blue',
|
||||
info: 'green',
|
||||
data: 'grey',
|
||||
help: 'cyan',
|
||||
warn: 'yellow',
|
||||
error: 'red'
|
||||
};
|
||||
27
node_modules/winston/lib/winston/config/npm-config.js
generated
vendored
Normal file
27
node_modules/winston/lib/winston/config/npm-config.js
generated
vendored
Normal 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 = {
|
||||
silly: 0,
|
||||
debug: 1,
|
||||
verbose: 2,
|
||||
info: 3,
|
||||
warn: 4,
|
||||
error: 5
|
||||
};
|
||||
|
||||
npmConfig.colors = {
|
||||
silly: 'magenta',
|
||||
verbose: 'cyan',
|
||||
debug: 'blue',
|
||||
info: 'green',
|
||||
warn: 'yellow',
|
||||
error: 'red'
|
||||
};
|
||||
31
node_modules/winston/lib/winston/config/syslog-config.js
generated
vendored
Normal file
31
node_modules/winston/lib/winston/config/syslog-config.js
generated
vendored
Normal 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',
|
||||
};
|
||||
112
node_modules/winston/lib/winston/container.js
generated
vendored
Normal file
112
node_modules/winston/lib/winston/container.js
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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 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);
|
||||
}
|
||||
|
||||
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();
|
||||
delete self.loggers[id];
|
||||
}
|
||||
|
||||
return id ? _close(id) : Object.keys(this.loggers).forEach(function (id) {
|
||||
_close(id);
|
||||
});
|
||||
};
|
||||
|
||||
56
node_modules/winston/lib/winston/exception.js
generated
vendored
Normal file
56
node_modules/winston/lib/winston/exception.js
generated
vendored
Normal 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(),
|
||||
}
|
||||
});
|
||||
};
|
||||
665
node_modules/winston/lib/winston/logger.js
generated
vendored
Executable file
665
node_modules/winston/lib/winston/logger.js
generated
vendored
Executable file
@@ -0,0 +1,665 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
//
|
||||
// Time constants
|
||||
//
|
||||
var ticksPerMillisecond = 10000;
|
||||
|
||||
//
|
||||
// ### 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);
|
||||
options = options || {};
|
||||
|
||||
var self = this,
|
||||
handleExceptions = false;
|
||||
|
||||
//
|
||||
// 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 other intelligent default settings.
|
||||
//
|
||||
this.transports = {};
|
||||
this.rewriters = [];
|
||||
this.exceptionHandlers = {};
|
||||
this.profilers = {};
|
||||
this._names = [];
|
||||
this._hnames = [];
|
||||
|
||||
if (options.transports) {
|
||||
options.transports.forEach(function (transport) {
|
||||
self.add(transport, null, true);
|
||||
|
||||
if (transport.handleExceptions) {
|
||||
handleExceptions = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (options.rewriters) {
|
||||
options.rewriters.forEach(function (rewriter) {
|
||||
self.addRewriter(rewriter);
|
||||
});
|
||||
}
|
||||
|
||||
if (options.exceptionHandlers) {
|
||||
handleExceptions = true;
|
||||
options.exceptionHandlers.forEach(function (handler) {
|
||||
self._hnames.push(handler.name);
|
||||
self.exceptionHandlers[handler.name] = handler;
|
||||
});
|
||||
}
|
||||
|
||||
if (options.handleExceptions || handleExceptions) {
|
||||
this.handleExceptions();
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Inherit from `events.EventEmitter`.
|
||||
//
|
||||
util.inherits(Logger, events.EventEmitter);
|
||||
|
||||
//
|
||||
// ### function extend (target)
|
||||
// #### @target {Object} Target to extend.
|
||||
// Extends the target object with a 'log' method
|
||||
// along with a method for each level in this instance.
|
||||
//
|
||||
Logger.prototype.extend = function (target) {
|
||||
var self = this;
|
||||
['log', 'profile', 'startTimer'].concat(Object.keys(this.levels)).forEach(function (method) {
|
||||
target[method] = function () {
|
||||
return self[method].apply(self, arguments);
|
||||
};
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
//
|
||||
// ### 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 self = this,
|
||||
args = Array.prototype.slice.call(arguments, 1);
|
||||
|
||||
while(args[args.length - 1] === null) {
|
||||
args.pop();
|
||||
}
|
||||
|
||||
var callback = typeof args[args.length - 1] === 'function' ? args.pop() : null,
|
||||
meta = typeof args[args.length - 1] === 'object' ? args.pop() : {},
|
||||
msg = util.format.apply(null, args);
|
||||
|
||||
// If we should pad for levels, do so
|
||||
if (this.padLevels) {
|
||||
msg = new Array(this.levelLength - level.length + 1).join(' ') + msg;
|
||||
}
|
||||
|
||||
function onError (err) {
|
||||
if (callback) {
|
||||
callback(err);
|
||||
}
|
||||
else if (self.emitErrs) {
|
||||
self.emit('error', err);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.transports.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));
|
||||
}
|
||||
|
||||
this.rewriters.forEach(function (rewriter) {
|
||||
meta = rewriter(level, msg, 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 emit(name, next) {
|
||||
var transport = self.transports[name];
|
||||
if ((transport.level && self.levels[transport.level] <= self.levels[level])
|
||||
|| (!transport.level && self.levels[self.level] <= self.levels[level])) {
|
||||
transport.log(level, msg, meta, function (err) {
|
||||
if (err) {
|
||||
err.transport = transport;
|
||||
cb(err);
|
||||
return next();
|
||||
}
|
||||
self.emit('logging', transport, level, msg, meta);
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Respond to the callback
|
||||
//
|
||||
function cb(err) {
|
||||
if (callback) {
|
||||
if (err) return callback(err);
|
||||
callback(null, level, msg, meta);
|
||||
}
|
||||
callback = null;
|
||||
if (!err) {
|
||||
self.emit('logged', level, msg, meta);
|
||||
}
|
||||
}
|
||||
|
||||
async.forEach(this._names, emit, cb);
|
||||
|
||||
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) {
|
||||
result = err || result;
|
||||
if (result) {
|
||||
results[transport.name] = result;
|
||||
}
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// 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();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// ### function handleExceptions ()
|
||||
// Handles `uncaughtException` events for the current process
|
||||
//
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
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)
|
||||
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 addRewriter (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.addRewriter = function (rewriter) {
|
||||
this.rewriters.push(rewriter);
|
||||
}
|
||||
|
||||
//
|
||||
// ### function clear ()
|
||||
// Remove all transports from this instance
|
||||
//
|
||||
Logger.prototype.clear = function () {
|
||||
for (var name in this.transports) {
|
||||
this.remove({ name: name });
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// ### function remove (transport)
|
||||
// #### @transport {Transport} Transport to remove.
|
||||
// Removes a transport of the specified type from this instance.
|
||||
//
|
||||
Logger.prototype.remove = function (transport) {
|
||||
var name = transport.name || transport.prototype.name;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
instance.removeListener('error', instance._onError);
|
||||
return this;
|
||||
};
|
||||
|
||||
var ProfileHandler = function (logger) {
|
||||
this.logger = logger;
|
||||
|
||||
this.start = Date.now();
|
||||
|
||||
this.done = function (msg) {
|
||||
var args, callback, meta;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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.duration = now - then + 'ms';
|
||||
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 = true;
|
||||
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, 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);
|
||||
}
|
||||
};
|
||||
34
node_modules/winston/lib/winston/transports.js
generated
vendored
Normal file
34
node_modules/winston/lib/winston/transports.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* transports.js: Set of all transports Winston knows about
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var fs = require('fs'),
|
||||
path = require('path'),
|
||||
common = require('./common');
|
||||
|
||||
var transports = exports;
|
||||
|
||||
//
|
||||
// Setup all transports as lazy-loaded getters.
|
||||
//
|
||||
fs.readdirSync(path.join(__dirname, 'transports')).forEach(function (file) {
|
||||
var transport = file.replace('.js', ''),
|
||||
name = common.capitalize(transport);
|
||||
|
||||
if (transport === 'transport') {
|
||||
return;
|
||||
}
|
||||
else if (~transport.indexOf('-')) {
|
||||
name = transport.split('-').map(function (part) {
|
||||
return common.capitalize(part);
|
||||
}).join('');
|
||||
}
|
||||
|
||||
transports.__defineGetter__(name, function () {
|
||||
return require('./transports/' + transport)[name];
|
||||
});
|
||||
});
|
||||
89
node_modules/winston/lib/winston/transports/console.js
generated
vendored
Normal file
89
node_modules/winston/lib/winston/transports/console.js
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* console.js: Transport for outputting to the console
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var events = require('events'),
|
||||
util = require('util'),
|
||||
colors = require('colors'),
|
||||
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.label = options.label || null;
|
||||
|
||||
if (this.json) {
|
||||
this.stringify = options.stringify || function (obj) {
|
||||
return JSON.stringify(obj, null, 2);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// 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,
|
||||
prettyPrint: this.prettyPrint,
|
||||
raw: this.raw,
|
||||
label: this.label
|
||||
});
|
||||
|
||||
if (level === 'error' || level === 'debug') {
|
||||
process.stderr.write(output + '\n');
|
||||
} else {
|
||||
process.stdout.write(output + '\n');
|
||||
}
|
||||
|
||||
//
|
||||
// Emit the `logged` event immediately because the event loop
|
||||
// will not exit until `process.stdout` has drained anyway.
|
||||
//
|
||||
self.emit('logged');
|
||||
callback(null, true);
|
||||
};
|
||||
569
node_modules/winston/lib/winston/transports/daily-rotate-file.js
generated
vendored
Normal file
569
node_modules/winston/lib/winston/transports/daily-rotate-file.js
generated
vendored
Normal file
@@ -0,0 +1,569 @@
|
||||
/*
|
||||
* daily-rotate-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'),
|
||||
colors = require('colors'),
|
||||
common = require('../common'),
|
||||
Transport = require('./transport').Transport,
|
||||
Stream = require('stream').Stream;
|
||||
|
||||
//
|
||||
// ### function DailyRotateFile (options)
|
||||
// #### @options {Object} Options for this instance.
|
||||
// Constructor function for the DailyRotateFile transport object responsible
|
||||
// for persisting log messages and metadata to one or more files.
|
||||
//
|
||||
var DailyRotateFile = exports.DailyRotateFile = function (options) {
|
||||
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;
|
||||
|
||||
//
|
||||
// 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.colorize = options.colorize || false;
|
||||
this.maxsize = options.maxsize || null;
|
||||
this.maxFiles = options.maxFiles || null;
|
||||
this.prettyPrint = options.prettyPrint || false;
|
||||
this.timestamp = options.timestamp != null ? options.timestamp : true;
|
||||
this.datePattern = options.datePattern != null ? options.datePattern : '.yyyy-MM-dd';
|
||||
|
||||
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;
|
||||
|
||||
var now = new Date();
|
||||
this._year = now.getFullYear();
|
||||
this._month = now.getMonth();
|
||||
this._date = now.getDate();
|
||||
this._hour = now.getHours();
|
||||
this._minute = now.getMinutes();
|
||||
|
||||
var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhM])\1?/g,
|
||||
pad = function (val, len) {
|
||||
val = String(val);
|
||||
len = len || 2;
|
||||
while (val.length < len) val = "0" + val;
|
||||
return val;
|
||||
};
|
||||
|
||||
this.getFormattedDate = function() {
|
||||
var flags = {
|
||||
yy: String(this._year).slice(2),
|
||||
yyyy: this._year,
|
||||
M: this._month + 1,
|
||||
MM: pad(this._month + 1),
|
||||
d: this._date,
|
||||
dd: pad(this._date),
|
||||
H: this._hour,
|
||||
HH: pad(this._hour),
|
||||
m: this._minute,
|
||||
mm: pad(this._minute)
|
||||
};
|
||||
return this.datePattern.replace(token, function ($0) {
|
||||
return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
//
|
||||
// Inherit from `winston.Transport`.
|
||||
//
|
||||
util.inherits(DailyRotateFile, Transport);
|
||||
|
||||
//
|
||||
// Expose the name of this Transport on the prototype
|
||||
//
|
||||
DailyRotateFile.prototype.name = 'dailyRotateFile';
|
||||
|
||||
//
|
||||
// ### 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.
|
||||
//
|
||||
DailyRotateFile.prototype.log = function (level, msg, meta, callback) {
|
||||
if (this.silent) {
|
||||
return callback(null, true);
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
var output = common.log({
|
||||
level: level,
|
||||
message: msg,
|
||||
meta: meta,
|
||||
json: this.json,
|
||||
colorize: this.colorize,
|
||||
prettyPrint: this.prettyPrint,
|
||||
timestamp: this.timestamp,
|
||||
stringify: this.stringify
|
||||
}) + '\n';
|
||||
|
||||
this._size += output.length;
|
||||
|
||||
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._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._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.
|
||||
//
|
||||
DailyRotateFile.prototype._write = function(data, callback) {
|
||||
// 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);
|
||||
});
|
||||
}
|
||||
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.
|
||||
//
|
||||
DailyRotateFile.prototype.query = function (options, callback) {
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
// TODO when maxfilesize rotate occurs
|
||||
var file = path.join(this.dirname, this._basename + this.getFormattedDate()),
|
||||
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.
|
||||
//
|
||||
DailyRotateFile.prototype.stream = function (options) {
|
||||
var file = path.join(this.dirname, this._basename + this.getFormattedDate()),
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
if(stream.resume){
|
||||
stream.resume();
|
||||
}
|
||||
|
||||
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.
|
||||
//
|
||||
DailyRotateFile.prototype.open = function (callback) {
|
||||
var now = new Date();
|
||||
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) ||
|
||||
(this._year < now.getFullYear() || this._month < now.getMonth() || this._date < now.getDate() || this._hour < now.getHours() || this._minute < now.getMinutes())) {
|
||||
//
|
||||
// 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();
|
||||
}
|
||||
|
||||
//
|
||||
// Otherwise we have a valid (and ready) stream.
|
||||
//
|
||||
callback();
|
||||
};
|
||||
|
||||
//
|
||||
// ### function close ()
|
||||
// Closes the stream associated with this instance.
|
||||
//
|
||||
DailyRotateFile.prototype.close = function () {
|
||||
var self = this;
|
||||
|
||||
if (this._stream) {
|
||||
this._stream.end();
|
||||
this._stream.destroySoon();
|
||||
|
||||
this._stream.once('drain', function () {
|
||||
self.emit('flush');
|
||||
self.emit('closed');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// ### function flush ()
|
||||
// Flushes any buffered messages to the current `stream`
|
||||
// used by this instance.
|
||||
//
|
||||
DailyRotateFile.prototype.flush = function () {
|
||||
var self = this;
|
||||
|
||||
//
|
||||
// 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`).
|
||||
//
|
||||
DailyRotateFile.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);
|
||||
|
||||
//
|
||||
// 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 () {
|
||||
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();
|
||||
}
|
||||
|
||||
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 checkFile(self._getFile(true));
|
||||
}
|
||||
|
||||
var now = new Date();
|
||||
if (self._year < now.getFullYear() || self._month < now.getMonth() || self._date < now.getDate() || self._hour < now.getHours() || self._minute < now.getMinutes()) {
|
||||
self._year = now.getFullYear();
|
||||
self._month = now.getMonth();
|
||||
self._date = now.getDate();
|
||||
self._hour = now.getHours();
|
||||
self._minute = now.getMinutes();
|
||||
self._created = 0;
|
||||
return checkFile(self._getFile());
|
||||
}
|
||||
|
||||
createAndFlush(stats.size);
|
||||
});
|
||||
})(this._getFile());
|
||||
};
|
||||
|
||||
//
|
||||
// ### @private function _getFile ()
|
||||
// Gets the next filename to use for this instance
|
||||
// in the case that log filesizes are being capped.
|
||||
//
|
||||
DailyRotateFile.prototype._getFile = function (inc) {
|
||||
var self = this,
|
||||
filename = this._basename + this.getFormattedDate(),
|
||||
remaining;
|
||||
|
||||
if (inc) {
|
||||
//
|
||||
// Increment the number of files created or
|
||||
// checked by this instance.
|
||||
//
|
||||
// Check for maxFiles option and delete file
|
||||
if (this.maxFiles && (this._created >= (this.maxFiles - 1))) {
|
||||
remaining = this._created - (this.maxFiles - 1);
|
||||
if (remaining === 0) {
|
||||
fs.unlinkSync(path.join(this.dirname, filename));
|
||||
}
|
||||
else {
|
||||
fs.unlinkSync(path.join(this.dirname, filename + '.' + remaining));
|
||||
}
|
||||
}
|
||||
|
||||
this._created += 1;
|
||||
}
|
||||
|
||||
return this._created
|
||||
? filename + '.' + this._created
|
||||
: filename;
|
||||
};
|
||||
|
||||
//
|
||||
// ### @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.
|
||||
//
|
||||
DailyRotateFile.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');
|
||||
});
|
||||
}
|
||||
};
|
||||
538
node_modules/winston/lib/winston/transports/file.js
generated
vendored
Normal file
538
node_modules/winston/lib/winston/transports/file.js
generated
vendored
Normal file
@@ -0,0 +1,538 @@
|
||||
/*
|
||||
* 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'),
|
||||
colors = require('colors'),
|
||||
common = require('../common'),
|
||||
Transport = require('./transport').Transport,
|
||||
Stream = require('stream').Stream;
|
||||
|
||||
//
|
||||
// ### 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) {
|
||||
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;
|
||||
|
||||
//
|
||||
// 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.colorize = options.colorize || false;
|
||||
this.maxsize = options.maxsize || null;
|
||||
this.maxFiles = options.maxFiles || null;
|
||||
this.prettyPrint = options.prettyPrint || false;
|
||||
this.label = options.label || null;
|
||||
this.timestamp = options.timestamp != null ? options.timestamp : true;
|
||||
this.logstash = options.logstash || false;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
if (typeof msg !== 'string') {
|
||||
msg = '' + msg;
|
||||
}
|
||||
|
||||
var output = common.log({
|
||||
level: level,
|
||||
message: msg,
|
||||
meta: meta,
|
||||
json: this.json,
|
||||
colorize: this.colorize,
|
||||
prettyPrint: this.prettyPrint,
|
||||
timestamp: this.timestamp,
|
||||
stringify: this.stringify,
|
||||
label: this.label,
|
||||
logstash: this.logstash
|
||||
}) + '\n';
|
||||
|
||||
this._size += output.length;
|
||||
|
||||
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._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._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 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);
|
||||
});
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
//
|
||||
// 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('drain', 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);
|
||||
|
||||
//
|
||||
// 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();
|
||||
}
|
||||
|
||||
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 checkFile(self._getFile(true));
|
||||
}
|
||||
|
||||
createAndFlush(stats.size);
|
||||
});
|
||||
})(this._getFile());
|
||||
};
|
||||
|
||||
//
|
||||
// ### @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 (inc) {
|
||||
var self = this,
|
||||
ext = path.extname(this._basename),
|
||||
basename = path.basename(this._basename, ext),
|
||||
remaining;
|
||||
|
||||
if (inc) {
|
||||
//
|
||||
// Increment the number of files created or
|
||||
// checked by this instance.
|
||||
//
|
||||
// Check for maxFiles option and delete file
|
||||
if (this.maxFiles && (this._created >= (this.maxFiles - 1))) {
|
||||
remaining = this._created - (this.maxFiles - 1);
|
||||
if (remaining === 0) {
|
||||
fs.unlinkSync(path.join(this.dirname, basename + ext));
|
||||
}
|
||||
else {
|
||||
fs.unlinkSync(path.join(this.dirname, basename + remaining + ext));
|
||||
}
|
||||
}
|
||||
|
||||
this._created += 1;
|
||||
}
|
||||
|
||||
return this._created
|
||||
? basename + this._created + ext
|
||||
: basename + ext;
|
||||
};
|
||||
|
||||
//
|
||||
// ### @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');
|
||||
});
|
||||
}
|
||||
};
|
||||
228
node_modules/winston/lib/winston/transports/http.js
generated
vendored
Normal file
228
node_modules/winston/lib/winston/transports/http.js
generated
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
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) {
|
||||
var options = options || {},
|
||||
auth = options.auth || this.auth,
|
||||
path = options.path || this.path || '';
|
||||
|
||||
delete options.auth;
|
||||
delete options.path;
|
||||
|
||||
// Prepare options for outgoing HTTP request
|
||||
req = (self.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.end(new Buffer(JSON.stringify(options), 'utf8'));
|
||||
|
||||
req.on('error', callback);
|
||||
|
||||
req.on('response', function (res) {
|
||||
res.on('end', function () {
|
||||
callback(null, res);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// ### 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) {
|
||||
var self = this,
|
||||
options = options || {},
|
||||
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;
|
||||
};
|
||||
85
node_modules/winston/lib/winston/transports/memory.js
generated
vendored
Normal file
85
node_modules/winston/lib/winston/transports/memory.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
var events = require('events'),
|
||||
util = require('util'),
|
||||
colors = require('colors'),
|
||||
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.label = options.label || 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
|
||||
});
|
||||
|
||||
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 = [];
|
||||
};
|
||||
121
node_modules/winston/lib/winston/transports/transport.js
generated
vendored
Normal file
121
node_modules/winston/lib/winston/transports/transport.js
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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.level = options.level === undefined ? 'info' : options.level;
|
||||
this.silent = options.silent || false;
|
||||
this.raw = options.raw || false;
|
||||
this.name = options.name || this.name;
|
||||
|
||||
this.handleExceptions = options.handleExceptions || 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 - 24
|
||||
options.from = options.from || new Date - (24 * 60 * 60 * 1000);
|
||||
if (typeof options.from !== 'object') {
|
||||
options.from = new Date(options.from);
|
||||
}
|
||||
|
||||
// now
|
||||
options.until = options.until || new Date;
|
||||
if (typeof options.until !== 'object') {
|
||||
options.until = new Date(options.until);
|
||||
}
|
||||
|
||||
// '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;
|
||||
|
||||
function onLogged () {
|
||||
self.removeListener('error', onError);
|
||||
callback();
|
||||
}
|
||||
|
||||
function onError () {
|
||||
self.removeListener('logged', onLogged);
|
||||
callback();
|
||||
}
|
||||
|
||||
this.once('logged', onLogged);
|
||||
this.once('error', onError);
|
||||
this.log('error', msg, meta, function () { });
|
||||
};
|
||||
146
node_modules/winston/lib/winston/transports/webhook.js
generated
vendored
Normal file
146
node_modules/winston/lib/winston/transports/webhook.js
generated
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* webhook.js: Transport for logging to remote http endpoints ( POST / RECEIVE webhooks )
|
||||
*
|
||||
* (C) 2011 Marak Squires
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var events = require('events'),
|
||||
http = require('http'),
|
||||
https = require('https'),
|
||||
util = require('util'),
|
||||
cycle = require('cycle'),
|
||||
common = require('../common'),
|
||||
Transport = require('./transport').Transport;
|
||||
|
||||
//
|
||||
// ### function WebHook (options)
|
||||
// #### @options {Object} Options for this instance.
|
||||
// Constructor function for the Console transport object responsible
|
||||
// for making arbitrary HTTP requests whenever log messages and metadata
|
||||
// are received.
|
||||
//
|
||||
var Webhook = exports.Webhook = function (options) {
|
||||
Transport.call(this, options);
|
||||
|
||||
this.name = 'webhook';
|
||||
this.host = options.host || 'localhost';
|
||||
this.port = options.port || 8080;
|
||||
this.method = options.method || 'POST';
|
||||
this.path = options.path || '/winston-log';
|
||||
|
||||
if (options.auth) {
|
||||
this.auth = {};
|
||||
this.auth.username = options.auth.username || '';
|
||||
this.auth.password = options.auth.password || '';
|
||||
}
|
||||
|
||||
if (options.ssl) {
|
||||
this.port = options.port || 443;
|
||||
this.ssl = {
|
||||
key: options.ssl.key || null,
|
||||
cert: options.ssl.cert || null,
|
||||
ca: options.ssl.ca
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Inherit from `winston.Transport`.
|
||||
//
|
||||
util.inherits(Webhook, Transport);
|
||||
|
||||
//
|
||||
// Expose the name of this Transport on the prototype
|
||||
//
|
||||
Webhook.prototype.name = 'webhook';
|
||||
|
||||
//
|
||||
// ### 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.
|
||||
//
|
||||
Webhook.prototype.log = function (level, msg, meta, callback) {
|
||||
if (this.silent) {
|
||||
return callback(null, true);
|
||||
}
|
||||
|
||||
var self = this,
|
||||
meta = cycle.decycle(meta),
|
||||
message = common.clone(meta),
|
||||
options,
|
||||
req;
|
||||
|
||||
// Prepare options for outgoing HTTP request
|
||||
options = {
|
||||
host: this.host,
|
||||
port: this.port,
|
||||
path: this.path,
|
||||
method: this.method,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
};
|
||||
|
||||
if (this.ssl) {
|
||||
options.ca = this.ssl.ca;
|
||||
options.key = this.ssl.key;
|
||||
options.cert = this.ssl.cert;
|
||||
|
||||
// Required for the test fixture SSL certificate to be considered valid.
|
||||
options.rejectUnauthorized = false;
|
||||
}
|
||||
|
||||
if (this.auth) {
|
||||
// Encode `Authorization` header used by Basic Auth
|
||||
options.headers['Authorization'] = 'Basic ' + new Buffer(
|
||||
this.auth.username + ':' + this.auth.password, 'utf8'
|
||||
).toString('base64');
|
||||
}
|
||||
|
||||
// Perform HTTP logging request
|
||||
req = (self.ssl ? https : http).request(options, function (res) {
|
||||
// TODO: emit 'logged' correctly,
|
||||
// keep track of pending logs.
|
||||
res.on('data', function(data) {
|
||||
// Do nothing. We need to read the response, or we run into maxSockets
|
||||
// after 5 requests.
|
||||
});
|
||||
|
||||
self.emit('logged');
|
||||
if (callback) callback(null, true);
|
||||
callback = null;
|
||||
});
|
||||
|
||||
req.on('error', function (err) {
|
||||
//
|
||||
// Propagate the `error` back up to the `Logger` that this
|
||||
// instance belongs to.
|
||||
//
|
||||
self.emit('error', err);
|
||||
if (callback) callback(err, false);
|
||||
callback = null;
|
||||
});
|
||||
|
||||
//
|
||||
// Write logging event to the outgoing request body
|
||||
//
|
||||
// jsonMessage is currently conforming to JSON-RPC v1.0,
|
||||
// but without the unique id since there is no anticipated response
|
||||
// see: http://en.wikipedia.org/wiki/JSON-RPC
|
||||
//
|
||||
|
||||
var params = common.clone(meta) || {};
|
||||
params.timestamp = new Date();
|
||||
params.message = msg;
|
||||
params.level = level;
|
||||
|
||||
req.write(JSON.stringify({
|
||||
method: 'log',
|
||||
params: params
|
||||
}));
|
||||
|
||||
req.end();
|
||||
};
|
||||
106
node_modules/winston/package.json
generated
vendored
Normal file
106
node_modules/winston/package.json
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"winston@0.8.0",
|
||||
"/home/mywebsite/node_modules/broadway"
|
||||
]
|
||||
],
|
||||
"_from": "winston@0.8.0",
|
||||
"_id": "winston@0.8.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/winston",
|
||||
"_npmUser": {
|
||||
"email": "jcrugzz@gmail.com",
|
||||
"name": "jcrugzz"
|
||||
},
|
||||
"_npmVersion": "1.4.23",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "winston",
|
||||
"raw": "winston@0.8.0",
|
||||
"rawSpec": "0.8.0",
|
||||
"scope": null,
|
||||
"spec": "0.8.0",
|
||||
"type": "version"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/broadway",
|
||||
"/cliff"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/winston/-/winston-0.8.0.tgz",
|
||||
"_shasum": "61d0830fa699706212206b0a2b5ca69a93043668",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "winston@0.8.0",
|
||||
"_where": "/home/mywebsite/node_modules/broadway",
|
||||
"author": {
|
||||
"email": "info@nodejitsu.com",
|
||||
"name": "Nodejitsu Inc."
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/flatiron/winston/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "0.2.x",
|
||||
"colors": "0.6.x",
|
||||
"cycle": "1.0.x",
|
||||
"eyes": "0.1.x",
|
||||
"pkginfo": "0.3.x",
|
||||
"stack-trace": "0.0.x"
|
||||
},
|
||||
"description": "A multi-transport async logging library for Node.js",
|
||||
"devDependencies": {
|
||||
"vows": "0.7.x"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "61d0830fa699706212206b0a2b5ca69a93043668",
|
||||
"tarball": "http://registry.npmjs.org/winston/-/winston-0.8.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6.0"
|
||||
},
|
||||
"gitHead": "5ff2673ea37f0122436248968f1e886a14f42c77",
|
||||
"homepage": "https://github.com/flatiron/winston",
|
||||
"keywords": [
|
||||
"logging",
|
||||
"sysadmin",
|
||||
"tools"
|
||||
],
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "https://raw.github.com/flatiron/winston/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"main": "./lib/winston",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "indexzero",
|
||||
"email": "charlie.robbins@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "chjj",
|
||||
"email": "chjjeffrey@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "V1",
|
||||
"email": "info@3rd-Eden.com"
|
||||
},
|
||||
{
|
||||
"name": "jcrugzz",
|
||||
"email": "jcrugzz@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "winston",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/flatiron/winston.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "vows --spec --isolate"
|
||||
},
|
||||
"version": "0.8.0"
|
||||
}
|
||||
40
node_modules/winston/test/cli-test.js
generated
vendored
Normal file
40
node_modules/winston/test/cli-test.js
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* cli-test.js: Tests for the cli levels available in winston.
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var path = require('path'),
|
||||
vows = require('vows'),
|
||||
assert = require('assert'),
|
||||
winston = require('../lib/winston'),
|
||||
helpers = require('./helpers');
|
||||
|
||||
vows.describe('winston/logger/cli').addBatch({
|
||||
"When an instance of winston.Logger": {
|
||||
topic: function () {
|
||||
return new winston.Logger({
|
||||
transports: [
|
||||
new winston.transports.Console()
|
||||
]
|
||||
})
|
||||
},
|
||||
"the cli() method": {
|
||||
"should set the appropriate values on the logger": function (logger) {
|
||||
logger.cli();
|
||||
assert.isTrue(logger.padLevels);
|
||||
assert.isTrue(logger.transports.console.colorize);
|
||||
assert.isFalse(logger.transports.console.timestamp);
|
||||
Object.keys(winston.config.cli.levels).forEach(function (level) {
|
||||
assert.isNumber(logger.levels[level]);
|
||||
});
|
||||
|
||||
Object.keys(winston.config.cli.colors).forEach(function (color) {
|
||||
assert.isString(winston.config.allColors[color]);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
99
node_modules/winston/test/container-test.js
generated
vendored
Normal file
99
node_modules/winston/test/container-test.js
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* container-test.js: Tests for the Container object
|
||||
*
|
||||
* (C) 2011 Charlie Robbins
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var assert = require('assert'),
|
||||
fs = require('fs'),
|
||||
http = require('http'),
|
||||
path = require('path'),
|
||||
vows = require('vows'),
|
||||
winston = require('../lib/winston'),
|
||||
helpers = require('./helpers');
|
||||
|
||||
vows.describe('winston/container').addBatch({
|
||||
"An instance of winston.Container": {
|
||||
topic: new winston.Container(),
|
||||
"the add() method": {
|
||||
topic: function (container) {
|
||||
return container.add('default-test');
|
||||
},
|
||||
"should correctly instantiate a Logger": function (logger) {
|
||||
assert.instanceOf(logger, winston.Logger);
|
||||
},
|
||||
"the get() method": {
|
||||
topic: function (logger, container) {
|
||||
this.callback.apply(this, arguments);
|
||||
},
|
||||
"should respond with the logger previously created": function (existing, container) {
|
||||
var logger = container.get('default-test');
|
||||
assert.isTrue(existing === logger);
|
||||
}
|
||||
},
|
||||
"the has() method": {
|
||||
topic: function (logger, container) {
|
||||
this.callback.apply(this, arguments);
|
||||
},
|
||||
"should indicate `default-test` logger exists": function (existing, container) {
|
||||
assert.isTrue(container.has('default-test'));
|
||||
},
|
||||
"should indicate `not-has` logger doesnt exists": function (existing, container) {
|
||||
assert.isFalse(container.has('not-has'));
|
||||
}
|
||||
},
|
||||
"the close() method": {
|
||||
topic: function (logger, container) {
|
||||
this.callback.apply(this, arguments);
|
||||
},
|
||||
"should remove the specified logger": function (logger, container) {
|
||||
container.close('default-test');
|
||||
assert.isTrue(!container.loggers['default-test']);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"An instance of winston.Container with explicit transports": {
|
||||
topic: function () {
|
||||
this.port = 9412;
|
||||
this.transports = [
|
||||
new winston.transports.Webhook({
|
||||
port: this.port
|
||||
})
|
||||
];
|
||||
|
||||
this.container = new winston.Container({
|
||||
transports: this.transports
|
||||
});
|
||||
|
||||
return null;
|
||||
},
|
||||
"the get() method": {
|
||||
topic: function (container) {
|
||||
var server = http.createServer(function (req, res) {
|
||||
res.end();
|
||||
});
|
||||
|
||||
server.listen(this.port, this.callback.bind(this, null));
|
||||
},
|
||||
"should add the logger correctly": function () {
|
||||
this.someLogger = this.container.get('some-logger');
|
||||
assert.isObject(this.someLogger.transports);
|
||||
assert.instanceOf(this.someLogger.transports['webhook'], winston.transports.Webhook);
|
||||
assert.strictEqual(this.someLogger.transports['webhook'], this.transports[0]);
|
||||
},
|
||||
"a second call to get()": {
|
||||
"should respond with the same transport object": function () {
|
||||
this.someOtherLogger = this.container.get('some-other-logger');
|
||||
|
||||
assert.isObject(this.someOtherLogger.transports);
|
||||
assert.instanceOf(this.someOtherLogger.transports['webhook'], winston.transports.Webhook);
|
||||
assert.strictEqual(this.someOtherLogger.transports['webhook'], this.transports[0]);
|
||||
assert.strictEqual(this.someOtherLogger.transports['webhook'], this.someLogger.transports['webhook']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
62
node_modules/winston/test/custom-timestamp-test.js
generated
vendored
Normal file
62
node_modules/winston/test/custom-timestamp-test.js
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* custom-timestamp-test.js: Test function as timestamp option for transport `{ timestamp: function () {} }`
|
||||
*
|
||||
* (C) 2011 Charlie Robbins, Tom Shinnick
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var assert = require('assert'),
|
||||
events = require('events'),
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
vows = require('vows'),
|
||||
winston = require('../lib/winston'),
|
||||
helpers = require('./helpers');
|
||||
|
||||
function assertTimestamp (basename, options) {
|
||||
var filename = path.join(__dirname, 'fixtures', 'logs', basename + '.log');
|
||||
|
||||
try { fs.unlinkSync(filename) }
|
||||
catch (ex) { }
|
||||
|
||||
return {
|
||||
topic: function () {
|
||||
options.filename = filename;
|
||||
var transport = new (winston.transports.File)(options);
|
||||
|
||||
// We must wait until transport file has emitted the 'flush'
|
||||
// event to be sure the file has been created and written
|
||||
transport.once('flush', this.callback.bind(this, null, filename));
|
||||
transport.log('info', 'When a fake tree falls in the forest...', null, function () {});
|
||||
},
|
||||
"should log with the appropriate timestamp": function (_, filename) {
|
||||
var data = fs.readFileSync(filename, 'utf8');
|
||||
assert.isNotNull(data.match(options.pattern));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vows.describe('winston/transport/timestamp').addBatch({
|
||||
"When timestamp option is used": {
|
||||
"with file transport": {
|
||||
"with value set to false": assertTimestamp('noTimestamp', {
|
||||
pattern: /^info\:/,
|
||||
json: false,
|
||||
timestamp: false
|
||||
}),
|
||||
"with value set to true ": assertTimestamp('defaultTimestamp', {
|
||||
pattern: /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z/,
|
||||
json: false,
|
||||
timestamp: true
|
||||
}),
|
||||
"and function value": assertTimestamp('customTimestamp', {
|
||||
pattern: /^\d{8}\./,
|
||||
json: false,
|
||||
timestamp: function () {
|
||||
return '20110803.171657';
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
47
node_modules/winston/test/exception-test.js
generated
vendored
Normal file
47
node_modules/winston/test/exception-test.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* exception-test.js: Tests for exception data gathering in winston.
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var path = require('path'),
|
||||
vows = require('vows'),
|
||||
assert = require('assert'),
|
||||
winston = require('../lib/winston'),
|
||||
helpers = require('./helpers');
|
||||
|
||||
vows.describe('winston/exception').addBatch({
|
||||
"When using the winston exception module": {
|
||||
"the getProcessInfo() method": {
|
||||
topic: winston.exception.getProcessInfo(),
|
||||
"should respond with the appropriate data": function (info) {
|
||||
helpers.assertProcessInfo(info);
|
||||
}
|
||||
},
|
||||
"the getOsInfo() method": {
|
||||
topic: winston.exception.getOsInfo(),
|
||||
"should respond with the appropriate data": function (info) {
|
||||
helpers.assertOsInfo(info);
|
||||
}
|
||||
},
|
||||
"the getTrace() method": {
|
||||
topic: winston.exception.getTrace(new Error()),
|
||||
"should have the appropriate info": function (trace) {
|
||||
helpers.assertTrace(trace);
|
||||
}
|
||||
},
|
||||
"the getAllInfo() method": {
|
||||
topic: winston.exception.getAllInfo(new Error()),
|
||||
"should have the appropriate info": function (info) {
|
||||
assert.isObject(info);
|
||||
assert.isArray(info.stack);
|
||||
helpers.assertDateInfo(info.date);
|
||||
helpers.assertProcessInfo(info.process);
|
||||
helpers.assertOsInfo(info.os);
|
||||
helpers.assertTrace(info.trace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
0
node_modules/winston/test/fixtures/.gitkeep
generated
vendored
Normal file
0
node_modules/winston/test/fixtures/.gitkeep
generated
vendored
Normal file
13
node_modules/winston/test/fixtures/keys/agent2-cert.pem
generated
vendored
Normal file
13
node_modules/winston/test/fixtures/keys/agent2-cert.pem
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIB7DCCAZYCCQC7gs0MDNn6MTANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJV
|
||||
UzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYDVQQKEwZKb3llbnQxEDAO
|
||||
BgNVBAsTB05vZGUuanMxDzANBgNVBAMTBmFnZW50MjEgMB4GCSqGSIb3DQEJARYR
|
||||
cnlAdGlueWNsb3Vkcy5vcmcwHhcNMTEwMzE0MTgyOTEyWhcNMzgwNzI5MTgyOTEy
|
||||
WjB9MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYD
|
||||
VQQKEwZKb3llbnQxEDAOBgNVBAsTB05vZGUuanMxDzANBgNVBAMTBmFnZW50MjEg
|
||||
MB4GCSqGSIb3DQEJARYRcnlAdGlueWNsb3Vkcy5vcmcwXDANBgkqhkiG9w0BAQEF
|
||||
AANLADBIAkEAyXb8FrRdKbhrKLgLSsn61i1C7w7fVVVd7OQsmV/7p9WB2lWFiDlC
|
||||
WKGU9SiIz/A6wNZDUAuc2E+VwtpCT561AQIDAQABMA0GCSqGSIb3DQEBBQUAA0EA
|
||||
C8HzpuNhFLCI3A5KkBS5zHAQax6TFUOhbpBCR0aTDbJ6F1liDTK1lmU/BjvPoj+9
|
||||
1LHwrmh29rK8kBPEjmymCQ==
|
||||
-----END CERTIFICATE-----
|
||||
9
node_modules/winston/test/fixtures/keys/agent2-key.pem
generated
vendored
Normal file
9
node_modules/winston/test/fixtures/keys/agent2-key.pem
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIBOgIBAAJBAMl2/Ba0XSm4ayi4C0rJ+tYtQu8O31VVXezkLJlf+6fVgdpVhYg5
|
||||
QlihlPUoiM/wOsDWQ1ALnNhPlcLaQk+etQECAwEAAQJBAMT6Bf34+UHKY1ObpsbH
|
||||
9u2jsVblFq1rWvs8GPMY6oertzvwm3DpuSUp7PTgOB1nLTLYtCERbQ4ovtN8tn3p
|
||||
OHUCIQDzIEGsoCr5vlxXvy2zJwu+fxYuhTZWMVuo1397L0VyhwIhANQh+yzqUgaf
|
||||
WRtSB4T2W7ADtJI35ET61jKBty3CqJY3AiAIwju7dVW3A5WeD6Qc1SZGKZvp9yCb
|
||||
AFI2BfVwwaY11wIgXF3PeGcvACMyMWsuSv7aPXHfliswAbkWuzcwA4TW01ECIGWa
|
||||
cgsDvVFxmfM5NPSuT/UDTa6R5BFISB5ea0N0AR3I
|
||||
-----END RSA PRIVATE KEY-----
|
||||
0
node_modules/winston/test/fixtures/logs/.gitkeep
generated
vendored
Normal file
0
node_modules/winston/test/fixtures/logs/.gitkeep
generated
vendored
Normal file
21
node_modules/winston/test/fixtures/scripts/default-exceptions.js
generated
vendored
Normal file
21
node_modules/winston/test/fixtures/scripts/default-exceptions.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* default-exceptions.js: A test fixture for logging exceptions with the default winston logger.
|
||||
*
|
||||
* (C) 2011 Charlie Robbins
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var path = require('path'),
|
||||
winston = require('../../../lib/winston');
|
||||
|
||||
winston.handleExceptions([
|
||||
new (winston.transports.File)({
|
||||
filename: path.join(__dirname, '..', 'logs', 'default-exception.log'),
|
||||
handleExceptions: true
|
||||
})
|
||||
]);
|
||||
|
||||
setTimeout(function () {
|
||||
throw new Error('OH NOES! It failed!');
|
||||
}, 1000);
|
||||
25
node_modules/winston/test/fixtures/scripts/exit-on-error.js
generated
vendored
Normal file
25
node_modules/winston/test/fixtures/scripts/exit-on-error.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* default-exceptions.js: A test fixture for logging exceptions with the default winston logger.
|
||||
*
|
||||
* (C) 2011 Charlie Robbins
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var path = require('path'),
|
||||
winston = require('../../../lib/winston');
|
||||
|
||||
winston.exitOnError = function (err) {
|
||||
return err.message !== 'Ignore this error';
|
||||
};
|
||||
|
||||
winston.handleExceptions([
|
||||
new (winston.transports.File)({
|
||||
filename: path.join(__dirname, '..', 'logs', 'exit-on-error.log'),
|
||||
handleExceptions: true
|
||||
})
|
||||
]);
|
||||
|
||||
setTimeout(function () {
|
||||
throw new Error('Ignore this error');
|
||||
}, 1000);
|
||||
25
node_modules/winston/test/fixtures/scripts/log-exceptions.js
generated
vendored
Normal file
25
node_modules/winston/test/fixtures/scripts/log-exceptions.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* log-exceptions.js: A test fixture for logging exceptions in winston.
|
||||
*
|
||||
* (C) 2011 Charlie Robbins
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var path = require('path'),
|
||||
winston = require('../../../lib/winston');
|
||||
|
||||
var logger = new (winston.Logger)({
|
||||
transports: [
|
||||
new (winston.transports.File)({
|
||||
filename: path.join(__dirname, '..', 'logs', 'exception.log'),
|
||||
handleExceptions: true
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
logger.handleExceptions();
|
||||
|
||||
setTimeout(function () {
|
||||
throw new Error('OH NOES! It failed!');
|
||||
}, 1000);
|
||||
26
node_modules/winston/test/fixtures/scripts/unhandle-exceptions.js
generated
vendored
Normal file
26
node_modules/winston/test/fixtures/scripts/unhandle-exceptions.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* unhandle-exceptions.js: A test fixture for using `.unhandleExceptions()` winston.
|
||||
*
|
||||
* (C) 2011 Charlie Robbins
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var path = require('path'),
|
||||
winston = require('../../../lib/winston');
|
||||
|
||||
var logger = new (winston.Logger)({
|
||||
transports: [
|
||||
new (winston.transports.File)({
|
||||
filename: path.join(__dirname, '..', 'logs', 'unhandle-exception.log'),
|
||||
handleExceptions: true
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
logger.handleExceptions();
|
||||
logger.unhandleExceptions();
|
||||
|
||||
setTimeout(function () {
|
||||
throw new Error('OH NOES! It failed!');
|
||||
}, 1000);
|
||||
183
node_modules/winston/test/helpers.js
generated
vendored
Normal file
183
node_modules/winston/test/helpers.js
generated
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* helpers.js: Test helpers for winston
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var assert = require('assert'),
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
spawn = require('child_process').spawn,
|
||||
util = require('util'),
|
||||
vows = require('vows'),
|
||||
winston = require('../lib/winston');
|
||||
|
||||
var helpers = exports;
|
||||
|
||||
helpers.size = function (obj) {
|
||||
var size = 0, key;
|
||||
for (key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
};
|
||||
|
||||
helpers.tryUnlink = function (file) {
|
||||
try { fs.unlinkSync(file) }
|
||||
catch (ex) { }
|
||||
};
|
||||
|
||||
helpers.assertDateInfo = function (info) {
|
||||
assert.isNumber(Date.parse(info));
|
||||
};
|
||||
|
||||
helpers.assertProcessInfo = function (info) {
|
||||
assert.isNumber(info.pid);
|
||||
assert.isNumber(info.uid);
|
||||
assert.isNumber(info.gid);
|
||||
assert.isString(info.cwd);
|
||||
assert.isString(info.execPath);
|
||||
assert.isString(info.version);
|
||||
assert.isArray(info.argv);
|
||||
assert.isObject(info.memoryUsage);
|
||||
};
|
||||
|
||||
helpers.assertOsInfo = function (info) {
|
||||
assert.isArray(info.loadavg);
|
||||
assert.isNumber(info.uptime);
|
||||
};
|
||||
|
||||
helpers.assertTrace = function (trace) {
|
||||
trace.forEach(function (site) {
|
||||
assert.isTrue(!site.column || typeof site.column === 'number');
|
||||
assert.isTrue(!site.line || typeof site.line === 'number');
|
||||
assert.isTrue(!site.file || typeof site.file === 'string');
|
||||
assert.isTrue(!site.method || typeof site.method === 'string');
|
||||
assert.isTrue(!site.function || typeof site.function === 'string');
|
||||
assert.isTrue(typeof site.native === 'boolean');
|
||||
});
|
||||
};
|
||||
|
||||
helpers.assertLogger = function (logger, level) {
|
||||
assert.instanceOf(logger, winston.Logger);
|
||||
assert.isFunction(logger.log);
|
||||
assert.isFunction(logger.add);
|
||||
assert.isFunction(logger.remove);
|
||||
assert.equal(logger.level, level || "info");
|
||||
Object.keys(logger.levels).forEach(function (method) {
|
||||
assert.isFunction(logger[method]);
|
||||
});
|
||||
};
|
||||
|
||||
helpers.assertConsole = function (transport) {
|
||||
assert.instanceOf(transport, winston.transports.Console);
|
||||
assert.isFunction(transport.log);
|
||||
};
|
||||
|
||||
helpers.assertMemory = function (transport) {
|
||||
assert.instanceOf(transport, winston.transports.Memory);
|
||||
assert.isFunction(transport.log);
|
||||
};
|
||||
|
||||
helpers.assertFile = function (transport) {
|
||||
assert.instanceOf(transport, winston.transports.File);
|
||||
assert.isFunction(transport.log);
|
||||
}
|
||||
|
||||
helpers.assertDailyRotateFile = function (transport) {
|
||||
assert.instanceOf(transport, winston.transports.DailyRotateFile);
|
||||
assert.isFunction(transport.log);
|
||||
}
|
||||
|
||||
helpers.assertWebhook = function (transport) {
|
||||
assert.instanceOf(transport, winston.transports.Webhook);
|
||||
assert.isFunction(transport.log);
|
||||
};
|
||||
|
||||
helpers.assertCouchdb = function (transport) {
|
||||
assert.instanceOf(transport, winston.transports.Couchdb);
|
||||
assert.isFunction(transport.log);
|
||||
};
|
||||
|
||||
helpers.assertHandleExceptions = function (options) {
|
||||
return {
|
||||
topic: function () {
|
||||
var that = this,
|
||||
child = spawn('node', [options.script]);
|
||||
|
||||
helpers.tryUnlink(options.logfile);
|
||||
child.on('exit', function () {
|
||||
fs.readFile(options.logfile, that.callback);
|
||||
});
|
||||
},
|
||||
"should save the error information to the specified file": function (err, data) {
|
||||
assert.isTrue(!err);
|
||||
data = JSON.parse(data);
|
||||
|
||||
assert.isObject(data);
|
||||
helpers.assertProcessInfo(data.process);
|
||||
helpers.assertOsInfo(data.os);
|
||||
helpers.assertTrace(data.trace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
helpers.testNpmLevels = function (transport, assertMsg, assertFn) {
|
||||
return helpers.testLevels(winston.config.npm.levels, transport, assertMsg, assertFn);
|
||||
};
|
||||
|
||||
helpers.testSyslogLevels = function (transport, assertMsg, assertFn) {
|
||||
return helpers.testLevels(winston.config.syslog.levels, transport, assertMsg, assertFn);
|
||||
};
|
||||
|
||||
helpers.testLevels = function (levels, transport, assertMsg, assertFn) {
|
||||
var tests = {};
|
||||
|
||||
Object.keys(levels).forEach(function (level) {
|
||||
var test = {
|
||||
topic: function () {
|
||||
transport.log(level, 'test message', {}, this.callback.bind(this, null));
|
||||
}
|
||||
};
|
||||
|
||||
test[assertMsg] = assertFn;
|
||||
tests['with the ' + level + ' level'] = test;
|
||||
});
|
||||
|
||||
var metadatatest = {
|
||||
topic: function () {
|
||||
transport.log('info', 'test message', { metadata: true }, this.callback.bind(this, null));
|
||||
}
|
||||
};
|
||||
|
||||
metadatatest[assertMsg] = assertFn;
|
||||
tests['when passed metadata'] = metadatatest;
|
||||
|
||||
var primmetadatatest = {
|
||||
topic: function () {
|
||||
transport.log('info', 'test message', 'metadata', this.callback.bind(this, null));
|
||||
}
|
||||
};
|
||||
|
||||
primmetadatatest[assertMsg] = assertFn;
|
||||
tests['when passed primitive metadata'] = primmetadatatest;
|
||||
|
||||
var circmetadata = { };
|
||||
circmetadata['metadata'] = circmetadata;
|
||||
|
||||
var circmetadatatest = {
|
||||
topic: function () {
|
||||
transport.log('info', 'test message', circmetadata, this.callback.bind(this, null));
|
||||
}
|
||||
};
|
||||
|
||||
circmetadatatest[assertMsg] = assertFn;
|
||||
tests['when passed circular metadata'] = circmetadatatest;
|
||||
|
||||
return tests;
|
||||
};
|
||||
60
node_modules/winston/test/log-exception-test.js
generated
vendored
Normal file
60
node_modules/winston/test/log-exception-test.js
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* exception-test.js: Tests for exception data gathering in winston.
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var assert = require('assert'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
spawn = require('child_process').spawn,
|
||||
vows = require('vows'),
|
||||
winston = require('../lib/winston'),
|
||||
helpers = require('./helpers'),
|
||||
exists = (fs.exists || path.exists);
|
||||
|
||||
vows.describe('winston/logger/exceptions').addBatch({
|
||||
"When using winston": {
|
||||
"the handleException() method": {
|
||||
"with a custom winston.Logger instance": helpers.assertHandleExceptions({
|
||||
script: path.join(__dirname, 'fixtures', 'scripts', 'log-exceptions.js'),
|
||||
logfile: path.join(__dirname, 'fixtures', 'logs', 'exception.log')
|
||||
}),
|
||||
"with the default winston logger": helpers.assertHandleExceptions({
|
||||
script: path.join(__dirname, 'fixtures', 'scripts', 'default-exceptions.js'),
|
||||
logfile: path.join(__dirname, 'fixtures', 'logs', 'default-exception.log')
|
||||
}),
|
||||
"when a custom exitOnError function is set": {
|
||||
topic: function () {
|
||||
var that = this,
|
||||
scriptDir = path.join(__dirname, 'fixtures', 'scripts');
|
||||
|
||||
that.child = spawn('node', [path.join(scriptDir, 'exit-on-error.js')]);
|
||||
setTimeout(this.callback.bind(this), 1500);
|
||||
},
|
||||
"should not exit the process": function () {
|
||||
assert.isFalse(this.child.killed);
|
||||
this.child.kill();
|
||||
}
|
||||
}
|
||||
},
|
||||
"the unhandleException() method": {
|
||||
topic: function () {
|
||||
var that = this,
|
||||
child = spawn('node', [path.join(__dirname, 'fixtures', 'scripts', 'unhandle-exceptions.js')]),
|
||||
exception = path.join(__dirname, 'fixtures', 'logs', 'unhandle-exception.log');
|
||||
|
||||
helpers.tryUnlink(exception);
|
||||
child.on('exit', function () {
|
||||
exists(exception, that.callback.bind(this, null));
|
||||
});
|
||||
},
|
||||
"should not write to the specified error file": function (err, exists) {
|
||||
assert.isTrue(!err);
|
||||
assert.isFalse(exists);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
98
node_modules/winston/test/log-rewriter-test.js
generated
vendored
Normal file
98
node_modules/winston/test/log-rewriter-test.js
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* log-rewriter-test.js: Tests for rewriting metadata in winston.
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var assert = require('assert'),
|
||||
vows = require('vows'),
|
||||
winston = require('../lib/winston'),
|
||||
helpers = require('./helpers');
|
||||
|
||||
vows.describe('winston/logger/rewriter').addBatch({
|
||||
"An instance of winston.Logger": {
|
||||
topic: new (winston.Logger)({transports: [
|
||||
new (winston.transports.Console)({ level: 'info' })
|
||||
]}),
|
||||
"the addRewriter() method": {
|
||||
topic: function (logger) {
|
||||
logger.addRewriter(function (level, msg, meta) {
|
||||
meta.level = level;
|
||||
meta.msg = msg;
|
||||
meta.foo = 'bar';
|
||||
return meta;
|
||||
});
|
||||
return logger;
|
||||
},
|
||||
"should add the rewriter": function (logger) {
|
||||
assert.equal(helpers.size(logger.rewriters), 1);
|
||||
},
|
||||
"the log() method": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.log('info', 'test message', {"a": "b"});
|
||||
},
|
||||
"should run the rewriter": function (transport, level, msg, meta) {
|
||||
assert.equal(meta.a, 'b');
|
||||
assert.equal(meta.level, 'info');
|
||||
assert.equal(meta.msg, 'test message');
|
||||
assert.equal(meta.foo, 'bar');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"An instance of winston.Logger with explicit rewriter": {
|
||||
topic: new (winston.Logger)({transports: [
|
||||
new (winston.transports.Console)({ level: 'info'})
|
||||
], rewriters: [
|
||||
function (level, msg, meta) {
|
||||
meta.level = level;
|
||||
meta.msg = msg;
|
||||
meta.foo = 'bar';
|
||||
return meta;
|
||||
}
|
||||
]}),
|
||||
"should add the rewriter": function (logger) {
|
||||
assert.equal(helpers.size(logger.rewriters), 1);
|
||||
},
|
||||
"the log() method": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.log('info', 'test message', {"a": "b"});
|
||||
},
|
||||
"should run the rewriter": function (transport, level, msg, meta) {
|
||||
assert.equal(meta.a, 'b');
|
||||
assert.equal(meta.level, 'info');
|
||||
assert.equal(meta.msg, 'test message');
|
||||
assert.equal(meta.foo, 'bar');
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"An instance of winston.Logger with rewriters": {
|
||||
topic: new (winston.Logger)({transports: [
|
||||
new (winston.transports.Console)({ level: 'info' })
|
||||
], rewriters: [
|
||||
function (level, msg, meta) {
|
||||
meta.numbers.push(1);
|
||||
return meta;
|
||||
},
|
||||
function (level, msg, meta) {
|
||||
meta.numbers.push(2);
|
||||
return meta;
|
||||
}
|
||||
]}),
|
||||
"the log() method": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.log('info', 'test message', {"numbers": [0]});
|
||||
},
|
||||
"should run the rewriters in correct order": function (transport, level, msg, meta) {
|
||||
assert.deepEqual(meta.numbers, [0, 1, 2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
116
node_modules/winston/test/logger-levels-test.js
generated
vendored
Normal file
116
node_modules/winston/test/logger-levels-test.js
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* log-rewriter-test.js: Tests for rewriting metadata in winston.
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var assert = require('assert'),
|
||||
vows = require('vows'),
|
||||
winston = require('../lib/winston'),
|
||||
util = require('util'),
|
||||
helpers = require('./helpers');
|
||||
|
||||
vows.describe('winston/logger/levels').addBatch({
|
||||
"The winston logger": {
|
||||
topic: new (winston.Logger)({
|
||||
transports: [
|
||||
new (winston.transports.Console)()
|
||||
]
|
||||
}),
|
||||
"the info() method": {
|
||||
"when passed metadata": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.info('test message', {foo: 'bar'});
|
||||
},
|
||||
"should have metadata object": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, 'test message');
|
||||
assert.deepEqual(meta, {foo: 'bar'});
|
||||
}
|
||||
}
|
||||
},
|
||||
"when passed a string placeholder": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.info('test message %s', 'my string');
|
||||
},
|
||||
"should interpolate": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, 'test message my string');
|
||||
},
|
||||
},
|
||||
"when passed a number placeholder": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.info('test message %d', 123);
|
||||
},
|
||||
"should interpolate": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, 'test message 123');
|
||||
},
|
||||
},
|
||||
"when passed a json placholder and an empty object": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.info('test message %j', {number: 123}, {});
|
||||
},
|
||||
"should interpolate": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, 'test message {"number":123}');
|
||||
},
|
||||
},
|
||||
"when passed a escaped percent sign": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.info('test message %%', {number: 123});
|
||||
},
|
||||
"should not interpolate": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, util.format('test message %%'));
|
||||
assert.deepEqual(meta, {number: 123});
|
||||
},
|
||||
},
|
||||
"when passed interpolation strings and a meta object": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.info('test message %s, %s', 'first', 'second' ,{number: 123});
|
||||
},
|
||||
"should interpolate and have a meta object": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, 'test message first, second');
|
||||
assert.deepEqual(meta, {number: 123});
|
||||
},
|
||||
},
|
||||
"when passed multiple strings and a meta object": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.info('test message', 'first', 'second' , {number: 123});
|
||||
},
|
||||
"should join and have a meta object": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, 'test message first second');
|
||||
assert.deepEqual(meta, {number: 123});
|
||||
},
|
||||
},
|
||||
"when passed interpolations strings, meta object and a callback": {
|
||||
topic: function (logger) {
|
||||
var that = this;
|
||||
logger.info('test message %s, %s', 'first', 'second' , {number: 123}, function(transport, level, msg, meta){
|
||||
that.callback(transport, level, msg, meta)
|
||||
});
|
||||
},
|
||||
"should interpolate and have a meta object": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, 'test message first, second');
|
||||
assert.deepEqual(meta, {number: 123});
|
||||
},
|
||||
},
|
||||
"when passed multiple strings, a meta object and a callback": {
|
||||
topic: function (logger) {
|
||||
var that = this;
|
||||
logger.info('test message', 'first', 'second' , {number: 123}, function(transport, level, msg, meta){
|
||||
that.callback(transport, level, msg, meta)
|
||||
});
|
||||
},
|
||||
"should join and have a meta object": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, 'test message first second');
|
||||
assert.deepEqual(meta, {number: 123});
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
346
node_modules/winston/test/logger-test.js
generated
vendored
Executable file
346
node_modules/winston/test/logger-test.js
generated
vendored
Executable file
@@ -0,0 +1,346 @@
|
||||
/*
|
||||
* logger-test.js: Tests for instances of the winston Logger
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var path = require('path'),
|
||||
vows = require('vows'),
|
||||
assert = require('assert'),
|
||||
util = require('util'),
|
||||
winston = require('../lib/winston'),
|
||||
helpers = require('./helpers'),
|
||||
transport = require('./transports/transport');
|
||||
|
||||
vows.describe('winton/logger').addBatch({
|
||||
"An instance of winston.Logger": {
|
||||
topic: new (winston.Logger)({ transports: [new (winston.transports.Console)({ level: 'info' })] }),
|
||||
"should have the correct methods / properties defined": function (logger) {
|
||||
helpers.assertLogger(logger);
|
||||
},
|
||||
"the add() with an unsupported transport": {
|
||||
"should throw an error": function () {
|
||||
assert.throws(function () { logger.add('unsupported') }, Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"An instance of winston.Logger": {
|
||||
topic: new (winston.Logger)({ transports: [new (winston.transports.Console)({ level: 'info' })] }),
|
||||
"the log() method": {
|
||||
"when listening for the 'logging' event": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.log('info', 'test message');
|
||||
},
|
||||
"should emit the 'log' event with the appropriate transport": function (transport, ign) {
|
||||
helpers.assertConsole(transport);
|
||||
}
|
||||
},
|
||||
"when listening for the 'logged' event": {
|
||||
topic: function (logger) {
|
||||
logger.once('logged', this.callback);
|
||||
logger.log('info', 'test message');
|
||||
},
|
||||
"should emit the 'logged' event": function (level, msg, meta) {
|
||||
assert.equal(level, 'info');
|
||||
assert.equal(msg, 'test message');
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"An instance of winston.Logger with no transports": {
|
||||
topic: new (winston.Logger)({ emitErrs: true }),
|
||||
"the log() method should throw an error": function (logger) {
|
||||
assert.throws(function () { logger.log('anything') }, Error);
|
||||
},
|
||||
"the extend() method called on an empty object": {
|
||||
topic: function (logger) {
|
||||
var empty = {};
|
||||
logger.extend(empty);
|
||||
return empty;
|
||||
},
|
||||
"should define the appropriate methods": function (extended) {
|
||||
['log', 'profile', 'startTimer'].concat(Object.keys(winston.config.npm.levels)).forEach(function (method) {
|
||||
assert.isFunction(extended[method]);
|
||||
});
|
||||
}
|
||||
},
|
||||
"the add() method with a supported transport": {
|
||||
topic: function (logger) {
|
||||
return logger.add(winston.transports.Console);
|
||||
},
|
||||
"should add the console Transport onto transports": function (logger) {
|
||||
assert.equal(helpers.size(logger.transports), 1);
|
||||
helpers.assertConsole(logger.transports.console);
|
||||
},
|
||||
"should throw an error when the same Transport is added": function (logger) {
|
||||
assert.throws(function () { logger.add(winston.transports.Console) }, Error);
|
||||
},
|
||||
"the profile() method": {
|
||||
"when passed a callback": {
|
||||
topic: function (logger) {
|
||||
var cb = this.callback;
|
||||
logger.profile('test1');
|
||||
setTimeout(function () {
|
||||
logger.profile('test1', function (err, level, msg, meta) {
|
||||
cb(err, level, msg, meta, logger);
|
||||
});
|
||||
}, 50);
|
||||
},
|
||||
"should respond with the appropriate profile message": function (err, level, msg, meta, logger) {
|
||||
assert.isNull(err);
|
||||
assert.equal(level, 'info');
|
||||
assert.match(meta.duration, /(\d+)ms/);
|
||||
assert.isTrue(typeof logger.profilers['test'] === 'undefined');
|
||||
},
|
||||
"when passed some metadata": {
|
||||
topic: function () {
|
||||
var logger = arguments[arguments.length - 1];
|
||||
var cb = this.callback.bind(null, null);
|
||||
logger.profile('test3');
|
||||
setTimeout(function () {
|
||||
logger.once('logging', cb);
|
||||
logger.profile('test3', {
|
||||
some: 'data'
|
||||
});
|
||||
}, 50);
|
||||
},
|
||||
"should respond with the right metadata": function (err, transport, level, msg, meta) {
|
||||
assert.equal(msg, 'test3');
|
||||
assert.isNull(err);
|
||||
assert.equal(level, 'info');
|
||||
assert.match(meta.duration, /(\d+)ms/);
|
||||
assert.equal(meta.some, 'data');
|
||||
},
|
||||
"when not passed a callback": {
|
||||
topic: function () {
|
||||
var logger = arguments[arguments.length - 1];
|
||||
var cb = this.callback.bind(null, null);
|
||||
logger.profile('test2');
|
||||
setTimeout(function () {
|
||||
logger.once('logging', cb);
|
||||
logger.profile('test2');
|
||||
}, 50);
|
||||
},
|
||||
"should respond with the appropriate profile message": function (err, transport, level, msg, meta) {
|
||||
assert.isNull(err);
|
||||
assert.equal(msg, 'test2');
|
||||
assert.equal(level, 'info');
|
||||
assert.match(meta.duration, /(\d+)ms/);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"the startTimer() method": {
|
||||
"when passed a callback": {
|
||||
topic: function (logger) {
|
||||
var that = this;
|
||||
var timer = logger.startTimer()
|
||||
setTimeout(function () {
|
||||
timer.done('test', function (err, level, msg, meta) {
|
||||
that.callback(err, level, msg, meta, logger);
|
||||
});
|
||||
}, 1000);
|
||||
},
|
||||
"should respond with the appropriate message": function (err, level, msg, meta, logger) {
|
||||
assert.isNull(err);
|
||||
assert.equal(level, 'info');
|
||||
assert.match(meta.duration, /(\d+)ms/);
|
||||
}
|
||||
},
|
||||
"when not passed a callback": {
|
||||
topic: function (logger) {
|
||||
var that = this;
|
||||
var timer = logger.startTimer()
|
||||
logger.once('logging', that.callback.bind(null, null));
|
||||
setTimeout(function () {
|
||||
timer.done();
|
||||
}, 1000);
|
||||
},
|
||||
"should respond with the appropriate message": function (err, transport, level, msg, meta) {
|
||||
assert.isNull(err);
|
||||
assert.equal(level, 'info');
|
||||
assert.match(meta.duration, /(\d+)ms/);
|
||||
|
||||
var duration = parseInt(meta.duration);
|
||||
assert.isNumber(duration);
|
||||
assert.isTrue(duration >= 50 && duration < 100);
|
||||
}
|
||||
}
|
||||
},
|
||||
"and adding an additional transport": {
|
||||
topic: function (logger) {
|
||||
return logger.add(winston.transports.File, {
|
||||
filename: path.join(__dirname, 'fixtures', 'logs', 'testfile2.log')
|
||||
});
|
||||
},
|
||||
"should be able to add multiple transports": function (logger) {
|
||||
assert.equal(helpers.size(logger.transports), 2);
|
||||
helpers.assertConsole(logger.transports.console);
|
||||
helpers.assertFile(logger.transports.file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"The winston logger": {
|
||||
topic: new (winston.Logger)({
|
||||
transports: [
|
||||
new (winston.transports.Console)(),
|
||||
new (winston.transports.File)({ filename: path.join(__dirname, 'fixtures', 'logs', 'filelog.log' )})
|
||||
]
|
||||
}),
|
||||
"should return have two transports": function (logger) {
|
||||
assert.equal(helpers.size(logger.transports), 2);
|
||||
},
|
||||
"the remove() with an unadded transport": {
|
||||
"should throw an Error": function (logger) {
|
||||
assert.throws(function () { logger.remove(winston.transports.Webhook) }, Error);
|
||||
}
|
||||
},
|
||||
"the remove() method with an added transport": {
|
||||
topic: function (logger) {
|
||||
return logger.remove(winston.transports.Console);
|
||||
},
|
||||
"should remove the Console transport from transports": function (logger) {
|
||||
assert.equal(helpers.size(logger.transports), 1);
|
||||
helpers.assertFile(logger.transports.file);
|
||||
},
|
||||
"and removing an additional transport": {
|
||||
topic: function (logger) {
|
||||
return logger.remove(winston.transports.File);
|
||||
},
|
||||
"should remove File transport from transports": function (logger) {
|
||||
assert.equal(helpers.size(logger.transports), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"The winston logger": {
|
||||
topic: new (winston.Logger)({
|
||||
transports: [
|
||||
new (winston.transports.Console)(),
|
||||
new (winston.transports.File)({ filename: path.join(__dirname, 'fixtures', 'logs', 'filelog.log' )})
|
||||
]
|
||||
}),
|
||||
"the clear() method": {
|
||||
"should remove all transports": function (logger) {
|
||||
logger.clear();
|
||||
assert.equal(helpers.size(logger.transports), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"The winston logger": {
|
||||
topic: new (winston.Logger)({
|
||||
exceptionHandlers: [
|
||||
new (winston.transports.Console)(),
|
||||
new (winston.transports.File)({ filename: path.join(__dirname, 'fixtures', 'logs', 'filelog.log' )})
|
||||
]
|
||||
}),
|
||||
"the unhandleExceptions() method": {
|
||||
"should remove all transports": function (logger) {
|
||||
assert.equal(helpers.size(logger.exceptionHandlers), 2);
|
||||
logger.unhandleExceptions();
|
||||
assert.equal(helpers.size(logger.exceptionHandlers), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"The winston logger": {
|
||||
topic: new (winston.Logger)({
|
||||
transports: [
|
||||
new (winston.transports.Console)()
|
||||
]
|
||||
}),
|
||||
"the log() method": {
|
||||
"when passed a string placeholder": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.log('info', 'test message %s', 'my string');
|
||||
},
|
||||
"should interpolate": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, 'test message my string');
|
||||
},
|
||||
},
|
||||
"when passed a number placeholder": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.log('info', 'test message %d', 123);
|
||||
},
|
||||
"should interpolate": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, 'test message 123');
|
||||
},
|
||||
},
|
||||
"when passed a json placholder and an empty object": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.log('info', 'test message %j', {number: 123}, {});
|
||||
},
|
||||
"should interpolate": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, 'test message {"number":123}');
|
||||
},
|
||||
},
|
||||
"when passed a escaped percent sign": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.log('info', 'test message %%', {number: 123});
|
||||
},
|
||||
"should not interpolate": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, util.format('test message %%'));
|
||||
assert.deepEqual(meta, {number: 123});
|
||||
},
|
||||
},
|
||||
"when passed interpolation strings and a meta object": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.log('info', 'test message %s, %s', 'first', 'second' ,{number: 123});
|
||||
},
|
||||
"should interpolate and have a meta object": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, 'test message first, second');
|
||||
assert.deepEqual(meta, {number: 123});
|
||||
},
|
||||
},
|
||||
"when passed multiple strings and a meta object": {
|
||||
topic: function (logger) {
|
||||
logger.once('logging', this.callback);
|
||||
logger.log('info', 'test message', 'first', 'second' , {number: 123});
|
||||
},
|
||||
"should join and have a meta object": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, 'test message first second');
|
||||
assert.deepEqual(meta, {number: 123});
|
||||
},
|
||||
},
|
||||
"when passed interpolations strings, meta object and a callback": {
|
||||
topic: function (logger) {
|
||||
var that = this;
|
||||
logger.log('info', 'test message %s, %s', 'first', 'second' , {number: 123}, function(transport, level, msg, meta){
|
||||
that.callback(transport, level, msg, meta)
|
||||
});
|
||||
},
|
||||
"should interpolate and have a meta object": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, 'test message first, second');
|
||||
assert.deepEqual(meta, {number: 123});
|
||||
},
|
||||
},
|
||||
"when passed multiple strings, a meta object and a callback": {
|
||||
topic: function (logger) {
|
||||
var that = this;
|
||||
logger.log('info', 'test message', 'first', 'second' , {number: 123}, function(transport, level, msg, meta){
|
||||
that.callback(transport, level, msg, meta)
|
||||
});
|
||||
},
|
||||
"should join and have a meta object": function (transport, level, msg, meta) {
|
||||
assert.strictEqual(msg, 'test message first second');
|
||||
assert.deepEqual(meta, {number: 123});
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
39
node_modules/winston/test/transports/console-test.js
generated
vendored
Normal file
39
node_modules/winston/test/transports/console-test.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* console-test.js: Tests for instances of the Console transport
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var path = require('path'),
|
||||
vows = require('vows'),
|
||||
assert = require('assert'),
|
||||
winston = require('../../lib/winston'),
|
||||
helpers = require('../helpers');
|
||||
|
||||
var npmTransport = new (winston.transports.Console)(),
|
||||
syslogTransport = new (winston.transports.Console)({ levels: winston.config.syslog.levels });
|
||||
|
||||
vows.describe('winston/transports/console').addBatch({
|
||||
"An instance of the Console Transport": {
|
||||
"with npm levels": {
|
||||
"should have the proper methods defined": function () {
|
||||
helpers.assertConsole(npmTransport);
|
||||
},
|
||||
"the log() method": helpers.testNpmLevels(npmTransport, "should respond with true", function (ign, err, logged) {
|
||||
assert.isNull(err);
|
||||
assert.isTrue(logged);
|
||||
})
|
||||
},
|
||||
"with syslog levels": {
|
||||
"should have the proper methods defined": function () {
|
||||
helpers.assertConsole(syslogTransport);
|
||||
},
|
||||
"the log() method": helpers.testSyslogLevels(syslogTransport, "should respond with true", function (ign, err, logged) {
|
||||
assert.isNull(err);
|
||||
assert.isTrue(logged);
|
||||
})
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
62
node_modules/winston/test/transports/daily-rotate-file-test.js
generated
vendored
Normal file
62
node_modules/winston/test/transports/daily-rotate-file-test.js
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* file-test.js: Tests for instances of the Daily Rotate File transport
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var path = require('path'),
|
||||
vows = require('vows'),
|
||||
fs = require('fs'),
|
||||
assert = require('assert'),
|
||||
winston = require('../../lib/winston'),
|
||||
helpers = require('../helpers');
|
||||
|
||||
var transport = require('./transport');
|
||||
|
||||
var stream = fs.createWriteStream(
|
||||
path.join(__dirname, '..', 'fixtures', 'logs', 'testfile.log.2012-12-18')
|
||||
),
|
||||
dailyRotateFileTransport = new (winston.transports.DailyRotateFile)({
|
||||
filename: path.join(__dirname, '..', 'fixtures', 'logs', 'testfilename.log'),
|
||||
datePattern: '.yyyy-MM-dd'
|
||||
}),
|
||||
streamTransport = new (winston.transports.DailyRotateFile)({ stream: stream });
|
||||
|
||||
vows.describe('winston/transports/daily-rotate-file').addBatch({
|
||||
"An instance of the Daily Rotate File Transport": {
|
||||
"when passed a valid filename": {
|
||||
"should have the proper methods defined": function () {
|
||||
helpers.assertDailyRotateFile(dailyRotateFileTransport);
|
||||
},
|
||||
"the log() method": helpers.testNpmLevels(dailyRotateFileTransport, "should respond with true", function (ign, err, logged) {
|
||||
assert.isNull(err);
|
||||
assert.isTrue(logged);
|
||||
})
|
||||
},
|
||||
"when passed a valid file stream": {
|
||||
"should have the proper methods defined": function () {
|
||||
helpers.assertDailyRotateFile(streamTransport);
|
||||
},
|
||||
"the log() method": helpers.testNpmLevels(streamTransport, "should respond with true", function (ign, err, logged) {
|
||||
assert.isNull(err);
|
||||
assert.isTrue(logged);
|
||||
})
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"These tests have a non-deterministic end": {
|
||||
topic: function () {
|
||||
setTimeout(this.callback, 200);
|
||||
},
|
||||
"and this should be fixed before releasing": function () {
|
||||
assert.isTrue(true);
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"An instance of the Daily Rotate File Transport": transport(winston.transports.DailyRotateFile, {
|
||||
filename: path.join(__dirname, '..', 'fixtures', 'logs', 'testfile.log'),
|
||||
datePattern: '.2012-12-18'
|
||||
})
|
||||
}).export(module);
|
||||
102
node_modules/winston/test/transports/file-maxfiles-test.js
generated
vendored
Normal file
102
node_modules/winston/test/transports/file-maxfiles-test.js
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* file-maxfiles-test.js: Tests for instances of the File transport setting the max file size,
|
||||
* and setting a number for max files created.
|
||||
* maxSize * maxFiles = total storage used by winston.
|
||||
*
|
||||
* (C) 2011 Daniel Aristizabal
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var assert = require('assert'),
|
||||
exec = require('child_process').exec,
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
vows = require('vows'),
|
||||
winston = require('../../lib/winston'),
|
||||
helpers = require('../helpers');
|
||||
|
||||
var maxfilesTransport = new winston.transports.File({
|
||||
timestamp: false,
|
||||
json: false,
|
||||
filename: path.join(__dirname, '..', 'fixtures', 'logs', 'testmaxfiles.log'),
|
||||
maxsize: 4096,
|
||||
maxFiles: 3
|
||||
});
|
||||
|
||||
vows.describe('winston/transports/file/maxfiles').addBatch({
|
||||
"An instance of the File Transport": {
|
||||
"when passed a valid filename": {
|
||||
topic: maxfilesTransport,
|
||||
"should be a valid transporter": function (transportTest) {
|
||||
helpers.assertFile(transportTest);
|
||||
},
|
||||
"should set the maxFiles option correctly": function (transportTest) {
|
||||
assert.isNumber(transportTest.maxFiles);
|
||||
}
|
||||
},
|
||||
"when delete old test files": {
|
||||
topic: function () {
|
||||
exec('rm -rf ' + path.join(__dirname, '..', 'fixtures', 'logs', 'testmaxfiles*'), this.callback);
|
||||
},
|
||||
"and when passed more files than the maxFiles": {
|
||||
topic: function () {
|
||||
var that = this,
|
||||
created = 0;
|
||||
|
||||
function data(ch) {
|
||||
return new Array(1018).join(String.fromCharCode(65 + ch));
|
||||
};
|
||||
|
||||
function logKbytes(kbytes, txt) {
|
||||
//
|
||||
// With no timestamp and at the info level,
|
||||
// winston adds exactly 7 characters:
|
||||
// [info](4)[ :](2)[\n](1)
|
||||
//
|
||||
for (var i = 0; i < kbytes; i++) {
|
||||
maxfilesTransport.log('info', data(txt), null, function () { });
|
||||
}
|
||||
}
|
||||
|
||||
maxfilesTransport.on('logged', function () {
|
||||
if (++created === 6) {
|
||||
return that.callback();
|
||||
}
|
||||
|
||||
logKbytes(4, created);
|
||||
});
|
||||
|
||||
logKbytes(4, created);
|
||||
},
|
||||
"should be only 3 files called 5.log, 4.log and 3.log": function () {
|
||||
for (var num = 0; num < 6; num++) {
|
||||
var file = !num ? 'testmaxfiles.log' : 'testmaxfiles' + num + '.log',
|
||||
fullpath = path.join(__dirname, '..', 'fixtures', 'logs', file);
|
||||
|
||||
// There should be no files with that name
|
||||
if (num >= 0 && num < 3) {
|
||||
return assert.throws(function () {
|
||||
fs.statSync(file);
|
||||
}, Error);
|
||||
}
|
||||
|
||||
// The other files should be exist
|
||||
assert.doesNotThrow(function () {
|
||||
fs.statSync(file);
|
||||
}, Error);
|
||||
}
|
||||
},
|
||||
"should have the correct content": function () {
|
||||
['D', 'E', 'F'].forEach(function (name, inx) {
|
||||
var counter = inx + 3,
|
||||
logsDir = path.join(__dirname, '..', 'fixtures', 'logs'),
|
||||
content = fs.readFileSync(path.join(logsDir, 'testmaxfiles' + counter + '.log'), 'utf-8');
|
||||
// The content minus the 7 characters added by winston
|
||||
assert.lengthOf(content.match(new RegExp(name, 'g')), 4068);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
82
node_modules/winston/test/transports/file-maxsize-test.js
generated
vendored
Normal file
82
node_modules/winston/test/transports/file-maxsize-test.js
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* file-test.js: Tests for instances of the File transport
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var assert = require('assert'),
|
||||
exec = require('child_process').exec,
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
vows = require('vows'),
|
||||
winston = require('../../lib/winston'),
|
||||
helpers = require('../helpers');
|
||||
|
||||
var maxsizeTransport = new winston.transports.File({
|
||||
timestamp: false,
|
||||
json: false,
|
||||
filename: path.join(__dirname, '..', 'fixtures', 'logs', 'testmaxsize.log'),
|
||||
maxsize: 4096
|
||||
});
|
||||
|
||||
vows.describe('winston/transports/file/maxsize').addBatch({
|
||||
"An instance of the File Transport": {
|
||||
"when passed a valid filename": {
|
||||
"the log() method": {
|
||||
topic: function () {
|
||||
exec('rm -rf ' + path.join(__dirname, '..', 'fixtures', 'logs', 'testmaxsize*'), this.callback);
|
||||
},
|
||||
"when passed more than the maxsize": {
|
||||
topic: function () {
|
||||
var that = this,
|
||||
data = new Array(1018).join('-');
|
||||
|
||||
//
|
||||
// Setup a list of files which we will later stat.
|
||||
//
|
||||
that.files = [];
|
||||
|
||||
function logKbytes (kbytes) {
|
||||
//
|
||||
// With no timestamp and at the info level,
|
||||
// winston adds exactly 7 characters:
|
||||
// [info](4)[ :](2)[\n](1)
|
||||
//
|
||||
for (var i = 0; i < kbytes; i++) {
|
||||
maxsizeTransport.log('info', data, null, function () { });
|
||||
}
|
||||
}
|
||||
|
||||
maxsizeTransport.on('open', function (file) {
|
||||
var match = file.match(/(\d+)\.log$/),
|
||||
count = match ? match[1] : 0;
|
||||
|
||||
that.files.push(file);
|
||||
|
||||
if (that.files.length === 5) {
|
||||
return that.callback();
|
||||
}
|
||||
|
||||
logKbytes(4);
|
||||
});
|
||||
|
||||
logKbytes(4);
|
||||
},
|
||||
"should create multiple files correctly": function () {
|
||||
this.files.forEach(function (file) {
|
||||
try {
|
||||
var stats = fs.statSync(file);
|
||||
assert.equal(stats.size, 4096);
|
||||
}
|
||||
catch (ex) {
|
||||
assert.isNull(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
61
node_modules/winston/test/transports/file-open-test.js
generated
vendored
Normal file
61
node_modules/winston/test/transports/file-open-test.js
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* file-open-test.js: Tests for File transport "open" event
|
||||
*
|
||||
* (C) 2014 William Wong
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
!function (assert, fs, os, path, vows, winston) {
|
||||
'use strict';
|
||||
|
||||
vows.describe('winston/transports/file').addBatch({
|
||||
'An instance of the File Transport': {
|
||||
topic: function () {
|
||||
var callback = this.callback.bind(this),
|
||||
logPath = path.resolve(__dirname, '../fixtures/logs/file-open-test.log');
|
||||
|
||||
try {
|
||||
fs.unlinkSync(logPath);
|
||||
} catch (ex) {
|
||||
if (ex && ex.code !== 'ENOENT') { return callback(ex); }
|
||||
}
|
||||
|
||||
var fileTransport = new (winston.transports.File)({
|
||||
filename: logPath
|
||||
}),
|
||||
logger = new (winston.Logger)({
|
||||
transports: [fileTransport]
|
||||
}),
|
||||
timeline = {};
|
||||
|
||||
fileTransport.open(function () {
|
||||
timeline.open = Date.now();
|
||||
|
||||
setTimeout(function () {
|
||||
logger.info('Hello, World!', function () {
|
||||
timeline.logged = Date.now();
|
||||
});
|
||||
}, 100);
|
||||
|
||||
setTimeout(function () {
|
||||
callback(null, timeline);
|
||||
}, 1000);
|
||||
});
|
||||
},
|
||||
'should fire "open" event': function (results) {
|
||||
assert.isTrue(!!results.open);
|
||||
},
|
||||
'should fire "logged" event': function (results) {
|
||||
assert.isTrue(!!results.logged);
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
}(
|
||||
require('assert'),
|
||||
require('fs'),
|
||||
require('os'),
|
||||
require('path'),
|
||||
require('vows'),
|
||||
require('../../lib/winston')
|
||||
);
|
||||
76
node_modules/winston/test/transports/file-stress-test.js
generated
vendored
Normal file
76
node_modules/winston/test/transports/file-stress-test.js
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* file-stress-test.js: Tests for stressing File transport
|
||||
*
|
||||
* (C) 2014 William Wong
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
!function (assert, fs, os, path, vows, winston) {
|
||||
'use strict';
|
||||
|
||||
vows.describe('winston/transports/file').addBatch({
|
||||
'A stressed instance of the File Transport': {
|
||||
topic: function () {
|
||||
var callback = this.callback.bind(this),
|
||||
logPath = path.resolve(__dirname, '../fixtures/logs/file-stress-test.log');
|
||||
|
||||
try {
|
||||
fs.unlinkSync(logPath);
|
||||
} catch (ex) {
|
||||
if (ex && ex.code !== 'ENOENT') { return callback(ex); }
|
||||
}
|
||||
|
||||
var fileTransport = new (winston.transports.File)({
|
||||
filename: logPath
|
||||
}),
|
||||
logger = new (winston.Logger)({
|
||||
transports: [fileTransport]
|
||||
});
|
||||
|
||||
fileTransport.on('open', function () {
|
||||
setTimeout(function () {
|
||||
clearInterval(interval);
|
||||
|
||||
logger.query({ order: 'asc' }, function (err, results) {
|
||||
callback(null, results);
|
||||
});
|
||||
}, 100);
|
||||
});
|
||||
|
||||
var logIndex = 0,
|
||||
interval = setInterval(function () {
|
||||
logger.info(++logIndex);
|
||||
stress(200);
|
||||
}, 0);
|
||||
|
||||
logger.info(++logIndex);
|
||||
stress(200);
|
||||
|
||||
function stress(duration) {
|
||||
var startTime = Date.now();
|
||||
|
||||
while (Date.now() - startTime < duration) {
|
||||
Math.sqrt(Math.PI);
|
||||
}
|
||||
}
|
||||
},
|
||||
'should not skip any log lines': function (results) {
|
||||
var testIndex = 0;
|
||||
|
||||
results.file.forEach(function (log) {
|
||||
if (+log.message !== ++testIndex) {
|
||||
throw new Error('Number skipped');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
}(
|
||||
require('assert'),
|
||||
require('fs'),
|
||||
require('os'),
|
||||
require('path'),
|
||||
require('vows'),
|
||||
require('../../lib/winston')
|
||||
);
|
||||
60
node_modules/winston/test/transports/file-test.js
generated
vendored
Normal file
60
node_modules/winston/test/transports/file-test.js
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* file-test.js: Tests for instances of the File transport
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var path = require('path'),
|
||||
vows = require('vows'),
|
||||
fs = require('fs'),
|
||||
assert = require('assert'),
|
||||
winston = require('../../lib/winston'),
|
||||
helpers = require('../helpers');
|
||||
|
||||
var transport = require('./transport');
|
||||
|
||||
var stream = fs.createWriteStream(
|
||||
path.join(__dirname, '..', 'fixtures', 'logs', 'testfile.log')
|
||||
),
|
||||
fileTransport = new (winston.transports.File)({
|
||||
filename: path.join(__dirname, '..', 'fixtures', 'logs', 'testfilename.log')
|
||||
}),
|
||||
streamTransport = new (winston.transports.File)({ stream: stream });
|
||||
|
||||
vows.describe('winston/transports/file').addBatch({
|
||||
"An instance of the File Transport": {
|
||||
"when passed a valid filename": {
|
||||
"should have the proper methods defined": function () {
|
||||
helpers.assertFile(fileTransport);
|
||||
},
|
||||
"the log() method": helpers.testNpmLevels(fileTransport, "should respond with true", function (ign, err, logged) {
|
||||
assert.isNull(err);
|
||||
assert.isTrue(logged);
|
||||
})
|
||||
},
|
||||
"when passed a valid file stream": {
|
||||
"should have the proper methods defined": function () {
|
||||
helpers.assertFile(streamTransport);
|
||||
},
|
||||
"the log() method": helpers.testNpmLevels(streamTransport, "should respond with true", function (ign, err, logged) {
|
||||
assert.isNull(err);
|
||||
assert.isTrue(logged);
|
||||
})
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"These tests have a non-deterministic end": {
|
||||
topic: function () {
|
||||
setTimeout(this.callback, 200);
|
||||
},
|
||||
"and this should be fixed before releasing": function () {
|
||||
assert.isTrue(true);
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"An instance of the File Transport": transport(winston.transports.File, {
|
||||
filename: path.join(__dirname, '..', 'fixtures', 'logs', 'testfile.log')
|
||||
})
|
||||
}).export(module);
|
||||
31
node_modules/winston/test/transports/memory-test.js
generated
vendored
Normal file
31
node_modules/winston/test/transports/memory-test.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
var path = require('path'),
|
||||
vows = require('vows'),
|
||||
assert = require('assert'),
|
||||
winston = require('../../lib/winston'),
|
||||
helpers = require('../helpers');
|
||||
|
||||
var npmTransport = new (winston.transports.Memory)(),
|
||||
syslogTransport = new (winston.transports.Memory)({ levels: winston.config.syslog.levels });
|
||||
|
||||
vows.describe('winston/transports/memory').addBatch({
|
||||
"An instance of the Memory Transport": {
|
||||
"with npm levels": {
|
||||
"should have the proper methods defined": function () {
|
||||
helpers.assertMemory(npmTransport);
|
||||
},
|
||||
"the log() method": helpers.testNpmLevels(npmTransport, "should respond with true", function (ign, err, logged) {
|
||||
assert.isNull(err);
|
||||
assert.isTrue(logged);
|
||||
})
|
||||
},
|
||||
"with syslog levels": {
|
||||
"should have the proper methods defined": function () {
|
||||
helpers.assertMemory(syslogTransport);
|
||||
},
|
||||
"the log() method": helpers.testSyslogLevels(syslogTransport, "should respond with true", function (ign, err, logged) {
|
||||
assert.isNull(err);
|
||||
assert.isTrue(logged);
|
||||
})
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
215
node_modules/winston/test/transports/transport.js
generated
vendored
Normal file
215
node_modules/winston/test/transports/transport.js
generated
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
var assert = require('assert'),
|
||||
winston = require('../../lib/winston'),
|
||||
helpers = require('../helpers');
|
||||
|
||||
module.exports = function (transport, options) {
|
||||
var logger = transport instanceof winston.Logger
|
||||
? transport
|
||||
: new winston.Logger({
|
||||
transports: [
|
||||
new transport(options)
|
||||
]
|
||||
});
|
||||
|
||||
// hack to fix transports that don't log
|
||||
// any unit of time smaller than seconds
|
||||
var common = require('../../lib/winston/common');
|
||||
common.timestamp = function() {
|
||||
return new Date().toISOString();
|
||||
};
|
||||
|
||||
var transport = logger.transports[logger._names[0]];
|
||||
|
||||
var out = {
|
||||
'topic': logger,
|
||||
'when passed valid options': {
|
||||
'should have the proper methods defined': function () {
|
||||
switch (transport.name) {
|
||||
case 'console':
|
||||
helpers.assertConsole(transport);
|
||||
break;
|
||||
case 'file':
|
||||
helpers.assertFile(transport);
|
||||
break;
|
||||
case 'webhook':
|
||||
helpers.assertWebhook(transport);
|
||||
break;
|
||||
case 'couchdb':
|
||||
helpers.assertCouchdb(transport);
|
||||
break;
|
||||
}
|
||||
assert.isFunction(transport.log);
|
||||
}
|
||||
},
|
||||
'the log() method': helpers.testNpmLevels(transport,
|
||||
'should respond with true', function (ign, err, logged) {
|
||||
assert.isNull(err);
|
||||
assert.isNotNull(logged);
|
||||
}
|
||||
),
|
||||
'the stream() method': {
|
||||
'using no options': {
|
||||
'topic': function () {
|
||||
if (!transport.stream) return;
|
||||
|
||||
logger.log('info', 'hello world', {});
|
||||
|
||||
var cb = this.callback,
|
||||
j = 10,
|
||||
i = 10,
|
||||
results = [],
|
||||
stream = logger.stream();
|
||||
|
||||
stream.on('log', function (log) {
|
||||
results.push(log);
|
||||
results.stream = stream;
|
||||
if (!--j) cb(null, results);
|
||||
});
|
||||
|
||||
stream.on('error', function (err) {
|
||||
j = -1; //don't call the callback again
|
||||
cb(err);
|
||||
});
|
||||
|
||||
while (i--) logger.log('info', 'hello world ' + i, {});
|
||||
},
|
||||
'should stream logs': function (err, results) {
|
||||
if (!transport.stream) return;
|
||||
assert.isNull(err);
|
||||
results.forEach(function (log) {
|
||||
assert.ok(log.message.indexOf('hello world') === 0
|
||||
|| log.message.indexOf('test message') === 0);
|
||||
});
|
||||
results.stream.destroy();
|
||||
}
|
||||
},
|
||||
'using the `start` option': {
|
||||
'topic': function () {
|
||||
if (!transport.stream) return;
|
||||
|
||||
var cb = this.callback,
|
||||
stream = logger.stream({ start: 0 });
|
||||
|
||||
stream.on('log', function (log) {
|
||||
log.stream = stream;
|
||||
if (cb) cb(null, log);
|
||||
cb = null;
|
||||
});
|
||||
},
|
||||
'should stream logs': function (err, log) {
|
||||
if (!transport.stream) return;
|
||||
assert.isNull(err);
|
||||
assert.isNotNull(log.message);
|
||||
log.stream.destroy();
|
||||
}
|
||||
}
|
||||
},
|
||||
'after the logs have flushed': {
|
||||
topic: function () {
|
||||
setTimeout(this.callback, 1000);
|
||||
},
|
||||
'the query() method': {
|
||||
'using basic querying': {
|
||||
'topic': function () {
|
||||
if (!transport.query) return;
|
||||
var cb = this.callback;
|
||||
logger.log('info', 'hello world', {}, function () {
|
||||
logger.query(cb);
|
||||
});
|
||||
},
|
||||
'should return matching results': function (err, results) {
|
||||
if (!transport.query) return;
|
||||
assert.isNull(err);
|
||||
results = results[transport.name];
|
||||
while (!Array.isArray(results)) {
|
||||
results = results[Object.keys(results).pop()];
|
||||
}
|
||||
var log = results.pop();
|
||||
assert.ok(log.message.indexOf('hello world') === 0
|
||||
|| log.message.indexOf('test message') === 0);
|
||||
}
|
||||
},
|
||||
'using the `rows` option': {
|
||||
'topic': function () {
|
||||
if (!transport.query) return;
|
||||
var cb = this.callback;
|
||||
logger.log('info', 'hello world', {}, function () {
|
||||
logger.query({ rows: 1 }, cb);
|
||||
});
|
||||
},
|
||||
'should return one result': function (err, results) {
|
||||
if (!transport.query) return;
|
||||
assert.isNull(err);
|
||||
results = results[transport.name];
|
||||
while (!Array.isArray(results)) {
|
||||
results = results[Object.keys(results).pop()];
|
||||
}
|
||||
assert.equal(results.length, 1);
|
||||
}
|
||||
},
|
||||
'using `fields` and `order` option': {
|
||||
'topic': function () {
|
||||
if (!transport.query) return;
|
||||
var cb = this.callback;
|
||||
logger.log('info', 'hello world', {}, function () {
|
||||
logger.query({ order: 'asc', fields: ['timestamp'] }, cb);
|
||||
});
|
||||
},
|
||||
'should return matching results': function (err, results) {
|
||||
if (!transport.query) return;
|
||||
assert.isNull(err);
|
||||
results = results[transport.name];
|
||||
while (!Array.isArray(results)) {
|
||||
results = results[Object.keys(results).pop()];
|
||||
}
|
||||
assert.equal(Object.keys(results[0]).length, 1);
|
||||
assert.ok(new Date(results.shift().timestamp)
|
||||
< new Date(results.pop().timestamp));
|
||||
}
|
||||
},
|
||||
'using the `from` and `until` option': {
|
||||
'topic': function () {
|
||||
if (!transport.query) return;
|
||||
var cb = this.callback;
|
||||
var start = new Date - 100 * 1000;
|
||||
var end = new Date + 100 * 1000;
|
||||
logger.query({ from: start, until: end }, cb);
|
||||
},
|
||||
'should return matching results': function (err, results) {
|
||||
if (!transport.query) return;
|
||||
assert.isNull(err);
|
||||
results = results[transport.name];
|
||||
while (!Array.isArray(results)) {
|
||||
results = results[Object.keys(results).pop()];
|
||||
}
|
||||
assert.ok(results.length >= 1);
|
||||
}
|
||||
},
|
||||
'using a bad `from` and `until` option': {
|
||||
'topic': function () {
|
||||
if (!transport.query) return;
|
||||
var cb = this.callback;
|
||||
logger.log('info', 'bad from and until', {}, function () {
|
||||
var now = new Date + 1000000;
|
||||
logger.query({ from: now, until: now }, cb);
|
||||
});
|
||||
},
|
||||
'should return no results': function (err, results) {
|
||||
if (!transport.query) return;
|
||||
assert.isNull(err);
|
||||
results = results[transport.name];
|
||||
while (!Array.isArray(results)) {
|
||||
results = results[Object.keys(results).pop()];
|
||||
}
|
||||
results = [results.filter(function(log) {
|
||||
return log.message === 'bad from and until';
|
||||
}).pop()];
|
||||
assert.isUndefined(results[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return out;
|
||||
};
|
||||
125
node_modules/winston/test/transports/webhook-test.js
generated
vendored
Normal file
125
node_modules/winston/test/transports/webhook-test.js
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* webhook-test.js: Tests for instances of the Webhook transport
|
||||
*
|
||||
* (C) 2011 Marak Squires
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var path = require('path'),
|
||||
vows = require('vows'),
|
||||
fs = require('fs'),
|
||||
http = require('http'),
|
||||
https = require('https'),
|
||||
assert = require('assert'),
|
||||
winston = require('../../lib/winston'),
|
||||
helpers = require('../helpers');
|
||||
|
||||
var webhookTransport = new (winston.transports.Webhook)({
|
||||
"host": "localhost",
|
||||
"port": 8080,
|
||||
"path": "/winston-test"
|
||||
});
|
||||
|
||||
var httpsWebhookTransport = new (winston.transports.Webhook)({
|
||||
"host": "localhost",
|
||||
"port": 8081,
|
||||
"path": "/winston-test",
|
||||
"ssl": true
|
||||
});
|
||||
|
||||
var authWebhookTransport = new (winston.transports.Webhook)({
|
||||
"host": "localhost",
|
||||
"port": 8080,
|
||||
"path": "/winston-auth-test",
|
||||
"auth": {
|
||||
"username": "winston",
|
||||
"password": "churchill"
|
||||
}
|
||||
});
|
||||
|
||||
var requestsAuthenticated = true;
|
||||
|
||||
var server = http.createServer(function (req, res) {
|
||||
if (req.url == '/winston-auth-test') {
|
||||
//
|
||||
// Test if request has been correctly authenticated
|
||||
//
|
||||
// Strip 'Basic' from Authorization header
|
||||
var signature = req.headers['authorization'].substr(6);
|
||||
requestsAuthenticated = requestsAuthenticated &&
|
||||
new Buffer(signature, 'base64').toString('utf8') == 'winston:churchill';
|
||||
}
|
||||
res.end();
|
||||
});
|
||||
|
||||
server.listen(8080);
|
||||
|
||||
|
||||
var httpsServer = https.createServer({
|
||||
cert: fs.readFileSync(path.join(__dirname, '..', 'fixtures', 'keys', 'agent2-cert.pem')),
|
||||
key: fs.readFileSync(path.join(__dirname, '..', 'fixtures', 'keys', 'agent2-key.pem'))
|
||||
}, function (req, res) {
|
||||
res.end();
|
||||
});
|
||||
|
||||
httpsServer.listen(8081);
|
||||
|
||||
vows.describe('winston/transports/webhook').addBatch({
|
||||
"An instance of the Webhook Transport": {
|
||||
"when passed valid options": {
|
||||
"should have the proper methods defined": function () {
|
||||
helpers.assertWebhook(webhookTransport);
|
||||
},
|
||||
"the log() method": helpers.testNpmLevels(webhookTransport, "should respond with true", function (ign, err, logged) {
|
||||
assert.isNull(err);
|
||||
assert.isTrue(logged);
|
||||
})
|
||||
}
|
||||
},
|
||||
"An https instance of the Webhook Transport": {
|
||||
"when passed valid options": {
|
||||
"should have the proper methods defined": function () {
|
||||
helpers.assertWebhook(httpsWebhookTransport);
|
||||
},
|
||||
"the log() method": helpers.testNpmLevels(httpsWebhookTransport, "should respond with true", function (ign, err, logged) {
|
||||
assert.isNull(err);
|
||||
assert.isTrue(logged);
|
||||
})
|
||||
}
|
||||
},
|
||||
"An http Basic Auth instance of the Webhook Transport": {
|
||||
"when passed valid options": {
|
||||
"should have the proper methods defined": function () {
|
||||
helpers.assertWebhook(authWebhookTransport);
|
||||
},
|
||||
"the log() method": helpers.testNpmLevels(authWebhookTransport, "should respond with true", function (ign, err, logged) {
|
||||
assert.isNull(err);
|
||||
assert.isTrue(logged);
|
||||
})
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"When the tests are over": {
|
||||
topic: function () {
|
||||
//
|
||||
// Delay destruction of the server since the
|
||||
// WebHook transport responds before the request
|
||||
// has actually be completed.
|
||||
//
|
||||
setTimeout(this.callback, 1000);
|
||||
},
|
||||
"the server should cleanup": function () {
|
||||
server.close();
|
||||
},
|
||||
"requests have been correctly authenticated": function () {
|
||||
assert.ok(requestsAuthenticated);
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
// "An instance of the Webhook Transport": transport(winston.transports.Webhook, {
|
||||
// "host": "localhost",
|
||||
// "port": 8080,
|
||||
// "path": "/winston-test"
|
||||
// })
|
||||
}).export(module);
|
||||
98
node_modules/winston/test/winston-test.js
generated
vendored
Normal file
98
node_modules/winston/test/winston-test.js
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* logger-test.js: Tests for instances of the winston Logger
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var fs = require('fs'),
|
||||
path = require('path'),
|
||||
vows = require('vows'),
|
||||
http = require('http'),
|
||||
assert = require('assert'),
|
||||
winston = require('../lib/winston'),
|
||||
helpers = require('./helpers');
|
||||
|
||||
vows.describe('winston').addBatch({
|
||||
"The winston module": {
|
||||
topic: function () {
|
||||
winston.default.transports.console.level = 'silly';
|
||||
return null;
|
||||
},
|
||||
"should have the correct methods defined": function () {
|
||||
assert.isObject(winston.transports);
|
||||
assert.isFunction(winston.Transport);
|
||||
assert.isTrue(!winston.transports.Transport);
|
||||
assert.isFunction(winston.transports.Console);
|
||||
assert.isFunction(winston.transports.File);
|
||||
assert.isFunction(winston.transports.Webhook);
|
||||
assert.isObject(winston.default.transports.console);
|
||||
assert.isFalse(winston.emitErrs);
|
||||
assert.isObject(winston.config);
|
||||
['Logger', 'add', 'remove', 'extend', 'clear']
|
||||
.concat(Object.keys(winston.config.npm.levels))
|
||||
.forEach(function (key) {
|
||||
assert.isFunction(winston[key]);
|
||||
});
|
||||
},
|
||||
"it should": {
|
||||
topic: function () {
|
||||
fs.readFile(path.join(__dirname, '..', 'package.json'), this.callback);
|
||||
},
|
||||
"have the correct version set": function (err, data) {
|
||||
assert.isNull(err);
|
||||
data = JSON.parse(data.toString());
|
||||
assert.equal(winston.version, data.version);
|
||||
}
|
||||
},
|
||||
"the log() method": helpers.testNpmLevels(winston, "should respond without an error", function (err) {
|
||||
assert.isNull(err);
|
||||
}),
|
||||
"the extend() method called on an empty object": {
|
||||
topic: function (logger) {
|
||||
var empty = {};
|
||||
winston.extend(empty);
|
||||
return empty;
|
||||
},
|
||||
"should define the appropriate methods": function (extended) {
|
||||
['log', 'profile', 'startTimer'].concat(Object.keys(winston.config.npm.levels)).forEach(function (method) {
|
||||
assert.isFunction(extended[method]);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"The winston module": {
|
||||
"the setLevels() method": {
|
||||
topic: function () {
|
||||
winston.setLevels(winston.config.syslog.levels);
|
||||
return null;
|
||||
},
|
||||
"should have the proper methods defined": function () {
|
||||
assert.isObject(winston.transports);
|
||||
assert.isFunction(winston.transports.Console);
|
||||
assert.isFunction(winston.transports.Webhook);
|
||||
assert.isObject(winston.default.transports.console);
|
||||
assert.isFalse(winston.emitErrs);
|
||||
assert.isObject(winston.config);
|
||||
|
||||
var newLevels = Object.keys(winston.config.syslog.levels);
|
||||
['Logger', 'add', 'remove', 'extend', 'clear']
|
||||
.concat(newLevels)
|
||||
.forEach(function (key) {
|
||||
assert.isFunction(winston[key]);
|
||||
});
|
||||
|
||||
|
||||
Object.keys(winston.config.npm.levels)
|
||||
.filter(function (key) {
|
||||
return newLevels.indexOf(key) === -1;
|
||||
})
|
||||
.forEach(function (key) {
|
||||
assert.isTrue(typeof winston[key] === 'undefined');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
Reference in New Issue
Block a user