Skip to content

Commit aebf93c

Browse files
authored
Merge pull request #6 from statful/sampleRate
feat: add sampleRate
2 parents f3e52e9 + 7b2ffce commit aebf93c

File tree

9 files changed

+112
-28
lines changed

9 files changed

+112
-28
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ The custom options that can be set on config param are detailed below.
6868
| debug | Defines logs should be sent to console. | `boolean` | `false` | **NO** |
6969
| app | Defines the application global name. If specified sets a global tag `app=setValue`. | `string` | **undefined** | **NO** |
7070
| namespace | Defines the global namespace. | `string` | `web` | **NO** |
71+
| sampleRate | Defines the rate sampling. **Should be a number between [1, 100]**. | `number` | `100` | **NO** |
7172
| flushInterval | Defines the periodicity of buffer flushes in **miliseconds**. | `number` | `10000` | **NO** |
7273
| timeout | Defines the timeout. | `number` | `2000` | **NO** |
7374
| tags | Defines the global tags. | `object` | `{}` | **NO** |

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "statful-client-javascript",
3-
"version": "1.1.5",
3+
"version": "1.1.6",
44
"description": "Statful client for Javascript applications",
55
"main": "dist/statful.js",
66
"authors": [

dist/statful.js

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* statful-client-javascript 1.1.5
2+
* statful-client-javascript 1.1.6
33
* Copyright 2016 Statful <https://www.statful.com/>
44
*/
55
(function(window) {
@@ -128,8 +128,13 @@
128128
* @param {object} item - object to be sent
129129
*/
130130
this.addItemToQueue = function(queueName, item) {
131-
if (this.listQueues[queueName]) {
131+
var sampleRateNormalized = (item.sampleRate || this.config.sampleRate || 100) / 100;
132+
if (this.listQueues[queueName] && Math.random() <= sampleRateNormalized) {
132133
this.listQueues[queueName].data.push(item);
134+
return true;
135+
} else {
136+
logger.debug("Metric was discarded due to sample rate.");
137+
return false;
133138
}
134139
};
135140
/**
@@ -262,7 +267,8 @@
262267
aggregations: [ "last" ]
263268
},
264269
timeout: 2e3,
265-
flushInterval: 1e4
270+
flushInterval: 1e4,
271+
sampleRate: 100
266272
};
267273
var logger;
268274
var statful = {
@@ -291,15 +297,16 @@
291297
self.config[key] = clientConfig[key];
292298
});
293299
};
294-
self.metricsData = function(name, type, value, tags, aggregations, aggregationFrequency, namespace) {
300+
self.metricsData = function(name, type, value, tags, aggregations, aggregationFrequency, namespace, sampleRate) {
295301
return {
296302
name: name,
297303
type: type,
298304
value: value,
299305
tags: self.util.setTags(tags || {}, self.config.tags, self.config[type].tags, self.config.app),
300306
aggregations: self.util.setAggregations(aggregations, self.config.aggregations, self.config[type].aggregations),
301307
aggregationFrequency: self.util.setAggregationFrequency(aggregationFrequency, self.config.aggregationFrequency, self.config[type].aggregationFrequency),
302-
namespace: namespace || self.config.namespace
308+
namespace: namespace || self.config.namespace,
309+
sampleRate: sampleRate || self.config.sampleRate
303310
};
304311
};
305312
this.mergeConfigs(clientConfig);
@@ -424,7 +431,7 @@
424431
var time = this.measureTimeUserTiming(measureName);
425432
if (time) {
426433
// Push metrics to queue
427-
this.util.addItemToQueue("metrics", new this.metricsData(metricName, "timer", time, defaults.tags, defaults.aggregations, defaults.aggregationFrequency));
434+
this.util.addItemToQueue("metrics", new this.metricsData(metricName, "timer", time, defaults.tags, defaults.aggregations, defaults.aggregationFrequency, defaults.namespace, defaults.sampleRate));
428435
} else {
429436
logger.error("Failed to get measure time to register as timer value");
430437
}
@@ -453,7 +460,7 @@
453460
if (metricName && metricValue) {
454461
options = options || {};
455462
// Push metrics to queue
456-
var item = new this.metricsData(metricName, "timer", metricValue, options.tags, options.agg, options.aggFreq, options.namespace);
463+
var item = new this.metricsData(metricName, "timer", metricValue, options.tags, options.agg, options.aggFreq, options.namespace, options.sampleRate);
457464
this.util.addItemToQueue("metrics", item);
458465
} else {
459466
logger.error("Undefined metric name/value to register as a timer");
@@ -475,7 +482,7 @@
475482
if (metricName) {
476483
options = options || {};
477484
// Push metrics to queue
478-
var item = new this.metricsData(metricName, "counter", metricValue, options.tags, options.agg, options.aggFreq, options.namespace);
485+
var item = new this.metricsData(metricName, "counter", metricValue, options.tags, options.agg, options.aggFreq, options.namespace, options.sampleRate);
479486
this.util.addItemToQueue("metrics", item);
480487
} else {
481488
logger.error("Undefined metric name to register as a counter");
@@ -496,7 +503,7 @@
496503
if (metricName && metricValue) {
497504
options = options || {};
498505
// Push metrics to queue
499-
var item = new this.metricsData(metricName, "gauge", metricValue, options.tags, options.agg, options.aggFreq, options.namespace);
506+
var item = new this.metricsData(metricName, "gauge", metricValue, options.tags, options.agg, options.aggFreq, options.namespace, options.sampleRate);
500507
this.util.addItemToQueue("metrics", item);
501508
} else {
502509
logger.error("Undefined metric name/value to register as a gauge");

dist/statful.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "statful-client-javascript",
3-
"version": "1.1.5",
3+
"version": "1.1.6",
44
"description": "Statful client for Javascript applications",
55
"banner": "/**\n* <%= pkg.name %> <%= pkg.version %>\n* Copyright 2016 Statful <https://www.statful.com/>\n*/\n",
66
"scripts": {

src/statful-util.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,14 @@
121121
* @param {object} item - object to be sent
122122
*/
123123
this.addItemToQueue = function (queueName, item) {
124-
if (this.listQueues[queueName]) {
124+
var sampleRateNormalized = (item.sampleRate || this.config.sampleRate || 100) / 100;
125+
126+
if (this.listQueues[queueName] && Math.random() <= sampleRateNormalized) {
125127
this.listQueues[queueName].data.push(item);
128+
return true;
129+
} else {
130+
logger.debug('Metric was discarded due to sample rate.');
131+
return false;
126132
}
127133
};
128134

src/statful.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
aggregations: ['last']
4141
},
4242
timeout: 2000,
43-
flushInterval: 10000
43+
flushInterval: 10000,
44+
sampleRate: 100
4445
};
4546

4647
var logger;
@@ -76,15 +77,16 @@
7677
});
7778
};
7879

79-
self.metricsData = function (name, type, value, tags, aggregations, aggregationFrequency, namespace) {
80+
self.metricsData = function (name, type, value, tags, aggregations, aggregationFrequency, namespace, sampleRate) {
8081
return {
8182
name: name,
8283
type: type,
8384
value: value,
8485
tags: self.util.setTags(tags || {}, self.config.tags, self.config[type].tags, self.config.app),
8586
aggregations: self.util.setAggregations(aggregations, self.config.aggregations, self.config[type].aggregations),
8687
aggregationFrequency: self.util.setAggregationFrequency(aggregationFrequency, self.config.aggregationFrequency, self.config[type].aggregationFrequency),
87-
namespace: namespace || self.config.namespace
88+
namespace: namespace || self.config.namespace,
89+
sampleRate: sampleRate || self.config.sampleRate
8890
};
8991
};
9092

@@ -229,7 +231,7 @@
229231
if (time) {
230232
// Push metrics to queue
231233
this.util.addItemToQueue('metrics', new this.metricsData(metricName, 'timer', time,
232-
defaults.tags, defaults.aggregations, defaults.aggregationFrequency));
234+
defaults.tags, defaults.aggregations, defaults.aggregationFrequency, defaults.namespace, defaults.sampleRate));
233235
} else {
234236
logger.error('Failed to get measure time to register as timer value');
235237
}
@@ -262,7 +264,7 @@
262264
options = options || {};
263265

264266
// Push metrics to queue
265-
var item = new this.metricsData(metricName, 'timer', metricValue, options.tags, options.agg, options.aggFreq, options.namespace);
267+
var item = new this.metricsData(metricName, 'timer', metricValue, options.tags, options.agg, options.aggFreq, options.namespace, options.sampleRate);
266268
this.util.addItemToQueue('metrics', item);
267269
} else {
268270
logger.error('Undefined metric name/value to register as a timer');
@@ -287,7 +289,7 @@
287289
options = options || {};
288290

289291
// Push metrics to queue
290-
var item = new this.metricsData(metricName, 'counter', metricValue, options.tags, options.agg, options.aggFreq, options.namespace);
292+
var item = new this.metricsData(metricName, 'counter', metricValue, options.tags, options.agg, options.aggFreq, options.namespace, options.sampleRate);
291293
this.util.addItemToQueue('metrics', item);
292294
} else {
293295
logger.error('Undefined metric name to register as a counter');
@@ -310,7 +312,7 @@
310312
options = options || {};
311313

312314
// Push metrics to queue
313-
var item = new this.metricsData(metricName, 'gauge', metricValue, options.tags, options.agg, options.aggFreq, options.namespace);
315+
var item = new this.metricsData(metricName, 'gauge', metricValue, options.tags, options.agg, options.aggFreq, options.namespace, options.sampleRate);
314316
this.util.addItemToQueue('metrics', item);
315317
} else {
316318
logger.error('Undefined metric name/value to register as a gauge');

tests/statful-util.tests.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ describe('Statful Util Unit testing', function () {
44
beforeEach(function () {
55
statfulUtil= new StatfulUtil({
66
apiAddress: '//beacon.statful.com',
7-
flushInterval: 30000
7+
flushInterval: 30000,
8+
sampleRate: 100
89
});
910
});
1011

@@ -124,4 +125,33 @@ describe('Statful Util Unit testing', function () {
124125
expect(statfulUtil.listQueues.length).toEqual(0);
125126
});
126127

128+
it('should not add items to queue (sample rate)', function () {
129+
expect(statfulUtil.listQueues.length).toEqual(0);
130+
131+
expect(statfulUtil.registerQueue('metrics', 'endpoint', 5000)).toEqual(true);
132+
133+
spyOn(Math, 'random').and.returnValue(0.5);
134+
135+
expect(statfulUtil.addItemToQueue('metrics', {
136+
name: 'test',
137+
type: 'counter',
138+
value: 1,
139+
sampleRate: 40
140+
})).toBeFalsy();
141+
});
142+
143+
it('should add items to queue (sample rate)', function () {
144+
expect(statfulUtil.listQueues.length).toEqual(0);
145+
146+
expect(statfulUtil.registerQueue('metrics', 'endpoint', 5000)).toEqual(true);
147+
148+
spyOn(Math, 'random').and.returnValue(0.5);
149+
150+
expect(statfulUtil.addItemToQueue('metrics', {
151+
name: 'test',
152+
type: 'counter',
153+
value: 1,
154+
sampleRate: 60
155+
})).toBeTruthy();
156+
});
127157
});

tests/statful.tests.js

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ describe('Statful Client Unit testing', function () {
6161
tags: {mark: 'gauge', meh: 'yep'},
6262
aggregations: ['last'],
6363
aggregationFrequency: 300,
64-
namespace: 'web'
64+
namespace: 'web',
65+
sampleRate: 100
6566
});
6667
});
6768

@@ -91,7 +92,40 @@ describe('Statful Client Unit testing', function () {
9192
tags: {mark: 'gauge', meh: 'yep'},
9293
aggregations: ['last'],
9394
aggregationFrequency: 60,
94-
namespace: 'web'
95+
namespace: 'web',
96+
sampleRate: 100
97+
});
98+
});
99+
100+
it('should override sample rate by type over global', function() {
101+
statful.initialize({
102+
tags: {},
103+
aggregations: ['last'],
104+
timer: {tags: {foo: 'bar'}},
105+
gauge: {tags: {meh: 'yep'}, aggregations: [], aggregationFrequency: 60}
106+
});
107+
108+
var util = statful.util;
109+
110+
spyOn(util, 'addItemToQueue');
111+
112+
var options = {
113+
tags: {mark: 'gauge'},
114+
agg: [],
115+
sampleRate: 50
116+
};
117+
118+
statful.gauge('test', 1234, options);
119+
120+
expect(util.addItemToQueue).toHaveBeenCalledWith('metrics', {
121+
name: 'test',
122+
type: 'gauge',
123+
value: 1234,
124+
tags: {mark: 'gauge', meh: 'yep'},
125+
aggregations: ['last'],
126+
aggregationFrequency: 60,
127+
namespace: 'web',
128+
sampleRate: 50
95129
});
96130
});
97131

@@ -122,7 +156,8 @@ describe('Statful Client Unit testing', function () {
122156
tags: {mark: 'gauge', meh: 'yep'},
123157
aggregations: ['last'],
124158
aggregationFrequency: 300,
125-
namespace: 'web'
159+
namespace: 'web',
160+
sampleRate: 100
126161
});
127162
});
128163

@@ -151,7 +186,8 @@ describe('Statful Client Unit testing', function () {
151186
tags: {mark: 'gauge', meh: 'yep'},
152187
aggregations: [],
153188
aggregationFrequency: 10,
154-
namespace: 'web'
189+
namespace: 'web',
190+
sampleRate: 100
155191
});
156192
});
157193

@@ -301,7 +337,8 @@ describe('Statful Client Unit testing', function () {
301337
tags: {mark: 'measure', unit: 'ms'},
302338
aggregations: ['avg', 'p90', 'count'],
303339
aggregationFrequency: 10,
304-
namespace: 'web'
340+
namespace: 'web',
341+
sampleRate: 100
305342
});
306343
});
307344

@@ -398,7 +435,8 @@ describe('Statful Client Unit testing', function () {
398435
tags: {mark: 'gauge'},
399436
aggregations: ['last'],
400437
aggregationFrequency: 30,
401-
namespace: 'web'
438+
namespace: 'web',
439+
sampleRate: 100
402440
});
403441
});
404442
});

0 commit comments

Comments
 (0)