winston-papertrail
Advanced tools
Comparing version 0.1.5 to 0.2.0
@@ -0,1 +1,7 @@ | ||
# v0.2.0 # | ||
- Added support for non-TLS connections | ||
- Cleaned up Socket Error handling due to keep-alive changes #23 [eric][4] | ||
- Moved tests to Mocha (Finally!) | ||
- Cleaned up README for all options | ||
# v0.1.4 # | ||
@@ -42,1 +48,3 @@ - Handling case when meta is an empty object [voodootikigod][3] | ||
[3]: https://github.com/voodootikigod | ||
[4]: https://github.com/eric | ||
@@ -29,2 +29,4 @@ /* | ||
* | ||
* @param {Boolean} [options.disableTls] disable TLS connections, enabled by default | ||
* | ||
* @param {string} [options.hostname] name for the logging hostname in Papertrail | ||
@@ -76,2 +78,5 @@ * | ||
// Disable TLS connections (enabled by default) | ||
self.disableTls = typeof options.disableTls === 'boolean' ? options.disableTls : false; | ||
// Hostname of the current app | ||
@@ -107,2 +112,6 @@ self.hostname = options.hostname || os.hostname(); | ||
// Maximum buffer size (default: 1MB) | ||
self.maxBufferSize = | ||
options.maxBufferSize || 1 * 1024 * 1024; | ||
// Inline meta flag | ||
@@ -123,61 +132,80 @@ self.inlineMeta = options.inlineMeta || false; | ||
// Open the connection | ||
try { | ||
connectStream(); | ||
} | ||
catch (e) { | ||
// TODO figure out a better way of sending errors from connection | ||
self.emit('error', e); | ||
} | ||
connectStream(); | ||
// Opens a connection to Papertrail | ||
function connectStream() { | ||
if (self._shutdown) { | ||
// don't connect on either error or shutdown | ||
if (self._shutdown || self._erroring) { | ||
return; | ||
} | ||
self.socket = net.createConnection(self.port, self.host, function () { | ||
self.socket.setKeepAlive(true, self._KEEPALIVE_INTERVAL); | ||
self.stream = tls.connect({ | ||
socket: self.socket, | ||
rejectUnauthorized: false | ||
}, onConnected); | ||
self.stream.on('error', function (err) { | ||
self.emit('error', err); | ||
try { | ||
// We may be disconnected from the papertrail endpoint for any number of reasons; | ||
// i.e. inactivity, network problems, etc, and we need to be resilient against this | ||
// that said, we back off reconnection attempts in case Papertrail is truly down | ||
function wireStreams() { | ||
self.stream.on('error', onErrored); | ||
setTimeout(function () { | ||
// If we have the stream end, simply reconnect | ||
self.stream.on('end', connectStream); | ||
} | ||
// Increment our retry counts | ||
self.currentRetries++; | ||
self.totalRetries++; | ||
if (self.disableTls) { | ||
self.stream = net.createConnection(self.port, self.host, onConnected); | ||
self.stream.setKeepAlive(true, self._KEEPALIVE_INTERVAL); | ||
// Decay the retry rate exponentially up to max between attempts | ||
if ((self.connectionDelay < self.maxDelayBetweenReconnection) && | ||
(self.currentRetries >= self.attemptsBeforeDecay)) { | ||
self.connectionDelay = self.connectionDelay * 2; | ||
self.currentRetries = 0; | ||
} | ||
wireStreams(); | ||
} | ||
else { | ||
var socket = net.createConnection(self.port, self.host, function () { | ||
socket.setKeepAlive(true, self._KEEPALIVE_INTERVAL); | ||
connectStream(); | ||
self.stream = tls.connect({ | ||
socket: socket, | ||
rejectUnauthorized: false | ||
}, onConnected); | ||
// Stop buffering messages after a fixed number of retries. | ||
// This is to keep the buffer from growing unbounded | ||
if (self.loggingEnabled && | ||
(self.totalRetries >= (self.maximumAttempts))) { | ||
self.loggingEnabled = false; | ||
self.emit('error', new Error('Max entries eclipsed, disabling buffering')); | ||
} | ||
wireStreams(); | ||
}); | ||
}, self.connectionDelay); | ||
}); | ||
socket.on('error', onErrored); | ||
} | ||
} | ||
catch (e) { | ||
onErrored(e); | ||
} | ||
} | ||
// If we have the stream end, simply reconnect | ||
self.stream.on('end', function () { | ||
connectStream(); | ||
}); | ||
}); | ||
function onErrored(err) { | ||
// make sure we prevent simultaneous attempts to connect and handle errors | ||
self._erroring = true; | ||
self.emit('error', err); | ||
// We may be disconnected from the papertrail endpoint for any number of reasons; | ||
// i.e. inactivity, network problems, etc, and we need to be resilient against this | ||
// that said, we back off reconnection attempts in case Papertrail is truly down | ||
setTimeout(function () { | ||
// Increment our retry counts | ||
self.currentRetries++; | ||
self.totalRetries++; | ||
// Decay the retry rate exponentially up to max between attempts | ||
if ((self.connectionDelay < self.maxDelayBetweenReconnection) && | ||
(self.currentRetries >= self.attemptsBeforeDecay)) { | ||
self.connectionDelay = self.connectionDelay * 2; | ||
self.currentRetries = 0; | ||
} | ||
// Stop buffering messages after a fixed number of retries. | ||
// This is to keep the buffer from growing unbounded | ||
if (self.loggingEnabled && | ||
(self.totalRetries >= (self.maximumAttempts))) { | ||
self.loggingEnabled = false; | ||
self.emit('error', new Error('Max entries eclipsed, disabling buffering')); | ||
} | ||
// continue | ||
self._erroring = false; | ||
connectStream(); | ||
}, self.connectionDelay); | ||
} | ||
@@ -190,3 +218,3 @@ | ||
self.totalRetries = 0; | ||
self.connectionDelay = 1000; | ||
self.connectionDelay = options.connectionDelay || 1000; | ||
@@ -196,3 +224,3 @@ self.emit('connect', 'Connected to Papertrail at ' + self.host + ':' + self.port); | ||
// Did we get messages buffered | ||
if (self.buffer) { | ||
if (self.buffer.length > 0) { | ||
self.stream.write(self.buffer); | ||
@@ -259,3 +287,3 @@ self.buffer = ''; | ||
} | ||
else { | ||
else if (meta.length > 0) { | ||
if (this.inlineMeta) { | ||
@@ -324,3 +352,3 @@ output += ' ' + util.inspect(meta, false, null, self.colorize).replace(/[\n\t]/gm, " "); | ||
} | ||
else if (this.loggingEnabled) { | ||
else if (this.loggingEnabled && this.buffer.length < this.maxBufferSize) { | ||
this.buffer += msg; | ||
@@ -327,0 +355,0 @@ } |
{ | ||
"name": "winston-papertrail", | ||
"description": "A Papertrail transport for winston", | ||
"version": "0.1.5", | ||
"version": "0.2.0", | ||
"author": "Ken Perkins <ken.perkins@rackspace.com>", | ||
@@ -18,4 +18,5 @@ "repository": { | ||
"devDependencies": { | ||
"winston": ">=0.6.x", | ||
"vows": "0.5.x" | ||
"mocha": "^2.0.1", | ||
"should": "^4.3.0", | ||
"winston": ">=0.6.x" | ||
}, | ||
@@ -27,3 +28,3 @@ "peerDependencies": { | ||
"scripts": { | ||
"test": "vows test/*-test.js --spec" | ||
"test": "mocha test/*-test.js --spec" | ||
}, | ||
@@ -30,0 +31,0 @@ "engines": { |
@@ -1,2 +0,2 @@ | ||
# winston-papertrail | ||
# winston-papertrail [![Build Status](https://secure.travis-ci.org/kenperkins/winston-papertrail.png?branch=master)](http://travis-ci.org/kenperkins/winston-papertrail) [![NPM version](https://badge.fury.io/js/winston-papertrail.png)](http://badge.fury.io/js/winston-papertrail) | ||
@@ -23,4 +23,5 @@ A Papertrail transport for [winston][0]. | ||
* __host:__ FQDN or IP Address of the Papertrail Service Endpoint | ||
* __port:__ The TLS Endpoint TCP Port | ||
* __port:__ The Endpoint TCP Port | ||
## Usage | ||
@@ -41,3 +42,3 @@ ``` js | ||
port: 12345 | ||
}) | ||
}); | ||
] | ||
@@ -49,2 +50,23 @@ }); | ||
There are a number of optional settings: | ||
- `disableTls` - set to `true` to disable TLS on your transport. Defaults to `false` | ||
- `level` - The log level to use for this transport, defaults to `info` | ||
- `hostname` - The hostname for your transport, defaults to `os.hostname()` | ||
- `program` - The program for your transport, defaults to `default` | ||
- `logFormat` - A function to format your log message before sending, see below | ||
- `colorize` - Enable colors in Papertrail, defaults to `false` | ||
- `inlineMeta` - Inline multi-line messages, defaults to `false` | ||
- `handleExceptions` - Tell this Transport to handle exceptions, defaults to `false` | ||
There are also a number of settings for connection failure and retry behavior | ||
- `attemptsBeforeDecay` - How many retries should be attempted before backing off, defaults to `5` | ||
- `maximumAttempts` - How many retries before disabling buffering, defaults to `25` | ||
- `connectionDelay` - How long between backoff in milliseconds, defaults to `1000` | ||
- `maxDelayBetweenReconnection` - The maximum backoff in milliseconds, defaults to `60000` | ||
- `maxBufferSize` - The maximum size of the retry buffer, in bytes, defaults to `1048576` | ||
## Advanced Usage | ||
For more some advanced logging, you can take advantage of custom formatting for | ||
@@ -77,2 +99,4 @@ Papertrail: | ||
## Transport Events | ||
The Papertrail transport is also capable of emitting events for `error` and `connect` so you can log to other transports: | ||
@@ -96,2 +120,3 @@ | ||
hostname: 'web-01', | ||
level: 'debug', | ||
logFormat: function(level, message) { | ||
@@ -166,11 +191,8 @@ return '[' + level + '] ' + message; | ||
logger.info('logging before I close'); | ||
logger.close(); // this closes the underlying TLS connection in the Papertrailt transport | ||
logger.close(); // this closes the underlying connection in the Papertrail transport | ||
}); | ||
``` | ||
Currently, the Papertrail transport only supports TLS logging. | ||
#### Author: [Ken Perkins](http://blog.clipboard.com) | ||
[0]: https://github.com/flatiron/winston |
/* | ||
* papertrail-test.js: Tests for instances of the Papertrail transport | ||
* | ||
* (C) 2012 Ken Perkins | ||
* (C) 2014 Ken Perkins | ||
* MIT LICENSE | ||
@@ -12,25 +12,207 @@ * | ||
var path = require('path'), | ||
vows = require('vows'), | ||
assert = require('assert'), | ||
winston = require('winston'), | ||
helpers = require('winston/test/helpers'), | ||
Papertrail = require('../lib/winston-papertrail').Papertrail; | ||
should = require('should'), | ||
fs = require('fs'), | ||
winston = require('winston'), | ||
net = require('net'), | ||
tls = require('tls'), | ||
Papertrail = require('../lib/winston-papertrail').Papertrail; | ||
function assertPapertrail (transport) { | ||
assert.instanceOf(transport, Papertrail); | ||
assert.isFunction(transport.log); | ||
}; | ||
describe('connection tests', function() { | ||
var transport = new Papertrail({host: 'localhost', port: 12345}); | ||
describe('invalid connections', function() { | ||
it('should fail to connect', function (done) { | ||
var pt = new Papertrail({ | ||
host: 'this.wont.resolve', | ||
port: 12345, | ||
attemptsBeforeDecay: 0, | ||
connectionDelay: 10000 | ||
}); | ||
vows.describe('winston-papertrail').addBatch({ | ||
"An instance of the Papertrail Transport": { | ||
"should have the proper methods defined": function () { | ||
assertPapertrail(transport); | ||
}, | ||
"the log() method": helpers.testNpmLevels(transport, "should log messages to papertrail", function (ign, err, meta, result) { | ||
assert.isTrue(!err); | ||
assert.isObject(result); | ||
}) | ||
} | ||
}).export(module); | ||
pt.on('error', function (err) { | ||
should.exist(err); | ||
done(); | ||
}); | ||
}); | ||
it.skip('should timeout', function (done) { | ||
var pt = new Papertrail({ | ||
host: '8.8.8.8', // TODO Figure out how to enable a timeout test | ||
port: 12345, | ||
attemptsBeforeDecay: 0, | ||
connectionDelay: 10000 | ||
}); | ||
pt.on('error', function (err) { | ||
should.exist(err); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
describe('valid connection over tls', function() { | ||
var server, listener = function() {}; | ||
before(function(done) { | ||
server = tls.createServer({ | ||
key: fs.readFileSync('./test/server.key'), | ||
cert: fs.readFileSync('./test/server.crt'), | ||
rejectUnauthorized: false | ||
}, function (socket) { | ||
socket.on('data', listener); | ||
}); | ||
server.listen(23456, function() { | ||
done(); | ||
}); | ||
}); | ||
it('should connect', function (done) { | ||
var pt = new Papertrail({ | ||
host: 'localhost', | ||
port: 23456, | ||
attemptsBeforeDecay: 0, | ||
connectionDelay: 10000 | ||
}); | ||
pt.on('error', function (err) { | ||
should.not.exist(err); | ||
}); | ||
pt.on('connect', function () { | ||
done(); | ||
}); | ||
}); | ||
it('should send message', function (done) { | ||
var pt = new Papertrail({ | ||
host: 'localhost', | ||
port: 23456, | ||
attemptsBeforeDecay: 0, | ||
connectionDelay: 10000 | ||
}); | ||
pt.on('error', function (err) { | ||
should.not.exist(err); | ||
}); | ||
pt.on('connect', function () { | ||
pt.log('info', 'hello', function() { | ||
}); | ||
}); | ||
listener = function(data) { | ||
should.exist(data); | ||
data.toString().indexOf('default info hello\r\n').should.not.equal(-1); | ||
done(); | ||
} | ||
}); | ||
// TODO need to fix the TLS Server to reject new sockets that are not over tls | ||
it.skip('should fail to connect without tls', function (done) { | ||
var pt = new Papertrail({ | ||
host: 'localhost', | ||
port: 23456, | ||
disableTls: true, | ||
attemptsBeforeDecay: 0, | ||
connectionDelay: 10000 | ||
}); | ||
pt.on('error', function (err) { | ||
should.exist.exist(err); | ||
done(); | ||
}); | ||
}); | ||
after(function(done) { | ||
server.close(); | ||
done(); | ||
}); | ||
}); | ||
describe('valid connection over tcp', function () { | ||
var server, listener = function () { | ||
}; | ||
before(function (done) { | ||
server = net.createServer(function (socket) { | ||
socket.on('data', listener); | ||
}); | ||
server.listen(23456, function () { | ||
done(); | ||
}); | ||
}); | ||
it('should connect', function (done) { | ||
var pt = new Papertrail({ | ||
host: 'localhost', | ||
port: 23456, | ||
disableTls: true, | ||
attemptsBeforeDecay: 0, | ||
connectionDelay: 10000 | ||
}); | ||
pt.on('error', function (err) { | ||
should.not.exist(err); | ||
}); | ||
pt.on('connect', function () { | ||
done(); | ||
}); | ||
}); | ||
it('should send message', function (done) { | ||
var pt = new Papertrail({ | ||
host: 'localhost', | ||
port: 23456, | ||
disableTls: true, | ||
attemptsBeforeDecay: 0, | ||
connectionDelay: 10000 | ||
}); | ||
pt.on('error', function (err) { | ||
should.not.exist(err); | ||
}); | ||
pt.on('connect', function () { | ||
pt.log('info', 'hello', function () { | ||
}); | ||
}); | ||
listener = function (data) { | ||
should.exist(data); | ||
data.toString().indexOf('default info hello\r\n').should.not.equal(-1); | ||
done(); | ||
} | ||
}); | ||
// TODO figure out how to get this to fail | ||
it.skip('should fail to connect via tls', function (done) { | ||
var pt = new Papertrail({ | ||
host: 'localhost', | ||
port: 23456, | ||
attemptsBeforeDecay: 0, | ||
connectionDelay: 10000 | ||
}); | ||
pt.on('error', function (err) { | ||
throw err; | ||
should.exist.exist(err); | ||
done(); | ||
}); | ||
}); | ||
after(function (done) { | ||
server.close(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
55543
22
486
193
3
1
4