mirror of
https://github.com/atlanticbiomedical/biomedjs.git
synced 2025-07-02 00:47:26 -04:00
Changes
This commit is contained in:
188
node_modules/winston/CHANGELOG.md
generated
vendored
Normal file
188
node_modules/winston/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,188 @@
|
||||
## v2.1.1 / 2015-11-18
|
||||
### COLOR ME IMPRESSED EDITION
|
||||
|
||||
- [#751](https://github.com/winstonjs/winston/pull/751), Fix colors not appearing in non-tty environments. Fixes [#609](https://github.com/winstonjs/winston/issues/609), [#616](https://github.com/winstonjs/winston/issues/616), [#669](https://github.com/winstonjs/winston/issues/669), [#648](https://github.com/winstonjs/winston/issues/648) (`fiznool`).
|
||||
- [#752](https://github.com/winstonjs/winston/pull/752) Correct syslog RFC number. 5424 instead of 524. (`jbenoit2011`)
|
||||
|
||||
## v2.1.0 / 2015-11-03
|
||||
### TEST ALL THE ECOSYSTEM EDITION
|
||||
|
||||
- [#742](https://github.com/winstonjs/winston/pull/742), [32d52b7](https://github.com/winstonjs/winston/commit/32d52b7) Distribute common test files used by transports in the `winston` ecosystem.
|
||||
|
||||
## v2.0.1 / 2015-11-02
|
||||
### BUGS ALWAYS HAPPEN OK EDITION
|
||||
|
||||
- [#739](https://github.com/winstonjs/winston/issues/739), [1f16861](https://github.com/winstonjs/winston/commit/1f16861) Ensure that `logger.log("info", undefined)` does not throw.
|
||||
|
||||
## v2.0.0 / 2015-10-29
|
||||
### OMG IT'S MY SISTER'S BIRTHDAY EDITION
|
||||
|
||||
#### Breaking changes
|
||||
|
||||
**Most important**
|
||||
- **[0f82204](https://github.com/winstonjs/winston/commit/0f82204) Move `winston.transports.DailyRotateFile` [into a separate module](https://github.com/winstonjs/winston-daily-rotate-file)**: `require('winston-daily-rotate-file');`
|
||||
- **[fb9eec0](https://github.com/winstonjs/winston/commit/fb9eec0) Reverse log levels in `npm` and `cli` configs to conform to [RFC524](https://tools.ietf.org/html/rfc5424). Fixes [#424](https://github.com/winstonjs/winston/pull/424) [#406](https://github.com/winstonjs/winston/pull/406) [#290](https://github.com/winstonjs/winston/pull/290)**
|
||||
- **[8cd8368](https://github.com/winstonjs/winston/commit/8cd8368) Change the method signature to a `filter` function to be consistent with `rewriter` and log functions:**
|
||||
``` js
|
||||
function filter (level, msg, meta, inst) {
|
||||
// Filter logic goes here...
|
||||
}
|
||||
```
|
||||
|
||||
**Other breaking changes**
|
||||
- [e0c9dde](https://github.com/winstonjs/winston/commit/e0c9dde) Remove `winston.transports.Webhook`. Use `winston.transports.Http` instead.
|
||||
- [f71e638](https://github.com/winstonjs/winston/commit/f71e638) Remove `Logger.prototype.addRewriter` and `Logger.prototype.addFilter` since they just push to an Array of functions. Use `logger.filters.push` or `logger.rewriters.push` explicitly instead.
|
||||
- [a470ab5](https://github.com/winstonjs/winston/commit/a470ab5) No longer respect the `handleExceptions` option to `new winston.Logger`. Instead just pass in the `exceptionHandlers` option itself.
|
||||
- [8cb7048](https://github.com/winstonjs/winston/commit/8cb7048) Removed `Logger.prototype.extend` functionality
|
||||
|
||||
#### New features
|
||||
- [3aa990c](https://github.com/winstonjs/winston/commit/3aa990c) Added `Logger.prototype.configure` which now contains all logic previously in the `winston.Logger` constructor function. (`indexzero`)
|
||||
- [#726](https://github.com/winstonjs/winston/pull/726) Update .npmignore (`coreybutler`)
|
||||
- [#700](https://github.com/winstonjs/winston/pull/700) Add an `eol` option to the `Console` transport. (`aquavitae`)
|
||||
- [#731](https://github.com/winstonjs/winston/pull/731) Update `lib/transports.js` for better static analysis. (`indexzero`)
|
||||
|
||||
#### Fixes, refactoring, and optimizations. OH MY!
|
||||
- [#632](https://github.com/winstonjs/winston/pull/632) Allow `File` transport to be an `objectMode` writable stream. (`stambata`)
|
||||
- [#527](https://github.com/winstonjs/winston/issues/527), [163f4f9](https://github.com/winstonjs/winston/commit/163f4f9), [3747ccf](https://github.com/winstonjs/winston/commit/3747ccf) Performance optimizations and string interpolation edge cases (`indexzero`)
|
||||
- [f0edafd](https://github.com/winstonjs/winston/commit/f0edafd) Code cleanup for reability, ad-hoc styleguide enforcement (`indexzero`)
|
||||
|
||||
## v1.1.1 - v1.1.2 / 2015-10
|
||||
### MINOR FIXES EDITION
|
||||
|
||||
#### Notable changes
|
||||
* [727](https://github.com/winstonjs/winston/pull/727) Fix "raw" mode (`jcrugzz`)
|
||||
* [703](https://github.com/winstonjs/winston/pull/703) Do not modify Error or Date objects when logging. Fixes #610 (`harriha`).
|
||||
|
||||
## v1.1.0 / 2015-10-09
|
||||
### GREETINGS FROM CARTAGENA EDITION
|
||||
|
||||
#### Notable Changes
|
||||
* [#721](https://github.com/winstonjs/winston/pull/721) Fixed octal literal to work with node 4 strict mode (`wesleyeff`)
|
||||
* [#630](https://github.com/winstonjs/winston/pull/630) Add stderrLevels option to Console Transport and update docs (`paulhroth`)
|
||||
* [#626](https://github.com/winstonjs/winston/pull/626) Add the logger (this) in the fourth argument in the rewriters and filters functions (`christophehurpeau `)
|
||||
* [#623](https://github.com/winstonjs/winston/pull/623) Fix Console Transport's align option tests (`paulhroth`, `kikobeats`)
|
||||
* [#692](https://github.com/winstonjs/winston/pull/692) Adding winston-aws-cloudwatch to transport docs (`timdp`)
|
||||
|
||||
## v1.0.2 2015-09-25
|
||||
### LET'S TALK ON GITTER EDITION
|
||||
|
||||
#### Notable Changes
|
||||
* [de80160](https://github.com/winstonjs/winston/commit/de80160) Add Gitter badge (`The Gitter Badger`)
|
||||
* [44564de](https://github.com/winstonjs/winston/commit/44564de) [fix] Correct listeners in `logException`. Fixes [#218](https://github.com/winstonjs/winston/issues/218) [#213](https://github.com/winstonjs/winston/issues/213) [#327](https://github.com/winstonjs/winston/issues/327). (`indexzero`)
|
||||
* [45b1eeb](https://github.com/winstonjs/winston/commit/45b1eeb) [fix] Get `tailFile` function working on latest/all node versions (`Christopher Jeffrey`)
|
||||
* [c6d45f9](https://github.com/winstonjs/winston/commit/c6d45f9) Fixed event subscription on close (`Roman Stetsyshin`)
|
||||
|
||||
#### Other changes
|
||||
* TravisCI updates & best practices [87b97cc](https://github.com/winstonjs/winston/commit/87b97cc) [91a5bc4](https://github.com/winstonjs/winston/commit/91a5bc4), [cf24e6a](https://github.com/winstonjs/winston/commit/cf24e6a) (`indexzero`)
|
||||
* [d5397e7](https://github.com/winstonjs/winston/commit/d5397e7) Bump async version (`Roderick Hsiao`)
|
||||
* Documentation updates & fixes [86d7527](https://github.com/winstonjs/winston/commit/86d7527), [38254c1](https://github.com/winstonjs/winston/commit/38254c1), [04e2928](https://github.com/winstonjs/winston/commit/04e2928), [61c8a89](https://github.com/winstonjs/winston/commit/61c8a89), [c42a783](https://github.com/winstonjs/winston/commit/c42a783), [0688a22](https://github.com/winstonjs/winston/commit/0688a22), [eabc113](https://github.com/winstonjs/winston/commit/eabc113) [c9506b7](https://github.com/winstonjs/winston/commit/c9506b7), [17534d2](https://github.com/winstonjs/winston/commit/17534d2), [b575e7b](https://github.com/winstonjs/winston/commit/b575e7b) (`Stefan Thies`, `charukiewicz`, `unLucio`, `Adam Cohen`, `Denis Gorbachev`, `Frederik Ring`, `Luigi Pinca`, `jeffreypriebe`)
|
||||
* Documentation refactor & cleanup [a19607e](https://github.com/winstonjs/winston/commit/a19607e), [d1932b4](https://github.com/winstonjs/winston/commit/d1932b4), [7a13132](https://github.com/winstonjs/winston/commit/7a13132) (`indexzero`)
|
||||
|
||||
|
||||
## v1.0.1 / 2015-06-26
|
||||
### YAY DOCS EDITION
|
||||
|
||||
* [#639](https://github.com/winstonjs/winston/pull/639) Fix for [#213](https://github.com/winstonjs/winston/issues/213): More than 10 containers triggers EventEmitter memory leak warning (`marcus`)
|
||||
* Documentation and `package.json` updates [cec892c](https://github.com/winstonjs/winston/commit/cec892c), [2f13b4f](https://github.com/winstonjs/winston/commit/2f13b4f), [b246efd](https://github.com/winstonjs/winston/commit/b246efd), [22a5f5a](https://github.com/winstonjs/winston/commit/22a5f5a), [5868b78](https://github.com/winstonjs/winston/commit/5868b78), [99b6b44](https://github.com/winstonjs/winston/commit/99b6b44), [447a813](https://github.com/winstonjs/winston/commit/447a813), [7f75b48](https://github.com/winstonjs/winston/commit/7f75b48) (`peteward44`, `Gilad Peleg`, `Anton Ian Sipos`, `nimrod-becker`, `LarsTi`, `indexzero`)
|
||||
|
||||
## v1.0.0 / 2015-04-07
|
||||
### OMG 1.0.0 FINALLY EDITION
|
||||
|
||||
#### Breaking Changes
|
||||
* [#587](https://github.com/winstonjs/winston/pull/587) Do not extend `String` prototypes as a side effect of using `colors`. (`kenperkins`)
|
||||
* [#581](https://github.com/winstonjs/winston/pull/581) File transports now emit `error` on error of the underlying streams after `maxRetries` attempts. (`ambbell`).
|
||||
* [#583](https://github.com/winstonjs/winston/pull/583), [92729a](https://github.com/winstonjs/winston/commit/92729a68d71d07715501c35d94d2ac06ac03ca08) Use `os.EOL` for all file writing by default. (`Mik13`, `indexzero`)
|
||||
* [#532](https://github.com/winstonjs/winston/pull/532) Delete logger instance from `Container` when `close` event is emitted. (`snater`)
|
||||
* [#380](https://github.com/winstonjs/winston/pull/380) Rename `duration` to `durationMs`, which is now a number a not a string ending in `ms`. (`neoziro`)
|
||||
* [#253](https://github.com/winstonjs/winston/pull/253) Do not set a default level. When `level` is falsey on any `Transport` instance, any `Logger` instance uses the configured level (instead of the Transport level) (`jstamerj`).
|
||||
|
||||
#### Other changes
|
||||
|
||||
* [b83de62](https://github.com/winstonjs/winston/commit/b83de62) Fix rendering of stack traces.
|
||||
* [c899cc](https://github.com/winstonjs/winston/commit/c899cc1f0719e49b26ec933e0fa263578168ea3b) Update documentation (Fixes [#549](https://github.com/winstonjs/winston/issues/549))
|
||||
* [#551](https://github.com/winstonjs/winston/pull/551) Filter metadata along with messages
|
||||
* [#578](https://github.com/winstonjs/winston/pull/578) Fixes minor issue with `maxFiles` in `File` transport (Fixes [#556](https://github.com/winstonjs/winston/issues/556)).
|
||||
* [#560](https://github.com/winstonjs/winston/pull/560) Added `showLevel` support to `File` transport.
|
||||
* [#558](https://github.com/winstonjs/winston/pull/558) Added `showLevel` support to `Console` transport.
|
||||
|
||||
## v0.9.0 / 2015-02-03
|
||||
|
||||
* [#496](https://github.com/flatiron/winston/pull/496) Updated default option handling for CLI (`oojacoboo`).
|
||||
* [f37634b](https://github.com/flatiron/winston/commit/f37634b) [dist] Only support `node >= 0.8.0`. (`indexzero`)
|
||||
* [91a1e90](https://github.com/flatiron/winston/commit/91a1e90), [50163a0](https://github.com/flatiron/winston/commit/50163a0) Fix #84 [Enable a better unhandled exception experience](https://github.com/flatiron/winston/issues/84) (`samz`)
|
||||
* [8b5fbcd](https://github.com/flatiron/winston/commit/8b5fbcd) #448 Added tailable option to file transport which rolls files backwards instead of creating incrementing appends. Implements #268 (`neouser99`)
|
||||
* [a34f7d2](https://github.com/flatiron/winston/commit/a34f7d2) Custom log formatter functionality were added. (`Melnyk Andii`)
|
||||
* [4c08191](https://github.com/flatiron/winston/commit/4c08191) Added showLevel flag to common.js, file*, memory and console transports. (`Tony Germaneri`)
|
||||
* [64ed8e0](https://github.com/flatiron/winston/commit/64ed8e0) Adding custom pretty print function test. (`Alberto Pose`)
|
||||
* [3872dfb](https://github.com/flatiron/winston/commit/3872dfb) Adding prettyPrint parameter as function example. (`Alberto Pose`)
|
||||
* [2b96eee](https://github.com/flatiron/winston/commit/2b96eee) implemented filters #526 (`Chris Oloff`)
|
||||
* [72273b1](https://github.com/flatiron/winston/commit/72273b1) Added the options to colorize only the level, only the message or all. Default behavior is kept. Using true will only colorize the level and false will not colorize anything. (`Michiel De Mey`)
|
||||
* [178e8a6](https://github.com/flatiron/winston/commit/178e8a6) Prevent message from meta input being overwritten (`Leonard Martin`)
|
||||
* [270be86](https://github.com/flatiron/winston/commit/270be86) [api] Allow for transports to be removed by their string name [test fix] Add test coverage for multiple transports of the same type added in #187. [doc] Document using multiple transports of the same type (`indexzero`)
|
||||
* [0a848fa](https://github.com/flatiron/winston/commit/0a848fa) Add depth options for meta pretty print (`Loïc Mahieu`)
|
||||
* [106b670](https://github.com/flatiron/winston/commit/106b670) Allow debug messages to be sent to stdout (`John Frizelle`)
|
||||
* [ad2d5e1](https://github.com/flatiron/winston/commit/ad2d5e1) [fix] Handle Error instances in a sane way since their properties are non-enumerable __by default.__ Fixes #280. (`indexzero`)
|
||||
* [5109dd0](https://github.com/flatiron/winston/commit/5109dd0) [fix] Have a default `until` before a default `from`. Fixes #478. (`indexzero`)
|
||||
* [d761960](https://github.com/flatiron/winston/commit/d761960) Fix logging regular expression objects (`Chasen Le Hara`)
|
||||
* [2632eb8](https://github.com/flatiron/winston/commit/2632eb8) Add option for EOL chars on FileTransport (`José F. Romaniello`)
|
||||
* [bdecce7](https://github.com/flatiron/winston/commit/bdecce7) Remove duplicate logstash option (`José F. Romaniello`)
|
||||
* [7a01f9a](https://github.com/flatiron/winston/commit/7a01f9a) Update declaration block according to project's style guide (`Ricardo Torres`)
|
||||
* [ae27a19](https://github.com/flatiron/winston/commit/ae27a19) Fixes #306: Can't set customlevels to my loggers (RangeError: Maximum call stack size exceeded) (`Alberto Pose`)
|
||||
* [1ba4f51](https://github.com/flatiron/winston/commit/1ba4f51) [fix] Call `res.resume()` in HttpTransport to get around known issues in streams2. (`indexzero`)
|
||||
* [39e0258](https://github.com/flatiron/winston/commit/39e0258) Updated default option handling for CLI (`Jacob Thomason`)
|
||||
* [8252801](https://github.com/flatiron/winston/commit/8252801) Added logstash support to console transport (`Ramon Snir`)
|
||||
* [18aa301](https://github.com/flatiron/winston/commit/18aa301) Module isStream should be isstream (`Michael Neil`)
|
||||
* [2f5f296](https://github.com/flatiron/winston/commit/2f5f296) options.prettyPrint can now be a function (`Matt Zukowski`)
|
||||
* [a87a876](https://github.com/flatiron/winston/commit/a87a876) Adding rotationFormat prop to file.js (`orcaman`)
|
||||
* [ff187f4](https://github.com/flatiron/winston/commit/ff187f4) Allow custom exception level (`jupiter`)
|
||||
|
||||
## 0.8.3 / 2014-11-04
|
||||
|
||||
* [fix lowercase issue (`jcrugzz`)](https://github.com/flatiron/winston/commit/b3ffaa10b5fe9d2a510af5348cf4fb3870534123)
|
||||
|
||||
## 0.8.2 / 2014-11-04
|
||||
|
||||
* [Full fix for #296 with proper streams2 detection with `isstream` for file transport (`jcrugzz`)](https://github.com/flatiron/winston/commit/5c4bd4191468570e46805ed399cad63cfb1856cc)
|
||||
* [Add isstream module (`jcrugzz`)](https://github.com/flatiron/winston/commit/498b216d0199aebaef72ee4d8659a00fb737b9ae)
|
||||
* [Partially fix #296 with streams2 detection for file transport (`indexzero`)](https://github.com/flatiron/winston/commit/b0227b6c27cf651ffa8b8192ef79ab24296362e3)
|
||||
* [add stress test for issue #288 (`indexzero`)](https://github.com/flatiron/winston/commit/e08e504b5b3a00f0acaade75c5ba69e6439c84a6)
|
||||
* [lessen timeouts to check test sanity (`indexzero`)](https://github.com/flatiron/winston/commit/e925f5bc398a88464f3e796545ff88912aff7568)
|
||||
* [update winston-graylog2 documentation (`unlucio`)](https://github.com/flatiron/winston/commit/49fa86c31baf12c8ac3adced3bdba6deeea2e363)
|
||||
* [fix test formatting (`indexzero`)](https://github.com/flatiron/winston/commit/8e2225799520a4598044cdf93006d216812a27f9)
|
||||
* [fix so options are not redefined (`indexzero`)](https://github.com/flatiron/winston/commit/d1d146e8a5bb73dcb01579ad433f6d4f70b668ea)
|
||||
* [fix self/this issue that broke `http` transport (`indexzero`)](https://github.com/flatiron/winston/commit/d10cbc07755c853b60729ab0cd14aa665da2a63b)
|
||||
|
||||
|
||||
## 0.8.1 / 2014-10-06
|
||||
|
||||
* [Add label option for DailyRotateFile transport (`francoisTemasys`)](https://github.com/flatiron/winston/pull/459)
|
||||
* [fix Logger#transports length check upon Logger#log (`adriano-di-giovanni`, `indexzero`)](https://github.com/flatiron/winston/pull/404)
|
||||
* [err can be a string. (`gdw2`, `indexzero`)](https://github.com/flatiron/winston/pull/396)
|
||||
* [Added color for pre-defined cli set. (`danilo1105`, `indexzero`)](https://github.com/flatiron/winston/pull/365)
|
||||
* [Fix dates on transport test (`revington`)](https://github.com/flatiron/winston/pull/346)
|
||||
* [Included the label from options to the output in JSON mode. (`arxony`)](https://github.com/flatiron/winston/pull/326)
|
||||
* [Allow using logstash option with the File transport (`gmajoulet`)](https://github.com/flatiron/winston/pull/299)
|
||||
* [Be more defensive when working with `query` methods from Transports. Fixes #356. (indexzero)](https://github.com/flatiron/winston/commit/b80638974057f74b521dbe6f43fef2105110afa2)
|
||||
* [Catch exceptions for file transport unlinkSync (`calvinfo`)](https://github.com/flatiron/winston/pull/266)
|
||||
* [Adding the 'addRewriter' to winston (`machadogj`)](https://github.com/flatiron/winston/pull/258)
|
||||
* [Updates to transport documentation (`pose`)](https://github.com/flatiron/winston/pull/262)
|
||||
* [fix typo in "Extending another object with Logging" section.](https://github.com/flatiron/winston/pull/281)
|
||||
* [Updated README.md - Replaced properties with those listed in winston-mongodb module](https://github.com/flatiron/winston/pull/264)
|
||||
|
||||
## 0.8.0 / 2014-09-15
|
||||
* [Fixes for HTTP Transport](https://github.com/flatiron/winston/commit/a876a012641f8eba1a976eada15b6687d4a03f82)
|
||||
* Removing [jsonquest](https://github.com/flatiron/winston/commit/4f088382aeda28012b7a0498829ceb243ed74ac1) and [request](https://github.com/flatiron/winston/commit/a5676313b4e9744802cc3b8e1468e4af48830876) dependencies.
|
||||
* Configuration is now [shalow cloned](https://github.com/flatiron/winston/commit/08fccc81d18536d33050496102d98bde648853f2).
|
||||
* [Added logstash support](https://github.com/flatiron/winston/pull/445/files)
|
||||
* Fix for ["flush" event should always fire after "flush" call bug](https://github.com/flatiron/winston/pull/446/files)
|
||||
* Added tests for file: [open and stress](https://github.com/flatiron/winston/commit/47d885797a2dd0d3cd879305ca813a0bd951c378).
|
||||
* [Test fixes](https://github.com/flatiron/winston/commit/9e39150e0018f43d198ca4c160acef2af9860bf4)
|
||||
* [Fix ")" on string interpolation](https://github.com/flatiron/winston/pull/394/files)
|
||||
|
||||
## 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.
|
833
node_modules/winston/README.md
generated
vendored
Normal file
833
node_modules/winston/README.md
generated
vendored
Normal file
@ -0,0 +1,833 @@
|
||||
# winston
|
||||
|
||||
[](https://gitter.im/winstonjs/winston?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
[](https://www.npmjs.com/package/winston)[](https://www.npmjs.com/package/winston)[](https://travis-ci.org/winstonjs/winston)[](https://david-dm.org/winstonjs/winston)
|
||||
|
||||
[](https://nodei.co/npm/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
|
||||
|
||||
```bashp
|
||||
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/winstonjs/winston/blob/master/docs/transports.md)
|
||||
* [Multiple transports of the same type](#multiple-transports-of-the-same-type)
|
||||
* [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)
|
||||
* [Filters and Rewriters](#filters-and-rewriters)
|
||||
* [Adding Custom Transports](#adding-custom-transports)
|
||||
* [Installation](#installation)
|
||||
* [Run Tests](#run-tests)
|
||||
|
||||
|
||||
## Logging
|
||||
|
||||
Logging levels in `winston` conform to the severity ordering specified by [RFC5424](https://tools.ietf.org/html/rfc5424): _severity of all levels is assumed to be numerically **ascending** from most important to least important._
|
||||
|
||||
### 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');
|
||||
|
||||
winston.level = 'debug';
|
||||
winston.log('debug', 'Now my debug messages are written to console!');
|
||||
```
|
||||
|
||||
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 [Winston Transports](docs/transports.md) document.
|
||||
|
||||
### 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);
|
||||
```
|
||||
|
||||
You can also wholesale reconfigure a `winston.Logger` instance using the `configure` method:
|
||||
|
||||
``` js
|
||||
var logger = new winston.Logger({
|
||||
level: 'info',
|
||||
transports: [
|
||||
new (winston.transports.Console)(),
|
||||
new (winston.transports.File)({ filename: 'somefile.log' })
|
||||
]
|
||||
});
|
||||
|
||||
//
|
||||
// Replaces the previous transports with those in the
|
||||
// new configuration wholesale.
|
||||
//
|
||||
logger.configure({
|
||||
level: 'verbose',
|
||||
transports: [
|
||||
new require('winston-daily-rotate-file')(opts)
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
### 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)
|
||||
|
||||
## Multiple transports of the same type
|
||||
|
||||
It is possible to use multiple transports of the same type e.g. `winston.transports.File` by passing in a custom `name` when you construct the transport.
|
||||
|
||||
``` js
|
||||
var logger = new (winston.Logger)({
|
||||
transports: [
|
||||
new (winston.transports.File)({
|
||||
name: 'info-file',
|
||||
filename: 'filelog-info.log',
|
||||
level: 'info'
|
||||
}),
|
||||
new (winston.transports.File)({
|
||||
name: 'error-file',
|
||||
filename: 'filelog-error.log',
|
||||
level: 'error'
|
||||
})
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
If you later want to remove one of these transports you can do so by using the string name. e.g.:
|
||||
|
||||
``` js
|
||||
logger.remove('info-file');
|
||||
```
|
||||
|
||||
In this example one could also remove by passing in the instance of the Transport itself. e.g. this is equivalent to the string example above;
|
||||
|
||||
``` js
|
||||
// Notice it was first in the Array above
|
||||
var infoFile = logger.transports[0];
|
||||
logger.remove(infoFile);
|
||||
```
|
||||
|
||||
## 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 = {number: 123}
|
||||
// callback = function(){}
|
||||
|
||||
logger.log('info', 'test message', 'first', 'second', {number: 123}, function(){});
|
||||
// info: test message first second
|
||||
// meta = {number: 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.
|
||||
// You can use the `.humanReadableUnhandledException` option to get more readable exceptions.
|
||||
//
|
||||
winston.add(winston.transports.File, {
|
||||
filename: 'path/to/all-logs.log',
|
||||
handleExceptions: true,
|
||||
humanReadableUnhandledException: 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
|
||||
|
||||
``` js
|
||||
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
|
||||
|
||||
Each `level` is given a specific integer priority. The higher the priority the more important the message is considered to be, and the lower the corresponding integer priority. For example, `npm` logging levels are prioritized from 0 to 5 (highest to lowest):
|
||||
|
||||
``` js
|
||||
{ error: 0, warn: 1, info: 2, verbose: 3, debug: 4, silly: 5 }
|
||||
```
|
||||
|
||||
Similarly, as specified exactly in RFC5424 the `syslog` levels are prioritized from 0 to 7 (highest to lowest).
|
||||
|
||||
```js
|
||||
{ emerg: 0, alert: 1, crit: 2, error: 3, warning: 4, notice: 5, info: 6, debug: 7 }
|
||||
```
|
||||
|
||||
If you do not explicitly define the levels that `winston` should use the `npm` levels above will be used.
|
||||
|
||||
### 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 define a `level` property on each transport which specifies the **maximum** level of messages that a transport should log. For example, using the `npm` levels you could log only `error` messages to the console and everything `info` and below to a file (which includes `error` messages):
|
||||
|
||||
``` js
|
||||
var logger = new (winston.Logger)({
|
||||
transports: [
|
||||
new (winston.transports.Console)({ level: 'error' }),
|
||||
new (winston.transports.File)({
|
||||
filename: 'somefile.log',
|
||||
level: 'info'
|
||||
})
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
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 do not want 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();
|
||||
```
|
||||
|
||||
### Filters and Rewriters
|
||||
Filters allow modifying the contents of **log messages**, and Rewriters allow modifying the contents of **log meta** e.g. to mask data that should not appear in logs.
|
||||
|
||||
Both filters and rewriters are simple Arrays of functions which can be provided when creating a `new winston.Logger(options)`. e.g.:
|
||||
|
||||
``` js
|
||||
var logger = new winston.Logger({
|
||||
rewriters: [function (level, msg, meta) { /* etc etc */ }]
|
||||
filters: [function (level, msg, meta) { /* etc etc */ }]
|
||||
})
|
||||
```
|
||||
|
||||
Like any Array they can also be modified at runtime with no adverse side-effects to the `winston` internals.
|
||||
|
||||
``` js
|
||||
logger.filters.push(function(level, msg, meta) {
|
||||
return meta.production
|
||||
? maskCardNumbers(msg)
|
||||
: msg;
|
||||
});
|
||||
|
||||
logger.info('transaction with card number 123456789012345 successful.');
|
||||
```
|
||||
|
||||
This may result in this output:
|
||||
|
||||
```
|
||||
info: transaction with card number 123456****2345 successful.
|
||||
```
|
||||
|
||||
Where as for rewriters, if you wanted to sanitize the `creditCard` field of your `meta` you could:
|
||||
|
||||
``` js
|
||||
logger.rewriters.push(function(level, msg, meta) {
|
||||
if (meta.creditCard) {
|
||||
meta.creditCard = maskCardNumbers(meta.creditCard)
|
||||
}
|
||||
|
||||
return meta;
|
||||
});
|
||||
|
||||
logger.info('transaction ok', { creditCard: 123456789012345 });
|
||||
```
|
||||
|
||||
which may result in this output:
|
||||
|
||||
```
|
||||
info: transaction ok creditCard=123456****2345
|
||||
```
|
||||
|
||||
See [log-filter-test.js](./test/log-filter-test.js), where card number masking is implemented as an example along with [log-rewriter-test.js](./test/log-rewriter-test.js)
|
||||
|
||||
## Adding Custom Transports
|
||||
Adding a custom transport 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.CustomLogger = 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);
|
||||
};
|
||||
```
|
||||
|
||||
### Custom Log Format
|
||||
To specify custom log format you should set formatter function for transport. Currently supported transports are: Console, File, Memory.
|
||||
Options object will be passed to the format function. It's general properties are: timestamp, level, message, meta. Depending on the transport type may be additional properties.
|
||||
|
||||
``` js
|
||||
var logger = new (winston.Logger)({
|
||||
transports: [
|
||||
new (winston.transports.Console)({
|
||||
timestamp: function() {
|
||||
return Date.now();
|
||||
},
|
||||
formatter: function(options) {
|
||||
// Return string will be passed to logger.
|
||||
return options.timestamp() +' '+ options.level.toUpperCase() +' '+ (undefined !== options.message ? options.message : '') +
|
||||
(options.meta && Object.keys(options.meta).length ? '\n\t'+ JSON.stringify(options.meta) : '' );
|
||||
}
|
||||
})
|
||||
]
|
||||
});
|
||||
logger.info('Data to log.');
|
||||
```
|
||||
|
||||
### 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
|
||||
[25]: https://github.com/jesseditson/winston-sns
|
||||
[26]: https://github.com/inspiredjw/winston-dynamodb/
|
165
node_modules/winston/lib/winston.js
generated
vendored
Normal file
165
node_modules/winston/lib/winston.js
generated
vendored
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* winston.js: Top-level include defining Winston.
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var winston = exports;
|
||||
|
||||
//
|
||||
// Expose version using `pkginfo`
|
||||
//
|
||||
require('pkginfo')(module, 'version');
|
||||
|
||||
//
|
||||
// Include transports defined by default by winston
|
||||
//
|
||||
winston.transports = require('./winston/transports');
|
||||
|
||||
//
|
||||
// Expose utility methods
|
||||
//
|
||||
var common = require('./winston/common');
|
||||
winston.hash = common.hash;
|
||||
winston.clone = common.clone;
|
||||
winston.longestElement = common.longestElement;
|
||||
winston.exception = require('./winston/exception');
|
||||
winston.config = require('./winston/config');
|
||||
winston.addColors = winston.config.addColors;
|
||||
|
||||
//
|
||||
// Expose core Logging-related prototypes.
|
||||
//
|
||||
winston.Container = require('./winston/container').Container;
|
||||
winston.Logger = require('./winston/logger').Logger;
|
||||
winston.Transport = require('./winston/transports/transport').Transport;
|
||||
|
||||
//
|
||||
// We create and expose a default `Container` to `winston.loggers` so that the
|
||||
// programmer may manage multiple `winston.Logger` instances without any additional overhead.
|
||||
//
|
||||
// ### some-file1.js
|
||||
//
|
||||
// var logger = require('winston').loggers.get('something');
|
||||
//
|
||||
// ### some-file2.js
|
||||
//
|
||||
// var logger = require('winston').loggers.get('something');
|
||||
//
|
||||
winston.loggers = new winston.Container();
|
||||
|
||||
//
|
||||
// We create and expose a 'defaultLogger' so that the programmer may do the
|
||||
// following without the need to create an instance of winston.Logger directly:
|
||||
//
|
||||
// var winston = require('winston');
|
||||
// winston.log('info', 'some message');
|
||||
// winston.error('some error');
|
||||
//
|
||||
var defaultLogger = new winston.Logger({
|
||||
transports: [new winston.transports.Console()]
|
||||
});
|
||||
|
||||
//
|
||||
// Pass through the target methods onto `winston.
|
||||
//
|
||||
var methods = [
|
||||
'log',
|
||||
'query',
|
||||
'stream',
|
||||
'add',
|
||||
'remove',
|
||||
'clear',
|
||||
'profile',
|
||||
'startTimer',
|
||||
'extend',
|
||||
'cli',
|
||||
'handleExceptions',
|
||||
'unhandleExceptions',
|
||||
'addRewriter',
|
||||
'addFilter'
|
||||
];
|
||||
common.setLevels(winston, null, defaultLogger.levels);
|
||||
methods.forEach(function (method) {
|
||||
winston[method] = function () {
|
||||
return defaultLogger[method].apply(defaultLogger, arguments);
|
||||
};
|
||||
});
|
||||
|
||||
//
|
||||
// ### function cli ()
|
||||
// Configures the default winston logger to have the
|
||||
// settings for command-line interfaces: no timestamp,
|
||||
// colors enabled, padded output, and additional levels.
|
||||
//
|
||||
winston.cli = function () {
|
||||
winston.padLevels = true;
|
||||
common.setLevels(winston, defaultLogger.levels, winston.config.cli.levels);
|
||||
defaultLogger.setLevels(winston.config.cli.levels);
|
||||
winston.config.addColors(winston.config.cli.colors);
|
||||
|
||||
if (defaultLogger.transports.console) {
|
||||
defaultLogger.transports.console.colorize = true;
|
||||
defaultLogger.transports.console.timestamp = false;
|
||||
}
|
||||
|
||||
return winston;
|
||||
};
|
||||
|
||||
//
|
||||
// ### function setLevels (target)
|
||||
// #### @target {Object} Target levels to use
|
||||
// Sets the `target` levels specified on the default winston logger.
|
||||
//
|
||||
winston.setLevels = function (target) {
|
||||
common.setLevels(winston, defaultLogger.levels, target);
|
||||
defaultLogger.setLevels(target);
|
||||
};
|
||||
|
||||
//
|
||||
// Define getter / setter for the default logger level
|
||||
// which need to be exposed by winston.
|
||||
//
|
||||
Object.defineProperty(winston, 'level', {
|
||||
get: function () {
|
||||
return defaultLogger.level;
|
||||
},
|
||||
set: function (val) {
|
||||
defaultLogger.level = val;
|
||||
|
||||
Object.keys(defaultLogger.transports).forEach(function(key) {
|
||||
defaultLogger.transports[key].level = val;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
// Define getters / setters for appropriate properties of the
|
||||
// default logger which need to be exposed by winston.
|
||||
//
|
||||
['emitErrs', 'exitOnError', 'padLevels', 'levelLength', 'stripColors'].forEach(function (prop) {
|
||||
Object.defineProperty(winston, prop, {
|
||||
get: function () {
|
||||
return defaultLogger[prop];
|
||||
},
|
||||
set: function (val) {
|
||||
defaultLogger[prop] = val;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//
|
||||
// @default {Object}
|
||||
// The default transports and exceptionHandlers for
|
||||
// the default winston logger.
|
||||
//
|
||||
Object.defineProperty(winston, 'default', {
|
||||
get: function () {
|
||||
return {
|
||||
transports: defaultLogger.transports,
|
||||
exceptionHandlers: defaultLogger.exceptionHandlers
|
||||
};
|
||||
}
|
||||
});
|
483
node_modules/winston/lib/winston/common.js
generated
vendored
Normal file
483
node_modules/winston/lib/winston/common.js
generated
vendored
Normal file
@ -0,0 +1,483 @@
|
||||
/*
|
||||
* common.js: Internal helper and utility functions for winston
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var util = require('util'),
|
||||
crypto = require('crypto'),
|
||||
cycle = require('cycle'),
|
||||
fs = require('fs'),
|
||||
StringDecoder = require('string_decoder').StringDecoder,
|
||||
Stream = require('stream').Stream,
|
||||
config = require('./config');
|
||||
|
||||
//
|
||||
// ### function setLevels (target, past, current)
|
||||
// #### @target {Object} Object on which to set levels.
|
||||
// #### @past {Object} Previous levels set on target.
|
||||
// #### @current {Object} Current levels to set on target.
|
||||
// Create functions on the target objects for each level
|
||||
// in current.levels. If past is defined, remove functions
|
||||
// for each of those levels.
|
||||
//
|
||||
exports.setLevels = function (target, past, current, isDefault) {
|
||||
var self = this;
|
||||
if (past) {
|
||||
Object.keys(past).forEach(function (level) {
|
||||
delete target[level];
|
||||
});
|
||||
}
|
||||
|
||||
target.levels = current || config.npm.levels;
|
||||
if (target.padLevels) {
|
||||
target.levelLength = exports.longestElement(Object.keys(target.levels));
|
||||
}
|
||||
|
||||
//
|
||||
// Define prototype methods for each log level
|
||||
// e.g. target.log('info', msg) <=> target.info(msg)
|
||||
//
|
||||
Object.keys(target.levels).forEach(function (level) {
|
||||
|
||||
// TODO Refactor logging methods into a different object to avoid name clashes
|
||||
if (level === 'log') {
|
||||
console.warn('Log level named "log" will clash with the method "log". Consider using a different name.');
|
||||
return;
|
||||
}
|
||||
|
||||
target[level] = function (msg) {
|
||||
// build argument list (level, msg, ... [string interpolate], [{metadata}], [callback])
|
||||
var args = [level].concat(Array.prototype.slice.call(arguments));
|
||||
target.log.apply(target, args);
|
||||
};
|
||||
});
|
||||
|
||||
return target;
|
||||
};
|
||||
|
||||
//
|
||||
// ### function longestElement
|
||||
// #### @xs {Array} Array to calculate against
|
||||
// Returns the longest element in the `xs` array.
|
||||
//
|
||||
exports.longestElement = function (xs) {
|
||||
return Math.max.apply(
|
||||
null,
|
||||
xs.map(function (x) { return x.length; })
|
||||
);
|
||||
};
|
||||
|
||||
//
|
||||
// ### function clone (obj)
|
||||
// #### @obj {Object} Object to clone.
|
||||
// Helper method for deep cloning pure JSON objects
|
||||
// i.e. JSON objects that are either literals or objects (no Arrays, etc)
|
||||
//
|
||||
exports.clone = function (obj) {
|
||||
//
|
||||
// We only need to clone reference types (Object)
|
||||
//
|
||||
var copy = {};
|
||||
|
||||
if (obj instanceof Error) {
|
||||
// With potential custom Error objects, this might not be exactly correct,
|
||||
// but probably close-enough for purposes of this lib.
|
||||
copy = new Error(obj.message);
|
||||
Object.getOwnPropertyNames(obj).forEach(function (key) {
|
||||
copy[key] = obj[key];
|
||||
});
|
||||
|
||||
return copy;
|
||||
}
|
||||
else if (!(obj instanceof Object)) {
|
||||
return obj;
|
||||
}
|
||||
else if (obj instanceof Date) {
|
||||
return new Date(obj.getTime());
|
||||
}
|
||||
|
||||
for (var i in obj) {
|
||||
if (Array.isArray(obj[i])) {
|
||||
copy[i] = obj[i].slice(0);
|
||||
}
|
||||
else if (obj[i] instanceof Buffer) {
|
||||
copy[i] = obj[i].slice(0);
|
||||
}
|
||||
else if (typeof obj[i] != 'function') {
|
||||
copy[i] = obj[i] instanceof Object ? exports.clone(obj[i]) : obj[i];
|
||||
}
|
||||
else if (typeof obj[i] === 'function') {
|
||||
copy[i] = obj[i];
|
||||
}
|
||||
}
|
||||
|
||||
return copy;
|
||||
};
|
||||
|
||||
//
|
||||
// ### function log (options)
|
||||
// #### @options {Object} All information about the log serialization.
|
||||
// Generic logging function for returning timestamped strings
|
||||
// with the following options:
|
||||
//
|
||||
// {
|
||||
// level: 'level to add to serialized message',
|
||||
// message: 'message to serialize',
|
||||
// meta: 'additional logging metadata to serialize',
|
||||
// colorize: false, // Colorizes output (only if `.json` is false)
|
||||
// align: false // Align message level.
|
||||
// timestamp: true // Adds a timestamp to the serialized message
|
||||
// label: 'label to prepend the message'
|
||||
// }
|
||||
//
|
||||
exports.log = function (options) {
|
||||
var timestampFn = typeof options.timestamp === 'function'
|
||||
? options.timestamp
|
||||
: exports.timestamp,
|
||||
timestamp = options.timestamp ? timestampFn() : null,
|
||||
showLevel = options.showLevel === undefined ? true : options.showLevel,
|
||||
meta = options.meta !== null && options.meta !== undefined && !(options.meta instanceof Error)
|
||||
? exports.clone(cycle.decycle(options.meta))
|
||||
: options.meta || null,
|
||||
output;
|
||||
|
||||
//
|
||||
// raw mode is intended for outputing winston as streaming JSON to STDOUT
|
||||
//
|
||||
if (options.raw) {
|
||||
if (typeof meta !== 'object' && meta != null) {
|
||||
meta = { meta: meta };
|
||||
}
|
||||
output = exports.clone(meta) || {};
|
||||
output.level = options.level;
|
||||
//
|
||||
// Remark (jcrugzz): This used to be output.message = options.message.stripColors.
|
||||
// I do not know why this is, it does not make sense but im handling that
|
||||
// case here as well as handling the case that does make sense which is to
|
||||
// make the `output.message = options.message`
|
||||
//
|
||||
output.message = options.message.stripColors
|
||||
? options.message.stripColors
|
||||
: options.message;
|
||||
|
||||
return JSON.stringify(output);
|
||||
}
|
||||
|
||||
//
|
||||
// json mode is intended for pretty printing multi-line json to the terminal
|
||||
//
|
||||
if (options.json || true === options.logstash) {
|
||||
if (typeof meta !== 'object' && meta != null) {
|
||||
meta = { meta: meta };
|
||||
}
|
||||
|
||||
output = exports.clone(meta) || {};
|
||||
output.level = options.level;
|
||||
output.message = output.message || '';
|
||||
|
||||
if (options.label) { output.label = options.label; }
|
||||
if (options.message) { output.message = options.message; }
|
||||
if (timestamp) { output.timestamp = timestamp; }
|
||||
|
||||
if (options.logstash === true) {
|
||||
// use logstash format
|
||||
var logstashOutput = {};
|
||||
if (output.message !== undefined) {
|
||||
logstashOutput['@message'] = output.message;
|
||||
delete output.message;
|
||||
}
|
||||
|
||||
if (output.timestamp !== undefined) {
|
||||
logstashOutput['@timestamp'] = output.timestamp;
|
||||
delete output.timestamp;
|
||||
}
|
||||
|
||||
logstashOutput['@fields'] = exports.clone(output);
|
||||
output = logstashOutput;
|
||||
}
|
||||
|
||||
if (typeof options.stringify === 'function') {
|
||||
return options.stringify(output);
|
||||
}
|
||||
|
||||
return JSON.stringify(output, function (key, value) {
|
||||
return value instanceof Buffer
|
||||
? value.toString('base64')
|
||||
: value;
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Remark: this should really be a call to `util.format`.
|
||||
//
|
||||
if (typeof options.formatter == 'function') {
|
||||
return String(options.formatter(exports.clone(options)));
|
||||
}
|
||||
|
||||
output = timestamp ? timestamp + ' - ' : '';
|
||||
if (showLevel) {
|
||||
output += options.colorize === 'all' || options.colorize === 'level' || options.colorize === true
|
||||
? config.colorize(options.level)
|
||||
: options.level;
|
||||
}
|
||||
|
||||
output += (options.align) ? '\t' : '';
|
||||
output += (timestamp || showLevel) ? ': ' : '';
|
||||
output += options.label ? ('[' + options.label + '] ') : '';
|
||||
output += options.colorize === 'all' || options.colorize === 'message'
|
||||
? config.colorize(options.level, options.message)
|
||||
: options.message;
|
||||
|
||||
if (meta !== null && meta !== undefined) {
|
||||
if (meta && meta instanceof Error && meta.stack) {
|
||||
meta = meta.stack;
|
||||
}
|
||||
|
||||
if (typeof meta !== 'object') {
|
||||
output += ' ' + meta;
|
||||
}
|
||||
else if (Object.keys(meta).length > 0) {
|
||||
if (typeof options.prettyPrint === 'function') {
|
||||
output += ' ' + options.prettyPrint(meta);
|
||||
} else if (options.prettyPrint) {
|
||||
output += ' ' + '\n' + util.inspect(meta, false, options.depth || null, options.colorize);
|
||||
} else if (
|
||||
options.humanReadableUnhandledException
|
||||
&& Object.keys(meta).length === 5
|
||||
&& meta.hasOwnProperty('date')
|
||||
&& meta.hasOwnProperty('process')
|
||||
&& meta.hasOwnProperty('os')
|
||||
&& meta.hasOwnProperty('trace')
|
||||
&& meta.hasOwnProperty('stack')) {
|
||||
|
||||
//
|
||||
// If meta carries unhandled exception data serialize the stack nicely
|
||||
//
|
||||
var stack = meta.stack;
|
||||
delete meta.stack;
|
||||
delete meta.trace;
|
||||
output += ' ' + exports.serialize(meta);
|
||||
output += '\n' + stack.join('\n');
|
||||
} else {
|
||||
output += ' ' + exports.serialize(meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
||||
|
||||
exports.capitalize = function (str) {
|
||||
return str && str[0].toUpperCase() + str.slice(1);
|
||||
};
|
||||
|
||||
//
|
||||
// ### function hash (str)
|
||||
// #### @str {string} String to hash.
|
||||
// Utility function for creating unique ids
|
||||
// e.g. Profiling incoming HTTP requests on the same tick
|
||||
//
|
||||
exports.hash = function (str) {
|
||||
return crypto.createHash('sha1').update(str).digest('hex');
|
||||
};
|
||||
|
||||
//
|
||||
// ### function pad (n)
|
||||
// Returns a padded string if `n < 10`.
|
||||
//
|
||||
exports.pad = function (n) {
|
||||
return n < 10 ? '0' + n.toString(10) : n.toString(10);
|
||||
};
|
||||
|
||||
//
|
||||
// ### function timestamp ()
|
||||
// Returns a timestamp string for the current time.
|
||||
//
|
||||
exports.timestamp = function () {
|
||||
return new Date().toISOString();
|
||||
};
|
||||
|
||||
//
|
||||
// ### function serialize (obj, key)
|
||||
// #### @obj {Object|literal} Object to serialize
|
||||
// #### @key {string} **Optional** Optional key represented by obj in a larger object
|
||||
// Performs simple comma-separated, `key=value` serialization for Loggly when
|
||||
// logging to non-JSON inputs.
|
||||
//
|
||||
exports.serialize = function (obj, key) {
|
||||
if (obj === null) {
|
||||
obj = 'null';
|
||||
}
|
||||
else if (obj === undefined) {
|
||||
obj = 'undefined';
|
||||
}
|
||||
else if (obj === false) {
|
||||
obj = 'false';
|
||||
}
|
||||
|
||||
if (typeof obj !== 'object') {
|
||||
return key ? key + '=' + obj : obj;
|
||||
}
|
||||
|
||||
if (obj instanceof Buffer) {
|
||||
return key ? key + '=' + obj.toString('base64') : obj.toString('base64');
|
||||
}
|
||||
|
||||
var msg = '',
|
||||
keys = Object.keys(obj),
|
||||
length = keys.length;
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
if (Array.isArray(obj[keys[i]])) {
|
||||
msg += keys[i] + '=[';
|
||||
|
||||
for (var j = 0, l = obj[keys[i]].length; j < l; j++) {
|
||||
msg += exports.serialize(obj[keys[i]][j]);
|
||||
if (j < l - 1) {
|
||||
msg += ', ';
|
||||
}
|
||||
}
|
||||
|
||||
msg += ']';
|
||||
}
|
||||
else if (obj[keys[i]] instanceof Date) {
|
||||
msg += keys[i] + '=' + obj[keys[i]];
|
||||
}
|
||||
else {
|
||||
msg += exports.serialize(obj[keys[i]], keys[i]);
|
||||
}
|
||||
|
||||
if (i < length - 1) {
|
||||
msg += ', ';
|
||||
}
|
||||
}
|
||||
|
||||
return msg;
|
||||
};
|
||||
|
||||
//
|
||||
// ### function tailFile (options, callback)
|
||||
// #### @options {Object} Options for tail.
|
||||
// #### @callback {function} Callback to execute on every line.
|
||||
// `tail -f` a file. Options must include file.
|
||||
//
|
||||
exports.tailFile = function(options, callback) {
|
||||
var buffer = new Buffer(64 * 1024)
|
||||
, decode = new StringDecoder('utf8')
|
||||
, stream = new Stream
|
||||
, buff = ''
|
||||
, pos = 0
|
||||
, row = 0;
|
||||
|
||||
if (options.start === -1) {
|
||||
delete options.start;
|
||||
}
|
||||
|
||||
stream.readable = true;
|
||||
stream.destroy = function() {
|
||||
stream.destroyed = true;
|
||||
stream.emit('end');
|
||||
stream.emit('close');
|
||||
};
|
||||
|
||||
fs.open(options.file, 'a+', '0644', function(err, fd) {
|
||||
if (err) {
|
||||
if (!callback) {
|
||||
stream.emit('error', err);
|
||||
} else {
|
||||
callback(err);
|
||||
}
|
||||
stream.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
(function read() {
|
||||
if (stream.destroyed) {
|
||||
fs.close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
return fs.read(fd, buffer, 0, buffer.length, pos, function(err, bytes) {
|
||||
if (err) {
|
||||
if (!callback) {
|
||||
stream.emit('error', err);
|
||||
} else {
|
||||
callback(err);
|
||||
}
|
||||
stream.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bytes) {
|
||||
if (buff) {
|
||||
if (options.start == null || row > options.start) {
|
||||
if (!callback) {
|
||||
stream.emit('line', buff);
|
||||
} else {
|
||||
callback(null, buff);
|
||||
}
|
||||
}
|
||||
row++;
|
||||
buff = '';
|
||||
}
|
||||
return setTimeout(read, 1000);
|
||||
}
|
||||
|
||||
var data = decode.write(buffer.slice(0, bytes));
|
||||
|
||||
if (!callback) {
|
||||
stream.emit('data', data);
|
||||
}
|
||||
|
||||
var data = (buff + data).split(/\n+/)
|
||||
, l = data.length - 1
|
||||
, i = 0;
|
||||
|
||||
for (; i < l; i++) {
|
||||
if (options.start == null || row > options.start) {
|
||||
if (!callback) {
|
||||
stream.emit('line', data[i]);
|
||||
} else {
|
||||
callback(null, data[i]);
|
||||
}
|
||||
}
|
||||
row++;
|
||||
}
|
||||
|
||||
buff = data[l];
|
||||
|
||||
pos += bytes;
|
||||
|
||||
return read();
|
||||
});
|
||||
})();
|
||||
});
|
||||
|
||||
if (!callback) {
|
||||
return stream;
|
||||
}
|
||||
|
||||
return stream.destroy;
|
||||
};
|
||||
|
||||
//
|
||||
// ### function stringArrayToSet (array)
|
||||
// #### @strArray {Array} Array of Set-elements as strings.
|
||||
// #### @errMsg {string} **Optional** Custom error message thrown on invalid input.
|
||||
// Returns a Set-like object with strArray's elements as keys (each with the value true).
|
||||
//
|
||||
exports.stringArrayToSet = function (strArray, errMsg) {
|
||||
if (typeof errMsg === 'undefined') {
|
||||
errMsg = 'Cannot make set from Array with non-string elements';
|
||||
}
|
||||
return strArray.reduce(function (set, el) {
|
||||
if (!(typeof el === 'string' || el instanceof String)) {
|
||||
throw new Error(errMsg);
|
||||
}
|
||||
set[el] = true;
|
||||
return set;
|
||||
}, Object.create(null));
|
||||
};
|
68
node_modules/winston/lib/winston/config.js
generated
vendored
Normal file
68
node_modules/winston/lib/winston/config.js
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* config.js: Default settings for all levels that winston knows about
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var colors = require('colors/safe');
|
||||
|
||||
// Fix colors not appearing in non-tty environments
|
||||
colors.enabled = true;
|
||||
|
||||
var config = exports,
|
||||
allColors = exports.allColors = {};
|
||||
|
||||
config.addColors = function (colors) {
|
||||
mixin(allColors, colors);
|
||||
};
|
||||
|
||||
config.colorize = function (level, message) {
|
||||
if (typeof message === 'undefined') message = level;
|
||||
|
||||
var colorized = message;
|
||||
if (allColors[level] instanceof Array) {
|
||||
for (var i = 0, l = allColors[level].length; i < l; ++i) {
|
||||
colorized = colors[allColors[level][i]](colorized);
|
||||
}
|
||||
}
|
||||
else if (allColors[level].match(/\s/)) {
|
||||
var colorArr = allColors[level].split(/\s+/);
|
||||
for (var i = 0; i < colorArr.length; ++i) {
|
||||
colorized = colors[colorArr[i]](colorized);
|
||||
}
|
||||
allColors[level] = colorArr;
|
||||
}
|
||||
else {
|
||||
colorized = colors[allColors[level]](colorized);
|
||||
}
|
||||
|
||||
return colorized;
|
||||
};
|
||||
|
||||
//
|
||||
// Export config sets
|
||||
//
|
||||
config.cli = require('./config/cli-config');
|
||||
config.npm = require('./config/npm-config');
|
||||
config.syslog = require('./config/syslog-config');
|
||||
|
||||
//
|
||||
// Add colors for pre-defined config sets
|
||||
//
|
||||
config.addColors(config.cli.colors);
|
||||
config.addColors(config.npm.colors);
|
||||
config.addColors(config.syslog.colors);
|
||||
|
||||
function mixin (target) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
|
||||
args.forEach(function (a) {
|
||||
var keys = Object.keys(a);
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
target[keys[i]] = a[keys[i]];
|
||||
}
|
||||
});
|
||||
return target;
|
||||
};
|
35
node_modules/winston/lib/winston/config/cli-config.js
generated
vendored
Normal file
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 = {
|
||||
error: 0,
|
||||
warn: 1,
|
||||
help: 2,
|
||||
data: 3,
|
||||
info: 4,
|
||||
debug: 5,
|
||||
prompt: 6,
|
||||
verbose: 7,
|
||||
input: 8,
|
||||
silly: 9,
|
||||
};
|
||||
|
||||
cliConfig.colors = {
|
||||
error: 'red',
|
||||
warn: 'yellow',
|
||||
help: 'cyan',
|
||||
data: 'grey',
|
||||
info: 'green',
|
||||
debug: 'blue',
|
||||
prompt: 'grey',
|
||||
verbose: 'cyan',
|
||||
input: 'grey',
|
||||
silly: 'magenta'
|
||||
};
|
27
node_modules/winston/lib/winston/config/npm-config.js
generated
vendored
Normal file
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 = {
|
||||
error: 0,
|
||||
warn: 1,
|
||||
info: 2,
|
||||
verbose: 3,
|
||||
debug: 4,
|
||||
silly: 5
|
||||
};
|
||||
|
||||
npmConfig.colors = {
|
||||
error: 'red',
|
||||
warn: 'yellow',
|
||||
info: 'green',
|
||||
verbose: 'cyan',
|
||||
debug: 'blue',
|
||||
silly: 'magenta'
|
||||
};
|
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'
|
||||
};
|
127
node_modules/winston/lib/winston/container.js
generated
vendored
Normal file
127
node_modules/winston/lib/winston/container.js
generated
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* container.js: Inversion of control container for winston logger instances
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var common = require('./common'),
|
||||
winston = require('../winston'),
|
||||
extend = require('util')._extend;
|
||||
|
||||
//
|
||||
// ### function Container (options)
|
||||
// #### @options {Object} Default pass-thru options for Loggers
|
||||
// Constructor function for the Container object responsible for managing
|
||||
// a set of `winston.Logger` instances based on string ids.
|
||||
//
|
||||
var Container = exports.Container = function (options) {
|
||||
this.loggers = {};
|
||||
this.options = options || {};
|
||||
this.default = {
|
||||
transports: [
|
||||
new winston.transports.Console({
|
||||
level: 'silly',
|
||||
colorize: false
|
||||
})
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// ### function get / add (id, options)
|
||||
// #### @id {string} Id of the Logger to get
|
||||
// #### @options {Object} **Optional** Options for the Logger instance
|
||||
// Retreives a `winston.Logger` instance for the specified `id`. If
|
||||
// an instance does not exist, one is created.
|
||||
//
|
||||
Container.prototype.get = Container.prototype.add = function (id, options) {
|
||||
var self = this,
|
||||
existing;
|
||||
|
||||
if (!this.loggers[id]) {
|
||||
//
|
||||
// Remark: Simple shallow clone for configuration options in case we pass in
|
||||
// instantiated protoypal objects
|
||||
//
|
||||
options = extend({}, options || this.options || this.default);
|
||||
existing = options.transports || this.options.transports;
|
||||
//
|
||||
// Remark: Make sure if we have an array of transports we slice it to make copies
|
||||
// of those references.
|
||||
//
|
||||
options.transports = existing ? existing.slice() : [];
|
||||
|
||||
if (options.transports.length === 0 && (!options || !options['console'])) {
|
||||
options.transports.push(this.default.transports[0]);
|
||||
}
|
||||
|
||||
Object.keys(options).forEach(function (key) {
|
||||
if (key === 'transports') {
|
||||
return;
|
||||
}
|
||||
|
||||
var name = common.capitalize(key);
|
||||
|
||||
if (!winston.transports[name]) {
|
||||
throw new Error('Cannot add unknown transport: ' + name);
|
||||
}
|
||||
|
||||
var namedOptions = options[key];
|
||||
namedOptions.id = id;
|
||||
options.transports.push(new (winston.transports[name])(namedOptions));
|
||||
});
|
||||
|
||||
this.loggers[id] = new winston.Logger(options);
|
||||
|
||||
this.loggers[id].on('close', function () {
|
||||
self._delete(id);
|
||||
});
|
||||
}
|
||||
|
||||
return this.loggers[id];
|
||||
};
|
||||
|
||||
//
|
||||
// ### function close (id)
|
||||
// #### @id {string} **Optional** Id of the Logger instance to find
|
||||
// Returns a boolean value indicating if this instance
|
||||
// has a logger with the specified `id`.
|
||||
//
|
||||
Container.prototype.has = function (id) {
|
||||
return !!this.loggers[id];
|
||||
};
|
||||
|
||||
//
|
||||
// ### function close (id)
|
||||
// #### @id {string} **Optional** Id of the Logger instance to close
|
||||
// Closes a `Logger` instance with the specified `id` if it exists.
|
||||
// If no `id` is supplied then all Loggers are closed.
|
||||
//
|
||||
Container.prototype.close = function (id) {
|
||||
var self = this;
|
||||
|
||||
function _close (id) {
|
||||
if (!self.loggers[id]) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.loggers[id].close();
|
||||
self._delete(id);
|
||||
}
|
||||
|
||||
return id ? _close(id) : Object.keys(this.loggers).forEach(function (id) {
|
||||
_close(id);
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// ### @private function _delete (id)
|
||||
// #### @id {string} Id of the Logger instance to delete from container
|
||||
// Deletes a `Logger` instance with the specified `id`.
|
||||
//
|
||||
Container.prototype._delete = function (id) {
|
||||
delete this.loggers[id];
|
||||
}
|
||||
|
56
node_modules/winston/lib/winston/exception.js
generated
vendored
Normal file
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(),
|
||||
}
|
||||
});
|
||||
};
|
723
node_modules/winston/lib/winston/logger.js
generated
vendored
Executable file
723
node_modules/winston/lib/winston/logger.js
generated
vendored
Executable file
@ -0,0 +1,723 @@
|
||||
/*
|
||||
* logger.js: Core logger object used by winston.
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var events = require('events'),
|
||||
util = require('util'),
|
||||
async = require('async'),
|
||||
config = require('./config'),
|
||||
common = require('./common'),
|
||||
exception = require('./exception'),
|
||||
Stream = require('stream').Stream;
|
||||
|
||||
const formatRegExp = /%[sdj%]/g;
|
||||
|
||||
//
|
||||
// ### function Logger (options)
|
||||
// #### @options {Object} Options for this instance.
|
||||
// Constructor function for the Logger object responsible
|
||||
// for persisting log messages and metadata to one or more transports.
|
||||
//
|
||||
var Logger = exports.Logger = function (options) {
|
||||
events.EventEmitter.call(this);
|
||||
this.configure(options);
|
||||
};
|
||||
|
||||
//
|
||||
// Inherit from `events.EventEmitter`.
|
||||
//
|
||||
util.inherits(Logger, events.EventEmitter);
|
||||
|
||||
//
|
||||
// ### function configure (options)
|
||||
// This will wholesale reconfigure this instance by:
|
||||
// 1. Resetting all transports. Older transports will be removed implicitly.
|
||||
// 2. Set all other options including levels, colors, rewriters, filters,
|
||||
// exceptionHandlers, etc.
|
||||
//
|
||||
Logger.prototype.configure = function (options) {
|
||||
var self = this;
|
||||
|
||||
//
|
||||
// If we have already been setup with transports
|
||||
// then remove them before proceeding.
|
||||
//
|
||||
if (Array.isArray(this._names) && this._names.length) {
|
||||
this.clear();
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
this.transports = {};
|
||||
this._names = [];
|
||||
|
||||
if (options.transports) {
|
||||
options.transports.forEach(function (transport) {
|
||||
self.add(transport, null, true);
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Set Levels and default logging level
|
||||
//
|
||||
this.padLevels = options.padLevels || false;
|
||||
this.setLevels(options.levels);
|
||||
if (options.colors) {
|
||||
config.addColors(options.colors);
|
||||
}
|
||||
|
||||
//
|
||||
// Hoist other options onto this instance.
|
||||
//
|
||||
this.level = options.level || 'info';
|
||||
this.emitErrs = options.emitErrs || false;
|
||||
this.stripColors = options.stripColors || false;
|
||||
this.exitOnError = typeof options.exitOnError !== 'undefined'
|
||||
? options.exitOnError
|
||||
: true;
|
||||
|
||||
//
|
||||
// Setup internal state as empty Objects even though it is
|
||||
// defined lazily later to ensure a strong existential API contract.
|
||||
//
|
||||
this.exceptionHandlers = {};
|
||||
this.profilers = {};
|
||||
|
||||
['rewriters', 'filters'].forEach(function (kind) {
|
||||
self[kind] = Array.isArray(options[kind])
|
||||
? options[kind]
|
||||
: [];
|
||||
});
|
||||
|
||||
if (options.exceptionHandlers) {
|
||||
this.handleExceptions(options.exceptionHandlers);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// ### function log (level, msg, [meta], callback)
|
||||
// #### @level {string} Level at which to log the message.
|
||||
// #### @msg {string} Message to log
|
||||
// #### @meta {Object} **Optional** Additional metadata to attach
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Core logging method exposed to Winston. Metadata is optional.
|
||||
//
|
||||
Logger.prototype.log = function (level) {
|
||||
var args = Array.prototype.slice.call(arguments, 1),
|
||||
self = this,
|
||||
transports;
|
||||
|
||||
while (args[args.length - 1] === null) {
|
||||
args.pop();
|
||||
}
|
||||
|
||||
//
|
||||
// Determining what is `meta` and what are arguments for string interpolation
|
||||
// turns out to be VERY tricky. e.g. in the cases like this:
|
||||
//
|
||||
// logger.info('No interpolation symbols', 'ok', 'why', { meta: 'is-this' });
|
||||
//
|
||||
var callback = typeof args[args.length - 1] === 'function'
|
||||
? args.pop()
|
||||
: null;
|
||||
|
||||
//
|
||||
// Handle errors appropriately.
|
||||
//
|
||||
function onError(err) {
|
||||
if (callback) {
|
||||
callback(err);
|
||||
}
|
||||
else if (self.emitErrs) {
|
||||
self.emit('error', err);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._names.length === 0) {
|
||||
return onError(new Error('Cannot log with no transports.'));
|
||||
}
|
||||
else if (typeof self.levels[level] === 'undefined') {
|
||||
return onError(new Error('Unknown log level: ' + level));
|
||||
}
|
||||
|
||||
//
|
||||
// If there are no transports that match the level
|
||||
// then be eager and return. This could potentially be calculated
|
||||
// during `setLevels` for more performance gains.
|
||||
//
|
||||
var targets = this._names.filter(function (name) {
|
||||
var transport = self.transports[name];
|
||||
return (transport.level && self.levels[transport.level] >= self.levels[level])
|
||||
|| (!transport.level && self.levels[self.level] >= self.levels[level]);
|
||||
});
|
||||
|
||||
if (!targets.length) {
|
||||
if (callback) { callback(); }
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Determining what is `meta` and what are arguments for string interpolation
|
||||
// turns out to be VERY tricky. e.g. in the cases like this:
|
||||
//
|
||||
// logger.info('No interpolation symbols', 'ok', 'why', { meta: 'is-this' });
|
||||
//
|
||||
var metaType = Object.prototype.toString.call(args[args.length - 1]),
|
||||
fmtMatch = args[0] && args[0].match && args[0].match(formatRegExp),
|
||||
isFormat = fmtMatch && fmtMatch.length,
|
||||
validMeta = !isFormat
|
||||
? metaType === '[object Object]' || metaType === '[object Error]' || metaType === '[object Array]'
|
||||
: metaType === '[object Object]',
|
||||
meta = validMeta ? args.pop() : {},
|
||||
msg = util.format.apply(null, args);
|
||||
|
||||
//
|
||||
// Respond to the callback.
|
||||
//
|
||||
function finish(err) {
|
||||
if (callback) {
|
||||
if (err) return callback(err);
|
||||
callback(null, level, msg, meta);
|
||||
}
|
||||
|
||||
callback = null;
|
||||
if (!err) {
|
||||
self.emit('logged', level, msg, meta);
|
||||
}
|
||||
}
|
||||
|
||||
// If we should pad for levels, do so
|
||||
if (this.padLevels) {
|
||||
msg = new Array(this.levelLength - level.length + 1).join(' ') + msg;
|
||||
}
|
||||
|
||||
this.rewriters.forEach(function (rewriter) {
|
||||
meta = rewriter(level, msg, meta, self);
|
||||
});
|
||||
|
||||
this.filters.forEach(function(filter) {
|
||||
var filtered = filter(level, msg, meta, self);
|
||||
if (typeof filtered === 'string')
|
||||
msg = filtered;
|
||||
else {
|
||||
msg = filtered.msg;
|
||||
meta = filtered.meta;
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
// For consideration of terminal 'color" programs like colors.js,
|
||||
// which can add ANSI escape color codes to strings, we destyle the
|
||||
// ANSI color escape codes when `this.stripColors` is set.
|
||||
//
|
||||
// see: http://en.wikipedia.org/wiki/ANSI_escape_code
|
||||
//
|
||||
if (this.stripColors) {
|
||||
var code = /\u001b\[(\d+(;\d+)*)?m/g;
|
||||
msg = ('' + msg).replace(code, '');
|
||||
}
|
||||
|
||||
//
|
||||
// Log for each transport and emit 'logging' event
|
||||
//
|
||||
function transportLog(name, next) {
|
||||
var transport = self.transports[name];
|
||||
transport.log(level, msg, meta, function (err) {
|
||||
if (err) {
|
||||
err.transport = transport;
|
||||
finish(err);
|
||||
return next();
|
||||
}
|
||||
|
||||
self.emit('logging', transport, level, msg, meta);
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
async.forEach(targets, transportLog, finish);
|
||||
return this;
|
||||
};
|
||||
|
||||
//
|
||||
// ### function query (options, callback)
|
||||
// #### @options {Object} Query options for this instance.
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Queries the all transports for this instance with the specified `options`.
|
||||
// This will aggregate each transport's results into one object containing
|
||||
// a property per transport.
|
||||
//
|
||||
Logger.prototype.query = function (options, callback) {
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
var self = this,
|
||||
options = options || {},
|
||||
results = {},
|
||||
query = common.clone(options.query) || {},
|
||||
transports;
|
||||
|
||||
//
|
||||
// Helper function to query a single transport
|
||||
//
|
||||
function queryTransport(transport, next) {
|
||||
if (options.query) {
|
||||
options.query = transport.formatQuery(query);
|
||||
}
|
||||
|
||||
transport.query(options, function (err, results) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
next(null, transport.formatResults(results, options.format));
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Helper function to accumulate the results from
|
||||
// `queryTransport` into the `results`.
|
||||
//
|
||||
function addResults(transport, next) {
|
||||
queryTransport(transport, function (err, result) {
|
||||
//
|
||||
// queryTransport could potentially invoke the callback
|
||||
// multiple times since Transport code can be unpredictable.
|
||||
//
|
||||
if (next) {
|
||||
result = err || result;
|
||||
if (result) {
|
||||
results[transport.name] = result;
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
next = null;
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// If an explicit transport is being queried then
|
||||
// respond with the results from only that transport
|
||||
//
|
||||
if (options.transport) {
|
||||
options.transport = options.transport.toLowerCase();
|
||||
return queryTransport(this.transports[options.transport], callback);
|
||||
}
|
||||
|
||||
//
|
||||
// Create a list of all transports for this instance.
|
||||
//
|
||||
transports = this._names.map(function (name) {
|
||||
return self.transports[name];
|
||||
}).filter(function (transport) {
|
||||
return !!transport.query;
|
||||
});
|
||||
|
||||
//
|
||||
// Iterate over the transports in parallel setting the
|
||||
// appropriate key in the `results`
|
||||
//
|
||||
async.forEach(transports, addResults, function () {
|
||||
callback(null, results);
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// ### function stream (options)
|
||||
// #### @options {Object} Stream options for this instance.
|
||||
// Returns a log stream for all transports. Options object is optional.
|
||||
//
|
||||
Logger.prototype.stream = function (options) {
|
||||
var self = this,
|
||||
options = options || {},
|
||||
out = new Stream,
|
||||
streams = [],
|
||||
transports;
|
||||
|
||||
if (options.transport) {
|
||||
var transport = this.transports[options.transport];
|
||||
delete options.transport;
|
||||
if (transport && transport.stream) {
|
||||
return transport.stream(options);
|
||||
}
|
||||
}
|
||||
|
||||
out._streams = streams;
|
||||
out.destroy = function () {
|
||||
var i = streams.length;
|
||||
while (i--) streams[i].destroy();
|
||||
};
|
||||
|
||||
//
|
||||
// Create a list of all transports for this instance.
|
||||
//
|
||||
transports = this._names.map(function (name) {
|
||||
return self.transports[name];
|
||||
}).filter(function (transport) {
|
||||
return !!transport.stream;
|
||||
});
|
||||
|
||||
transports.forEach(function (transport) {
|
||||
var stream = transport.stream(options);
|
||||
if (!stream) return;
|
||||
|
||||
streams.push(stream);
|
||||
|
||||
stream.on('log', function (log) {
|
||||
log.transport = log.transport || [];
|
||||
log.transport.push(transport.name);
|
||||
out.emit('log', log);
|
||||
});
|
||||
|
||||
stream.on('error', function (err) {
|
||||
err.transport = err.transport || [];
|
||||
err.transport.push(transport.name);
|
||||
out.emit('error', err);
|
||||
});
|
||||
});
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
//
|
||||
// ### function close ()
|
||||
// Cleans up resources (streams, event listeners) for all
|
||||
// transports associated with this instance (if necessary).
|
||||
//
|
||||
Logger.prototype.close = function () {
|
||||
var self = this;
|
||||
|
||||
this._names.forEach(function (name) {
|
||||
var transport = self.transports[name];
|
||||
if (transport && transport.close) {
|
||||
transport.close();
|
||||
}
|
||||
});
|
||||
|
||||
this.emit('close');
|
||||
};
|
||||
|
||||
//
|
||||
// ### function handleExceptions ([tr0, tr1...] || tr0, tr1, ...)
|
||||
// Handles `uncaughtException` events for the current process by
|
||||
// ADDING any handlers passed in.
|
||||
//
|
||||
Logger.prototype.handleExceptions = function () {
|
||||
var args = Array.prototype.slice.call(arguments),
|
||||
handlers = [],
|
||||
self = this;
|
||||
|
||||
args.forEach(function (a) {
|
||||
if (Array.isArray(a)) {
|
||||
handlers = handlers.concat(a);
|
||||
}
|
||||
else {
|
||||
handlers.push(a);
|
||||
}
|
||||
});
|
||||
|
||||
this.exceptionHandlers = this.exceptionHandlers || {};
|
||||
handlers.forEach(function (handler) {
|
||||
self.exceptionHandlers[handler.name] = handler;
|
||||
});
|
||||
|
||||
this._hnames = Object.keys(self.exceptionHandlers);
|
||||
|
||||
if (!this.catchExceptions) {
|
||||
this.catchExceptions = this._uncaughtException.bind(this);
|
||||
process.on('uncaughtException', this.catchExceptions);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// ### function unhandleExceptions ()
|
||||
// Removes any handlers to `uncaughtException` events
|
||||
// for the current process
|
||||
//
|
||||
Logger.prototype.unhandleExceptions = function () {
|
||||
var self = this;
|
||||
|
||||
if (this.catchExceptions) {
|
||||
Object.keys(this.exceptionHandlers).forEach(function (name) {
|
||||
var handler = self.exceptionHandlers[name];
|
||||
if (handler.close) {
|
||||
handler.close();
|
||||
}
|
||||
});
|
||||
|
||||
this.exceptionHandlers = {};
|
||||
Object.keys(this.transports).forEach(function (name) {
|
||||
var transport = self.transports[name];
|
||||
if (transport.handleExceptions) {
|
||||
transport.handleExceptions = false;
|
||||
}
|
||||
})
|
||||
|
||||
process.removeListener('uncaughtException', this.catchExceptions);
|
||||
this.catchExceptions = false;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// ### function add (transport, [options])
|
||||
// #### @transport {Transport} Prototype of the Transport object to add.
|
||||
// #### @options {Object} **Optional** Options for the Transport to add.
|
||||
// #### @instance {Boolean} **Optional** Value indicating if `transport` is already instantiated.
|
||||
// Adds a transport of the specified type to this instance.
|
||||
//
|
||||
Logger.prototype.add = function (transport, options, created) {
|
||||
var instance = created ? transport : (new (transport)(options));
|
||||
|
||||
if (!instance.name && !instance.log) {
|
||||
throw new Error('Unknown transport with no log() method');
|
||||
}
|
||||
else if (this.transports[instance.name]) {
|
||||
throw new Error('Transport already attached: ' + instance.name);
|
||||
}
|
||||
|
||||
this.transports[instance.name] = instance;
|
||||
this._names = Object.keys(this.transports);
|
||||
|
||||
//
|
||||
// Listen for the `error` event on the new Transport
|
||||
//
|
||||
instance._onError = this._onError.bind(this, instance)
|
||||
if (!created) {
|
||||
instance.on('error', instance._onError);
|
||||
}
|
||||
|
||||
//
|
||||
// If this transport has `handleExceptions` set to `true`
|
||||
// and we are not already handling exceptions, do so.
|
||||
//
|
||||
if (instance.handleExceptions && !this.catchExceptions) {
|
||||
this.handleExceptions();
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
//
|
||||
// ### function clear ()
|
||||
// Remove all transports from this instance
|
||||
//
|
||||
Logger.prototype.clear = function () {
|
||||
Object.keys(this.transports).forEach(function (name) {
|
||||
this.remove({ name: name });
|
||||
}, this);
|
||||
};
|
||||
|
||||
//
|
||||
// ### function remove (transport)
|
||||
// #### @transport {Transport|String} Transport or Name to remove.
|
||||
// Removes a transport of the specified type from this instance.
|
||||
//
|
||||
Logger.prototype.remove = function (transport) {
|
||||
var name = typeof transport !== 'string'
|
||||
? transport.name || transport.prototype.name
|
||||
: transport;
|
||||
|
||||
if (!this.transports[name]) {
|
||||
throw new Error('Transport ' + name + ' not attached to this instance');
|
||||
}
|
||||
|
||||
var instance = this.transports[name];
|
||||
delete this.transports[name];
|
||||
this._names = Object.keys(this.transports);
|
||||
|
||||
if (instance.close) {
|
||||
instance.close();
|
||||
}
|
||||
|
||||
if (instance._onError) {
|
||||
instance.removeListener('error', instance._onError);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
//
|
||||
// ### function startTimer ()
|
||||
// Returns an object corresponding to a specific timing. When done
|
||||
// is called the timer will finish and log the duration. e.g.:
|
||||
//
|
||||
// timer = winston.startTimer()
|
||||
// setTimeout(function(){
|
||||
// timer.done("Logging message");
|
||||
// }, 1000);
|
||||
//
|
||||
Logger.prototype.startTimer = function () {
|
||||
return new ProfileHandler(this);
|
||||
};
|
||||
|
||||
//
|
||||
// ### function profile (id, [msg, meta, callback])
|
||||
// #### @id {string} Unique id of the profiler
|
||||
// #### @msg {string} **Optional** Message to log
|
||||
// #### @meta {Object} **Optional** Additional metadata to attach
|
||||
// #### @callback {function} **Optional** Continuation to respond to when complete.
|
||||
// Tracks the time inbetween subsequent calls to this method
|
||||
// with the same `id` parameter. The second call to this method
|
||||
// will log the difference in milliseconds along with the message.
|
||||
//
|
||||
Logger.prototype.profile = function (id) {
|
||||
var now = Date.now(), then, args,
|
||||
msg, meta, callback;
|
||||
|
||||
if (this.profilers[id]) {
|
||||
then = this.profilers[id];
|
||||
delete this.profilers[id];
|
||||
|
||||
// Support variable arguments: msg, meta, callback
|
||||
args = Array.prototype.slice.call(arguments);
|
||||
callback = typeof args[args.length - 1] === 'function' ? args.pop() : null;
|
||||
meta = typeof args[args.length - 1] === 'object' ? args.pop() : {};
|
||||
msg = args.length === 2 ? args[1] : id;
|
||||
|
||||
// Set the duration property of the metadata
|
||||
meta.durationMs = now - then;
|
||||
return this.info(msg, meta, callback);
|
||||
}
|
||||
else {
|
||||
this.profilers[id] = now;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
//
|
||||
// ### function setLevels (target)
|
||||
// #### @target {Object} Target levels to use on this instance
|
||||
// Sets the `target` levels specified on this instance.
|
||||
//
|
||||
Logger.prototype.setLevels = function (target) {
|
||||
return common.setLevels(this, this.levels, target);
|
||||
};
|
||||
|
||||
//
|
||||
// ### function cli ()
|
||||
// Configures this instance to have the default
|
||||
// settings for command-line interfaces: no timestamp,
|
||||
// colors enabled, padded output, and additional levels.
|
||||
//
|
||||
Logger.prototype.cli = function () {
|
||||
this.padLevels = true;
|
||||
this.setLevels(config.cli.levels);
|
||||
config.addColors(config.cli.colors);
|
||||
|
||||
if (this.transports.console) {
|
||||
this.transports.console.colorize = this.transports.console.colorize || true;
|
||||
this.transports.console.timestamp = this.transports.console.timestamp || false;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
//
|
||||
// ### @private function _uncaughtException (err)
|
||||
// #### @err {Error} Error to handle
|
||||
// Logs all relevant information around the `err` and
|
||||
// exits the current process.
|
||||
//
|
||||
Logger.prototype._uncaughtException = function (err) {
|
||||
var self = this,
|
||||
responded = false,
|
||||
info = exception.getAllInfo(err),
|
||||
handlers = this._getExceptionHandlers(),
|
||||
timeout,
|
||||
doExit;
|
||||
|
||||
//
|
||||
// Calculate if we should exit on this error
|
||||
//
|
||||
doExit = typeof this.exitOnError === 'function'
|
||||
? this.exitOnError(err)
|
||||
: this.exitOnError;
|
||||
|
||||
function logAndWait(transport, next) {
|
||||
transport.logException('uncaughtException: ' + (err.message || err), info, next, err);
|
||||
}
|
||||
|
||||
function gracefulExit() {
|
||||
if (doExit && !responded) {
|
||||
//
|
||||
// Remark: Currently ignoring any exceptions from transports
|
||||
// when catching uncaught exceptions.
|
||||
//
|
||||
clearTimeout(timeout);
|
||||
responded = true;
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!handlers || handlers.length === 0) {
|
||||
return gracefulExit();
|
||||
}
|
||||
|
||||
//
|
||||
// Log to all transports and allow the operation to take
|
||||
// only up to `3000ms`.
|
||||
//
|
||||
async.forEach(handlers, logAndWait, gracefulExit);
|
||||
if (doExit) {
|
||||
timeout = setTimeout(gracefulExit, 3000);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// ### @private function _getExceptionHandlers ()
|
||||
// Returns the list of transports and exceptionHandlers
|
||||
// for this instance.
|
||||
//
|
||||
Logger.prototype._getExceptionHandlers = function () {
|
||||
var self = this;
|
||||
|
||||
return this._hnames.map(function (name) {
|
||||
return self.exceptionHandlers[name];
|
||||
}).concat(this._names.map(function (name) {
|
||||
return self.transports[name].handleExceptions && self.transports[name];
|
||||
})).filter(Boolean);
|
||||
};
|
||||
|
||||
//
|
||||
// ### @private function _onError (transport, err)
|
||||
// #### @transport {Object} Transport on which the error occured
|
||||
// #### @err {Error} Error that occurred on the transport
|
||||
// Bubbles the error, `err`, that occured on the specified `transport`
|
||||
// up from this instance if `emitErrs` has been set.
|
||||
//
|
||||
Logger.prototype._onError = function (transport, err) {
|
||||
if (this.emitErrs) {
|
||||
this.emit('error', err, transport);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// ### @private ProfileHandler
|
||||
// Constructor function for the ProfileHandler instance used by
|
||||
// `Logger.prototype.startTimer`. When done is called the timer
|
||||
// will finish and log the duration.
|
||||
//
|
||||
function ProfileHandler(logger) {
|
||||
this.logger = logger;
|
||||
this.start = Date.now();
|
||||
}
|
||||
|
||||
//
|
||||
// ### function done (msg)
|
||||
// Ends the current timer (i.e. ProfileHandler) instance and
|
||||
// logs the `msg` along with the duration since creation.
|
||||
//
|
||||
ProfileHandler.prototype.done = function (msg) {
|
||||
var args = Array.prototype.slice.call(arguments),
|
||||
callback = typeof args[args.length - 1] === 'function' ? args.pop() : null,
|
||||
meta = typeof args[args.length - 1] === 'object' ? args.pop() : {};
|
||||
|
||||
meta.duration = (Date.now()) - this.start + 'ms';
|
||||
return this.logger.info(msg, meta, callback);
|
||||
};
|
29
node_modules/winston/lib/winston/transports.js
generated
vendored
Normal file
29
node_modules/winston/lib/winston/transports.js
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* transports.js: Set of all transports Winston knows about
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var path = require('path');
|
||||
|
||||
//
|
||||
// Setup all transports as lazy-loaded getters.
|
||||
//
|
||||
Object.defineProperties(
|
||||
exports,
|
||||
['Console', 'File', 'Http', 'Memory']
|
||||
.reduce(function (acc, name) {
|
||||
acc[name] = {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
var fullpath = path.join(__dirname, 'transports', name.toLowerCase());
|
||||
return exports[name] = require(fullpath)[name];
|
||||
}
|
||||
};
|
||||
|
||||
return acc;
|
||||
}, {})
|
||||
);
|
130
node_modules/winston/lib/winston/transports/console.js
generated
vendored
Normal file
130
node_modules/winston/lib/winston/transports/console.js
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* console.js: Transport for outputting to the console
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var events = require('events'),
|
||||
os = require('os'),
|
||||
util = require('util'),
|
||||
common = require('../common'),
|
||||
Transport = require('./transport').Transport;
|
||||
|
||||
//
|
||||
// ### function Console (options)
|
||||
// #### @options {Object} Options for this instance.
|
||||
// Constructor function for the Console transport object responsible
|
||||
// for persisting log messages and metadata to a terminal or TTY.
|
||||
//
|
||||
var Console = exports.Console = function (options) {
|
||||
Transport.call(this, options);
|
||||
options = options || {};
|
||||
|
||||
this.json = options.json || false;
|
||||
this.colorize = options.colorize || false;
|
||||
this.prettyPrint = options.prettyPrint || false;
|
||||
this.timestamp = typeof options.timestamp !== 'undefined' ? options.timestamp : false;
|
||||
this.showLevel = options.showLevel === undefined ? true : options.showLevel;
|
||||
this.label = options.label || null;
|
||||
this.logstash = options.logstash || false;
|
||||
this.depth = options.depth || null;
|
||||
this.align = options.align || false;
|
||||
this.stderrLevels = setStderrLevels(options.stderrLevels, options.debugStdout);
|
||||
this.eol = options.eol || os.EOL;
|
||||
|
||||
if (this.json) {
|
||||
this.stringify = options.stringify || function (obj) {
|
||||
return JSON.stringify(obj, null, 2);
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Convert stderrLevels into an Object for faster key-lookup times than an Array.
|
||||
//
|
||||
// For backwards compatibility, stderrLevels defaults to ['error', 'debug']
|
||||
// or ['error'] depending on whether options.debugStdout is true.
|
||||
//
|
||||
function setStderrLevels (levels, debugStdout) {
|
||||
var defaultMsg = 'Cannot have non-string elements in stderrLevels Array';
|
||||
if (debugStdout) {
|
||||
if (levels) {
|
||||
//
|
||||
// Don't allow setting both debugStdout and stderrLevels together,
|
||||
// since this could cause behaviour a programmer might not expect.
|
||||
//
|
||||
throw new Error('Cannot set debugStdout and stderrLevels together');
|
||||
}
|
||||
|
||||
return common.stringArrayToSet(['error'], defaultMsg);
|
||||
}
|
||||
|
||||
if (!levels) {
|
||||
return common.stringArrayToSet(['error', 'debug'], defaultMsg);
|
||||
} else if (!(Array.isArray(levels))) {
|
||||
throw new Error('Cannot set stderrLevels to type other than Array');
|
||||
}
|
||||
|
||||
return common.stringArrayToSet(levels, defaultMsg);
|
||||
};
|
||||
};
|
||||
|
||||
//
|
||||
// Inherit from `winston.Transport`.
|
||||
//
|
||||
util.inherits(Console, Transport);
|
||||
|
||||
//
|
||||
// Expose the name of this Transport on the prototype
|
||||
//
|
||||
Console.prototype.name = 'console';
|
||||
|
||||
//
|
||||
// ### function log (level, msg, [meta], callback)
|
||||
// #### @level {string} Level at which to log the message.
|
||||
// #### @msg {string} Message to log
|
||||
// #### @meta {Object} **Optional** Additional metadata to attach
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Core logging method exposed to Winston. Metadata is optional.
|
||||
//
|
||||
Console.prototype.log = function (level, msg, meta, callback) {
|
||||
if (this.silent) {
|
||||
return callback(null, true);
|
||||
}
|
||||
|
||||
var self = this,
|
||||
output;
|
||||
|
||||
output = common.log({
|
||||
colorize: this.colorize,
|
||||
json: this.json,
|
||||
level: level,
|
||||
message: msg,
|
||||
meta: meta,
|
||||
stringify: this.stringify,
|
||||
timestamp: this.timestamp,
|
||||
showLevel: this.showLevel,
|
||||
prettyPrint: this.prettyPrint,
|
||||
raw: this.raw,
|
||||
label: this.label,
|
||||
logstash: this.logstash,
|
||||
depth: this.depth,
|
||||
formatter: this.formatter,
|
||||
align: this.align,
|
||||
humanReadableUnhandledException: this.humanReadableUnhandledException
|
||||
});
|
||||
|
||||
if (this.stderrLevels[level]) {
|
||||
process.stderr.write(output + '\n');
|
||||
} else {
|
||||
process.stdout.write(output + this.eol);
|
||||
}
|
||||
|
||||
//
|
||||
// Emit the `logged` event immediately because the event loop
|
||||
// will not exit until `process.stdout` has drained anyway.
|
||||
//
|
||||
self.emit('logged');
|
||||
callback(null, true);
|
||||
};
|
678
node_modules/winston/lib/winston/transports/file.js
generated
vendored
Normal file
678
node_modules/winston/lib/winston/transports/file.js
generated
vendored
Normal file
@ -0,0 +1,678 @@
|
||||
/*
|
||||
* file.js: Transport for outputting to a local log file
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var events = require('events'),
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
util = require('util'),
|
||||
async = require('async'),
|
||||
zlib = require('zlib'),
|
||||
common = require('../common'),
|
||||
Transport = require('./transport').Transport,
|
||||
isWritable = require('isstream').isWritable,
|
||||
Stream = require('stream').Stream,
|
||||
os = require('os');
|
||||
|
||||
//
|
||||
// ### function File (options)
|
||||
// #### @options {Object} Options for this instance.
|
||||
// Constructor function for the File transport object responsible
|
||||
// for persisting log messages and metadata to one or more files.
|
||||
//
|
||||
var File = exports.File = function (options) {
|
||||
var self = this;
|
||||
Transport.call(this, options);
|
||||
|
||||
//
|
||||
// Helper function which throws an `Error` in the event
|
||||
// that any of the rest of the arguments is present in `options`.
|
||||
//
|
||||
function throwIf (target /*, illegal... */) {
|
||||
Array.prototype.slice.call(arguments, 1).forEach(function (name) {
|
||||
if (options[name]) {
|
||||
throw new Error('Cannot set ' + name + ' and ' + target + 'together');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (options.filename || options.dirname) {
|
||||
throwIf('filename or dirname', 'stream');
|
||||
this._basename = this.filename = options.filename
|
||||
? path.basename(options.filename)
|
||||
: 'winston.log';
|
||||
|
||||
this.dirname = options.dirname || path.dirname(options.filename);
|
||||
this.options = options.options || { flags: 'a' };
|
||||
|
||||
//
|
||||
// "24 bytes" is maybe a good value for logging lines.
|
||||
//
|
||||
this.options.highWaterMark = this.options.highWaterMark || 24;
|
||||
}
|
||||
else if (options.stream) {
|
||||
throwIf('stream', 'filename', 'maxsize');
|
||||
this._stream = options.stream;
|
||||
this._isStreams2 = isWritable(this._stream);
|
||||
this._stream.on('error', function(error){
|
||||
self.emit('error', error);
|
||||
});
|
||||
//
|
||||
// We need to listen for drain events when
|
||||
// write() returns false. This can make node
|
||||
// mad at times.
|
||||
//
|
||||
this._stream.setMaxListeners(Infinity);
|
||||
}
|
||||
else {
|
||||
throw new Error('Cannot log to file without filename or stream.');
|
||||
}
|
||||
|
||||
this.json = options.json !== false;
|
||||
this.logstash = options.logstash || false;
|
||||
this.colorize = options.colorize || false;
|
||||
this.maxsize = options.maxsize || null;
|
||||
this.rotationFormat = options.rotationFormat || false;
|
||||
this.zippedArchive = options.zippedArchive || false;
|
||||
this.maxFiles = options.maxFiles || null;
|
||||
this.prettyPrint = options.prettyPrint || false;
|
||||
this.label = options.label || null;
|
||||
this.timestamp = options.timestamp != null ? options.timestamp : true;
|
||||
this.eol = options.eol || os.EOL;
|
||||
this.tailable = options.tailable || false;
|
||||
this.depth = options.depth || null;
|
||||
this.showLevel = options.showLevel === undefined ? true : options.showLevel;
|
||||
this.maxRetries = options.maxRetries || 2;
|
||||
|
||||
if (this.json) {
|
||||
this.stringify = options.stringify;
|
||||
}
|
||||
|
||||
//
|
||||
// Internal state variables representing the number
|
||||
// of files this instance has created and the current
|
||||
// size (in bytes) of the current logfile.
|
||||
//
|
||||
this._size = 0;
|
||||
this._created = 0;
|
||||
this._buffer = [];
|
||||
this._draining = false;
|
||||
this._opening = false;
|
||||
this._failures = 0;
|
||||
this._archive = null;
|
||||
};
|
||||
|
||||
//
|
||||
// Inherit from `winston.Transport`.
|
||||
//
|
||||
util.inherits(File, Transport);
|
||||
|
||||
//
|
||||
// Expose the name of this Transport on the prototype
|
||||
//
|
||||
File.prototype.name = 'file';
|
||||
|
||||
//
|
||||
// ### function log (level, msg, [meta], callback)
|
||||
// #### @level {string} Level at which to log the message.
|
||||
// #### @msg {string} Message to log
|
||||
// #### @meta {Object} **Optional** Additional metadata to attach
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Core logging method exposed to Winston. Metadata is optional.
|
||||
//
|
||||
File.prototype.log = function (level, msg, meta, callback) {
|
||||
if (this.silent) {
|
||||
return callback(null, true);
|
||||
}
|
||||
|
||||
//
|
||||
// If failures exceeds maxRetries then we can't access the
|
||||
// stream. In this case we need to perform a noop and return
|
||||
// an error.
|
||||
//
|
||||
if (this._failures >= this.maxRetries) {
|
||||
return callback(new Error('Transport is in a failed state.'));
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
if (typeof msg !== 'string') {
|
||||
msg = '' + msg;
|
||||
}
|
||||
|
||||
var output = common.log({
|
||||
level: level,
|
||||
message: msg,
|
||||
meta: meta,
|
||||
json: this.json,
|
||||
logstash: this.logstash,
|
||||
colorize: this.colorize,
|
||||
prettyPrint: this.prettyPrint,
|
||||
timestamp: this.timestamp,
|
||||
showLevel: this.showLevel,
|
||||
stringify: this.stringify,
|
||||
label: this.label,
|
||||
depth: this.depth,
|
||||
formatter: this.formatter,
|
||||
humanReadableUnhandledException: this.humanReadableUnhandledException
|
||||
});
|
||||
|
||||
if (typeof output === 'string') {
|
||||
output += this.eol;
|
||||
}
|
||||
|
||||
if (!this.filename) {
|
||||
//
|
||||
// If there is no `filename` on this instance then it was configured
|
||||
// with a raw `WriteableStream` instance and we should not perform any
|
||||
// size restrictions.
|
||||
//
|
||||
this._write(output, callback);
|
||||
this._size += output.length;
|
||||
this._lazyDrain();
|
||||
}
|
||||
else {
|
||||
this.open(function (err) {
|
||||
if (err) {
|
||||
//
|
||||
// If there was an error enqueue the message
|
||||
//
|
||||
return self._buffer.push([output, callback]);
|
||||
}
|
||||
|
||||
self._write(output, callback);
|
||||
self._size += output.length;
|
||||
self._lazyDrain();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// ### function _write (data, cb)
|
||||
// #### @data {String|Buffer} Data to write to the instance's stream.
|
||||
// #### @cb {function} Continuation to respond to when complete.
|
||||
// Write to the stream, ensure execution of a callback on completion.
|
||||
//
|
||||
File.prototype._write = function(data, callback) {
|
||||
if (this._isStreams2) {
|
||||
this._stream.write(data);
|
||||
return callback && process.nextTick(function () {
|
||||
callback(null, true);
|
||||
});
|
||||
}
|
||||
|
||||
// If this is a file write stream, we could use the builtin
|
||||
// callback functionality, however, the stream is not guaranteed
|
||||
// to be an fs.WriteStream.
|
||||
var ret = this._stream.write(data);
|
||||
if (!callback) return;
|
||||
if (ret === false) {
|
||||
return this._stream.once('drain', function() {
|
||||
callback(null, true);
|
||||
});
|
||||
}
|
||||
process.nextTick(function () {
|
||||
callback(null, true);
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// ### function query (options, callback)
|
||||
// #### @options {Object} Loggly-like query options for this instance.
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Query the transport. Options object is optional.
|
||||
//
|
||||
File.prototype.query = function (options, callback) {
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
var file = path.join(this.dirname, this.filename),
|
||||
options = this.normalizeQuery(options),
|
||||
buff = '',
|
||||
results = [],
|
||||
row = 0;
|
||||
|
||||
var stream = fs.createReadStream(file, {
|
||||
encoding: 'utf8'
|
||||
});
|
||||
|
||||
stream.on('error', function (err) {
|
||||
if (stream.readable) {
|
||||
stream.destroy();
|
||||
}
|
||||
if (!callback) return;
|
||||
return err.code !== 'ENOENT'
|
||||
? callback(err)
|
||||
: callback(null, results);
|
||||
});
|
||||
|
||||
stream.on('data', function (data) {
|
||||
var data = (buff + data).split(/\n+/),
|
||||
l = data.length - 1,
|
||||
i = 0;
|
||||
|
||||
for (; i < l; i++) {
|
||||
if (!options.start || row >= options.start) {
|
||||
add(data[i]);
|
||||
}
|
||||
row++;
|
||||
}
|
||||
|
||||
buff = data[l];
|
||||
});
|
||||
|
||||
stream.on('close', function () {
|
||||
if (buff) add(buff, true);
|
||||
if (options.order === 'desc') {
|
||||
results = results.reverse();
|
||||
}
|
||||
if (callback) callback(null, results);
|
||||
});
|
||||
|
||||
function add(buff, attempt) {
|
||||
try {
|
||||
var log = JSON.parse(buff);
|
||||
if (check(log)) push(log);
|
||||
} catch (e) {
|
||||
if (!attempt) {
|
||||
stream.emit('error', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function push(log) {
|
||||
if (options.rows && results.length >= options.rows) {
|
||||
if (stream.readable) {
|
||||
stream.destroy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.fields) {
|
||||
var obj = {};
|
||||
options.fields.forEach(function (key) {
|
||||
obj[key] = log[key];
|
||||
});
|
||||
log = obj;
|
||||
}
|
||||
|
||||
results.push(log);
|
||||
}
|
||||
|
||||
function check(log) {
|
||||
if (!log) return;
|
||||
|
||||
if (typeof log !== 'object') return;
|
||||
|
||||
var time = new Date(log.timestamp);
|
||||
if ((options.from && time < options.from)
|
||||
|| (options.until && time > options.until)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// ### function stream (options)
|
||||
// #### @options {Object} Stream options for this instance.
|
||||
// Returns a log stream for this transport. Options object is optional.
|
||||
//
|
||||
File.prototype.stream = function (options) {
|
||||
var file = path.join(this.dirname, this.filename),
|
||||
options = options || {},
|
||||
stream = new Stream;
|
||||
|
||||
var tail = {
|
||||
file: file,
|
||||
start: options.start
|
||||
};
|
||||
|
||||
stream.destroy = common.tailFile(tail, function (err, line) {
|
||||
|
||||
if(err){
|
||||
return stream.emit('error',err);
|
||||
}
|
||||
|
||||
try {
|
||||
stream.emit('data', line);
|
||||
line = JSON.parse(line);
|
||||
stream.emit('log', line);
|
||||
} catch (e) {
|
||||
stream.emit('error', e);
|
||||
}
|
||||
});
|
||||
|
||||
return stream;
|
||||
};
|
||||
|
||||
//
|
||||
// ### function open (callback)
|
||||
// #### @callback {function} Continuation to respond to when complete
|
||||
// Checks to see if a new file needs to be created based on the `maxsize`
|
||||
// (if any) and the current size of the file used.
|
||||
//
|
||||
File.prototype.open = function (callback) {
|
||||
if (this.opening) {
|
||||
//
|
||||
// If we are already attempting to open the next
|
||||
// available file then respond with a value indicating
|
||||
// that the message should be buffered.
|
||||
//
|
||||
return callback(true);
|
||||
}
|
||||
else if (!this._stream || (this.maxsize && this._size >= this.maxsize)) {
|
||||
//
|
||||
// If we dont have a stream or have exceeded our size, then create
|
||||
// the next stream and respond with a value indicating that
|
||||
// the message should be buffered.
|
||||
//
|
||||
callback(true);
|
||||
return this._createStream();
|
||||
}
|
||||
|
||||
this._archive = this.zippedArchive ? this._stream.path : null;
|
||||
|
||||
//
|
||||
// Otherwise we have a valid (and ready) stream.
|
||||
//
|
||||
callback();
|
||||
};
|
||||
|
||||
//
|
||||
// ### function close ()
|
||||
// Closes the stream associated with this instance.
|
||||
//
|
||||
File.prototype.close = function () {
|
||||
var self = this;
|
||||
|
||||
if (this._stream) {
|
||||
this._stream.end();
|
||||
this._stream.destroySoon();
|
||||
|
||||
this._stream.once('finish', function () {
|
||||
self.emit('flush');
|
||||
self.emit('closed');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// ### function flush ()
|
||||
// Flushes any buffered messages to the current `stream`
|
||||
// used by this instance.
|
||||
//
|
||||
File.prototype.flush = function () {
|
||||
var self = this;
|
||||
|
||||
// If nothing to flush, there will be no "flush" event from native stream
|
||||
// Thus, the "open" event will never be fired (see _createStream.createAndFlush function)
|
||||
// That means, self.opening will never set to false and no logs will be written to disk
|
||||
if (!this._buffer.length) {
|
||||
return self.emit('flush');
|
||||
}
|
||||
|
||||
//
|
||||
// Iterate over the `_buffer` of enqueued messaged
|
||||
// and then write them to the newly created stream.
|
||||
//
|
||||
this._buffer.forEach(function (item) {
|
||||
var str = item[0],
|
||||
callback = item[1];
|
||||
|
||||
process.nextTick(function () {
|
||||
self._write(str, callback);
|
||||
self._size += str.length;
|
||||
});
|
||||
});
|
||||
|
||||
//
|
||||
// Quickly truncate the `_buffer` once the write operations
|
||||
// have been started
|
||||
//
|
||||
self._buffer.length = 0;
|
||||
|
||||
//
|
||||
// When the stream has drained we have flushed
|
||||
// our buffer.
|
||||
//
|
||||
self._stream.once('drain', function () {
|
||||
self.emit('flush');
|
||||
self.emit('logged');
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// ### @private function _createStream ()
|
||||
// Attempts to open the next appropriate file for this instance
|
||||
// based on the common state (such as `maxsize` and `_basename`).
|
||||
//
|
||||
File.prototype._createStream = function () {
|
||||
var self = this;
|
||||
this.opening = true;
|
||||
|
||||
(function checkFile (target) {
|
||||
var fullname = path.join(self.dirname, target);
|
||||
|
||||
//
|
||||
// Creates the `WriteStream` and then flushes any
|
||||
// buffered messages.
|
||||
//
|
||||
function createAndFlush (size) {
|
||||
if (self._stream) {
|
||||
self._stream.end();
|
||||
self._stream.destroySoon();
|
||||
}
|
||||
|
||||
self._size = size;
|
||||
self.filename = target;
|
||||
self._stream = fs.createWriteStream(fullname, self.options);
|
||||
self._isStreams2 = isWritable(self._stream);
|
||||
self._stream.on('error', function(error){
|
||||
if (self._failures < self.maxRetries) {
|
||||
self._createStream();
|
||||
self._failures++;
|
||||
}
|
||||
else {
|
||||
self.emit('error', error);
|
||||
}
|
||||
});
|
||||
//
|
||||
// We need to listen for drain events when
|
||||
// write() returns false. This can make node
|
||||
// mad at times.
|
||||
//
|
||||
self._stream.setMaxListeners(Infinity);
|
||||
|
||||
//
|
||||
// When the current stream has finished flushing
|
||||
// then we can be sure we have finished opening
|
||||
// and thus can emit the `open` event.
|
||||
//
|
||||
self.once('flush', function () {
|
||||
// Because "flush" event is based on native stream "drain" event,
|
||||
// logs could be written inbetween "self.flush()" and here
|
||||
// Therefore, we need to flush again to make sure everything is flushed
|
||||
self.flush();
|
||||
|
||||
self.opening = false;
|
||||
self.emit('open', fullname);
|
||||
});
|
||||
//
|
||||
// Remark: It is possible that in the time it has taken to find the
|
||||
// next logfile to be written more data than `maxsize` has been buffered,
|
||||
// but for sensible limits (10s - 100s of MB) this seems unlikely in less
|
||||
// than one second.
|
||||
//
|
||||
self.flush();
|
||||
compressFile();
|
||||
}
|
||||
|
||||
function compressFile() {
|
||||
if (self._archive) {
|
||||
var gzip = zlib.createGzip();
|
||||
|
||||
var inp = fs.createReadStream(String(self._archive));
|
||||
var out = fs.createWriteStream(self._archive + '.gz');
|
||||
|
||||
inp.pipe(gzip).pipe(out);
|
||||
|
||||
fs.unlink(String(self._archive));
|
||||
self._archive = '';
|
||||
}
|
||||
}
|
||||
|
||||
fs.stat(fullname, function (err, stats) {
|
||||
if (err) {
|
||||
if (err.code !== 'ENOENT') {
|
||||
return self.emit('error', err);
|
||||
}
|
||||
return createAndFlush(0);
|
||||
}
|
||||
|
||||
if (!stats || (self.maxsize && stats.size >= self.maxsize)) {
|
||||
//
|
||||
// If `stats.size` is greater than the `maxsize` for
|
||||
// this instance then try again
|
||||
//
|
||||
return self._incFile(function() {
|
||||
checkFile(self._getFile());
|
||||
});
|
||||
}
|
||||
|
||||
createAndFlush(stats.size);
|
||||
});
|
||||
})(this._getFile());
|
||||
};
|
||||
|
||||
|
||||
File.prototype._incFile = function (callback) {
|
||||
var ext = path.extname(this._basename),
|
||||
basename = path.basename(this._basename, ext),
|
||||
oldest,
|
||||
target;
|
||||
|
||||
if (!this.tailable) {
|
||||
this._created += 1;
|
||||
this._checkMaxFilesIncrementing(ext, basename, callback);
|
||||
}
|
||||
else {
|
||||
this._checkMaxFilesTailable(ext, basename, callback);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// ### @private function _getFile ()
|
||||
// Gets the next filename to use for this instance
|
||||
// in the case that log filesizes are being capped.
|
||||
//
|
||||
File.prototype._getFile = function () {
|
||||
var ext = path.extname(this._basename),
|
||||
basename = path.basename(this._basename, ext);
|
||||
|
||||
//
|
||||
// Caveat emptor (indexzero): rotationFormat() was broken by design
|
||||
// when combined with max files because the set of files to unlink
|
||||
// is never stored.
|
||||
//
|
||||
return !this.tailable && this._created
|
||||
? basename + (this.rotationFormat ? this.rotationFormat() : this._created) + ext
|
||||
: basename + ext;
|
||||
};
|
||||
|
||||
//
|
||||
// ### @private function _checkMaxFilesIncrementing ()
|
||||
// Increment the number of files created or
|
||||
// checked by this instance.
|
||||
//
|
||||
File.prototype._checkMaxFilesIncrementing = function (ext, basename, callback) {
|
||||
var oldest, target,
|
||||
self = this;
|
||||
|
||||
if (self.zippedArchive) {
|
||||
self._archive = path.join(self.dirname, basename +
|
||||
((self._created === 1) ? '' : self._created-1) +
|
||||
ext);
|
||||
}
|
||||
|
||||
|
||||
// Check for maxFiles option and delete file
|
||||
if (!self.maxFiles || self._created < self.maxFiles) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
oldest = self._created - self.maxFiles;
|
||||
target = path.join(self.dirname, basename + (oldest !== 0 ? oldest : '') + ext +
|
||||
(self.zippedArchive ? '.gz' : ''));
|
||||
fs.unlink(target, callback);
|
||||
};
|
||||
|
||||
//
|
||||
// ### @private function _checkMaxFilesTailable ()
|
||||
//
|
||||
// Roll files forward based on integer, up to maxFiles.
|
||||
// e.g. if base if file.log and it becomes oversized, roll
|
||||
// to file1.log, and allow file.log to be re-used. If
|
||||
// file is oversized again, roll file1.log to file2.log,
|
||||
// roll file.log to file1.log, and so on.
|
||||
File.prototype._checkMaxFilesTailable = function (ext, basename, callback) {
|
||||
var tasks = [],
|
||||
self = this;
|
||||
|
||||
if (!this.maxFiles)
|
||||
return;
|
||||
|
||||
for (var x = this.maxFiles - 1; x > 0; x--) {
|
||||
tasks.push(function (i) {
|
||||
return function (cb) {
|
||||
var tmppath = path.join(self.dirname, basename + (i - 1) + ext +
|
||||
(self.zippedArchive ? '.gz' : ''));
|
||||
fs.exists(tmppath, function (exists) {
|
||||
if (!exists) {
|
||||
return cb(null);
|
||||
}
|
||||
|
||||
fs.rename(tmppath, path.join(self.dirname, basename + i + ext +
|
||||
(self.zippedArchive ? '.gz' : '')), cb);
|
||||
});
|
||||
};
|
||||
}(x));
|
||||
}
|
||||
|
||||
if (self.zippedArchive) {
|
||||
self._archive = path.join(self.dirname, basename + 1 + ext);
|
||||
}
|
||||
async.series(tasks, function (err) {
|
||||
fs.rename(
|
||||
path.join(self.dirname, basename + ext),
|
||||
path.join(self.dirname, basename + 1 + ext),
|
||||
callback
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// ### @private function _lazyDrain ()
|
||||
// Lazily attempts to emit the `logged` event when `this.stream` has
|
||||
// drained. This is really just a simple mutex that only works because
|
||||
// Node.js is single-threaded.
|
||||
//
|
||||
File.prototype._lazyDrain = function () {
|
||||
var self = this;
|
||||
|
||||
if (!this._draining && this._stream) {
|
||||
this._draining = true;
|
||||
|
||||
this._stream.once('drain', function () {
|
||||
this._draining = false;
|
||||
self.emit('logged');
|
||||
});
|
||||
}
|
||||
};
|
232
node_modules/winston/lib/winston/transports/http.js
generated
vendored
Normal file
232
node_modules/winston/lib/winston/transports/http.js
generated
vendored
Normal file
@ -0,0 +1,232 @@
|
||||
var util = require('util'),
|
||||
winston = require('../../winston'),
|
||||
http = require('http'),
|
||||
https = require('https'),
|
||||
Stream = require('stream').Stream,
|
||||
Transport = require('./transport').Transport;
|
||||
|
||||
//
|
||||
// ### function Http (options)
|
||||
// #### @options {Object} Options for this instance.
|
||||
// Constructor function for the Http transport object responsible
|
||||
// for persisting log messages and metadata to a terminal or TTY.
|
||||
//
|
||||
var Http = exports.Http = function (options) {
|
||||
Transport.call(this, options);
|
||||
options = options || {};
|
||||
|
||||
this.name = 'http';
|
||||
this.ssl = !!options.ssl;
|
||||
this.host = options.host || 'localhost';
|
||||
this.port = options.port;
|
||||
this.auth = options.auth;
|
||||
this.path = options.path || '';
|
||||
|
||||
if (!this.port) {
|
||||
this.port = this.ssl ? 443 : 80;
|
||||
}
|
||||
};
|
||||
|
||||
util.inherits(Http, winston.Transport);
|
||||
|
||||
//
|
||||
// Expose the name of this Transport on the prototype
|
||||
//
|
||||
Http.prototype.name = 'http';
|
||||
|
||||
//
|
||||
// ### function _request (options, callback)
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Make a request to a winstond server or any http server which can
|
||||
// handle json-rpc.
|
||||
//
|
||||
Http.prototype._request = function (options, callback) {
|
||||
options = options || {};
|
||||
|
||||
var auth = options.auth || this.auth,
|
||||
path = options.path || this.path || '',
|
||||
req;
|
||||
|
||||
delete options.auth;
|
||||
delete options.path;
|
||||
|
||||
// Prepare options for outgoing HTTP request
|
||||
req = (this.ssl ? https : http).request({
|
||||
host: this.host,
|
||||
port: this.port,
|
||||
path: '/' + path.replace(/^\//, ''),
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
auth: (auth) ? auth.username + ':' + auth.password : ''
|
||||
});
|
||||
|
||||
req.on('error', callback);
|
||||
req.on('response', function (res) {
|
||||
res.on('end', function () {
|
||||
callback(null, res);
|
||||
});
|
||||
|
||||
res.resume();
|
||||
});
|
||||
|
||||
req.end(new Buffer(JSON.stringify(options), 'utf8'));
|
||||
};
|
||||
|
||||
//
|
||||
// ### function log (level, msg, [meta], callback)
|
||||
// #### @level {string} Level at which to log the message.
|
||||
// #### @msg {string} Message to log
|
||||
// #### @meta {Object} **Optional** Additional metadata to attach
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Core logging method exposed to Winston. Metadata is optional.
|
||||
//
|
||||
Http.prototype.log = function (level, msg, meta, callback) {
|
||||
var self = this;
|
||||
|
||||
if (typeof meta === 'function') {
|
||||
callback = meta;
|
||||
meta = {};
|
||||
}
|
||||
|
||||
var options = {
|
||||
method: 'collect',
|
||||
params: {
|
||||
level: level,
|
||||
message: msg,
|
||||
meta: meta
|
||||
}
|
||||
};
|
||||
|
||||
if (meta) {
|
||||
if (meta.path) {
|
||||
options.path = meta.path;
|
||||
delete meta.path;
|
||||
}
|
||||
|
||||
if (meta.auth) {
|
||||
options.auth = meta.auth;
|
||||
delete meta.auth;
|
||||
}
|
||||
}
|
||||
|
||||
this._request(options, function (err, res) {
|
||||
if (res && res.statusCode !== 200) {
|
||||
err = new Error('HTTP Status Code: ' + res.statusCode);
|
||||
}
|
||||
|
||||
if (err) return callback(err);
|
||||
|
||||
// TODO: emit 'logged' correctly,
|
||||
// keep track of pending logs.
|
||||
self.emit('logged');
|
||||
|
||||
if (callback) callback(null, true);
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// ### function query (options, callback)
|
||||
// #### @options {Object} Loggly-like query options for this instance.
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Query the transport. Options object is optional.
|
||||
//
|
||||
Http.prototype.query = function (options, callback) {
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
var self = this,
|
||||
options = this.normalizeQuery(options);
|
||||
|
||||
options = {
|
||||
method: 'query',
|
||||
params: options
|
||||
};
|
||||
|
||||
if (options.params.path) {
|
||||
options.path = options.params.path;
|
||||
delete options.params.path;
|
||||
}
|
||||
|
||||
if (options.params.auth) {
|
||||
options.auth = options.params.auth;
|
||||
delete options.params.auth;
|
||||
}
|
||||
|
||||
this._request(options, function (err, res, body) {
|
||||
if (res && res.statusCode !== 200) {
|
||||
err = new Error('HTTP Status Code: ' + res.statusCode);
|
||||
}
|
||||
|
||||
if (err) return callback(err);
|
||||
|
||||
if (typeof body === 'string') {
|
||||
try {
|
||||
body = JSON.parse(body);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
}
|
||||
|
||||
callback(null, body);
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// ### function stream (options)
|
||||
// #### @options {Object} Stream options for this instance.
|
||||
// Returns a log stream for this transport. Options object is optional.
|
||||
//
|
||||
Http.prototype.stream = function (options) {
|
||||
options = options || {};
|
||||
|
||||
var self = this,
|
||||
stream = new Stream,
|
||||
req,
|
||||
buff;
|
||||
|
||||
stream.destroy = function () {
|
||||
req.destroy();
|
||||
};
|
||||
|
||||
options = {
|
||||
method: 'stream',
|
||||
params: options
|
||||
};
|
||||
|
||||
if (options.params.path) {
|
||||
options.path = options.params.path;
|
||||
delete options.params.path;
|
||||
}
|
||||
|
||||
if (options.params.auth) {
|
||||
options.auth = options.params.auth;
|
||||
delete options.params.auth;
|
||||
}
|
||||
|
||||
req = this._request(options);
|
||||
buff = '';
|
||||
|
||||
req.on('data', function (data) {
|
||||
var data = (buff + data).split(/\n+/),
|
||||
l = data.length - 1,
|
||||
i = 0;
|
||||
|
||||
for (; i < l; i++) {
|
||||
try {
|
||||
stream.emit('log', JSON.parse(data[i]));
|
||||
} catch (e) {
|
||||
stream.emit('error', e);
|
||||
}
|
||||
}
|
||||
|
||||
buff = data[l];
|
||||
});
|
||||
|
||||
req.on('error', function (err) {
|
||||
stream.emit('error', err);
|
||||
});
|
||||
|
||||
return stream;
|
||||
};
|
89
node_modules/winston/lib/winston/transports/memory.js
generated
vendored
Normal file
89
node_modules/winston/lib/winston/transports/memory.js
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
var events = require('events'),
|
||||
util = require('util'),
|
||||
common = require('../common'),
|
||||
Transport = require('./transport').Transport;
|
||||
|
||||
//
|
||||
// ### function Memory (options)
|
||||
// #### @options {Object} Options for this instance.
|
||||
// Constructor function for the Memory transport object responsible
|
||||
// for persisting log messages and metadata to a memory array of messages.
|
||||
//
|
||||
var Memory = exports.Memory = function (options) {
|
||||
Transport.call(this, options);
|
||||
options = options || {};
|
||||
|
||||
this.errorOutput = [];
|
||||
this.writeOutput = [];
|
||||
|
||||
this.json = options.json || false;
|
||||
this.colorize = options.colorize || false;
|
||||
this.prettyPrint = options.prettyPrint || false;
|
||||
this.timestamp = typeof options.timestamp !== 'undefined' ? options.timestamp : false;
|
||||
this.showLevel = options.showLevel === undefined ? true : options.showLevel;
|
||||
this.label = options.label || null;
|
||||
this.depth = options.depth || null;
|
||||
|
||||
if (this.json) {
|
||||
this.stringify = options.stringify || function (obj) {
|
||||
return JSON.stringify(obj, null, 2);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Inherit from `winston.Transport`.
|
||||
//
|
||||
util.inherits(Memory, Transport);
|
||||
|
||||
//
|
||||
// Expose the name of this Transport on the prototype
|
||||
//
|
||||
Memory.prototype.name = 'memory';
|
||||
|
||||
//
|
||||
// ### function log (level, msg, [meta], callback)
|
||||
// #### @level {string} Level at which to log the message.
|
||||
// #### @msg {string} Message to log
|
||||
// #### @meta {Object} **Optional** Additional metadata to attach
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Core logging method exposed to Winston. Metadata is optional.
|
||||
//
|
||||
Memory.prototype.log = function (level, msg, meta, callback) {
|
||||
if (this.silent) {
|
||||
return callback(null, true);
|
||||
}
|
||||
|
||||
var self = this,
|
||||
output;
|
||||
|
||||
output = common.log({
|
||||
colorize: this.colorize,
|
||||
json: this.json,
|
||||
level: level,
|
||||
message: msg,
|
||||
meta: meta,
|
||||
stringify: this.stringify,
|
||||
timestamp: this.timestamp,
|
||||
prettyPrint: this.prettyPrint,
|
||||
raw: this.raw,
|
||||
label: this.label,
|
||||
depth: this.depth,
|
||||
formatter: this.formatter,
|
||||
humanReadableUnhandledException: this.humanReadableUnhandledException
|
||||
});
|
||||
|
||||
if (level === 'error' || level === 'debug') {
|
||||
this.errorOutput.push(output);
|
||||
} else {
|
||||
this.writeOutput.push(output);
|
||||
}
|
||||
|
||||
self.emit('logged');
|
||||
callback(null, true);
|
||||
};
|
||||
|
||||
Memory.prototype.clearLogs = function () {
|
||||
this.errorOutput = [];
|
||||
this.writeOutput = [];
|
||||
};
|
135
node_modules/winston/lib/winston/transports/transport.js
generated
vendored
Normal file
135
node_modules/winston/lib/winston/transports/transport.js
generated
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* transport.js: Base Transport object for all Winston transports.
|
||||
*
|
||||
* (C) 2010 Charlie Robbins
|
||||
* MIT LICENCE
|
||||
*
|
||||
*/
|
||||
|
||||
var events = require('events'),
|
||||
util = require('util');
|
||||
|
||||
//
|
||||
// ### function Transport (options)
|
||||
// #### @options {Object} Options for this instance.
|
||||
// Constructor function for the Tranport object responsible
|
||||
// base functionality for all winston transports.
|
||||
//
|
||||
var Transport = exports.Transport = function (options) {
|
||||
events.EventEmitter.call(this);
|
||||
|
||||
options = options || {};
|
||||
this.silent = options.silent || false;
|
||||
this.raw = options.raw || false;
|
||||
this.name = options.name || this.name;
|
||||
this.formatter = options.formatter;
|
||||
|
||||
//
|
||||
// Do not set a default level. When `level` is falsey on any
|
||||
// `Transport` instance, any `Logger` instance uses the
|
||||
// configured level (instead of the Transport level)
|
||||
//
|
||||
this.level = options.level;
|
||||
|
||||
this.handleExceptions = options.handleExceptions || false;
|
||||
this.exceptionsLevel = options.exceptionsLevel || 'error';
|
||||
this.humanReadableUnhandledException = options.humanReadableUnhandledException || false;
|
||||
};
|
||||
|
||||
//
|
||||
// Inherit from `events.EventEmitter`.
|
||||
//
|
||||
util.inherits(Transport, events.EventEmitter);
|
||||
|
||||
//
|
||||
// ### function formatQuery (query)
|
||||
// #### @query {string|Object} Query to format
|
||||
// Formats the specified `query` Object (or string) to conform
|
||||
// with the underlying implementation of this transport.
|
||||
//
|
||||
Transport.prototype.formatQuery = function (query) {
|
||||
return query;
|
||||
};
|
||||
|
||||
//
|
||||
// ### function normalizeQuery (query)
|
||||
// #### @options {string|Object} Query to normalize
|
||||
// Normalize options for query
|
||||
//
|
||||
Transport.prototype.normalizeQuery = function (options) {
|
||||
//
|
||||
// Use options similar to loggly.
|
||||
// [See Loggly Search API](http://wiki.loggly.com/retrieve_events#optional)
|
||||
//
|
||||
|
||||
options = options || {};
|
||||
|
||||
// limit
|
||||
options.rows = options.rows || options.limit || 10;
|
||||
|
||||
// starting row offset
|
||||
options.start = options.start || 0;
|
||||
|
||||
// now
|
||||
options.until = options.until || new Date;
|
||||
if (typeof options.until !== 'object') {
|
||||
options.until = new Date(options.until);
|
||||
}
|
||||
|
||||
// now - 24
|
||||
options.from = options.from || (options.until - (24 * 60 * 60 * 1000));
|
||||
if (typeof options.from !== 'object') {
|
||||
options.from = new Date(options.from);
|
||||
}
|
||||
|
||||
|
||||
// 'asc' or 'desc'
|
||||
options.order = options.order || 'desc';
|
||||
|
||||
// which fields to select
|
||||
options.fields = options.fields;
|
||||
|
||||
return options;
|
||||
};
|
||||
|
||||
//
|
||||
// ### function formatResults (results, options)
|
||||
// #### @results {Object|Array} Results returned from `.query`.
|
||||
// #### @options {Object} **Optional** Formatting options
|
||||
// Formats the specified `results` with the given `options` accordinging
|
||||
// to the implementation of this transport.
|
||||
//
|
||||
Transport.prototype.formatResults = function (results, options) {
|
||||
return results;
|
||||
};
|
||||
|
||||
//
|
||||
// ### function logException (msg, meta, callback)
|
||||
// #### @msg {string} Message to log
|
||||
// #### @meta {Object} **Optional** Additional metadata to attach
|
||||
// #### @callback {function} Continuation to respond to when complete.
|
||||
// Logs the specified `msg`, `meta` and responds to the callback once the log
|
||||
// operation is complete to ensure that the event loop will not exit before
|
||||
// all logging has completed.
|
||||
//
|
||||
Transport.prototype.logException = function (msg, meta, callback) {
|
||||
var self = this,
|
||||
called;
|
||||
|
||||
if (this.silent) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
function onComplete () {
|
||||
if (!called) {
|
||||
called = true;
|
||||
self.removeListener('logged', onComplete);
|
||||
self.removeListener('error', onComplete);
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
this.once('logged', onComplete);
|
||||
this.once('error', onComplete);
|
||||
this.log(self.exceptionsLevel, msg, meta, function () { });
|
||||
};
|
24
node_modules/winston/node_modules/async/.jshintrc
generated
vendored
Normal file
24
node_modules/winston/node_modules/async/.jshintrc
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
// Enforcing options
|
||||
"eqeqeq": false,
|
||||
"forin": true,
|
||||
"indent": 4,
|
||||
"noarg": true,
|
||||
"undef": true,
|
||||
"trailing": true,
|
||||
"evil": true,
|
||||
"laxcomma": true,
|
||||
|
||||
// Relaxing options
|
||||
"onevar": false,
|
||||
"asi": false,
|
||||
"eqnull": true,
|
||||
"expr": false,
|
||||
"loopfunc": true,
|
||||
"sub": true,
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"globals": {
|
||||
"define": true
|
||||
}
|
||||
}
|
5
node_modules/winston/node_modules/async/.travis.yml
generated
vendored
Normal file
5
node_modules/winston/node_modules/async/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "0.10"
|
||||
- "0.12"
|
||||
- "iojs"
|
16
node_modules/winston/node_modules/async/CHANGELOG.md
generated
vendored
Normal file
16
node_modules/winston/node_modules/async/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
# v1.0.0
|
||||
|
||||
No known breaking changes, we are simply complying with semver from here on out.
|
||||
|
||||
Changes:
|
||||
|
||||
- Start using a changelog!
|
||||
- Add `forEachOf` for iterating over Objects (or to iterate Arrays with indexes available) (#168 #704 #321)
|
||||
- Detect deadlocks in `auto` (#663)
|
||||
- Better support for require.js (#527)
|
||||
- Throw if queue created with concurrency `0` (#714)
|
||||
- Fix unneeded iteration in `queue.resume()` (#758)
|
||||
- Guard against timer mocking overriding `setImmediate` (#609 #611)
|
||||
- Miscellaneous doc fixes (#542 #596 #615 #628 #631 #690 #729)
|
||||
- Use single noop function internally (#546)
|
||||
- Optimize internal `_each`, `_map` and `_keys` functions.
|
19
node_modules/winston/node_modules/async/LICENSE
generated
vendored
Normal file
19
node_modules/winston/node_modules/async/LICENSE
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2010-2014 Caolan McMahon
|
||||
|
||||
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.
|
1720
node_modules/winston/node_modules/async/README.md
generated
vendored
Normal file
1720
node_modules/winston/node_modules/async/README.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
40
node_modules/winston/node_modules/async/bower.json
generated
vendored
Normal file
40
node_modules/winston/node_modules/async/bower.json
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "async",
|
||||
"description": "Higher-order functions and common patterns for asynchronous code",
|
||||
"version": "1.0.0",
|
||||
"main": "lib/async.js",
|
||||
"keywords": [
|
||||
"async",
|
||||
"callback",
|
||||
"utility",
|
||||
"module"
|
||||
],
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/caolan/async.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"benchmark": "~1.0.0",
|
||||
"jshint": "~2.7.0",
|
||||
"lodash": ">=2.4.1",
|
||||
"mkdirp": "~0.5.1",
|
||||
"nodeunit": ">0.0.0",
|
||||
"uglify-js": "1.2.x"
|
||||
},
|
||||
"moduleType": [
|
||||
"amd",
|
||||
"globals",
|
||||
"node"
|
||||
],
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"authors": [
|
||||
"Caolan McMahon"
|
||||
]
|
||||
}
|
17
node_modules/winston/node_modules/async/component.json
generated
vendored
Normal file
17
node_modules/winston/node_modules/async/component.json
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "async",
|
||||
"description": "Higher-order functions and common patterns for asynchronous code",
|
||||
"version": "1.0.0",
|
||||
"keywords": [
|
||||
"async",
|
||||
"callback",
|
||||
"utility",
|
||||
"module"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "lib/async.js",
|
||||
"repository": "caolan/async",
|
||||
"scripts": [
|
||||
"lib/async.js"
|
||||
]
|
||||
}
|
1283
node_modules/winston/node_modules/async/lib/async.js
generated
vendored
Normal file
1283
node_modules/winston/node_modules/async/lib/async.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
117
node_modules/winston/node_modules/async/package.json
generated
vendored
Normal file
117
node_modules/winston/node_modules/async/package.json
generated
vendored
Normal file
@ -0,0 +1,117 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"async@~1.0.0",
|
||||
"/Users/akira/src/biomedjs/node_modules/winston"
|
||||
]
|
||||
],
|
||||
"_from": "async@>=1.0.0 <1.1.0",
|
||||
"_id": "async@1.0.0",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/winston/async",
|
||||
"_nodeVersion": "0.12.3",
|
||||
"_npmUser": {
|
||||
"email": "alexander.early@gmail.com",
|
||||
"name": "aearly"
|
||||
},
|
||||
"_npmVersion": "2.9.1",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "async",
|
||||
"raw": "async@~1.0.0",
|
||||
"rawSpec": "~1.0.0",
|
||||
"scope": null,
|
||||
"spec": ">=1.0.0 <1.1.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/winston"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz",
|
||||
"_shasum": "f8fc04ca3a13784ade9e1641af98578cfbd647a9",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "async@~1.0.0",
|
||||
"_where": "/Users/akira/src/biomedjs/node_modules/winston",
|
||||
"author": {
|
||||
"name": "Caolan McMahon"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/caolan/async/issues"
|
||||
},
|
||||
"dependencies": {},
|
||||
"description": "Higher-order functions and common patterns for asynchronous code",
|
||||
"devDependencies": {
|
||||
"benchmark": "~1.0.0",
|
||||
"jshint": "~2.7.0",
|
||||
"lodash": ">=2.4.1",
|
||||
"mkdirp": "~0.5.1",
|
||||
"nodeunit": ">0.0.0",
|
||||
"uglify-js": "1.2.x"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "f8fc04ca3a13784ade9e1641af98578cfbd647a9",
|
||||
"tarball": "http://registry.npmjs.org/async/-/async-1.0.0.tgz"
|
||||
},
|
||||
"gitHead": "cfa81645c9cb4011b23d1d1a445ad855762568e0",
|
||||
"homepage": "https://github.com/caolan/async#readme",
|
||||
"jam": {
|
||||
"categories": [
|
||||
"Utilities"
|
||||
],
|
||||
"include": [
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"lib/async.js"
|
||||
],
|
||||
"main": "lib/async.js"
|
||||
},
|
||||
"keywords": [
|
||||
"async",
|
||||
"callback",
|
||||
"module",
|
||||
"utility"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "lib/async.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "caolan",
|
||||
"email": "caolan.mcmahon@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "beaugunderson",
|
||||
"email": "beau@beaugunderson.com"
|
||||
},
|
||||
{
|
||||
"name": "aearly",
|
||||
"email": "alexander.early@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "async",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/caolan/async.git"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "jshint lib/*.js test/*.js perf/*.js",
|
||||
"test": "npm run-script lint && nodeunit test/test-async.js"
|
||||
},
|
||||
"spm": {
|
||||
"main": "lib/async.js"
|
||||
},
|
||||
"version": "1.0.0",
|
||||
"volo": {
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"bower_components",
|
||||
"node_modules",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"main": "lib/async.js"
|
||||
}
|
||||
}
|
53
node_modules/winston/node_modules/async/support/sync-package-managers.js
generated
vendored
Executable file
53
node_modules/winston/node_modules/async/support/sync-package-managers.js
generated
vendored
Executable file
@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// This should probably be its own module but complaints about bower/etc.
|
||||
// support keep coming up and I'd rather just enable the workflow here for now
|
||||
// and figure out where this should live later. -- @beaugunderson
|
||||
|
||||
var fs = require('fs');
|
||||
var _ = require('lodash');
|
||||
|
||||
var packageJson = require('../package.json');
|
||||
|
||||
var IGNORES = ['**/.*', 'node_modules', 'bower_components', 'test', 'tests'];
|
||||
var INCLUDES = ['lib/async.js', 'README.md', 'LICENSE'];
|
||||
var REPOSITORY_NAME = 'caolan/async';
|
||||
|
||||
packageJson.jam = {
|
||||
main: packageJson.main,
|
||||
include: INCLUDES,
|
||||
categories: ['Utilities']
|
||||
};
|
||||
|
||||
packageJson.spm = {
|
||||
main: packageJson.main
|
||||
};
|
||||
|
||||
packageJson.volo = {
|
||||
main: packageJson.main,
|
||||
ignore: IGNORES
|
||||
};
|
||||
|
||||
var bowerSpecific = {
|
||||
moduleType: ['amd', 'globals', 'node'],
|
||||
ignore: IGNORES,
|
||||
authors: [packageJson.author]
|
||||
};
|
||||
|
||||
var bowerInclude = ['name', 'description', 'version', 'main', 'keywords',
|
||||
'license', 'homepage', 'repository', 'devDependencies'];
|
||||
|
||||
var componentSpecific = {
|
||||
repository: REPOSITORY_NAME,
|
||||
scripts: [packageJson.main]
|
||||
};
|
||||
|
||||
var componentInclude = ['name', 'description', 'version', 'keywords',
|
||||
'license', 'main'];
|
||||
|
||||
var bowerJson = _.merge({}, _.pick(packageJson, bowerInclude), bowerSpecific);
|
||||
var componentJson = _.merge({}, _.pick(packageJson, componentInclude), componentSpecific);
|
||||
|
||||
fs.writeFileSync('./bower.json', JSON.stringify(bowerJson, null, 2));
|
||||
fs.writeFileSync('./component.json', JSON.stringify(componentJson, null, 2));
|
||||
fs.writeFileSync('./package.json', JSON.stringify(packageJson, null, 2));
|
114
node_modules/winston/package.json
generated
vendored
Normal file
114
node_modules/winston/package.json
generated
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"winston",
|
||||
"/Users/akira/src/biomedjs"
|
||||
]
|
||||
],
|
||||
"_from": "winston@*",
|
||||
"_id": "winston@2.1.1",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/winston",
|
||||
"_nodeVersion": "4.2.2",
|
||||
"_npmUser": {
|
||||
"email": "charlie.robbins@gmail.com",
|
||||
"name": "indexzero"
|
||||
},
|
||||
"_npmVersion": "2.14.5",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "winston",
|
||||
"raw": "winston",
|
||||
"rawSpec": "",
|
||||
"scope": null,
|
||||
"spec": "*",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/winston/-/winston-2.1.1.tgz",
|
||||
"_shasum": "3c9349d196207fd1bdff9d4bc43ef72510e3a12e",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "winston",
|
||||
"_where": "/Users/akira/src/biomedjs",
|
||||
"author": {
|
||||
"email": "charlie.robbins@gmail.com",
|
||||
"name": "Charlie Robbins"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/winstonjs/winston/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "~1.0.0",
|
||||
"colors": "1.0.x",
|
||||
"cycle": "1.0.x",
|
||||
"eyes": "0.1.x",
|
||||
"isstream": "0.1.x",
|
||||
"pkginfo": "0.3.x",
|
||||
"stack-trace": "0.0.x"
|
||||
},
|
||||
"description": "A multi-transport async logging library for Node.js",
|
||||
"devDependencies": {
|
||||
"cross-spawn-async": "^2.0.0",
|
||||
"hock": "1.x.x",
|
||||
"std-mocks": "~1.0.0",
|
||||
"vows": "0.7.x"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "3c9349d196207fd1bdff9d4bc43ef72510e3a12e",
|
||||
"tarball": "http://registry.npmjs.org/winston/-/winston-2.1.1.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
},
|
||||
"gitHead": "69171ed1679a290e947f22a83b044b3980be3565",
|
||||
"homepage": "https://github.com/winstonjs/winston#readme",
|
||||
"keywords": [
|
||||
"logging",
|
||||
"sysadmin",
|
||||
"tools",
|
||||
"winston"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "./lib/winston",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "indexzero",
|
||||
"email": "charlie.robbins@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "chjj",
|
||||
"email": "chjjeffrey@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "jcrugzz",
|
||||
"email": "jcrugzz@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "pose",
|
||||
"email": "albertopose@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "v1",
|
||||
"email": "info@3rd-Eden.com"
|
||||
},
|
||||
{
|
||||
"name": "3rdeden",
|
||||
"email": "npm@3rd-Eden.com"
|
||||
}
|
||||
],
|
||||
"name": "winston",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/winstonjs/winston.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "vows --spec --isolate"
|
||||
},
|
||||
"version": "2.1.1"
|
||||
}
|
256
node_modules/winston/test/helpers.js
generated
vendored
Normal file
256
node_modules/winston/test/helpers.js
generated
vendored
Normal file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
* 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.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);
|
||||
if (options.message) {
|
||||
assert.equal('uncaughtException: ' + options.message, data.message);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
helpers.assertFailedTransport = function (transport) {
|
||||
return {
|
||||
topic: function () {
|
||||
var self = this;
|
||||
transport.on('error', function(emitErr){
|
||||
transport.log('error', 'test message 2', {}, function(logErr, logged){
|
||||
self.callback(emitErr, logErr);
|
||||
});
|
||||
});
|
||||
transport.log('error', 'test message');
|
||||
},
|
||||
"should emit an error": function (emitErr, logErr) {
|
||||
assert.instanceOf(emitErr, Error);
|
||||
assert.equal(emitErr.code, 'ENOENT');
|
||||
},
|
||||
"should enter noop failed state": function (emitErr, logErr) {
|
||||
assert.instanceOf(logErr, Error);
|
||||
assert.equal(transport._failures, transport.maxRetries);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
helpers.assertOptionsThrow = function (options, errMsg) {
|
||||
return function () {
|
||||
assert.throws(
|
||||
function () {
|
||||
try {
|
||||
new (winston.transports.Console)(options);
|
||||
} catch (err) {
|
||||
throw(err);
|
||||
}
|
||||
},
|
||||
new RegExp('^' + errMsg.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '$')
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
helpers.assertStderrLevels = function (transport, stderrLevels) {
|
||||
return function () {
|
||||
assert.equal(
|
||||
JSON.stringify(Object.keys(transport.stderrLevels).sort()),
|
||||
JSON.stringify(stderrLevels.sort())
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
helpers.testLoggingToStreams = function (levels, transport, stderrLevels, stdMocks) {
|
||||
return {
|
||||
topic: function () {
|
||||
stdMocks.use();
|
||||
transport.showLevel = true;
|
||||
Object.keys(levels).forEach(function (level) {
|
||||
transport.log(
|
||||
level,
|
||||
level + ' should go to ' + (stderrLevels.indexOf(level) > -1 ? 'stderr' : 'stdout'),
|
||||
{},
|
||||
function () {}
|
||||
);
|
||||
});
|
||||
var output = stdMocks.flush();
|
||||
stdMocks.restore();
|
||||
this.callback(null, output, levels);
|
||||
},
|
||||
"output should go to the appropriate streams": function (ign, output, levels) {
|
||||
var outCount = 0,
|
||||
errCount = 0;
|
||||
Object.keys(levels).forEach(function (level) {
|
||||
var line;
|
||||
if (stderrLevels.indexOf(level) > -1) {
|
||||
line = output.stderr[errCount++];
|
||||
assert.equal(line, level + ': ' + level + ' should go to stderr\n');
|
||||
} else {
|
||||
line = output.stdout[outCount++];
|
||||
assert.equal(line, level + ': ' + level + ' should go to stdout\n');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
202
node_modules/winston/test/transports/console-test.js
generated
vendored
Normal file
202
node_modules/winston/test/transports/console-test.js
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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'),
|
||||
stdMocks = require('std-mocks');
|
||||
|
||||
var npmTransport = new (winston.transports.Console)(),
|
||||
syslogTransport = new (winston.transports.Console)({ levels: winston.config.syslog.levels }),
|
||||
alignTransport = new (winston.transports.Console)({ showLevel: true, align: true }),
|
||||
defaultTransport = new (winston.transports.Console)(),
|
||||
rawTransport = new (winston.transports.Console)({ level: 'verbose', raw: true }),
|
||||
debugStdoutTransport = new (winston.transports.Console)({ debugStdout: true }),
|
||||
stderrLevelsTransport = new (winston.transports.Console)({ stderrLevels: ['info', 'warn'] }),
|
||||
customLevels = {
|
||||
alpha: 0,
|
||||
beta: 1,
|
||||
gamma: 2,
|
||||
delta: 3,
|
||||
epsilon: 4,
|
||||
},
|
||||
customLevelsAndStderrTransport = new (winston.transports.Console)({
|
||||
levels: customLevels,
|
||||
stderrLevels: ['delta', 'epsilon']
|
||||
}),
|
||||
noStderrTransport = new (winston.transports.Console)({ stderrLevels: [] });
|
||||
|
||||
vows.describe('winston/transports/console').addBatch({
|
||||
"An instance of the Console Transport": {
|
||||
"with showLevel off": {
|
||||
topic : function() {
|
||||
npmTransport.showLevel = false;
|
||||
stdMocks.use();
|
||||
npmTransport.log('info', 'Le message', { meta: true }, this.callback);
|
||||
},
|
||||
"should not have level prepended": function () {
|
||||
stdMocks.restore();
|
||||
var output = stdMocks.flush(),
|
||||
line = output.stdout[0];
|
||||
|
||||
assert.equal(line, 'Le message meta=true\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"An instance of the Console Transport": {
|
||||
"with showLevel on": {
|
||||
topic : function() {
|
||||
npmTransport.showLevel = true;
|
||||
stdMocks.use();
|
||||
npmTransport.log('info', '');
|
||||
},
|
||||
"should have level prepended": function () {
|
||||
stdMocks.restore();
|
||||
var output = stdMocks.flush(),
|
||||
line = output.stdout[0];
|
||||
|
||||
assert.equal(line, 'info: \n');
|
||||
}
|
||||
},
|
||||
}
|
||||
}).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);
|
||||
})
|
||||
},
|
||||
"with end-of-line": {
|
||||
topic : function() {
|
||||
npmTransport.eol = 'X';
|
||||
stdMocks.use();
|
||||
npmTransport.log('info', 'Le message', { meta: true }, this.callback);
|
||||
},
|
||||
"should have end-of-line character appended": function () {
|
||||
stdMocks.restore();
|
||||
var output = stdMocks.flush(),
|
||||
line = output.stdout[0];
|
||||
console.dir(line);
|
||||
|
||||
assert.equal(line, 'info: Le message meta=trueX');
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"An instance of the Console Transport with the align option on": {
|
||||
topic : function() {
|
||||
stdMocks.use();
|
||||
alignTransport.log('info', '');
|
||||
},
|
||||
"should have logs aligned": function () {
|
||||
stdMocks.restore();
|
||||
var output = stdMocks.flush(),
|
||||
line = output.stdout[0];
|
||||
|
||||
assert.equal(line, 'info\011: \n');
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"with align off": {
|
||||
topic : function() {
|
||||
alignTransport.align = false;
|
||||
stdMocks.use();
|
||||
alignTransport.log('info', '');
|
||||
},
|
||||
"should not have logs aligned": function () {
|
||||
stdMocks.restore();
|
||||
var output = stdMocks.flush(),
|
||||
line = output.stdout[0];
|
||||
|
||||
assert.equal(line, 'info: \n');
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
'An instance of a raw Console transport': {
|
||||
'logging to stdout': {
|
||||
topic: function () {
|
||||
stdMocks.use();
|
||||
rawTransport.log('verbose', 'hello there');
|
||||
}, 'should output json with message property': function () {
|
||||
stdMocks.restore();
|
||||
var output = stdMocks.flush();
|
||||
assert.ok(output.stdout[0].indexOf('"message":"hello there"') > -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"An instance of the Console Transport with no options": {
|
||||
"should set stderrLevels to 'error' and 'debug' by default": helpers.assertStderrLevels(
|
||||
defaultTransport,
|
||||
['error', 'debug']
|
||||
),
|
||||
"should log only 'error' and 'debug' to stderr": helpers.testLoggingToStreams(
|
||||
winston.config.npm.levels, defaultTransport, ['debug', 'error'], stdMocks
|
||||
)
|
||||
}
|
||||
}).addBatch({
|
||||
"An instance of the Console Transport with debugStdout set": {
|
||||
"should throw an Error if stderrLevels is set": helpers.assertOptionsThrow(
|
||||
{ debugStdout: true, stderrLevels: ['debug'] },
|
||||
"Error: Cannot set debugStdout and stderrLevels together"
|
||||
),
|
||||
"should set stderrLevels to 'error' by default": helpers.assertStderrLevels(
|
||||
debugStdoutTransport,
|
||||
['error']
|
||||
),
|
||||
"should log only the 'error' level to stderr": helpers.testLoggingToStreams(
|
||||
winston.config.npm.levels, debugStdoutTransport, ['error'], stdMocks
|
||||
)
|
||||
}
|
||||
}).addBatch({
|
||||
"An instance of the Console Transport with stderrLevels set": {
|
||||
"should throw an Error if stderrLevels is set but not an Array": helpers.assertOptionsThrow(
|
||||
{ debugStdout: false, stderrLevels: new String('Not an Array') },
|
||||
"Error: Cannot set stderrLevels to type other than Array"
|
||||
),
|
||||
"should throw an Error if stderrLevels contains non-string elements": helpers.assertOptionsThrow(
|
||||
{ debugStdout: false, stderrLevels: ["good", /^invalid$/, "valid"] },
|
||||
"Error: Cannot have non-string elements in stderrLevels Array"
|
||||
),
|
||||
"should correctly set stderrLevels": helpers.assertStderrLevels(
|
||||
stderrLevelsTransport,
|
||||
['info', 'warn']
|
||||
),
|
||||
"should log only the levels in stderrLevels to stderr": helpers.testLoggingToStreams(
|
||||
winston.config.npm.levels, stderrLevelsTransport, ['info', 'warn'], stdMocks
|
||||
)
|
||||
}
|
||||
}).addBatch({
|
||||
"An instance of the Console Transport with stderrLevels set to an empty array": {
|
||||
"should log only to stdout, and not to stderr": helpers.testLoggingToStreams(
|
||||
winston.config.npm.levels, noStderrTransport, [], stdMocks
|
||||
)
|
||||
}
|
||||
}).addBatch({
|
||||
"An instance of the Console Transport with custom levels and stderrLevels set": {
|
||||
"should log only the levels in stderrLevels to stderr": helpers.testLoggingToStreams(
|
||||
customLevels, customLevelsAndStderrTransport, ['delta', 'epsilon'], stdMocks
|
||||
)
|
||||
}
|
||||
}).export(module);
|
83
node_modules/winston/test/transports/file-archive-test.js
generated
vendored
Normal file
83
node_modules/winston/test/transports/file-archive-test.js
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* file-archive-test.js: Tests for instances of the File transport setting the archive option,
|
||||
*
|
||||
* (C) 2015 Nimrod Becker
|
||||
* 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 archiveTransport = new winston.transports.File({
|
||||
timestamp: true,
|
||||
json: false,
|
||||
zippedArchive: true,
|
||||
tailable: true,
|
||||
filename: 'testarchive.log',
|
||||
dirname: path.join(__dirname, '..', 'fixtures', 'logs'),
|
||||
maxsize: 4096,
|
||||
maxFiles: 3
|
||||
});
|
||||
|
||||
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++) {
|
||||
archiveTransport.log('info', data(txt), null, function() {});
|
||||
}
|
||||
}
|
||||
|
||||
vows.describe('winston/transports/file/zippedArchive').addBatch({
|
||||
"An instance of the File Transport with tailable true": {
|
||||
"when created archived files are rolled": {
|
||||
topic: function() {
|
||||
var that = this,
|
||||
created = 0;
|
||||
|
||||
archiveTransport.on('logged', function() {
|
||||
if (++created === 6) {
|
||||
return that.callback();
|
||||
}
|
||||
|
||||
logKbytes(4, created);
|
||||
});
|
||||
|
||||
logKbytes(4, created);
|
||||
},
|
||||
"should be only 3 files called testarchive.log, testarchive1.log.gz and testarchive2.log.gz": function() {
|
||||
//Give the archive a little time to settle
|
||||
// setTimeout(function() {
|
||||
for (var num = 0; num < 6; num++) {
|
||||
var file = !num ? 'testarchive.log' : 'testarchive' + num + '.log.gz',
|
||||
fullpath = path.join(__dirname, '..', 'fixtures', 'logs', file);
|
||||
|
||||
// There should be no files with that name
|
||||
if (num >= 3) {
|
||||
assert.throws(function() {
|
||||
fs.statSync(fullpath);
|
||||
}, Error);
|
||||
} else {
|
||||
// The other files should exist
|
||||
assert.doesNotThrow(function() {
|
||||
fs.statSync(fullpath);
|
||||
}, Error);
|
||||
}
|
||||
}
|
||||
//},5000);
|
||||
},
|
||||
}
|
||||
},
|
||||
}).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) {
|
||||
assert.throws(function () {
|
||||
fs.statSync(fullpath);
|
||||
}, Error);
|
||||
} else {
|
||||
// The other files should be exist
|
||||
assert.doesNotThrow(function () {
|
||||
fs.statSync(fullpath);
|
||||
}, 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);
|
57
node_modules/winston/test/transports/file-open-test.js
generated
vendored
Normal file
57
node_modules/winston/test/transports/file-open-test.js
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* file-open-test.js: Tests for File transport "open" event
|
||||
*
|
||||
* (C) 2014 William Wong
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var assert = require('assert'),
|
||||
fs = require('fs'),
|
||||
os = require('os'),
|
||||
path = require('path'),
|
||||
vows = require('vows'),
|
||||
winston = require('../../lib/winston');
|
||||
|
||||
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);
|
72
node_modules/winston/test/transports/file-stress-test.js
generated
vendored
Normal file
72
node_modules/winston/test/transports/file-stress-test.js
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* file-stress-test.js: Tests for stressing File transport
|
||||
*
|
||||
* (C) 2014 William Wong
|
||||
* MIT LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
var assert = require('assert'),
|
||||
fs = require('fs'),
|
||||
os = require('os'),
|
||||
path = require('path'),
|
||||
vows = require('vows'),
|
||||
winston = require('../../lib/winston');
|
||||
|
||||
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);
|
92
node_modules/winston/test/transports/file-tailrolling-test.js
generated
vendored
Normal file
92
node_modules/winston/test/transports/file-tailrolling-test.js
generated
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
var assert = require('assert'),
|
||||
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', 'testtailrollingfiles.log'),
|
||||
maxsize: 4096,
|
||||
maxFiles: 3,
|
||||
tailable: true
|
||||
});
|
||||
|
||||
process.on('uncaughtException', function (err) {
|
||||
console.log('caught exception');
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
vows.describe('winston/transports/file/tailrolling').addBatch({
|
||||
"An instance of the File Transport": {
|
||||
"when delete old test files": {
|
||||
topic: function () {
|
||||
var logs = path.join(__dirname, '..', 'fixtures', 'logs');
|
||||
fs.readdirSync(logs).forEach(function (file) {
|
||||
if (~file.indexOf('testtailrollingfiles')) {
|
||||
fs.unlinkSync(path.join(logs, file));
|
||||
}
|
||||
});
|
||||
|
||||
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 == 4) {
|
||||
return that.callback();
|
||||
}
|
||||
|
||||
logKbytes(4, created);
|
||||
});
|
||||
|
||||
logKbytes(4, created);
|
||||
},
|
||||
"should be 3 log files, base to maxFiles - 1": function () {
|
||||
var file, fullpath;
|
||||
for (var num = 0; num < 4; num++) {
|
||||
file = !num ? 'testtailrollingfiles.log' : 'testtailrollingfiles' + num + '.log';
|
||||
fullpath = path.join(__dirname, '..', 'fixtures', 'logs', file);
|
||||
|
||||
if (num == 3) {
|
||||
return assert.ok(!fs.existsSync(fullpath));
|
||||
}
|
||||
|
||||
assert.ok(fs.existsSync(fullpath));
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
"should have files in correct order": function () {
|
||||
var file, fullpath, content;
|
||||
['D', 'C', 'B'].forEach(function (letter, i) {
|
||||
file = !i ? 'testtailrollingfiles.log' : 'testtailrollingfiles' + i + '.log';
|
||||
content = fs.readFileSync(path.join(__dirname, '..', 'fixtures', 'logs', file), 'ascii');
|
||||
|
||||
assert.lengthOf(content.match(new RegExp(letter, 'g')), 4068);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module);
|
134
node_modules/winston/test/transports/file-test.js
generated
vendored
Normal file
134
node_modules/winston/test/transports/file-test.js
generated
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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'),
|
||||
stdMocks = require('std-mocks'),
|
||||
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')
|
||||
}),
|
||||
failedFileTransport = new (winston.transports.File)({
|
||||
filename: path.join(__dirname, '..', 'fixtures', 'logs', 'dir404', 'testfile.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 an invalid filename": {
|
||||
"should have proper methods defined": function () {
|
||||
helpers.assertFile(failedFileTransport);
|
||||
},
|
||||
"should enter noop failed state": function () {
|
||||
helpers.assertFailedTransport(failedFileTransport);
|
||||
}
|
||||
},
|
||||
"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);
|
||||
})
|
||||
},
|
||||
"streaming to stdout": {
|
||||
topic: function () {
|
||||
var transport = new (winston.transports.File)({
|
||||
stream: process.stdout, timestamp: false, json: false
|
||||
});
|
||||
stdMocks.use();
|
||||
return transport;
|
||||
},
|
||||
"with showLevel off": {
|
||||
topic: function (stdoutStreamTransport) {
|
||||
stdoutStreamTransport.showLevel = false;
|
||||
stdoutStreamTransport.log('info', '', undefined, this.callback);
|
||||
},
|
||||
"should not have level prepended": function () {
|
||||
var output = stdMocks.flush(),
|
||||
line = output.stdout[0];
|
||||
|
||||
assert.equal(line, '\n');
|
||||
}
|
||||
},
|
||||
// there would be a "with showLevel on" here but I think it's a bug in
|
||||
// this version of vows. ugprading causes even more problems
|
||||
teardown: function() {
|
||||
stdMocks.restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
}).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({
|
||||
"Error object in metadata #610": {
|
||||
topic: function () {
|
||||
var myErr = new Error("foo");
|
||||
|
||||
fileTransport.log('info', 'test message', myErr, this.callback.bind(this, null, myErr));
|
||||
},
|
||||
"should not be modified": function (err, myErr) {
|
||||
assert.equal(myErr.message, "foo");
|
||||
// Not sure if this is the best possible way to check if additional props appeared
|
||||
assert.deepEqual(Object.getOwnPropertyNames(myErr), Object.getOwnPropertyNames(new Error("foo")));
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"Date object in metadata": {
|
||||
topic: function () {
|
||||
var obj = new Date(1000);
|
||||
|
||||
fileTransport.log('info', 'test message', obj, this.callback.bind(this, null, obj));
|
||||
},
|
||||
"should not be modified": function (err, obj) {
|
||||
// Not sure if this is the best possible way to check if additional props appeared
|
||||
assert.deepEqual(Object.getOwnPropertyNames(obj), Object.getOwnPropertyNames(new Date()));
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"Plain object in metadata": {
|
||||
topic: function () {
|
||||
var obj = { message: "foo" };
|
||||
|
||||
fileTransport.log('info', 'test message', obj, this.callback.bind(this, null, obj));
|
||||
},
|
||||
"should not be modified": function (err, obj) {
|
||||
assert.deepEqual(obj, { message: "foo" });
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
"An instance of the File Transport": transport(winston.transports.File, {
|
||||
filename: path.join(__dirname, '..', 'fixtures', 'logs', 'testfile.log')
|
||||
})
|
||||
}).export(module);
|
70
node_modules/winston/test/transports/http-test.js
generated
vendored
Normal file
70
node_modules/winston/test/transports/http-test.js
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* http-test.js: Tests for instances of the HTTP transport
|
||||
*
|
||||
* MIT LICENSE
|
||||
*/
|
||||
|
||||
var path = require('path'),
|
||||
vows = require('vows'),
|
||||
http = require('http'),
|
||||
fs = require('fs'),
|
||||
assert = require('assert'),
|
||||
winston = require('../../lib/winston'),
|
||||
helpers = require('../helpers'),
|
||||
hock = require('hock');
|
||||
|
||||
var transport = require('./transport');
|
||||
|
||||
var host = '127.0.0.1';
|
||||
|
||||
vows.describe('winston/transports/http').addBatch({
|
||||
"When the HTTP endpoint": {
|
||||
topic: function () {
|
||||
var mock = this.mock = hock.createHock(),
|
||||
self = this;
|
||||
|
||||
mock
|
||||
.post('/log', {
|
||||
"method":"collect",
|
||||
"params":{
|
||||
"level":"info",
|
||||
"message":"hello",
|
||||
"meta":{}
|
||||
}
|
||||
})
|
||||
.min(1)
|
||||
.max(1)
|
||||
.reply(200);
|
||||
|
||||
var server = this.server = http.createServer(mock.handler);
|
||||
server.listen(0, '0.0.0.0', this.callback);
|
||||
},
|
||||
"is running": function (err) {
|
||||
assert.ifError(err);
|
||||
},
|
||||
"an instance of the Http transport": {
|
||||
topic: function () {
|
||||
|
||||
var port = this.server.address().port;
|
||||
var self = this,
|
||||
httpTransport = new (winston.transports.Http)({
|
||||
host: host,
|
||||
port: port,
|
||||
path: 'log'
|
||||
});
|
||||
|
||||
httpTransport.log('info', 'hello', function (logErr, logged) {
|
||||
self.mock.done(function (doneErr) {
|
||||
self.callback(null, logErr, logged, doneErr);
|
||||
});
|
||||
});
|
||||
},
|
||||
"should log to the specified URL": function (_, err, logged, requested) {
|
||||
assert.ifError(err);
|
||||
assert.isTrue(logged);
|
||||
assert.ifError(requested);
|
||||
this.server.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}).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);
|
212
node_modules/winston/test/transports/transport.js
generated
vendored
Normal file
212
node_modules/winston/test/transports/transport.js
generated
vendored
Normal file
@ -0,0 +1,212 @@
|
||||
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 '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 = Date.now() - (100 * 1000);
|
||||
var end = Date.now() + (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 = Date.now() + 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;
|
||||
};
|
Reference in New Issue
Block a user