UNPKG

pandora-metrics

Version:
125 lines 3.95 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const Counter_1 = require("./Counter"); class BucketDeque { constructor(length = 11) { this.queue = []; this.current = 0; this.size = 11; this.size = length; // init buckets for (let i = 0; i < length; i++) { this.queue[i] = this.createQueueItem(); } } createQueueItem() { return { timestamp: -1, count: 0, }; } addLast(e) { this.current = (this.current + 1) % this.size; this.queue[this.current] = e; } peek() { return this.queue[this.current]; } /** * Example1: * 10:00 10:01 10:02 09:57 09:58 09:59 * 70 80 90 40 50 60 * | \ * startPos latestIndex * Example2: * 10:00 09:55 09:56 09:57 09:58 09:59 * 70 20 30 40 50 60 * | | * latestIndex startPos */ getBucketList() { let length = this.queue.length - 1; let bucketList = []; let startPos = this.current; let startTs = this.queue[this.current].timestamp; if (startPos < 0) { startPos = 0; } for (let i = startPos; i >= 0 && startPos - i < length; i--) { bucketList.push(this.queue[i]); } for (let i = length; i > startPos + 1; i--) { if (this.queue[i].timestamp > startTs) { // the current index has been update during this iteration // therefore the data shall not be collected } else { bucketList.push(this.queue[i]); } } return bucketList; } } exports.BucketDeque = BucketDeque; class BucketCounter extends Counter_1.BaseCounter { constructor(interval = 1, numberOfBucket = 10, updateTotalCount = true) { super(); /** * 是否更新总次数 */ this.updateTotalCount = false; this.totalCount = new Counter_1.BaseCounter(); this.interval = interval; this.buckets = new BucketDeque(numberOfBucket + 1); this.updateTotalCount = updateTotalCount; } update(n = 1) { if (this.updateTotalCount) { this.totalCount.inc(n); } let curTs = this.calculateCurrentTimestamp(Date.now()); let lastBucket = this.buckets.peek(); if (curTs > lastBucket.timestamp) { // create a new bucket and evict the oldest one let newBucket = { count: 0, timestamp: curTs }; this.buckets.addLast(newBucket); lastBucket = newBucket; } lastBucket.count += n; } /** * Return the bucket count, keyed by timestamp * @return the bucket count, keyed by timestamp */ getBucketCounts(startTime = 0) { let counts = new Map(); let curTs = this.calculateCurrentTimestamp(Date.now()); for (let bucket of this.buckets.getBucketList()) { if (1000 * bucket.timestamp >= startTime && bucket.timestamp <= curTs) { counts.set(bucket.timestamp * 1000, bucket.count); } } return counts; } calculateCurrentTimestamp(timestamp) { // transform to seconds and discard fractional part return Math.floor(Math.floor(timestamp / 1000) / this.interval) * this.interval; } getCount() { return this.totalCount.getCount(); } inc(n) { this.update(n); } dec(n = 1) { this.update(-n); } getBucketInterval() { return this.interval; } } exports.BucketCounter = BucketCounter; //# sourceMappingURL=BucketCounter.js.map