prom-client
Advanced tools
Comparing version 2.0.2 to 3.0.0
@@ -8,22 +8,33 @@ 'use strict'; | ||
var Histogram = require('../lib/histogram'); | ||
var h = new Histogram('test_histogram', 'Example of a histogram'); | ||
var h = new Histogram('test_histogram', 'Example of a histogram', [ 'code' ]); | ||
var Counter = require('../lib/counter'); | ||
var c = new Counter('test_counter', 'Example of a counter', { labels: { 'code': 200 }}); | ||
var c = new Counter('test_counter', 'Example of a counter', [ 'code' ]); | ||
var Gauge = require('../lib/gauge'); | ||
var g = new Gauge('test_gauge', 'Example of a gauge'); | ||
var g = new Gauge('test_gauge', 'Example of a gauge', [ 'method', 'code' ]); | ||
setInterval(function() { | ||
h.observe(Math.random()); | ||
}, 100); | ||
h.labels('200').observe(Math.random()); | ||
}, 1000); | ||
setInterval(function() { | ||
c.inc(); | ||
c.inc({ code: 200 }); | ||
}, 5000); | ||
setInterval(function() { | ||
c.inc({ code: 400 }); | ||
}, 2000); | ||
setInterval(function() { | ||
c.inc(); | ||
}, 2000); | ||
setInterval(function() { | ||
g.set({ method: 'get', code: 200 }, Math.random()); | ||
g.set(Math.random()); | ||
g.labels('post', '300').inc(); | ||
}, 100); | ||
server.get('/metrics', function(req, res) { | ||
@@ -30,0 +41,0 @@ res.end(register.metrics()); |
@@ -8,3 +8,10 @@ /** | ||
var isNumber = require('./util').isNumber; | ||
var getProperties = require('./util').getPropertiesFromObj; | ||
var createValue = require('./util').incValue; | ||
var validateLabels = require('./validation').validateLabel; | ||
var validateMetricName = require('./validation').validateMetricName; | ||
var validateLabelNames = require('./validation').validateLabelName; | ||
var getLabels = require('./util').getLabels; | ||
/** | ||
@@ -14,6 +21,6 @@ * Counter | ||
* @param {string} help - Help description for the metric | ||
* @param {object} obj - Configuration | ||
* @param {array} labels - Labels | ||
* @constructor | ||
*/ | ||
function Counter(name, help, obj) { | ||
function Counter(name, help, labels) { | ||
if(!help) { | ||
@@ -25,8 +32,14 @@ throw new Error('Missing mandatory help parameter'); | ||
} | ||
obj = obj || {}; | ||
if(!validateMetricName(name)) { | ||
throw new Error('Invalid metric name'); | ||
} | ||
if(!validateLabelNames(labels)) { | ||
throw new Error('Invalid label name'); | ||
} | ||
this.name = name; | ||
this.values = [{ | ||
value: 0, | ||
labels: obj.labels | ||
}]; | ||
this.hashMap = {}; | ||
this.labelNames = (labels || []); | ||
this.help = help; | ||
@@ -38,13 +51,11 @@ register.registerMetric(this); | ||
* Increment counter | ||
* @param {object} labels - What label you want to be incremented | ||
* @param {float} value - Value to increment, if omitted increment with 1 | ||
* @returns {void} | ||
*/ | ||
Counter.prototype.inc = function(value) { | ||
if(value && !isNumber(value)) { | ||
throw new Error('Value is not a valid number', value); | ||
Counter.prototype.inc = function(labels, value) { | ||
if(isNumber(labels)) { | ||
return inc.call(this, null)(labels); | ||
} | ||
if(value < 0) { | ||
throw new Error('It is not possible to decrease a counter'); | ||
} | ||
this.values[0].value = this.values[0].value += value || 1; | ||
return inc.call(this, labels)(value); | ||
}; | ||
@@ -57,6 +68,30 @@ | ||
type: type, | ||
values: this.values | ||
values: getProperties(this.hashMap) | ||
}; | ||
}; | ||
Counter.prototype.labels = function() { | ||
var labels = getLabels(this.labelNames, arguments); | ||
return { | ||
inc: inc.call(this, labels) | ||
}; | ||
}; | ||
var inc = function(labels) { | ||
var that = this; | ||
return function(value) { | ||
if(value && !isNumber(value)) { | ||
throw new Error('Value is not a valid number', value); | ||
} | ||
if(value < 0) { | ||
throw new Error('It is not possible to decrease a counter'); | ||
} | ||
labels = labels || {}; | ||
validateLabels(that.labelNames, labels); | ||
that.hashMap = createValue(that.hashMap, value || 1, labels); | ||
}; | ||
}; | ||
module.exports = Counter; |
145
lib/gauge.js
@@ -8,4 +8,11 @@ /** | ||
var type = 'gauge'; | ||
var objectHash = require('object-hash'); | ||
var isNumber = require('./util').isNumber; | ||
var createValue = require('./util').setValue; | ||
var getProperties = require('./util').getPropertiesFromObj; | ||
var getLabels = require('./util').getLabels; | ||
var validateMetricName = require('./validation').validateMetricName; | ||
var validateLabels = require('./validation').validateLabel; | ||
var validateLabelNames = require('./validation').validateLabelName; | ||
@@ -16,6 +23,6 @@ /** | ||
* @param {string} help - Help for the metric | ||
* @param {object} obj - Configuration | ||
* @param {array} labels - Array with strings, all label keywords supported | ||
* @constructor | ||
*/ | ||
function Gauge(name, help, obj) { | ||
function Gauge(name, help, labels) { | ||
if(!help) { | ||
@@ -27,8 +34,13 @@ throw new Error('Missing mandatory help parameter'); | ||
} | ||
obj = obj || {}; | ||
if(!validateMetricName(name)) { | ||
throw new Error('Invalid metric name'); | ||
} | ||
if(!validateLabelNames(labels)) { | ||
throw new Error('Invalid label name'); | ||
} | ||
this.name = name; | ||
this.values = [{ | ||
value: 0, | ||
labels: obj.labels | ||
}]; | ||
this.labelNames = labels || []; | ||
this.hashMap = {}; | ||
this.help = help; | ||
@@ -40,10 +52,11 @@ register.registerMetric(this); | ||
* Set a gauge to a value | ||
* @param {object} labels - Object with labels and their values | ||
* @param {float} value - Value to set the gauge to, must be positive | ||
* @returns {void} | ||
*/ | ||
Gauge.prototype.set = function(value) { | ||
if(!isNumber(value)) { | ||
throw new Error('Value is not a valid number', value); | ||
Gauge.prototype.set = function(labels, value) { | ||
if(isNumber(labels)) { | ||
return set.call(this, null)(labels); | ||
} | ||
this.values[0].value = value; | ||
return set.call(this, labels)(value); | ||
}; | ||
@@ -53,16 +66,19 @@ | ||
* Increment a gauge value | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @param {float} value - Value to increment - if omitted, increment with 1 | ||
* @returns {void} | ||
*/ | ||
Gauge.prototype.inc = function(value) { | ||
this.set(this._getValue() + (value || 1)); | ||
Gauge.prototype.inc = function(labels, value) { | ||
inc.call(this, labels)(value); | ||
}; | ||
/** | ||
* Decrement a gauge value | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @param {float} value - Value to decrement - if omitted, decrement with 1 | ||
* @returns {void} | ||
*/ | ||
Gauge.prototype.dec = function(value) { | ||
this.set(this._getValue() - (value || 1)); | ||
Gauge.prototype.dec = function(labels, value) { | ||
dec.call(this, labels)(value); | ||
}; | ||
@@ -72,6 +88,7 @@ | ||
* Set the gauge to current unix epoch | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @returns {void} | ||
*/ | ||
Gauge.prototype.setToCurrentTime = function() { | ||
this.set(new Date().getTime()); | ||
Gauge.prototype.setToCurrentTime = function(labels) { | ||
return setToCurrentTime.call(this, labels)(); | ||
}; | ||
@@ -81,2 +98,3 @@ | ||
* Start a timer | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @returns {function} - Invoke this function to set the duration in seconds since you started the timer. | ||
@@ -89,9 +107,4 @@ * @example | ||
*/ | ||
Gauge.prototype.startTimer = function() { | ||
var start = new Date(); | ||
var gauge = this; | ||
return function() { | ||
var end = new Date(); | ||
gauge.set((end - start) / 1000); | ||
}; | ||
Gauge.prototype.startTimer = function(labels) { | ||
return startTimer.call(this, labels)(); | ||
}; | ||
@@ -104,18 +117,84 @@ | ||
type: type, | ||
values: this.values | ||
values: getProperties(this.hashMap) | ||
}; | ||
}; | ||
/** | ||
* Reset the value of the gauge to 0 | ||
* @returns {void} | ||
*/ | ||
Gauge.prototype.reset = function() { | ||
this.values[0].value = 0; | ||
Gauge.prototype._getValue = function(labels) { | ||
var hash = objectHash(labels || {}); | ||
return this.hashMap[hash] ? this.hashMap[hash].value : 0; | ||
}; | ||
Gauge.prototype._getValue = function() { | ||
return this.values[0].value; | ||
Gauge.prototype.labels = function() { | ||
var labels = getLabels(this.labelNames, arguments); | ||
return { | ||
inc: inc.call(this, labels), | ||
dec: dec.call(this, labels), | ||
set: set.call(this, labels), | ||
setToCurrentTime: setToCurrentTime.call(this, labels), | ||
startTimer: startTimer.call(this, labels) | ||
}; | ||
}; | ||
function setToCurrentTime(labels) { | ||
var gauge = this; | ||
return function() { | ||
gauge.set(labels, new Date().getTime()); | ||
}; | ||
} | ||
function startTimer(labels) { | ||
var gauge = this; | ||
return function() { | ||
var start = new Date(); | ||
return function() { | ||
var end = new Date(); | ||
gauge.set(labels, (end - start) / 1000); | ||
}; | ||
}; | ||
} | ||
function dec(labels) { | ||
var gauge = this; | ||
return function(value) { | ||
var data = convertLabelsAndValues(labels, value); | ||
gauge.set(data.labels, gauge._getValue(data.labels) - (data.value || 1)); | ||
}; | ||
} | ||
function inc(labels) { | ||
var gauge = this; | ||
return function(value) { | ||
var data = convertLabelsAndValues(labels, value); | ||
gauge.set(data.labels, gauge._getValue(data.labels) + (data.value || 1)); | ||
}; | ||
} | ||
function set(labels) { | ||
var that = this; | ||
return function(value) { | ||
if(!isNumber(value)) { | ||
throw new Error('Value is not a valid number', val); | ||
} | ||
labels = labels || {}; | ||
validateLabels(that.labelNames, labels); | ||
that.hashMap = createValue(that.hashMap, value, labels); | ||
}; | ||
} | ||
function convertLabelsAndValues(labels, value) { | ||
if(isNumber(labels)) { | ||
return { | ||
value: labels, | ||
labels: {} | ||
}; | ||
} | ||
return { | ||
labels: labels, | ||
value: value | ||
}; | ||
} | ||
module.exports = Gauge; |
@@ -10,2 +10,8 @@ /** | ||
var extend = require('util-extend'); | ||
var getProperties = require('./util').getPropertiesFromObj; | ||
var getLabels = require('./util').getLabels; | ||
var createValue = require('./util'); | ||
var validateLabels = require('./validation').validateLabel; | ||
var validateMetricName = require('./validation').validateMetricName; | ||
var validateLabelNames = require('./validation').validateLabelName; | ||
@@ -16,24 +22,23 @@ /** | ||
* @param {string} help - Help for the metric | ||
* @param {object} obj - Configuration object | ||
* @param {object|array} labelsOrConf - Either array of label names or config object as a key-value object | ||
* @param {object} conf - Configuration object | ||
* @constructor | ||
*/ | ||
function Histogram(name, help, obj) { | ||
if(!help) { | ||
throw new Error('Missing mandatory help parameter'); | ||
} | ||
if(!name) { | ||
throw new Error('Missing mandatory name parameter'); | ||
} | ||
function Histogram(name, help, labelsOrConf, conf) { | ||
var obj; | ||
var labels = []; | ||
obj = obj || {}; | ||
if(obj.labels && obj.labels.le) { | ||
throw new Error('Le is a reserved keyword and can not be used as a custom label'); | ||
if(Array.isArray(labelsOrConf)) { | ||
obj = conf || {}; | ||
labels = labelsOrConf; | ||
} else { | ||
obj = labelsOrConf || {}; | ||
} | ||
var defaultUpperbounds = (obj.buckets || [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10]).sort(function(x, y) { | ||
return x - y; | ||
}); | ||
validateInput(name, help, labels); | ||
this.name = name; | ||
this.help = help; | ||
this.upperBounds = defaultUpperbounds; | ||
this.upperBounds = configureUpperbounds(obj.buckets); | ||
this.bucketValues = this.upperBounds.reduce(function(acc, upperBound) { | ||
@@ -43,6 +48,9 @@ acc[upperBound] = 0; | ||
}, {}); | ||
Object.freeze(this.upperBounds); | ||
this.sum = 0; | ||
this.count = 0; | ||
this.labels = {}; | ||
this.hashMap = {}; | ||
this.labelNames = labels || []; | ||
register.registerMetric(this); | ||
@@ -53,27 +61,16 @@ } | ||
* Observe a value in histogram | ||
* @param {float} val - Value to observe in the histogram | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @param {float} value - Value to observe in the histogram | ||
* @returns {void} | ||
*/ | ||
Histogram.prototype.observe = function(val) { | ||
if(!isNumber(val)) { | ||
throw new Error('Value is not a valid number', val); | ||
} | ||
var b = findBound(this.upperBounds, val); | ||
if(!this.bucketValues.hasOwnProperty(b)) { | ||
return; | ||
} | ||
this.bucketValues[b] += 1; | ||
this.sum += val; | ||
this.count += 1; | ||
Histogram.prototype.observe = function(labels, value) { | ||
observe.call(this, labels || {})(value); | ||
}; | ||
Histogram.prototype.get = function() { | ||
var histogram = this; | ||
var values = this.upperBounds.map(function(upperBound) { | ||
var lbls = extend({ le: upperBound }, histogram.labels); | ||
return createValuePair(lbls, histogram.bucketValues[upperBound], histogram.name + '_bucket'); | ||
}); | ||
values.push(createValuePair({ le: '+Inf' }, this.count, histogram.name + '_bucket')); | ||
values.push(createValuePair({}, this.sum, histogram.name + '_sum')); | ||
values.push(createValuePair({}, this.count, histogram.name + '_count')); | ||
var data = getProperties(this.hashMap); | ||
var values = | ||
data.map(extractBucketValuesForExport(this)) | ||
.reduce(addSumAndCountForExport(this), []); | ||
return { | ||
@@ -89,2 +86,3 @@ name: this.name, | ||
* Start a timer that could be used to logging durations | ||
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep | ||
* @returns {function} - Function to invoke when you want to stop the timer and observe the duration in seconds | ||
@@ -97,11 +95,56 @@ * @example | ||
*/ | ||
Histogram.prototype.startTimer = function() { | ||
var start = new Date(); | ||
Histogram.prototype.startTimer = function(labels) { | ||
return startTimer.call(this, labels)(); | ||
}; | ||
Histogram.prototype.labels = function() { | ||
var labels = getLabels(this.labelNames, arguments); | ||
return { | ||
observe: observe.call(this, labels), | ||
startTimer: startTimer.call(this, labels) | ||
}; | ||
}; | ||
function startTimer(labels) { | ||
var histogram = this; | ||
return function() { | ||
var end = new Date(); | ||
histogram.observe((end - start) / 1000); | ||
var start = new Date(); | ||
return function() { | ||
var end = new Date(); | ||
histogram.observe(labels, (end - start) / 1000); | ||
}; | ||
}; | ||
}; | ||
} | ||
function validateInput(name, help, labels) { | ||
if(!help) { | ||
throw new Error('Missing mandatory help parameter'); | ||
} | ||
if(!name) { | ||
throw new Error('Missing mandatory name parameter'); | ||
} | ||
if(!validateMetricName(name)) { | ||
throw new Error('Invalid metric name'); | ||
} | ||
if(!validateLabelNames(labels)) { | ||
throw new Error('Invalid label name'); | ||
} | ||
labels.forEach(function(label) { | ||
if(label === 'le') { | ||
throw new Error('le is a reserved label keyword'); | ||
} | ||
}); | ||
} | ||
function configureUpperbounds(configuredBuckets) { | ||
var defaultBuckets = [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10]; | ||
return (configuredBuckets || defaultBuckets).sort(sortAscending); | ||
} | ||
function sortAscending(x, y) { | ||
return x - y; | ||
} | ||
function createValuePair(labels, value, metricName) { | ||
@@ -115,3 +158,2 @@ return { | ||
function findBound(upperBounds, value) { | ||
@@ -125,4 +167,84 @@ for(var i = 0; i < upperBounds.length; i++) { | ||
} | ||
//TODO: What to return? | ||
return -1; | ||
} | ||
function observe(labels) { | ||
var histogram = this; | ||
return function(value) { | ||
var labelValuePair = convertLabelsAndValues(labels, value); | ||
validateLabels(histogram.labelNames, labelValuePair.labels); | ||
if(!isNumber(labelValuePair.value)) { | ||
throw new Error('Value is not a valid number', labelValuePair.value); | ||
} | ||
var objectHash = require('object-hash'); | ||
var hash = objectHash(labelValuePair.labels); | ||
var valueFromMap = histogram.hashMap[hash]; | ||
if(!valueFromMap) { | ||
valueFromMap = createBaseValues(labelValuePair.labels, histogram.bucketValues); | ||
} | ||
var b = findBound(histogram.upperBounds, labelValuePair.value); | ||
valueFromMap.sum += labelValuePair.value; | ||
valueFromMap.count += 1; | ||
if(histogram.bucketValues.hasOwnProperty(b)) { | ||
valueFromMap.bucketValues[b] += 1; | ||
} | ||
histogram.hashMap[hash] = valueFromMap; | ||
}; | ||
} | ||
function createBaseValues(labels, bucketValues) { | ||
return { | ||
labels: labels, | ||
bucketValues: bucketValues, | ||
sum: 0, | ||
count: 0 | ||
}; | ||
} | ||
function convertLabelsAndValues(labels, value) { | ||
if(isNumber(labels)) { | ||
return { | ||
value: labels, | ||
labels: {} | ||
}; | ||
} | ||
return { | ||
labels: labels, | ||
value: value | ||
}; | ||
} | ||
function extractBucketValuesForExport(histogram) { | ||
return function(bucketData) { | ||
var buckets = histogram.upperBounds.map(createBucketValues(bucketData, histogram)); | ||
return { buckets: buckets, data: bucketData }; | ||
}; | ||
} | ||
function addSumAndCountForExport(histogram) { | ||
return function(acc, d) { | ||
acc = acc.concat(d.buckets); | ||
var infLabel = extend({ le: '+Inf'}, d.data.labels); | ||
acc.push(createValuePair(infLabel, d.data.count, histogram.name + '_bucket')); | ||
acc.push(createValuePair(d.data.labels, d.data.sum, histogram.name + '_sum')); | ||
acc.push(createValuePair(d.data.labels, d.data.count, histogram.name + '_count')); | ||
return acc; | ||
}; | ||
} | ||
function createBucketValues(bucket, histogram) { | ||
return function(upperBound) { | ||
var lbls = extend({ le: upperBound }, bucket.labels); | ||
var valuePair = createValuePair(lbls, bucket.bucketValues[upperBound], histogram.name + '_bucket'); | ||
return valuePair; | ||
}; | ||
} | ||
module.exports = Histogram; |
@@ -8,6 +8,8 @@ 'use strict'; | ||
var item = metric.get(); | ||
var help = ['#', 'HELP', item.name, item.help].join(' '); | ||
var type = ['#', 'TYPE', item.name, item.type].join(' '); | ||
var name = escapeString(item.name); | ||
var help = escapeString(item.help); | ||
var help = ['#', 'HELP', name, help].join(' '); | ||
var type = ['#', 'TYPE', name, item.type].join(' '); | ||
var values = item.values.reduce(function(valAcc, val) { | ||
var values = (item.values || []).reduce(function(valAcc, val) { | ||
var labels = Object.keys(val.labels || {}).map(function(key) { | ||
@@ -32,2 +34,6 @@ return key + '="' + val.labels[key] + '"'; | ||
function escapeString(str) { | ||
return str.replace('"', '\\"').replace('\\n', '\\\n').replace('\\', '\\\\'); | ||
} | ||
var registerMetric = function registerMetric(metricFn) { | ||
@@ -34,0 +40,0 @@ metrics.push(metricFn); |
'use strict'; | ||
exports.isNumber = function isNumber(obj) { return !isNaN(parseFloat(obj)); }; | ||
var objectHash = require('object-hash'); | ||
exports.isNumber = isNumber; | ||
exports.getPropertiesFromObj = function(hashMap) { | ||
var obj = Object.keys(hashMap).map(function(x) { | ||
return hashMap[x]; | ||
}); | ||
return obj; | ||
}; | ||
exports.incValue = function createValue(hashMap, value, labels) { | ||
var hash = hashObject(labels); | ||
if(hashMap[hash]){ | ||
hashMap[hash].value += value || 1; | ||
} else { | ||
hashMap[hash] = { value: value || 1, labels: labels || {} }; | ||
} | ||
return hashMap; | ||
}; | ||
exports.setValue = function setValue(hashMap, value, labels) { | ||
var hash = hashObject(labels); | ||
hashMap[hash] = { value: isNumber(value) ? value : 0, labels: labels || {} }; | ||
return hashMap; | ||
}; | ||
exports.getLabels = function(labelNames, args) { | ||
if(labelNames.length !== args.length) { | ||
throw new Error('Invalid number of arguments'); | ||
} | ||
var argsAsArray = Array.prototype.slice.call(args); | ||
return labelNames.reduce(function(acc, label, index){ | ||
acc[label] = argsAsArray[index]; | ||
return acc; | ||
}, {}); | ||
}; | ||
function hashObject(labels) { | ||
return objectHash(labels); | ||
} | ||
function isNumber(obj) { return !isNaN(parseFloat(obj)); }; |
{ | ||
"name": "prom-client", | ||
"version": "2.0.2", | ||
"version": "3.0.0", | ||
"description": "Client for prometheus", | ||
@@ -33,4 +33,5 @@ "main": "index.js", | ||
"dependencies": { | ||
"object-hash": "^0.9.2", | ||
"util-extend": "^1.0.1" | ||
} | ||
} |
@@ -13,14 +13,4 @@ # Prometheus client for node.js | ||
All metric types has 2 mandatory parameters, name and help. Other than that, it always takes a configuration object as 3rd parameter. For all types, you can these properties: | ||
All metric types has 2 mandatory parameters, name and help. | ||
**labels** | ||
``` | ||
new Client.counter('name', 'help', | ||
{ | ||
labels: { | ||
type: 'request' | ||
} | ||
}); | ||
``` | ||
#### Counter | ||
@@ -92,1 +82,11 @@ | ||
#### Labels | ||
All metrics take an array as 3rd parameter that should include all supported label keys. There are 2 ways to add values to the labels | ||
``` | ||
var Client = require('prom-client'); | ||
var gauge = new Client.gauge('metric_name', 'metric_help', [ 'method', 'statusCode' ]); | ||
gauge.set({ method: 'GET', statusCode: '200' }, 100); // 1st version, Set value 100 with method set to GET and statusCode to 200 | ||
gauge.labels('GET', '200').set(100); // 2nd version, Same as above | ||
``` |
@@ -34,2 +34,29 @@ 'use strict'; | ||
}); | ||
describe('labels', function() { | ||
beforeEach(function() { | ||
instance = new Counter('gauge_test', 'help', [ 'method', 'endpoint']); | ||
}); | ||
it('should 1 value per label', function() { | ||
instance.labels('GET', '/test').inc(); | ||
instance.labels('POST', '/test').inc(); | ||
var values = instance.get().values; | ||
expect(values).to.have.length(2); | ||
}); | ||
it('should throw error if label lengths does not match', function() { | ||
var fn = function() { | ||
instance.labels('GET').inc(); | ||
}; | ||
expect(fn).to.throw(Error); | ||
}); | ||
it('should increment label value with provided value', function() { | ||
instance.labels('GET', '/test').inc(100); | ||
var values = instance.get().values; | ||
expect(values[0].value).to.equal(100); | ||
}); | ||
}); | ||
}); |
@@ -17,7 +17,2 @@ 'use strict'; | ||
it('should reset a gauge', function() { | ||
instance.reset(); | ||
expectValue(0); | ||
}); | ||
it('should increase with 1 if no param provided', function() { | ||
@@ -65,2 +60,35 @@ instance.inc(); | ||
describe('with labels', function() { | ||
beforeEach(function() { | ||
instance = new Gauge('name', 'help', ['code']); | ||
instance.set({ 'code': '200' }, 20); | ||
}); | ||
it('should be able to increment', function() { | ||
instance.labels('200').inc(); | ||
expectValue(21); | ||
}); | ||
it('should be able to decrement', function() { | ||
instance.labels('200').dec(); | ||
expectValue(19); | ||
}); | ||
it('should be able to set value', function() { | ||
instance.labels('200').set(500); | ||
expectValue(500); | ||
}); | ||
it('should be able to set value to current time', function() { | ||
var clock = sinon.useFakeTimers(); | ||
instance.labels('200').setToCurrentTime(); | ||
expectValue(new Date().getTime()); | ||
clock.restore(); | ||
}); | ||
it('should be able to start a timer', function(){ | ||
var clock = sinon.useFakeTimers(); | ||
var end = instance.labels('200').startTimer(); | ||
clock.tick(1000); | ||
end(); | ||
expectValue(1); | ||
clock.restore(); | ||
}); | ||
}); | ||
function expectValue(val) { | ||
@@ -67,0 +95,0 @@ expect(instance.get().values[0].value).to.equal(val); |
@@ -74,6 +74,6 @@ 'use strict'; | ||
it('should allow custom labels', function() { | ||
var i = new Histogram('histo', 'help', { labels: { code: 'test' }}); | ||
i.observe(1); | ||
var pair = getValueByLabel('test', instance.get().values); | ||
expect(pair).to.exist; | ||
var i = new Histogram('histo', 'help', [ 'code' ]); | ||
i.observe({ code: 'test'}, 1); | ||
var pair = getValueByLeAndLabel(1, 'code', 'test', i.get().values); | ||
expect(pair.value).to.equal(1); | ||
}); | ||
@@ -83,3 +83,3 @@ | ||
var fn = function() { | ||
new Histogram('name', 'help', { labels: { le: 'test' }}); | ||
new Histogram('name', 'help', [ 'le' ]); | ||
}; | ||
@@ -89,12 +89,38 @@ expect(fn).to.throw(Error); | ||
it('should not observe value if outside most upper bound', function() { | ||
it('should observe value if outside most upper bound', function() { | ||
instance.observe(100000); | ||
var values = instance.get().values; | ||
var valuesAboveZero = values.reduce(function(acc, v) { | ||
acc += v.value; | ||
return acc; | ||
}, 0); | ||
expect(valuesAboveZero).to.equal(0); | ||
var count = getValueByLabel('+Inf', values, 'le'); | ||
expect(count.value).to.equal(1); | ||
}); | ||
describe('labels', function() { | ||
beforeEach(function() { | ||
instance = new Histogram('histogram_labels', 'Histogram with labels fn', [ 'method' ]); | ||
}); | ||
it('should observe', function() { | ||
instance.labels('get').observe(4); | ||
var res = getValueByLeAndLabel(5, 'method', 'get', instance.get().values); | ||
expect(res.value).to.equal(1); | ||
}); | ||
it('should not allow different number of labels', function() { | ||
var fn = function() { | ||
instance.labels('get', '500').observe(4); | ||
}; | ||
expect(fn).to.throw(Error); | ||
}); | ||
it('should start a timer', function() { | ||
var clock = sinon.useFakeTimers(); | ||
var end = instance.labels('get').startTimer(); | ||
clock.tick(500); | ||
end(); | ||
var res = getValueByLeAndLabel(0.5, 'method', 'get', instance.get().values); | ||
expect(res.value).to.equal(1); | ||
clock.restore(); | ||
}); | ||
}); | ||
function getValueByName(name, values) { | ||
@@ -108,5 +134,5 @@ return values.reduce(function(acc, val) { | ||
} | ||
function getValueByLabel(label, values) { | ||
function getValueByLeAndLabel(le, key, label, values) { | ||
return values.reduce(function(acc, val) { | ||
if(val.labels && val.labels.le === label) { | ||
if(val.labels && val.labels.le === le && val.labels[key] === label) { | ||
acc = val; | ||
@@ -117,2 +143,11 @@ } | ||
} | ||
function getValueByLabel(label, values, key) { | ||
return values.reduce(function(acc, val) { | ||
console.log('val', val.labels[key]); | ||
if(val.labels && val.labels[key || 'le'] === label) { | ||
acc = val; | ||
} | ||
return acc; | ||
}, {}); | ||
} | ||
}); |
@@ -54,2 +54,27 @@ 'use strict'; | ||
describe('should escape', function() { | ||
var escapedResult; | ||
beforeEach(function() { | ||
register.registerMetric({ | ||
get: function() { | ||
return { | ||
name: 'test_"_\_\n_metric', | ||
help: 'help_help', | ||
type: 'counter' | ||
}; | ||
} | ||
}); | ||
escapedResult = register.metrics(); | ||
}); | ||
it('double quote to /"', function() { | ||
expect(escapedResult).to.match(/\\"/); | ||
}); | ||
it('backslash to \\\\', function() { | ||
expect(escapedResult).to.match(/\\\\/); | ||
}); | ||
it('newline to \\\\n', function() { | ||
// expect(escapedResult).to.match(/\/); | ||
}); | ||
}); | ||
function getMetric() { | ||
@@ -56,0 +81,0 @@ return { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
32335
18
947
2
+ Addedobject-hash@^0.9.2
+ Addedobject-hash@0.9.5(transitive)