@opentelemetry/sdk-metrics
Version:
315 lines • 11 kB
JavaScript
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var Buckets = /** @class */ (function () {
/**
* The term index refers to the number of the exponential histogram bucket
* used to determine its boundaries. The lower boundary of a bucket is
* determined by base ** index and the upper boundary of a bucket is
* determined by base ** (index + 1). index values are signed to account
* for values less than or equal to 1.
*
* indexBase is the index of the 0th position in the
* backing array, i.e., backing[0] is the count
* in the bucket with index `indexBase`.
*
* indexStart is the smallest index value represented
* in the backing array.
*
* indexEnd is the largest index value represented in
* the backing array.
*/
function Buckets(backing, indexBase, indexStart, indexEnd) {
if (backing === void 0) { backing = new BucketsBacking(); }
if (indexBase === void 0) { indexBase = 0; }
if (indexStart === void 0) { indexStart = 0; }
if (indexEnd === void 0) { indexEnd = 0; }
this.backing = backing;
this.indexBase = indexBase;
this.indexStart = indexStart;
this.indexEnd = indexEnd;
}
Object.defineProperty(Buckets.prototype, "offset", {
/**
* Offset is the bucket index of the smallest entry in the counts array
* @returns {number}
*/
get: function () {
return this.indexStart;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Buckets.prototype, "length", {
/**
* Buckets is a view into the backing array.
* @returns {number}
*/
get: function () {
if (this.backing.length === 0) {
return 0;
}
if (this.indexEnd === this.indexStart && this.at(0) === 0) {
return 0;
}
return this.indexEnd - this.indexStart + 1;
},
enumerable: false,
configurable: true
});
/**
* An array of counts, where count[i] carries the count
* of the bucket at index (offset+i). count[i] is the count of
* values greater than base^(offset+i) and less than or equal to
* base^(offset+i+1).
* @returns {number} The logical counts based on the backing array
*/
Buckets.prototype.counts = function () {
var _this = this;
return Array.from({ length: this.length }, function (_, i) { return _this.at(i); });
};
/**
* At returns the count of the bucket at a position in the logical
* array of counts.
* @param position
* @returns {number}
*/
Buckets.prototype.at = function (position) {
var bias = this.indexBase - this.indexStart;
if (position < bias) {
position += this.backing.length;
}
position -= bias;
return this.backing.countAt(position);
};
/**
* incrementBucket increments the backing array index by `increment`
* @param bucketIndex
* @param increment
*/
Buckets.prototype.incrementBucket = function (bucketIndex, increment) {
this.backing.increment(bucketIndex, increment);
};
/**
* decrementBucket decrements the backing array index by `decrement`
* if decrement is greater than the current value, it's set to 0.
* @param bucketIndex
* @param decrement
*/
Buckets.prototype.decrementBucket = function (bucketIndex, decrement) {
this.backing.decrement(bucketIndex, decrement);
};
/**
* trim removes leading and / or trailing zero buckets (which can occur
* after diffing two histos) and rotates the backing array so that the
* smallest non-zero index is in the 0th position of the backing array
*/
Buckets.prototype.trim = function () {
for (var i = 0; i < this.length; i++) {
if (this.at(i) !== 0) {
this.indexStart += i;
break;
}
else if (i === this.length - 1) {
//the entire array is zeroed out
this.indexStart = this.indexEnd = this.indexBase = 0;
return;
}
}
for (var i = this.length - 1; i >= 0; i--) {
if (this.at(i) !== 0) {
this.indexEnd -= this.length - i - 1;
break;
}
}
this._rotate();
};
/**
* downscale first rotates, then collapses 2**`by`-to-1 buckets.
* @param by
*/
Buckets.prototype.downscale = function (by) {
this._rotate();
var size = 1 + this.indexEnd - this.indexStart;
var each = 1 << by;
var inpos = 0;
var outpos = 0;
for (var pos = this.indexStart; pos <= this.indexEnd;) {
var mod = pos % each;
if (mod < 0) {
mod += each;
}
for (var i = mod; i < each && inpos < size; i++) {
this._relocateBucket(outpos, inpos);
inpos++;
pos++;
}
outpos++;
}
this.indexStart >>= by;
this.indexEnd >>= by;
this.indexBase = this.indexStart;
};
/**
* Clone returns a deep copy of Buckets
* @returns {Buckets}
*/
Buckets.prototype.clone = function () {
return new Buckets(this.backing.clone(), this.indexBase, this.indexStart, this.indexEnd);
};
/**
* _rotate shifts the backing array contents so that indexStart ==
* indexBase to simplify the downscale logic.
*/
Buckets.prototype._rotate = function () {
var bias = this.indexBase - this.indexStart;
if (bias === 0) {
return;
}
else if (bias > 0) {
this.backing.reverse(0, this.backing.length);
this.backing.reverse(0, bias);
this.backing.reverse(bias, this.backing.length);
}
else {
// negative bias, this can happen when diffing two histograms
this.backing.reverse(0, this.backing.length);
this.backing.reverse(0, this.backing.length + bias);
}
this.indexBase = this.indexStart;
};
/**
* _relocateBucket adds the count in counts[src] to counts[dest] and
* resets count[src] to zero.
*/
Buckets.prototype._relocateBucket = function (dest, src) {
if (dest === src) {
return;
}
this.incrementBucket(dest, this.backing.emptyBucket(src));
};
return Buckets;
}());
export { Buckets };
/**
* BucketsBacking holds the raw buckets and some utility methods to
* manage them.
*/
var BucketsBacking = /** @class */ (function () {
function BucketsBacking(_counts) {
if (_counts === void 0) { _counts = [0]; }
this._counts = _counts;
}
Object.defineProperty(BucketsBacking.prototype, "length", {
/**
* length returns the physical size of the backing array, which
* is >= buckets.length()
*/
get: function () {
return this._counts.length;
},
enumerable: false,
configurable: true
});
/**
* countAt returns the count in a specific bucket
*/
BucketsBacking.prototype.countAt = function (pos) {
return this._counts[pos];
};
/**
* growTo grows a backing array and copies old entries
* into their correct new positions.
*/
BucketsBacking.prototype.growTo = function (newSize, oldPositiveLimit, newPositiveLimit) {
var tmp = new Array(newSize).fill(0);
tmp.splice.apply(tmp, __spreadArray([newPositiveLimit,
this._counts.length - oldPositiveLimit], __read(this._counts.slice(oldPositiveLimit)), false));
tmp.splice.apply(tmp, __spreadArray([0, oldPositiveLimit], __read(this._counts.slice(0, oldPositiveLimit)), false));
this._counts = tmp;
};
/**
* reverse the items in the backing array in the range [from, limit).
*/
BucketsBacking.prototype.reverse = function (from, limit) {
var num = Math.floor((from + limit) / 2) - from;
for (var i = 0; i < num; i++) {
var tmp = this._counts[from + i];
this._counts[from + i] = this._counts[limit - i - 1];
this._counts[limit - i - 1] = tmp;
}
};
/**
* emptyBucket empties the count from a bucket, for
* moving into another.
*/
BucketsBacking.prototype.emptyBucket = function (src) {
var tmp = this._counts[src];
this._counts[src] = 0;
return tmp;
};
/**
* increments a bucket by `increment`
*/
BucketsBacking.prototype.increment = function (bucketIndex, increment) {
this._counts[bucketIndex] += increment;
};
/**
* decrements a bucket by `decrement`
*/
BucketsBacking.prototype.decrement = function (bucketIndex, decrement) {
if (this._counts[bucketIndex] >= decrement) {
this._counts[bucketIndex] -= decrement;
}
else {
// this should not happen, but we're being defensive against
// negative counts.
this._counts[bucketIndex] = 0;
}
};
/**
* clone returns a deep copy of BucketsBacking
*/
BucketsBacking.prototype.clone = function () {
return new BucketsBacking(__spreadArray([], __read(this._counts), false));
};
return BucketsBacking;
}());
//# sourceMappingURL=Buckets.js.map