diff --git a/README.md b/README.md index 1021b6a..3147adc 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,9 @@ Please note that the documentation below is for `winston-loggly-bulk@2.x`. [Read // Requiring `winston-loggly-bulk` will expose // `winston.transports.Loggly` // - require('winston-loggly-bulk'); + 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: @@ -45,6 +45,22 @@ The Loggly transport is based on [Nodejitsu's][2] [node-loggly][3] implementatio *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). @@ -65,11 +81,11 @@ Our library uses ajax requests to send logs to Loggly, and as ajax requests take Here is an example of how to use the method: ``` js -var winston = require('winston'), -winlog = require('winston-loggly-bulk'); +var winston = require('winston'); +var {flushLogsAndExit} = require('winston-loggly-bulk'); -winston.log("info", "hello World"); -winlog.flushLogsAndExit(); +winston.log("info", "Hello World from Node.js!"); +flushLogsAndExit(); ``` diff --git a/lib/winston-loggly.js b/lib/winston-loggly.js old mode 100644 new mode 100755 index ca82fb8..5ebc90a --- a/lib/winston-loggly.js +++ b/lib/winston-loggly.js @@ -6,10 +6,11 @@ * */ -var events = require('events'), +var clone = require('clone'), loggly = require('node-loggly-bulk'), util = require('util'), winston = require('winston'), + Transport = require('winston-transport'), Stream = require('stream').Stream; // @@ -35,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'); } @@ -52,7 +53,7 @@ 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, @@ -80,7 +81,7 @@ var flushLogsAndExit = exports.flushLogsAndExit = function () { // // Inherit from `winston.Transport`. // -util.inherits(Loggly, winston.Transport); +util.inherits(Loggly, Transport); // // Define a getter so that `winston.transports.Loggly` @@ -94,6 +95,16 @@ winston.transports.flushLogsAndExit = flushLogsAndExit; // 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. @@ -102,37 +113,37 @@ Loggly.prototype.name = 'loggly'; // #### @callback {function} Continuation to respond to when complete. // Core logging method exposed to Winston. Metadata is optional. // -Loggly.prototype.log = function (level, msg, meta, callback) { +Loggly.prototype.log = function (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, ''); + message.message = ('' + message.message).replace(code, ''); } - var message = winston.clone(meta || {}), - self = this; - - message.level = level; - message.message = msg || message.message; + const self = this; // // Helper function for responded to logging. // function logged(err) { self.emit('logged'); - callback(err, true); } - return meta && meta.tags + result = (meta && meta.tags) ? this.client.log(message, meta.tags, logged) : this.client.log(message, logged); + + callback(); + return result; }; // @@ -140,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, @@ -174,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; @@ -182,7 +193,7 @@ Loggly.prototype.stream = function(options) { } last = result.timestamp; } else { - return func(); + return; } results.forEach(function(log) { @@ -235,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.json b/package.json index e6accdb..6daa4a1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "winston-loggly-bulk", - "version": "2.0.3", + "version": "3.0.1", "description": "A Loggly transport for winston", "author": "Loggly ", "contributors": [ @@ -19,15 +19,27 @@ "type": "git", "url": "https://github.com/loggly/winston-loggly-bulk.git" }, - "keywords": ["loggly", "logging", "sysadmin", "tools", "winston"], + "keywords": [ + "loggly", + "logging", + "sysadmin", + "tools", + "winston" + ], "dependencies": { "node-loggly-bulk": "^2.0.1", - "winston": "^2.3.1" + "clone": "^2.1.1", + "winston": "^3.0", + "winston-transport": "^4.2.0" }, "devDependencies": { "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);