heimdalljs
Advanced tools
Comparing version 0.3.2 to 0.3.3
# master | ||
# 0.3.3 | ||
* add runtime version information | ||
* replace `EmptyObject` with `Object.create(null)` | ||
* don't include tests in published package | ||
# 0.3.2 | ||
* add session-root and page-root to tree construction | ||
# 0.3.1 | ||
* don't depend on Uint32Array | ||
* add hasMonitor | ||
# 0.3.0 | ||
@@ -4,0 +19,0 @@ |
@@ -1,256 +0,143 @@ | ||
// All Credit for this goes to the Ember.js Core Team | ||
// This exists because `Object.create(null)` is absurdly slow compared | ||
// to `new EmptyObject()`. In either case, you want a null prototype | ||
// when you're treating the object instances as arbitrary dictionaries | ||
// and don't want your keys colliding with build-in methods on the | ||
// default object prototype. | ||
var proto = Object.create(null, { | ||
// without this, we will always still end up with (new | ||
// EmptyObject()).constructor === Object | ||
constructor: { | ||
value: undefined, | ||
enumerable: false, | ||
writable: true | ||
} | ||
}); | ||
function EmptyObject() {} | ||
EmptyObject.prototype = proto; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { | ||
return typeof obj; | ||
} : function (obj) { | ||
return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; | ||
}; | ||
var createClass = function () { | ||
function defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
return function (Constructor, protoProps, staticProps) { | ||
if (protoProps) defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) defineProperties(Constructor, staticProps); | ||
return Constructor; | ||
}; | ||
}(); | ||
var slicedToArray = function () { | ||
function sliceIterator(arr, i) { | ||
var _arr = []; | ||
var _n = true; | ||
var _d = false; | ||
var _e = undefined; | ||
try { | ||
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { | ||
_arr.push(_s.value); | ||
if (i && _arr.length === i) break; | ||
} | ||
} catch (err) { | ||
_d = true; | ||
_e = err; | ||
} finally { | ||
try { | ||
if (!_n && _i["return"]) _i["return"](); | ||
} finally { | ||
if (_d) throw _e; | ||
} | ||
} | ||
return _arr; | ||
} | ||
return function (arr, i) { | ||
if (Array.isArray(arr)) { | ||
return arr; | ||
} else if (Symbol.iterator in Object(arr)) { | ||
return sliceIterator(arr, i); | ||
} else { | ||
throw new TypeError("Invalid attempt to destructure non-iterable instance"); | ||
} | ||
}; | ||
}(); | ||
var UNDEFINED_KEY = Object.create(null); | ||
var HashMap = function () { | ||
function HashMap(entries) { | ||
this._data = new EmptyObject(); | ||
if (entries) { | ||
for (var i = 0; i < entries.length; i++) { | ||
this.data[entries[i][0]] = entries[i][1]; | ||
} | ||
var HashMap = (function () { | ||
function HashMap(entries) { | ||
this._data = Object.create(null); | ||
if (entries) { | ||
for (var i = 0; i < entries.length; i++) { | ||
this.data[entries[i][0]] = entries[i][1]; | ||
} | ||
} | ||
} | ||
} | ||
createClass(HashMap, [{ | ||
key: 'forEach', | ||
value: function forEach(cb) { | ||
for (var key in this._data) { | ||
// skip undefined | ||
if (this._data[key] !== UNDEFINED_KEY) { | ||
cb(this._data[key], key); | ||
HashMap.prototype.forEach = function (cb) { | ||
for (var key in this._data) { | ||
// skip undefined | ||
if (this._data[key] !== UNDEFINED_KEY) { | ||
cb(this._data[key], key); | ||
} | ||
} | ||
} | ||
return this; | ||
}; | ||
HashMap.prototype.has = function (key) { | ||
return key in this._data && this._data[key] !== UNDEFINED_KEY; | ||
}; | ||
HashMap.prototype.get = function (key) { | ||
var val = this._data[key]; | ||
return val === UNDEFINED_KEY ? undefined : val; | ||
}; | ||
HashMap.prototype.set = function (key, value) { | ||
this._data[key] = value; | ||
return this; | ||
}; | ||
HashMap.prototype.delete = function (key) { | ||
this._data[key] = UNDEFINED_KEY; | ||
}; | ||
return HashMap; | ||
}()); | ||
return this; | ||
} | ||
}, { | ||
key: 'has', | ||
value: function has(key) { | ||
return key in this._data && this._data[key] !== UNDEFINED_KEY; | ||
} | ||
}, { | ||
key: 'get', | ||
value: function get(key) { | ||
var val = this._data[key]; | ||
return val === UNDEFINED_KEY ? undefined : val; | ||
} | ||
}, { | ||
key: 'set', | ||
value: function set(key, value) { | ||
this._data[key] = value; | ||
return this; | ||
} | ||
}, { | ||
key: 'delete', | ||
value: function _delete(key) { | ||
this._data[key] = UNDEFINED_KEY; | ||
} | ||
}]); | ||
return HashMap; | ||
}(); | ||
var SMALL_ARRAY_LENGTH = 250; | ||
var EventArray = function () { | ||
function EventArray() { | ||
var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH : arguments[0]; | ||
var initialData = arguments[1]; | ||
this.init(length, initialData); | ||
} | ||
createClass(EventArray, [{ | ||
key: "toJSON", | ||
value: function toJSON() { | ||
return this._data.slice(0, this.length); | ||
var EventArray = (function () { | ||
function EventArray(length, initialData) { | ||
if (length === void 0) { length = SMALL_ARRAY_LENGTH; } | ||
this.init(length, initialData); | ||
} | ||
}, { | ||
key: "init", | ||
value: function init() { | ||
var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH : arguments[0]; | ||
var initialData = arguments[1]; | ||
this.length = 0; | ||
this._length = length; | ||
this._data = new Array(length); | ||
if (initialData) { | ||
if (initialData.length > length) { | ||
length = initialData.length; | ||
this._data.length = length; | ||
this._length = length; | ||
EventArray.prototype.toJSON = function () { | ||
return this._data.slice(0, this.length); | ||
}; | ||
EventArray.prototype.init = function (length, initialData) { | ||
if (length === void 0) { length = SMALL_ARRAY_LENGTH; } | ||
this.length = 0; | ||
this._length = length; | ||
this._data = new Array(length); | ||
if (initialData) { | ||
if (initialData.length > length) { | ||
length = initialData.length; | ||
this._data.length = length; | ||
this._length = length; | ||
} | ||
for (var j = 0; j < initialData.length; j++) { | ||
this._data[j] = initialData[j]; | ||
this.length++; | ||
} | ||
} | ||
for (var j = 0; j < initialData.length; j++) { | ||
this._data[j] = initialData[j]; | ||
this.length++; | ||
} | ||
} | ||
} | ||
}; | ||
// TODO this should probably multiple index by 4 to hide | ||
// that we store in a flat array | ||
EventArray.prototype.get = function (index) { | ||
if (index >= 0 && index < this.length) { | ||
return this._data.slice(index, index + 4); | ||
} | ||
return undefined; | ||
}; | ||
EventArray.prototype.set = function (index, value) { | ||
if (index > this.length) { | ||
throw new Error("Index is out of array bounds."); | ||
} | ||
if (index === this.length) { | ||
this.length++; | ||
} | ||
this._data[index] = value; | ||
}; | ||
EventArray.prototype.forEach = function (cb) { | ||
for (var i = 0; i < this.length; i += 4) { | ||
cb(this._data.slice(i, i + 4), i); | ||
} | ||
}; | ||
EventArray.prototype.push = function (op, name, time, data) { | ||
var index = this.length; | ||
this.length += 4; | ||
if (index >= this._length) { | ||
this._length *= 2; | ||
this._data.length = this._length; | ||
} | ||
this._data[index] = op; | ||
this._data[index + 1] = name; | ||
this._data[index + 2] = time; | ||
this._data[index + 3] = data; | ||
return index; | ||
}; | ||
EventArray.prototype.pop = function () { | ||
var index = --this.length; | ||
if (index < 0) { | ||
this.length = 0; | ||
return undefined; | ||
} | ||
return this._data[index]; | ||
}; | ||
return EventArray; | ||
}()); | ||
}, { | ||
key: "get", | ||
value: function get(index) { | ||
if (index >= 0 && index < this.length) { | ||
return this._data.slice(index, index + 4); | ||
} | ||
var HAS_TYPED_ARRAYS = typeof Uint32Array !== 'undefined'; | ||
function hasTypedArrays() { | ||
return HAS_TYPED_ARRAYS; | ||
} | ||
return undefined; | ||
function fill(array, value, start, end) { | ||
if (hasTypedArrays()) { | ||
return array.fill(value, start, end); | ||
} | ||
}, { | ||
key: "set", | ||
value: function set(index, value) { | ||
if (index > this.length) { | ||
throw new Error("Index is out of array bounds."); | ||
} | ||
if (index === this.length) { | ||
this.length++; | ||
} | ||
this._data[index] = value; | ||
else { | ||
var s = start || 0; | ||
var e = end || array.length; | ||
for (; s < e; s++) { | ||
array[s] = value; | ||
} | ||
return array; | ||
} | ||
}, { | ||
key: "forEach", | ||
value: function forEach(cb) { | ||
for (var i = 0; i < this.length; i += 4) { | ||
cb(this._data.slice(i, i + 4), i); | ||
} | ||
} | ||
}, { | ||
key: "push", | ||
value: function push(op, name, time, data) { | ||
var index = this.length; | ||
this.length += 4; | ||
} | ||
if (index >= this._length) { | ||
this._length *= 2; | ||
this._data.length = this._length; | ||
} | ||
this._data[index] = op; | ||
this._data[index + 1] = name; | ||
this._data[index + 2] = time; | ||
this._data[index + 3] = data; | ||
return index; | ||
function grow(array, oldLength, newLength, fillValue) { | ||
if (fillValue === void 0) { fillValue = 0; } | ||
if (hasTypedArrays()) { | ||
var ret = new Uint32Array(newLength); | ||
ret.set(array); | ||
if (fillValue !== 0) { | ||
ret.fill(fillValue, oldLength); | ||
} | ||
return ret; | ||
} | ||
}, { | ||
key: "pop", | ||
value: function pop() { | ||
var index = --this.length; | ||
if (index < 0) { | ||
this.length = 0; | ||
return undefined; | ||
} | ||
return this._data[index]; | ||
else { | ||
array.length = newLength; | ||
fill(array, fillValue, oldLength, newLength); | ||
return array; | ||
} | ||
}]); | ||
return EventArray; | ||
}(); | ||
var A = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; | ||
function fill(array, value, start, end) { | ||
if (typeof array.fill === 'function') { | ||
return array.fill(value, start, end); | ||
} else { | ||
var len = array.length; | ||
var s = start || 0; | ||
var e = end || len; | ||
for (; s < e; s++) { | ||
array[s] = value; | ||
} | ||
return array; | ||
} | ||
} | ||
@@ -260,54 +147,40 @@ | ||
var MAX_ARRAY_LENGTH = 1e6; | ||
var FastIntArray = function () { | ||
function FastIntArray() { | ||
var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH$1 : arguments[0]; | ||
var initialData = arguments[1]; | ||
this.init(length, initialData); | ||
} | ||
createClass(FastIntArray, [{ | ||
key: 'init', | ||
value: function init() { | ||
var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH$1 : arguments[0]; | ||
var initialData = arguments[1]; | ||
this.length = 0; | ||
this._length = length; | ||
this._fill = 0; | ||
this._data = new A(length); | ||
if (initialData) { | ||
if (initialData.length > length) { | ||
length = initialData.length; | ||
this.grow(length); | ||
var FastIntArray = (function () { | ||
function FastIntArray(length, initialData) { | ||
if (length === void 0) { length = SMALL_ARRAY_LENGTH$1; } | ||
this.init(length, initialData); | ||
} | ||
FastIntArray.prototype.init = function (length, initialData) { | ||
if (length === void 0) { length = SMALL_ARRAY_LENGTH$1; } | ||
var useTypedArray = hasTypedArrays(); | ||
this.length = 0; | ||
this._length = length; | ||
this._fillValue = 0; | ||
this._data = useTypedArray ? new Uint32Array(length) : new Array(length); | ||
if (!useTypedArray) { | ||
fill(this._data, this._fillValue); | ||
} | ||
for (var j = 0; j < initialData.length; j++) { | ||
this._data[j] = initialData[j]; | ||
this.length++; | ||
if (initialData) { | ||
if (initialData.length > length) { | ||
length = initialData.length; | ||
this.grow(length); | ||
} | ||
for (var j = 0; j < initialData.length; j++) { | ||
this._data[j] = initialData[j]; | ||
this.length++; | ||
} | ||
} | ||
} | ||
} | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
return this._data.slice(0, this.length); | ||
} | ||
}, { | ||
key: 'get', | ||
value: function get(index) { | ||
if (index >= 0 && index < this.length) { | ||
return this._data[index]; | ||
} | ||
return undefined; | ||
} | ||
}, { | ||
key: 'increment', | ||
value: function increment(index) { | ||
this._data[index]++; | ||
} | ||
}; | ||
FastIntArray.prototype.toJSON = function () { | ||
return this._data.slice(0, this.length); | ||
}; | ||
FastIntArray.prototype.get = function (index) { | ||
if (index >= 0 && index < this.length) { | ||
return this._data[index]; | ||
} | ||
return undefined; | ||
}; | ||
FastIntArray.prototype.increment = function (index) { | ||
this._data[index]++; | ||
}; | ||
/* | ||
@@ -318,44 +191,41 @@ Uint32Arrays have an immutable length. This method | ||
*/ | ||
FastIntArray.prototype.grow = function (newLength) { | ||
this._data = grow(this._data, this._length, newLength, this._fillValue); | ||
this._length = newLength; | ||
}; | ||
FastIntArray.prototype.claim = function (count) { | ||
this.length += count; | ||
while (this.length > this._length) { | ||
this.grow(this._length * 2); | ||
} | ||
}; | ||
FastIntArray.prototype.push = function (int) { | ||
var index = this.length++; | ||
if (index === this._length) { | ||
this.grow(this._length * 2); | ||
} | ||
this._data[index] = int; | ||
}; | ||
return FastIntArray; | ||
}()); | ||
}, { | ||
key: 'grow', | ||
value: function grow(newLength) { | ||
var l = this._length; | ||
this._length = newLength; | ||
var data = this._data; | ||
var _d = this._data = new A(newLength); | ||
_d.set(data); | ||
if (this._fill !== 0) { | ||
fill(_d, this._fill, l); | ||
} | ||
} | ||
}, { | ||
key: 'claim', | ||
value: function claim(count) { | ||
this.length += count; | ||
while (this.length > this._length) { | ||
this.grow(this._length * 2); | ||
} | ||
} | ||
}, { | ||
key: 'push', | ||
value: function push(int) { | ||
var index = this.length++; | ||
if (index === this._length) { | ||
this.grow(this._length * 2); | ||
} | ||
this._data[index] = int; | ||
} | ||
}]); | ||
return FastIntArray; | ||
}(); | ||
var DEFAULT_STORE_SIZE = 1e3; | ||
var DEFAULT_NAMESPACE_SIZE = 10; | ||
/** | ||
* Wrapper type around options for `CounterStore`. | ||
* | ||
* Intentionally left private as `CounterStore` | ||
* only used internally when `HeimdallSession` is created. | ||
* | ||
* @class CounterStoreOptions | ||
*/ | ||
var CounterStoreOptions = (function () { | ||
function CounterStoreOptions(storeSize, namespaceAllocation) { | ||
if (storeSize === void 0) { storeSize = DEFAULT_STORE_SIZE; } | ||
if (namespaceAllocation === void 0) { namespaceAllocation = DEFAULT_NAMESPACE_SIZE; } | ||
this.storeSize = storeSize; | ||
this.namespaceAllocation = namespaceAllocation; | ||
} | ||
return CounterStoreOptions; | ||
}()); | ||
// NULL_NUMBER is a number larger than the largest | ||
@@ -366,196 +236,142 @@ // index we are capable of utilizing in the store. | ||
var LOB = (1 << 16) - 1; | ||
var CounterStore = function () { | ||
function CounterStore() { | ||
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
this.options = options; | ||
this.initialized = false; | ||
this._storeInitialized = false; | ||
this._store = null; | ||
this._namespaceCount = 0; | ||
this._config = null; | ||
this._cache = null; | ||
this._labelCache = null; | ||
this._nameCache = null; | ||
} | ||
createClass(CounterStore, [{ | ||
key: 'clean', | ||
value: function clean() { | ||
this._storeInitialized = false; | ||
this._store = null; | ||
this._cache = null; | ||
var CounterStore = (function () { | ||
function CounterStore(options) { | ||
if (options === void 0) { options = new CounterStoreOptions(); } | ||
this.options = options; | ||
this.initialized = false; | ||
this._storeInitialized = false; | ||
this._store = null; | ||
this._namespaceCount = 0; | ||
this._config = null; | ||
this._cache = null; | ||
this._labelCache = null; | ||
this._nameCache = null; | ||
} | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
return { | ||
_namespaceCount: this._namespaceCount, | ||
_config: this._config, | ||
_labelCache: this._labelCache, | ||
_nameCache: this._nameCache, | ||
_store: this._store | ||
}; | ||
} | ||
}, { | ||
key: 'registerNamespace', | ||
value: function registerNamespace(name, labels) { | ||
this._initializeIfNeeded(); | ||
var numCounters = labels.length; | ||
var namespaceIndex = this._namespaceCount++; | ||
var bitNamespaceIndex = namespaceIndex << 16; | ||
var namespace = new EmptyObject(); | ||
// we also generate a map between the counters | ||
// and these labels so that we can reconstruct | ||
// a meaningful structure later. | ||
this._nameCache[namespaceIndex] = name; | ||
this._labelCache[name] = labels; | ||
// grow the existing config and cache to account | ||
// for the new namespace | ||
this._config.push(numCounters); | ||
if (this._cache !== null) { | ||
CounterStore.prototype.clean = function () { | ||
this._storeInitialized = false; | ||
this._store = null; | ||
this._cache = null; | ||
}; | ||
CounterStore.prototype.toJSON = function () { | ||
return { | ||
_namespaceCount: this._namespaceCount, | ||
_config: this._config, | ||
_labelCache: this._labelCache, | ||
_nameCache: this._nameCache, | ||
_store: this._store | ||
}; | ||
}; | ||
CounterStore.fromJSON = function (json) { | ||
var store = new CounterStore(); | ||
store._namespaceCount = json._namespaceCount; | ||
store._labelCache = json._labelCache; | ||
store._nameCache = json._nameCache; | ||
if (json._store) { | ||
store._store = new FastIntArray(json._store.length, json._store); | ||
} | ||
if (json._config) { | ||
store._config = new FastIntArray(json._config.length, json._config); | ||
} | ||
return store; | ||
}; | ||
CounterStore.prototype.registerNamespace = function (name, labels) { | ||
this._initializeIfNeeded(); | ||
var numCounters = labels.length; | ||
var namespaceIndex = this._namespaceCount++; | ||
var bitNamespaceIndex = namespaceIndex << 16; | ||
var namespace = Object.create(null); | ||
// we also generate a map between the counters | ||
// and these labels so that we can reconstruct | ||
// a meaningful structure later. | ||
this._nameCache[namespaceIndex] = name; | ||
this._labelCache[name] = labels; | ||
// grow the existing config and cache to account | ||
// for the new namespace | ||
this._config.push(numCounters); | ||
if (this._cache !== null) { | ||
this._cache = grow(this._cache, namespaceIndex, this._namespaceCount, NULL_NUMBER); | ||
} | ||
for (var i = 0; i < numCounters; i++) { | ||
namespace[labels[i]] = bitNamespaceIndex + i; | ||
} | ||
return namespace; | ||
}; | ||
CounterStore.prototype._initializeIfNeeded = function () { | ||
if (this.initialized === false) { | ||
this._config = new FastIntArray(this.options.namespaceAllocation); | ||
this._labelCache = Object.create(null); | ||
this._nameCache = Object.create(null); | ||
this.initialized = true; | ||
} | ||
}; | ||
CounterStore.prototype.restoreFromCache = function (cache) { | ||
var stats = Object.create(null); | ||
for (var i = 0; i < cache.length; i++) { | ||
if (cache[i] !== NULL_NUMBER) { | ||
var startIndex = cache[i]; | ||
var namespace = this._nameCache[i]; | ||
var counterCount = this._config.get(i); | ||
stats[namespace] = Object.create(null); | ||
for (var j = 0; j < counterCount; j++) { | ||
var storeIndex = startIndex + j; | ||
var label = this._labelCache[namespace][j]; | ||
stats[namespace][label] = this._store.get(storeIndex); | ||
} | ||
} | ||
} | ||
return stats; | ||
}; | ||
CounterStore.prototype.increment = function (counter) { | ||
var namespaceIndex = counter >> 16; | ||
var counterIndex = counter & LOB; | ||
if (this._cache === null) { | ||
this._initializeStoreIfNeeded(); | ||
var a = hasTypedArrays() ? new Uint32Array(this._namespaceCount) : new Array(this._namespaceCount); | ||
this._cache = fill(a, NULL_NUMBER); | ||
} | ||
if (this._cache[namespaceIndex] === NULL_NUMBER) { | ||
var counterCount = this._config.get(namespaceIndex); | ||
this._cache[namespaceIndex] = this._store.length; | ||
this._store.claim(counterCount); | ||
} | ||
var storeIndex = this._cache[namespaceIndex] + counterIndex; | ||
this._store.increment(storeIndex); | ||
}; | ||
CounterStore.prototype._initializeStoreIfNeeded = function () { | ||
if (this._storeInitialized === false) { | ||
this._store = new FastIntArray(this.options.storeSize); | ||
this._storeInitialized = true; | ||
} | ||
}; | ||
CounterStore.prototype.has = function (name) { | ||
return this._labelCache && name in this._labelCache; | ||
}; | ||
CounterStore.prototype.cache = function () { | ||
var cache = this._cache; | ||
this._cache = null; | ||
return cache; | ||
}; | ||
return CounterStore; | ||
}()); | ||
this._cache = new A(this._namespaceCount); | ||
this._cache.set(cache); | ||
this._cache[namespaceIndex] = NULL_NUMBER; | ||
} | ||
for (var i = 0; i < numCounters; i++) { | ||
namespace[labels[i]] = bitNamespaceIndex + i; | ||
} | ||
return namespace; | ||
var Session = (function () { | ||
function HeimdallSession() { | ||
this.init(); | ||
} | ||
}, { | ||
key: '_initializeIfNeeded', | ||
value: function _initializeIfNeeded() { | ||
if (this.initialized === false) { | ||
this._config = new FastIntArray(this.options.namespaceAllocation || DEFAULT_NAMESPACE_SIZE); | ||
this._labelCache = new EmptyObject(); | ||
this._nameCache = new EmptyObject(); | ||
this.initialized = true; | ||
} | ||
} | ||
}, { | ||
key: 'restoreFromCache', | ||
value: function restoreFromCache(cache) { | ||
var stats = new EmptyObject(); | ||
for (var i = 0; i < cache.length; i++) { | ||
if (cache[i] !== NULL_NUMBER) { | ||
var startIndex = cache[i]; | ||
var namespace = this._nameCache[i]; | ||
var counterCount = this._config.get(i); | ||
stats[namespace] = new EmptyObject(); | ||
for (var j = 0; j < counterCount; j++) { | ||
var storeIndex = startIndex + j; | ||
var label = this._labelCache[namespace][j]; | ||
stats[namespace][label] = this._store.get(storeIndex); | ||
} | ||
} | ||
} | ||
return stats; | ||
} | ||
}, { | ||
key: 'increment', | ||
value: function increment(counter) { | ||
var namespaceIndex = counter >> 16; | ||
var counterIndex = counter & LOB; | ||
if (this._cache === null) { | ||
this._initializeStoreIfNeeded(); | ||
this._cache = fill(new A(this._namespaceCount), NULL_NUMBER); | ||
} | ||
if (this._cache[namespaceIndex] === NULL_NUMBER) { | ||
var counterCount = this._config.get(namespaceIndex); | ||
this._cache[namespaceIndex] = this._store.length; | ||
this._store.claim(counterCount); | ||
} | ||
var storeIndex = this._cache[namespaceIndex] + counterIndex; | ||
this._store.increment(storeIndex); | ||
} | ||
}, { | ||
key: '_initializeStoreIfNeeded', | ||
value: function _initializeStoreIfNeeded() { | ||
if (this._storeInitialized === false) { | ||
this._store = new FastIntArray(this.options.storeSize || DEFAULT_STORE_SIZE); | ||
this._storeInitialized = true; | ||
} | ||
} | ||
}, { | ||
key: 'has', | ||
value: function has(name) { | ||
return this._labelCache && name in this._labelCache; | ||
} | ||
}, { | ||
key: 'cache', | ||
value: function cache() { | ||
var cache = this._cache; | ||
this._cache = null; | ||
return cache; | ||
} | ||
}], [{ | ||
key: 'fromJSON', | ||
value: function fromJSON(json) { | ||
var store = new CounterStore(); | ||
store._namespaceCount = json._namespaceCount; | ||
store._labelCache = json._labelCache; | ||
store._nameCache = json._nameCache; | ||
if (json._store) { | ||
store._store = new FastIntArray(json._store.length, json._store); | ||
} | ||
if (json._config) { | ||
store._config = new FastIntArray(json._config.length, json._config); | ||
} | ||
} | ||
}]); | ||
return CounterStore; | ||
}(); | ||
// provides easily interceptable indirection. | ||
var HeimdallSession = function () { | ||
function HeimdallSession() { | ||
this.init(); | ||
} | ||
createClass(HeimdallSession, [{ | ||
key: 'init', | ||
value: function init() { | ||
this.monitors = new CounterStore(); | ||
this.configs = new HashMap(); | ||
this.events = new EventArray(640000 * 4); | ||
} | ||
HeimdallSession.prototype.init = function () { | ||
this.monitors = new CounterStore(); | ||
this.configs = new HashMap(); | ||
this.events = new EventArray(640000 * 4); | ||
}; | ||
// mostly for test helper purposes | ||
HeimdallSession.prototype.reset = function () { | ||
this.monitors.clean(); | ||
this.events.length = 0; | ||
}; | ||
return HeimdallSession; | ||
}()); | ||
}, { | ||
key: 'reset', | ||
value: function reset() { | ||
this.monitors.clean(); | ||
this.events.length = 0; | ||
} | ||
}]); | ||
return HeimdallSession; | ||
}(); | ||
var now = void 0; | ||
var format = void 0; | ||
var ORIGIN_TIME = void 0; | ||
var now; | ||
var format; | ||
var ORIGIN_TIME; | ||
// It turns out to be nicer for perf to bind than to close over the time method | ||
@@ -566,125 +382,128 @@ // however, when testing we need to be able to stub the clock via the global | ||
var IS_TESTING = freeGlobal.IS_HEIMDALL_TEST_ENVIRONMENT; | ||
if ((typeof performance === 'undefined' ? 'undefined' : _typeof(performance)) === 'object' && typeof performance.now === 'function') { | ||
now = IS_TESTING ? function now() { | ||
return performance.now(); | ||
} : performance.now.bind(performance); | ||
format = 'milli'; | ||
} else if (typeof process !== 'undefined' && typeof process.hrtime === 'function') { | ||
now = IS_TESTING ? function now() { | ||
return process.hrtime(); | ||
} : process.hrtime.bind(process); | ||
format = 'hrtime'; | ||
} else { | ||
ORIGIN_TIME = Date.now(); | ||
now = Date.now.bind(Date); | ||
format = 'timestamp'; | ||
if (typeof performance === 'object' && typeof performance.now === 'function') { | ||
now = IS_TESTING ? function now() { return performance.now(); } : performance.now.bind(performance); | ||
format = 'milli'; | ||
} | ||
function normalizeTime(time) { | ||
var format = arguments.length <= 1 || arguments[1] === undefined ? format : arguments[1]; | ||
switch (format) { | ||
case 'milli': | ||
return milliToNano(time); | ||
case 'hrtime': | ||
return timeFromHRTime(time); | ||
case 'timestamp': | ||
return milliToNano(time - ORIGIN_TIME); | ||
default: | ||
throw new Error('Unknown Format'); | ||
} | ||
else if (typeof process !== 'undefined' && typeof process.hrtime === 'function') { | ||
now = IS_TESTING ? function now() { return process.hrtime(); } : process.hrtime.bind(process); | ||
format = 'hrtime'; | ||
} | ||
else { | ||
ORIGIN_TIME = Date.now(); | ||
now = Date.now.bind(Date); | ||
format = 'timestamp'; | ||
} | ||
function normalizeTime(time, optionalFormat) { | ||
if (optionalFormat === void 0) { optionalFormat = format; } | ||
switch (optionalFormat) { | ||
case 'milli': | ||
return milliToNano(time); | ||
case 'hrtime': | ||
return timeFromHRTime(time); | ||
case 'timestamp': | ||
return milliToNano(time - ORIGIN_TIME); | ||
default: | ||
throw new Error('Unknown Format'); | ||
} | ||
} | ||
function milliToNano(time) { | ||
return Math.floor(time * 1e6); | ||
return Math.floor(time * 1e6); | ||
} | ||
function timeFromHRTime(hrtime) { | ||
return hrtime[0] * 1e9 + hrtime[1]; | ||
return hrtime[0] * 1e9 + hrtime[1]; | ||
} | ||
var now$1 = now; | ||
var OP_START = 0; | ||
var OP_STOP = 1; | ||
var OP_RESUME = 2; | ||
var OP_ANNOTATE = 3; | ||
var OpCodes; | ||
(function (OpCodes) { | ||
OpCodes[OpCodes["OP_START"] = 0] = "OP_START"; | ||
OpCodes[OpCodes["OP_STOP"] = 1] = "OP_STOP"; | ||
OpCodes[OpCodes["OP_RESUME"] = 2] = "OP_RESUME"; | ||
OpCodes[OpCodes["OP_ANNOTATE"] = 3] = "OP_ANNOTATE"; | ||
})(OpCodes || (OpCodes = {})); | ||
var OpCodes$1 = OpCodes; | ||
var Heimdall = function () { | ||
function Heimdall(session) { | ||
if (arguments.length < 1) { | ||
this._session = new HeimdallSession(); | ||
this.start('session-root'); | ||
} else { | ||
this._session = session; | ||
var VERSION = '0.3.3'; | ||
var Heimdall = (function () { | ||
function Heimdall(session) { | ||
if (arguments.length < 1) { | ||
this._session = new Session(); | ||
this.start('session-root'); | ||
} | ||
else { | ||
this._session = session; | ||
} | ||
} | ||
} | ||
createClass(Heimdall, [{ | ||
key: '_retrieveCounters', | ||
value: function _retrieveCounters() { | ||
return this._monitors.cache(); | ||
} | ||
}, { | ||
key: 'start', | ||
value: function start(name) { | ||
return this._session.events.push(OP_START, name, now$1(), this._retrieveCounters()); | ||
} | ||
}, { | ||
key: 'stop', | ||
value: function stop(token) { | ||
this._session.events.push(OP_STOP, token, now$1(), this._retrieveCounters()); | ||
} | ||
}, { | ||
key: 'resume', | ||
value: function resume(token) { | ||
this._session.events.push(OP_RESUME, token, now$1(), this._retrieveCounters()); | ||
} | ||
}, { | ||
key: 'annotate', | ||
value: function annotate(info) { | ||
// This has the side effect of making events heterogenous, as info is an object | ||
// while counters will always be `null` or an `Array` | ||
this._session.events.push(OP_ANNOTATE, NULL_NUMBER, NULL_NUMBER, info); | ||
} | ||
}, { | ||
key: 'hasMonitor', | ||
value: function hasMonitor(name) { | ||
return !!this._monitors.has(name); | ||
} | ||
}, { | ||
key: 'registerMonitor', | ||
value: function registerMonitor(name) { | ||
if (name === 'own' || name === 'time') { | ||
throw new Error('Cannot register monitor at namespace "' + name + '". "own" and "time" are reserved'); | ||
} | ||
if (this.hasMonitor(name)) { | ||
throw new Error('A monitor for "' + name + '" is already registered"'); | ||
} | ||
for (var _len = arguments.length, keys = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
keys[_key - 1] = arguments[_key]; | ||
} | ||
return this._monitors.registerNamespace(name, keys); | ||
} | ||
}, { | ||
key: 'increment', | ||
value: function increment(token) { | ||
this._session.monitors.increment(token); | ||
} | ||
}, { | ||
key: 'configFor', | ||
value: function configFor(name) { | ||
var config = this._session.configs.get(name); | ||
if (!config) { | ||
config = new EmptyObject(); | ||
this._session.configs.set(name, config); | ||
} | ||
return config; | ||
} | ||
Object.defineProperty(Heimdall, "VERSION", { | ||
get: function () { | ||
return VERSION; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(Heimdall.prototype, "VERSION", { | ||
get: function () { | ||
return VERSION; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(Heimdall.prototype, "_monitors", { | ||
get: function () { | ||
return this._session.monitors; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(Heimdall.prototype, "_events", { | ||
get: function () { | ||
return this._session.events; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Heimdall.prototype._retrieveCounters = function () { | ||
return this._monitors.cache(); | ||
}; | ||
Heimdall.prototype.start = function (name) { | ||
return this._session.events.push(OpCodes$1.OP_START, name, now$1(), this._retrieveCounters()); | ||
}; | ||
Heimdall.prototype.stop = function (token) { | ||
this._session.events.push(OpCodes$1.OP_STOP, token, now$1(), this._retrieveCounters()); | ||
}; | ||
Heimdall.prototype.resume = function (token) { | ||
this._session.events.push(OpCodes$1.OP_RESUME, token, now$1(), this._retrieveCounters()); | ||
}; | ||
Heimdall.prototype.annotate = function (info) { | ||
// This has the side effect of making events heterogenous, as info is an object | ||
// while counters will always be `null` or an `Array` | ||
this._session.events.push(OpCodes$1.OP_ANNOTATE, NULL_NUMBER, NULL_NUMBER, info); | ||
}; | ||
Heimdall.prototype.hasMonitor = function (name) { | ||
return !!this._monitors.has(name); | ||
}; | ||
Heimdall.prototype.registerMonitor = function (name) { | ||
var keys = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
keys[_i - 1] = arguments[_i]; | ||
} | ||
if (name === 'own' || name === 'time') { | ||
throw new Error('Cannot register monitor at namespace "' + name + '". "own" and "time" are reserved'); | ||
} | ||
if (this.hasMonitor(name)) { | ||
throw new Error('A monitor for "' + name + '" is already registered"'); | ||
} | ||
return this._monitors.registerNamespace(name, keys); | ||
}; | ||
Heimdall.prototype.increment = function (token) { | ||
this._session.monitors.increment(token); | ||
}; | ||
Heimdall.prototype.configFor = function (name) { | ||
var config = this._session.configs.get(name); | ||
if (!config) { | ||
config = Object.create(null); | ||
this._session.configs.set(name, config); | ||
} | ||
return config; | ||
}; | ||
/* | ||
@@ -695,260 +514,200 @@ Ideally, this method should only be used for serializing | ||
*/ | ||
Heimdall.prototype.toJSON = function () { | ||
return { | ||
heimdallVersion: VERSION, | ||
format, | ||
monitors: this._monitors.toJSON(), | ||
events: this._events.toJSON(), | ||
serializationTime: now$1() | ||
}; | ||
}; | ||
Heimdall.prototype.toString = function () { | ||
return JSON.stringify(this.toJSON()); | ||
}; | ||
return Heimdall; | ||
}()); | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
return { | ||
format: format, | ||
monitors: this._monitors.toJSON(), | ||
events: this._events.toJSON(), | ||
serializationTime: now$1() | ||
}; | ||
var HeimdallNode = (function () { | ||
function HeimdallNode(name, id) { | ||
this._id = id; | ||
this.parent = null; | ||
this.resumeNode = null; | ||
this.name = name; | ||
this.stopped = false; | ||
this.leaves = []; | ||
this.nodes = []; | ||
this.children = []; | ||
} | ||
}, { | ||
key: 'toString', | ||
value: function toString() { | ||
return JSON.stringify(this.toJSON()); | ||
} | ||
}, { | ||
key: '_monitors', | ||
get: function get() { | ||
return this._session.monitors; | ||
} | ||
}, { | ||
key: '_events', | ||
get: function get() { | ||
return this._session.events; | ||
} | ||
}]); | ||
return Heimdall; | ||
}(); | ||
Object.defineProperty(HeimdallNode.prototype, "stats", { | ||
get: function () { | ||
var own = { | ||
selfTime: 0, | ||
duration: 0, | ||
startTime: this.leaves[0].startTime, | ||
endTime: this.leaves[this.leaves.length - 1].endTime | ||
}; | ||
own.duration = own.endTime - own.startTime; | ||
var counters = []; | ||
var annotations = []; | ||
var stats = { | ||
self: own | ||
}; | ||
this.forEachLeaf(function (leaf) { | ||
own.selfTime += leaf.selfTime; | ||
annotations.push(leaf.annotations); | ||
for (var namespace in leaf.counters) { | ||
var value = leaf.counters[namespace]; | ||
if (!stats.hasOwnProperty(namespace)) { | ||
stats[namespace] = value; | ||
} | ||
else { | ||
for (var label in value) { | ||
stats[namespace][label] += value[label]; | ||
} | ||
} | ||
} | ||
counters.push(leaf.counters); | ||
}); | ||
return stats; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
HeimdallNode.prototype.stop = function () { | ||
if (this.stopped === true) { | ||
throw new Error('Cannot Stop node, already stopped!'); | ||
} | ||
this.stopped = true; | ||
}; | ||
HeimdallNode.prototype.resume = function (resumeNode) { | ||
if (!this.stopped) { | ||
throw new Error('Cannot Resume node, already running!'); | ||
} | ||
this.resumeNode = resumeNode; | ||
this.stopped = false; | ||
}; | ||
HeimdallNode.prototype.addLeaf = function (leaf) { | ||
leaf.owner = this; | ||
this.leaves.push(leaf); | ||
this.children.push(leaf); | ||
}; | ||
HeimdallNode.prototype.addNode = function (node) { | ||
if (node.parent) { | ||
throw new Error("Cannot set parent of node '" + node.name + "', node already has a parent!"); | ||
} | ||
node.parent = this; | ||
node.resumeNode = this; | ||
this.nodes.push(node); | ||
this.children.push(node); | ||
}; | ||
Object.defineProperty(HeimdallNode.prototype, "isRoot", { | ||
get: function () { | ||
return this.parent === null; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
HeimdallNode.prototype.visitPreOrder = function (cb) { | ||
cb(this); | ||
for (var i = 0; i < this.nodes.length; i++) { | ||
this.nodes[i].visitPreOrder(cb); | ||
} | ||
}; | ||
HeimdallNode.prototype.visitPostOrder = function (cb) { | ||
for (var i = 0; i < this.nodes.length; i++) { | ||
this.nodes[i].visitPostOrder(cb); | ||
} | ||
cb(this); | ||
}; | ||
HeimdallNode.prototype.forEachNode = function (cb) { | ||
for (var i = 0; i < this.nodes.length; ++i) { | ||
cb(this.nodes[i]); | ||
} | ||
}; | ||
HeimdallNode.prototype.forEachLeaf = function (cb) { | ||
for (var i = 0; i < this.leaves.length; ++i) { | ||
cb(this.leaves[i]); | ||
} | ||
}; | ||
HeimdallNode.prototype.forEachChild = function (cb) { | ||
for (var i = 0; i < this.children.length; ++i) { | ||
cb(this.children[i]); | ||
} | ||
}; | ||
HeimdallNode.prototype.toJSON = function () { | ||
return { | ||
_id: this._id, | ||
name: this.name, | ||
leaves: this.leaves.map(function (leaf) { return leaf.toJSON(); }), | ||
nodes: this.nodes.map(function (child) { return child._id; }), | ||
children: this.children.map(function (child) { return child._id; }) | ||
}; | ||
}; | ||
HeimdallNode.prototype.toJSONSubgraph = function () { | ||
var nodes = []; | ||
this.visitPreOrder(function (node) { return nodes.push(node.toJSON()); }); | ||
return nodes; | ||
}; | ||
return HeimdallNode; | ||
}()); | ||
var HeimdallNode = function () { | ||
function HeimdallNode(name, id) { | ||
this._id = id; | ||
this.parent = null; | ||
this.resumeNode = null; | ||
this.name = name; | ||
this.stopped = false; | ||
this.leaves = []; | ||
this.nodes = []; | ||
this.children = []; | ||
} | ||
createClass(HeimdallNode, [{ | ||
key: 'stop', | ||
value: function stop() { | ||
if (this.stopped === true) { | ||
throw new Error('Cannot Stop node, already stopped!'); | ||
} | ||
this.stopped = true; | ||
var HeimdallLeaf = (function () { | ||
function HeimdallLeaf() { | ||
// set on start | ||
this._id = null; | ||
this.owner = null; | ||
this.previousOp = null; | ||
this.startTime = 0; | ||
// set on annotate | ||
this.annotations = null; | ||
// set on stop | ||
this.nextOp = null; | ||
this.endTime = 0; | ||
this.counters = null; | ||
this.name = null; | ||
} | ||
}, { | ||
key: 'resume', | ||
value: function resume(resumeNode) { | ||
if (!this.stopped) { | ||
throw new Error('Cannot Resume node, already running!'); | ||
} | ||
this.resumeNode = resumeNode; | ||
this.stopped = false; | ||
} | ||
}, { | ||
key: 'addLeaf', | ||
value: function addLeaf(leaf) { | ||
leaf.owner = this; | ||
this.leaves.push(leaf); | ||
this.children.push(leaf); | ||
} | ||
}, { | ||
key: 'addNode', | ||
value: function addNode(node) { | ||
if (node.parent) { | ||
throw new Error('Cannot set parent of node \'' + node.name + '\', node already has a parent!'); | ||
} | ||
node.parent = this; | ||
node.resumeNode = this; | ||
this.nodes.push(node); | ||
this.children.push(node); | ||
} | ||
}, { | ||
key: 'visitPreOrder', | ||
value: function visitPreOrder(cb) { | ||
cb(this); | ||
for (var i = 0; i < this.nodes.length; i++) { | ||
this.nodes[i].visitPreOrder(cb); | ||
} | ||
} | ||
}, { | ||
key: 'visitPostOrder', | ||
value: function visitPostOrder(cb) { | ||
for (var i = 0; i < this.nodes.length; i++) { | ||
this.nodes[i].visitPostOrder(cb); | ||
} | ||
cb(this); | ||
} | ||
}, { | ||
key: 'forEachNode', | ||
value: function forEachNode(cb) { | ||
for (var i = 0; i < this.nodes.length; ++i) { | ||
cb(this.nodes[i]); | ||
} | ||
} | ||
}, { | ||
key: 'forEachLeaf', | ||
value: function forEachLeaf(cb) { | ||
for (var i = 0; i < this.leaves.length; ++i) { | ||
cb(this.leaves[i]); | ||
} | ||
} | ||
}, { | ||
key: 'forEachChild', | ||
value: function forEachChild(cb) { | ||
for (var i = 0; i < this.children.length; ++i) { | ||
cb(this.children[i]); | ||
} | ||
} | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
return { | ||
_id: this._id, | ||
name: this.name, | ||
leaves: this.leaves.map(function (leaf) { | ||
return leaf.toJSON(); | ||
}), | ||
nodes: this.nodes.map(function (child) { | ||
return child._id; | ||
}), | ||
children: this.children.map(function (child) { | ||
return child._id; | ||
}) | ||
}; | ||
} | ||
}, { | ||
key: 'toJSONSubgraph', | ||
value: function toJSONSubgraph() { | ||
var nodes = []; | ||
this.visitPreOrder(function (node) { | ||
return nodes.push(node.toJSON()); | ||
}); | ||
return nodes; | ||
} | ||
}, { | ||
key: 'stats', | ||
get: function get() { | ||
var own = { | ||
selfTime: 0, | ||
duration: 0, | ||
startTime: this.leaves[0].startTime, | ||
endTime: this.leaves[this.leaves.length - 1].endTime | ||
}; | ||
own.duration = own.endTime - own.startTime; | ||
var counters = []; | ||
var annotations = []; | ||
var stats = { | ||
self: own | ||
}; | ||
this.forEachLeaf(function (leaf) { | ||
own.selfTime += leaf.selfTime; | ||
annotations.push(leaf.annotations); | ||
for (var namespace in leaf.counters) { | ||
var value = leaf.counters[namespace]; | ||
if (!stats.hasOwnProperty(namespace)) { | ||
stats[namespace] = value; | ||
} else { | ||
for (var label in value) { | ||
stats[namespace][label] += value[label]; | ||
} | ||
} | ||
Object.defineProperty(HeimdallLeaf.prototype, "selfTime", { | ||
get: function () { | ||
return this.endTime - this.startTime; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(HeimdallLeaf.prototype, "isStopped", { | ||
get: function () { | ||
return this.endTime !== 0; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
HeimdallLeaf.prototype.annotate = function (annotation) { | ||
if (this.annotations === null) { | ||
this.annotations = []; | ||
} | ||
this.annotations.push(annotation); | ||
}; | ||
HeimdallLeaf.prototype.start = function (owner, previousOp, time) { | ||
this.owner = owner; | ||
this.previousOp = previousOp; | ||
this.startTime = time; | ||
}; | ||
HeimdallLeaf.prototype.stop = function (nextOp, time, counters) { | ||
this.nextOp = nextOp; | ||
this.endTime = time; | ||
this.counters = counters; | ||
this._id = this.name = "[" + this.owner.name + "]#" + this.previousOp + ":" + nextOp; | ||
}; | ||
HeimdallLeaf.prototype.toJSON = function () { | ||
return { | ||
_id: this._id, | ||
name: this.name, | ||
startTime: this.startTime, | ||
endTime: this.endTime, | ||
counters: this.counters, | ||
annotations: this.annotations | ||
}; | ||
}; | ||
return HeimdallLeaf; | ||
}()); | ||
counters.push(leaf.counters); | ||
}); | ||
return stats; | ||
} | ||
}, { | ||
key: 'isRoot', | ||
get: function get() { | ||
return this.parent === null; | ||
} | ||
}]); | ||
return HeimdallNode; | ||
}(); | ||
var HeimdallLeaf = function () { | ||
function HeimdallLeaf() { | ||
// set on start | ||
this._id = null; | ||
this.owner = null; | ||
this.previousOp = null; | ||
this.startTime = 0; | ||
// set on annotate | ||
this.annotations = null; | ||
// set on stop | ||
this.nextOp = null; | ||
this.endTime = 0; | ||
this.counters = null; | ||
this.name = null; | ||
} | ||
createClass(HeimdallLeaf, [{ | ||
key: "annotate", | ||
value: function annotate(annotation) { | ||
if (this.annotations === null) { | ||
this.annotations = []; | ||
} | ||
this.annotations.push(annotation); | ||
} | ||
}, { | ||
key: "start", | ||
value: function start(owner, previousOp, time) { | ||
this.owner = owner; | ||
this.previousOp = previousOp; | ||
this.startTime = time; | ||
} | ||
}, { | ||
key: "stop", | ||
value: function stop(nextOp, time, counters) { | ||
this.nextOp = nextOp; | ||
this.endTime = time; | ||
this.counters = counters; | ||
this._id = this.name = "[" + this.owner.name + "]#" + this.previousOp + ":" + nextOp; | ||
} | ||
}, { | ||
key: "toJSON", | ||
value: function toJSON() { | ||
return { | ||
_id: this._id, | ||
name: this.name, | ||
startTime: this.startTime, | ||
endTime: this.endTime, | ||
counters: this.counters, | ||
annotations: this.annotations | ||
}; | ||
} | ||
}, { | ||
key: "selfTime", | ||
get: function get() { | ||
return this.endTime - this.startTime; | ||
} | ||
}, { | ||
key: "isStopped", | ||
get: function get() { | ||
return this.endTime !== 0; | ||
} | ||
}]); | ||
return HeimdallLeaf; | ||
}(); | ||
/* | ||
@@ -982,301 +741,240 @@ Example Event Timeline and tree reconstruction | ||
*/ | ||
function statsFromCounters(counterStore, counterCache) { | ||
if (!counterStore || !counterCache) { | ||
return null; | ||
} | ||
return counterStore.restoreFromCache(counterCache); | ||
if (!counterStore || !counterCache) { | ||
return null; | ||
} | ||
return counterStore.restoreFromCache(counterCache); | ||
} | ||
var HeimdallTree = function () { | ||
function HeimdallTree(heimdall, lastKnownTime) { | ||
this._heimdall = heimdall; | ||
this.root = null; | ||
this.format = heimdall && heimdall._timeFormat ? heimdall._timeFormat : format; | ||
this.lastKnownTime = lastKnownTime; | ||
} | ||
createClass(HeimdallTree, [{ | ||
key: '_createLeaf', | ||
value: function _createLeaf(currentNode, time) { | ||
var leaf = new HeimdallLeaf(); | ||
leaf.start(currentNode, currentNode.name, time); | ||
currentNode.addLeaf(leaf); | ||
return leaf; | ||
var HeimdallTree = (function () { | ||
function HeimdallTree(heimdall, lastKnownTime) { | ||
this._heimdall = heimdall; | ||
this.root = null; | ||
this.format = heimdall && heimdall._timeFormat ? heimdall._timeFormat : format; | ||
this.lastKnownTime = lastKnownTime; | ||
} | ||
}, { | ||
key: '_chainLeaf', | ||
value: function _chainLeaf(currentNode, incomingNode, time) { | ||
var leaf = new HeimdallLeaf(); | ||
leaf.start(currentNode, incomingNode.name, time); | ||
currentNode.addLeaf(leaf); | ||
return leaf; | ||
} | ||
}, { | ||
key: '_createNode', | ||
value: function _createNode(nodeName, index, nodeMap) { | ||
var node = new HeimdallNode(nodeName, index); | ||
nodeMap.set(index, node); | ||
return node; | ||
} | ||
}, { | ||
key: '_chainNode', | ||
value: function _chainNode(currentNode, nodeName, index, nodeMap) { | ||
var node = this._createNode(nodeName, index, nodeMap); | ||
currentNode.addNode(node); | ||
return node; | ||
} | ||
}, { | ||
key: 'construct', | ||
value: function construct() { | ||
var _this = this; | ||
var events = this._heimdall._events; | ||
var currentLeaf = null; | ||
var currentNode = null; | ||
var nodeMap = new HashMap(); | ||
var openNodes = []; | ||
var node = void 0; | ||
var format = this.format; | ||
var counterStore = this._heimdall._monitors; | ||
var stopTime = this.lastKnownTime ? normalizeTime(this.lastKnownTime) : now$1(); | ||
var pageRootIndex = events._length + 1; | ||
currentNode = this.root = this._createNode('page-root', pageRootIndex, nodeMap); | ||
currentLeaf = this._createLeaf(currentNode, 0); | ||
openNodes.push(node); | ||
events.forEach(function (_ref, i) { | ||
var _ref2 = slicedToArray(_ref, 4); | ||
var op = _ref2[0]; | ||
var name = _ref2[1]; | ||
var time = _ref2[2]; | ||
var counters = _ref2[3]; | ||
if (op !== OP_ANNOTATE) { | ||
time = normalizeTime(time, format); | ||
counters = statsFromCounters(counterStore, counters); | ||
} | ||
switch (op) { | ||
case OP_START: | ||
currentNode = _this._chainNode(currentNode, name, i, nodeMap); | ||
openNodes.push(currentNode); | ||
if (currentLeaf) { | ||
currentLeaf.stop(name, time, counters); | ||
HeimdallTree.fromJSON = function (json) { | ||
var events = json.events || []; | ||
var heimdall = { | ||
_timeFormat: json.format || format, | ||
_events: new EventArray(events.length, events), | ||
_monitors: CounterStore.fromJSON(json.monitors) | ||
}; | ||
return new HeimdallTree(heimdall, json.serializationTime); | ||
}; | ||
Object.defineProperty(HeimdallTree.prototype, "path", { | ||
// primarily a test helper, you can get this at any time | ||
// to get an array representing the path of open node names | ||
// from "root" to the last open node. | ||
get: function () { | ||
var events = this._heimdall._events; | ||
var root = new HeimdallNode('root', 1e9); | ||
var currentNode = root; | ||
var nodeMap = new HashMap(); | ||
var node; | ||
var top; | ||
var path = []; | ||
events.forEach(function (_a, i) { | ||
var op = _a[0], name = _a[1]; | ||
switch (op) { | ||
case OpCodes$1.OP_START: | ||
node = new HeimdallNode(name, i); | ||
nodeMap.set(i, node); | ||
currentNode.addNode(node); | ||
currentNode = node; | ||
break; | ||
case OpCodes$1.OP_STOP: | ||
node = nodeMap.get(name); | ||
if (name !== currentNode._id) { | ||
// potentially throw the correct error (already stopped) | ||
if (node) { | ||
node.stop(); | ||
} | ||
else { | ||
throw new Error("Cannot Stop, Attempting to stop a non-existent node!"); | ||
} | ||
throw new Error("Cannot Stop, Attempting to stop a node with an active child!"); | ||
} | ||
currentNode.stop(); | ||
currentNode = currentNode.resumeNode; | ||
break; | ||
case OpCodes$1.OP_RESUME: | ||
node = nodeMap.get(name); | ||
node.resume(currentNode); | ||
currentNode = node; | ||
break; | ||
default: | ||
throw new Error("HeimdallTree encountered an unknown OpCode '" + op + "' during path construction."); | ||
} | ||
}); | ||
top = currentNode; | ||
while (top !== undefined && top !== root) { | ||
path.unshift(top.name); | ||
top = top.parent; | ||
} | ||
currentLeaf = _this._createLeaf(currentNode, time); | ||
break; | ||
case OP_STOP: | ||
node = nodeMap.get(name); | ||
if (name !== currentNode._id) { | ||
// potentially throw the correct error (already stopped) | ||
if (node) { | ||
node.stop(); | ||
} else { | ||
throw new Error("Cannot Stop, Attempting to stop a non-existent node!"); | ||
} | ||
throw new Error("Cannot Stop, Attempting to stop a node with an active child!"); | ||
return path; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(HeimdallTree.prototype, "stack", { | ||
// primarily a test helper, you can get this at any time | ||
// to get an array representing the "stack" of open node names. | ||
get: function () { | ||
var events = this._heimdall._events; | ||
var stack = []; | ||
var nodeMap = new HashMap(); | ||
events.forEach(function (_a, i) { | ||
var op = _a[0], name = _a[1]; | ||
if (op === OpCodes$1.OP_START) { | ||
stack.push(name); | ||
nodeMap.set(i, name); | ||
} | ||
else if (op === OpCodes$1.OP_RESUME) { | ||
var n = nodeMap.get(name); | ||
stack.push(n); | ||
} | ||
else if (op === OpCodes$1.OP_STOP) { | ||
var n = nodeMap.get(name); | ||
if (n !== stack[stack.length - 1]) { | ||
throw new Error('Invalid Stack!'); | ||
} | ||
stack.pop(); | ||
} | ||
}); | ||
return stack; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
HeimdallTree.prototype._createLeaf = function (currentNode, time) { | ||
var leaf = new HeimdallLeaf(); | ||
leaf.start(currentNode, currentNode.name, time); | ||
currentNode.addLeaf(leaf); | ||
return leaf; | ||
}; | ||
HeimdallTree.prototype._chainLeaf = function (currentNode, incomingNode, time) { | ||
var leaf = new HeimdallLeaf(); | ||
leaf.start(currentNode, incomingNode.name, time); | ||
currentNode.addLeaf(leaf); | ||
return leaf; | ||
}; | ||
HeimdallTree.prototype._createNode = function (nodeName, index, nodeMap) { | ||
var node = new HeimdallNode(nodeName, index); | ||
nodeMap.set(index, node); | ||
return node; | ||
}; | ||
HeimdallTree.prototype._chainNode = function (currentNode, nodeName, index, nodeMap) { | ||
var node = this._createNode(nodeName, index, nodeMap); | ||
currentNode.addNode(node); | ||
return node; | ||
}; | ||
HeimdallTree.prototype.construct = function () { | ||
var _this = this; | ||
var events = this._heimdall._events; | ||
var currentLeaf = null; | ||
var currentNode = null; | ||
var nodeMap = new HashMap(); | ||
var openNodes = []; | ||
var node; | ||
var format = this.format; | ||
var counterStore = this._heimdall._monitors; | ||
var stopTime = this.lastKnownTime ? normalizeTime(this.lastKnownTime) : now$1(); | ||
var pageRootIndex = events._length + 1; | ||
currentNode = this.root = this._createNode('page-root', pageRootIndex, nodeMap); | ||
currentLeaf = this._createLeaf(currentNode, 0); | ||
openNodes.push(node); | ||
events.forEach(function (_a, i) { | ||
var op = _a[0], name = _a[1], time = _a[2], counters = _a[3]; | ||
if (op !== OpCodes$1.OP_ANNOTATE) { | ||
time = normalizeTime(time, format); | ||
counters = statsFromCounters(counterStore, counters); | ||
} | ||
switch (op) { | ||
case OpCodes$1.OP_START: | ||
currentNode = _this._chainNode(currentNode, name, i, nodeMap); | ||
openNodes.push(currentNode); | ||
if (currentLeaf) { | ||
currentLeaf.stop(name, time, counters); | ||
} | ||
currentLeaf = _this._createLeaf(currentNode, time); | ||
break; | ||
case OpCodes$1.OP_STOP: | ||
node = nodeMap.get(name); | ||
if (name !== currentNode._id) { | ||
// potentially throw the correct error (already stopped) | ||
if (node) { | ||
node.stop(); | ||
} | ||
else { | ||
throw new Error("Cannot Stop, Attempting to stop a non-existent node!"); | ||
} | ||
throw new Error("Cannot Stop, Attempting to stop a node with an active child!"); | ||
} | ||
currentNode.stop(); | ||
openNodes.splice(openNodes.indexOf(currentNode), 1); | ||
currentNode = currentNode.resumeNode; | ||
currentLeaf.stop(node.name, time, counters); | ||
currentLeaf = _this._chainLeaf(currentNode, node, time); | ||
break; | ||
case OpCodes$1.OP_RESUME: | ||
node = nodeMap.get(name); | ||
node.resume(currentNode); | ||
currentNode = node; | ||
openNodes.push(node); | ||
if (currentLeaf) { | ||
currentLeaf.stop(node.name, time, counters); | ||
} | ||
currentLeaf = _this._chainLeaf(currentNode, node, time); | ||
break; | ||
case OpCodes$1.OP_ANNOTATE: | ||
currentLeaf.annotate(counters); | ||
break; | ||
default: | ||
throw new Error("HeimdallTree encountered an unknown OpCode '" + op + "' during tree construction."); | ||
} | ||
}); | ||
while (currentNode && !currentNode.stopped) { | ||
var name = currentNode.name; | ||
var node_1 = currentNode; | ||
currentNode.stop(); | ||
openNodes.splice(openNodes.indexOf(currentNode), 1); | ||
currentNode = currentNode.resumeNode; | ||
currentLeaf.stop(node.name, time, counters); | ||
currentLeaf = _this._chainLeaf(currentNode, node, time); | ||
break; | ||
case OP_RESUME: | ||
node = nodeMap.get(name); | ||
node.resume(currentNode); | ||
currentNode = node; | ||
openNodes.push(node); | ||
if (currentLeaf) { | ||
currentLeaf.stop(node.name, time, counters); | ||
currentLeaf.stop(node_1.name, stopTime, null); | ||
if (currentNode) { | ||
currentLeaf = this._chainLeaf(currentNode, node_1, stopTime); | ||
} | ||
currentLeaf = _this._chainLeaf(currentNode, node, time); | ||
break; | ||
case OP_ANNOTATE: | ||
currentLeaf.annotate(counters); | ||
break; | ||
default: | ||
throw new Error('HeimdallTree encountered an unknown OpCode \'' + op + '\' during tree construction.'); | ||
} | ||
}); | ||
while (currentNode && !currentNode.stopped) { | ||
var name = currentNode.name; | ||
var _node = currentNode; | ||
currentNode.stop(); | ||
currentNode = currentNode.resumeNode; | ||
currentLeaf.stop(_node.name, stopTime, null); | ||
if (currentNode) { | ||
currentLeaf = this._chainLeaf(currentNode, _node, stopTime); | ||
}; | ||
HeimdallTree.prototype.toJSON = function () { | ||
if (!this.root) { | ||
this.construct(); | ||
} | ||
} | ||
} | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
if (!this.root) { | ||
this.construct(); | ||
} | ||
return { nodes: this.root.toJSONSubgraph() }; | ||
} | ||
}, { | ||
key: 'visitPreOrder', | ||
value: function visitPreOrder(cb) { | ||
return this.root.visitPreOrder(cb); | ||
} | ||
}, { | ||
key: 'visitPostOrder', | ||
value: function visitPostOrder(cb) { | ||
return this.root.visitPostOrder(cb); | ||
} | ||
}, { | ||
key: 'path', | ||
return { | ||
heimdallVersion: '0.3.3', | ||
nodes: this.root.toJSONSubgraph() | ||
}; | ||
}; | ||
HeimdallTree.prototype.visitPreOrder = function (cb) { | ||
this.root.visitPreOrder(cb); | ||
}; | ||
HeimdallTree.prototype.visitPostOrder = function (cb) { | ||
this.root.visitPostOrder(cb); | ||
}; | ||
return HeimdallTree; | ||
}()); | ||
// primarily a test helper, you can get this at any time | ||
// to get an array representing the path of open node names | ||
// from "root" to the last open node. | ||
get: function get() { | ||
var events = this._heimdall._events; | ||
var root = new HeimdallNode('root', 1e9); | ||
var currentNode = root; | ||
var nodeMap = new HashMap(); | ||
var node = void 0; | ||
var top = void 0; | ||
var path = []; | ||
events.forEach(function (_ref3, i) { | ||
var _ref4 = slicedToArray(_ref3, 2); | ||
var op = _ref4[0]; | ||
var name = _ref4[1]; | ||
switch (op) { | ||
case OP_START: | ||
node = new HeimdallNode(name, i); | ||
nodeMap.set(i, node); | ||
currentNode.addNode(node); | ||
currentNode = node; | ||
break; | ||
case OP_STOP: | ||
node = nodeMap.get(name); | ||
if (name !== currentNode._id) { | ||
// potentially throw the correct error (already stopped) | ||
if (node) { | ||
node.stop(); | ||
} else { | ||
throw new Error("Cannot Stop, Attempting to stop a non-existent node!"); | ||
} | ||
throw new Error("Cannot Stop, Attempting to stop a node with an active child!"); | ||
} | ||
currentNode.stop(); | ||
currentNode = currentNode.resumeNode; | ||
break; | ||
case OP_RESUME: | ||
node = nodeMap.get(name); | ||
node.resume(currentNode); | ||
currentNode = node; | ||
break; | ||
default: | ||
throw new Error('HeimdallTree encountered an unknown OpCode \'' + op + '\' during path construction.'); | ||
} | ||
}); | ||
top = currentNode; | ||
while (top !== undefined && top !== root) { | ||
path.unshift(top.name); | ||
top = top.parent; | ||
} | ||
return path; | ||
function setupSession(global) { | ||
// The name of the property encodes the session/node compatibilty version | ||
if (!global._heimdall_session_3) { | ||
global._heimdall_session_3 = new Session(); | ||
} | ||
// primarily a test helper, you can get this at any time | ||
// to get an array representing the "stack" of open node names. | ||
}, { | ||
key: 'stack', | ||
get: function get() { | ||
var events = this._heimdall._events; | ||
var stack = []; | ||
var nodeMap = new HashMap(); | ||
events.forEach(function (_ref5, i) { | ||
var _ref6 = slicedToArray(_ref5, 2); | ||
var op = _ref6[0]; | ||
var name = _ref6[1]; | ||
if (op === OP_START) { | ||
stack.push(name); | ||
nodeMap.set(i, name); | ||
} else if (op === OP_RESUME) { | ||
var n = nodeMap.get(name); | ||
stack.push(n); | ||
} else if (op === OP_STOP) { | ||
var _n = nodeMap.get(name); | ||
if (_n !== stack[stack.length - 1]) { | ||
throw new Error('Invalid Stack!'); | ||
} | ||
stack.pop(); | ||
} | ||
}); | ||
return stack; | ||
} | ||
}], [{ | ||
key: 'fromJSON', | ||
value: function fromJSON(json) { | ||
var events = json.events || []; | ||
var heimdall = { | ||
_timeFormat: json.format || format, | ||
_events: new EventArray(events.length, events), | ||
_monitors: CounterStore.fromJSON(json.monitors) | ||
}; | ||
return new HeimdallTree(heimdall, json.serializationTime); | ||
} | ||
}]); | ||
return HeimdallTree; | ||
}(); | ||
function setupSession(global) { | ||
// The name of the property encodes the session/node compatibilty version | ||
if (!global._heimdall_session_3) { | ||
global._heimdall_session_3 = new HeimdallSession(); | ||
} | ||
} | ||
setupSession(process); | ||
var defaultHeimdall = new Heimdall(process._heimdall_session_3); | ||
defaultHeimdall.now = now$1; | ||
defaultHeimdall.Heimdall = Heimdall; | ||
defaultHeimdall.Session = Session; | ||
defaultHeimdall._Tree = HeimdallTree; | ||
defaultHeimdall._Node = HeimdallNode; | ||
Heimdall.now = now$1; | ||
Heimdall.Session = HeimdallSession; | ||
Heimdall.Tree = HeimdallTree; | ||
Heimdall.Node = HeimdallNode; | ||
var index = new Heimdall(process._heimdall_session_3); | ||
module.exports = index; | ||
module.exports = defaultHeimdall; |
@@ -1,256 +0,143 @@ | ||
// All Credit for this goes to the Ember.js Core Team | ||
// This exists because `Object.create(null)` is absurdly slow compared | ||
// to `new EmptyObject()`. In either case, you want a null prototype | ||
// when you're treating the object instances as arbitrary dictionaries | ||
// and don't want your keys colliding with build-in methods on the | ||
// default object prototype. | ||
var proto = Object.create(null, { | ||
// without this, we will always still end up with (new | ||
// EmptyObject()).constructor === Object | ||
constructor: { | ||
value: undefined, | ||
enumerable: false, | ||
writable: true | ||
} | ||
}); | ||
function EmptyObject() {} | ||
EmptyObject.prototype = proto; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { | ||
return typeof obj; | ||
} : function (obj) { | ||
return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; | ||
}; | ||
var createClass = function () { | ||
function defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
return function (Constructor, protoProps, staticProps) { | ||
if (protoProps) defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) defineProperties(Constructor, staticProps); | ||
return Constructor; | ||
}; | ||
}(); | ||
var slicedToArray = function () { | ||
function sliceIterator(arr, i) { | ||
var _arr = []; | ||
var _n = true; | ||
var _d = false; | ||
var _e = undefined; | ||
try { | ||
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { | ||
_arr.push(_s.value); | ||
if (i && _arr.length === i) break; | ||
} | ||
} catch (err) { | ||
_d = true; | ||
_e = err; | ||
} finally { | ||
try { | ||
if (!_n && _i["return"]) _i["return"](); | ||
} finally { | ||
if (_d) throw _e; | ||
} | ||
} | ||
return _arr; | ||
} | ||
return function (arr, i) { | ||
if (Array.isArray(arr)) { | ||
return arr; | ||
} else if (Symbol.iterator in Object(arr)) { | ||
return sliceIterator(arr, i); | ||
} else { | ||
throw new TypeError("Invalid attempt to destructure non-iterable instance"); | ||
} | ||
}; | ||
}(); | ||
var UNDEFINED_KEY = Object.create(null); | ||
var HashMap = function () { | ||
function HashMap(entries) { | ||
this._data = new EmptyObject(); | ||
if (entries) { | ||
for (var i = 0; i < entries.length; i++) { | ||
this.data[entries[i][0]] = entries[i][1]; | ||
} | ||
var HashMap = (function () { | ||
function HashMap(entries) { | ||
this._data = Object.create(null); | ||
if (entries) { | ||
for (var i = 0; i < entries.length; i++) { | ||
this.data[entries[i][0]] = entries[i][1]; | ||
} | ||
} | ||
} | ||
} | ||
createClass(HashMap, [{ | ||
key: 'forEach', | ||
value: function forEach(cb) { | ||
for (var key in this._data) { | ||
// skip undefined | ||
if (this._data[key] !== UNDEFINED_KEY) { | ||
cb(this._data[key], key); | ||
HashMap.prototype.forEach = function (cb) { | ||
for (var key in this._data) { | ||
// skip undefined | ||
if (this._data[key] !== UNDEFINED_KEY) { | ||
cb(this._data[key], key); | ||
} | ||
} | ||
} | ||
return this; | ||
}; | ||
HashMap.prototype.has = function (key) { | ||
return key in this._data && this._data[key] !== UNDEFINED_KEY; | ||
}; | ||
HashMap.prototype.get = function (key) { | ||
var val = this._data[key]; | ||
return val === UNDEFINED_KEY ? undefined : val; | ||
}; | ||
HashMap.prototype.set = function (key, value) { | ||
this._data[key] = value; | ||
return this; | ||
}; | ||
HashMap.prototype.delete = function (key) { | ||
this._data[key] = UNDEFINED_KEY; | ||
}; | ||
return HashMap; | ||
}()); | ||
return this; | ||
} | ||
}, { | ||
key: 'has', | ||
value: function has(key) { | ||
return key in this._data && this._data[key] !== UNDEFINED_KEY; | ||
} | ||
}, { | ||
key: 'get', | ||
value: function get(key) { | ||
var val = this._data[key]; | ||
return val === UNDEFINED_KEY ? undefined : val; | ||
} | ||
}, { | ||
key: 'set', | ||
value: function set(key, value) { | ||
this._data[key] = value; | ||
return this; | ||
} | ||
}, { | ||
key: 'delete', | ||
value: function _delete(key) { | ||
this._data[key] = UNDEFINED_KEY; | ||
} | ||
}]); | ||
return HashMap; | ||
}(); | ||
var SMALL_ARRAY_LENGTH = 250; | ||
var EventArray = function () { | ||
function EventArray() { | ||
var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH : arguments[0]; | ||
var initialData = arguments[1]; | ||
this.init(length, initialData); | ||
} | ||
createClass(EventArray, [{ | ||
key: "toJSON", | ||
value: function toJSON() { | ||
return this._data.slice(0, this.length); | ||
var EventArray = (function () { | ||
function EventArray(length, initialData) { | ||
if (length === void 0) { length = SMALL_ARRAY_LENGTH; } | ||
this.init(length, initialData); | ||
} | ||
}, { | ||
key: "init", | ||
value: function init() { | ||
var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH : arguments[0]; | ||
var initialData = arguments[1]; | ||
this.length = 0; | ||
this._length = length; | ||
this._data = new Array(length); | ||
if (initialData) { | ||
if (initialData.length > length) { | ||
length = initialData.length; | ||
this._data.length = length; | ||
this._length = length; | ||
EventArray.prototype.toJSON = function () { | ||
return this._data.slice(0, this.length); | ||
}; | ||
EventArray.prototype.init = function (length, initialData) { | ||
if (length === void 0) { length = SMALL_ARRAY_LENGTH; } | ||
this.length = 0; | ||
this._length = length; | ||
this._data = new Array(length); | ||
if (initialData) { | ||
if (initialData.length > length) { | ||
length = initialData.length; | ||
this._data.length = length; | ||
this._length = length; | ||
} | ||
for (var j = 0; j < initialData.length; j++) { | ||
this._data[j] = initialData[j]; | ||
this.length++; | ||
} | ||
} | ||
for (var j = 0; j < initialData.length; j++) { | ||
this._data[j] = initialData[j]; | ||
this.length++; | ||
} | ||
} | ||
} | ||
}; | ||
// TODO this should probably multiple index by 4 to hide | ||
// that we store in a flat array | ||
EventArray.prototype.get = function (index) { | ||
if (index >= 0 && index < this.length) { | ||
return this._data.slice(index, index + 4); | ||
} | ||
return undefined; | ||
}; | ||
EventArray.prototype.set = function (index, value) { | ||
if (index > this.length) { | ||
throw new Error("Index is out of array bounds."); | ||
} | ||
if (index === this.length) { | ||
this.length++; | ||
} | ||
this._data[index] = value; | ||
}; | ||
EventArray.prototype.forEach = function (cb) { | ||
for (var i = 0; i < this.length; i += 4) { | ||
cb(this._data.slice(i, i + 4), i); | ||
} | ||
}; | ||
EventArray.prototype.push = function (op, name, time, data) { | ||
var index = this.length; | ||
this.length += 4; | ||
if (index >= this._length) { | ||
this._length *= 2; | ||
this._data.length = this._length; | ||
} | ||
this._data[index] = op; | ||
this._data[index + 1] = name; | ||
this._data[index + 2] = time; | ||
this._data[index + 3] = data; | ||
return index; | ||
}; | ||
EventArray.prototype.pop = function () { | ||
var index = --this.length; | ||
if (index < 0) { | ||
this.length = 0; | ||
return undefined; | ||
} | ||
return this._data[index]; | ||
}; | ||
return EventArray; | ||
}()); | ||
}, { | ||
key: "get", | ||
value: function get(index) { | ||
if (index >= 0 && index < this.length) { | ||
return this._data.slice(index, index + 4); | ||
} | ||
var HAS_TYPED_ARRAYS = typeof Uint32Array !== 'undefined'; | ||
function hasTypedArrays() { | ||
return HAS_TYPED_ARRAYS; | ||
} | ||
return undefined; | ||
function fill(array, value, start, end) { | ||
if (hasTypedArrays()) { | ||
return array.fill(value, start, end); | ||
} | ||
}, { | ||
key: "set", | ||
value: function set(index, value) { | ||
if (index > this.length) { | ||
throw new Error("Index is out of array bounds."); | ||
} | ||
if (index === this.length) { | ||
this.length++; | ||
} | ||
this._data[index] = value; | ||
else { | ||
var s = start || 0; | ||
var e = end || array.length; | ||
for (; s < e; s++) { | ||
array[s] = value; | ||
} | ||
return array; | ||
} | ||
}, { | ||
key: "forEach", | ||
value: function forEach(cb) { | ||
for (var i = 0; i < this.length; i += 4) { | ||
cb(this._data.slice(i, i + 4), i); | ||
} | ||
} | ||
}, { | ||
key: "push", | ||
value: function push(op, name, time, data) { | ||
var index = this.length; | ||
this.length += 4; | ||
} | ||
if (index >= this._length) { | ||
this._length *= 2; | ||
this._data.length = this._length; | ||
} | ||
this._data[index] = op; | ||
this._data[index + 1] = name; | ||
this._data[index + 2] = time; | ||
this._data[index + 3] = data; | ||
return index; | ||
function grow(array, oldLength, newLength, fillValue) { | ||
if (fillValue === void 0) { fillValue = 0; } | ||
if (hasTypedArrays()) { | ||
var ret = new Uint32Array(newLength); | ||
ret.set(array); | ||
if (fillValue !== 0) { | ||
ret.fill(fillValue, oldLength); | ||
} | ||
return ret; | ||
} | ||
}, { | ||
key: "pop", | ||
value: function pop() { | ||
var index = --this.length; | ||
if (index < 0) { | ||
this.length = 0; | ||
return undefined; | ||
} | ||
return this._data[index]; | ||
else { | ||
array.length = newLength; | ||
fill(array, fillValue, oldLength, newLength); | ||
return array; | ||
} | ||
}]); | ||
return EventArray; | ||
}(); | ||
var A = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; | ||
function fill(array, value, start, end) { | ||
if (typeof array.fill === 'function') { | ||
return array.fill(value, start, end); | ||
} else { | ||
var len = array.length; | ||
var s = start || 0; | ||
var e = end || len; | ||
for (; s < e; s++) { | ||
array[s] = value; | ||
} | ||
return array; | ||
} | ||
} | ||
@@ -260,54 +147,40 @@ | ||
var MAX_ARRAY_LENGTH = 1e6; | ||
var FastIntArray = function () { | ||
function FastIntArray() { | ||
var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH$1 : arguments[0]; | ||
var initialData = arguments[1]; | ||
this.init(length, initialData); | ||
} | ||
createClass(FastIntArray, [{ | ||
key: 'init', | ||
value: function init() { | ||
var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH$1 : arguments[0]; | ||
var initialData = arguments[1]; | ||
this.length = 0; | ||
this._length = length; | ||
this._fill = 0; | ||
this._data = new A(length); | ||
if (initialData) { | ||
if (initialData.length > length) { | ||
length = initialData.length; | ||
this.grow(length); | ||
var FastIntArray = (function () { | ||
function FastIntArray(length, initialData) { | ||
if (length === void 0) { length = SMALL_ARRAY_LENGTH$1; } | ||
this.init(length, initialData); | ||
} | ||
FastIntArray.prototype.init = function (length, initialData) { | ||
if (length === void 0) { length = SMALL_ARRAY_LENGTH$1; } | ||
var useTypedArray = hasTypedArrays(); | ||
this.length = 0; | ||
this._length = length; | ||
this._fillValue = 0; | ||
this._data = useTypedArray ? new Uint32Array(length) : new Array(length); | ||
if (!useTypedArray) { | ||
fill(this._data, this._fillValue); | ||
} | ||
for (var j = 0; j < initialData.length; j++) { | ||
this._data[j] = initialData[j]; | ||
this.length++; | ||
if (initialData) { | ||
if (initialData.length > length) { | ||
length = initialData.length; | ||
this.grow(length); | ||
} | ||
for (var j = 0; j < initialData.length; j++) { | ||
this._data[j] = initialData[j]; | ||
this.length++; | ||
} | ||
} | ||
} | ||
} | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
return this._data.slice(0, this.length); | ||
} | ||
}, { | ||
key: 'get', | ||
value: function get(index) { | ||
if (index >= 0 && index < this.length) { | ||
return this._data[index]; | ||
} | ||
return undefined; | ||
} | ||
}, { | ||
key: 'increment', | ||
value: function increment(index) { | ||
this._data[index]++; | ||
} | ||
}; | ||
FastIntArray.prototype.toJSON = function () { | ||
return this._data.slice(0, this.length); | ||
}; | ||
FastIntArray.prototype.get = function (index) { | ||
if (index >= 0 && index < this.length) { | ||
return this._data[index]; | ||
} | ||
return undefined; | ||
}; | ||
FastIntArray.prototype.increment = function (index) { | ||
this._data[index]++; | ||
}; | ||
/* | ||
@@ -318,44 +191,41 @@ Uint32Arrays have an immutable length. This method | ||
*/ | ||
FastIntArray.prototype.grow = function (newLength) { | ||
this._data = grow(this._data, this._length, newLength, this._fillValue); | ||
this._length = newLength; | ||
}; | ||
FastIntArray.prototype.claim = function (count) { | ||
this.length += count; | ||
while (this.length > this._length) { | ||
this.grow(this._length * 2); | ||
} | ||
}; | ||
FastIntArray.prototype.push = function (int) { | ||
var index = this.length++; | ||
if (index === this._length) { | ||
this.grow(this._length * 2); | ||
} | ||
this._data[index] = int; | ||
}; | ||
return FastIntArray; | ||
}()); | ||
}, { | ||
key: 'grow', | ||
value: function grow(newLength) { | ||
var l = this._length; | ||
this._length = newLength; | ||
var data = this._data; | ||
var _d = this._data = new A(newLength); | ||
_d.set(data); | ||
if (this._fill !== 0) { | ||
fill(_d, this._fill, l); | ||
} | ||
} | ||
}, { | ||
key: 'claim', | ||
value: function claim(count) { | ||
this.length += count; | ||
while (this.length > this._length) { | ||
this.grow(this._length * 2); | ||
} | ||
} | ||
}, { | ||
key: 'push', | ||
value: function push(int) { | ||
var index = this.length++; | ||
if (index === this._length) { | ||
this.grow(this._length * 2); | ||
} | ||
this._data[index] = int; | ||
} | ||
}]); | ||
return FastIntArray; | ||
}(); | ||
var DEFAULT_STORE_SIZE = 1e3; | ||
var DEFAULT_NAMESPACE_SIZE = 10; | ||
/** | ||
* Wrapper type around options for `CounterStore`. | ||
* | ||
* Intentionally left private as `CounterStore` | ||
* only used internally when `HeimdallSession` is created. | ||
* | ||
* @class CounterStoreOptions | ||
*/ | ||
var CounterStoreOptions = (function () { | ||
function CounterStoreOptions(storeSize, namespaceAllocation) { | ||
if (storeSize === void 0) { storeSize = DEFAULT_STORE_SIZE; } | ||
if (namespaceAllocation === void 0) { namespaceAllocation = DEFAULT_NAMESPACE_SIZE; } | ||
this.storeSize = storeSize; | ||
this.namespaceAllocation = namespaceAllocation; | ||
} | ||
return CounterStoreOptions; | ||
}()); | ||
// NULL_NUMBER is a number larger than the largest | ||
@@ -366,196 +236,142 @@ // index we are capable of utilizing in the store. | ||
var LOB = (1 << 16) - 1; | ||
var CounterStore = function () { | ||
function CounterStore() { | ||
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
this.options = options; | ||
this.initialized = false; | ||
this._storeInitialized = false; | ||
this._store = null; | ||
this._namespaceCount = 0; | ||
this._config = null; | ||
this._cache = null; | ||
this._labelCache = null; | ||
this._nameCache = null; | ||
} | ||
createClass(CounterStore, [{ | ||
key: 'clean', | ||
value: function clean() { | ||
this._storeInitialized = false; | ||
this._store = null; | ||
this._cache = null; | ||
var CounterStore = (function () { | ||
function CounterStore(options) { | ||
if (options === void 0) { options = new CounterStoreOptions(); } | ||
this.options = options; | ||
this.initialized = false; | ||
this._storeInitialized = false; | ||
this._store = null; | ||
this._namespaceCount = 0; | ||
this._config = null; | ||
this._cache = null; | ||
this._labelCache = null; | ||
this._nameCache = null; | ||
} | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
return { | ||
_namespaceCount: this._namespaceCount, | ||
_config: this._config, | ||
_labelCache: this._labelCache, | ||
_nameCache: this._nameCache, | ||
_store: this._store | ||
}; | ||
} | ||
}, { | ||
key: 'registerNamespace', | ||
value: function registerNamespace(name, labels) { | ||
this._initializeIfNeeded(); | ||
var numCounters = labels.length; | ||
var namespaceIndex = this._namespaceCount++; | ||
var bitNamespaceIndex = namespaceIndex << 16; | ||
var namespace = new EmptyObject(); | ||
// we also generate a map between the counters | ||
// and these labels so that we can reconstruct | ||
// a meaningful structure later. | ||
this._nameCache[namespaceIndex] = name; | ||
this._labelCache[name] = labels; | ||
// grow the existing config and cache to account | ||
// for the new namespace | ||
this._config.push(numCounters); | ||
if (this._cache !== null) { | ||
CounterStore.prototype.clean = function () { | ||
this._storeInitialized = false; | ||
this._store = null; | ||
this._cache = null; | ||
}; | ||
CounterStore.prototype.toJSON = function () { | ||
return { | ||
_namespaceCount: this._namespaceCount, | ||
_config: this._config, | ||
_labelCache: this._labelCache, | ||
_nameCache: this._nameCache, | ||
_store: this._store | ||
}; | ||
}; | ||
CounterStore.fromJSON = function (json) { | ||
var store = new CounterStore(); | ||
store._namespaceCount = json._namespaceCount; | ||
store._labelCache = json._labelCache; | ||
store._nameCache = json._nameCache; | ||
if (json._store) { | ||
store._store = new FastIntArray(json._store.length, json._store); | ||
} | ||
if (json._config) { | ||
store._config = new FastIntArray(json._config.length, json._config); | ||
} | ||
return store; | ||
}; | ||
CounterStore.prototype.registerNamespace = function (name, labels) { | ||
this._initializeIfNeeded(); | ||
var numCounters = labels.length; | ||
var namespaceIndex = this._namespaceCount++; | ||
var bitNamespaceIndex = namespaceIndex << 16; | ||
var namespace = Object.create(null); | ||
// we also generate a map between the counters | ||
// and these labels so that we can reconstruct | ||
// a meaningful structure later. | ||
this._nameCache[namespaceIndex] = name; | ||
this._labelCache[name] = labels; | ||
// grow the existing config and cache to account | ||
// for the new namespace | ||
this._config.push(numCounters); | ||
if (this._cache !== null) { | ||
this._cache = grow(this._cache, namespaceIndex, this._namespaceCount, NULL_NUMBER); | ||
} | ||
for (var i = 0; i < numCounters; i++) { | ||
namespace[labels[i]] = bitNamespaceIndex + i; | ||
} | ||
return namespace; | ||
}; | ||
CounterStore.prototype._initializeIfNeeded = function () { | ||
if (this.initialized === false) { | ||
this._config = new FastIntArray(this.options.namespaceAllocation); | ||
this._labelCache = Object.create(null); | ||
this._nameCache = Object.create(null); | ||
this.initialized = true; | ||
} | ||
}; | ||
CounterStore.prototype.restoreFromCache = function (cache) { | ||
var stats = Object.create(null); | ||
for (var i = 0; i < cache.length; i++) { | ||
if (cache[i] !== NULL_NUMBER) { | ||
var startIndex = cache[i]; | ||
var namespace = this._nameCache[i]; | ||
var counterCount = this._config.get(i); | ||
stats[namespace] = Object.create(null); | ||
for (var j = 0; j < counterCount; j++) { | ||
var storeIndex = startIndex + j; | ||
var label = this._labelCache[namespace][j]; | ||
stats[namespace][label] = this._store.get(storeIndex); | ||
} | ||
} | ||
} | ||
return stats; | ||
}; | ||
CounterStore.prototype.increment = function (counter) { | ||
var namespaceIndex = counter >> 16; | ||
var counterIndex = counter & LOB; | ||
if (this._cache === null) { | ||
this._initializeStoreIfNeeded(); | ||
var a = hasTypedArrays() ? new Uint32Array(this._namespaceCount) : new Array(this._namespaceCount); | ||
this._cache = fill(a, NULL_NUMBER); | ||
} | ||
if (this._cache[namespaceIndex] === NULL_NUMBER) { | ||
var counterCount = this._config.get(namespaceIndex); | ||
this._cache[namespaceIndex] = this._store.length; | ||
this._store.claim(counterCount); | ||
} | ||
var storeIndex = this._cache[namespaceIndex] + counterIndex; | ||
this._store.increment(storeIndex); | ||
}; | ||
CounterStore.prototype._initializeStoreIfNeeded = function () { | ||
if (this._storeInitialized === false) { | ||
this._store = new FastIntArray(this.options.storeSize); | ||
this._storeInitialized = true; | ||
} | ||
}; | ||
CounterStore.prototype.has = function (name) { | ||
return this._labelCache && name in this._labelCache; | ||
}; | ||
CounterStore.prototype.cache = function () { | ||
var cache = this._cache; | ||
this._cache = null; | ||
return cache; | ||
}; | ||
return CounterStore; | ||
}()); | ||
this._cache = new A(this._namespaceCount); | ||
this._cache.set(cache); | ||
this._cache[namespaceIndex] = NULL_NUMBER; | ||
} | ||
for (var i = 0; i < numCounters; i++) { | ||
namespace[labels[i]] = bitNamespaceIndex + i; | ||
} | ||
return namespace; | ||
var Session = (function () { | ||
function HeimdallSession() { | ||
this.init(); | ||
} | ||
}, { | ||
key: '_initializeIfNeeded', | ||
value: function _initializeIfNeeded() { | ||
if (this.initialized === false) { | ||
this._config = new FastIntArray(this.options.namespaceAllocation || DEFAULT_NAMESPACE_SIZE); | ||
this._labelCache = new EmptyObject(); | ||
this._nameCache = new EmptyObject(); | ||
this.initialized = true; | ||
} | ||
} | ||
}, { | ||
key: 'restoreFromCache', | ||
value: function restoreFromCache(cache) { | ||
var stats = new EmptyObject(); | ||
for (var i = 0; i < cache.length; i++) { | ||
if (cache[i] !== NULL_NUMBER) { | ||
var startIndex = cache[i]; | ||
var namespace = this._nameCache[i]; | ||
var counterCount = this._config.get(i); | ||
stats[namespace] = new EmptyObject(); | ||
for (var j = 0; j < counterCount; j++) { | ||
var storeIndex = startIndex + j; | ||
var label = this._labelCache[namespace][j]; | ||
stats[namespace][label] = this._store.get(storeIndex); | ||
} | ||
} | ||
} | ||
return stats; | ||
} | ||
}, { | ||
key: 'increment', | ||
value: function increment(counter) { | ||
var namespaceIndex = counter >> 16; | ||
var counterIndex = counter & LOB; | ||
if (this._cache === null) { | ||
this._initializeStoreIfNeeded(); | ||
this._cache = fill(new A(this._namespaceCount), NULL_NUMBER); | ||
} | ||
if (this._cache[namespaceIndex] === NULL_NUMBER) { | ||
var counterCount = this._config.get(namespaceIndex); | ||
this._cache[namespaceIndex] = this._store.length; | ||
this._store.claim(counterCount); | ||
} | ||
var storeIndex = this._cache[namespaceIndex] + counterIndex; | ||
this._store.increment(storeIndex); | ||
} | ||
}, { | ||
key: '_initializeStoreIfNeeded', | ||
value: function _initializeStoreIfNeeded() { | ||
if (this._storeInitialized === false) { | ||
this._store = new FastIntArray(this.options.storeSize || DEFAULT_STORE_SIZE); | ||
this._storeInitialized = true; | ||
} | ||
} | ||
}, { | ||
key: 'has', | ||
value: function has(name) { | ||
return this._labelCache && name in this._labelCache; | ||
} | ||
}, { | ||
key: 'cache', | ||
value: function cache() { | ||
var cache = this._cache; | ||
this._cache = null; | ||
return cache; | ||
} | ||
}], [{ | ||
key: 'fromJSON', | ||
value: function fromJSON(json) { | ||
var store = new CounterStore(); | ||
store._namespaceCount = json._namespaceCount; | ||
store._labelCache = json._labelCache; | ||
store._nameCache = json._nameCache; | ||
if (json._store) { | ||
store._store = new FastIntArray(json._store.length, json._store); | ||
} | ||
if (json._config) { | ||
store._config = new FastIntArray(json._config.length, json._config); | ||
} | ||
} | ||
}]); | ||
return CounterStore; | ||
}(); | ||
// provides easily interceptable indirection. | ||
var HeimdallSession = function () { | ||
function HeimdallSession() { | ||
this.init(); | ||
} | ||
createClass(HeimdallSession, [{ | ||
key: 'init', | ||
value: function init() { | ||
this.monitors = new CounterStore(); | ||
this.configs = new HashMap(); | ||
this.events = new EventArray(640000 * 4); | ||
} | ||
HeimdallSession.prototype.init = function () { | ||
this.monitors = new CounterStore(); | ||
this.configs = new HashMap(); | ||
this.events = new EventArray(640000 * 4); | ||
}; | ||
// mostly for test helper purposes | ||
HeimdallSession.prototype.reset = function () { | ||
this.monitors.clean(); | ||
this.events.length = 0; | ||
}; | ||
return HeimdallSession; | ||
}()); | ||
}, { | ||
key: 'reset', | ||
value: function reset() { | ||
this.monitors.clean(); | ||
this.events.length = 0; | ||
} | ||
}]); | ||
return HeimdallSession; | ||
}(); | ||
var now = void 0; | ||
var format = void 0; | ||
var ORIGIN_TIME = void 0; | ||
var now; | ||
var format; | ||
var ORIGIN_TIME; | ||
// It turns out to be nicer for perf to bind than to close over the time method | ||
@@ -566,125 +382,128 @@ // however, when testing we need to be able to stub the clock via the global | ||
var IS_TESTING = freeGlobal.IS_HEIMDALL_TEST_ENVIRONMENT; | ||
if ((typeof performance === 'undefined' ? 'undefined' : _typeof(performance)) === 'object' && typeof performance.now === 'function') { | ||
now = IS_TESTING ? function now() { | ||
return performance.now(); | ||
} : performance.now.bind(performance); | ||
format = 'milli'; | ||
} else if (typeof process !== 'undefined' && typeof process.hrtime === 'function') { | ||
now = IS_TESTING ? function now() { | ||
return process.hrtime(); | ||
} : process.hrtime.bind(process); | ||
format = 'hrtime'; | ||
} else { | ||
ORIGIN_TIME = Date.now(); | ||
now = Date.now.bind(Date); | ||
format = 'timestamp'; | ||
if (typeof performance === 'object' && typeof performance.now === 'function') { | ||
now = IS_TESTING ? function now() { return performance.now(); } : performance.now.bind(performance); | ||
format = 'milli'; | ||
} | ||
function normalizeTime(time) { | ||
var format = arguments.length <= 1 || arguments[1] === undefined ? format : arguments[1]; | ||
switch (format) { | ||
case 'milli': | ||
return milliToNano(time); | ||
case 'hrtime': | ||
return timeFromHRTime(time); | ||
case 'timestamp': | ||
return milliToNano(time - ORIGIN_TIME); | ||
default: | ||
throw new Error('Unknown Format'); | ||
} | ||
else if (typeof process !== 'undefined' && typeof process.hrtime === 'function') { | ||
now = IS_TESTING ? function now() { return process.hrtime(); } : process.hrtime.bind(process); | ||
format = 'hrtime'; | ||
} | ||
else { | ||
ORIGIN_TIME = Date.now(); | ||
now = Date.now.bind(Date); | ||
format = 'timestamp'; | ||
} | ||
function normalizeTime(time, optionalFormat) { | ||
if (optionalFormat === void 0) { optionalFormat = format; } | ||
switch (optionalFormat) { | ||
case 'milli': | ||
return milliToNano(time); | ||
case 'hrtime': | ||
return timeFromHRTime(time); | ||
case 'timestamp': | ||
return milliToNano(time - ORIGIN_TIME); | ||
default: | ||
throw new Error('Unknown Format'); | ||
} | ||
} | ||
function milliToNano(time) { | ||
return Math.floor(time * 1e6); | ||
return Math.floor(time * 1e6); | ||
} | ||
function timeFromHRTime(hrtime) { | ||
return hrtime[0] * 1e9 + hrtime[1]; | ||
return hrtime[0] * 1e9 + hrtime[1]; | ||
} | ||
var now$1 = now; | ||
var OP_START = 0; | ||
var OP_STOP = 1; | ||
var OP_RESUME = 2; | ||
var OP_ANNOTATE = 3; | ||
var OpCodes; | ||
(function (OpCodes) { | ||
OpCodes[OpCodes["OP_START"] = 0] = "OP_START"; | ||
OpCodes[OpCodes["OP_STOP"] = 1] = "OP_STOP"; | ||
OpCodes[OpCodes["OP_RESUME"] = 2] = "OP_RESUME"; | ||
OpCodes[OpCodes["OP_ANNOTATE"] = 3] = "OP_ANNOTATE"; | ||
})(OpCodes || (OpCodes = {})); | ||
var OpCodes$1 = OpCodes; | ||
var Heimdall = function () { | ||
function Heimdall(session) { | ||
if (arguments.length < 1) { | ||
this._session = new HeimdallSession(); | ||
this.start('session-root'); | ||
} else { | ||
this._session = session; | ||
var VERSION = '0.3.3'; | ||
var Heimdall = (function () { | ||
function Heimdall(session) { | ||
if (arguments.length < 1) { | ||
this._session = new Session(); | ||
this.start('session-root'); | ||
} | ||
else { | ||
this._session = session; | ||
} | ||
} | ||
} | ||
createClass(Heimdall, [{ | ||
key: '_retrieveCounters', | ||
value: function _retrieveCounters() { | ||
return this._monitors.cache(); | ||
} | ||
}, { | ||
key: 'start', | ||
value: function start(name) { | ||
return this._session.events.push(OP_START, name, now$1(), this._retrieveCounters()); | ||
} | ||
}, { | ||
key: 'stop', | ||
value: function stop(token) { | ||
this._session.events.push(OP_STOP, token, now$1(), this._retrieveCounters()); | ||
} | ||
}, { | ||
key: 'resume', | ||
value: function resume(token) { | ||
this._session.events.push(OP_RESUME, token, now$1(), this._retrieveCounters()); | ||
} | ||
}, { | ||
key: 'annotate', | ||
value: function annotate(info) { | ||
// This has the side effect of making events heterogenous, as info is an object | ||
// while counters will always be `null` or an `Array` | ||
this._session.events.push(OP_ANNOTATE, NULL_NUMBER, NULL_NUMBER, info); | ||
} | ||
}, { | ||
key: 'hasMonitor', | ||
value: function hasMonitor(name) { | ||
return !!this._monitors.has(name); | ||
} | ||
}, { | ||
key: 'registerMonitor', | ||
value: function registerMonitor(name) { | ||
if (name === 'own' || name === 'time') { | ||
throw new Error('Cannot register monitor at namespace "' + name + '". "own" and "time" are reserved'); | ||
} | ||
if (this.hasMonitor(name)) { | ||
throw new Error('A monitor for "' + name + '" is already registered"'); | ||
} | ||
for (var _len = arguments.length, keys = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
keys[_key - 1] = arguments[_key]; | ||
} | ||
return this._monitors.registerNamespace(name, keys); | ||
} | ||
}, { | ||
key: 'increment', | ||
value: function increment(token) { | ||
this._session.monitors.increment(token); | ||
} | ||
}, { | ||
key: 'configFor', | ||
value: function configFor(name) { | ||
var config = this._session.configs.get(name); | ||
if (!config) { | ||
config = new EmptyObject(); | ||
this._session.configs.set(name, config); | ||
} | ||
return config; | ||
} | ||
Object.defineProperty(Heimdall, "VERSION", { | ||
get: function () { | ||
return VERSION; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(Heimdall.prototype, "VERSION", { | ||
get: function () { | ||
return VERSION; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(Heimdall.prototype, "_monitors", { | ||
get: function () { | ||
return this._session.monitors; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(Heimdall.prototype, "_events", { | ||
get: function () { | ||
return this._session.events; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Heimdall.prototype._retrieveCounters = function () { | ||
return this._monitors.cache(); | ||
}; | ||
Heimdall.prototype.start = function (name) { | ||
return this._session.events.push(OpCodes$1.OP_START, name, now$1(), this._retrieveCounters()); | ||
}; | ||
Heimdall.prototype.stop = function (token) { | ||
this._session.events.push(OpCodes$1.OP_STOP, token, now$1(), this._retrieveCounters()); | ||
}; | ||
Heimdall.prototype.resume = function (token) { | ||
this._session.events.push(OpCodes$1.OP_RESUME, token, now$1(), this._retrieveCounters()); | ||
}; | ||
Heimdall.prototype.annotate = function (info) { | ||
// This has the side effect of making events heterogenous, as info is an object | ||
// while counters will always be `null` or an `Array` | ||
this._session.events.push(OpCodes$1.OP_ANNOTATE, NULL_NUMBER, NULL_NUMBER, info); | ||
}; | ||
Heimdall.prototype.hasMonitor = function (name) { | ||
return !!this._monitors.has(name); | ||
}; | ||
Heimdall.prototype.registerMonitor = function (name) { | ||
var keys = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
keys[_i - 1] = arguments[_i]; | ||
} | ||
if (name === 'own' || name === 'time') { | ||
throw new Error('Cannot register monitor at namespace "' + name + '". "own" and "time" are reserved'); | ||
} | ||
if (this.hasMonitor(name)) { | ||
throw new Error('A monitor for "' + name + '" is already registered"'); | ||
} | ||
return this._monitors.registerNamespace(name, keys); | ||
}; | ||
Heimdall.prototype.increment = function (token) { | ||
this._session.monitors.increment(token); | ||
}; | ||
Heimdall.prototype.configFor = function (name) { | ||
var config = this._session.configs.get(name); | ||
if (!config) { | ||
config = Object.create(null); | ||
this._session.configs.set(name, config); | ||
} | ||
return config; | ||
}; | ||
/* | ||
@@ -695,260 +514,200 @@ Ideally, this method should only be used for serializing | ||
*/ | ||
Heimdall.prototype.toJSON = function () { | ||
return { | ||
heimdallVersion: VERSION, | ||
format, | ||
monitors: this._monitors.toJSON(), | ||
events: this._events.toJSON(), | ||
serializationTime: now$1() | ||
}; | ||
}; | ||
Heimdall.prototype.toString = function () { | ||
return JSON.stringify(this.toJSON()); | ||
}; | ||
return Heimdall; | ||
}()); | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
return { | ||
format: format, | ||
monitors: this._monitors.toJSON(), | ||
events: this._events.toJSON(), | ||
serializationTime: now$1() | ||
}; | ||
var HeimdallNode = (function () { | ||
function HeimdallNode(name, id) { | ||
this._id = id; | ||
this.parent = null; | ||
this.resumeNode = null; | ||
this.name = name; | ||
this.stopped = false; | ||
this.leaves = []; | ||
this.nodes = []; | ||
this.children = []; | ||
} | ||
}, { | ||
key: 'toString', | ||
value: function toString() { | ||
return JSON.stringify(this.toJSON()); | ||
} | ||
}, { | ||
key: '_monitors', | ||
get: function get() { | ||
return this._session.monitors; | ||
} | ||
}, { | ||
key: '_events', | ||
get: function get() { | ||
return this._session.events; | ||
} | ||
}]); | ||
return Heimdall; | ||
}(); | ||
Object.defineProperty(HeimdallNode.prototype, "stats", { | ||
get: function () { | ||
var own = { | ||
selfTime: 0, | ||
duration: 0, | ||
startTime: this.leaves[0].startTime, | ||
endTime: this.leaves[this.leaves.length - 1].endTime | ||
}; | ||
own.duration = own.endTime - own.startTime; | ||
var counters = []; | ||
var annotations = []; | ||
var stats = { | ||
self: own | ||
}; | ||
this.forEachLeaf(function (leaf) { | ||
own.selfTime += leaf.selfTime; | ||
annotations.push(leaf.annotations); | ||
for (var namespace in leaf.counters) { | ||
var value = leaf.counters[namespace]; | ||
if (!stats.hasOwnProperty(namespace)) { | ||
stats[namespace] = value; | ||
} | ||
else { | ||
for (var label in value) { | ||
stats[namespace][label] += value[label]; | ||
} | ||
} | ||
} | ||
counters.push(leaf.counters); | ||
}); | ||
return stats; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
HeimdallNode.prototype.stop = function () { | ||
if (this.stopped === true) { | ||
throw new Error('Cannot Stop node, already stopped!'); | ||
} | ||
this.stopped = true; | ||
}; | ||
HeimdallNode.prototype.resume = function (resumeNode) { | ||
if (!this.stopped) { | ||
throw new Error('Cannot Resume node, already running!'); | ||
} | ||
this.resumeNode = resumeNode; | ||
this.stopped = false; | ||
}; | ||
HeimdallNode.prototype.addLeaf = function (leaf) { | ||
leaf.owner = this; | ||
this.leaves.push(leaf); | ||
this.children.push(leaf); | ||
}; | ||
HeimdallNode.prototype.addNode = function (node) { | ||
if (node.parent) { | ||
throw new Error("Cannot set parent of node '" + node.name + "', node already has a parent!"); | ||
} | ||
node.parent = this; | ||
node.resumeNode = this; | ||
this.nodes.push(node); | ||
this.children.push(node); | ||
}; | ||
Object.defineProperty(HeimdallNode.prototype, "isRoot", { | ||
get: function () { | ||
return this.parent === null; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
HeimdallNode.prototype.visitPreOrder = function (cb) { | ||
cb(this); | ||
for (var i = 0; i < this.nodes.length; i++) { | ||
this.nodes[i].visitPreOrder(cb); | ||
} | ||
}; | ||
HeimdallNode.prototype.visitPostOrder = function (cb) { | ||
for (var i = 0; i < this.nodes.length; i++) { | ||
this.nodes[i].visitPostOrder(cb); | ||
} | ||
cb(this); | ||
}; | ||
HeimdallNode.prototype.forEachNode = function (cb) { | ||
for (var i = 0; i < this.nodes.length; ++i) { | ||
cb(this.nodes[i]); | ||
} | ||
}; | ||
HeimdallNode.prototype.forEachLeaf = function (cb) { | ||
for (var i = 0; i < this.leaves.length; ++i) { | ||
cb(this.leaves[i]); | ||
} | ||
}; | ||
HeimdallNode.prototype.forEachChild = function (cb) { | ||
for (var i = 0; i < this.children.length; ++i) { | ||
cb(this.children[i]); | ||
} | ||
}; | ||
HeimdallNode.prototype.toJSON = function () { | ||
return { | ||
_id: this._id, | ||
name: this.name, | ||
leaves: this.leaves.map(function (leaf) { return leaf.toJSON(); }), | ||
nodes: this.nodes.map(function (child) { return child._id; }), | ||
children: this.children.map(function (child) { return child._id; }) | ||
}; | ||
}; | ||
HeimdallNode.prototype.toJSONSubgraph = function () { | ||
var nodes = []; | ||
this.visitPreOrder(function (node) { return nodes.push(node.toJSON()); }); | ||
return nodes; | ||
}; | ||
return HeimdallNode; | ||
}()); | ||
var HeimdallNode = function () { | ||
function HeimdallNode(name, id) { | ||
this._id = id; | ||
this.parent = null; | ||
this.resumeNode = null; | ||
this.name = name; | ||
this.stopped = false; | ||
this.leaves = []; | ||
this.nodes = []; | ||
this.children = []; | ||
} | ||
createClass(HeimdallNode, [{ | ||
key: 'stop', | ||
value: function stop() { | ||
if (this.stopped === true) { | ||
throw new Error('Cannot Stop node, already stopped!'); | ||
} | ||
this.stopped = true; | ||
var HeimdallLeaf = (function () { | ||
function HeimdallLeaf() { | ||
// set on start | ||
this._id = null; | ||
this.owner = null; | ||
this.previousOp = null; | ||
this.startTime = 0; | ||
// set on annotate | ||
this.annotations = null; | ||
// set on stop | ||
this.nextOp = null; | ||
this.endTime = 0; | ||
this.counters = null; | ||
this.name = null; | ||
} | ||
}, { | ||
key: 'resume', | ||
value: function resume(resumeNode) { | ||
if (!this.stopped) { | ||
throw new Error('Cannot Resume node, already running!'); | ||
} | ||
this.resumeNode = resumeNode; | ||
this.stopped = false; | ||
} | ||
}, { | ||
key: 'addLeaf', | ||
value: function addLeaf(leaf) { | ||
leaf.owner = this; | ||
this.leaves.push(leaf); | ||
this.children.push(leaf); | ||
} | ||
}, { | ||
key: 'addNode', | ||
value: function addNode(node) { | ||
if (node.parent) { | ||
throw new Error('Cannot set parent of node \'' + node.name + '\', node already has a parent!'); | ||
} | ||
node.parent = this; | ||
node.resumeNode = this; | ||
this.nodes.push(node); | ||
this.children.push(node); | ||
} | ||
}, { | ||
key: 'visitPreOrder', | ||
value: function visitPreOrder(cb) { | ||
cb(this); | ||
for (var i = 0; i < this.nodes.length; i++) { | ||
this.nodes[i].visitPreOrder(cb); | ||
} | ||
} | ||
}, { | ||
key: 'visitPostOrder', | ||
value: function visitPostOrder(cb) { | ||
for (var i = 0; i < this.nodes.length; i++) { | ||
this.nodes[i].visitPostOrder(cb); | ||
} | ||
cb(this); | ||
} | ||
}, { | ||
key: 'forEachNode', | ||
value: function forEachNode(cb) { | ||
for (var i = 0; i < this.nodes.length; ++i) { | ||
cb(this.nodes[i]); | ||
} | ||
} | ||
}, { | ||
key: 'forEachLeaf', | ||
value: function forEachLeaf(cb) { | ||
for (var i = 0; i < this.leaves.length; ++i) { | ||
cb(this.leaves[i]); | ||
} | ||
} | ||
}, { | ||
key: 'forEachChild', | ||
value: function forEachChild(cb) { | ||
for (var i = 0; i < this.children.length; ++i) { | ||
cb(this.children[i]); | ||
} | ||
} | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
return { | ||
_id: this._id, | ||
name: this.name, | ||
leaves: this.leaves.map(function (leaf) { | ||
return leaf.toJSON(); | ||
}), | ||
nodes: this.nodes.map(function (child) { | ||
return child._id; | ||
}), | ||
children: this.children.map(function (child) { | ||
return child._id; | ||
}) | ||
}; | ||
} | ||
}, { | ||
key: 'toJSONSubgraph', | ||
value: function toJSONSubgraph() { | ||
var nodes = []; | ||
this.visitPreOrder(function (node) { | ||
return nodes.push(node.toJSON()); | ||
}); | ||
return nodes; | ||
} | ||
}, { | ||
key: 'stats', | ||
get: function get() { | ||
var own = { | ||
selfTime: 0, | ||
duration: 0, | ||
startTime: this.leaves[0].startTime, | ||
endTime: this.leaves[this.leaves.length - 1].endTime | ||
}; | ||
own.duration = own.endTime - own.startTime; | ||
var counters = []; | ||
var annotations = []; | ||
var stats = { | ||
self: own | ||
}; | ||
this.forEachLeaf(function (leaf) { | ||
own.selfTime += leaf.selfTime; | ||
annotations.push(leaf.annotations); | ||
for (var namespace in leaf.counters) { | ||
var value = leaf.counters[namespace]; | ||
if (!stats.hasOwnProperty(namespace)) { | ||
stats[namespace] = value; | ||
} else { | ||
for (var label in value) { | ||
stats[namespace][label] += value[label]; | ||
} | ||
} | ||
Object.defineProperty(HeimdallLeaf.prototype, "selfTime", { | ||
get: function () { | ||
return this.endTime - this.startTime; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(HeimdallLeaf.prototype, "isStopped", { | ||
get: function () { | ||
return this.endTime !== 0; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
HeimdallLeaf.prototype.annotate = function (annotation) { | ||
if (this.annotations === null) { | ||
this.annotations = []; | ||
} | ||
this.annotations.push(annotation); | ||
}; | ||
HeimdallLeaf.prototype.start = function (owner, previousOp, time) { | ||
this.owner = owner; | ||
this.previousOp = previousOp; | ||
this.startTime = time; | ||
}; | ||
HeimdallLeaf.prototype.stop = function (nextOp, time, counters) { | ||
this.nextOp = nextOp; | ||
this.endTime = time; | ||
this.counters = counters; | ||
this._id = this.name = "[" + this.owner.name + "]#" + this.previousOp + ":" + nextOp; | ||
}; | ||
HeimdallLeaf.prototype.toJSON = function () { | ||
return { | ||
_id: this._id, | ||
name: this.name, | ||
startTime: this.startTime, | ||
endTime: this.endTime, | ||
counters: this.counters, | ||
annotations: this.annotations | ||
}; | ||
}; | ||
return HeimdallLeaf; | ||
}()); | ||
counters.push(leaf.counters); | ||
}); | ||
return stats; | ||
} | ||
}, { | ||
key: 'isRoot', | ||
get: function get() { | ||
return this.parent === null; | ||
} | ||
}]); | ||
return HeimdallNode; | ||
}(); | ||
var HeimdallLeaf = function () { | ||
function HeimdallLeaf() { | ||
// set on start | ||
this._id = null; | ||
this.owner = null; | ||
this.previousOp = null; | ||
this.startTime = 0; | ||
// set on annotate | ||
this.annotations = null; | ||
// set on stop | ||
this.nextOp = null; | ||
this.endTime = 0; | ||
this.counters = null; | ||
this.name = null; | ||
} | ||
createClass(HeimdallLeaf, [{ | ||
key: "annotate", | ||
value: function annotate(annotation) { | ||
if (this.annotations === null) { | ||
this.annotations = []; | ||
} | ||
this.annotations.push(annotation); | ||
} | ||
}, { | ||
key: "start", | ||
value: function start(owner, previousOp, time) { | ||
this.owner = owner; | ||
this.previousOp = previousOp; | ||
this.startTime = time; | ||
} | ||
}, { | ||
key: "stop", | ||
value: function stop(nextOp, time, counters) { | ||
this.nextOp = nextOp; | ||
this.endTime = time; | ||
this.counters = counters; | ||
this._id = this.name = "[" + this.owner.name + "]#" + this.previousOp + ":" + nextOp; | ||
} | ||
}, { | ||
key: "toJSON", | ||
value: function toJSON() { | ||
return { | ||
_id: this._id, | ||
name: this.name, | ||
startTime: this.startTime, | ||
endTime: this.endTime, | ||
counters: this.counters, | ||
annotations: this.annotations | ||
}; | ||
} | ||
}, { | ||
key: "selfTime", | ||
get: function get() { | ||
return this.endTime - this.startTime; | ||
} | ||
}, { | ||
key: "isStopped", | ||
get: function get() { | ||
return this.endTime !== 0; | ||
} | ||
}]); | ||
return HeimdallLeaf; | ||
}(); | ||
/* | ||
@@ -982,301 +741,240 @@ Example Event Timeline and tree reconstruction | ||
*/ | ||
function statsFromCounters(counterStore, counterCache) { | ||
if (!counterStore || !counterCache) { | ||
return null; | ||
} | ||
return counterStore.restoreFromCache(counterCache); | ||
if (!counterStore || !counterCache) { | ||
return null; | ||
} | ||
return counterStore.restoreFromCache(counterCache); | ||
} | ||
var HeimdallTree = function () { | ||
function HeimdallTree(heimdall, lastKnownTime) { | ||
this._heimdall = heimdall; | ||
this.root = null; | ||
this.format = heimdall && heimdall._timeFormat ? heimdall._timeFormat : format; | ||
this.lastKnownTime = lastKnownTime; | ||
} | ||
createClass(HeimdallTree, [{ | ||
key: '_createLeaf', | ||
value: function _createLeaf(currentNode, time) { | ||
var leaf = new HeimdallLeaf(); | ||
leaf.start(currentNode, currentNode.name, time); | ||
currentNode.addLeaf(leaf); | ||
return leaf; | ||
var HeimdallTree = (function () { | ||
function HeimdallTree(heimdall, lastKnownTime) { | ||
this._heimdall = heimdall; | ||
this.root = null; | ||
this.format = heimdall && heimdall._timeFormat ? heimdall._timeFormat : format; | ||
this.lastKnownTime = lastKnownTime; | ||
} | ||
}, { | ||
key: '_chainLeaf', | ||
value: function _chainLeaf(currentNode, incomingNode, time) { | ||
var leaf = new HeimdallLeaf(); | ||
leaf.start(currentNode, incomingNode.name, time); | ||
currentNode.addLeaf(leaf); | ||
return leaf; | ||
} | ||
}, { | ||
key: '_createNode', | ||
value: function _createNode(nodeName, index, nodeMap) { | ||
var node = new HeimdallNode(nodeName, index); | ||
nodeMap.set(index, node); | ||
return node; | ||
} | ||
}, { | ||
key: '_chainNode', | ||
value: function _chainNode(currentNode, nodeName, index, nodeMap) { | ||
var node = this._createNode(nodeName, index, nodeMap); | ||
currentNode.addNode(node); | ||
return node; | ||
} | ||
}, { | ||
key: 'construct', | ||
value: function construct() { | ||
var _this = this; | ||
var events = this._heimdall._events; | ||
var currentLeaf = null; | ||
var currentNode = null; | ||
var nodeMap = new HashMap(); | ||
var openNodes = []; | ||
var node = void 0; | ||
var format = this.format; | ||
var counterStore = this._heimdall._monitors; | ||
var stopTime = this.lastKnownTime ? normalizeTime(this.lastKnownTime) : now$1(); | ||
var pageRootIndex = events._length + 1; | ||
currentNode = this.root = this._createNode('page-root', pageRootIndex, nodeMap); | ||
currentLeaf = this._createLeaf(currentNode, 0); | ||
openNodes.push(node); | ||
events.forEach(function (_ref, i) { | ||
var _ref2 = slicedToArray(_ref, 4); | ||
var op = _ref2[0]; | ||
var name = _ref2[1]; | ||
var time = _ref2[2]; | ||
var counters = _ref2[3]; | ||
if (op !== OP_ANNOTATE) { | ||
time = normalizeTime(time, format); | ||
counters = statsFromCounters(counterStore, counters); | ||
} | ||
switch (op) { | ||
case OP_START: | ||
currentNode = _this._chainNode(currentNode, name, i, nodeMap); | ||
openNodes.push(currentNode); | ||
if (currentLeaf) { | ||
currentLeaf.stop(name, time, counters); | ||
HeimdallTree.fromJSON = function (json) { | ||
var events = json.events || []; | ||
var heimdall = { | ||
_timeFormat: json.format || format, | ||
_events: new EventArray(events.length, events), | ||
_monitors: CounterStore.fromJSON(json.monitors) | ||
}; | ||
return new HeimdallTree(heimdall, json.serializationTime); | ||
}; | ||
Object.defineProperty(HeimdallTree.prototype, "path", { | ||
// primarily a test helper, you can get this at any time | ||
// to get an array representing the path of open node names | ||
// from "root" to the last open node. | ||
get: function () { | ||
var events = this._heimdall._events; | ||
var root = new HeimdallNode('root', 1e9); | ||
var currentNode = root; | ||
var nodeMap = new HashMap(); | ||
var node; | ||
var top; | ||
var path = []; | ||
events.forEach(function (_a, i) { | ||
var op = _a[0], name = _a[1]; | ||
switch (op) { | ||
case OpCodes$1.OP_START: | ||
node = new HeimdallNode(name, i); | ||
nodeMap.set(i, node); | ||
currentNode.addNode(node); | ||
currentNode = node; | ||
break; | ||
case OpCodes$1.OP_STOP: | ||
node = nodeMap.get(name); | ||
if (name !== currentNode._id) { | ||
// potentially throw the correct error (already stopped) | ||
if (node) { | ||
node.stop(); | ||
} | ||
else { | ||
throw new Error("Cannot Stop, Attempting to stop a non-existent node!"); | ||
} | ||
throw new Error("Cannot Stop, Attempting to stop a node with an active child!"); | ||
} | ||
currentNode.stop(); | ||
currentNode = currentNode.resumeNode; | ||
break; | ||
case OpCodes$1.OP_RESUME: | ||
node = nodeMap.get(name); | ||
node.resume(currentNode); | ||
currentNode = node; | ||
break; | ||
default: | ||
throw new Error("HeimdallTree encountered an unknown OpCode '" + op + "' during path construction."); | ||
} | ||
}); | ||
top = currentNode; | ||
while (top !== undefined && top !== root) { | ||
path.unshift(top.name); | ||
top = top.parent; | ||
} | ||
currentLeaf = _this._createLeaf(currentNode, time); | ||
break; | ||
case OP_STOP: | ||
node = nodeMap.get(name); | ||
if (name !== currentNode._id) { | ||
// potentially throw the correct error (already stopped) | ||
if (node) { | ||
node.stop(); | ||
} else { | ||
throw new Error("Cannot Stop, Attempting to stop a non-existent node!"); | ||
} | ||
throw new Error("Cannot Stop, Attempting to stop a node with an active child!"); | ||
return path; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(HeimdallTree.prototype, "stack", { | ||
// primarily a test helper, you can get this at any time | ||
// to get an array representing the "stack" of open node names. | ||
get: function () { | ||
var events = this._heimdall._events; | ||
var stack = []; | ||
var nodeMap = new HashMap(); | ||
events.forEach(function (_a, i) { | ||
var op = _a[0], name = _a[1]; | ||
if (op === OpCodes$1.OP_START) { | ||
stack.push(name); | ||
nodeMap.set(i, name); | ||
} | ||
else if (op === OpCodes$1.OP_RESUME) { | ||
var n = nodeMap.get(name); | ||
stack.push(n); | ||
} | ||
else if (op === OpCodes$1.OP_STOP) { | ||
var n = nodeMap.get(name); | ||
if (n !== stack[stack.length - 1]) { | ||
throw new Error('Invalid Stack!'); | ||
} | ||
stack.pop(); | ||
} | ||
}); | ||
return stack; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
HeimdallTree.prototype._createLeaf = function (currentNode, time) { | ||
var leaf = new HeimdallLeaf(); | ||
leaf.start(currentNode, currentNode.name, time); | ||
currentNode.addLeaf(leaf); | ||
return leaf; | ||
}; | ||
HeimdallTree.prototype._chainLeaf = function (currentNode, incomingNode, time) { | ||
var leaf = new HeimdallLeaf(); | ||
leaf.start(currentNode, incomingNode.name, time); | ||
currentNode.addLeaf(leaf); | ||
return leaf; | ||
}; | ||
HeimdallTree.prototype._createNode = function (nodeName, index, nodeMap) { | ||
var node = new HeimdallNode(nodeName, index); | ||
nodeMap.set(index, node); | ||
return node; | ||
}; | ||
HeimdallTree.prototype._chainNode = function (currentNode, nodeName, index, nodeMap) { | ||
var node = this._createNode(nodeName, index, nodeMap); | ||
currentNode.addNode(node); | ||
return node; | ||
}; | ||
HeimdallTree.prototype.construct = function () { | ||
var _this = this; | ||
var events = this._heimdall._events; | ||
var currentLeaf = null; | ||
var currentNode = null; | ||
var nodeMap = new HashMap(); | ||
var openNodes = []; | ||
var node; | ||
var format = this.format; | ||
var counterStore = this._heimdall._monitors; | ||
var stopTime = this.lastKnownTime ? normalizeTime(this.lastKnownTime) : now$1(); | ||
var pageRootIndex = events._length + 1; | ||
currentNode = this.root = this._createNode('page-root', pageRootIndex, nodeMap); | ||
currentLeaf = this._createLeaf(currentNode, 0); | ||
openNodes.push(node); | ||
events.forEach(function (_a, i) { | ||
var op = _a[0], name = _a[1], time = _a[2], counters = _a[3]; | ||
if (op !== OpCodes$1.OP_ANNOTATE) { | ||
time = normalizeTime(time, format); | ||
counters = statsFromCounters(counterStore, counters); | ||
} | ||
switch (op) { | ||
case OpCodes$1.OP_START: | ||
currentNode = _this._chainNode(currentNode, name, i, nodeMap); | ||
openNodes.push(currentNode); | ||
if (currentLeaf) { | ||
currentLeaf.stop(name, time, counters); | ||
} | ||
currentLeaf = _this._createLeaf(currentNode, time); | ||
break; | ||
case OpCodes$1.OP_STOP: | ||
node = nodeMap.get(name); | ||
if (name !== currentNode._id) { | ||
// potentially throw the correct error (already stopped) | ||
if (node) { | ||
node.stop(); | ||
} | ||
else { | ||
throw new Error("Cannot Stop, Attempting to stop a non-existent node!"); | ||
} | ||
throw new Error("Cannot Stop, Attempting to stop a node with an active child!"); | ||
} | ||
currentNode.stop(); | ||
openNodes.splice(openNodes.indexOf(currentNode), 1); | ||
currentNode = currentNode.resumeNode; | ||
currentLeaf.stop(node.name, time, counters); | ||
currentLeaf = _this._chainLeaf(currentNode, node, time); | ||
break; | ||
case OpCodes$1.OP_RESUME: | ||
node = nodeMap.get(name); | ||
node.resume(currentNode); | ||
currentNode = node; | ||
openNodes.push(node); | ||
if (currentLeaf) { | ||
currentLeaf.stop(node.name, time, counters); | ||
} | ||
currentLeaf = _this._chainLeaf(currentNode, node, time); | ||
break; | ||
case OpCodes$1.OP_ANNOTATE: | ||
currentLeaf.annotate(counters); | ||
break; | ||
default: | ||
throw new Error("HeimdallTree encountered an unknown OpCode '" + op + "' during tree construction."); | ||
} | ||
}); | ||
while (currentNode && !currentNode.stopped) { | ||
var name = currentNode.name; | ||
var node_1 = currentNode; | ||
currentNode.stop(); | ||
openNodes.splice(openNodes.indexOf(currentNode), 1); | ||
currentNode = currentNode.resumeNode; | ||
currentLeaf.stop(node.name, time, counters); | ||
currentLeaf = _this._chainLeaf(currentNode, node, time); | ||
break; | ||
case OP_RESUME: | ||
node = nodeMap.get(name); | ||
node.resume(currentNode); | ||
currentNode = node; | ||
openNodes.push(node); | ||
if (currentLeaf) { | ||
currentLeaf.stop(node.name, time, counters); | ||
currentLeaf.stop(node_1.name, stopTime, null); | ||
if (currentNode) { | ||
currentLeaf = this._chainLeaf(currentNode, node_1, stopTime); | ||
} | ||
currentLeaf = _this._chainLeaf(currentNode, node, time); | ||
break; | ||
case OP_ANNOTATE: | ||
currentLeaf.annotate(counters); | ||
break; | ||
default: | ||
throw new Error('HeimdallTree encountered an unknown OpCode \'' + op + '\' during tree construction.'); | ||
} | ||
}); | ||
while (currentNode && !currentNode.stopped) { | ||
var name = currentNode.name; | ||
var _node = currentNode; | ||
currentNode.stop(); | ||
currentNode = currentNode.resumeNode; | ||
currentLeaf.stop(_node.name, stopTime, null); | ||
if (currentNode) { | ||
currentLeaf = this._chainLeaf(currentNode, _node, stopTime); | ||
}; | ||
HeimdallTree.prototype.toJSON = function () { | ||
if (!this.root) { | ||
this.construct(); | ||
} | ||
} | ||
} | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
if (!this.root) { | ||
this.construct(); | ||
} | ||
return { nodes: this.root.toJSONSubgraph() }; | ||
} | ||
}, { | ||
key: 'visitPreOrder', | ||
value: function visitPreOrder(cb) { | ||
return this.root.visitPreOrder(cb); | ||
} | ||
}, { | ||
key: 'visitPostOrder', | ||
value: function visitPostOrder(cb) { | ||
return this.root.visitPostOrder(cb); | ||
} | ||
}, { | ||
key: 'path', | ||
return { | ||
heimdallVersion: '0.3.3', | ||
nodes: this.root.toJSONSubgraph() | ||
}; | ||
}; | ||
HeimdallTree.prototype.visitPreOrder = function (cb) { | ||
this.root.visitPreOrder(cb); | ||
}; | ||
HeimdallTree.prototype.visitPostOrder = function (cb) { | ||
this.root.visitPostOrder(cb); | ||
}; | ||
return HeimdallTree; | ||
}()); | ||
// primarily a test helper, you can get this at any time | ||
// to get an array representing the path of open node names | ||
// from "root" to the last open node. | ||
get: function get() { | ||
var events = this._heimdall._events; | ||
var root = new HeimdallNode('root', 1e9); | ||
var currentNode = root; | ||
var nodeMap = new HashMap(); | ||
var node = void 0; | ||
var top = void 0; | ||
var path = []; | ||
events.forEach(function (_ref3, i) { | ||
var _ref4 = slicedToArray(_ref3, 2); | ||
var op = _ref4[0]; | ||
var name = _ref4[1]; | ||
switch (op) { | ||
case OP_START: | ||
node = new HeimdallNode(name, i); | ||
nodeMap.set(i, node); | ||
currentNode.addNode(node); | ||
currentNode = node; | ||
break; | ||
case OP_STOP: | ||
node = nodeMap.get(name); | ||
if (name !== currentNode._id) { | ||
// potentially throw the correct error (already stopped) | ||
if (node) { | ||
node.stop(); | ||
} else { | ||
throw new Error("Cannot Stop, Attempting to stop a non-existent node!"); | ||
} | ||
throw new Error("Cannot Stop, Attempting to stop a node with an active child!"); | ||
} | ||
currentNode.stop(); | ||
currentNode = currentNode.resumeNode; | ||
break; | ||
case OP_RESUME: | ||
node = nodeMap.get(name); | ||
node.resume(currentNode); | ||
currentNode = node; | ||
break; | ||
default: | ||
throw new Error('HeimdallTree encountered an unknown OpCode \'' + op + '\' during path construction.'); | ||
} | ||
}); | ||
top = currentNode; | ||
while (top !== undefined && top !== root) { | ||
path.unshift(top.name); | ||
top = top.parent; | ||
} | ||
return path; | ||
function setupSession(global) { | ||
// The name of the property encodes the session/node compatibilty version | ||
if (!global._heimdall_session_3) { | ||
global._heimdall_session_3 = new Session(); | ||
} | ||
// primarily a test helper, you can get this at any time | ||
// to get an array representing the "stack" of open node names. | ||
}, { | ||
key: 'stack', | ||
get: function get() { | ||
var events = this._heimdall._events; | ||
var stack = []; | ||
var nodeMap = new HashMap(); | ||
events.forEach(function (_ref5, i) { | ||
var _ref6 = slicedToArray(_ref5, 2); | ||
var op = _ref6[0]; | ||
var name = _ref6[1]; | ||
if (op === OP_START) { | ||
stack.push(name); | ||
nodeMap.set(i, name); | ||
} else if (op === OP_RESUME) { | ||
var n = nodeMap.get(name); | ||
stack.push(n); | ||
} else if (op === OP_STOP) { | ||
var _n = nodeMap.get(name); | ||
if (_n !== stack[stack.length - 1]) { | ||
throw new Error('Invalid Stack!'); | ||
} | ||
stack.pop(); | ||
} | ||
}); | ||
return stack; | ||
} | ||
}], [{ | ||
key: 'fromJSON', | ||
value: function fromJSON(json) { | ||
var events = json.events || []; | ||
var heimdall = { | ||
_timeFormat: json.format || format, | ||
_events: new EventArray(events.length, events), | ||
_monitors: CounterStore.fromJSON(json.monitors) | ||
}; | ||
return new HeimdallTree(heimdall, json.serializationTime); | ||
} | ||
}]); | ||
return HeimdallTree; | ||
}(); | ||
function setupSession(global) { | ||
// The name of the property encodes the session/node compatibilty version | ||
if (!global._heimdall_session_3) { | ||
global._heimdall_session_3 = new HeimdallSession(); | ||
} | ||
} | ||
setupSession(process); | ||
var defaultHeimdall = new Heimdall(process._heimdall_session_3); | ||
defaultHeimdall.now = now$1; | ||
defaultHeimdall.Heimdall = Heimdall; | ||
defaultHeimdall.Session = Session; | ||
defaultHeimdall._Tree = HeimdallTree; | ||
defaultHeimdall._Node = HeimdallNode; | ||
Heimdall.now = now$1; | ||
Heimdall.Session = HeimdallSession; | ||
Heimdall.Tree = HeimdallTree; | ||
Heimdall.Node = HeimdallNode; | ||
var index = new Heimdall(process._heimdall_session_3); | ||
export default index; | ||
export default defaultHeimdall; |
var heimdall = (function () { | ||
// All Credit for this goes to the Ember.js Core Team | ||
// This exists because `Object.create(null)` is absurdly slow compared | ||
// to `new EmptyObject()`. In either case, you want a null prototype | ||
// when you're treating the object instances as arbitrary dictionaries | ||
// and don't want your keys colliding with build-in methods on the | ||
// default object prototype. | ||
var proto = Object.create(null, { | ||
// without this, we will always still end up with (new | ||
// EmptyObject()).constructor === Object | ||
constructor: { | ||
value: undefined, | ||
enumerable: false, | ||
writable: true | ||
} | ||
}); | ||
function EmptyObject() {} | ||
EmptyObject.prototype = proto; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { | ||
return typeof obj; | ||
} : function (obj) { | ||
return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; | ||
}; | ||
var createClass = function () { | ||
function defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
return function (Constructor, protoProps, staticProps) { | ||
if (protoProps) defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) defineProperties(Constructor, staticProps); | ||
return Constructor; | ||
}; | ||
}(); | ||
var slicedToArray = function () { | ||
function sliceIterator(arr, i) { | ||
var _arr = []; | ||
var _n = true; | ||
var _d = false; | ||
var _e = undefined; | ||
try { | ||
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { | ||
_arr.push(_s.value); | ||
if (i && _arr.length === i) break; | ||
} | ||
} catch (err) { | ||
_d = true; | ||
_e = err; | ||
} finally { | ||
try { | ||
if (!_n && _i["return"]) _i["return"](); | ||
} finally { | ||
if (_d) throw _e; | ||
} | ||
} | ||
return _arr; | ||
} | ||
return function (arr, i) { | ||
if (Array.isArray(arr)) { | ||
return arr; | ||
} else if (Symbol.iterator in Object(arr)) { | ||
return sliceIterator(arr, i); | ||
} else { | ||
throw new TypeError("Invalid attempt to destructure non-iterable instance"); | ||
} | ||
}; | ||
}(); | ||
var UNDEFINED_KEY = Object.create(null); | ||
var HashMap = function () { | ||
function HashMap(entries) { | ||
this._data = new EmptyObject(); | ||
if (entries) { | ||
for (var i = 0; i < entries.length; i++) { | ||
this.data[entries[i][0]] = entries[i][1]; | ||
} | ||
var HashMap = (function () { | ||
function HashMap(entries) { | ||
this._data = Object.create(null); | ||
if (entries) { | ||
for (var i = 0; i < entries.length; i++) { | ||
this.data[entries[i][0]] = entries[i][1]; | ||
} | ||
} | ||
} | ||
} | ||
createClass(HashMap, [{ | ||
key: 'forEach', | ||
value: function forEach(cb) { | ||
for (var key in this._data) { | ||
// skip undefined | ||
if (this._data[key] !== UNDEFINED_KEY) { | ||
cb(this._data[key], key); | ||
HashMap.prototype.forEach = function (cb) { | ||
for (var key in this._data) { | ||
// skip undefined | ||
if (this._data[key] !== UNDEFINED_KEY) { | ||
cb(this._data[key], key); | ||
} | ||
} | ||
} | ||
return this; | ||
}; | ||
HashMap.prototype.has = function (key) { | ||
return key in this._data && this._data[key] !== UNDEFINED_KEY; | ||
}; | ||
HashMap.prototype.get = function (key) { | ||
var val = this._data[key]; | ||
return val === UNDEFINED_KEY ? undefined : val; | ||
}; | ||
HashMap.prototype.set = function (key, value) { | ||
this._data[key] = value; | ||
return this; | ||
}; | ||
HashMap.prototype.delete = function (key) { | ||
this._data[key] = UNDEFINED_KEY; | ||
}; | ||
return HashMap; | ||
}()); | ||
return this; | ||
} | ||
}, { | ||
key: 'has', | ||
value: function has(key) { | ||
return key in this._data && this._data[key] !== UNDEFINED_KEY; | ||
} | ||
}, { | ||
key: 'get', | ||
value: function get(key) { | ||
var val = this._data[key]; | ||
return val === UNDEFINED_KEY ? undefined : val; | ||
} | ||
}, { | ||
key: 'set', | ||
value: function set(key, value) { | ||
this._data[key] = value; | ||
return this; | ||
} | ||
}, { | ||
key: 'delete', | ||
value: function _delete(key) { | ||
this._data[key] = UNDEFINED_KEY; | ||
} | ||
}]); | ||
return HashMap; | ||
}(); | ||
var SMALL_ARRAY_LENGTH = 250; | ||
var EventArray = function () { | ||
function EventArray() { | ||
var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH : arguments[0]; | ||
var initialData = arguments[1]; | ||
this.init(length, initialData); | ||
} | ||
createClass(EventArray, [{ | ||
key: "toJSON", | ||
value: function toJSON() { | ||
return this._data.slice(0, this.length); | ||
var EventArray = (function () { | ||
function EventArray(length, initialData) { | ||
if (length === void 0) { length = SMALL_ARRAY_LENGTH; } | ||
this.init(length, initialData); | ||
} | ||
}, { | ||
key: "init", | ||
value: function init() { | ||
var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH : arguments[0]; | ||
var initialData = arguments[1]; | ||
this.length = 0; | ||
this._length = length; | ||
this._data = new Array(length); | ||
if (initialData) { | ||
if (initialData.length > length) { | ||
length = initialData.length; | ||
this._data.length = length; | ||
this._length = length; | ||
EventArray.prototype.toJSON = function () { | ||
return this._data.slice(0, this.length); | ||
}; | ||
EventArray.prototype.init = function (length, initialData) { | ||
if (length === void 0) { length = SMALL_ARRAY_LENGTH; } | ||
this.length = 0; | ||
this._length = length; | ||
this._data = new Array(length); | ||
if (initialData) { | ||
if (initialData.length > length) { | ||
length = initialData.length; | ||
this._data.length = length; | ||
this._length = length; | ||
} | ||
for (var j = 0; j < initialData.length; j++) { | ||
this._data[j] = initialData[j]; | ||
this.length++; | ||
} | ||
} | ||
for (var j = 0; j < initialData.length; j++) { | ||
this._data[j] = initialData[j]; | ||
this.length++; | ||
} | ||
} | ||
} | ||
}; | ||
// TODO this should probably multiple index by 4 to hide | ||
// that we store in a flat array | ||
EventArray.prototype.get = function (index) { | ||
if (index >= 0 && index < this.length) { | ||
return this._data.slice(index, index + 4); | ||
} | ||
return undefined; | ||
}; | ||
EventArray.prototype.set = function (index, value) { | ||
if (index > this.length) { | ||
throw new Error("Index is out of array bounds."); | ||
} | ||
if (index === this.length) { | ||
this.length++; | ||
} | ||
this._data[index] = value; | ||
}; | ||
EventArray.prototype.forEach = function (cb) { | ||
for (var i = 0; i < this.length; i += 4) { | ||
cb(this._data.slice(i, i + 4), i); | ||
} | ||
}; | ||
EventArray.prototype.push = function (op, name, time, data) { | ||
var index = this.length; | ||
this.length += 4; | ||
if (index >= this._length) { | ||
this._length *= 2; | ||
this._data.length = this._length; | ||
} | ||
this._data[index] = op; | ||
this._data[index + 1] = name; | ||
this._data[index + 2] = time; | ||
this._data[index + 3] = data; | ||
return index; | ||
}; | ||
EventArray.prototype.pop = function () { | ||
var index = --this.length; | ||
if (index < 0) { | ||
this.length = 0; | ||
return undefined; | ||
} | ||
return this._data[index]; | ||
}; | ||
return EventArray; | ||
}()); | ||
}, { | ||
key: "get", | ||
value: function get(index) { | ||
if (index >= 0 && index < this.length) { | ||
return this._data.slice(index, index + 4); | ||
} | ||
var HAS_TYPED_ARRAYS = typeof Uint32Array !== 'undefined'; | ||
function hasTypedArrays() { | ||
return HAS_TYPED_ARRAYS; | ||
} | ||
return undefined; | ||
function fill(array, value, start, end) { | ||
if (hasTypedArrays()) { | ||
return array.fill(value, start, end); | ||
} | ||
}, { | ||
key: "set", | ||
value: function set(index, value) { | ||
if (index > this.length) { | ||
throw new Error("Index is out of array bounds."); | ||
} | ||
if (index === this.length) { | ||
this.length++; | ||
} | ||
this._data[index] = value; | ||
else { | ||
var s = start || 0; | ||
var e = end || array.length; | ||
for (; s < e; s++) { | ||
array[s] = value; | ||
} | ||
return array; | ||
} | ||
}, { | ||
key: "forEach", | ||
value: function forEach(cb) { | ||
for (var i = 0; i < this.length; i += 4) { | ||
cb(this._data.slice(i, i + 4), i); | ||
} | ||
} | ||
}, { | ||
key: "push", | ||
value: function push(op, name, time, data) { | ||
var index = this.length; | ||
this.length += 4; | ||
} | ||
if (index >= this._length) { | ||
this._length *= 2; | ||
this._data.length = this._length; | ||
} | ||
this._data[index] = op; | ||
this._data[index + 1] = name; | ||
this._data[index + 2] = time; | ||
this._data[index + 3] = data; | ||
return index; | ||
function grow(array, oldLength, newLength, fillValue) { | ||
if (fillValue === void 0) { fillValue = 0; } | ||
if (hasTypedArrays()) { | ||
var ret = new Uint32Array(newLength); | ||
ret.set(array); | ||
if (fillValue !== 0) { | ||
ret.fill(fillValue, oldLength); | ||
} | ||
return ret; | ||
} | ||
}, { | ||
key: "pop", | ||
value: function pop() { | ||
var index = --this.length; | ||
if (index < 0) { | ||
this.length = 0; | ||
return undefined; | ||
} | ||
return this._data[index]; | ||
else { | ||
array.length = newLength; | ||
fill(array, fillValue, oldLength, newLength); | ||
return array; | ||
} | ||
}]); | ||
return EventArray; | ||
}(); | ||
var A = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; | ||
function fill(array, value, start, end) { | ||
if (typeof array.fill === 'function') { | ||
return array.fill(value, start, end); | ||
} else { | ||
var len = array.length; | ||
var s = start || 0; | ||
var e = end || len; | ||
for (; s < e; s++) { | ||
array[s] = value; | ||
} | ||
return array; | ||
} | ||
} | ||
@@ -261,54 +148,40 @@ | ||
var MAX_ARRAY_LENGTH = 1e6; | ||
var FastIntArray = function () { | ||
function FastIntArray() { | ||
var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH$1 : arguments[0]; | ||
var initialData = arguments[1]; | ||
this.init(length, initialData); | ||
} | ||
createClass(FastIntArray, [{ | ||
key: 'init', | ||
value: function init() { | ||
var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH$1 : arguments[0]; | ||
var initialData = arguments[1]; | ||
this.length = 0; | ||
this._length = length; | ||
this._fill = 0; | ||
this._data = new A(length); | ||
if (initialData) { | ||
if (initialData.length > length) { | ||
length = initialData.length; | ||
this.grow(length); | ||
var FastIntArray = (function () { | ||
function FastIntArray(length, initialData) { | ||
if (length === void 0) { length = SMALL_ARRAY_LENGTH$1; } | ||
this.init(length, initialData); | ||
} | ||
FastIntArray.prototype.init = function (length, initialData) { | ||
if (length === void 0) { length = SMALL_ARRAY_LENGTH$1; } | ||
var useTypedArray = hasTypedArrays(); | ||
this.length = 0; | ||
this._length = length; | ||
this._fillValue = 0; | ||
this._data = useTypedArray ? new Uint32Array(length) : new Array(length); | ||
if (!useTypedArray) { | ||
fill(this._data, this._fillValue); | ||
} | ||
for (var j = 0; j < initialData.length; j++) { | ||
this._data[j] = initialData[j]; | ||
this.length++; | ||
if (initialData) { | ||
if (initialData.length > length) { | ||
length = initialData.length; | ||
this.grow(length); | ||
} | ||
for (var j = 0; j < initialData.length; j++) { | ||
this._data[j] = initialData[j]; | ||
this.length++; | ||
} | ||
} | ||
} | ||
} | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
return this._data.slice(0, this.length); | ||
} | ||
}, { | ||
key: 'get', | ||
value: function get(index) { | ||
if (index >= 0 && index < this.length) { | ||
return this._data[index]; | ||
} | ||
return undefined; | ||
} | ||
}, { | ||
key: 'increment', | ||
value: function increment(index) { | ||
this._data[index]++; | ||
} | ||
}; | ||
FastIntArray.prototype.toJSON = function () { | ||
return this._data.slice(0, this.length); | ||
}; | ||
FastIntArray.prototype.get = function (index) { | ||
if (index >= 0 && index < this.length) { | ||
return this._data[index]; | ||
} | ||
return undefined; | ||
}; | ||
FastIntArray.prototype.increment = function (index) { | ||
this._data[index]++; | ||
}; | ||
/* | ||
@@ -319,44 +192,41 @@ Uint32Arrays have an immutable length. This method | ||
*/ | ||
FastIntArray.prototype.grow = function (newLength) { | ||
this._data = grow(this._data, this._length, newLength, this._fillValue); | ||
this._length = newLength; | ||
}; | ||
FastIntArray.prototype.claim = function (count) { | ||
this.length += count; | ||
while (this.length > this._length) { | ||
this.grow(this._length * 2); | ||
} | ||
}; | ||
FastIntArray.prototype.push = function (int) { | ||
var index = this.length++; | ||
if (index === this._length) { | ||
this.grow(this._length * 2); | ||
} | ||
this._data[index] = int; | ||
}; | ||
return FastIntArray; | ||
}()); | ||
}, { | ||
key: 'grow', | ||
value: function grow(newLength) { | ||
var l = this._length; | ||
this._length = newLength; | ||
var data = this._data; | ||
var _d = this._data = new A(newLength); | ||
_d.set(data); | ||
if (this._fill !== 0) { | ||
fill(_d, this._fill, l); | ||
} | ||
} | ||
}, { | ||
key: 'claim', | ||
value: function claim(count) { | ||
this.length += count; | ||
while (this.length > this._length) { | ||
this.grow(this._length * 2); | ||
} | ||
} | ||
}, { | ||
key: 'push', | ||
value: function push(int) { | ||
var index = this.length++; | ||
if (index === this._length) { | ||
this.grow(this._length * 2); | ||
} | ||
this._data[index] = int; | ||
} | ||
}]); | ||
return FastIntArray; | ||
}(); | ||
var DEFAULT_STORE_SIZE = 1e3; | ||
var DEFAULT_NAMESPACE_SIZE = 10; | ||
/** | ||
* Wrapper type around options for `CounterStore`. | ||
* | ||
* Intentionally left private as `CounterStore` | ||
* only used internally when `HeimdallSession` is created. | ||
* | ||
* @class CounterStoreOptions | ||
*/ | ||
var CounterStoreOptions = (function () { | ||
function CounterStoreOptions(storeSize, namespaceAllocation) { | ||
if (storeSize === void 0) { storeSize = DEFAULT_STORE_SIZE; } | ||
if (namespaceAllocation === void 0) { namespaceAllocation = DEFAULT_NAMESPACE_SIZE; } | ||
this.storeSize = storeSize; | ||
this.namespaceAllocation = namespaceAllocation; | ||
} | ||
return CounterStoreOptions; | ||
}()); | ||
// NULL_NUMBER is a number larger than the largest | ||
@@ -367,196 +237,142 @@ // index we are capable of utilizing in the store. | ||
var LOB = (1 << 16) - 1; | ||
var CounterStore = function () { | ||
function CounterStore() { | ||
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
this.options = options; | ||
this.initialized = false; | ||
this._storeInitialized = false; | ||
this._store = null; | ||
this._namespaceCount = 0; | ||
this._config = null; | ||
this._cache = null; | ||
this._labelCache = null; | ||
this._nameCache = null; | ||
} | ||
createClass(CounterStore, [{ | ||
key: 'clean', | ||
value: function clean() { | ||
this._storeInitialized = false; | ||
this._store = null; | ||
this._cache = null; | ||
var CounterStore = (function () { | ||
function CounterStore(options) { | ||
if (options === void 0) { options = new CounterStoreOptions(); } | ||
this.options = options; | ||
this.initialized = false; | ||
this._storeInitialized = false; | ||
this._store = null; | ||
this._namespaceCount = 0; | ||
this._config = null; | ||
this._cache = null; | ||
this._labelCache = null; | ||
this._nameCache = null; | ||
} | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
return { | ||
_namespaceCount: this._namespaceCount, | ||
_config: this._config, | ||
_labelCache: this._labelCache, | ||
_nameCache: this._nameCache, | ||
_store: this._store | ||
}; | ||
} | ||
}, { | ||
key: 'registerNamespace', | ||
value: function registerNamespace(name, labels) { | ||
this._initializeIfNeeded(); | ||
var numCounters = labels.length; | ||
var namespaceIndex = this._namespaceCount++; | ||
var bitNamespaceIndex = namespaceIndex << 16; | ||
var namespace = new EmptyObject(); | ||
// we also generate a map between the counters | ||
// and these labels so that we can reconstruct | ||
// a meaningful structure later. | ||
this._nameCache[namespaceIndex] = name; | ||
this._labelCache[name] = labels; | ||
// grow the existing config and cache to account | ||
// for the new namespace | ||
this._config.push(numCounters); | ||
if (this._cache !== null) { | ||
CounterStore.prototype.clean = function () { | ||
this._storeInitialized = false; | ||
this._store = null; | ||
this._cache = null; | ||
}; | ||
CounterStore.prototype.toJSON = function () { | ||
return { | ||
_namespaceCount: this._namespaceCount, | ||
_config: this._config, | ||
_labelCache: this._labelCache, | ||
_nameCache: this._nameCache, | ||
_store: this._store | ||
}; | ||
}; | ||
CounterStore.fromJSON = function (json) { | ||
var store = new CounterStore(); | ||
store._namespaceCount = json._namespaceCount; | ||
store._labelCache = json._labelCache; | ||
store._nameCache = json._nameCache; | ||
if (json._store) { | ||
store._store = new FastIntArray(json._store.length, json._store); | ||
} | ||
if (json._config) { | ||
store._config = new FastIntArray(json._config.length, json._config); | ||
} | ||
return store; | ||
}; | ||
CounterStore.prototype.registerNamespace = function (name, labels) { | ||
this._initializeIfNeeded(); | ||
var numCounters = labels.length; | ||
var namespaceIndex = this._namespaceCount++; | ||
var bitNamespaceIndex = namespaceIndex << 16; | ||
var namespace = Object.create(null); | ||
// we also generate a map between the counters | ||
// and these labels so that we can reconstruct | ||
// a meaningful structure later. | ||
this._nameCache[namespaceIndex] = name; | ||
this._labelCache[name] = labels; | ||
// grow the existing config and cache to account | ||
// for the new namespace | ||
this._config.push(numCounters); | ||
if (this._cache !== null) { | ||
this._cache = grow(this._cache, namespaceIndex, this._namespaceCount, NULL_NUMBER); | ||
} | ||
for (var i = 0; i < numCounters; i++) { | ||
namespace[labels[i]] = bitNamespaceIndex + i; | ||
} | ||
return namespace; | ||
}; | ||
CounterStore.prototype._initializeIfNeeded = function () { | ||
if (this.initialized === false) { | ||
this._config = new FastIntArray(this.options.namespaceAllocation); | ||
this._labelCache = Object.create(null); | ||
this._nameCache = Object.create(null); | ||
this.initialized = true; | ||
} | ||
}; | ||
CounterStore.prototype.restoreFromCache = function (cache) { | ||
var stats = Object.create(null); | ||
for (var i = 0; i < cache.length; i++) { | ||
if (cache[i] !== NULL_NUMBER) { | ||
var startIndex = cache[i]; | ||
var namespace = this._nameCache[i]; | ||
var counterCount = this._config.get(i); | ||
stats[namespace] = Object.create(null); | ||
for (var j = 0; j < counterCount; j++) { | ||
var storeIndex = startIndex + j; | ||
var label = this._labelCache[namespace][j]; | ||
stats[namespace][label] = this._store.get(storeIndex); | ||
} | ||
} | ||
} | ||
return stats; | ||
}; | ||
CounterStore.prototype.increment = function (counter) { | ||
var namespaceIndex = counter >> 16; | ||
var counterIndex = counter & LOB; | ||
if (this._cache === null) { | ||
this._initializeStoreIfNeeded(); | ||
var a = hasTypedArrays() ? new Uint32Array(this._namespaceCount) : new Array(this._namespaceCount); | ||
this._cache = fill(a, NULL_NUMBER); | ||
} | ||
if (this._cache[namespaceIndex] === NULL_NUMBER) { | ||
var counterCount = this._config.get(namespaceIndex); | ||
this._cache[namespaceIndex] = this._store.length; | ||
this._store.claim(counterCount); | ||
} | ||
var storeIndex = this._cache[namespaceIndex] + counterIndex; | ||
this._store.increment(storeIndex); | ||
}; | ||
CounterStore.prototype._initializeStoreIfNeeded = function () { | ||
if (this._storeInitialized === false) { | ||
this._store = new FastIntArray(this.options.storeSize); | ||
this._storeInitialized = true; | ||
} | ||
}; | ||
CounterStore.prototype.has = function (name) { | ||
return this._labelCache && name in this._labelCache; | ||
}; | ||
CounterStore.prototype.cache = function () { | ||
var cache = this._cache; | ||
this._cache = null; | ||
return cache; | ||
}; | ||
return CounterStore; | ||
}()); | ||
this._cache = new A(this._namespaceCount); | ||
this._cache.set(cache); | ||
this._cache[namespaceIndex] = NULL_NUMBER; | ||
} | ||
for (var i = 0; i < numCounters; i++) { | ||
namespace[labels[i]] = bitNamespaceIndex + i; | ||
} | ||
return namespace; | ||
var Session = (function () { | ||
function HeimdallSession() { | ||
this.init(); | ||
} | ||
}, { | ||
key: '_initializeIfNeeded', | ||
value: function _initializeIfNeeded() { | ||
if (this.initialized === false) { | ||
this._config = new FastIntArray(this.options.namespaceAllocation || DEFAULT_NAMESPACE_SIZE); | ||
this._labelCache = new EmptyObject(); | ||
this._nameCache = new EmptyObject(); | ||
this.initialized = true; | ||
} | ||
} | ||
}, { | ||
key: 'restoreFromCache', | ||
value: function restoreFromCache(cache) { | ||
var stats = new EmptyObject(); | ||
for (var i = 0; i < cache.length; i++) { | ||
if (cache[i] !== NULL_NUMBER) { | ||
var startIndex = cache[i]; | ||
var namespace = this._nameCache[i]; | ||
var counterCount = this._config.get(i); | ||
stats[namespace] = new EmptyObject(); | ||
for (var j = 0; j < counterCount; j++) { | ||
var storeIndex = startIndex + j; | ||
var label = this._labelCache[namespace][j]; | ||
stats[namespace][label] = this._store.get(storeIndex); | ||
} | ||
} | ||
} | ||
return stats; | ||
} | ||
}, { | ||
key: 'increment', | ||
value: function increment(counter) { | ||
var namespaceIndex = counter >> 16; | ||
var counterIndex = counter & LOB; | ||
if (this._cache === null) { | ||
this._initializeStoreIfNeeded(); | ||
this._cache = fill(new A(this._namespaceCount), NULL_NUMBER); | ||
} | ||
if (this._cache[namespaceIndex] === NULL_NUMBER) { | ||
var counterCount = this._config.get(namespaceIndex); | ||
this._cache[namespaceIndex] = this._store.length; | ||
this._store.claim(counterCount); | ||
} | ||
var storeIndex = this._cache[namespaceIndex] + counterIndex; | ||
this._store.increment(storeIndex); | ||
} | ||
}, { | ||
key: '_initializeStoreIfNeeded', | ||
value: function _initializeStoreIfNeeded() { | ||
if (this._storeInitialized === false) { | ||
this._store = new FastIntArray(this.options.storeSize || DEFAULT_STORE_SIZE); | ||
this._storeInitialized = true; | ||
} | ||
} | ||
}, { | ||
key: 'has', | ||
value: function has(name) { | ||
return this._labelCache && name in this._labelCache; | ||
} | ||
}, { | ||
key: 'cache', | ||
value: function cache() { | ||
var cache = this._cache; | ||
this._cache = null; | ||
return cache; | ||
} | ||
}], [{ | ||
key: 'fromJSON', | ||
value: function fromJSON(json) { | ||
var store = new CounterStore(); | ||
store._namespaceCount = json._namespaceCount; | ||
store._labelCache = json._labelCache; | ||
store._nameCache = json._nameCache; | ||
if (json._store) { | ||
store._store = new FastIntArray(json._store.length, json._store); | ||
} | ||
if (json._config) { | ||
store._config = new FastIntArray(json._config.length, json._config); | ||
} | ||
} | ||
}]); | ||
return CounterStore; | ||
}(); | ||
// provides easily interceptable indirection. | ||
var HeimdallSession = function () { | ||
function HeimdallSession() { | ||
this.init(); | ||
} | ||
createClass(HeimdallSession, [{ | ||
key: 'init', | ||
value: function init() { | ||
this.monitors = new CounterStore(); | ||
this.configs = new HashMap(); | ||
this.events = new EventArray(640000 * 4); | ||
} | ||
HeimdallSession.prototype.init = function () { | ||
this.monitors = new CounterStore(); | ||
this.configs = new HashMap(); | ||
this.events = new EventArray(640000 * 4); | ||
}; | ||
// mostly for test helper purposes | ||
HeimdallSession.prototype.reset = function () { | ||
this.monitors.clean(); | ||
this.events.length = 0; | ||
}; | ||
return HeimdallSession; | ||
}()); | ||
}, { | ||
key: 'reset', | ||
value: function reset() { | ||
this.monitors.clean(); | ||
this.events.length = 0; | ||
} | ||
}]); | ||
return HeimdallSession; | ||
}(); | ||
var now = void 0; | ||
var format = void 0; | ||
var ORIGIN_TIME = void 0; | ||
var now; | ||
var format; | ||
var ORIGIN_TIME; | ||
// It turns out to be nicer for perf to bind than to close over the time method | ||
@@ -567,125 +383,128 @@ // however, when testing we need to be able to stub the clock via the global | ||
var IS_TESTING = freeGlobal.IS_HEIMDALL_TEST_ENVIRONMENT; | ||
if ((typeof performance === 'undefined' ? 'undefined' : _typeof(performance)) === 'object' && typeof performance.now === 'function') { | ||
now = IS_TESTING ? function now() { | ||
return performance.now(); | ||
} : performance.now.bind(performance); | ||
format = 'milli'; | ||
} else if (typeof process !== 'undefined' && typeof process.hrtime === 'function') { | ||
now = IS_TESTING ? function now() { | ||
return process.hrtime(); | ||
} : process.hrtime.bind(process); | ||
format = 'hrtime'; | ||
} else { | ||
ORIGIN_TIME = Date.now(); | ||
now = Date.now.bind(Date); | ||
format = 'timestamp'; | ||
if (typeof performance === 'object' && typeof performance.now === 'function') { | ||
now = IS_TESTING ? function now() { return performance.now(); } : performance.now.bind(performance); | ||
format = 'milli'; | ||
} | ||
function normalizeTime(time) { | ||
var format = arguments.length <= 1 || arguments[1] === undefined ? format : arguments[1]; | ||
switch (format) { | ||
case 'milli': | ||
return milliToNano(time); | ||
case 'hrtime': | ||
return timeFromHRTime(time); | ||
case 'timestamp': | ||
return milliToNano(time - ORIGIN_TIME); | ||
default: | ||
throw new Error('Unknown Format'); | ||
} | ||
else if (typeof process !== 'undefined' && typeof process.hrtime === 'function') { | ||
now = IS_TESTING ? function now() { return process.hrtime(); } : process.hrtime.bind(process); | ||
format = 'hrtime'; | ||
} | ||
else { | ||
ORIGIN_TIME = Date.now(); | ||
now = Date.now.bind(Date); | ||
format = 'timestamp'; | ||
} | ||
function normalizeTime(time, optionalFormat) { | ||
if (optionalFormat === void 0) { optionalFormat = format; } | ||
switch (optionalFormat) { | ||
case 'milli': | ||
return milliToNano(time); | ||
case 'hrtime': | ||
return timeFromHRTime(time); | ||
case 'timestamp': | ||
return milliToNano(time - ORIGIN_TIME); | ||
default: | ||
throw new Error('Unknown Format'); | ||
} | ||
} | ||
function milliToNano(time) { | ||
return Math.floor(time * 1e6); | ||
return Math.floor(time * 1e6); | ||
} | ||
function timeFromHRTime(hrtime) { | ||
return hrtime[0] * 1e9 + hrtime[1]; | ||
return hrtime[0] * 1e9 + hrtime[1]; | ||
} | ||
var now$1 = now; | ||
var OP_START = 0; | ||
var OP_STOP = 1; | ||
var OP_RESUME = 2; | ||
var OP_ANNOTATE = 3; | ||
var OpCodes; | ||
(function (OpCodes) { | ||
OpCodes[OpCodes["OP_START"] = 0] = "OP_START"; | ||
OpCodes[OpCodes["OP_STOP"] = 1] = "OP_STOP"; | ||
OpCodes[OpCodes["OP_RESUME"] = 2] = "OP_RESUME"; | ||
OpCodes[OpCodes["OP_ANNOTATE"] = 3] = "OP_ANNOTATE"; | ||
})(OpCodes || (OpCodes = {})); | ||
var OpCodes$1 = OpCodes; | ||
var Heimdall = function () { | ||
function Heimdall(session) { | ||
if (arguments.length < 1) { | ||
this._session = new HeimdallSession(); | ||
this.start('session-root'); | ||
} else { | ||
this._session = session; | ||
var VERSION = '0.3.3'; | ||
var Heimdall = (function () { | ||
function Heimdall(session) { | ||
if (arguments.length < 1) { | ||
this._session = new Session(); | ||
this.start('session-root'); | ||
} | ||
else { | ||
this._session = session; | ||
} | ||
} | ||
} | ||
createClass(Heimdall, [{ | ||
key: '_retrieveCounters', | ||
value: function _retrieveCounters() { | ||
return this._monitors.cache(); | ||
} | ||
}, { | ||
key: 'start', | ||
value: function start(name) { | ||
return this._session.events.push(OP_START, name, now$1(), this._retrieveCounters()); | ||
} | ||
}, { | ||
key: 'stop', | ||
value: function stop(token) { | ||
this._session.events.push(OP_STOP, token, now$1(), this._retrieveCounters()); | ||
} | ||
}, { | ||
key: 'resume', | ||
value: function resume(token) { | ||
this._session.events.push(OP_RESUME, token, now$1(), this._retrieveCounters()); | ||
} | ||
}, { | ||
key: 'annotate', | ||
value: function annotate(info) { | ||
// This has the side effect of making events heterogenous, as info is an object | ||
// while counters will always be `null` or an `Array` | ||
this._session.events.push(OP_ANNOTATE, NULL_NUMBER, NULL_NUMBER, info); | ||
} | ||
}, { | ||
key: 'hasMonitor', | ||
value: function hasMonitor(name) { | ||
return !!this._monitors.has(name); | ||
} | ||
}, { | ||
key: 'registerMonitor', | ||
value: function registerMonitor(name) { | ||
if (name === 'own' || name === 'time') { | ||
throw new Error('Cannot register monitor at namespace "' + name + '". "own" and "time" are reserved'); | ||
} | ||
if (this.hasMonitor(name)) { | ||
throw new Error('A monitor for "' + name + '" is already registered"'); | ||
} | ||
for (var _len = arguments.length, keys = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
keys[_key - 1] = arguments[_key]; | ||
} | ||
return this._monitors.registerNamespace(name, keys); | ||
} | ||
}, { | ||
key: 'increment', | ||
value: function increment(token) { | ||
this._session.monitors.increment(token); | ||
} | ||
}, { | ||
key: 'configFor', | ||
value: function configFor(name) { | ||
var config = this._session.configs.get(name); | ||
if (!config) { | ||
config = new EmptyObject(); | ||
this._session.configs.set(name, config); | ||
} | ||
return config; | ||
} | ||
Object.defineProperty(Heimdall, "VERSION", { | ||
get: function () { | ||
return VERSION; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(Heimdall.prototype, "VERSION", { | ||
get: function () { | ||
return VERSION; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(Heimdall.prototype, "_monitors", { | ||
get: function () { | ||
return this._session.monitors; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(Heimdall.prototype, "_events", { | ||
get: function () { | ||
return this._session.events; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Heimdall.prototype._retrieveCounters = function () { | ||
return this._monitors.cache(); | ||
}; | ||
Heimdall.prototype.start = function (name) { | ||
return this._session.events.push(OpCodes$1.OP_START, name, now$1(), this._retrieveCounters()); | ||
}; | ||
Heimdall.prototype.stop = function (token) { | ||
this._session.events.push(OpCodes$1.OP_STOP, token, now$1(), this._retrieveCounters()); | ||
}; | ||
Heimdall.prototype.resume = function (token) { | ||
this._session.events.push(OpCodes$1.OP_RESUME, token, now$1(), this._retrieveCounters()); | ||
}; | ||
Heimdall.prototype.annotate = function (info) { | ||
// This has the side effect of making events heterogenous, as info is an object | ||
// while counters will always be `null` or an `Array` | ||
this._session.events.push(OpCodes$1.OP_ANNOTATE, NULL_NUMBER, NULL_NUMBER, info); | ||
}; | ||
Heimdall.prototype.hasMonitor = function (name) { | ||
return !!this._monitors.has(name); | ||
}; | ||
Heimdall.prototype.registerMonitor = function (name) { | ||
var keys = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
keys[_i - 1] = arguments[_i]; | ||
} | ||
if (name === 'own' || name === 'time') { | ||
throw new Error('Cannot register monitor at namespace "' + name + '". "own" and "time" are reserved'); | ||
} | ||
if (this.hasMonitor(name)) { | ||
throw new Error('A monitor for "' + name + '" is already registered"'); | ||
} | ||
return this._monitors.registerNamespace(name, keys); | ||
}; | ||
Heimdall.prototype.increment = function (token) { | ||
this._session.monitors.increment(token); | ||
}; | ||
Heimdall.prototype.configFor = function (name) { | ||
var config = this._session.configs.get(name); | ||
if (!config) { | ||
config = Object.create(null); | ||
this._session.configs.set(name, config); | ||
} | ||
return config; | ||
}; | ||
/* | ||
@@ -696,260 +515,200 @@ Ideally, this method should only be used for serializing | ||
*/ | ||
Heimdall.prototype.toJSON = function () { | ||
return { | ||
heimdallVersion: VERSION, | ||
format, | ||
monitors: this._monitors.toJSON(), | ||
events: this._events.toJSON(), | ||
serializationTime: now$1() | ||
}; | ||
}; | ||
Heimdall.prototype.toString = function () { | ||
return JSON.stringify(this.toJSON()); | ||
}; | ||
return Heimdall; | ||
}()); | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
return { | ||
format: format, | ||
monitors: this._monitors.toJSON(), | ||
events: this._events.toJSON(), | ||
serializationTime: now$1() | ||
}; | ||
var HeimdallNode = (function () { | ||
function HeimdallNode(name, id) { | ||
this._id = id; | ||
this.parent = null; | ||
this.resumeNode = null; | ||
this.name = name; | ||
this.stopped = false; | ||
this.leaves = []; | ||
this.nodes = []; | ||
this.children = []; | ||
} | ||
}, { | ||
key: 'toString', | ||
value: function toString() { | ||
return JSON.stringify(this.toJSON()); | ||
} | ||
}, { | ||
key: '_monitors', | ||
get: function get() { | ||
return this._session.monitors; | ||
} | ||
}, { | ||
key: '_events', | ||
get: function get() { | ||
return this._session.events; | ||
} | ||
}]); | ||
return Heimdall; | ||
}(); | ||
Object.defineProperty(HeimdallNode.prototype, "stats", { | ||
get: function () { | ||
var own = { | ||
selfTime: 0, | ||
duration: 0, | ||
startTime: this.leaves[0].startTime, | ||
endTime: this.leaves[this.leaves.length - 1].endTime | ||
}; | ||
own.duration = own.endTime - own.startTime; | ||
var counters = []; | ||
var annotations = []; | ||
var stats = { | ||
self: own | ||
}; | ||
this.forEachLeaf(function (leaf) { | ||
own.selfTime += leaf.selfTime; | ||
annotations.push(leaf.annotations); | ||
for (var namespace in leaf.counters) { | ||
var value = leaf.counters[namespace]; | ||
if (!stats.hasOwnProperty(namespace)) { | ||
stats[namespace] = value; | ||
} | ||
else { | ||
for (var label in value) { | ||
stats[namespace][label] += value[label]; | ||
} | ||
} | ||
} | ||
counters.push(leaf.counters); | ||
}); | ||
return stats; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
HeimdallNode.prototype.stop = function () { | ||
if (this.stopped === true) { | ||
throw new Error('Cannot Stop node, already stopped!'); | ||
} | ||
this.stopped = true; | ||
}; | ||
HeimdallNode.prototype.resume = function (resumeNode) { | ||
if (!this.stopped) { | ||
throw new Error('Cannot Resume node, already running!'); | ||
} | ||
this.resumeNode = resumeNode; | ||
this.stopped = false; | ||
}; | ||
HeimdallNode.prototype.addLeaf = function (leaf) { | ||
leaf.owner = this; | ||
this.leaves.push(leaf); | ||
this.children.push(leaf); | ||
}; | ||
HeimdallNode.prototype.addNode = function (node) { | ||
if (node.parent) { | ||
throw new Error("Cannot set parent of node '" + node.name + "', node already has a parent!"); | ||
} | ||
node.parent = this; | ||
node.resumeNode = this; | ||
this.nodes.push(node); | ||
this.children.push(node); | ||
}; | ||
Object.defineProperty(HeimdallNode.prototype, "isRoot", { | ||
get: function () { | ||
return this.parent === null; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
HeimdallNode.prototype.visitPreOrder = function (cb) { | ||
cb(this); | ||
for (var i = 0; i < this.nodes.length; i++) { | ||
this.nodes[i].visitPreOrder(cb); | ||
} | ||
}; | ||
HeimdallNode.prototype.visitPostOrder = function (cb) { | ||
for (var i = 0; i < this.nodes.length; i++) { | ||
this.nodes[i].visitPostOrder(cb); | ||
} | ||
cb(this); | ||
}; | ||
HeimdallNode.prototype.forEachNode = function (cb) { | ||
for (var i = 0; i < this.nodes.length; ++i) { | ||
cb(this.nodes[i]); | ||
} | ||
}; | ||
HeimdallNode.prototype.forEachLeaf = function (cb) { | ||
for (var i = 0; i < this.leaves.length; ++i) { | ||
cb(this.leaves[i]); | ||
} | ||
}; | ||
HeimdallNode.prototype.forEachChild = function (cb) { | ||
for (var i = 0; i < this.children.length; ++i) { | ||
cb(this.children[i]); | ||
} | ||
}; | ||
HeimdallNode.prototype.toJSON = function () { | ||
return { | ||
_id: this._id, | ||
name: this.name, | ||
leaves: this.leaves.map(function (leaf) { return leaf.toJSON(); }), | ||
nodes: this.nodes.map(function (child) { return child._id; }), | ||
children: this.children.map(function (child) { return child._id; }) | ||
}; | ||
}; | ||
HeimdallNode.prototype.toJSONSubgraph = function () { | ||
var nodes = []; | ||
this.visitPreOrder(function (node) { return nodes.push(node.toJSON()); }); | ||
return nodes; | ||
}; | ||
return HeimdallNode; | ||
}()); | ||
var HeimdallNode = function () { | ||
function HeimdallNode(name, id) { | ||
this._id = id; | ||
this.parent = null; | ||
this.resumeNode = null; | ||
this.name = name; | ||
this.stopped = false; | ||
this.leaves = []; | ||
this.nodes = []; | ||
this.children = []; | ||
} | ||
createClass(HeimdallNode, [{ | ||
key: 'stop', | ||
value: function stop() { | ||
if (this.stopped === true) { | ||
throw new Error('Cannot Stop node, already stopped!'); | ||
} | ||
this.stopped = true; | ||
var HeimdallLeaf = (function () { | ||
function HeimdallLeaf() { | ||
// set on start | ||
this._id = null; | ||
this.owner = null; | ||
this.previousOp = null; | ||
this.startTime = 0; | ||
// set on annotate | ||
this.annotations = null; | ||
// set on stop | ||
this.nextOp = null; | ||
this.endTime = 0; | ||
this.counters = null; | ||
this.name = null; | ||
} | ||
}, { | ||
key: 'resume', | ||
value: function resume(resumeNode) { | ||
if (!this.stopped) { | ||
throw new Error('Cannot Resume node, already running!'); | ||
} | ||
this.resumeNode = resumeNode; | ||
this.stopped = false; | ||
} | ||
}, { | ||
key: 'addLeaf', | ||
value: function addLeaf(leaf) { | ||
leaf.owner = this; | ||
this.leaves.push(leaf); | ||
this.children.push(leaf); | ||
} | ||
}, { | ||
key: 'addNode', | ||
value: function addNode(node) { | ||
if (node.parent) { | ||
throw new Error('Cannot set parent of node \'' + node.name + '\', node already has a parent!'); | ||
} | ||
node.parent = this; | ||
node.resumeNode = this; | ||
this.nodes.push(node); | ||
this.children.push(node); | ||
} | ||
}, { | ||
key: 'visitPreOrder', | ||
value: function visitPreOrder(cb) { | ||
cb(this); | ||
for (var i = 0; i < this.nodes.length; i++) { | ||
this.nodes[i].visitPreOrder(cb); | ||
} | ||
} | ||
}, { | ||
key: 'visitPostOrder', | ||
value: function visitPostOrder(cb) { | ||
for (var i = 0; i < this.nodes.length; i++) { | ||
this.nodes[i].visitPostOrder(cb); | ||
} | ||
cb(this); | ||
} | ||
}, { | ||
key: 'forEachNode', | ||
value: function forEachNode(cb) { | ||
for (var i = 0; i < this.nodes.length; ++i) { | ||
cb(this.nodes[i]); | ||
} | ||
} | ||
}, { | ||
key: 'forEachLeaf', | ||
value: function forEachLeaf(cb) { | ||
for (var i = 0; i < this.leaves.length; ++i) { | ||
cb(this.leaves[i]); | ||
} | ||
} | ||
}, { | ||
key: 'forEachChild', | ||
value: function forEachChild(cb) { | ||
for (var i = 0; i < this.children.length; ++i) { | ||
cb(this.children[i]); | ||
} | ||
} | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
return { | ||
_id: this._id, | ||
name: this.name, | ||
leaves: this.leaves.map(function (leaf) { | ||
return leaf.toJSON(); | ||
}), | ||
nodes: this.nodes.map(function (child) { | ||
return child._id; | ||
}), | ||
children: this.children.map(function (child) { | ||
return child._id; | ||
}) | ||
}; | ||
} | ||
}, { | ||
key: 'toJSONSubgraph', | ||
value: function toJSONSubgraph() { | ||
var nodes = []; | ||
this.visitPreOrder(function (node) { | ||
return nodes.push(node.toJSON()); | ||
}); | ||
return nodes; | ||
} | ||
}, { | ||
key: 'stats', | ||
get: function get() { | ||
var own = { | ||
selfTime: 0, | ||
duration: 0, | ||
startTime: this.leaves[0].startTime, | ||
endTime: this.leaves[this.leaves.length - 1].endTime | ||
}; | ||
own.duration = own.endTime - own.startTime; | ||
var counters = []; | ||
var annotations = []; | ||
var stats = { | ||
self: own | ||
}; | ||
this.forEachLeaf(function (leaf) { | ||
own.selfTime += leaf.selfTime; | ||
annotations.push(leaf.annotations); | ||
for (var namespace in leaf.counters) { | ||
var value = leaf.counters[namespace]; | ||
if (!stats.hasOwnProperty(namespace)) { | ||
stats[namespace] = value; | ||
} else { | ||
for (var label in value) { | ||
stats[namespace][label] += value[label]; | ||
} | ||
} | ||
Object.defineProperty(HeimdallLeaf.prototype, "selfTime", { | ||
get: function () { | ||
return this.endTime - this.startTime; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(HeimdallLeaf.prototype, "isStopped", { | ||
get: function () { | ||
return this.endTime !== 0; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
HeimdallLeaf.prototype.annotate = function (annotation) { | ||
if (this.annotations === null) { | ||
this.annotations = []; | ||
} | ||
this.annotations.push(annotation); | ||
}; | ||
HeimdallLeaf.prototype.start = function (owner, previousOp, time) { | ||
this.owner = owner; | ||
this.previousOp = previousOp; | ||
this.startTime = time; | ||
}; | ||
HeimdallLeaf.prototype.stop = function (nextOp, time, counters) { | ||
this.nextOp = nextOp; | ||
this.endTime = time; | ||
this.counters = counters; | ||
this._id = this.name = "[" + this.owner.name + "]#" + this.previousOp + ":" + nextOp; | ||
}; | ||
HeimdallLeaf.prototype.toJSON = function () { | ||
return { | ||
_id: this._id, | ||
name: this.name, | ||
startTime: this.startTime, | ||
endTime: this.endTime, | ||
counters: this.counters, | ||
annotations: this.annotations | ||
}; | ||
}; | ||
return HeimdallLeaf; | ||
}()); | ||
counters.push(leaf.counters); | ||
}); | ||
return stats; | ||
} | ||
}, { | ||
key: 'isRoot', | ||
get: function get() { | ||
return this.parent === null; | ||
} | ||
}]); | ||
return HeimdallNode; | ||
}(); | ||
var HeimdallLeaf = function () { | ||
function HeimdallLeaf() { | ||
// set on start | ||
this._id = null; | ||
this.owner = null; | ||
this.previousOp = null; | ||
this.startTime = 0; | ||
// set on annotate | ||
this.annotations = null; | ||
// set on stop | ||
this.nextOp = null; | ||
this.endTime = 0; | ||
this.counters = null; | ||
this.name = null; | ||
} | ||
createClass(HeimdallLeaf, [{ | ||
key: "annotate", | ||
value: function annotate(annotation) { | ||
if (this.annotations === null) { | ||
this.annotations = []; | ||
} | ||
this.annotations.push(annotation); | ||
} | ||
}, { | ||
key: "start", | ||
value: function start(owner, previousOp, time) { | ||
this.owner = owner; | ||
this.previousOp = previousOp; | ||
this.startTime = time; | ||
} | ||
}, { | ||
key: "stop", | ||
value: function stop(nextOp, time, counters) { | ||
this.nextOp = nextOp; | ||
this.endTime = time; | ||
this.counters = counters; | ||
this._id = this.name = "[" + this.owner.name + "]#" + this.previousOp + ":" + nextOp; | ||
} | ||
}, { | ||
key: "toJSON", | ||
value: function toJSON() { | ||
return { | ||
_id: this._id, | ||
name: this.name, | ||
startTime: this.startTime, | ||
endTime: this.endTime, | ||
counters: this.counters, | ||
annotations: this.annotations | ||
}; | ||
} | ||
}, { | ||
key: "selfTime", | ||
get: function get() { | ||
return this.endTime - this.startTime; | ||
} | ||
}, { | ||
key: "isStopped", | ||
get: function get() { | ||
return this.endTime !== 0; | ||
} | ||
}]); | ||
return HeimdallLeaf; | ||
}(); | ||
/* | ||
@@ -983,299 +742,237 @@ Example Event Timeline and tree reconstruction | ||
*/ | ||
function statsFromCounters(counterStore, counterCache) { | ||
if (!counterStore || !counterCache) { | ||
return null; | ||
} | ||
return counterStore.restoreFromCache(counterCache); | ||
if (!counterStore || !counterCache) { | ||
return null; | ||
} | ||
return counterStore.restoreFromCache(counterCache); | ||
} | ||
var HeimdallTree = function () { | ||
function HeimdallTree(heimdall, lastKnownTime) { | ||
this._heimdall = heimdall; | ||
this.root = null; | ||
this.format = heimdall && heimdall._timeFormat ? heimdall._timeFormat : format; | ||
this.lastKnownTime = lastKnownTime; | ||
} | ||
createClass(HeimdallTree, [{ | ||
key: '_createLeaf', | ||
value: function _createLeaf(currentNode, time) { | ||
var leaf = new HeimdallLeaf(); | ||
leaf.start(currentNode, currentNode.name, time); | ||
currentNode.addLeaf(leaf); | ||
return leaf; | ||
var HeimdallTree = (function () { | ||
function HeimdallTree(heimdall, lastKnownTime) { | ||
this._heimdall = heimdall; | ||
this.root = null; | ||
this.format = heimdall && heimdall._timeFormat ? heimdall._timeFormat : format; | ||
this.lastKnownTime = lastKnownTime; | ||
} | ||
}, { | ||
key: '_chainLeaf', | ||
value: function _chainLeaf(currentNode, incomingNode, time) { | ||
var leaf = new HeimdallLeaf(); | ||
leaf.start(currentNode, incomingNode.name, time); | ||
currentNode.addLeaf(leaf); | ||
return leaf; | ||
} | ||
}, { | ||
key: '_createNode', | ||
value: function _createNode(nodeName, index, nodeMap) { | ||
var node = new HeimdallNode(nodeName, index); | ||
nodeMap.set(index, node); | ||
return node; | ||
} | ||
}, { | ||
key: '_chainNode', | ||
value: function _chainNode(currentNode, nodeName, index, nodeMap) { | ||
var node = this._createNode(nodeName, index, nodeMap); | ||
currentNode.addNode(node); | ||
return node; | ||
} | ||
}, { | ||
key: 'construct', | ||
value: function construct() { | ||
var _this = this; | ||
var events = this._heimdall._events; | ||
var currentLeaf = null; | ||
var currentNode = null; | ||
var nodeMap = new HashMap(); | ||
var openNodes = []; | ||
var node = void 0; | ||
var format = this.format; | ||
var counterStore = this._heimdall._monitors; | ||
var stopTime = this.lastKnownTime ? normalizeTime(this.lastKnownTime) : now$1(); | ||
var pageRootIndex = events._length + 1; | ||
currentNode = this.root = this._createNode('page-root', pageRootIndex, nodeMap); | ||
currentLeaf = this._createLeaf(currentNode, 0); | ||
openNodes.push(node); | ||
events.forEach(function (_ref, i) { | ||
var _ref2 = slicedToArray(_ref, 4); | ||
var op = _ref2[0]; | ||
var name = _ref2[1]; | ||
var time = _ref2[2]; | ||
var counters = _ref2[3]; | ||
if (op !== OP_ANNOTATE) { | ||
time = normalizeTime(time, format); | ||
counters = statsFromCounters(counterStore, counters); | ||
} | ||
switch (op) { | ||
case OP_START: | ||
currentNode = _this._chainNode(currentNode, name, i, nodeMap); | ||
openNodes.push(currentNode); | ||
if (currentLeaf) { | ||
currentLeaf.stop(name, time, counters); | ||
HeimdallTree.fromJSON = function (json) { | ||
var events = json.events || []; | ||
var heimdall = { | ||
_timeFormat: json.format || format, | ||
_events: new EventArray(events.length, events), | ||
_monitors: CounterStore.fromJSON(json.monitors) | ||
}; | ||
return new HeimdallTree(heimdall, json.serializationTime); | ||
}; | ||
Object.defineProperty(HeimdallTree.prototype, "path", { | ||
// primarily a test helper, you can get this at any time | ||
// to get an array representing the path of open node names | ||
// from "root" to the last open node. | ||
get: function () { | ||
var events = this._heimdall._events; | ||
var root = new HeimdallNode('root', 1e9); | ||
var currentNode = root; | ||
var nodeMap = new HashMap(); | ||
var node; | ||
var top; | ||
var path = []; | ||
events.forEach(function (_a, i) { | ||
var op = _a[0], name = _a[1]; | ||
switch (op) { | ||
case OpCodes$1.OP_START: | ||
node = new HeimdallNode(name, i); | ||
nodeMap.set(i, node); | ||
currentNode.addNode(node); | ||
currentNode = node; | ||
break; | ||
case OpCodes$1.OP_STOP: | ||
node = nodeMap.get(name); | ||
if (name !== currentNode._id) { | ||
// potentially throw the correct error (already stopped) | ||
if (node) { | ||
node.stop(); | ||
} | ||
else { | ||
throw new Error("Cannot Stop, Attempting to stop a non-existent node!"); | ||
} | ||
throw new Error("Cannot Stop, Attempting to stop a node with an active child!"); | ||
} | ||
currentNode.stop(); | ||
currentNode = currentNode.resumeNode; | ||
break; | ||
case OpCodes$1.OP_RESUME: | ||
node = nodeMap.get(name); | ||
node.resume(currentNode); | ||
currentNode = node; | ||
break; | ||
default: | ||
throw new Error("HeimdallTree encountered an unknown OpCode '" + op + "' during path construction."); | ||
} | ||
}); | ||
top = currentNode; | ||
while (top !== undefined && top !== root) { | ||
path.unshift(top.name); | ||
top = top.parent; | ||
} | ||
currentLeaf = _this._createLeaf(currentNode, time); | ||
break; | ||
case OP_STOP: | ||
node = nodeMap.get(name); | ||
if (name !== currentNode._id) { | ||
// potentially throw the correct error (already stopped) | ||
if (node) { | ||
node.stop(); | ||
} else { | ||
throw new Error("Cannot Stop, Attempting to stop a non-existent node!"); | ||
} | ||
throw new Error("Cannot Stop, Attempting to stop a node with an active child!"); | ||
return path; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(HeimdallTree.prototype, "stack", { | ||
// primarily a test helper, you can get this at any time | ||
// to get an array representing the "stack" of open node names. | ||
get: function () { | ||
var events = this._heimdall._events; | ||
var stack = []; | ||
var nodeMap = new HashMap(); | ||
events.forEach(function (_a, i) { | ||
var op = _a[0], name = _a[1]; | ||
if (op === OpCodes$1.OP_START) { | ||
stack.push(name); | ||
nodeMap.set(i, name); | ||
} | ||
else if (op === OpCodes$1.OP_RESUME) { | ||
var n = nodeMap.get(name); | ||
stack.push(n); | ||
} | ||
else if (op === OpCodes$1.OP_STOP) { | ||
var n = nodeMap.get(name); | ||
if (n !== stack[stack.length - 1]) { | ||
throw new Error('Invalid Stack!'); | ||
} | ||
stack.pop(); | ||
} | ||
}); | ||
return stack; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
HeimdallTree.prototype._createLeaf = function (currentNode, time) { | ||
var leaf = new HeimdallLeaf(); | ||
leaf.start(currentNode, currentNode.name, time); | ||
currentNode.addLeaf(leaf); | ||
return leaf; | ||
}; | ||
HeimdallTree.prototype._chainLeaf = function (currentNode, incomingNode, time) { | ||
var leaf = new HeimdallLeaf(); | ||
leaf.start(currentNode, incomingNode.name, time); | ||
currentNode.addLeaf(leaf); | ||
return leaf; | ||
}; | ||
HeimdallTree.prototype._createNode = function (nodeName, index, nodeMap) { | ||
var node = new HeimdallNode(nodeName, index); | ||
nodeMap.set(index, node); | ||
return node; | ||
}; | ||
HeimdallTree.prototype._chainNode = function (currentNode, nodeName, index, nodeMap) { | ||
var node = this._createNode(nodeName, index, nodeMap); | ||
currentNode.addNode(node); | ||
return node; | ||
}; | ||
HeimdallTree.prototype.construct = function () { | ||
var _this = this; | ||
var events = this._heimdall._events; | ||
var currentLeaf = null; | ||
var currentNode = null; | ||
var nodeMap = new HashMap(); | ||
var openNodes = []; | ||
var node; | ||
var format = this.format; | ||
var counterStore = this._heimdall._monitors; | ||
var stopTime = this.lastKnownTime ? normalizeTime(this.lastKnownTime) : now$1(); | ||
var pageRootIndex = events._length + 1; | ||
currentNode = this.root = this._createNode('page-root', pageRootIndex, nodeMap); | ||
currentLeaf = this._createLeaf(currentNode, 0); | ||
openNodes.push(node); | ||
events.forEach(function (_a, i) { | ||
var op = _a[0], name = _a[1], time = _a[2], counters = _a[3]; | ||
if (op !== OpCodes$1.OP_ANNOTATE) { | ||
time = normalizeTime(time, format); | ||
counters = statsFromCounters(counterStore, counters); | ||
} | ||
switch (op) { | ||
case OpCodes$1.OP_START: | ||
currentNode = _this._chainNode(currentNode, name, i, nodeMap); | ||
openNodes.push(currentNode); | ||
if (currentLeaf) { | ||
currentLeaf.stop(name, time, counters); | ||
} | ||
currentLeaf = _this._createLeaf(currentNode, time); | ||
break; | ||
case OpCodes$1.OP_STOP: | ||
node = nodeMap.get(name); | ||
if (name !== currentNode._id) { | ||
// potentially throw the correct error (already stopped) | ||
if (node) { | ||
node.stop(); | ||
} | ||
else { | ||
throw new Error("Cannot Stop, Attempting to stop a non-existent node!"); | ||
} | ||
throw new Error("Cannot Stop, Attempting to stop a node with an active child!"); | ||
} | ||
currentNode.stop(); | ||
openNodes.splice(openNodes.indexOf(currentNode), 1); | ||
currentNode = currentNode.resumeNode; | ||
currentLeaf.stop(node.name, time, counters); | ||
currentLeaf = _this._chainLeaf(currentNode, node, time); | ||
break; | ||
case OpCodes$1.OP_RESUME: | ||
node = nodeMap.get(name); | ||
node.resume(currentNode); | ||
currentNode = node; | ||
openNodes.push(node); | ||
if (currentLeaf) { | ||
currentLeaf.stop(node.name, time, counters); | ||
} | ||
currentLeaf = _this._chainLeaf(currentNode, node, time); | ||
break; | ||
case OpCodes$1.OP_ANNOTATE: | ||
currentLeaf.annotate(counters); | ||
break; | ||
default: | ||
throw new Error("HeimdallTree encountered an unknown OpCode '" + op + "' during tree construction."); | ||
} | ||
}); | ||
while (currentNode && !currentNode.stopped) { | ||
var name = currentNode.name; | ||
var node_1 = currentNode; | ||
currentNode.stop(); | ||
openNodes.splice(openNodes.indexOf(currentNode), 1); | ||
currentNode = currentNode.resumeNode; | ||
currentLeaf.stop(node.name, time, counters); | ||
currentLeaf = _this._chainLeaf(currentNode, node, time); | ||
break; | ||
case OP_RESUME: | ||
node = nodeMap.get(name); | ||
node.resume(currentNode); | ||
currentNode = node; | ||
openNodes.push(node); | ||
if (currentLeaf) { | ||
currentLeaf.stop(node.name, time, counters); | ||
currentLeaf.stop(node_1.name, stopTime, null); | ||
if (currentNode) { | ||
currentLeaf = this._chainLeaf(currentNode, node_1, stopTime); | ||
} | ||
currentLeaf = _this._chainLeaf(currentNode, node, time); | ||
break; | ||
case OP_ANNOTATE: | ||
currentLeaf.annotate(counters); | ||
break; | ||
default: | ||
throw new Error('HeimdallTree encountered an unknown OpCode \'' + op + '\' during tree construction.'); | ||
} | ||
}); | ||
while (currentNode && !currentNode.stopped) { | ||
var name = currentNode.name; | ||
var _node = currentNode; | ||
currentNode.stop(); | ||
currentNode = currentNode.resumeNode; | ||
currentLeaf.stop(_node.name, stopTime, null); | ||
if (currentNode) { | ||
currentLeaf = this._chainLeaf(currentNode, _node, stopTime); | ||
}; | ||
HeimdallTree.prototype.toJSON = function () { | ||
if (!this.root) { | ||
this.construct(); | ||
} | ||
} | ||
} | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
if (!this.root) { | ||
this.construct(); | ||
} | ||
return { nodes: this.root.toJSONSubgraph() }; | ||
} | ||
}, { | ||
key: 'visitPreOrder', | ||
value: function visitPreOrder(cb) { | ||
return this.root.visitPreOrder(cb); | ||
} | ||
}, { | ||
key: 'visitPostOrder', | ||
value: function visitPostOrder(cb) { | ||
return this.root.visitPostOrder(cb); | ||
} | ||
}, { | ||
key: 'path', | ||
return { | ||
heimdallVersion: '0.3.3', | ||
nodes: this.root.toJSONSubgraph() | ||
}; | ||
}; | ||
HeimdallTree.prototype.visitPreOrder = function (cb) { | ||
this.root.visitPreOrder(cb); | ||
}; | ||
HeimdallTree.prototype.visitPostOrder = function (cb) { | ||
this.root.visitPostOrder(cb); | ||
}; | ||
return HeimdallTree; | ||
}()); | ||
// primarily a test helper, you can get this at any time | ||
// to get an array representing the path of open node names | ||
// from "root" to the last open node. | ||
get: function get() { | ||
var events = this._heimdall._events; | ||
var root = new HeimdallNode('root', 1e9); | ||
var currentNode = root; | ||
var nodeMap = new HashMap(); | ||
var node = void 0; | ||
var top = void 0; | ||
var path = []; | ||
events.forEach(function (_ref3, i) { | ||
var _ref4 = slicedToArray(_ref3, 2); | ||
var op = _ref4[0]; | ||
var name = _ref4[1]; | ||
switch (op) { | ||
case OP_START: | ||
node = new HeimdallNode(name, i); | ||
nodeMap.set(i, node); | ||
currentNode.addNode(node); | ||
currentNode = node; | ||
break; | ||
case OP_STOP: | ||
node = nodeMap.get(name); | ||
if (name !== currentNode._id) { | ||
// potentially throw the correct error (already stopped) | ||
if (node) { | ||
node.stop(); | ||
} else { | ||
throw new Error("Cannot Stop, Attempting to stop a non-existent node!"); | ||
} | ||
throw new Error("Cannot Stop, Attempting to stop a node with an active child!"); | ||
} | ||
currentNode.stop(); | ||
currentNode = currentNode.resumeNode; | ||
break; | ||
case OP_RESUME: | ||
node = nodeMap.get(name); | ||
node.resume(currentNode); | ||
currentNode = node; | ||
break; | ||
default: | ||
throw new Error('HeimdallTree encountered an unknown OpCode \'' + op + '\' during path construction.'); | ||
} | ||
}); | ||
top = currentNode; | ||
while (top !== undefined && top !== root) { | ||
path.unshift(top.name); | ||
top = top.parent; | ||
} | ||
return path; | ||
function setupSession(global) { | ||
// The name of the property encodes the session/node compatibilty version | ||
if (!global._heimdall_session_3) { | ||
global._heimdall_session_3 = new Session(); | ||
} | ||
// primarily a test helper, you can get this at any time | ||
// to get an array representing the "stack" of open node names. | ||
}, { | ||
key: 'stack', | ||
get: function get() { | ||
var events = this._heimdall._events; | ||
var stack = []; | ||
var nodeMap = new HashMap(); | ||
events.forEach(function (_ref5, i) { | ||
var _ref6 = slicedToArray(_ref5, 2); | ||
var op = _ref6[0]; | ||
var name = _ref6[1]; | ||
if (op === OP_START) { | ||
stack.push(name); | ||
nodeMap.set(i, name); | ||
} else if (op === OP_RESUME) { | ||
var n = nodeMap.get(name); | ||
stack.push(n); | ||
} else if (op === OP_STOP) { | ||
var _n = nodeMap.get(name); | ||
if (_n !== stack[stack.length - 1]) { | ||
throw new Error('Invalid Stack!'); | ||
} | ||
stack.pop(); | ||
} | ||
}); | ||
return stack; | ||
} | ||
}], [{ | ||
key: 'fromJSON', | ||
value: function fromJSON(json) { | ||
var events = json.events || []; | ||
var heimdall = { | ||
_timeFormat: json.format || format, | ||
_events: new EventArray(events.length, events), | ||
_monitors: CounterStore.fromJSON(json.monitors) | ||
}; | ||
return new HeimdallTree(heimdall, json.serializationTime); | ||
} | ||
}]); | ||
return HeimdallTree; | ||
}(); | ||
function setupSession(global) { | ||
// The name of the property encodes the session/node compatibilty version | ||
if (!global._heimdall_session_3) { | ||
global._heimdall_session_3 = new HeimdallSession(); | ||
} | ||
} | ||
setupSession(self); | ||
// browser equivalent of heimdall.js | ||
self.Heimdall = Heimdall; | ||
Heimdall.Session = HeimdallSession; | ||
Heimdall.Session = Session; | ||
Heimdall.Tree = HeimdallTree; | ||
var index = new Heimdall(self._heimdall_session_3); | ||
@@ -1282,0 +979,0 @@ |
@@ -7,257 +7,144 @@ (function (global, factory) { | ||
// All Credit for this goes to the Ember.js Core Team | ||
// This exists because `Object.create(null)` is absurdly slow compared | ||
// to `new EmptyObject()`. In either case, you want a null prototype | ||
// when you're treating the object instances as arbitrary dictionaries | ||
// and don't want your keys colliding with build-in methods on the | ||
// default object prototype. | ||
var proto = Object.create(null, { | ||
// without this, we will always still end up with (new | ||
// EmptyObject()).constructor === Object | ||
constructor: { | ||
value: undefined, | ||
enumerable: false, | ||
writable: true | ||
} | ||
}); | ||
function EmptyObject() {} | ||
EmptyObject.prototype = proto; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { | ||
return typeof obj; | ||
} : function (obj) { | ||
return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; | ||
}; | ||
var createClass = function () { | ||
function defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
return function (Constructor, protoProps, staticProps) { | ||
if (protoProps) defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) defineProperties(Constructor, staticProps); | ||
return Constructor; | ||
}; | ||
}(); | ||
var slicedToArray = function () { | ||
function sliceIterator(arr, i) { | ||
var _arr = []; | ||
var _n = true; | ||
var _d = false; | ||
var _e = undefined; | ||
try { | ||
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { | ||
_arr.push(_s.value); | ||
if (i && _arr.length === i) break; | ||
} | ||
} catch (err) { | ||
_d = true; | ||
_e = err; | ||
} finally { | ||
try { | ||
if (!_n && _i["return"]) _i["return"](); | ||
} finally { | ||
if (_d) throw _e; | ||
} | ||
} | ||
return _arr; | ||
} | ||
return function (arr, i) { | ||
if (Array.isArray(arr)) { | ||
return arr; | ||
} else if (Symbol.iterator in Object(arr)) { | ||
return sliceIterator(arr, i); | ||
} else { | ||
throw new TypeError("Invalid attempt to destructure non-iterable instance"); | ||
} | ||
}; | ||
}(); | ||
var UNDEFINED_KEY = Object.create(null); | ||
var HashMap = function () { | ||
function HashMap(entries) { | ||
this._data = new EmptyObject(); | ||
if (entries) { | ||
for (var i = 0; i < entries.length; i++) { | ||
this.data[entries[i][0]] = entries[i][1]; | ||
} | ||
var HashMap = (function () { | ||
function HashMap(entries) { | ||
this._data = Object.create(null); | ||
if (entries) { | ||
for (var i = 0; i < entries.length; i++) { | ||
this.data[entries[i][0]] = entries[i][1]; | ||
} | ||
} | ||
} | ||
} | ||
createClass(HashMap, [{ | ||
key: 'forEach', | ||
value: function forEach(cb) { | ||
for (var key in this._data) { | ||
// skip undefined | ||
if (this._data[key] !== UNDEFINED_KEY) { | ||
cb(this._data[key], key); | ||
HashMap.prototype.forEach = function (cb) { | ||
for (var key in this._data) { | ||
// skip undefined | ||
if (this._data[key] !== UNDEFINED_KEY) { | ||
cb(this._data[key], key); | ||
} | ||
} | ||
} | ||
return this; | ||
}; | ||
HashMap.prototype.has = function (key) { | ||
return key in this._data && this._data[key] !== UNDEFINED_KEY; | ||
}; | ||
HashMap.prototype.get = function (key) { | ||
var val = this._data[key]; | ||
return val === UNDEFINED_KEY ? undefined : val; | ||
}; | ||
HashMap.prototype.set = function (key, value) { | ||
this._data[key] = value; | ||
return this; | ||
}; | ||
HashMap.prototype.delete = function (key) { | ||
this._data[key] = UNDEFINED_KEY; | ||
}; | ||
return HashMap; | ||
}()); | ||
return this; | ||
} | ||
}, { | ||
key: 'has', | ||
value: function has(key) { | ||
return key in this._data && this._data[key] !== UNDEFINED_KEY; | ||
} | ||
}, { | ||
key: 'get', | ||
value: function get(key) { | ||
var val = this._data[key]; | ||
return val === UNDEFINED_KEY ? undefined : val; | ||
} | ||
}, { | ||
key: 'set', | ||
value: function set(key, value) { | ||
this._data[key] = value; | ||
return this; | ||
} | ||
}, { | ||
key: 'delete', | ||
value: function _delete(key) { | ||
this._data[key] = UNDEFINED_KEY; | ||
} | ||
}]); | ||
return HashMap; | ||
}(); | ||
var SMALL_ARRAY_LENGTH = 250; | ||
var EventArray = function () { | ||
function EventArray() { | ||
var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH : arguments[0]; | ||
var initialData = arguments[1]; | ||
this.init(length, initialData); | ||
} | ||
createClass(EventArray, [{ | ||
key: "toJSON", | ||
value: function toJSON() { | ||
return this._data.slice(0, this.length); | ||
var EventArray = (function () { | ||
function EventArray(length, initialData) { | ||
if (length === void 0) { length = SMALL_ARRAY_LENGTH; } | ||
this.init(length, initialData); | ||
} | ||
}, { | ||
key: "init", | ||
value: function init() { | ||
var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH : arguments[0]; | ||
var initialData = arguments[1]; | ||
this.length = 0; | ||
this._length = length; | ||
this._data = new Array(length); | ||
if (initialData) { | ||
if (initialData.length > length) { | ||
length = initialData.length; | ||
this._data.length = length; | ||
this._length = length; | ||
EventArray.prototype.toJSON = function () { | ||
return this._data.slice(0, this.length); | ||
}; | ||
EventArray.prototype.init = function (length, initialData) { | ||
if (length === void 0) { length = SMALL_ARRAY_LENGTH; } | ||
this.length = 0; | ||
this._length = length; | ||
this._data = new Array(length); | ||
if (initialData) { | ||
if (initialData.length > length) { | ||
length = initialData.length; | ||
this._data.length = length; | ||
this._length = length; | ||
} | ||
for (var j = 0; j < initialData.length; j++) { | ||
this._data[j] = initialData[j]; | ||
this.length++; | ||
} | ||
} | ||
for (var j = 0; j < initialData.length; j++) { | ||
this._data[j] = initialData[j]; | ||
this.length++; | ||
} | ||
} | ||
} | ||
}; | ||
// TODO this should probably multiple index by 4 to hide | ||
// that we store in a flat array | ||
EventArray.prototype.get = function (index) { | ||
if (index >= 0 && index < this.length) { | ||
return this._data.slice(index, index + 4); | ||
} | ||
return undefined; | ||
}; | ||
EventArray.prototype.set = function (index, value) { | ||
if (index > this.length) { | ||
throw new Error("Index is out of array bounds."); | ||
} | ||
if (index === this.length) { | ||
this.length++; | ||
} | ||
this._data[index] = value; | ||
}; | ||
EventArray.prototype.forEach = function (cb) { | ||
for (var i = 0; i < this.length; i += 4) { | ||
cb(this._data.slice(i, i + 4), i); | ||
} | ||
}; | ||
EventArray.prototype.push = function (op, name, time, data) { | ||
var index = this.length; | ||
this.length += 4; | ||
if (index >= this._length) { | ||
this._length *= 2; | ||
this._data.length = this._length; | ||
} | ||
this._data[index] = op; | ||
this._data[index + 1] = name; | ||
this._data[index + 2] = time; | ||
this._data[index + 3] = data; | ||
return index; | ||
}; | ||
EventArray.prototype.pop = function () { | ||
var index = --this.length; | ||
if (index < 0) { | ||
this.length = 0; | ||
return undefined; | ||
} | ||
return this._data[index]; | ||
}; | ||
return EventArray; | ||
}()); | ||
}, { | ||
key: "get", | ||
value: function get(index) { | ||
if (index >= 0 && index < this.length) { | ||
return this._data.slice(index, index + 4); | ||
} | ||
var HAS_TYPED_ARRAYS = typeof Uint32Array !== 'undefined'; | ||
function hasTypedArrays() { | ||
return HAS_TYPED_ARRAYS; | ||
} | ||
return undefined; | ||
function fill(array, value, start, end) { | ||
if (hasTypedArrays()) { | ||
return array.fill(value, start, end); | ||
} | ||
}, { | ||
key: "set", | ||
value: function set(index, value) { | ||
if (index > this.length) { | ||
throw new Error("Index is out of array bounds."); | ||
} | ||
if (index === this.length) { | ||
this.length++; | ||
} | ||
this._data[index] = value; | ||
else { | ||
var s = start || 0; | ||
var e = end || array.length; | ||
for (; s < e; s++) { | ||
array[s] = value; | ||
} | ||
return array; | ||
} | ||
}, { | ||
key: "forEach", | ||
value: function forEach(cb) { | ||
for (var i = 0; i < this.length; i += 4) { | ||
cb(this._data.slice(i, i + 4), i); | ||
} | ||
} | ||
}, { | ||
key: "push", | ||
value: function push(op, name, time, data) { | ||
var index = this.length; | ||
this.length += 4; | ||
} | ||
if (index >= this._length) { | ||
this._length *= 2; | ||
this._data.length = this._length; | ||
} | ||
this._data[index] = op; | ||
this._data[index + 1] = name; | ||
this._data[index + 2] = time; | ||
this._data[index + 3] = data; | ||
return index; | ||
function grow(array, oldLength, newLength, fillValue) { | ||
if (fillValue === void 0) { fillValue = 0; } | ||
if (hasTypedArrays()) { | ||
var ret = new Uint32Array(newLength); | ||
ret.set(array); | ||
if (fillValue !== 0) { | ||
ret.fill(fillValue, oldLength); | ||
} | ||
return ret; | ||
} | ||
}, { | ||
key: "pop", | ||
value: function pop() { | ||
var index = --this.length; | ||
if (index < 0) { | ||
this.length = 0; | ||
return undefined; | ||
} | ||
return this._data[index]; | ||
else { | ||
array.length = newLength; | ||
fill(array, fillValue, oldLength, newLength); | ||
return array; | ||
} | ||
}]); | ||
return EventArray; | ||
}(); | ||
var A = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; | ||
function fill(array, value, start, end) { | ||
if (typeof array.fill === 'function') { | ||
return array.fill(value, start, end); | ||
} else { | ||
var len = array.length; | ||
var s = start || 0; | ||
var e = end || len; | ||
for (; s < e; s++) { | ||
array[s] = value; | ||
} | ||
return array; | ||
} | ||
} | ||
@@ -267,54 +154,40 @@ | ||
var MAX_ARRAY_LENGTH = 1e6; | ||
var FastIntArray = function () { | ||
function FastIntArray() { | ||
var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH$1 : arguments[0]; | ||
var initialData = arguments[1]; | ||
this.init(length, initialData); | ||
} | ||
createClass(FastIntArray, [{ | ||
key: 'init', | ||
value: function init() { | ||
var length = arguments.length <= 0 || arguments[0] === undefined ? SMALL_ARRAY_LENGTH$1 : arguments[0]; | ||
var initialData = arguments[1]; | ||
this.length = 0; | ||
this._length = length; | ||
this._fill = 0; | ||
this._data = new A(length); | ||
if (initialData) { | ||
if (initialData.length > length) { | ||
length = initialData.length; | ||
this.grow(length); | ||
var FastIntArray = (function () { | ||
function FastIntArray(length, initialData) { | ||
if (length === void 0) { length = SMALL_ARRAY_LENGTH$1; } | ||
this.init(length, initialData); | ||
} | ||
FastIntArray.prototype.init = function (length, initialData) { | ||
if (length === void 0) { length = SMALL_ARRAY_LENGTH$1; } | ||
var useTypedArray = hasTypedArrays(); | ||
this.length = 0; | ||
this._length = length; | ||
this._fillValue = 0; | ||
this._data = useTypedArray ? new Uint32Array(length) : new Array(length); | ||
if (!useTypedArray) { | ||
fill(this._data, this._fillValue); | ||
} | ||
for (var j = 0; j < initialData.length; j++) { | ||
this._data[j] = initialData[j]; | ||
this.length++; | ||
if (initialData) { | ||
if (initialData.length > length) { | ||
length = initialData.length; | ||
this.grow(length); | ||
} | ||
for (var j = 0; j < initialData.length; j++) { | ||
this._data[j] = initialData[j]; | ||
this.length++; | ||
} | ||
} | ||
} | ||
} | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
return this._data.slice(0, this.length); | ||
} | ||
}, { | ||
key: 'get', | ||
value: function get(index) { | ||
if (index >= 0 && index < this.length) { | ||
return this._data[index]; | ||
} | ||
return undefined; | ||
} | ||
}, { | ||
key: 'increment', | ||
value: function increment(index) { | ||
this._data[index]++; | ||
} | ||
}; | ||
FastIntArray.prototype.toJSON = function () { | ||
return this._data.slice(0, this.length); | ||
}; | ||
FastIntArray.prototype.get = function (index) { | ||
if (index >= 0 && index < this.length) { | ||
return this._data[index]; | ||
} | ||
return undefined; | ||
}; | ||
FastIntArray.prototype.increment = function (index) { | ||
this._data[index]++; | ||
}; | ||
/* | ||
@@ -325,44 +198,41 @@ Uint32Arrays have an immutable length. This method | ||
*/ | ||
FastIntArray.prototype.grow = function (newLength) { | ||
this._data = grow(this._data, this._length, newLength, this._fillValue); | ||
this._length = newLength; | ||
}; | ||
FastIntArray.prototype.claim = function (count) { | ||
this.length += count; | ||
while (this.length > this._length) { | ||
this.grow(this._length * 2); | ||
} | ||
}; | ||
FastIntArray.prototype.push = function (int) { | ||
var index = this.length++; | ||
if (index === this._length) { | ||
this.grow(this._length * 2); | ||
} | ||
this._data[index] = int; | ||
}; | ||
return FastIntArray; | ||
}()); | ||
}, { | ||
key: 'grow', | ||
value: function grow(newLength) { | ||
var l = this._length; | ||
this._length = newLength; | ||
var data = this._data; | ||
var _d = this._data = new A(newLength); | ||
_d.set(data); | ||
if (this._fill !== 0) { | ||
fill(_d, this._fill, l); | ||
} | ||
} | ||
}, { | ||
key: 'claim', | ||
value: function claim(count) { | ||
this.length += count; | ||
while (this.length > this._length) { | ||
this.grow(this._length * 2); | ||
} | ||
} | ||
}, { | ||
key: 'push', | ||
value: function push(int) { | ||
var index = this.length++; | ||
if (index === this._length) { | ||
this.grow(this._length * 2); | ||
} | ||
this._data[index] = int; | ||
} | ||
}]); | ||
return FastIntArray; | ||
}(); | ||
var DEFAULT_STORE_SIZE = 1e3; | ||
var DEFAULT_NAMESPACE_SIZE = 10; | ||
/** | ||
* Wrapper type around options for `CounterStore`. | ||
* | ||
* Intentionally left private as `CounterStore` | ||
* only used internally when `HeimdallSession` is created. | ||
* | ||
* @class CounterStoreOptions | ||
*/ | ||
var CounterStoreOptions = (function () { | ||
function CounterStoreOptions(storeSize, namespaceAllocation) { | ||
if (storeSize === void 0) { storeSize = DEFAULT_STORE_SIZE; } | ||
if (namespaceAllocation === void 0) { namespaceAllocation = DEFAULT_NAMESPACE_SIZE; } | ||
this.storeSize = storeSize; | ||
this.namespaceAllocation = namespaceAllocation; | ||
} | ||
return CounterStoreOptions; | ||
}()); | ||
// NULL_NUMBER is a number larger than the largest | ||
@@ -373,196 +243,142 @@ // index we are capable of utilizing in the store. | ||
var LOB = (1 << 16) - 1; | ||
var CounterStore = function () { | ||
function CounterStore() { | ||
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
this.options = options; | ||
this.initialized = false; | ||
this._storeInitialized = false; | ||
this._store = null; | ||
this._namespaceCount = 0; | ||
this._config = null; | ||
this._cache = null; | ||
this._labelCache = null; | ||
this._nameCache = null; | ||
} | ||
createClass(CounterStore, [{ | ||
key: 'clean', | ||
value: function clean() { | ||
this._storeInitialized = false; | ||
this._store = null; | ||
this._cache = null; | ||
var CounterStore = (function () { | ||
function CounterStore(options) { | ||
if (options === void 0) { options = new CounterStoreOptions(); } | ||
this.options = options; | ||
this.initialized = false; | ||
this._storeInitialized = false; | ||
this._store = null; | ||
this._namespaceCount = 0; | ||
this._config = null; | ||
this._cache = null; | ||
this._labelCache = null; | ||
this._nameCache = null; | ||
} | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
return { | ||
_namespaceCount: this._namespaceCount, | ||
_config: this._config, | ||
_labelCache: this._labelCache, | ||
_nameCache: this._nameCache, | ||
_store: this._store | ||
}; | ||
} | ||
}, { | ||
key: 'registerNamespace', | ||
value: function registerNamespace(name, labels) { | ||
this._initializeIfNeeded(); | ||
var numCounters = labels.length; | ||
var namespaceIndex = this._namespaceCount++; | ||
var bitNamespaceIndex = namespaceIndex << 16; | ||
var namespace = new EmptyObject(); | ||
// we also generate a map between the counters | ||
// and these labels so that we can reconstruct | ||
// a meaningful structure later. | ||
this._nameCache[namespaceIndex] = name; | ||
this._labelCache[name] = labels; | ||
// grow the existing config and cache to account | ||
// for the new namespace | ||
this._config.push(numCounters); | ||
if (this._cache !== null) { | ||
CounterStore.prototype.clean = function () { | ||
this._storeInitialized = false; | ||
this._store = null; | ||
this._cache = null; | ||
}; | ||
CounterStore.prototype.toJSON = function () { | ||
return { | ||
_namespaceCount: this._namespaceCount, | ||
_config: this._config, | ||
_labelCache: this._labelCache, | ||
_nameCache: this._nameCache, | ||
_store: this._store | ||
}; | ||
}; | ||
CounterStore.fromJSON = function (json) { | ||
var store = new CounterStore(); | ||
store._namespaceCount = json._namespaceCount; | ||
store._labelCache = json._labelCache; | ||
store._nameCache = json._nameCache; | ||
if (json._store) { | ||
store._store = new FastIntArray(json._store.length, json._store); | ||
} | ||
if (json._config) { | ||
store._config = new FastIntArray(json._config.length, json._config); | ||
} | ||
return store; | ||
}; | ||
CounterStore.prototype.registerNamespace = function (name, labels) { | ||
this._initializeIfNeeded(); | ||
var numCounters = labels.length; | ||
var namespaceIndex = this._namespaceCount++; | ||
var bitNamespaceIndex = namespaceIndex << 16; | ||
var namespace = Object.create(null); | ||
// we also generate a map between the counters | ||
// and these labels so that we can reconstruct | ||
// a meaningful structure later. | ||
this._nameCache[namespaceIndex] = name; | ||
this._labelCache[name] = labels; | ||
// grow the existing config and cache to account | ||
// for the new namespace | ||
this._config.push(numCounters); | ||
if (this._cache !== null) { | ||
this._cache = grow(this._cache, namespaceIndex, this._namespaceCount, NULL_NUMBER); | ||
} | ||
for (var i = 0; i < numCounters; i++) { | ||
namespace[labels[i]] = bitNamespaceIndex + i; | ||
} | ||
return namespace; | ||
}; | ||
CounterStore.prototype._initializeIfNeeded = function () { | ||
if (this.initialized === false) { | ||
this._config = new FastIntArray(this.options.namespaceAllocation); | ||
this._labelCache = Object.create(null); | ||
this._nameCache = Object.create(null); | ||
this.initialized = true; | ||
} | ||
}; | ||
CounterStore.prototype.restoreFromCache = function (cache) { | ||
var stats = Object.create(null); | ||
for (var i = 0; i < cache.length; i++) { | ||
if (cache[i] !== NULL_NUMBER) { | ||
var startIndex = cache[i]; | ||
var namespace = this._nameCache[i]; | ||
var counterCount = this._config.get(i); | ||
stats[namespace] = Object.create(null); | ||
for (var j = 0; j < counterCount; j++) { | ||
var storeIndex = startIndex + j; | ||
var label = this._labelCache[namespace][j]; | ||
stats[namespace][label] = this._store.get(storeIndex); | ||
} | ||
} | ||
} | ||
return stats; | ||
}; | ||
CounterStore.prototype.increment = function (counter) { | ||
var namespaceIndex = counter >> 16; | ||
var counterIndex = counter & LOB; | ||
if (this._cache === null) { | ||
this._initializeStoreIfNeeded(); | ||
var a = hasTypedArrays() ? new Uint32Array(this._namespaceCount) : new Array(this._namespaceCount); | ||
this._cache = fill(a, NULL_NUMBER); | ||
} | ||
if (this._cache[namespaceIndex] === NULL_NUMBER) { | ||
var counterCount = this._config.get(namespaceIndex); | ||
this._cache[namespaceIndex] = this._store.length; | ||
this._store.claim(counterCount); | ||
} | ||
var storeIndex = this._cache[namespaceIndex] + counterIndex; | ||
this._store.increment(storeIndex); | ||
}; | ||
CounterStore.prototype._initializeStoreIfNeeded = function () { | ||
if (this._storeInitialized === false) { | ||
this._store = new FastIntArray(this.options.storeSize); | ||
this._storeInitialized = true; | ||
} | ||
}; | ||
CounterStore.prototype.has = function (name) { | ||
return this._labelCache && name in this._labelCache; | ||
}; | ||
CounterStore.prototype.cache = function () { | ||
var cache = this._cache; | ||
this._cache = null; | ||
return cache; | ||
}; | ||
return CounterStore; | ||
}()); | ||
this._cache = new A(this._namespaceCount); | ||
this._cache.set(cache); | ||
this._cache[namespaceIndex] = NULL_NUMBER; | ||
} | ||
for (var i = 0; i < numCounters; i++) { | ||
namespace[labels[i]] = bitNamespaceIndex + i; | ||
} | ||
return namespace; | ||
var Session = (function () { | ||
function HeimdallSession() { | ||
this.init(); | ||
} | ||
}, { | ||
key: '_initializeIfNeeded', | ||
value: function _initializeIfNeeded() { | ||
if (this.initialized === false) { | ||
this._config = new FastIntArray(this.options.namespaceAllocation || DEFAULT_NAMESPACE_SIZE); | ||
this._labelCache = new EmptyObject(); | ||
this._nameCache = new EmptyObject(); | ||
this.initialized = true; | ||
} | ||
} | ||
}, { | ||
key: 'restoreFromCache', | ||
value: function restoreFromCache(cache) { | ||
var stats = new EmptyObject(); | ||
for (var i = 0; i < cache.length; i++) { | ||
if (cache[i] !== NULL_NUMBER) { | ||
var startIndex = cache[i]; | ||
var namespace = this._nameCache[i]; | ||
var counterCount = this._config.get(i); | ||
stats[namespace] = new EmptyObject(); | ||
for (var j = 0; j < counterCount; j++) { | ||
var storeIndex = startIndex + j; | ||
var label = this._labelCache[namespace][j]; | ||
stats[namespace][label] = this._store.get(storeIndex); | ||
} | ||
} | ||
} | ||
return stats; | ||
} | ||
}, { | ||
key: 'increment', | ||
value: function increment(counter) { | ||
var namespaceIndex = counter >> 16; | ||
var counterIndex = counter & LOB; | ||
if (this._cache === null) { | ||
this._initializeStoreIfNeeded(); | ||
this._cache = fill(new A(this._namespaceCount), NULL_NUMBER); | ||
} | ||
if (this._cache[namespaceIndex] === NULL_NUMBER) { | ||
var counterCount = this._config.get(namespaceIndex); | ||
this._cache[namespaceIndex] = this._store.length; | ||
this._store.claim(counterCount); | ||
} | ||
var storeIndex = this._cache[namespaceIndex] + counterIndex; | ||
this._store.increment(storeIndex); | ||
} | ||
}, { | ||
key: '_initializeStoreIfNeeded', | ||
value: function _initializeStoreIfNeeded() { | ||
if (this._storeInitialized === false) { | ||
this._store = new FastIntArray(this.options.storeSize || DEFAULT_STORE_SIZE); | ||
this._storeInitialized = true; | ||
} | ||
} | ||
}, { | ||
key: 'has', | ||
value: function has(name) { | ||
return this._labelCache && name in this._labelCache; | ||
} | ||
}, { | ||
key: 'cache', | ||
value: function cache() { | ||
var cache = this._cache; | ||
this._cache = null; | ||
return cache; | ||
} | ||
}], [{ | ||
key: 'fromJSON', | ||
value: function fromJSON(json) { | ||
var store = new CounterStore(); | ||
store._namespaceCount = json._namespaceCount; | ||
store._labelCache = json._labelCache; | ||
store._nameCache = json._nameCache; | ||
if (json._store) { | ||
store._store = new FastIntArray(json._store.length, json._store); | ||
} | ||
if (json._config) { | ||
store._config = new FastIntArray(json._config.length, json._config); | ||
} | ||
} | ||
}]); | ||
return CounterStore; | ||
}(); | ||
// provides easily interceptable indirection. | ||
var HeimdallSession = function () { | ||
function HeimdallSession() { | ||
this.init(); | ||
} | ||
createClass(HeimdallSession, [{ | ||
key: 'init', | ||
value: function init() { | ||
this.monitors = new CounterStore(); | ||
this.configs = new HashMap(); | ||
this.events = new EventArray(640000 * 4); | ||
} | ||
HeimdallSession.prototype.init = function () { | ||
this.monitors = new CounterStore(); | ||
this.configs = new HashMap(); | ||
this.events = new EventArray(640000 * 4); | ||
}; | ||
// mostly for test helper purposes | ||
HeimdallSession.prototype.reset = function () { | ||
this.monitors.clean(); | ||
this.events.length = 0; | ||
}; | ||
return HeimdallSession; | ||
}()); | ||
}, { | ||
key: 'reset', | ||
value: function reset() { | ||
this.monitors.clean(); | ||
this.events.length = 0; | ||
} | ||
}]); | ||
return HeimdallSession; | ||
}(); | ||
var now = void 0; | ||
var format = void 0; | ||
var ORIGIN_TIME = void 0; | ||
var now; | ||
var format; | ||
var ORIGIN_TIME; | ||
// It turns out to be nicer for perf to bind than to close over the time method | ||
@@ -573,125 +389,128 @@ // however, when testing we need to be able to stub the clock via the global | ||
var IS_TESTING = freeGlobal.IS_HEIMDALL_TEST_ENVIRONMENT; | ||
if ((typeof performance === 'undefined' ? 'undefined' : _typeof(performance)) === 'object' && typeof performance.now === 'function') { | ||
now = IS_TESTING ? function now() { | ||
return performance.now(); | ||
} : performance.now.bind(performance); | ||
format = 'milli'; | ||
} else if (typeof process !== 'undefined' && typeof process.hrtime === 'function') { | ||
now = IS_TESTING ? function now() { | ||
return process.hrtime(); | ||
} : process.hrtime.bind(process); | ||
format = 'hrtime'; | ||
} else { | ||
ORIGIN_TIME = Date.now(); | ||
now = Date.now.bind(Date); | ||
format = 'timestamp'; | ||
if (typeof performance === 'object' && typeof performance.now === 'function') { | ||
now = IS_TESTING ? function now() { return performance.now(); } : performance.now.bind(performance); | ||
format = 'milli'; | ||
} | ||
function normalizeTime(time) { | ||
var format = arguments.length <= 1 || arguments[1] === undefined ? format : arguments[1]; | ||
switch (format) { | ||
case 'milli': | ||
return milliToNano(time); | ||
case 'hrtime': | ||
return timeFromHRTime(time); | ||
case 'timestamp': | ||
return milliToNano(time - ORIGIN_TIME); | ||
default: | ||
throw new Error('Unknown Format'); | ||
} | ||
else if (typeof process !== 'undefined' && typeof process.hrtime === 'function') { | ||
now = IS_TESTING ? function now() { return process.hrtime(); } : process.hrtime.bind(process); | ||
format = 'hrtime'; | ||
} | ||
else { | ||
ORIGIN_TIME = Date.now(); | ||
now = Date.now.bind(Date); | ||
format = 'timestamp'; | ||
} | ||
function normalizeTime(time, optionalFormat) { | ||
if (optionalFormat === void 0) { optionalFormat = format; } | ||
switch (optionalFormat) { | ||
case 'milli': | ||
return milliToNano(time); | ||
case 'hrtime': | ||
return timeFromHRTime(time); | ||
case 'timestamp': | ||
return milliToNano(time - ORIGIN_TIME); | ||
default: | ||
throw new Error('Unknown Format'); | ||
} | ||
} | ||
function milliToNano(time) { | ||
return Math.floor(time * 1e6); | ||
return Math.floor(time * 1e6); | ||
} | ||
function timeFromHRTime(hrtime) { | ||
return hrtime[0] * 1e9 + hrtime[1]; | ||
return hrtime[0] * 1e9 + hrtime[1]; | ||
} | ||
var now$1 = now; | ||
var OP_START = 0; | ||
var OP_STOP = 1; | ||
var OP_RESUME = 2; | ||
var OP_ANNOTATE = 3; | ||
var OpCodes; | ||
(function (OpCodes) { | ||
OpCodes[OpCodes["OP_START"] = 0] = "OP_START"; | ||
OpCodes[OpCodes["OP_STOP"] = 1] = "OP_STOP"; | ||
OpCodes[OpCodes["OP_RESUME"] = 2] = "OP_RESUME"; | ||
OpCodes[OpCodes["OP_ANNOTATE"] = 3] = "OP_ANNOTATE"; | ||
})(OpCodes || (OpCodes = {})); | ||
var OpCodes$1 = OpCodes; | ||
var Heimdall = function () { | ||
function Heimdall(session) { | ||
if (arguments.length < 1) { | ||
this._session = new HeimdallSession(); | ||
this.start('session-root'); | ||
} else { | ||
this._session = session; | ||
var VERSION = '0.3.3'; | ||
var Heimdall = (function () { | ||
function Heimdall(session) { | ||
if (arguments.length < 1) { | ||
this._session = new Session(); | ||
this.start('session-root'); | ||
} | ||
else { | ||
this._session = session; | ||
} | ||
} | ||
} | ||
createClass(Heimdall, [{ | ||
key: '_retrieveCounters', | ||
value: function _retrieveCounters() { | ||
return this._monitors.cache(); | ||
} | ||
}, { | ||
key: 'start', | ||
value: function start(name) { | ||
return this._session.events.push(OP_START, name, now$1(), this._retrieveCounters()); | ||
} | ||
}, { | ||
key: 'stop', | ||
value: function stop(token) { | ||
this._session.events.push(OP_STOP, token, now$1(), this._retrieveCounters()); | ||
} | ||
}, { | ||
key: 'resume', | ||
value: function resume(token) { | ||
this._session.events.push(OP_RESUME, token, now$1(), this._retrieveCounters()); | ||
} | ||
}, { | ||
key: 'annotate', | ||
value: function annotate(info) { | ||
// This has the side effect of making events heterogenous, as info is an object | ||
// while counters will always be `null` or an `Array` | ||
this._session.events.push(OP_ANNOTATE, NULL_NUMBER, NULL_NUMBER, info); | ||
} | ||
}, { | ||
key: 'hasMonitor', | ||
value: function hasMonitor(name) { | ||
return !!this._monitors.has(name); | ||
} | ||
}, { | ||
key: 'registerMonitor', | ||
value: function registerMonitor(name) { | ||
if (name === 'own' || name === 'time') { | ||
throw new Error('Cannot register monitor at namespace "' + name + '". "own" and "time" are reserved'); | ||
} | ||
if (this.hasMonitor(name)) { | ||
throw new Error('A monitor for "' + name + '" is already registered"'); | ||
} | ||
for (var _len = arguments.length, keys = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
keys[_key - 1] = arguments[_key]; | ||
} | ||
return this._monitors.registerNamespace(name, keys); | ||
} | ||
}, { | ||
key: 'increment', | ||
value: function increment(token) { | ||
this._session.monitors.increment(token); | ||
} | ||
}, { | ||
key: 'configFor', | ||
value: function configFor(name) { | ||
var config = this._session.configs.get(name); | ||
if (!config) { | ||
config = new EmptyObject(); | ||
this._session.configs.set(name, config); | ||
} | ||
return config; | ||
} | ||
Object.defineProperty(Heimdall, "VERSION", { | ||
get: function () { | ||
return VERSION; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(Heimdall.prototype, "VERSION", { | ||
get: function () { | ||
return VERSION; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(Heimdall.prototype, "_monitors", { | ||
get: function () { | ||
return this._session.monitors; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(Heimdall.prototype, "_events", { | ||
get: function () { | ||
return this._session.events; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Heimdall.prototype._retrieveCounters = function () { | ||
return this._monitors.cache(); | ||
}; | ||
Heimdall.prototype.start = function (name) { | ||
return this._session.events.push(OpCodes$1.OP_START, name, now$1(), this._retrieveCounters()); | ||
}; | ||
Heimdall.prototype.stop = function (token) { | ||
this._session.events.push(OpCodes$1.OP_STOP, token, now$1(), this._retrieveCounters()); | ||
}; | ||
Heimdall.prototype.resume = function (token) { | ||
this._session.events.push(OpCodes$1.OP_RESUME, token, now$1(), this._retrieveCounters()); | ||
}; | ||
Heimdall.prototype.annotate = function (info) { | ||
// This has the side effect of making events heterogenous, as info is an object | ||
// while counters will always be `null` or an `Array` | ||
this._session.events.push(OpCodes$1.OP_ANNOTATE, NULL_NUMBER, NULL_NUMBER, info); | ||
}; | ||
Heimdall.prototype.hasMonitor = function (name) { | ||
return !!this._monitors.has(name); | ||
}; | ||
Heimdall.prototype.registerMonitor = function (name) { | ||
var keys = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
keys[_i - 1] = arguments[_i]; | ||
} | ||
if (name === 'own' || name === 'time') { | ||
throw new Error('Cannot register monitor at namespace "' + name + '". "own" and "time" are reserved'); | ||
} | ||
if (this.hasMonitor(name)) { | ||
throw new Error('A monitor for "' + name + '" is already registered"'); | ||
} | ||
return this._monitors.registerNamespace(name, keys); | ||
}; | ||
Heimdall.prototype.increment = function (token) { | ||
this._session.monitors.increment(token); | ||
}; | ||
Heimdall.prototype.configFor = function (name) { | ||
var config = this._session.configs.get(name); | ||
if (!config) { | ||
config = Object.create(null); | ||
this._session.configs.set(name, config); | ||
} | ||
return config; | ||
}; | ||
/* | ||
@@ -702,260 +521,200 @@ Ideally, this method should only be used for serializing | ||
*/ | ||
Heimdall.prototype.toJSON = function () { | ||
return { | ||
heimdallVersion: VERSION, | ||
format, | ||
monitors: this._monitors.toJSON(), | ||
events: this._events.toJSON(), | ||
serializationTime: now$1() | ||
}; | ||
}; | ||
Heimdall.prototype.toString = function () { | ||
return JSON.stringify(this.toJSON()); | ||
}; | ||
return Heimdall; | ||
}()); | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
return { | ||
format: format, | ||
monitors: this._monitors.toJSON(), | ||
events: this._events.toJSON(), | ||
serializationTime: now$1() | ||
}; | ||
var HeimdallNode = (function () { | ||
function HeimdallNode(name, id) { | ||
this._id = id; | ||
this.parent = null; | ||
this.resumeNode = null; | ||
this.name = name; | ||
this.stopped = false; | ||
this.leaves = []; | ||
this.nodes = []; | ||
this.children = []; | ||
} | ||
}, { | ||
key: 'toString', | ||
value: function toString() { | ||
return JSON.stringify(this.toJSON()); | ||
} | ||
}, { | ||
key: '_monitors', | ||
get: function get() { | ||
return this._session.monitors; | ||
} | ||
}, { | ||
key: '_events', | ||
get: function get() { | ||
return this._session.events; | ||
} | ||
}]); | ||
return Heimdall; | ||
}(); | ||
Object.defineProperty(HeimdallNode.prototype, "stats", { | ||
get: function () { | ||
var own = { | ||
selfTime: 0, | ||
duration: 0, | ||
startTime: this.leaves[0].startTime, | ||
endTime: this.leaves[this.leaves.length - 1].endTime | ||
}; | ||
own.duration = own.endTime - own.startTime; | ||
var counters = []; | ||
var annotations = []; | ||
var stats = { | ||
self: own | ||
}; | ||
this.forEachLeaf(function (leaf) { | ||
own.selfTime += leaf.selfTime; | ||
annotations.push(leaf.annotations); | ||
for (var namespace in leaf.counters) { | ||
var value = leaf.counters[namespace]; | ||
if (!stats.hasOwnProperty(namespace)) { | ||
stats[namespace] = value; | ||
} | ||
else { | ||
for (var label in value) { | ||
stats[namespace][label] += value[label]; | ||
} | ||
} | ||
} | ||
counters.push(leaf.counters); | ||
}); | ||
return stats; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
HeimdallNode.prototype.stop = function () { | ||
if (this.stopped === true) { | ||
throw new Error('Cannot Stop node, already stopped!'); | ||
} | ||
this.stopped = true; | ||
}; | ||
HeimdallNode.prototype.resume = function (resumeNode) { | ||
if (!this.stopped) { | ||
throw new Error('Cannot Resume node, already running!'); | ||
} | ||
this.resumeNode = resumeNode; | ||
this.stopped = false; | ||
}; | ||
HeimdallNode.prototype.addLeaf = function (leaf) { | ||
leaf.owner = this; | ||
this.leaves.push(leaf); | ||
this.children.push(leaf); | ||
}; | ||
HeimdallNode.prototype.addNode = function (node) { | ||
if (node.parent) { | ||
throw new Error("Cannot set parent of node '" + node.name + "', node already has a parent!"); | ||
} | ||
node.parent = this; | ||
node.resumeNode = this; | ||
this.nodes.push(node); | ||
this.children.push(node); | ||
}; | ||
Object.defineProperty(HeimdallNode.prototype, "isRoot", { | ||
get: function () { | ||
return this.parent === null; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
HeimdallNode.prototype.visitPreOrder = function (cb) { | ||
cb(this); | ||
for (var i = 0; i < this.nodes.length; i++) { | ||
this.nodes[i].visitPreOrder(cb); | ||
} | ||
}; | ||
HeimdallNode.prototype.visitPostOrder = function (cb) { | ||
for (var i = 0; i < this.nodes.length; i++) { | ||
this.nodes[i].visitPostOrder(cb); | ||
} | ||
cb(this); | ||
}; | ||
HeimdallNode.prototype.forEachNode = function (cb) { | ||
for (var i = 0; i < this.nodes.length; ++i) { | ||
cb(this.nodes[i]); | ||
} | ||
}; | ||
HeimdallNode.prototype.forEachLeaf = function (cb) { | ||
for (var i = 0; i < this.leaves.length; ++i) { | ||
cb(this.leaves[i]); | ||
} | ||
}; | ||
HeimdallNode.prototype.forEachChild = function (cb) { | ||
for (var i = 0; i < this.children.length; ++i) { | ||
cb(this.children[i]); | ||
} | ||
}; | ||
HeimdallNode.prototype.toJSON = function () { | ||
return { | ||
_id: this._id, | ||
name: this.name, | ||
leaves: this.leaves.map(function (leaf) { return leaf.toJSON(); }), | ||
nodes: this.nodes.map(function (child) { return child._id; }), | ||
children: this.children.map(function (child) { return child._id; }) | ||
}; | ||
}; | ||
HeimdallNode.prototype.toJSONSubgraph = function () { | ||
var nodes = []; | ||
this.visitPreOrder(function (node) { return nodes.push(node.toJSON()); }); | ||
return nodes; | ||
}; | ||
return HeimdallNode; | ||
}()); | ||
var HeimdallNode = function () { | ||
function HeimdallNode(name, id) { | ||
this._id = id; | ||
this.parent = null; | ||
this.resumeNode = null; | ||
this.name = name; | ||
this.stopped = false; | ||
this.leaves = []; | ||
this.nodes = []; | ||
this.children = []; | ||
} | ||
createClass(HeimdallNode, [{ | ||
key: 'stop', | ||
value: function stop() { | ||
if (this.stopped === true) { | ||
throw new Error('Cannot Stop node, already stopped!'); | ||
} | ||
this.stopped = true; | ||
var HeimdallLeaf = (function () { | ||
function HeimdallLeaf() { | ||
// set on start | ||
this._id = null; | ||
this.owner = null; | ||
this.previousOp = null; | ||
this.startTime = 0; | ||
// set on annotate | ||
this.annotations = null; | ||
// set on stop | ||
this.nextOp = null; | ||
this.endTime = 0; | ||
this.counters = null; | ||
this.name = null; | ||
} | ||
}, { | ||
key: 'resume', | ||
value: function resume(resumeNode) { | ||
if (!this.stopped) { | ||
throw new Error('Cannot Resume node, already running!'); | ||
} | ||
this.resumeNode = resumeNode; | ||
this.stopped = false; | ||
} | ||
}, { | ||
key: 'addLeaf', | ||
value: function addLeaf(leaf) { | ||
leaf.owner = this; | ||
this.leaves.push(leaf); | ||
this.children.push(leaf); | ||
} | ||
}, { | ||
key: 'addNode', | ||
value: function addNode(node) { | ||
if (node.parent) { | ||
throw new Error('Cannot set parent of node \'' + node.name + '\', node already has a parent!'); | ||
} | ||
node.parent = this; | ||
node.resumeNode = this; | ||
this.nodes.push(node); | ||
this.children.push(node); | ||
} | ||
}, { | ||
key: 'visitPreOrder', | ||
value: function visitPreOrder(cb) { | ||
cb(this); | ||
for (var i = 0; i < this.nodes.length; i++) { | ||
this.nodes[i].visitPreOrder(cb); | ||
} | ||
} | ||
}, { | ||
key: 'visitPostOrder', | ||
value: function visitPostOrder(cb) { | ||
for (var i = 0; i < this.nodes.length; i++) { | ||
this.nodes[i].visitPostOrder(cb); | ||
} | ||
cb(this); | ||
} | ||
}, { | ||
key: 'forEachNode', | ||
value: function forEachNode(cb) { | ||
for (var i = 0; i < this.nodes.length; ++i) { | ||
cb(this.nodes[i]); | ||
} | ||
} | ||
}, { | ||
key: 'forEachLeaf', | ||
value: function forEachLeaf(cb) { | ||
for (var i = 0; i < this.leaves.length; ++i) { | ||
cb(this.leaves[i]); | ||
} | ||
} | ||
}, { | ||
key: 'forEachChild', | ||
value: function forEachChild(cb) { | ||
for (var i = 0; i < this.children.length; ++i) { | ||
cb(this.children[i]); | ||
} | ||
} | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
return { | ||
_id: this._id, | ||
name: this.name, | ||
leaves: this.leaves.map(function (leaf) { | ||
return leaf.toJSON(); | ||
}), | ||
nodes: this.nodes.map(function (child) { | ||
return child._id; | ||
}), | ||
children: this.children.map(function (child) { | ||
return child._id; | ||
}) | ||
}; | ||
} | ||
}, { | ||
key: 'toJSONSubgraph', | ||
value: function toJSONSubgraph() { | ||
var nodes = []; | ||
this.visitPreOrder(function (node) { | ||
return nodes.push(node.toJSON()); | ||
}); | ||
return nodes; | ||
} | ||
}, { | ||
key: 'stats', | ||
get: function get() { | ||
var own = { | ||
selfTime: 0, | ||
duration: 0, | ||
startTime: this.leaves[0].startTime, | ||
endTime: this.leaves[this.leaves.length - 1].endTime | ||
}; | ||
own.duration = own.endTime - own.startTime; | ||
var counters = []; | ||
var annotations = []; | ||
var stats = { | ||
self: own | ||
}; | ||
this.forEachLeaf(function (leaf) { | ||
own.selfTime += leaf.selfTime; | ||
annotations.push(leaf.annotations); | ||
for (var namespace in leaf.counters) { | ||
var value = leaf.counters[namespace]; | ||
if (!stats.hasOwnProperty(namespace)) { | ||
stats[namespace] = value; | ||
} else { | ||
for (var label in value) { | ||
stats[namespace][label] += value[label]; | ||
} | ||
} | ||
Object.defineProperty(HeimdallLeaf.prototype, "selfTime", { | ||
get: function () { | ||
return this.endTime - this.startTime; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(HeimdallLeaf.prototype, "isStopped", { | ||
get: function () { | ||
return this.endTime !== 0; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
HeimdallLeaf.prototype.annotate = function (annotation) { | ||
if (this.annotations === null) { | ||
this.annotations = []; | ||
} | ||
this.annotations.push(annotation); | ||
}; | ||
HeimdallLeaf.prototype.start = function (owner, previousOp, time) { | ||
this.owner = owner; | ||
this.previousOp = previousOp; | ||
this.startTime = time; | ||
}; | ||
HeimdallLeaf.prototype.stop = function (nextOp, time, counters) { | ||
this.nextOp = nextOp; | ||
this.endTime = time; | ||
this.counters = counters; | ||
this._id = this.name = "[" + this.owner.name + "]#" + this.previousOp + ":" + nextOp; | ||
}; | ||
HeimdallLeaf.prototype.toJSON = function () { | ||
return { | ||
_id: this._id, | ||
name: this.name, | ||
startTime: this.startTime, | ||
endTime: this.endTime, | ||
counters: this.counters, | ||
annotations: this.annotations | ||
}; | ||
}; | ||
return HeimdallLeaf; | ||
}()); | ||
counters.push(leaf.counters); | ||
}); | ||
return stats; | ||
} | ||
}, { | ||
key: 'isRoot', | ||
get: function get() { | ||
return this.parent === null; | ||
} | ||
}]); | ||
return HeimdallNode; | ||
}(); | ||
var HeimdallLeaf = function () { | ||
function HeimdallLeaf() { | ||
// set on start | ||
this._id = null; | ||
this.owner = null; | ||
this.previousOp = null; | ||
this.startTime = 0; | ||
// set on annotate | ||
this.annotations = null; | ||
// set on stop | ||
this.nextOp = null; | ||
this.endTime = 0; | ||
this.counters = null; | ||
this.name = null; | ||
} | ||
createClass(HeimdallLeaf, [{ | ||
key: "annotate", | ||
value: function annotate(annotation) { | ||
if (this.annotations === null) { | ||
this.annotations = []; | ||
} | ||
this.annotations.push(annotation); | ||
} | ||
}, { | ||
key: "start", | ||
value: function start(owner, previousOp, time) { | ||
this.owner = owner; | ||
this.previousOp = previousOp; | ||
this.startTime = time; | ||
} | ||
}, { | ||
key: "stop", | ||
value: function stop(nextOp, time, counters) { | ||
this.nextOp = nextOp; | ||
this.endTime = time; | ||
this.counters = counters; | ||
this._id = this.name = "[" + this.owner.name + "]#" + this.previousOp + ":" + nextOp; | ||
} | ||
}, { | ||
key: "toJSON", | ||
value: function toJSON() { | ||
return { | ||
_id: this._id, | ||
name: this.name, | ||
startTime: this.startTime, | ||
endTime: this.endTime, | ||
counters: this.counters, | ||
annotations: this.annotations | ||
}; | ||
} | ||
}, { | ||
key: "selfTime", | ||
get: function get() { | ||
return this.endTime - this.startTime; | ||
} | ||
}, { | ||
key: "isStopped", | ||
get: function get() { | ||
return this.endTime !== 0; | ||
} | ||
}]); | ||
return HeimdallLeaf; | ||
}(); | ||
/* | ||
@@ -989,299 +748,237 @@ Example Event Timeline and tree reconstruction | ||
*/ | ||
function statsFromCounters(counterStore, counterCache) { | ||
if (!counterStore || !counterCache) { | ||
return null; | ||
} | ||
return counterStore.restoreFromCache(counterCache); | ||
if (!counterStore || !counterCache) { | ||
return null; | ||
} | ||
return counterStore.restoreFromCache(counterCache); | ||
} | ||
var HeimdallTree = function () { | ||
function HeimdallTree(heimdall, lastKnownTime) { | ||
this._heimdall = heimdall; | ||
this.root = null; | ||
this.format = heimdall && heimdall._timeFormat ? heimdall._timeFormat : format; | ||
this.lastKnownTime = lastKnownTime; | ||
} | ||
createClass(HeimdallTree, [{ | ||
key: '_createLeaf', | ||
value: function _createLeaf(currentNode, time) { | ||
var leaf = new HeimdallLeaf(); | ||
leaf.start(currentNode, currentNode.name, time); | ||
currentNode.addLeaf(leaf); | ||
return leaf; | ||
var HeimdallTree = (function () { | ||
function HeimdallTree(heimdall, lastKnownTime) { | ||
this._heimdall = heimdall; | ||
this.root = null; | ||
this.format = heimdall && heimdall._timeFormat ? heimdall._timeFormat : format; | ||
this.lastKnownTime = lastKnownTime; | ||
} | ||
}, { | ||
key: '_chainLeaf', | ||
value: function _chainLeaf(currentNode, incomingNode, time) { | ||
var leaf = new HeimdallLeaf(); | ||
leaf.start(currentNode, incomingNode.name, time); | ||
currentNode.addLeaf(leaf); | ||
return leaf; | ||
} | ||
}, { | ||
key: '_createNode', | ||
value: function _createNode(nodeName, index, nodeMap) { | ||
var node = new HeimdallNode(nodeName, index); | ||
nodeMap.set(index, node); | ||
return node; | ||
} | ||
}, { | ||
key: '_chainNode', | ||
value: function _chainNode(currentNode, nodeName, index, nodeMap) { | ||
var node = this._createNode(nodeName, index, nodeMap); | ||
currentNode.addNode(node); | ||
return node; | ||
} | ||
}, { | ||
key: 'construct', | ||
value: function construct() { | ||
var _this = this; | ||
var events = this._heimdall._events; | ||
var currentLeaf = null; | ||
var currentNode = null; | ||
var nodeMap = new HashMap(); | ||
var openNodes = []; | ||
var node = void 0; | ||
var format = this.format; | ||
var counterStore = this._heimdall._monitors; | ||
var stopTime = this.lastKnownTime ? normalizeTime(this.lastKnownTime) : now$1(); | ||
var pageRootIndex = events._length + 1; | ||
currentNode = this.root = this._createNode('page-root', pageRootIndex, nodeMap); | ||
currentLeaf = this._createLeaf(currentNode, 0); | ||
openNodes.push(node); | ||
events.forEach(function (_ref, i) { | ||
var _ref2 = slicedToArray(_ref, 4); | ||
var op = _ref2[0]; | ||
var name = _ref2[1]; | ||
var time = _ref2[2]; | ||
var counters = _ref2[3]; | ||
if (op !== OP_ANNOTATE) { | ||
time = normalizeTime(time, format); | ||
counters = statsFromCounters(counterStore, counters); | ||
} | ||
switch (op) { | ||
case OP_START: | ||
currentNode = _this._chainNode(currentNode, name, i, nodeMap); | ||
openNodes.push(currentNode); | ||
if (currentLeaf) { | ||
currentLeaf.stop(name, time, counters); | ||
HeimdallTree.fromJSON = function (json) { | ||
var events = json.events || []; | ||
var heimdall = { | ||
_timeFormat: json.format || format, | ||
_events: new EventArray(events.length, events), | ||
_monitors: CounterStore.fromJSON(json.monitors) | ||
}; | ||
return new HeimdallTree(heimdall, json.serializationTime); | ||
}; | ||
Object.defineProperty(HeimdallTree.prototype, "path", { | ||
// primarily a test helper, you can get this at any time | ||
// to get an array representing the path of open node names | ||
// from "root" to the last open node. | ||
get: function () { | ||
var events = this._heimdall._events; | ||
var root = new HeimdallNode('root', 1e9); | ||
var currentNode = root; | ||
var nodeMap = new HashMap(); | ||
var node; | ||
var top; | ||
var path = []; | ||
events.forEach(function (_a, i) { | ||
var op = _a[0], name = _a[1]; | ||
switch (op) { | ||
case OpCodes$1.OP_START: | ||
node = new HeimdallNode(name, i); | ||
nodeMap.set(i, node); | ||
currentNode.addNode(node); | ||
currentNode = node; | ||
break; | ||
case OpCodes$1.OP_STOP: | ||
node = nodeMap.get(name); | ||
if (name !== currentNode._id) { | ||
// potentially throw the correct error (already stopped) | ||
if (node) { | ||
node.stop(); | ||
} | ||
else { | ||
throw new Error("Cannot Stop, Attempting to stop a non-existent node!"); | ||
} | ||
throw new Error("Cannot Stop, Attempting to stop a node with an active child!"); | ||
} | ||
currentNode.stop(); | ||
currentNode = currentNode.resumeNode; | ||
break; | ||
case OpCodes$1.OP_RESUME: | ||
node = nodeMap.get(name); | ||
node.resume(currentNode); | ||
currentNode = node; | ||
break; | ||
default: | ||
throw new Error("HeimdallTree encountered an unknown OpCode '" + op + "' during path construction."); | ||
} | ||
}); | ||
top = currentNode; | ||
while (top !== undefined && top !== root) { | ||
path.unshift(top.name); | ||
top = top.parent; | ||
} | ||
currentLeaf = _this._createLeaf(currentNode, time); | ||
break; | ||
case OP_STOP: | ||
node = nodeMap.get(name); | ||
if (name !== currentNode._id) { | ||
// potentially throw the correct error (already stopped) | ||
if (node) { | ||
node.stop(); | ||
} else { | ||
throw new Error("Cannot Stop, Attempting to stop a non-existent node!"); | ||
} | ||
throw new Error("Cannot Stop, Attempting to stop a node with an active child!"); | ||
return path; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(HeimdallTree.prototype, "stack", { | ||
// primarily a test helper, you can get this at any time | ||
// to get an array representing the "stack" of open node names. | ||
get: function () { | ||
var events = this._heimdall._events; | ||
var stack = []; | ||
var nodeMap = new HashMap(); | ||
events.forEach(function (_a, i) { | ||
var op = _a[0], name = _a[1]; | ||
if (op === OpCodes$1.OP_START) { | ||
stack.push(name); | ||
nodeMap.set(i, name); | ||
} | ||
else if (op === OpCodes$1.OP_RESUME) { | ||
var n = nodeMap.get(name); | ||
stack.push(n); | ||
} | ||
else if (op === OpCodes$1.OP_STOP) { | ||
var n = nodeMap.get(name); | ||
if (n !== stack[stack.length - 1]) { | ||
throw new Error('Invalid Stack!'); | ||
} | ||
stack.pop(); | ||
} | ||
}); | ||
return stack; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
HeimdallTree.prototype._createLeaf = function (currentNode, time) { | ||
var leaf = new HeimdallLeaf(); | ||
leaf.start(currentNode, currentNode.name, time); | ||
currentNode.addLeaf(leaf); | ||
return leaf; | ||
}; | ||
HeimdallTree.prototype._chainLeaf = function (currentNode, incomingNode, time) { | ||
var leaf = new HeimdallLeaf(); | ||
leaf.start(currentNode, incomingNode.name, time); | ||
currentNode.addLeaf(leaf); | ||
return leaf; | ||
}; | ||
HeimdallTree.prototype._createNode = function (nodeName, index, nodeMap) { | ||
var node = new HeimdallNode(nodeName, index); | ||
nodeMap.set(index, node); | ||
return node; | ||
}; | ||
HeimdallTree.prototype._chainNode = function (currentNode, nodeName, index, nodeMap) { | ||
var node = this._createNode(nodeName, index, nodeMap); | ||
currentNode.addNode(node); | ||
return node; | ||
}; | ||
HeimdallTree.prototype.construct = function () { | ||
var _this = this; | ||
var events = this._heimdall._events; | ||
var currentLeaf = null; | ||
var currentNode = null; | ||
var nodeMap = new HashMap(); | ||
var openNodes = []; | ||
var node; | ||
var format = this.format; | ||
var counterStore = this._heimdall._monitors; | ||
var stopTime = this.lastKnownTime ? normalizeTime(this.lastKnownTime) : now$1(); | ||
var pageRootIndex = events._length + 1; | ||
currentNode = this.root = this._createNode('page-root', pageRootIndex, nodeMap); | ||
currentLeaf = this._createLeaf(currentNode, 0); | ||
openNodes.push(node); | ||
events.forEach(function (_a, i) { | ||
var op = _a[0], name = _a[1], time = _a[2], counters = _a[3]; | ||
if (op !== OpCodes$1.OP_ANNOTATE) { | ||
time = normalizeTime(time, format); | ||
counters = statsFromCounters(counterStore, counters); | ||
} | ||
switch (op) { | ||
case OpCodes$1.OP_START: | ||
currentNode = _this._chainNode(currentNode, name, i, nodeMap); | ||
openNodes.push(currentNode); | ||
if (currentLeaf) { | ||
currentLeaf.stop(name, time, counters); | ||
} | ||
currentLeaf = _this._createLeaf(currentNode, time); | ||
break; | ||
case OpCodes$1.OP_STOP: | ||
node = nodeMap.get(name); | ||
if (name !== currentNode._id) { | ||
// potentially throw the correct error (already stopped) | ||
if (node) { | ||
node.stop(); | ||
} | ||
else { | ||
throw new Error("Cannot Stop, Attempting to stop a non-existent node!"); | ||
} | ||
throw new Error("Cannot Stop, Attempting to stop a node with an active child!"); | ||
} | ||
currentNode.stop(); | ||
openNodes.splice(openNodes.indexOf(currentNode), 1); | ||
currentNode = currentNode.resumeNode; | ||
currentLeaf.stop(node.name, time, counters); | ||
currentLeaf = _this._chainLeaf(currentNode, node, time); | ||
break; | ||
case OpCodes$1.OP_RESUME: | ||
node = nodeMap.get(name); | ||
node.resume(currentNode); | ||
currentNode = node; | ||
openNodes.push(node); | ||
if (currentLeaf) { | ||
currentLeaf.stop(node.name, time, counters); | ||
} | ||
currentLeaf = _this._chainLeaf(currentNode, node, time); | ||
break; | ||
case OpCodes$1.OP_ANNOTATE: | ||
currentLeaf.annotate(counters); | ||
break; | ||
default: | ||
throw new Error("HeimdallTree encountered an unknown OpCode '" + op + "' during tree construction."); | ||
} | ||
}); | ||
while (currentNode && !currentNode.stopped) { | ||
var name = currentNode.name; | ||
var node_1 = currentNode; | ||
currentNode.stop(); | ||
openNodes.splice(openNodes.indexOf(currentNode), 1); | ||
currentNode = currentNode.resumeNode; | ||
currentLeaf.stop(node.name, time, counters); | ||
currentLeaf = _this._chainLeaf(currentNode, node, time); | ||
break; | ||
case OP_RESUME: | ||
node = nodeMap.get(name); | ||
node.resume(currentNode); | ||
currentNode = node; | ||
openNodes.push(node); | ||
if (currentLeaf) { | ||
currentLeaf.stop(node.name, time, counters); | ||
currentLeaf.stop(node_1.name, stopTime, null); | ||
if (currentNode) { | ||
currentLeaf = this._chainLeaf(currentNode, node_1, stopTime); | ||
} | ||
currentLeaf = _this._chainLeaf(currentNode, node, time); | ||
break; | ||
case OP_ANNOTATE: | ||
currentLeaf.annotate(counters); | ||
break; | ||
default: | ||
throw new Error('HeimdallTree encountered an unknown OpCode \'' + op + '\' during tree construction.'); | ||
} | ||
}); | ||
while (currentNode && !currentNode.stopped) { | ||
var name = currentNode.name; | ||
var _node = currentNode; | ||
currentNode.stop(); | ||
currentNode = currentNode.resumeNode; | ||
currentLeaf.stop(_node.name, stopTime, null); | ||
if (currentNode) { | ||
currentLeaf = this._chainLeaf(currentNode, _node, stopTime); | ||
}; | ||
HeimdallTree.prototype.toJSON = function () { | ||
if (!this.root) { | ||
this.construct(); | ||
} | ||
} | ||
} | ||
}, { | ||
key: 'toJSON', | ||
value: function toJSON() { | ||
if (!this.root) { | ||
this.construct(); | ||
} | ||
return { nodes: this.root.toJSONSubgraph() }; | ||
} | ||
}, { | ||
key: 'visitPreOrder', | ||
value: function visitPreOrder(cb) { | ||
return this.root.visitPreOrder(cb); | ||
} | ||
}, { | ||
key: 'visitPostOrder', | ||
value: function visitPostOrder(cb) { | ||
return this.root.visitPostOrder(cb); | ||
} | ||
}, { | ||
key: 'path', | ||
return { | ||
heimdallVersion: '0.3.3', | ||
nodes: this.root.toJSONSubgraph() | ||
}; | ||
}; | ||
HeimdallTree.prototype.visitPreOrder = function (cb) { | ||
this.root.visitPreOrder(cb); | ||
}; | ||
HeimdallTree.prototype.visitPostOrder = function (cb) { | ||
this.root.visitPostOrder(cb); | ||
}; | ||
return HeimdallTree; | ||
}()); | ||
// primarily a test helper, you can get this at any time | ||
// to get an array representing the path of open node names | ||
// from "root" to the last open node. | ||
get: function get() { | ||
var events = this._heimdall._events; | ||
var root = new HeimdallNode('root', 1e9); | ||
var currentNode = root; | ||
var nodeMap = new HashMap(); | ||
var node = void 0; | ||
var top = void 0; | ||
var path = []; | ||
events.forEach(function (_ref3, i) { | ||
var _ref4 = slicedToArray(_ref3, 2); | ||
var op = _ref4[0]; | ||
var name = _ref4[1]; | ||
switch (op) { | ||
case OP_START: | ||
node = new HeimdallNode(name, i); | ||
nodeMap.set(i, node); | ||
currentNode.addNode(node); | ||
currentNode = node; | ||
break; | ||
case OP_STOP: | ||
node = nodeMap.get(name); | ||
if (name !== currentNode._id) { | ||
// potentially throw the correct error (already stopped) | ||
if (node) { | ||
node.stop(); | ||
} else { | ||
throw new Error("Cannot Stop, Attempting to stop a non-existent node!"); | ||
} | ||
throw new Error("Cannot Stop, Attempting to stop a node with an active child!"); | ||
} | ||
currentNode.stop(); | ||
currentNode = currentNode.resumeNode; | ||
break; | ||
case OP_RESUME: | ||
node = nodeMap.get(name); | ||
node.resume(currentNode); | ||
currentNode = node; | ||
break; | ||
default: | ||
throw new Error('HeimdallTree encountered an unknown OpCode \'' + op + '\' during path construction.'); | ||
} | ||
}); | ||
top = currentNode; | ||
while (top !== undefined && top !== root) { | ||
path.unshift(top.name); | ||
top = top.parent; | ||
} | ||
return path; | ||
function setupSession(global) { | ||
// The name of the property encodes the session/node compatibilty version | ||
if (!global._heimdall_session_3) { | ||
global._heimdall_session_3 = new Session(); | ||
} | ||
// primarily a test helper, you can get this at any time | ||
// to get an array representing the "stack" of open node names. | ||
}, { | ||
key: 'stack', | ||
get: function get() { | ||
var events = this._heimdall._events; | ||
var stack = []; | ||
var nodeMap = new HashMap(); | ||
events.forEach(function (_ref5, i) { | ||
var _ref6 = slicedToArray(_ref5, 2); | ||
var op = _ref6[0]; | ||
var name = _ref6[1]; | ||
if (op === OP_START) { | ||
stack.push(name); | ||
nodeMap.set(i, name); | ||
} else if (op === OP_RESUME) { | ||
var n = nodeMap.get(name); | ||
stack.push(n); | ||
} else if (op === OP_STOP) { | ||
var _n = nodeMap.get(name); | ||
if (_n !== stack[stack.length - 1]) { | ||
throw new Error('Invalid Stack!'); | ||
} | ||
stack.pop(); | ||
} | ||
}); | ||
return stack; | ||
} | ||
}], [{ | ||
key: 'fromJSON', | ||
value: function fromJSON(json) { | ||
var events = json.events || []; | ||
var heimdall = { | ||
_timeFormat: json.format || format, | ||
_events: new EventArray(events.length, events), | ||
_monitors: CounterStore.fromJSON(json.monitors) | ||
}; | ||
return new HeimdallTree(heimdall, json.serializationTime); | ||
} | ||
}]); | ||
return HeimdallTree; | ||
}(); | ||
function setupSession(global) { | ||
// The name of the property encodes the session/node compatibilty version | ||
if (!global._heimdall_session_3) { | ||
global._heimdall_session_3 = new HeimdallSession(); | ||
} | ||
} | ||
setupSession(self); | ||
// browser equivalent of heimdall.js | ||
self.Heimdall = Heimdall; | ||
Heimdall.Session = HeimdallSession; | ||
Heimdall.Session = Session; | ||
Heimdall.Tree = HeimdallTree; | ||
var index = new Heimdall(self._heimdall_session_3); | ||
@@ -1288,0 +985,0 @@ |
{ | ||
"name": "heimdalljs", | ||
"version": "0.3.2", | ||
"version": "0.3.3", | ||
"description": "Structured instrumentation library", | ||
@@ -12,5 +12,6 @@ "main": "dist/heimdalljs.cjs.js", | ||
"build:test": "rollup --no-strict -c test.config.js", | ||
"test": "mocha dist/tests/bundle.cjs", | ||
"test": "mocha dist/tests/bundle.cjs --scenario=default && mocha dist/tests/bundle.cjs --scenario=array-fallback", | ||
"test:debug": "mocha --no-timeouts debug dist/tests/bundle.cjs", | ||
"build_and_test": "npm run build:test && npm run test", | ||
"tslint": "tslint -c tslint.json --project tsconfig.json", | ||
"trace": "node --trace-hydrogen --trace_phase=Z --trace_deopt --code_comments --hydrogen_track_positions --redirect_code_traces bench/ ", | ||
@@ -33,9 +34,10 @@ "prepublish": "npm run build" | ||
"files": [ | ||
"dist", | ||
"dist/heimdalljs.cjs.js", | ||
"dist/heimdalljs.es.js", | ||
"dist/heimdalljs.iife.js", | ||
"dist/heimdalljs.umd.js", | ||
"heimdall.js" | ||
], | ||
"devDependencies": { | ||
"babel-preset-es2015": "^6.13.0", | ||
"babel-preset-es2015-rollup": "^1.1.1", | ||
"broccoli": "^0.16.9", | ||
"@types/node": "^7.0.5", | ||
"chai": "^3.2.0", | ||
@@ -48,6 +50,8 @@ "chai-as-promised": "^5.1.0", | ||
"rollup": "^0.34.1", | ||
"rollup-plugin-babel": "^2.6.1", | ||
"rollup-plugin-buble": "^0.12.1", | ||
"rollup-plugin-commonjs": "^3.3.1", | ||
"rollup-plugin-node-resolve": "^1.7.1" | ||
"rollup-plugin-node-resolve": "^1.7.1", | ||
"rollup-plugin-replace": "^1.1.1", | ||
"rollup-plugin-typescript": "^0.8.1", | ||
"tslint": "^4.4.2", | ||
"typescript": "^2.2" | ||
}, | ||
@@ -54,0 +58,0 @@ "dependencies": { |
@@ -51,2 +51,5 @@ # Heimdall | ||
A monitor is a group of counters which you can increment as needed to track things such as entry | ||
into a function or object creations. | ||
**querying** | ||
@@ -58,14 +61,18 @@ ```js | ||
**register** | ||
When you register a monitor, the first argument functions as the unique name for that monitor, | ||
while all other arguments (labels) will be the name of a specific counter in your group of counters. | ||
The call to `registerMonitor` will give you back an object with your labels as its keys and | ||
the token to increment as the value at that key. | ||
```js | ||
let tokens = heimdall.registerMonitor('<name>', ...labels); | ||
const tokens = heimdall.registerMonitor('<name>', ...labels); | ||
``` | ||
Example: | ||
Full Example: | ||
```js | ||
let [a, b, c] = heimdall.registerMonitor('<name>', 'foo', 'bar', 'baz'); | ||
``` | ||
const { foo, bar, baz } = heimdall.registerMonitor('my-first-monitor', 'foo', 'bar', 'baz'); | ||
**using** | ||
```js | ||
heimdall.increment(a); | ||
heimdall.increment(foo); // increment 'foo' counter in the 'my-first-monitor' group. | ||
``` | ||
@@ -107,1 +114,11 @@ | ||
also easy to detect this situation and issue a warning. | ||
## TypeScript | ||
If you are using [Visual Studio Code](https://code.visualstudio.com/) for development, | ||
you might want to install both [`typescript`](https://github.com/Microsoft/TypeScript) | ||
and [`tslint`](https://github.com/palantir/tslint) packages via [`yarn`](https://yarnpkg.com/en/). | ||
```sh | ||
yarn global add typescript tslint | ||
``` |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
122
0
142278
8
3819
1