From 0a0aaa897ee2746ebed44bc1af5c2b5200e63893 Mon Sep 17 00:00:00 2001 From: Lars Larsson Date: Thu, 15 Sep 2016 10:55:05 +0200 Subject: [PATCH 1/2] Params are now passed as an object. Also implemented better debugging --- lib/statsd.js | 44 ++++++++++++++++++++++---------------------- test/statsd_test.js | 38 +++++++++++++++++++++++++------------- 2 files changed, 47 insertions(+), 35 deletions(-) diff --git a/lib/statsd.js b/lib/statsd.js index dbaffaf..90d30bf 100644 --- a/lib/statsd.js +++ b/lib/statsd.js @@ -6,20 +6,22 @@ var mt = new mersenne.MersenneTwister19937(); var EPHEMERAL_LIFETIME_MS = 1000; -var Client = function(host, port, socket, options) { - this.host = host || "localhost"; - this.port = port || 8125; +var Client = function(params) { + params = !!params ? params : {}; + this.host = params.host || "localhost"; + this.port = params.port || 8125; + this.errorHandler = params.errorHandler || function() {}; // optional shared socket - this.socket = socket; + this.socket = params.socket; // when a *shared* socked isn't provided, an ephemeral // socket is demand allocated. This ephemeral socket is closed // after being idle for EPHEMERAL_LIFETIME_MS. this.ephemeral_socket = this.last_used_timer = null; - options = options || {}; - this.global_tags = options.global_tags; + params.options = params.options || {}; + this.global_tags = params.options.global_tags; }; Client.prototype.timing = function(stat, time, sample_rate, tags) { @@ -42,7 +44,7 @@ Client.prototype.incrementBy = function(stats, value, tags) { Client.prototype.decrement = function(stats, sample_rate, tags) { var self = this; - self.update_stats(stats, - 1, sample_rate, tags); + self.update_stats(stats, -1, sample_rate, tags); }; Client.prototype.decrementBy = function(stats, value, tags) { @@ -89,7 +91,7 @@ Client.prototype.update_stats = function(stats, delta, sampleRate, tags) { // used. This function is called when the socket is used // and causes demand allocated ephemeral sockets to be closed // after a period of inactivity. -Client.prototype._update_last_used = function () { +Client.prototype._update_last_used = function() { if (!this.ephemeral_socket) return; @@ -104,17 +106,16 @@ Client.prototype._update_last_used = function () { }, EPHEMERAL_LIFETIME_MS); }; -Client.prototype.send_data = function (buf) { +Client.prototype.send_data = function(buf) { var socket; if (!this.socket) { if (!this.ephemeral_socket) { this.ephemeral_socket = dgram.createSocket("udp4"); - this.ephemeral_socket.on("error", function() {}); + this.ephemeral_socket.on("error", this.errorHandler); } socket = this.ephemeral_socket; - } - else { + } else { socket = this.socket; } @@ -141,24 +142,23 @@ Client.prototype.send = function(data, sample_rate, tags) { sampled_data[stat] = value + "|@" + sample_rate; } } - } - else + } else sampled_data = data; if (this.global_tags || tags) { var merged_tags = []; if (Array.isArray(this.global_tags)) - merged_tags = merged_tags.concat(this.global_tags); - + merged_tags = merged_tags.concat(this.global_tags); if (Array.isArray(tags)) - merged_tags = merged_tags.concat(tags); + merged_tags = merged_tags.concat(tags); if (merged_tags.length > 0) { - var merged_tags_str = merged_tags.join(','); - for (stat in sampled_data) - sampled_data[stat] = sampled_data[stat] + "|#" + merged_tags_str; + var merged_tags_str = merged_tags.join(','); + for (stat in sampled_data) + sampled_data[stat] = sampled_data[stat] + "|#" + + merged_tags_str; } } @@ -177,8 +177,8 @@ Client.prototype.close = function() { clearTimeout(this.last_used_timer); this.ephemeral_socket = - this.last_used_timer = - this.socket = null; + this.last_used_timer = + this.socket = null; }; exports.StatsD = Client; diff --git a/test/statsd_test.js b/test/statsd_test.js index 9f6f252..2773ad5 100644 --- a/test/statsd_test.js +++ b/test/statsd_test.js @@ -15,7 +15,12 @@ describe('StatsD', function() { beforeEach(function(done) { fakeStatsDServerSocket = dgram.createSocket('udp4'); fakeStatsDServerSocket.bind(function() { - client = new StatsD('localhost', fakeStatsDServerSocket.address().port); + client = new StatsD({ + host: 'localhost', + port: fakeStatsDServerSocket + .address() + .port + }); done(); }); }); @@ -24,18 +29,22 @@ describe('StatsD', function() { fakeStatsDServerSocket.close(); }); - // Wraps up listening for the next message on our fake server and - // verifying that it's contents match those expected. Calls back - // once this check has been performed. + // Wraps up listening for the next message on our fake server and verifying + // that it's contents match those expected. Calls back once this check has been + // performed. var serverShouldReceive = function(expected, cb) { - fakeStatsDServerSocket.once('message', function(msg) { - try { - msg.toString('utf8').should.eql(expected); - } catch (e) { - return cb(e); - } - cb(); - }); + fakeStatsDServerSocket + .once('message', function(msg) { + try { + msg + .toString('utf8') + .should + .eql(expected); + } catch (e) { + return cb(e); + } + cb(); + }); }; var serverShouldReceiveMultiple = function(expected, n, cb) { @@ -43,7 +52,10 @@ describe('StatsD', function() { fakeStatsDServerSocket.on('message', function(msg) { remaining--; try { - msg.toString('utf8').should.eql(expected); + msg + .toString('utf8') + .should + .eql(expected); } catch (e) { return cb(e); } From 3507b494bf48d1dd7b710de6f6b3697f527c8b1f Mon Sep 17 00:00:00 2001 From: Lars Larsson Date: Thu, 15 Sep 2016 11:07:29 +0200 Subject: [PATCH 2/2] Updated README --- README.md | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index d19731c..16705cd 100644 --- a/README.md +++ b/README.md @@ -2,26 +2,26 @@ A node.js client for extended StatsD server of [Datadog](http://www.datadoghq.com). -Datadog added new some features(histogram and tags) to their own StatsD implementation. -This client is an extension of general StatsD client to work with that server. +Datadog added new some features(histogram and tags) to their own StatsD implementation. This client is an extension of general StatsD client to work with that server. -Most parts of codes came from [Steve Ivy](https://github.com/sivy)'s [node-statsd](https://github.com/sivy/node-statsd). -I just added few lines to support datadog's histogram and tags features. +Most parts of codes came from [Steve Ivy](https://github.com/sivy)'s [node-statsd](https://github.com/sivy/node-statsd). I just added few lines to support datadog's histogram and tags features. The name of the package is changed because this isn't really statsd client and should be able to be used with original statsd client. - % npm install node-dogstatsd - % node - > var StatsD = require('node-dogstatsd').StatsD - > c = new StatsD('example.org',8125) - { host: 'example.org', port: 8125 } - > c.increment('node_test.int') - > c.incrementBy('node_test.int', 7) - > c.decrement('node_test.int') - > c.decrementBy('node_test.int', 12) - > c.timing('node_test.some_service.task.time', 500) // time in millis - > c.histogram('node_test.some_service.data', 100) // works only with datadog' StatsD - > c.increment('node_test.int', 1, ['tag:one']) // works only with datadog' StatsD +``` +% npm install node-dogstatsd +% node +> var StatsD = require('node-dogstatsd').StatsD +> c = new StatsD({host:'example.org',port:8125}) +{ host: 'example.org', port: 8125 } +> c.increment('node_test.int') +> c.incrementBy('node_test.int', 7) +> c.decrement('node_test.int') +> c.decrementBy('node_test.int', 12) +> c.timing('node_test.some_service.task.time', 500) // time in millis +> c.histogram('node_test.some_service.data', 100) // works only with datadog' StatsD +> c.increment('node_test.int', 1, ['tag:one']) // works only with datadog' StatsD +``` ## License @@ -29,13 +29,14 @@ node-statsd is licensed under the MIT license. ## Error handling policy -* exceptions "bubble up" into the app that uses this library -* we don't log or print to console any errors ourself, it's the toplevel app that decides how to log/write to console. -* we document which exceptions can be raised, and where. (TODO, https://github.com/sivy/node-statsd/issues/17) +- exceptions "bubble up" into the app that uses this library +- we don't log or print to console any errors ourself, it's the toplevel app that decides how to log/write to console. +- we document which exceptions can be raised, and where. (TODO, ) -in your main app, you can leverage the fact that you have access to c.socket and do something like: -(this is the best way I've found so far) +in your main app, you can leverage the fact that you have access to c.socket and do something like: (this is the best way I've found so far) - c.socket.on('error', function (exception) { - return console.log ("error event in socket.send(): " + exception); - }); +``` +c.socket.on('error', function (exception) { + return console.log ("error event in socket.send(): " + exception); +}); +```