Skip to content

Commit

Permalink
Support hrtime (nanoseconds accuracy) (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
omrilotan authored Aug 5, 2019
1 parent 397db15 commit f898837
Show file tree
Hide file tree
Showing 30 changed files with 1,261 additions and 1,255 deletions.
4 changes: 2 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
indent_style = tab
tab_width = 2
indent_style = space
tab_width = 4

[*.yml]
indent_size = 2
Expand Down
7 changes: 7 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": [
"@fiverr/eslint-config-fiverr/rules/base",
"@fiverr/eslint-config-fiverr/rules/es6",
"@fiverr/eslint-config-fiverr/rules/mocha"
]
}
45 changes: 0 additions & 45 deletions .eslintrc.js

This file was deleted.

12 changes: 6 additions & 6 deletions .mocha.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ chai.use(require('chai-string'));
const wait = require('@lets/wait');

Object.assign(
global,
chai,
{
wait,
}
global,
chai,
{
wait
}
);

process.on('unhandledRejection', error => { throw error; });
process.on('unhandledRejection', (error) => { throw error; });
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,13 @@ Exposes a client with the functions: `count`, `time`, `gauge`, `set`, `histogram
| Argument | Type | Default | Meaning
| - | - | - | -
| metric | String | [Mandatory] | The metric name (key)
| value | Number|Date | 1 | The value to report (A date instance will send the time diff)
| value | Number|Date|BigInt | 1 | The value to report
| options.rate | Number | - | Sample rate - a fraction of 1 (.01 is one percent)
| options.tags | Object | - | Key-value pairs of tags set as object literal

> † If `value` if a Date - instance will send the time diff (`Date.now()`)
> † If `value` if a BigInt - instance will send the time diff (`process.hrtime.bigint()`) **in milliseconds** with nanoseconds accuracy
#### Count
```js
stats.count('some.counter'); // Increment by one.
Expand All @@ -82,7 +85,16 @@ stats.count('some.counter', 10); // Increment by ten.
#### Time
```js
stats.time('some.timer', 200); // Send time value in milliseconds
stats.time('some.timer', date); // If you send a date instance - it'll report the time diff

// Send date
const start = new Date();
...
stats.time('some.timer', start); // instance will send the time diff (`Date.now()`)

// Send high resolution time
const start = process.hrtime.bigint();
...
stats.time('some.timer', start); // instance will send the time diff (`process.hrtime.bigint()`) in milliseconds with nanoseconds accuracy
```

#### Gauge
Expand Down
206 changes: 104 additions & 102 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ const push = require('./lib/push');
const sender = require('./lib/sender');
const spread = require('./lib/spread');
const types = require('./lib/types');

const TYPES_LIST = Object.keys(types);
const TYPES = Object.freeze(
TYPES_LIST.reduce(
(accumulator, type) => Object.assign(
accumulator,
{[type]: type}
),
{}
)
TYPES_LIST.reduce(
(accumulator, type) => Object.assign(
accumulator,
{[type]: type}
),
{}
)
);

/**
Expand All @@ -36,7 +37,7 @@ const TYPES = Object.freeze(
* @property {Function} histogram
*/
class SDC {
/**
/**
* @static
* @getter
* @type {Object}
Expand All @@ -46,11 +47,11 @@ class SDC {
* @property {String} set 'set'
* @property {String} histogram 'histogram'
*/
static get TYPES() {
return TYPES;
}
static get TYPES() {
return TYPES;
}

/**
/**
* SDC constructor
* @param {String} [options.host='127.0.0.1']
* @param {String} [options.port=8125]
Expand All @@ -65,52 +66,52 @@ class SDC {
* @param {Function} [options.errorHandler]
* @param {Boolean} [options.enforceRate=true]
*/
constructor(
{
host = '127.0.0.1',
port = 8125,
protocol = 'UDP',
protocol_version = 'ipv4',
MTU = 576,
timeout = 1000,
tags,
scheme,
prefix,
sanitise,
errorHandler,
enforceRate = true,
} = {}
) {
Object.assign(
this,
{
MTU, // Maximum Transmission Unit
timeout,
tags,
errorHandler,
enforceRate,
bulk: [],
timer: null,
send: sender({host, port, protocol, protocol_version, errorHandler, timeout}),
format: formatter({sanitise, prefix, scheme}),
flush: flush.bind(this),
}
);
constructor(
{
host = '127.0.0.1',
port = 8125,
protocol = 'UDP',
protocol_version = 'ipv4',
MTU = 576,
timeout = 1000,
tags,
scheme,
prefix,
sanitise,
errorHandler,
enforceRate = true
} = {}
) {
Object.assign(
this,
{
MTU, // Maximum Transmission Unit
timeout,
tags,
errorHandler,
enforceRate,
bulk: [],
timer: null,
send: sender({host, port, protocol, protocol_version, errorHandler, timeout}),
format: formatter({sanitise, prefix, scheme}),
flush: flush.bind(this)
}
);

[...TYPES_LIST, 'generic'].forEach(fn => {
this[fn] = this[fn].bind(this);
});
}
[...TYPES_LIST, 'generic'].forEach((fn) => {
this[fn] = this[fn].bind(this);
});
}

/**
/**
* The size of current bulk
* @return {Number}
*/
get size() {
return this.bulk.join('\n').length;
}
get size() {
return this.bulk.join('\n').length;
}

/**
/**
* Generic metric send method
* @param {String} type Metric type
* @param {String} key The metric name (key)
Expand All @@ -119,69 +120,70 @@ class SDC {
* @param {Object} [options.tags] Key-value pairs of tags set as object literal
* @return {Number} current size of the bulk
*/
generic(...args) {
let [
type,
key,
value = 1,
rate,
tags,
] = spread(args);
generic(...args) {
let [
type, // eslint-disable-line prefer-const
key, // eslint-disable-line prefer-const
value = 1, // eslint-disable-line prefer-const
rate, // eslint-disable-line prefer-const
tags
] = spread(args);

if (rate) {
if (typeof rate !== 'number') {
throw new TypeError(`Expected 'rate' to be a number, instead got a ${typeof rate}`);
}
if (rate > 1) {
throw new TypeError(`Expected 'rate' to be a number between 0 and 1, instead got ${rate}`);
}
if (rate) {
if (typeof rate !== 'number') {
throw new TypeError(`Expected 'rate' to be a number, instead got a ${typeof rate}`);
}
if (rate > 1) {
throw new TypeError(`Expected 'rate' to be a number between 0 and 1, instead got ${rate}`);
}

if (this.enforceRate && !sample(rate)) {
return this.size;
}
}
if (this.enforceRate && !sample(rate)) {
return this.size;
}
}

if (this.tags) {
tags = Object.assign({}, this.tags, tags || {});
}
return push.call(
this,
this.format(
type,
key,
value,
{ rate, tags }
)
);
}
if (this.tags) {
tags = Object.assign({}, this.tags, tags || {});
}
return push.call(
this,
this.format(
type,
key,
value,
{ rate, tags }
)
);
}
}

Object.defineProperties(
SDC.prototype,
TYPES_LIST.reduce(
(accumulator, type) => Object.assign(
accumulator,
{
[type]: {
/**
SDC.prototype,
TYPES_LIST.reduce(
(accumulator, type) => Object.assign(
accumulator,
{
[type]: {

/**
* Specific metric type send method
* @param {String} key The metric name (key)
* @param {Number} [value] The value to report
* @param {Number} [options.rate] Sample rate - a fraction of 1 (.01 is one percent)
* @param {Object} [options.tags] Key-value pairs of tags set as object literal
* @return {Number} current size of the bulk
*/
value: function(...args) {
return this.generic(type, ...args);
},
configurable: true,
enumerable: true,
writable: true,
},
}
),
{}
)
value: function(...args) {
return this.generic(type, ...args);
},
configurable: true,
enumerable: true,
writable: true
}
}
),
{}
)
);

module.exports = SDC;
8 changes: 4 additions & 4 deletions lib/flush/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* @return {undefined}
*/
module.exports = function flush() {
clearTimeout(this.timer);
this.timer = null;
this.send(this.bulk.join('\n'));
this.bulk.length = 0;
clearTimeout(this.timer);
this.timer = null;
this.send(this.bulk.join('\n'));
this.bulk.length = 0;
};
Loading

0 comments on commit f898837

Please sign in to comment.