Compare commits

...

1 Commits

Author SHA1 Message Date
Rahul Padigela 9a97d49e54 fix: pad insufficient data points
This fix adds padding for insufficient data points i.e., when storageUtilized
or numberOfObject sorted sets have only one element.
2017-03-30 17:57:42 -07:00
3 changed files with 68 additions and 4 deletions

View File

@ -172,12 +172,17 @@ export default class ListMetrics {
start, '-inf', 'LIMIT', '0', '1']; start, '-inf', 'LIMIT', '0', '1'];
const numberOfObjectsEnd = ['zrevrangebyscore', numberOfObjectsKey, end, const numberOfObjectsEnd = ['zrevrangebyscore', numberOfObjectsKey, end,
'-inf', 'LIMIT', '0', '1']; '-inf', 'LIMIT', '0', '1'];
const storageUtilizedCount = ['zcount', storageUtilizedKey, '-inf',
'+inf'];
const numberOfObjectsCount = ['zcount', numberOfObjectsKey, '-inf',
'+inf'];
const timestampRange = this._getTimestampRange(start, end); const timestampRange = this._getTimestampRange(start, end);
const metricKeys = [].concat.apply([], timestampRange.map( const metricKeys = [].concat.apply([], timestampRange.map(
i => getKeys(obj, i))); i => getKeys(obj, i)));
const cmds = metricKeys.map(item => ['get', item]); const cmds = metricKeys.map(item => ['get', item]);
cmds.push(storageUtilizedStart, storageUtilizedEnd, cmds.push(storageUtilizedStart, storageUtilizedEnd,
numberOfObjectsStart, numberOfObjectsEnd); numberOfObjectsStart, numberOfObjectsEnd, storageUtilizedCount,
numberOfObjectsCount);
datastore.batch(cmds, (err, res) => { datastore.batch(cmds, (err, res) => {
if (err) { if (err) {
@ -191,8 +196,26 @@ export default class ListMetrics {
const metricResponse = this._getMetricResponse(resource, start, const metricResponse = this._getMetricResponse(resource, start,
end); end);
// last 4 are results of storageUtilized, numberOfObjects, // last 4 are results of storageUtilized, numberOfObjects,
const absolutes = res.slice(-4); const storageCountArr = res.slice(-2, -1)[0];
const deltas = res.slice(0, res.length - 4); if (storageCountArr[0]) {
log.trace('command in a batch failed to execute', {
error: storageCountArr[0],
method: 'ListMetrics.getMetrics',
});
}
const storageUtilizedItemCount = parseInt(storageCountArr[1], 10)
|| 0;
const numObjectsCountArr = res.slice(-1)[0];
if (numObjectsCountArr[0]) {
log.trace('command in a batch failed to execute', {
error: numObjectsCountArr[0],
method: 'ListMetrics.getMetrics',
});
}
const numberOfObjectsItemCount = parseInt(numObjectsCountArr[1], 10)
|| 0;
const absolutes = res.slice(-6, -2);
const deltas = res.slice(0, res.length - 6);
absolutes.forEach((item, index) => { absolutes.forEach((item, index) => {
if (item[0]) { if (item[0]) {
// log error and continue // log error and continue
@ -215,6 +238,24 @@ export default class ListMetrics {
} }
}); });
// fix for metrics with insufficient data points where having only
// one data point for storage or number of objects would result in
// arrays like [1024, 1024], [1, 1] ...
const storageUtilArr = metricResponse.storageUtilized;
const insufficientstorageDatapoint =
storageUtilArr[0] === storageUtilArr[1] &&
storageUtilizedItemCount === 1;
if (insufficientstorageDatapoint) {
metricResponse.storageUtilized[0] = 0;
}
const numObjectsArr = metricResponse.numberOfObjects;
const numObjectsDatapoint = numObjectsArr[0] === numObjectsArr[1] &&
numberOfObjectsItemCount === 1;
if (numObjectsDatapoint) {
metricResponse.numberOfObjects[0] = 0;
}
/** /**
* Batch result is of the format * Batch result is of the format
* [ [null, '1'], [null, '2'], [null, '3'] ] where each * [ [null, '1'], [null, '2'], [null, '3'] ] where each

View File

@ -301,6 +301,29 @@ export default class Memory {
}); });
} }
/**
* Count number of elements from sorted set at key with scores between
* min and max (all inclusive)
* @param {string} key - data key
* @param {string|number} min - min score (number or -inf)
* @param {string|number} max - max score (number or +inf)
* @param {callback} cb - callback
* @return {undefined}
*/
zcount(key, min, max, cb) {
assert.strictEqual(typeof key, 'string');
assert.strictEqual(typeof min === 'number'
|| typeof min === 'string', true);
assert.strictEqual(typeof max === 'number'
|| typeof max === 'string', true);
process.nextTick(() => {
if (!this.data[key]) {
return cb(null, 0);
}
return cb(null, this.data[key].length);
});
}
/** /**
* Returns a pipeline instance that can execute commmands as a batch * Returns a pipeline instance that can execute commmands as a batch
* @param {array} cmds - list of commands * @param {array} cmds - list of commands

View File

@ -77,7 +77,7 @@ function testOps(schemaKey, keyIndex, metricindex, done) {
if (keyIndex === 'storageUtilized' || keyIndex === 'numberOfObjects') { if (keyIndex === 'storageUtilized' || keyIndex === 'numberOfObjects') {
key = generateStateKey(schemaObject, keyIndex); key = generateStateKey(schemaObject, keyIndex);
val = 1024; val = 1024;
props[metricindex] = [val, val]; props[metricindex] = [0, val];
memBackend.zadd(key, timestamp, val, () => memBackend.zadd(key, timestamp, val, () =>
assertMetrics(schemaKey, schemaObject[schemaKey], props, done)); assertMetrics(schemaKey, schemaObject[schemaKey], props, done));
} else if (keyIndex === 'incomingBytes' || keyIndex === 'outgoingBytes') { } else if (keyIndex === 'incomingBytes' || keyIndex === 'outgoingBytes') {