68 lines
1.5 KiB
JavaScript
68 lines
1.5 KiB
JavaScript
'use strict';
|
|
|
|
const { TDigest } = require('tdigest');
|
|
|
|
class TimeWindowQuantiles {
|
|
constructor(maxAgeSeconds, ageBuckets) {
|
|
this.maxAgeSeconds = maxAgeSeconds || 0;
|
|
this.ageBuckets = ageBuckets || 0;
|
|
|
|
this.shouldRotate = maxAgeSeconds && ageBuckets;
|
|
|
|
this.ringBuffer = Array(ageBuckets).fill(new TDigest());
|
|
this.currentBuffer = 0;
|
|
|
|
this.lastRotateTimestampMillis = Date.now();
|
|
this.durationBetweenRotatesMillis =
|
|
(maxAgeSeconds * 1000) / ageBuckets || Infinity;
|
|
}
|
|
|
|
size() {
|
|
const bucket = rotate.call(this);
|
|
return bucket.size();
|
|
}
|
|
|
|
percentile(quantile) {
|
|
const bucket = rotate.call(this);
|
|
return bucket.percentile(quantile);
|
|
}
|
|
|
|
push(value) {
|
|
rotate.call(this);
|
|
this.ringBuffer.forEach(bucket => {
|
|
bucket.push(value);
|
|
});
|
|
}
|
|
|
|
reset() {
|
|
this.ringBuffer.forEach(bucket => {
|
|
bucket.reset();
|
|
});
|
|
}
|
|
|
|
compress() {
|
|
this.ringBuffer.forEach(bucket => {
|
|
bucket.compress();
|
|
});
|
|
}
|
|
}
|
|
|
|
function rotate() {
|
|
let timeSinceLastRotateMillis = Date.now() - this.lastRotateTimestampMillis;
|
|
while (
|
|
timeSinceLastRotateMillis > this.durationBetweenRotatesMillis &&
|
|
this.shouldRotate
|
|
) {
|
|
this.ringBuffer[this.currentBuffer] = new TDigest();
|
|
|
|
if (++this.currentBuffer >= this.ringBuffer.length) {
|
|
this.currentBuffer = 0;
|
|
}
|
|
timeSinceLastRotateMillis -= this.durationBetweenRotatesMillis;
|
|
this.lastRotateTimestampMillis += this.durationBetweenRotatesMillis;
|
|
}
|
|
return this.ringBuffer[this.currentBuffer];
|
|
}
|
|
|
|
module.exports = TimeWindowQuantiles;
|