Socket
Socket
Sign inDemoInstall

heimdalljs

Package Overview
Dependencies
1
Maintainers
3
Versions
21
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.3.2 to 0.3.3

15

CHANGELOG.md
# 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 @@

2028

dist/heimdalljs.cjs.js

@@ -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
```
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc