1 | var rsvp = require('rsvp');
|
2 |
|
3 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
|
4 | return typeof obj;
|
5 | } : function (obj) {
|
6 | return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
7 | };
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 | var classCallCheck = function (instance, Constructor) {
|
20 | if (!(instance instanceof Constructor)) {
|
21 | throw new TypeError("Cannot call a class as a function");
|
22 | }
|
23 | };
|
24 |
|
25 | var createClass = function () {
|
26 | function defineProperties(target, props) {
|
27 | for (var i = 0; i < props.length; i++) {
|
28 | var descriptor = props[i];
|
29 | descriptor.enumerable = descriptor.enumerable || false;
|
30 | descriptor.configurable = true;
|
31 | if ("value" in descriptor) descriptor.writable = true;
|
32 | Object.defineProperty(target, descriptor.key, descriptor);
|
33 | }
|
34 | }
|
35 |
|
36 | return function (Constructor, protoProps, staticProps) {
|
37 | if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
38 | if (staticProps) defineProperties(Constructor, staticProps);
|
39 | return Constructor;
|
40 | };
|
41 | }();
|
42 |
|
43 | var Cookie = function () {
|
44 | function Cookie(node, heimdall) {
|
45 | classCallCheck(this, Cookie);
|
46 |
|
47 | this._node = node;
|
48 | this._restoreNode = node.parent;
|
49 | this._heimdall = heimdall;
|
50 | this._stopped = false;
|
51 | }
|
52 |
|
53 | createClass(Cookie, [{
|
54 | key: "stop",
|
55 | value: function stop() {
|
56 | var monitor = void 0;
|
57 |
|
58 | if (this._heimdall.current !== this._node) {
|
59 | return;
|
60 | } else if (this.stopped === true) {
|
61 | return;
|
62 | }
|
63 |
|
64 | this._stopped = true;
|
65 | this._heimdall._recordTime();
|
66 | this._heimdall._session.current = this._restoreNode;
|
67 | }
|
68 | }, {
|
69 | key: "resume",
|
70 | value: function resume() {
|
71 | if (this._stopped === false) {
|
72 | return;
|
73 | }
|
74 |
|
75 | this._stopped = false;
|
76 | this._restoreNode = this._heimdall.current;
|
77 | this._heimdall._session.current = this._node;
|
78 | }
|
79 | }, {
|
80 | key: "stats",
|
81 | get: function get() {
|
82 | return this._node.stats.own;
|
83 | }
|
84 | }]);
|
85 | return Cookie;
|
86 | }();
|
87 |
|
88 | var HeimdallNode = function () {
|
89 | function HeimdallNode(heimdall, id, data) {
|
90 | classCallCheck(this, HeimdallNode);
|
91 |
|
92 | this._heimdall = heimdall;
|
93 |
|
94 | this._id = heimdall.generateNextId();
|
95 | this.id = id;
|
96 |
|
97 | if (!(_typeof(this.id) === 'object' && this.id !== null && typeof this.id.name === 'string')) {
|
98 | throw new TypeError('HeimdallNode#id.name must be a string');
|
99 | }
|
100 |
|
101 | this.stats = {
|
102 | own: data,
|
103 | time: { self: 0 }
|
104 | };
|
105 |
|
106 | this._children = [];
|
107 |
|
108 | this.parent = null;
|
109 | }
|
110 |
|
111 | createClass(HeimdallNode, [{
|
112 | key: 'visitPreOrder',
|
113 | value: function visitPreOrder(cb) {
|
114 | cb(this);
|
115 |
|
116 | for (var i = 0; i < this._children.length; i++) {
|
117 | this._children[i].visitPreOrder(cb);
|
118 | }
|
119 | }
|
120 | }, {
|
121 | key: 'visitPostOrder',
|
122 | value: function visitPostOrder(cb) {
|
123 | for (var i = 0; i < this._children.length; i++) {
|
124 | this._children[i].visitPostOrder(cb);
|
125 | }
|
126 |
|
127 | cb(this);
|
128 | }
|
129 | }, {
|
130 | key: 'forEachChild',
|
131 | value: function forEachChild(cb) {
|
132 | for (var i = 0; i < this._children.length; ++i) {
|
133 | cb(this._children[i]);
|
134 | }
|
135 | }
|
136 | }, {
|
137 | key: 'remove',
|
138 | value: function remove() {
|
139 | if (!this.parent) {
|
140 | throw new Error('Cannot remove the root heimdalljs node.');
|
141 | }
|
142 | if (this._heimdall.current === this) {
|
143 | throw new Error('Cannot remove an active heimdalljs node.');
|
144 | }
|
145 |
|
146 | return this.parent.removeChild(this);
|
147 | }
|
148 | }, {
|
149 | key: 'toJSON',
|
150 | value: function toJSON() {
|
151 | return {
|
152 | _id: this._id,
|
153 | id: this.id,
|
154 | stats: this.stats,
|
155 | children: this._children.map(function (child) {
|
156 | return child._id;
|
157 | })
|
158 | };
|
159 | }
|
160 | }, {
|
161 | key: 'toJSONSubgraph',
|
162 | value: function toJSONSubgraph() {
|
163 | var nodes = [];
|
164 |
|
165 | this.visitPreOrder(function (node) {
|
166 | return nodes.push(node.toJSON());
|
167 | });
|
168 |
|
169 | return nodes;
|
170 | }
|
171 | }, {
|
172 | key: 'addChild',
|
173 | value: function addChild(node) {
|
174 | if (node.parent) {
|
175 | throw new TypeError('Node ' + node._id + ' already has a parent. Cannot add to ' + this._id);
|
176 | }
|
177 |
|
178 | this._children.push(node);
|
179 |
|
180 | node.parent = this;
|
181 | }
|
182 | }, {
|
183 | key: 'removeChild',
|
184 | value: function removeChild(child) {
|
185 | var index = this._children.indexOf(child);
|
186 |
|
187 | if (index < 0) {
|
188 | throw new Error('Child(' + child._id + ') not found in Parent(' + this._id + '). Something is very wrong.');
|
189 | }
|
190 | this._children.splice(index, 1);
|
191 |
|
192 | child.parent = null;
|
193 |
|
194 | return child;
|
195 | }
|
196 | }, {
|
197 | key: 'isRoot',
|
198 | get: function get() {
|
199 | return this.parent === null;
|
200 | }
|
201 | }]);
|
202 | return HeimdallNode;
|
203 | }();
|
204 |
|
205 |
|
206 | var Dict = function () {
|
207 | function Dict() {
|
208 | classCallCheck(this, Dict);
|
209 |
|
210 | this._storage = {};
|
211 | }
|
212 |
|
213 | createClass(Dict, [{
|
214 | key: 'has',
|
215 | value: function has(key) {
|
216 | return key in this._storage;
|
217 | }
|
218 | }, {
|
219 | key: 'get',
|
220 | value: function get(key) {
|
221 | return this._storage[key];
|
222 | }
|
223 | }, {
|
224 | key: 'set',
|
225 | value: function set(key, value) {
|
226 | return this._storage[key] = value;
|
227 | }
|
228 | }, {
|
229 | key: 'delete',
|
230 | value: function _delete(key) {
|
231 | delete this._storage[key];
|
232 | }
|
233 | }]);
|
234 | return Dict;
|
235 | }();
|
236 |
|
237 | var HeimdallSession = function () {
|
238 | function HeimdallSession() {
|
239 | classCallCheck(this, HeimdallSession);
|
240 |
|
241 | this.reset();
|
242 | }
|
243 |
|
244 | createClass(HeimdallSession, [{
|
245 | key: 'reset',
|
246 | value: function reset() {
|
247 | this._nextId = 0;
|
248 | this.current = undefined;
|
249 | this.root = null;
|
250 | this.previousTimeNS = 0;
|
251 | this.monitorSchemas = new Dict();
|
252 | this.configs = new Dict();
|
253 | }
|
254 | }, {
|
255 | key: 'generateNextId',
|
256 | value: function generateNextId() {
|
257 | return this._nextId++;
|
258 | }
|
259 | }]);
|
260 | return HeimdallSession;
|
261 | }();
|
262 |
|
263 | var timeNS = void 0;
|
264 |
|
265 |
|
266 |
|
267 | var now = void 0;
|
268 | if ((typeof performance === 'undefined' ? 'undefined' : _typeof(performance)) === 'object' && typeof performance.now === 'function') {
|
269 | now = function now() {
|
270 | return performance.now.call(performance);
|
271 | };
|
272 | } else {
|
273 | now = Date.now || function () {
|
274 | return new Date().getTime();
|
275 | };
|
276 | }
|
277 |
|
278 | var dateOffset = now();
|
279 |
|
280 | function timeFromDate() {
|
281 | var timeMS = now() - dateOffset;
|
282 |
|
283 | return Math.floor(timeMS * 1e6);
|
284 | }
|
285 |
|
286 | function timeFromHRTime() {
|
287 | var hrtime = process.hrtime();
|
288 | return hrtime[0] * 1e9 + hrtime[1];
|
289 | }
|
290 |
|
291 | if ((typeof process === 'undefined' ? 'undefined' : _typeof(process)) === 'object' && typeof process.hrtime === 'function') {
|
292 | timeNS = timeFromHRTime;
|
293 | } else {
|
294 | timeNS = timeFromDate;
|
295 | }
|
296 |
|
297 | var timeNS$1 = timeNS;
|
298 |
|
299 | var Heimdall = function () {
|
300 | function Heimdall(session) {
|
301 | classCallCheck(this, Heimdall);
|
302 |
|
303 | if (arguments.length < 1) {
|
304 | session = new HeimdallSession();
|
305 | }
|
306 |
|
307 | this._session = session;
|
308 | this._reset(false);
|
309 | }
|
310 |
|
311 | createClass(Heimdall, [{
|
312 | key: '_reset',
|
313 | value: function _reset(resetSession) {
|
314 | if (resetSession !== false) {
|
315 | this._session.reset();
|
316 | }
|
317 |
|
318 | if (!this.root) {
|
319 |
|
320 |
|
321 | this.start('heimdall');
|
322 | this._session.root = this._session.current;
|
323 | }
|
324 | }
|
325 | }, {
|
326 | key: 'start',
|
327 | value: function start(name, Schema) {
|
328 | var id = void 0;
|
329 | var data = void 0;
|
330 |
|
331 | if (typeof name === 'string') {
|
332 | id = { name: name };
|
333 | } else {
|
334 | id = name;
|
335 | }
|
336 |
|
337 | if (typeof Schema === 'function') {
|
338 | data = new Schema();
|
339 | } else {
|
340 | data = {};
|
341 | }
|
342 |
|
343 | this._recordTime();
|
344 |
|
345 | var node = new HeimdallNode(this, id, data);
|
346 | if (this.current) {
|
347 | this.current.addChild(node);
|
348 | }
|
349 |
|
350 | this._session.current = node;
|
351 |
|
352 | return new Cookie(node, this);
|
353 | }
|
354 | }, {
|
355 | key: '_recordTime',
|
356 | value: function _recordTime() {
|
357 | var time = timeNS$1();
|
358 |
|
359 |
|
360 | if (this.current) {
|
361 | var delta = time - this._session.previousTimeNS;
|
362 | this.current.stats.time.self += delta;
|
363 | }
|
364 | this._session.previousTimeNS = time;
|
365 | }
|
366 | }, {
|
367 | key: 'node',
|
368 | value: function node(name, Schema, callback, context) {
|
369 | if (arguments.length < 3) {
|
370 | callback = Schema;
|
371 | Schema = undefined;
|
372 | }
|
373 |
|
374 | var cookie = this.start(name, Schema);
|
375 |
|
376 |
|
377 |
|
378 |
|
379 | return new rsvp.Promise(function (resolve) {
|
380 | return resolve(callback.call(context, cookie._node.stats.own));
|
381 | }).finally(function () {
|
382 | return cookie.stop();
|
383 | });
|
384 | }
|
385 | }, {
|
386 | key: 'hasMonitor',
|
387 | value: function hasMonitor(name) {
|
388 | return this._session.monitorSchemas.has(name);
|
389 | }
|
390 | }, {
|
391 | key: 'registerMonitor',
|
392 | value: function registerMonitor(name, Schema) {
|
393 | if (name === 'own' || name === 'time') {
|
394 | throw new Error('Cannot register monitor at namespace "' + name + '". "own" and "time" are reserved');
|
395 | }
|
396 | if (this.hasMonitor(name)) {
|
397 | throw new Error('A monitor for "' + name + '" is already registered"');
|
398 | }
|
399 |
|
400 | this._session.monitorSchemas.set(name, Schema);
|
401 | }
|
402 | }, {
|
403 | key: 'statsFor',
|
404 | value: function statsFor(name) {
|
405 | var stats = this.current.stats;
|
406 | var Schema = void 0;
|
407 |
|
408 | if (!stats[name]) {
|
409 | Schema = this._session.monitorSchemas.get(name);
|
410 | if (!Schema) {
|
411 | throw new Error('No monitor registered for "' + name + '"');
|
412 | }
|
413 | stats[name] = new Schema();
|
414 | }
|
415 |
|
416 | return stats[name];
|
417 | }
|
418 | }, {
|
419 | key: 'configFor',
|
420 | value: function configFor(name) {
|
421 | var config = this._session.configs.get(name);
|
422 |
|
423 | if (!config) {
|
424 | config = this._session.configs.set(name, {});
|
425 | }
|
426 |
|
427 | return config;
|
428 | }
|
429 | }, {
|
430 | key: 'toJSON',
|
431 | value: function toJSON() {
|
432 | return { nodes: this.root.toJSONSubgraph() };
|
433 | }
|
434 | }, {
|
435 | key: 'visitPreOrder',
|
436 | value: function visitPreOrder(cb) {
|
437 | return this.root.visitPreOrder(cb);
|
438 | }
|
439 | }, {
|
440 | key: 'visitPostOrder',
|
441 | value: function visitPostOrder(cb) {
|
442 | return this.root.visitPostOrder(cb);
|
443 | }
|
444 | }, {
|
445 | key: 'generateNextId',
|
446 | value: function generateNextId() {
|
447 | return this._session.generateNextId();
|
448 | }
|
449 | }, {
|
450 | key: 'current',
|
451 | get: function get() {
|
452 | return this._session.current;
|
453 | }
|
454 | }, {
|
455 | key: 'root',
|
456 | get: function get() {
|
457 | return this._session.root;
|
458 | }
|
459 | }, {
|
460 | key: 'stack',
|
461 | get: function get() {
|
462 | var stack = [];
|
463 | var top = this.current;
|
464 |
|
465 | while (top !== undefined && top !== this.root) {
|
466 | stack.unshift(top);
|
467 | top = top.parent;
|
468 | }
|
469 |
|
470 | return stack.map(function (node) {
|
471 | return node.id.name;
|
472 | });
|
473 | }
|
474 | }]);
|
475 | return Heimdall;
|
476 | }();
|
477 |
|
478 | function setupSession(global) {
|
479 |
|
480 |
|
481 | if (!global._heimdall_session_2) {
|
482 | global._heimdall_session_2 = new HeimdallSession();
|
483 | }
|
484 | }
|
485 |
|
486 | setupSession(process);
|
487 |
|
488 | var index = new Heimdall(process._heimdall_session_2);
|
489 |
|
490 | module.exports = index;
|