Skip to content
This repository was archived by the owner on Sep 19, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions lib/statsd.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ var dgram = require('dgram'),
* @option cacheDns {boolean} An optional option to only lookup the hostname -> ip address once
* @option mock {boolean} An optional boolean indicating this Client is a mock object, no stats are sent.
* @option global_tags {Array=} Optional tags that will be added to every metric
* @option sampleRate {Float} Global Sampling rate, default: 1 (No sampling)
* @constructor
*/
var Client = function (host, port, prefix, suffix, globalize, cacheDns, mock, global_tags) {
var Client = function (host, port, prefix, suffix, globalize, cacheDns, mock, global_tags, sampleRate) {
var options = host || {},
self = this;

Expand All @@ -27,7 +28,8 @@ var Client = function (host, port, prefix, suffix, globalize, cacheDns, mock, gl
globalize : globalize,
cacheDns : cacheDns,
mock : mock === true,
global_tags : global_tags
global_tags : global_tags,
sampleRate : sampleRate
};
}

Expand All @@ -38,6 +40,7 @@ var Client = function (host, port, prefix, suffix, globalize, cacheDns, mock, gl
this.socket = dgram.createSocket('udp4');
this.mock = options.mock;
this.global_tags = options.global_tags || [];
this.sampleRate = options.sampleRate || 1;

if(options.cacheDns === true){
dns.lookup(options.host, function(err, address, family){
Expand Down Expand Up @@ -196,6 +199,7 @@ Client.prototype.send = function (stat, value, type, sampleRate, tags, callback)
buf,
merged_tags = [];

sampleRate = sampleRate || this.sampleRate;
if(sampleRate && sampleRate < 1){
if(Math.random() < sampleRate){
message += '|@' + sampleRate;
Expand Down Expand Up @@ -231,7 +235,7 @@ Client.prototype.send = function (stat, value, type, sampleRate, tags, callback)
*/
Client.prototype.close = function(){
this.socket.close();
}
};

exports = module.exports = Client;
exports.StatsD = Client;
74 changes: 72 additions & 2 deletions test/test_statsd.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,21 @@ describe('StatsD', function(){
assert.equal(global.statsd, undefined);
assert.equal(statsd.mock, undefined);
assert.deepEqual(statsd.global_tags, []);
assert.deepEqual(statsd.sampleRate, 1);
assert.ok(!statsd.mock);
});

it('should set the proper values when specified', function(){
// cachedDns isn't tested here; see below
var statsd = new StatsD('host', 1234, 'prefix', 'suffix', true, null, true, ['gtag']);
var statsd = new StatsD('host', 1234, 'prefix', 'suffix', true, null, true, ['gtag'], 0.6);
assert.equal(statsd.host, 'host');
assert.equal(statsd.port, 1234);
assert.equal(statsd.prefix, 'prefix');
assert.equal(statsd.suffix, 'suffix');
assert.equal(statsd, global.statsd);
assert.equal(statsd.mock, true);
assert.deepEqual(statsd.global_tags, ['gtag']);
assert.deepEqual(statsd.sampleRate, 0.6);
});

it('should set the proper values with options hash format', function(){
Expand All @@ -108,7 +110,8 @@ describe('StatsD', function(){
suffix: 'suffix',
globalize: true,
mock: true,
global_tags: ['gtag']
global_tags: ['gtag'],
sampleRate: 0.6
});
assert.equal(statsd.host, 'host');
assert.equal(statsd.port, 1234);
Expand All @@ -117,6 +120,7 @@ describe('StatsD', function(){
assert.equal(statsd, global.statsd);
assert.equal(statsd.mock, true);
assert.deepEqual(statsd.global_tags, ['gtag']);
assert.deepEqual(statsd.sampleRate, 0.6);
});

it('should attempt to cache a dns record if dnsCache is specified', function(done){
Expand Down Expand Up @@ -229,6 +233,72 @@ describe('StatsD', function(){
});
});

describe('#global_sample_rate', function(){
it('should not sample if it is not specified', function(finished){
udpTest(function(message, server){
assert.equal(message, 'test:1|c');
server.close();
finished();
}, function(server){
var address = server.address(),
statsd = new StatsD(address.address, address.port);

statsd.increment('test');
});
});

it('should sample if global sample rate is specified', function(finished){
var called = false;
udpTest(function(message, server){
assert.equal(message, 'foo.test.bar:42|c|@0.6');
assert.equal(called, true);
server.close();
finished();
}, function(server){
var address = server.address(),
statsd = new StatsD(address.address, address.port, 'foo.', '.bar', true, false, false, [], 0.6);

statsd.increment('test', 42, function(){
called = true;
});
});
});

it('should sample if metric sample rate is specified', function(finished){
var called = false;
udpTest(function(message, server){
assert.equal(message, 'foo.test.bar:42|c|@0.5');
assert.equal(called, true);
server.close();
finished();
}, function(server){
var address = server.address(),
statsd = new StatsD(address.address, address.port, 'foo.', '.bar');

statsd.increment('test', 42, 0.5, function(){
called = true;
});
});
});

it('should honor metric sampleRate if both global and metric sample rate is specified', function(finished){
var called = false;
udpTest(function(message, server){
assert.equal(message, 'foo.test.bar:42|c|@0.5');
assert.equal(called, true);
server.close();
finished();
}, function(server){
var address = server.address(),
statsd = new StatsD(address.address, address.port, 'foo.', '.bar', true, false, false, [], 0.6);

statsd.increment('test', 42, 0.5, function(){
called = true;
});
});
});
});

describe('#timing', function(finished){
it('should send proper time format without prefix, suffix, sampling and callback', function(finished){
udpTest(function(message, server){
Expand Down