Comparing version 5.7.0 to 5.8.0
CHANGELOG | ||
========= | ||
## 5.8.0 (2018-7-17) | ||
* @michalholasek Clean up code formatting and split up tests | ||
* @michalholasek Add tcp protocol support | ||
* @remie Add tcp protocol support | ||
## 5.7.0 (2018-7-4) | ||
@@ -5,0 +10,0 @@ * @Willyham Add support for recording buffers in mock mode |
@@ -1,2 +0,2 @@ | ||
"use strict"; | ||
'use strict'; | ||
@@ -6,2 +6,3 @@ var dgram = require('dgram'), | ||
dns = require('dns'), | ||
net = require('net'), | ||
helpers = require('./helpers'), | ||
@@ -17,3 +18,3 @@ applyStatsFns = require('./statsFunctions'); | ||
* @option suffix {String} An optional suffix to assign to each stat name sent | ||
* @option globalize {boolean} An optional boolean to add "statsd" as an object in the global namespace | ||
* @option globalize {boolean} An optional boolean to add 'statsd' as an object in the global namespace | ||
* @option cacheDns {boolean} An optional option to only lookup the hostname -> ip address once | ||
@@ -30,7 +31,7 @@ * @option mock {boolean} An optional boolean indicating this Client is a mock object, no stats are sent. | ||
var Client = function (host, port, prefix, suffix, globalize, cacheDns, mock, | ||
globalTags, maxBufferSize, bufferFlushInterval, telegraf, sampleRate) { | ||
globalTags, maxBufferSize, bufferFlushInterval, telegraf, sampleRate, protocol) { | ||
var options = host || {}, | ||
self = this; | ||
if(arguments.length > 1 || typeof(host) === 'string'){ | ||
if (arguments.length > 1 || typeof(host) === 'string') { | ||
options = { | ||
@@ -48,9 +49,34 @@ host : host, | ||
telegraf : telegraf, | ||
sampleRate : sampleRate | ||
sampleRate : sampleRate, | ||
protocol : protocol | ||
}; | ||
} | ||
var createSocket = function createSocket(instance, args) { | ||
var socket; | ||
var errMessage; | ||
if (args.protocol === 'tcp') { | ||
try { | ||
socket = net.connect(args.port, args.host); | ||
socket.setKeepAlive(true); | ||
} catch (e) { | ||
errMessage = 'Could not establish connection to ' + args.host + ':' + args.port; | ||
if (instance.errorHandler) { | ||
instance.errorHandler(new Error(errMessage)); | ||
} else { | ||
console.log(errMessage); | ||
} | ||
} | ||
} else { | ||
socket = dgram.createSocket('udp4'); | ||
} | ||
return socket; | ||
}; | ||
// hidden global_tags option for backwards compatibility | ||
options.globalTags = options.globalTags || options.global_tags; | ||
this.protocol = (options.protocol && options.protocol.toLowerCase()); | ||
this.host = options.host || 'localhost'; | ||
@@ -60,5 +86,9 @@ this.port = options.port || 8125; | ||
this.suffix = options.suffix || ''; | ||
this.socket = options.isChild ? options.socket : dgram.createSocket('udp4'); | ||
this.socket = options.isChild ? options.socket : createSocket(this, { | ||
host: this.host, | ||
port: this.port, | ||
protocol: this.protocol | ||
}); | ||
this.mock = options.mock; | ||
this.globalTags = typeof options.globalTags === "object" ? | ||
this.globalTags = typeof options.globalTags === 'object' ? | ||
helpers.formatTags(options.globalTags, options.telegraf) : []; | ||
@@ -69,3 +99,3 @@ this.telegraf = options.telegraf || false; | ||
this.bufferFlushInterval = options.bufferFlushInterval || 1000; | ||
this.bufferHolder = options.isChild ? options.bufferHolder : { buffer: "" }; | ||
this.bufferHolder = options.isChild ? options.bufferHolder : { buffer: '' }; | ||
this.errorHandler = options.errorHandler; | ||
@@ -79,3 +109,3 @@ | ||
// We only want a single flush event per parent and all its child clients | ||
if(!options.isChild && this.maxBufferSize > 0) { | ||
if (!options.isChild && this.maxBufferSize > 0) { | ||
this.intervalHandle = setInterval(this.onBufferFlushInterval.bind(this), this.bufferFlushInterval); | ||
@@ -88,5 +118,5 @@ } | ||
} | ||
} else if (options.cacheDns === true){ | ||
dns.lookup(options.host, function(err, address, family){ | ||
if(err === null){ | ||
} else if (options.cacheDns === true) { | ||
dns.lookup(options.host, function (err, address, family) { | ||
if (err === null) { | ||
self.host = address; | ||
@@ -103,10 +133,10 @@ } else { | ||
if(options.globalize){ | ||
if (options.globalize) { | ||
global.statsd = this; | ||
} | ||
if(options.useDefaultRoute) { | ||
if (options.useDefaultRoute) { | ||
var defaultRoute = helpers.getDefaultRoute(); | ||
if (defaultRoute) { | ||
console.log('Got ' + defaultRoute + " for the system's default route"); | ||
console.log('Got ' + defaultRoute + ' for the system\'s default route'); | ||
this.host = defaultRoute; | ||
@@ -135,3 +165,3 @@ } | ||
*/ | ||
Client.prototype.sendAll = function(stat, value, type, sampleRate, tags, callback){ | ||
Client.prototype.sendAll = function (stat, value, type, sampleRate, tags, callback) { | ||
var completed = 0, | ||
@@ -142,3 +172,3 @@ calledback = false, | ||
if(sampleRate && typeof sampleRate !== 'number'){ | ||
if (sampleRate && typeof sampleRate !== 'number') { | ||
callback = tags; | ||
@@ -149,3 +179,3 @@ tags = sampleRate; | ||
if(tags && typeof tags !== "object"){ | ||
if (tags && typeof tags !== 'object') { | ||
callback = tags; | ||
@@ -160,14 +190,13 @@ tags = undefined; | ||
*/ | ||
function onSend(error, bytes){ | ||
function onSend(error, bytes) { | ||
completed += 1; | ||
if(calledback){ | ||
if (calledback) { | ||
return; | ||
} | ||
if(error){ | ||
if (error) { | ||
if (typeof callback === 'function') { | ||
calledback = true; | ||
callback(error); | ||
} | ||
else if (self.errorHandler) { | ||
} else if (self.errorHandler) { | ||
calledback = true; | ||
@@ -179,4 +208,7 @@ self.errorHandler(error); | ||
sentBytes += bytes; | ||
if(completed === stat.length && typeof callback === 'function'){ | ||
if (bytes) { | ||
sentBytes += bytes; | ||
} | ||
if (completed === stat.length && typeof callback === 'function') { | ||
callback(null, sentBytes); | ||
@@ -186,4 +218,4 @@ } | ||
if(Array.isArray(stat)){ | ||
stat.forEach(function(item){ | ||
if (Array.isArray(stat)) { | ||
stat.forEach(function (item) { | ||
self.sendStat(item, value, type, sampleRate, tags, onSend); | ||
@@ -209,7 +241,7 @@ }); | ||
sampleRate = sampleRate || this.sampleRate; | ||
if(sampleRate && sampleRate < 1){ | ||
if(Math.random() < sampleRate){ | ||
if (sampleRate && sampleRate < 1) { | ||
if (Math.random() < sampleRate) { | ||
message += '|@' + sampleRate; | ||
} else { | ||
//don't want to send if we don't meet the sample ratio | ||
// don't want to send if we don't meet the sample ratio | ||
return callback ? callback() : undefined; | ||
@@ -229,6 +261,6 @@ } | ||
var mergedTags = this.globalTags; | ||
if(tags && typeof tags === "object"){ | ||
if (tags && typeof tags === 'object') { | ||
mergedTags = helpers.overrideTags(mergedTags, tags, this.telegraf); | ||
} | ||
if(mergedTags.length > 0){ | ||
if (mergedTags.length > 0) { | ||
if (this.telegraf) { | ||
@@ -241,2 +273,3 @@ message = message.split(':'); | ||
} | ||
this._send(message, callback); | ||
@@ -256,4 +289,3 @@ }; | ||
return callback(this.dnsError); | ||
} | ||
else if (this.errorHandler) { | ||
} else if (this.errorHandler) { | ||
return this.errorHandler(this.dnsError); | ||
@@ -265,13 +297,11 @@ } | ||
// Only send this stat if we're not a mock Client. | ||
if(!this.mock) { | ||
if(this.maxBufferSize === 0) { | ||
if (!this.mock) { | ||
if (this.maxBufferSize === 0) { | ||
this.sendMessage(message, callback); | ||
} | ||
else { | ||
} else { | ||
this.enqueue(message, callback); | ||
} | ||
} | ||
else { | ||
} else { | ||
this.mockBuffer.push(message); | ||
if(typeof callback === 'function'){ | ||
if (typeof callback === 'function') { | ||
callback(null, 0); | ||
@@ -287,4 +317,4 @@ } | ||
*/ | ||
Client.prototype.enqueue = function(message, callback){ | ||
message += "\n"; | ||
Client.prototype.enqueue = function (message, callback) { | ||
message += '\n'; | ||
@@ -306,5 +336,5 @@ if (this.bufferHolder.buffer.length + message.length > this.maxBufferSize) { | ||
*/ | ||
Client.prototype.flushQueue = function(callback){ | ||
Client.prototype.flushQueue = function (callback) { | ||
this.sendMessage(this.bufferHolder.buffer, callback); | ||
this.bufferHolder.buffer = ""; | ||
this.bufferHolder.buffer = ''; | ||
}; | ||
@@ -318,6 +348,6 @@ | ||
*/ | ||
Client.prototype.sendMessage = function(message, callback){ | ||
// Guard against "RangeError: Offset into buffer too large" in node 0.10 | ||
Client.prototype.sendMessage = function (message, callback) { | ||
// Guard against 'RangeError: Offset into buffer too large' in node 0.10 | ||
// https://github.com/nodejs/node-v0.x-archive/issues/7884 | ||
if (message === "") { | ||
if (message === '') { | ||
if (callback) { | ||
@@ -328,15 +358,21 @@ callback(null); | ||
} | ||
if (this.protocol === 'tcp' && message.lastIndexOf('\n') !== message.length - 1) { | ||
message += '\n'; | ||
} | ||
var buf = new Buffer(message); | ||
try { | ||
this.socket.send(buf, 0, buf.length, this.port, this.host, callback); | ||
} | ||
catch(err) { | ||
if (this.protocol === 'tcp') { | ||
this.socket.write(buf, 'ascii', callback); | ||
} else { | ||
this.socket.send(buf, 0, buf.length, this.port, this.host, callback); | ||
} | ||
} catch (err) { | ||
var errMessage = 'Error sending hot-shots message: ' + err; | ||
if (callback) { | ||
callback(new Error(errMessage)); | ||
} | ||
else if (this.errorHandler) { | ||
} else if (this.errorHandler) { | ||
this.errorHandler(new Error(errMessage)); | ||
} | ||
else { | ||
} else { | ||
console.log(errMessage); | ||
@@ -350,3 +386,3 @@ } | ||
*/ | ||
Client.prototype.onBufferFlushInterval = function() { | ||
Client.prototype.onBufferFlushInterval = function () { | ||
this.flushQueue(); | ||
@@ -358,4 +394,4 @@ }; | ||
*/ | ||
Client.prototype.close = function(callback){ | ||
if(this.intervalHandle) { | ||
Client.prototype.close = function (callback) { | ||
if (this.intervalHandle) { | ||
clearInterval(this.intervalHandle); | ||
@@ -373,13 +409,14 @@ } | ||
try { | ||
this.socket.close(); | ||
} | ||
catch (err) { | ||
if (this.protocol === 'tcp') { | ||
this.socket.destroy(); | ||
} else { | ||
this.socket.close(); | ||
} | ||
} catch (err) { | ||
var errMessage = 'Error closing hot-shots socket: ' + err; | ||
if (callback) { | ||
callback(new Error(errMessage)); | ||
} | ||
else if (this.errorHandler) { | ||
} else if (this.errorHandler) { | ||
this.errorHandler(new Error(errMessage)); | ||
} | ||
else { | ||
} else { | ||
console.log(errMessage); | ||
@@ -399,3 +436,2 @@ } | ||
errorHandler: options.errorHandler || parent.errorHandler, // Handler for callback errors | ||
host : parent.host, | ||
@@ -405,10 +441,11 @@ port : parent.port, | ||
suffix : parent.suffix + (options.suffix || ''), // Child has its suffix appended to parent's suffix | ||
globalize : false, // Only "root" client can be global | ||
globalize : false, // Only 'root' client can be global | ||
mock : parent.mock, | ||
// Append child's tags to parent's tags | ||
globalTags : typeof options.globalTags === "object" ? | ||
globalTags : typeof options.globalTags === 'object' ? | ||
helpers.overrideTags(parent.globalTags, options.globalTags, parent.telegraf) : parent.globalTags, | ||
maxBufferSize : parent.maxBufferSize, | ||
bufferFlushInterval: parent.bufferFlushInterval, | ||
telegraf : parent.telegraf | ||
telegraf : parent.telegraf, | ||
protocol : parent.protocol | ||
}); | ||
@@ -425,3 +462,3 @@ }; | ||
*/ | ||
Client.prototype.childClient = function(options) { | ||
Client.prototype.childClient = function (options) { | ||
return new ChildClient(this, options); | ||
@@ -428,0 +465,0 @@ }; |
{ | ||
"name": "hot-shots", | ||
"description": "Node.js client for StatsD, DogStatsD, and Telegraf", | ||
"version": "5.7.0", | ||
"version": "5.8.0", | ||
"author": "Steve Ivy", | ||
@@ -34,3 +34,3 @@ "types": "./types.d.ts", | ||
"coverage": "nyc --reporter=lcov npm test", | ||
"test": "mocha -R spec", | ||
"test": "mocha -R spec --timeout 5000 test/index.js", | ||
"lint": "jshint lib/**.js test/**.js", | ||
@@ -37,0 +37,0 @@ "pretest": "npm run lint" |
@@ -40,2 +40,3 @@ # hot-shots | ||
* `useDefaultRoute`: Use the default interface on a Linux system. Useful when running in containers | ||
* `protocol`: Use `tcp` option for TCP protocol. Defaults to UDP otherwise | ||
@@ -42,0 +43,0 @@ All StatsD methods other than event and close have the same API: |
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
Network access
Supply chain riskThis module accesses the network.
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
52975
835
230
3