diff --git a/README.md b/README.md index dc6143a..a45fecf 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,25 @@ -# winston-loggly +# winston-loggly-bulk A [Loggly][0] transport for [winston][1]. +[![Version npm](https://img.shields.io/npm/v/winston-loggly-bulk.svg?style=flat-square)](https://www.npmjs.com/package/winston-loggly-bulk)[![npm Downloads](https://img.shields.io/npm/dm/winston-loggly-bulk.svg?style=flat-square)](https://www.npmjs.com/package/winston-loggly-bulk) + +[![NPM](https://nodei.co/npm/winston-loggly-bulk.png?downloads=true&downloadRank=true)](https://nodei.co/npm/winston-loggly-bulk/) + +A client implementation for Loggly in node.js. Check out Loggly's [Node logging documentation](https://www.loggly.com/docs/nodejs-logs/) for more. + + ## Usage ``` js var winston = require('winston'); // - // Requiring `winston-loggly` will expose + // Requiring `winston-loggly-bulk` will expose // `winston.transports.Loggly` // - require('winston-loggly'); + var {Loggly} = require('winston-loggly-bulk'); - winston.add(winston.transports.Loggly, options); + winston.add(new Loggly({options})); ``` The Loggly transport is based on [Nodejitsu's][2] [node-loggly][3] implementation of the [Loggly][0] API. If you haven't heard of Loggly before, you should probably read their [value proposition][4]. The Loggly transport takes the following options. Either 'inputToken' or 'inputName' is required: @@ -26,10 +33,58 @@ The Loggly transport is based on [Nodejitsu's][2] [node-loggly][3] implementatio * __tags:__ An array of tags to send to loggly. * __isBulk:__ If true, sends messages using bulk url * __stripColors:__ Strip color codes from the logs before sending - +* __bufferOptions:__ Buffer options has two configurations. + - __size:__ Number of logs to be buffered. + - __retriesInMilliSeconds:__ Time in milliseconds to retry sending buffered logs. +* __timestamp:__ If false, library will not include timestamp in log events. + - __Note:__ Library includes timestamp by default when we do not set timestamp option. *Metadata:* Logged in suggested [Loggly format][5] +## Sample Working Code Snippet + +``` js +var winston = require('winston'); +var {Loggly} = require('winston-loggly-bulk'); + +winston.add(new Loggly({ + token: "TOKEN", + subdomain: "SUBDOMAIN", + tags: ["Winston-NodeJS"], + json: true +})); + +winston.log('info', "Hello World from Node.js!"); +``` + +## Buffer Support + +This library has buffer support during temporary network outage. User can configure size of buffer (no. of logs to be stored during network outage). + +Add these below configuration in code snippet to override the default values of buffer option __size__ and __retriesInMilliSeconds__. +``` js +bufferOptions: { + size: 1000, + retriesInMilliSeconds: 60 * 1000 +} +``` +* __Note:__ The default value of buffer size and retries in milliseconds are 500 and 30000 (30 seconds) respectively. + +## Flush logs and exit + +Our library uses ajax requests to send logs to Loggly, and as ajax requests take time to complete, logs can be lost when process.exit() is called because it forces an immediate exit. To exit gracefully and ensure that the last logs get to Loggly, we created a function called flushLogsAndExit(). It waits for 10 seconds and then calls process.exit() itself. This allows enough time for the logs to be sent to Loggly. + +Here is an example of how to use the method: + +``` js +var winston = require('winston'); +var {flushLogsAndExit} = require('winston-loggly-bulk'); + +winston.log("info", "Hello World from Node.js!"); +flushLogsAndExit(); + +``` + ## Motivation `tldr;?`: To break the [winston][1] codebase into small modules that work together. @@ -43,11 +98,23 @@ The [winston][1] codebase has been growing significantly with contributions and $ curl http://npmjs.org/install.sh | sh ``` -### Installing winston-loggly +### Installing winston-loggly-bulk + +If you are running npm version 3 or higher then run the below command to setup the logging- + +``` bash + $ npm install winston-loggly-bulk +``` + +If you are running npm version 2 or lower then run the below command to setup the logging- + +``` bash + $ npm install winston-loggly-bulk winston +``` +* __Note:__ To check the currrent npm version run the below command- ``` bash - $ npm install winston - $ npm install winston-loggly + $ npm -v ``` ## Run Tests @@ -74,8 +141,8 @@ Once you have valid configuration and credentials you can run tests with [npm][7 npm test ``` -#### Author: [Charlie Robbins](http://blog.nodejitsu.com) -#### License: MIT +#### Author: [Charlie Robbins](http://www.github.com/indexzero) +#### Contributors: [Loggly](http://github.com/loggly), [Shweta Jain](http://github.com/shwetajain148), [0]: http://loggly.com [1]: https://github.com/flatiron/winston diff --git a/lib/winston-loggly.js b/lib/winston-loggly.js index 17ffc9d..cf08e02 100755 --- a/lib/winston-loggly.js +++ b/lib/winston-loggly.js @@ -6,10 +6,11 @@ * */ -var events = require('events'), - loggly = require('loggly'), +var clone = require('clone'), + loggly = require('node-loggly-bulk'), util = require('util'), winston = require('winston'), + Transport = require('winston-transport'), Stream = require('stream').Stream; // @@ -17,6 +18,8 @@ var events = require('events'), // var code = /\u001b\[(\d+(;\d+)*)?m/g; +var timerFunctionForProcessExit = null; + // // ### function Loggly (options) // #### @options {Object} Options for this instance. @@ -33,7 +36,7 @@ var Loggly = exports.Loggly = function (options) { options.token = options.inputToken; } - winston.Transport.call(this, options); + Transport.call(this, options); if (!options.subdomain) { throw new Error('Loggly Subdomain is required'); } @@ -50,33 +53,57 @@ var Loggly = exports.Loggly = function (options) { this.client = loggly.createClient({ subdomain: options.subdomain, auth: options.auth || null, - json: options.json || false, + json: options.json || false, //TODO: should be false proxy: options.proxy || null, token: options.token, tags: tags, - isBulk: options.isBulk || false + isBulk: options.isBulk || false, + bufferOptions: options.bufferOptions || {size: 500, retriesInMilliSeconds: 30 * 1000} }); - this.timestamp = options.timestamp || false; + this.timestamp = options.timestamp === false ? false : true; this.stripColors = options.stripColors || false; }; +// +// Helper function to call process.exit() after waiting +// 10 seconds. +// +var flushLogsAndExit = exports.flushLogsAndExit = function () { + if (timerFunctionForProcessExit === null) { + timerFunctionForProcessExit = setInterval(function () { + process.exit(); + },10000); + } +} + // // Inherit from `winston.Transport`. // -util.inherits(Loggly, winston.Transport); +util.inherits(Loggly, Transport); // // Define a getter so that `winston.transports.Loggly` // is available and thus backwards compatible. // winston.transports.Loggly = Loggly; +winston.transports.flushLogsAndExit = flushLogsAndExit; // // Expose the name of this Transport on the prototype // Loggly.prototype.name = 'loggly'; +const validateMetadata = (meta) => { + if (meta == null) { + return {}; + } else if (typeof meta !== 'object') { + return { metadata: meta }; + } else { + return clone(meta); + } +} + // // ### function log (level, msg, [meta], callback) // #### @level {string} Level at which to log the message. @@ -86,34 +113,35 @@ Loggly.prototype.name = 'loggly'; // Core logging method exposed to Winston. Metadata is optional. // Loggly.prototype.log = function (level, msg, meta, callback) { + + const message = validateMetadata(meta); + if (this.silent) { return callback(null, true); } - if (this.timestamp && (!meta || !meta.timestamp)) { - meta = meta || {}; - meta.timestamp = (new Date()).toISOString(); + if (this.timestamp && !message.timestamp) { + message.timestamp = (new Date()).toISOString(); } if (this.stripColors) { msg = ('' + msg).replace(code, ''); } - var message = winston.clone(meta || {}), - self = this; + const self = this; message.level = level; - message.message = msg; + message.message = msg || message.message; // // Helper function for responded to logging. // - function logged() { + function logged(err) { self.emit('logged'); - callback(null, true); + callback(err, true); } - return meta && meta.tags + return (meta && meta.tags) ? this.client.log(message, meta.tags, logged) : this.client.log(message, logged); }; @@ -123,9 +151,9 @@ Loggly.prototype.log = function (level, msg, meta, callback) { // #### @options {Object} Set stream options // Returns a log stream. // -Loggly.prototype.stream = function(options) { +Loggly.prototype.stream = function(maybeOptions) { var self = this, - options = options || {}, + options = maybeOptions || {}, stream = new Stream, last, start = options.start, @@ -157,7 +185,7 @@ Loggly.prototype.stream = function(options) { return setTimeout(check, 2000); } - var result = res[res.length-1]; + var result = results[results.length-1]; if (result && result.timestamp) { if (last == null) { last = result.timestamp; @@ -165,7 +193,7 @@ Loggly.prototype.stream = function(options) { } last = result.timestamp; } else { - return func(); + return; } results.forEach(function(log) { @@ -218,10 +246,10 @@ Loggly.prototype.formatQuery = function (query) { // ### 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 +// Formats the specified `results` with the given `options` according // to the implementation of this transport. // -Loggly.prototype.formatResults = function (results, options) { +Loggly.prototype.formatResults = function (results, _options) { return results; }; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..523988f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,646 @@ +{ + "name": "winston-loggly-bulk", + "version": "3.0.0-rc1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "4.17.10" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "color": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/color/-/color-0.8.0.tgz", + "integrity": "sha1-iQwHw/1OZJU3Y4kRz2keVFi2/KU=", + "requires": { + "color-convert": "0.5.3", + "color-string": "0.3.0" + } + }, + "color-convert": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=" + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", + "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", + "requires": { + "color-name": "1.1.3" + } + }, + "colornames": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/colornames/-/colornames-0.0.2.tgz", + "integrity": "sha1-2BH9bIT1kClJmorEQ2ICk1uSvjE=" + }, + "colors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.0.tgz", + "integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw==" + }, + "colorspace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.0.1.tgz", + "integrity": "sha1-yZx5btMRKLmHalLh7l7gOkpxl0k=", + "requires": { + "color": "0.8.0", + "text-hex": "0.0.0" + } + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "diagnostics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.0.tgz", + "integrity": "sha1-4QkJALSVI+hSe+IPCBJ1IF8q42o=", + "requires": { + "colorspace": "1.0.1", + "enabled": "1.0.2", + "kuler": "0.0.0" + } + }, + "diff": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.8.tgz", + "integrity": "sha1-NDJ2MI7Jkbe8giZ+1VvBQR+XFmY=", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "enabled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", + "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", + "requires": { + "env-variable": "0.0.4" + } + }, + "env-variable": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.4.tgz", + "integrity": "sha512-+jpGxSWG4vr6gVxUHOc4p+ilPnql7NzZxOZBxNldsKGjCF+97df3CbuX7XMaDa5oAVkKQj4rKp38rYdC4VcpDg==" + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", + "dev": true + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-safe-stringify": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.4.tgz", + "integrity": "sha512-mNlGUdKOeGNleyrmgbKYtbnCr9KZkZXU7eM89JRo8vY10f7Ul1Fbj07hUBW3N4fC0xM+fmfFfa2zM7mIizhpNQ==" + }, + "fecha": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", + "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.0.6.tgz", + "integrity": "sha1-aVxQvdTi+1xdNwsJHziNNwfikac=", + "dev": true, + "requires": { + "graceful-fs": "3.0.11", + "inherits": "2.0.3", + "minimatch": "1.0.0", + "once": "1.4.0" + } + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.4" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kuler": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-0.0.0.tgz", + "integrity": "sha1-tmu0a5NOVQ9Z2BiEjgq7pPf1VTw=", + "requires": { + "colornames": "0.0.2" + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, + "logform": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-1.9.0.tgz", + "integrity": "sha512-H1gneJlqo1dwmXq52p/X57SztuX20aWQArp69u4x7DDmCkMZgMLtBTm2LMoTz0+wu7HdkICiPj6vBbX8WJFRig==", + "requires": { + "colors": "1.3.0", + "fast-safe-stringify": "2.0.4", + "fecha": "2.3.3", + "ms": "2.1.1", + "triple-beam": "1.3.0" + } + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, + "minimatch": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-1.0.0.tgz", + "integrity": "sha1-4N0hILSeG3JM6NcUxSCCKpQ4V20=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + }, + "moment": { + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", + "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=" + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "natives": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.4.tgz", + "integrity": "sha512-Q29yeg9aFKwhLVdkTAejM/HvYG0Y1Am1+HUkFQGn5k2j8GS+v60TVmZh6nujpEAj/qql+wGUrlryO8bF+b1jEg==", + "dev": true + }, + "node-loggly-bulk": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/node-loggly-bulk/-/node-loggly-bulk-2.2.2.tgz", + "integrity": "sha512-1mjTyyiNID8WXpN1afvsuK4Qp7JX/JsKdnO5xMJpRfEo8ePleCBvWVyaDpJgWuypxZ4BGHcH2MKMe4TClbb5dA==", + "requires": { + "json-stringify-safe": "5.0.1", + "moment": "2.22.2", + "request": "2.87.0" + } + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "one-time": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", + "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", + "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.7.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "sshpk": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "text-hex": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-0.0.0.tgz", + "integrity": "sha1-V4+8haapJjbkLdF7QdAhjM6esrM=" + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "requires": { + "punycode": "1.4.1" + } + }, + "triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "vows": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/vows/-/vows-0.8.0.tgz", + "integrity": "sha1-zQESKnGk+oU4chmBgtQQ3mw9uKM=", + "dev": true, + "requires": { + "diff": "1.0.8", + "eyes": "0.1.8", + "glob": "4.0.6" + } + }, + "winston": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.0.0.tgz", + "integrity": "sha512-7QyfOo1PM5zGL6qma6NIeQQMh71FBg/8fhkSAePqtf5YEi6t+UrPDcUuHhuuUasgso49ccvMEsmqr0GBG2qaMQ==", + "requires": { + "async": "2.6.1", + "diagnostics": "1.1.0", + "is-stream": "1.1.0", + "logform": "1.9.0", + "one-time": "0.0.4", + "readable-stream": "2.3.6", + "stack-trace": "0.0.10", + "triple-beam": "1.3.0", + "winston-transport": "4.2.0" + } + }, + "winston-transport": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.2.0.tgz", + "integrity": "sha512-0R1bvFqxSlK/ZKTH86nymOuKv/cT1PQBMuDdA7k7f0S9fM44dNH6bXnuxwXPrN8lefJgtZq08BKdyZ0DZIy/rg==", + "requires": { + "readable-stream": "2.3.6", + "triple-beam": "1.3.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/package.json b/package.json index 797c7e3..e1fbbd4 100644 --- a/package.json +++ b/package.json @@ -1,21 +1,45 @@ { - "name": "winston-loggly", - "version": "1.3.1", + "name": "winston-loggly-bulk", + "version": "3.0.0-rc1", "description": "A Loggly transport for winston", - "author": "Charlie Robbins ", + "author": "Loggly ", + "contributors": [ + { + "name": "Loggly", + "email": "opensource@loggly.com", + "url": "https://github.com/loggly" + }, + { + "name": "Shweta Jain", + "email": "shweta.jain@psquickit.com", + "url": "https://github.com/shwetajain148" + } + ], "repository": { "type": "git", - "url": "http://github.com/indexzero/winston-loggly.git" + "url": "https://github.com/loggly/winston-loggly-bulk.git" }, - "keywords": ["logging", "sysadmin", "tools"], + "keywords": [ + "loggly", + "logging", + "sysadmin", + "tools", + "winston" + ], "dependencies": { - "loggly": "~1.1.0" + "clone": "^2.1.1", + "node-loggly-bulk": "^2.0.1", + "winston": "^3.0", + "winston-transport": "^4.2.0" }, "devDependencies": { - "winston": "1.0.x", "vows": "0.8.0" }, "main": "./lib/winston-loggly", - "scripts": { "test": "vows --spec" }, - "engines": { "node": ">= 0.8.0" } + "scripts": { + "test": "vows --spec" + }, + "engines": { + "node": ">= 6.4.0" + } } diff --git a/test/helpers.js b/test/helpers.js new file mode 100644 index 0000000..292c041 --- /dev/null +++ b/test/helpers.js @@ -0,0 +1,79 @@ +const winston = require('winston'); +module.exports.testLevels = function (transport, assertMsg, assertFn) { + var tests = {}; + const levels = winston.config.npm.levels; + + 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 nummetadatatest = { + topic: function () { + transport.log('info', 'test message', 123456789, this.callback.bind(this, null)); + } + }; + + nummetadatatest[assertMsg] = assertFn; + tests['when passed numeric metadata'] = nummetadatatest; + +// circular references aren't supportded by regular JSON, and it's not supported +// by node-loggly-bulk. I'm omitting it for now. If it wants to be fixed, then +// node-loggly-bulk needs an update. +/* + var circmetadata = { }; + circmetadata['metadata'] = circmetadata; + + var circmetadatatest = { + topic: function () { + transport.log('info', 'circular message', circmetadata, this.callback.bind(this, null)); + } + }; + + circmetadatatest[assertMsg] = assertFn; + tests['when passed circular metadata'] = circmetadatatest; + + var circerror = new Error("message!"); + var foo = {}; + var circerrordatatest; + + foo.bar = foo; + circerror.foo = foo; + circerror.stack = 'Some stacktrace'; + + circerrordatatest = { + topic: function () { + transport.log('info', 'circular error', circerror, this.callback.bind(this, null)); + } + }; + + circerrordatatest[assertMsg] = assertFn; + tests['when passed circular error as metadata'] = circerrordatatest; +*/ + + return tests; +}; diff --git a/test/winston-loggly-test.js b/test/winston-loggly-test.js index 55eb1d5..57ead75 100644 --- a/test/winston-loggly-test.js +++ b/test/winston-loggly-test.js @@ -6,11 +6,9 @@ * */ -var path = require('path'), - vows = require('vows'), +var vows = require('vows'), assert = require('assert'), - winston = require('winston'), - helpers = require('winston/test/helpers'), + helpers = require('./helpers.js'), Loggly = require('../lib/winston-loggly').Loggly; var tokenTransport, @@ -20,8 +18,8 @@ try { config = require('./config'); } catch (ex) { - console.log('Error reading test/config.json.') - console.log('Are you sure it exists?\n'); + console.error('Error reading test/config.json.') + console.error('Are you sure it exists?\n'); console.dir(ex); process.exit(1); } @@ -31,6 +29,9 @@ tokenTransport = new (Loggly)({ token: config.transports.loggly.token }); +tokenTransport.log('warning', 'test message', {}, (_err, _res) => { +}) + function assertLoggly(transport) { assert.instanceOf(transport, Loggly); assert.isFunction(transport.log); @@ -42,10 +43,10 @@ vows.describe('winston-loggly').addBatch({ "should have the proper methods defined": function () { assertLoggly(tokenTransport); }, - "the log() method": helpers.testNpmLevels(tokenTransport, "should log messages to loggly", function (ign, err, logged) { + "the log() method": helpers.testLevels(tokenTransport, "should log messages to loggly", function (ign, err, logged) { assert.isNull(err); assert.isTrue(logged); }) } } -}).export(module); \ No newline at end of file +}).export(module);