Skip to content

Commit

Permalink
Add details to errors (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
omrilotan authored Dec 11, 2019
1 parent 7bdfbdb commit aeeb279
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 8 deletions.
5 changes: 3 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const sample = require('sample-size');
const betterror = require('./lib/betterror');
const flush = require('./lib/flush');
const formatter = require('./lib/formatter');
const push = require('./lib/push');
Expand Down Expand Up @@ -131,10 +132,10 @@ class SDC {

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

if (this.enforceRate && !sample(rate)) {
Expand Down
15 changes: 15 additions & 0 deletions lib/betterror/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Mutate: enrich error with details
* @param {Error} error
* @param {...any} arguments
* @return {void}
*/
module.exports = function betterror(error, details) {
if (details && typeof details === 'object') {
error.details = Object.assign(
error.details || {},
details
);
}
return error;
};
26 changes: 26 additions & 0 deletions lib/betterror/spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const betterror = require('.');

describe('betterror', () => {
it('Should return the original error', () => {
const error = new Error('Something must have gone terribly wrong');
expect(betterror(error)).to.equal(error);
});
it('Should not a "details" field when not applicable', () => {
const error = betterror(new Error('Something must have gone terribly wrong'));
expect(error).to.not.have.keys(['details']);
});
it('Should add a "details" field when applicable', () => {
const error = betterror(new Error('Something must have gone terribly wrong'), { a: 1 });
expect(error).to.have.keys(['details']);
});
it('Should add "details" to error', () => {
const error = betterror(new Error('Something must have gone terribly wrong'), { a: 1 });
expect(error.details).to.deep.equal({ a: 1 });
});
it('Should assign details if there is are some already', () => {
const err = new Error('Something must have gone terribly wrong');
err.details = { a: 1 };
const error = betterror(err, { b: 2 });
expect(error.details).to.deep.equal({ a: 1, b: 2 });
});
});
9 changes: 5 additions & 4 deletions lib/formatter/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const isNumber = require('is-number');
const betterror = require('../betterror');
const sanitiser = require('../sanitiser');
const types = require('../types');

Expand Down Expand Up @@ -62,13 +63,13 @@ module.exports = function formatter({prefix, sanitise = sanitiser, scheme = 'dat
if (type in types) {
type = types[type];
} else {
throw new RangeError(`Expected 'type' to be one of ${Object.keys(types).join(', ')}, instead got ${type}`);
throw betterror(new RangeError(`Expected 'type' to be one of ${Object.keys(types).join(', ')}, instead got ${type}`), { type, key, value, rate, tags });
}
if (typeof key !== 'string') {
throw new TypeError(`Expected 'key' to be a string, instead got ${key} (${typeof key})`);
throw betterror(new TypeError(`Expected 'key' to be a string, instead got ${key} (${typeof key})`), { type, key, value, rate, tags });
}
if (!prefix && !letterLeading(key)) {
throw new Error(`Expected 'key' to start with an alphabetical character (${key}).`);
throw betterror(new Error(`Expected 'key' to start with an alphabetical character (${key}).`), { type, key, value, rate, tags });
}
if (value instanceof Date) {
value = new Date() - value;
Expand All @@ -77,7 +78,7 @@ module.exports = function formatter({prefix, sanitise = sanitiser, scheme = 'dat
value = Number(process.hrtime.bigint() - value) / 1e6;
}
if (typeof value !== 'number' || !isNumber(value)) {
throw new TypeError(`Expected 'value' to be a number, instead got ${value} (${typeof value})`);
throw betterror(new TypeError(`Expected 'value' to be a number, instead got ${value} (${typeof value})`), { type, key, value, rate, tags });
}

if (prefix) {
Expand Down
16 changes: 15 additions & 1 deletion lib/formatter/spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,19 @@ describe('formatter', () => {
(type) => expect(() => format(type, 'Hello', undefined)).to.throw()
)
);
it(
'Should add details to errors',
() => {
let error;
try {
format('time', 'Hello', NaN);
} catch (e) {
error = e;
}
console.log(error);
expect(error.details).to.deep.equal({ type: 'ms', key: 'Hello', value: NaN, rate: undefined, tags: undefined });
}
);
it(
'Should default type to counter',
() => {
Expand Down Expand Up @@ -135,7 +148,8 @@ describe('formatter', () => {
expect(time).to.be.a('number');
expect(time).to.be.at.least(9);
});
it('Should use a BigInt in order to get the time diff', async() => {
it('Should use a BigInt in order to get the time diff', async function() {
this.retries(3);
let time;
const format = formatter({scheme: ({value}) => {
time = value;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@fiverr/statsd-client",
"version": "1.0.0",
"version": "1.0.1",
"description": "📈 A feature packed, highly customisable StatsD client",
"keywords": [
"StatsD",
Expand Down
1 change: 1 addition & 0 deletions test/spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ describe('Integration: bulk sending', () => {

new Array(4).fill('a').forEach(client.count);
expect(metrics).to.be.undefined;
await wait(5);

client.flush();
expect(metrics).to.be.instanceof(Buffer);
Expand Down

0 comments on commit aeeb279

Please sign in to comment.